@@ -20,25 +20,64 @@ const SEARCH_ENGINES = {
2020 altpower : { name : 'Altpower' , url : 'https://altpower.app/#open-source&gsc.tab=0&gsc.q=' , suffix : '&gsc.sort=' } ,
2121 oxiverse : { name : 'Oxiverse' , url : 'https://search.oxiverse.com/?q=' , suffix : '&tab=web' } ,
2222} ;
23+ // Tor-network search engines — used automatically when the 🧅 toggle is on
24+ // (torEnabled in chrome.storage.local, set by background.js). Ahmia is the
25+ // default: ahmia.fi is a stable clearnet domain reachable over the Tor SOCKS
26+ // proxy that still indexes/returns .onion results, so it keeps working even
27+ // when the onion-only mirrors rotate their addresses. The .onion URLs below
28+ // resolve inside the SOCKS proxy (Chromium does DNS at the proxy for .onion).
29+ // NOTE: onion addresses drift over time — verify against each engine's current
30+ // mirror if a result page stops loading.
31+ const TOR_SEARCH_ENGINES = {
32+ ahmia : { name : 'Ahmia' , url : 'https://ahmia.fi/search/?q=' } ,
33+ torch : { name : 'Torch' , url : 'http://torchdeedp3i2jigzjdmfpn5ttjhthh5wbmda2rr3jvqjg5p77c54dqd.onion/search?query=' } ,
34+ haystak : { name : 'Haystak' , url : 'http://haystak5njsmn2hqkewecpaxetahtwhsbsa64jom2k22z5afxhnpxfid.onion/?q=' } ,
35+ onionland : { name : 'OnionLand' , url : 'http://3bbad7fauom4d6sgppalyqddsqbf5u5p56b5k5uk2zxsy3d6ey2jobad.onion/search?q=' } ,
36+ excavator : { name : 'Excavator' , url : 'http://2fd6cemt4gmccflhm6imvdfvli3nf7zn6rfrwpsy7uhxrgbypvwf5fad.onion/?q=' } ,
37+ } ;
2338let searchMode = 'web' ;
2439let searchEngine = 'neosearch' ;
40+ let torSearchEngine = 'ahmia' ;
41+ let torEnabled = false ;
42+
43+ // Resolve the engine to use right now: the Tor default while the onion toggle
44+ // is on, otherwise the clearnet default.
45+ function activeEngine ( ) {
46+ if ( torEnabled ) return TOR_SEARCH_ENGINES [ torSearchEngine ] || TOR_SEARCH_ENGINES . ahmia ;
47+ return SEARCH_ENGINES [ searchEngine ] || SEARCH_ENGINES . neosearch ;
48+ }
2549
2650function setMode ( mode ) {
2751 searchMode = mode ;
2852 el ( 'mode-web' ) . classList . toggle ( 'active' , mode === 'web' ) ;
2953 el ( 'mode-ai' ) . classList . toggle ( 'active' , mode === 'ai' ) ;
3054 el ( 'mode-web' ) . setAttribute ( 'aria-selected' , mode === 'web' ) ;
3155 el ( 'mode-ai' ) . setAttribute ( 'aria-selected' , mode === 'ai' ) ;
32- const eng = SEARCH_ENGINES [ searchEngine ] || SEARCH_ENGINES . neosearch ;
56+ const eng = activeEngine ( ) ;
3357 el ( 'q' ) . placeholder = mode === 'ai' ? 'Ask AI anything…' : `Search ${ eng . name } …` ;
3458 el ( 'q' ) . focus ( ) ;
3559}
3660el ( 'mode-web' ) . addEventListener ( 'click' , ( ) => setMode ( 'web' ) ) ;
3761el ( 'mode-ai' ) . addEventListener ( 'click' , ( ) => setMode ( 'ai' ) ) ;
3862
39- // Load the chosen web search engine (default NeoSearch).
40- chrome . storage . local . get ( 'searchEngine' ) . then ( ( { searchEngine : se } ) => {
41- if ( se && SEARCH_ENGINES [ se ] ) searchEngine = se ;
63+ // Load the chosen clearnet + Tor search engines and current onion-toggle state.
64+ chrome . storage . local . get ( [ 'searchEngine' , 'torSearchEngine' , 'torEnabled' ] ) . then ( ( v ) => {
65+ if ( v . searchEngine && SEARCH_ENGINES [ v . searchEngine ] ) searchEngine = v . searchEngine ;
66+ if ( v . torSearchEngine && TOR_SEARCH_ENGINES [ v . torSearchEngine ] ) torSearchEngine = v . torSearchEngine ;
67+ torEnabled = ! ! v . torEnabled ;
68+ if ( searchMode === 'web' ) setMode ( 'web' ) ;
69+ } ) ;
70+
71+ // Keep the active engine in sync if the 🧅 toggle flips while the tab is open.
72+ chrome . storage . onChanged . addListener ( ( changes , area ) => {
73+ if ( area !== 'local' ) return ;
74+ if ( 'torEnabled' in changes ) torEnabled = ! ! changes . torEnabled . newValue ;
75+ if ( 'torSearchEngine' in changes && TOR_SEARCH_ENGINES [ changes . torSearchEngine . newValue ] ) {
76+ torSearchEngine = changes . torSearchEngine . newValue ;
77+ }
78+ if ( 'searchEngine' in changes && SEARCH_ENGINES [ changes . searchEngine . newValue ] ) {
79+ searchEngine = changes . searchEngine . newValue ;
80+ }
4281 if ( searchMode === 'web' ) setMode ( 'web' ) ;
4382} ) ;
4483
@@ -52,7 +91,7 @@ el('search').addEventListener('submit', async (e) => {
5291 chrome . runtime . sendMessage ( { type : 'open-sidepanel' } ) ;
5392 el ( 'q' ) . value = '' ;
5493 } else {
55- const eng = SEARCH_ENGINES [ searchEngine ] || SEARCH_ENGINES . neosearch ;
94+ const eng = activeEngine ( ) ;
5695 location . href = eng . url + encodeURIComponent ( q ) + ( eng . suffix || '' ) ;
5796 }
5897} ) ;
0 commit comments