Plugin
ReverseImageSearch
Adds ImageSearch to image context menus
1
import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";2
import { Flex } from "@components/Flex";3
import { OpenExternalIcon } from "@components/Icons";4
import { Devs } from "@utils/constants";5
import definePlugin from "@utils/types";6
import { Menu } from "@webpack/common";7
8
const 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
18
function search(src: string, engine: string) {19
open(engine + encodeURIComponent(src), "_blank");20
}21
22
function makeSearchItem(src: string) {23
return (24
<Menu.MenuItem25
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.MenuItem33
key={key}34
id={key}35
label={36
<Flex alignItems="center" gap="0.5em">37
<img38
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.MenuItem54
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
All60
</Flex>61
}62
action={() => Object.values(Engines).forEach(e => search(src, e))}63
/>64
</Menu.MenuItem>65
);66
}67
68
const 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
77
const 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
84
export 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": imageContextMenuPatch103
}104
});105