Created
December 3, 2025 22:40
-
-
Save thoroc/acf828d94a364457945eb381ed44bdfa to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bun | |
| import { promises as fs } from 'node:fs'; | |
| import path from 'node:path'; | |
| import process from 'node:process'; | |
| const chromeExtensionIds = [ | |
| 'bpgaffohfacaamplbbojgbiicfgedmoi', 'cdgonefipacceedbkflolomdegncceid', | |
| 'cihbmmokhmieaidfgamioabhhkggnehm', 'eagiakjmjnblliacokhcalebgnhellfi', | |
| 'eaokmbopbenbmgegkmoiogmpejlaikea', 'gipnpcencdgljnaecpekokmpgnhgpela', | |
| 'gnhgdhlkojnlgljamagoigaabdmfhfeg', 'hlcjkaoneihodfmonjnlnnfpdcopgfjk', | |
| 'hmhifpbclhgklaaepgbabgcpfgidkoei', 'ibiejjpajlfljcgjndbonclhcbdcamai', | |
| 'ijcpbhmpbaafndchbjdjchogaogelnjl', 'imdgpklnabbkghcbhmkbjbhcomnfdige', | |
| 'ineempkjpmbdejmdgienaphomigjjiej', 'jbnopeoocgbmnochaadfnhiiimfpbpmf', | |
| 'lehjnmndiohfaphecnjhopgookigekdk', 'lhiehjmkpbhhkfapacaiheolgejcifgd', | |
| 'llkncpcdceadgibhbedecmkencokjajg', 'lnlononncfdnhdfmgpkdfoibmfdehfoj', | |
| 'Mljmfnkjmcdmongjnnnbbnajjdbojoci', 'nagbiboibhbjbclhcigklajjdefaiidc', | |
| 'nmfbniajnpceakchicdhfofoejhgjefb', 'nnnklgkfdfbdijeeglhjfleaoagiagig', | |
| 'ocffbdeldlbilgegmifiakciiicnoaeo', 'ofkopmlicnffaiiabnmnaajaimmenkjn', | |
| 'ogjneoecnllmjcegcfpaamfpbiaaiekh', 'olaahjgjlhoehkpemnfognpgmkbedodk', | |
| 'ondhgmkgppbdnogfiglikgpdkmkaiggk', | |
| ]; | |
| const edgeExtensionIds = [ | |
| 'aadnmeanpbokjjahcnikajejglihibpd', 'acogeoajdpgplfhidldckbjkkpgeebod', | |
| 'afooldonhjnhddgnfahlepchipjennab', 'agdlpnhabjfcbeiempefhpgikapcapjb', | |
| 'ahebpkbnckhgjmndfjejibjjahjdlhdb', 'akialmafcdmkelghnomeneinkcllnoih', | |
| 'alknmfpopohfpdpafdmobclioihdkhjh', 'bafbmfpfepdlgnfkgfbobplkkaoakjcl', | |
| 'bbdioggpbhhodagchciaeaggdponnhpa', 'bboeoilakaofjkdmekpgeigieokkpgfn', | |
| 'bdhjinjoglaijpffoamhhnhooeimgoap', 'bjdclfjlhgcdcpjhmhfggkkfacipilai', | |
| 'bmlifknbfonkgphkpmkeoahgbhbdhebh', 'boiciofdokedkpmopjnghpkgdakmcpmb', | |
| 'bpelnogcookhocnaokfpoeinibimbeff', 'bpngofombcjloljkoafhmpcjclkekfbh', | |
| 'bppelgkcnhfkicolffhlkbdghdnjdkhi', 'cacbflgkiidgcekflfgdnjdnaalfmkob', | |
| 'cbijiaccpnkbdpgbmiiipedpepbhioel', 'cbkogccidanmoaicgphipbdofakomlak', | |
| 'ccdimkoieijdbgdlkfjjfncmihmlpanj', 'cgehahdmoijenmnhinajnojmmlnipckl', | |
| 'cgjgmbppcoolfkbkjhoogdpkboohhgel', 'chmcepembfffejphepoongapnlchjgil', | |
| 'dbagndmcddecodlmnlcmhheicgkaglpk', 'dfakjobhimnibdmkbgpkijoihplhcnil', | |
| 'dhjmmcjnajkpnbnbpagglbbfpbacoffm', 'dkkpollfhjoiapcenojlmgempmjekcla', | |
| 'dmpceopfiajfdnoiebfankfoabfehdpn', 'domfmjgbmkckapepjahpedlpdedmckbj', | |
| 'ebileebbekdcpfjlekjapgmbgpfigled', 'ehmnkbambjnodfbjcebjffilahbfjdml', | |
| 'eholblediahnodlgigdkdhkkpmbiafoj', 'ejdihbblcbdfobabjfebfjfopenohbjb', | |
| 'ejfocpkjndmkbloiobcdhkkoeekcpkik', 'ekndlocgcngbpebppapnpalpjfnkoffh', | |
| 'elckfehnjdbghpoheamjffpdbbogjhie', 'emiocjgakibimbopobplmfldkldhhiad', | |
| 'enaigkcpmpohpbokbfllbkijmllmpafm', 'enkihkfondbngohnmlefmobdgkpmejha', | |
| 'fbbmnieefocnacnecccgmedmcbhlkcpm', 'fcidgbgogbfdcgijkcfdjcagmhcelpbc', | |
| 'fckphkcbpgmappcgnfieaacjbknhkhin', 'ffgihbmcfcihmpbegcfdkmafaplheknk', | |
| 'fhababnomjcnhmobbemagohkldaeicad', 'fjigdpmfeomndepihcinokhcphdojepm', | |
| 'fjioinpkgmlcioajfnncgldldcnabffe', 'fkbcbgffcclobgbombinljckbelhnpif', | |
| 'fmgfcpjmmapcjlknncjgmbolgaecngfo', 'fnnigcfbmghcefaboigkhfimeolhhbcp', | |
| 'fodcokjckpkfpegbekkiallamhedahjd', 'fomlombffdkflbliepgpgcnagolnegjn', | |
| 'fpokgjmlcemklhmilomcljolhnbaaajk', 'fppchnhginnfabgenhihpncnphhafmac', | |
| 'gbcjipmcpedgndgdnfofbhgnkmghoamm', 'gdnhikbabcflemolpeaaknnieodgpiie', | |
| 'ghaggkcfafofhcfppignflhlocmcfimd', 'ghhddclfklljabeodmcejjjlhoaaiban', | |
| 'gkanlgbbnncfafkhlchnadcopcgjkfli', 'gkhggnaplpjkghjjcmpmnmidjndojpcn', | |
| 'glfddenhiaacfmhoiebfeljnfkkkmbjb', 'googojfbnbhbbnpfpdnffnklipgifngn', | |
| 'gpolcigkhldaighngmmmcjldkkiaonbg', 'hadkldcldaanpomhhllacdmglkoepaed', | |
| 'hajlmbnnniemimmaehcefkamdadpjlfa', 'hbghbdhfibifdgnbpaogepnkekonkdgc', | |
| 'hdfknlljfbdfjdjhfgoonpphpigjjjak', 'hdpmmcmblgbkllldbccfdejchjlpochf', | |
| 'hegpgapbnfiibpbkanjemgmdpmmlecbc', 'hfeialplaojonefabmojhobdmghnjkmf', | |
| 'hgolomhkdcpmbgckhebdhdknaemlbbaa', 'hiodlpcelfelhpinhgngoopbmclcaghd', | |
| 'hjfmkkelabjoojjmjljidocklbibphgl', 'hlglicejgohbanllnmnjllajhmnhjjel', | |
| 'hmbacpfgehmmoloinfmkgkpjoagiogai', 'hofaaigdagglolgiefkbencchnekjejl', | |
| 'hohobnhiiohgcipklpncfmjkjpmejjni', 'iaccapfapbjahnhcmkgjjonlccbhdpjl', | |
| 'ibfpbjfnpcgmiggfildbcngccoomddmj', 'ibmgdfenfldppaodbahpgcoebmmkdbac', | |
| 'idjhfmgaddmdojcfmhcjnnbhnhbmhipd', 'iedkeilnpbkeecjpmkelnglnjpnacnlh', | |
| 'igiakpjhacibmaichhgbagdkjmjbnanl', 'ikajognfijokhbgjdhgpemljgcjclpmn', | |
| 'ikgaleggljchgbihlaanjbkekmmgccam', 'ikkoanocgpdmmiamnkogipbpdpckcahn', | |
| 'ileojfedpkdbkcchpnghhaebfoimamop', 'iphacjobmeoknlhenjfiilbkddgaljad', | |
| 'ipnidmjhnoipibbinllilgeohohehabl', 'ipokalojgdmhfpagmhnjokidnpjfnfik', | |
| 'jbajdpebknffiaenkdhopebkolgdlfaf', 'jelgelidmodjpmohbapbghdgcpncahki', | |
| 'jhgfinhjcamijjoikplacnfknpchndgb', 'jiiggekklbbojgfmdenimcdkmidnfofl', | |
| 'jocnjcakendmllafpmjailfnlndaaklf', 'jpoofbjomdefajdjcimmaoildecebkjc', | |
| 'kcpkoopmfjhdpgjohcbgkbjpmbjmhgoi', 'kgmlodoegkmpfkbepkfhgeldidodgohd', | |
| 'klggeioacnkkpdcnapgcoicnblliidmf', 'klgjbnheihgnmimajhohfcldhfpjnahe', | |
| 'kpfbijpdidioaomoecdbfaodhajbcjfl', 'laholcgeblfbgdhkbiidbpiofdcbpeeo', | |
| 'lfgakdlafdenmaikccbojgcofkkhmolj', 'lgnjdldkappogbkljaiedgogobcgemch', | |
| 'lhfdakoonenpbggbeephofdlflloghhi', 'ljjngehkphcdnnapgciajcdbcpgmpknc', | |
| 'ljkgnegaajfacghepjiajibgdpfmcfip', 'ljmcneongnlaecabgneiippeacdoimaa', | |
| 'llilhpmmhicmiaoancaafdgganakopfg', 'lljplndkobdgkjilfmfiefpldkhkhbbd', | |
| 'lmnjiioclbjphkggicmldippjojgmldk', 'mddfnhdadbofiifdebeiegecchpkbgdb', | |
| 'mnophppbmlnlfobakddidbcgcjakipin', 'ncapkionddmdmfocnjfcfpnimepibggf', | |
| 'nchdmembkfgkejljapneliogidkchiop', 'nemkiffjklgaooligallbpmhdmmhepll', | |
| 'ngbfciefgjgijkkmpalnmhikoojilkob', 'nhdiopbebcklbkpfnhipecgfhdhdbfhb', | |
| 'njoedigapanaggiabjafnaklppphempm', 'nkjomoafjgemogbdkhledkoeaflnmgfi', | |
| 'nlcebdoehkdiojeahkofcfnolkleembf', 'nnceocbiolncfljcmajijmeakcdlffnh', | |
| 'nokknhlkpdfppefncfkdebhgfpfilieo', 'oaacndacaoelmkhfilennooagoelpjop', | |
| 'oghgaghnofhhoolfneepjneedejcpiic', 'omkjakddaeljdfgekdjebbbiboljnalk', | |
| 'onifebiiejdjncjpjnojlebibonmnhog', 'opakkgodhhongnhbdkgjgdlcbknacpaa', | |
| 'opncjjhgbllenobgbfjbblhghmdpmpbj', 'paghkadkhiladedijgodgghaajppmpcg', | |
| 'papedehkgfhnagdiempdbhlgcnioofnd', 'pkjfghocapckmendmgdmppjccbplccbg', | |
| ]; | |
| type BrowserMetadata = { | |
| name: string; | |
| installDirectory: string; | |
| extensionsDirectory: string; | |
| extensionIds: string[]; | |
| }; | |
| const COLOR_RESET = '\x1b[0m'; | |
| const COLOR_RED = '\x1b[31m'; | |
| const COLOR_GREEN = '\x1b[32m'; | |
| const COLOR_YELLOW = '\x1b[33m'; | |
| const COLOR_CYAN = '\x1b[36m'; | |
| const USER_HOME = process.env.HOME || process.env.USERPROFILE || ''; | |
| const isInstalled = async (browser: BrowserMetadata) => { | |
| console.log(`Checking if ${COLOR_CYAN}${browser.name}${COLOR_RESET} is installed...`); | |
| try { | |
| await fs.access(browser.installDirectory); | |
| console.log(`✅ ${COLOR_GREEN}${browser.name}${COLOR_RESET} is installed.`); | |
| return true; | |
| } catch { | |
| console.log(`❌ ${COLOR_RED}${browser.name}${COLOR_RESET} is not installed.`); | |
| return false; | |
| } | |
| }; | |
| const extensionPathExists = async (extensionPath: string) => { | |
| console.log(`Checking if extension path exists: ${COLOR_CYAN}${extensionPath}${COLOR_RESET}...`); | |
| try { | |
| await fs.access(extensionPath); | |
| console.log(`✅ Extension path exists: ${COLOR_GREEN}${extensionPath}${COLOR_RESET}`); | |
| return true; | |
| } catch { | |
| console.log(`⚠️ Extension path does not exist: ${COLOR_YELLOW}${extensionPath}${COLOR_RESET}`); | |
| return false; | |
| } | |
| }; | |
| const hasExtensionInstalled = async (browser: BrowserMetadata, extensionIds: string[]) => { | |
| console.log(`Checking for specified extensions for ${COLOR_CYAN}${browser.name}${COLOR_RESET}...`); | |
| const foundExtensions: string[] = []; | |
| for (const extensionId of extensionIds) { | |
| const extensionDir = path.join(browser.extensionsDirectory, extensionId); | |
| try { | |
| await fs.access(extensionDir); | |
| foundExtensions.push(extensionId); | |
| } catch { | |
| // Extension not found, do nothing | |
| } | |
| } | |
| if (foundExtensions.length > 0) { | |
| console.log(`⚠️ Found ${COLOR_YELLOW}${foundExtensions.length}${COLOR_RESET} matching extensions for ${COLOR_CYAN}${browser.name}${COLOR_RESET}.`); | |
| console.log(`❌ ${COLOR_RED}Problematic installed extensions:${COLOR_RESET} ${foundExtensions.join(', ')}`); | |
| return true; | |
| } else { | |
| console.log(`✅ ${COLOR_GREEN}No specified extensions found in ${browser.name}.${COLOR_RESET}`); | |
| return false; | |
| } | |
| }; | |
| const main = async () => { | |
| const browsers: BrowserMetadata[] = [ | |
| { | |
| name: 'Google Chrome', | |
| installDirectory: '/Applications/Google Chrome.app', | |
| extensionsDirectory: `${USER_HOME}/Library/Application Support/Google/Chrome/Default/Extensions/`, | |
| extensionIds: chromeExtensionIds, | |
| }, | |
| { | |
| name: 'Microsoft Edge', | |
| installDirectory: '/Applications/Microsoft Edge.app', | |
| extensionsDirectory: `${USER_HOME}/Library/Application Support/Microsoft Edge/Default/Extensions/`, | |
| extensionIds: [...chromeExtensionIds, ...edgeExtensionIds], | |
| }, | |
| { | |
| name: 'Opera', | |
| installDirectory: '/Applications/Opera.app', | |
| extensionsDirectory: `${USER_HOME}/Library/Application Support/com.operasoftware.Opera/Default/Extensions/`, | |
| extensionIds: chromeExtensionIds, | |
| }, | |
| { | |
| name: 'Vivaldi', | |
| installDirectory: '/Applications/Vivaldi.app', | |
| extensionsDirectory: `${USER_HOME}/Library/Application Support/Vivaldi/Default/Extensions/`, | |
| extensionIds: chromeExtensionIds, | |
| }, | |
| { | |
| name: 'Thorium', | |
| installDirectory: '/Applications/Thorium.app', | |
| extensionsDirectory: `${USER_HOME}/Library/Application Support/Thorium/Default/Extensions/`, | |
| extensionIds: chromeExtensionIds, | |
| }, | |
| { | |
| name: 'Brave', | |
| installDirectory: '/Applications/Brave Browser.app', | |
| extensionsDirectory: `${USER_HOME}/Library/Application Support/BraveSoftware/Brave-Browser/Default/Extensions/`, | |
| extensionIds: chromeExtensionIds, | |
| }, | |
| ]; | |
| for (const browser of browsers) { | |
| const installed = await isInstalled(browser); | |
| if (!installed) { | |
| console.log('----------------------------------------'); | |
| continue; | |
| } | |
| const extensionsPathExists = await extensionPathExists(browser.extensionsDirectory); | |
| if (!extensionsPathExists) { | |
| console.log('----------------------------------------'); | |
| continue; | |
| } | |
| await hasExtensionInstalled(browser, browser.extensionIds); | |
| console.log('----------------------------------------'); | |
| } | |
| }; | |
| main().catch((error) => { | |
| console.error('An error occurred:', error); | |
| process.exit(1); | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment