Plugin

ReverseImageSearch

Adds ImageSearch to image context menus

Media Utility
index.tsx
Download

Source

src/plugins/reverseImageSearch/index.tsx
1import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";
2import { Flex } from "@components/Flex";
3import { OpenExternalIcon } from "@components/Icons";
4import { Devs } from "@utils/constants";
5import definePlugin from "@utils/types";
6import { Menu } from "@webpack/common";
7
8const Engines = {
9 Google: "https:class="ts-cmt">//lens.google.com/uploadbyurl?url=",
10 Yandex: "https:class="ts-cmt">//yandex.com/images/search?rpt=imageview&url=",
11 SauceNAO: "https:class="ts-cmt">//saucenao.com/search.php?url=",
12 IQDB: "https:class="ts-cmt">//iqdb.org/?url=",
13 Bing: "https:class="ts-cmt">//www.bing.com/images/search?view=detailv2&iss=sbi&q=imgurl:",
14 TinEye: "https:class="ts-cmt">//www.tineye.com/search?url=",
15 ImgOps: "https:class="ts-cmt">//imgops.com/start?url="
16} as const;
17
18function search(src: string, engine: string) {
19 open(engine + encodeURIComponent(src), "_blank");
20}
21
22function makeSearchItem(src: string) {
23 return (
24 <Menu.MenuItem
25 label="Search Image"
26 key="search-image"
27 id="search-image"
28 >
29 {Object.keys(Engines).map((engine, i) => {
30 const key = "search-image-" + engine;
31 return (
32 <Menu.MenuItem
33 key={key}
34 id={key}
35 label={
36 <Flex alignItems="center" gap="0.5em">
37 <img
38 style={{
39 borderRadius: "50%",
40 }}
41 aria-hidden="true"
42 height={16}
43 width={16}
44 src={`https:class="ts-cmt">//icons.duckduckgo.com/ip3/${new URL(Engines[engine]).host}.ico`}
45 />
46 {engine}
47 </Flex>
48 }
49 action={() => search(src, Engines[engine])}
50 />
51 );
52 })}
53 <Menu.MenuItem
54 key="search-image-all"
55 id="search-image-all"
56 label={
57 <Flex alignItems="center" gap="0.5em">
58 <OpenExternalIcon height={16} width={16} />
59 All
60 </Flex>
61 }
62 action={() => Object.values(Engines).forEach(e => search(src, e))}
63 />
64 </Menu.MenuItem>
65 );
66}
67
68const messageContextMenuPatch: NavContextMenuPatchCallback = (children, props) => {
69 if (props?.reverseImageSearchType !== "img") return;
70
71 const src = props.itemHref ?? props.itemSrc;
72
73 const group = findGroupChildrenByChildId("copy-link", children);
74 group?.push(makeSearchItem(src));
75};
76
77const imageContextMenuPatch: NavContextMenuPatchCallback = (children, props) => {
78 if (!props?.src) return;
79
80 const group = findGroupChildrenByChildId("copy-native-link", children) ?? children;
81 group.push(makeSearchItem(props.src));
82};
83
84export default definePlugin({
85 name: "ReverseImageSearch",
86 description: "Adds ImageSearch to image context menus",
87 tags: ["Media", "Utility"],
88 authors: [Devs.Ven, Devs.Nuckyz],
89 searchTerms: ["ImageUtilities"],
90
91 patches: [
92 {
93 find: "#{intl::MESSAGE_ACTIONS_MENU_LABEL}),shouldHideMediaOptions:",
94 replacement: {
95 match: /favoriteableType:\i,(?<=(\i)\.getAttribute\("data-type"\).+?)/,
96 replace: (m, target) => `${m}reverseImageSearchType:${target}.getAttribute("data-role"),`
97 }
98 }
99 ],
100 contextMenus: {
101 "message": messageContextMenuPatch,
102 "image-context": imageContextMenuPatch
103 }
104});
105