Plugin

ReplaceGoogleSearch

Replaces the Google search with different Engine(s)

Utility Customisation
index.tsx
Download

Source

src/plugins/replaceGoogleSearch/index.tsx
1/*
2 * FiveCord — a Discord client mod
3 * Copyright (c) 2025 FiveCord
4 * SPDX-License-Identifier: GPL-3.0-or-later
5 */
6
7import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";
8import { definePluginSettings } from "@api/Settings";
9import { Flex } from "@components/Flex";
10import { Devs } from "@utils/constants";
11import definePlugin, { OptionType } from "@utils/types";
12import { Menu } from "@webpack/common";
13
14const DefaultEngines = {
15 Google: "https:class="ts-cmt">//www.google.com/search?q=",
16 DuckDuckGo: "https:class="ts-cmt">//duckduckgo.com/?q=",
17 Brave: "https:class="ts-cmt">//search.brave.com/search?q=",
18 Bing: "https:class="ts-cmt">//www.bing.com/search?q=",
19 Yahoo: "https:class="ts-cmt">//search.yahoo.com/search?p=",
20 Yandex: "https:class="ts-cmt">//yandex.com/search/?text=",
21 GitHub: "https:class="ts-cmt">//github.com/search?q=",
22 Reddit: "https:class="ts-cmt">//www.reddit.com/search?q=",
23 Wikipedia: "https:class="ts-cmt">//wikipedia.org/w/index.php?search=",
24 Startpage: "https:class="ts-cmt">//www.startpage.com/sp/search?query="
25} as const;
26
27const enum ReplacementEngineValue {
28 OFF = "off",
29 CUSTOM = "custom",
30}
31
32const settings = definePluginSettings({
33 customEngineName: {
34 description: "Name of the custom search engine",
35 type: OptionType.STRING,
36 placeholder: "Google"
37 },
38 customEngineURL: {
39 displayName: "Custom Engine URL",
40 description: "The URL of your Engine",
41 type: OptionType.STRING,
42 placeholder: "https:class="ts-cmt">//google.com/search?q="
43 },
44 replacementEngine: {
45 description: "Replace with a specific search engine instead of adding a menu",
46 type: OptionType.SELECT,
47 options: [
48 { label: "Off", value: ReplacementEngineValue.OFF, default: true },
49 { label: "Custom Engine", value: ReplacementEngineValue.CUSTOM },
50 ...Object.keys(DefaultEngines).map(engine => ({ label: engine, value: engine }))
51 ]
52 }
53});
54
55function search(src: string, engine: string) {
56 open(engine + encodeURIComponent(src.trim()), "_blank");
57}
58
59function makeSearchItem(src: string) {
60 const { customEngineName, customEngineURL, replacementEngine } = settings.store;
61
62 const hasCustomEngine = Boolean(customEngineName && customEngineURL);
63 const hasValidReplacementEngine = replacementEngine !== ReplacementEngineValue.OFF && !(replacementEngine === ReplacementEngineValue.CUSTOM && !hasCustomEngine);
64
65 const Engines = { ...DefaultEngines };
66
67 if (hasCustomEngine) {
68 Engines[customEngineName!] = customEngineURL;
69 }
70
71 if (hasValidReplacementEngine) {
72 const name = replacementEngine === ReplacementEngineValue.CUSTOM && hasCustomEngine
73 ? customEngineName
74 : replacementEngine;
75
76 return (
77 <Menu.MenuItem
78 label={`Search with ${name}`}
79 key="search-custom-engine"
80 id="vc-search-custom-engine"
81 action={() => search(src, Engines[name!])}
82 />
83 );
84 }
85
86 return (
87 <Menu.MenuItem
88 label="Search Text"
89 key="search-text"
90 id="vc-search-text"
91 >
92 {Object.keys(Engines).map(engine => {
93 const key = "vc-search-content-" + engine;
94 return (
95 <Menu.MenuItem
96 key={key}
97 id={key}
98 label={
99 <Flex gap="0.5em" alignItems="center">
100 <img
101 style={{
102 borderRadius: "50%"
103 }}
104 aria-hidden="true"
105 height={16}
106 width={16}
107 src={`https:class="ts-cmt">//icons.duckduckgo.com/ip3/${new URL(Engines[engine]).hostname}.ico`}
108 />
109 {engine}
110 </Flex>
111 }
112 action={() => search(src, Engines[engine])}
113 />
114 );
115 })}
116 </Menu.MenuItem>
117 );
118}
119
120const messageContextMenuPatch: NavContextMenuPatchCallback = (children, _props) => {
121 const selection = document.getSelection()?.toString();
122 if (!selection) return;
123
124 const group = findGroupChildrenByChildId("search-google", children);
125 if (group) {
126 const idx = group.findIndex(c => c?.props?.id === "search-google");
127 if (idx !== -1) group[idx] = makeSearchItem(selection);
128 }
129};
130
131export default definePlugin({
132 name: "ReplaceGoogleSearch",
133 description: "Replaces the Google search with different Engine(s)",
134 tags: ["Utility", "Customisation"],
135 authors: [Devs.Moxxie, Devs.Ethan],
136
137 settings,
138
139 contextMenus: {
140 "message": messageContextMenuPatch
141 }
142});
143