-
-
Notifications
You must be signed in to change notification settings - Fork 51
modularize the code, more robust error handling and languages support #118
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
4a28e22
refactor: split background script into modular components with TypeSc…
ptgms 145eb11
fix: make firefox background script work
ptgms 1412bb1
feat: improve error handling with detailed error messages and UI updates
ptgms c2cc935
feat: add multi-language support
ptgms 6f297e1
remove src folder if exists
ptgms 775d3b1
move a constant to constants
ptgms b944b98
fix: remove dupped id's and unused elements, change style selector to…
shadowwwind File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,326 +1,32 @@ | ||
| // import * as Sentry from '@sentry/browser'; | ||
|
|
||
| interface DatabaseEntry { | ||
| id: string; | ||
| url: string; | ||
| rating: string; | ||
| } | ||
|
|
||
| interface Service { | ||
| id: string; | ||
| rating: string; | ||
| } | ||
|
|
||
| const ALLOWED_PROTOCOLS = ['http:', 'https:']; | ||
|
|
||
| var apiUrl = 'api.tosdr.org'; | ||
|
|
||
| // let sentry = false; | ||
|
|
||
| function setPopup(tabId: number | null, popup: string): void { | ||
| if (!tabId) { | ||
| console.log('tabid is undefined, goodbye'); | ||
| // Sentry.captureException(`tabid is undefined! - ${popup}`); | ||
| return; | ||
| } | ||
| chrome.action.setPopup({ | ||
| tabId, | ||
| popup, | ||
| }); | ||
| } | ||
|
|
||
| function serviceDetected(tab: chrome.tabs.Tab, service: Service): void { | ||
| setTabIcon(tab, service.rating.toLowerCase()); | ||
|
|
||
| setPopup(tab?.id ?? null, `/views/popup.html?service-id=${service.id}`); | ||
| setTabBadgeNotification(false, tab); | ||
| } | ||
|
|
||
| function initializePageAction(tab: chrome.tabs.Tab): void { | ||
| if (!tab || !tab.url) { | ||
| console.log('tab is undefined'); | ||
| setPopup(null, '/views/popup.html'); | ||
| setTabIcon(tab, 'logo'); | ||
| setTabBadgeNotification(true, tab); | ||
| return; | ||
| } | ||
| const url = new URL(tab.url); | ||
| if (!ALLOWED_PROTOCOLS.includes(url.protocol)) { | ||
| // we only want to check http and https | ||
| setPopup(tab?.id ?? null, '/views/popup.html'); | ||
| setTabIcon(tab, 'logo'); | ||
| setTabBadgeNotification(true, tab); | ||
| return; | ||
| } | ||
|
|
||
| if (tab.url == '') { | ||
| setPopup(tab?.id ?? null, '/views/popup.html'); | ||
| setTabIcon(tab, 'logo'); | ||
| setTabBadgeNotification(true, tab); | ||
| return; | ||
| } | ||
|
|
||
| // change icon to icons/loading.png | ||
| setTabIcon(tab, 'loading'); | ||
| setTabBadgeNotification(false, tab); | ||
|
|
||
| // get database from chrome.storage | ||
| chrome.storage.local.get(['db'], function (result) { | ||
| if (result["db"]) { | ||
| // parse the database | ||
| const db = result["db"] as DatabaseEntry[]; | ||
|
|
||
| var domain = url.hostname; | ||
|
|
||
| if (domain.startsWith('www.')) { | ||
| domain = domain.substring(4); | ||
| } | ||
|
|
||
| console.log(domain); | ||
|
|
||
| var domainEntry = db.filter((entry) => | ||
| entry.url.split(',').includes(domain) | ||
| ); | ||
| if (domainEntry.length === 1 && domainEntry[0]) { | ||
| console.log('exact match!'); | ||
| serviceDetected(tab, domainEntry[0] as Service); | ||
| return; | ||
| } else { | ||
| const maxTries = 4; | ||
| var current = 0; | ||
|
|
||
| while (current < maxTries) { | ||
| const domainParts = domain.split('.'); | ||
| if (domainParts.length > 2) { | ||
| domain = domainParts.slice(1).join('.'); | ||
| console.log(`try ${current}: ${domain}`); | ||
| domainEntry = db.filter((entry) => | ||
| entry.url.split(',').includes(domain) | ||
| ); | ||
| if (domainEntry.length === 1 && domainEntry[0]) { | ||
| console.log('exact match!'); | ||
| current = maxTries + 1; | ||
| serviceDetected(tab, domainEntry[0] as Service); | ||
| return; | ||
| } | ||
| } else { | ||
| break; | ||
| } | ||
| current++; | ||
| } | ||
| } | ||
|
|
||
| // we didnt find the domain in the database try parent else show notfound.png | ||
| setPopup(tab?.id ?? null, `/views/popup.html?url=${domain}`); | ||
| setTabIcon(tab, 'notfound'); | ||
| } else { | ||
| // database is not in chrome.storage, download it | ||
| console.log('Database is not in chrome.storage'); | ||
| downloadDatabase().then(() => { | ||
| initializePageAction(tab); | ||
| }); | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| // Removed unused function handleRuntimeError | ||
|
|
||
| function setTabIcon(tab: chrome.tabs.Tab | null, icon: string): void { | ||
| const iconDetails: chrome.action.TabIconDetails = { | ||
| path: { | ||
| 32: `/icons/${icon}/${icon}32.png`, | ||
| 48: `/icons/${icon}/${icon}48.png`, | ||
| 128: `/icons/${icon}/${icon}128.png`, | ||
| }, | ||
| }; | ||
|
|
||
| if (tab) { | ||
| iconDetails.tabId = tab.id; | ||
| } | ||
|
|
||
| chrome.action.setIcon(iconDetails); | ||
| } | ||
|
|
||
| async function setTabBadgeNotification(on: boolean, tab: chrome.tabs.Tab): Promise<void> { | ||
| // Retrieve the value from storage and ensure it's a boolean | ||
| const data = await chrome.storage.local.get('displayDonationReminder'); | ||
| const dDR = Boolean(data["displayDonationReminder"]?.active); | ||
|
|
||
| if (on && dDR) { | ||
| chrome.action.setBadgeText({ text: '!', tabId: tab.id }); | ||
| chrome.action.setBadgeBackgroundColor({ color: 'red' }); | ||
| } else { | ||
| chrome.action.setBadgeText({ text: '', tabId: tab.id }); | ||
| } | ||
| } | ||
|
|
||
| async function downloadDatabase() { | ||
| // get the database directly from the new endpoint | ||
| const db_url = `https://${apiUrl}/appdb/version/v2`; | ||
| const response = await fetch(db_url, { | ||
| headers: { | ||
| apikey: atob('Y29uZ3JhdHMgb24gZ2V0dGluZyB0aGUga2V5IDpQ'), | ||
| }, | ||
| }); | ||
|
|
||
| if (response.status >= 300) { | ||
| chrome.action.setBadgeText({ text: 'err ' + response.status }); | ||
| return; | ||
| } | ||
|
|
||
| const data = await response.json(); | ||
|
|
||
| chrome.storage.local.set( | ||
| { | ||
| db: data, | ||
| lastModified: new Date().toISOString(), | ||
| }, | ||
| function () { | ||
| console.log('Database downloaded and saved to chrome.storage'); | ||
| } | ||
| ); | ||
| } | ||
| import { checkIfUpdateNeeded } from './background/database'; | ||
| import { checkDonationReminder } from './background/donation'; | ||
| import { handleExtensionInstalled } from './background/install'; | ||
| import { initializePageAction } from './background/pageAction'; | ||
|
|
||
| chrome.action.setBadgeText({ text: '' }); | ||
| //check if its time to show a donation reminder | ||
| async function checkDonationReminder() { | ||
| // Retrieve the value from storage and ensure it's a boolean | ||
| const data = await chrome.storage.local.get('displayDonationReminder'); | ||
| const displayDonationReminder = data["displayDonationReminder"]; | ||
| const dDR = Boolean(displayDonationReminder?.active); | ||
|
|
||
| if ( | ||
| dDR !== true && | ||
| displayDonationReminder?.allowedPlattform === true | ||
| ) { | ||
| const currentDate = new Date(); | ||
| const currentYear = currentDate.getFullYear(); | ||
|
|
||
| try { | ||
| const result: any = await chrome.storage.local.get( | ||
| 'lastDismissedReminder' | ||
| ); | ||
| const lastDismissedReminder = result.lastDismissedReminder; | ||
| const lastDismissedYear = lastDismissedReminder?.year; | ||
| console.log(lastDismissedYear); | ||
|
|
||
| if ( | ||
| currentYear > lastDismissedYear || | ||
| lastDismissedYear === undefined | ||
| ) { | ||
| chrome.action.setBadgeText({ text: '!' }); | ||
| chrome.storage.local.set({ | ||
| displayDonationReminder: { | ||
| active: true, | ||
| allowedPlattform: | ||
| displayDonationReminder?.allowedPlattform, | ||
| }, | ||
| }); | ||
| } | ||
| } catch (error) { | ||
| console.error('Error in checkDonationReminder:', error); | ||
| } | ||
| } else { | ||
| chrome.action.setBadgeText({ text: '!' }); | ||
| } | ||
| } | ||
|
|
||
| function checkIfUpdateNeeded(firstStart = false) { | ||
| chrome.storage.local.get( | ||
| ['db', 'lastModified', 'interval', 'api', 'sentry'], | ||
| function (result) { | ||
| // if (result.sentry) { | ||
| // sentry = result.sentry; | ||
| // Sentry.init({ | ||
| // dsn: 'https://07c0ebcab5894cff990fd0d3871590f0@sentry.internal.jrbit.de/38', | ||
| // }); | ||
| // } | ||
| if (result["api"]) { | ||
| if (result["api"].length !== 0) apiUrl = result["api"]; | ||
| } | ||
|
|
||
| if (result["db"] && result["lastModified"]) { | ||
| var interval = 8; | ||
| if (result["interval"]) { | ||
| interval = result["interval"]; | ||
| interval++; | ||
| } | ||
| // check if the database is less than 7 days old | ||
| const lastModified = new Date(result["lastModified"]); | ||
| const today = new Date(); | ||
| const diffTime = Math.abs( | ||
| today.getTime() - lastModified.getTime() | ||
| ); | ||
| const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); | ||
| if (diffDays < interval) { | ||
| console.log( | ||
| `Database is less than ${interval - 1 | ||
| } days old, skipping download` | ||
| ); | ||
| return; | ||
| } | ||
| } | ||
| downloadDatabase().then(() => { | ||
| if (firstStart) { | ||
| chrome.runtime.openOptionsPage(); | ||
| } | ||
| }); | ||
| } | ||
| ); | ||
| } | ||
|
|
||
| chrome.tabs.onUpdated.addListener(function (_tabId, changeInfo, tab) { | ||
| chrome.tabs.onUpdated.addListener((_, changeInfo, tab) => { | ||
| if (changeInfo.status === 'complete') { | ||
| initializePageAction(tab); | ||
| void initializePageAction(tab); | ||
| } | ||
| }); | ||
|
|
||
| chrome.tabs.onCreated.addListener(function (tab) { | ||
| initializePageAction(tab); | ||
| chrome.tabs.onCreated.addListener((tab) => { | ||
| void initializePageAction(tab); | ||
| }); | ||
|
|
||
| chrome.tabs.onActivated.addListener(function (activeInfo) { | ||
| chrome.tabs.get(activeInfo.tabId, function (tab) { | ||
| initializePageAction(tab); | ||
| chrome.tabs.onActivated.addListener((activeInfo) => { | ||
| chrome.tabs.get(activeInfo.tabId, (tab) => { | ||
| void initializePageAction(tab); | ||
| }); | ||
| }); | ||
|
|
||
| chrome.runtime.onInstalled.addListener(function () { | ||
| const userAgent = navigator.userAgent; | ||
| let donationReminderAllowed: boolean; | ||
| if (userAgent.indexOf('Mac') != -1 && userAgent.indexOf('Safari') != -1) { | ||
| console.log('MacOS and Safari detected' + userAgent); | ||
| donationReminderAllowed = false; | ||
| } else { | ||
| console.log('MacOS and Safari NOT detected' + userAgent); | ||
| donationReminderAllowed = true; | ||
| } | ||
|
|
||
| chrome.storage.local.set( | ||
| { | ||
| themeHeader: true, | ||
| sentry: false, | ||
| displayDonationReminder: { | ||
| active: false, | ||
| allowedPlattform: donationReminderAllowed, | ||
| }, | ||
| }, | ||
| function () { | ||
| console.log('enabled theme header by default'); | ||
| checkIfUpdateNeeded(true); | ||
| chrome.tabs.query( | ||
| { active: true, currentWindow: true }, | ||
| function (tabs) { | ||
| if (tabs[0]) { | ||
| initializePageAction(tabs[0]); | ||
| } | ||
| } | ||
| ); | ||
| } | ||
| ); | ||
| chrome.runtime.onInstalled.addListener(() => { | ||
| void handleExtensionInstalled(); | ||
| }); | ||
|
|
||
| chrome.runtime.onStartup.addListener(function () { | ||
| checkIfUpdateNeeded(); | ||
| chrome.runtime.onStartup.addListener(() => { | ||
| void checkIfUpdateNeeded(); | ||
| }); | ||
| checkDonationReminder(); | ||
|
|
||
| void checkDonationReminder(); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.