usrspace-browser-addon/src/background.js

122 lines
3.2 KiB
JavaScript

import { REFRESH_TIMEOUT, API_URLS, BADGE_COLORS } from './config.js';
// [INJECT-BROWSER-POLYFILL]
browser.runtime.onInstalled.addListener(async (details) => {
if (details.reason === 'install') {
await browser.tabs.create({
url: 'https://www.usrspace.at/',
});
}
});
browser.runtime.onStartup.addListener(async () => {
await browser.storage.local.remove(['calendar', 'spaceApi']);
});
browser.alarms.onAlarm.addListener((alarm) => {
if (alarm.name === 'fetchData') {
fetchNewData();
}
});
/**
* @param {string} url
* @returns {Promise<any>}
*/
async function fetchJson(url) {
const response = await fetch(url);
return response.json();
}
/**
* @param {number} days
* @returns {Promise<import("../types").Calendar>}
*/
function fetchCalendar(days = 28) {
let url = `${API_URLS.calender}?o=json`;
if (days) {
url += `&r=${days}`;
}
return fetchJson(url);
}
/**
* @returns {Promise<import("../types").SpaceApi>}
*/
function fetchSpaceApi() {
return fetchJson(API_URLS.spaceApi);
}
async function fetchNewData() {
if (!globalThis.navigator.onLine) {
return;
}
try {
const [resultCalendar, resultSpaceApi] = await Promise.allSettled([fetchCalendar(), fetchSpaceApi()]);
const calendarJson = (resultCalendar.status === 'fulfilled') ? resultCalendar.value : undefined;
const spaceApiJson = (resultSpaceApi.status === 'fulfilled') ? resultSpaceApi.value : undefined;
if (spaceApiJson) {
const now = new Date();
const eventActive = calendarJson?.some((event) => (
new Date(event.begin) <= now && now <= new Date(event.end)
)) ?? false;
await setBadgeStatus(spaceApiJson.state.open, eventActive);
/**
* @type {import("../types").Storage}
*/
const { spaceApi } = await browser.storage.local.get('spaceApi');
if (spaceApi && spaceApi.state.open !== spaceApiJson.state.open) {
await createStatusChangedNotification(spaceApiJson.state.open);
}
}
await browser.storage.local.set({
calendar: calendarJson,
spaceApi: spaceApiJson,
});
} catch (error) {
console.error(error);
}
}
/**
* @param {boolean} open
* @param {boolean} eventActive
*/
async function setBadgeStatus(open, eventActive) {
const badgeText = browser.i18n.getMessage(open ? 'badgeOpen' : eventActive ? 'badgeEvent' : 'badgeClosed');
const badgeBgColor = open ? BADGE_COLORS.open : eventActive ? BADGE_COLORS.event : BADGE_COLORS.closed;
await browser.action.setBadgeText({ text: badgeText });
await browser.action.setBadgeBackgroundColor({ color: badgeBgColor });
}
/**
* @param {boolean} open
*/
async function createStatusChangedNotification(open) {
const stateL10n = browser.i18n.getMessage(open ? 'open' : 'closed');
await browser.notifications.create('status-changed', {
type: 'basic',
title: browser.i18n.getMessage('stateNotificationTitle'),
message: browser.i18n.getMessage('stateNotificationMessage', stateL10n),
iconUrl: browser.runtime.getURL('icons/favicon.svg'),
});
}
function init() {
fetchNewData();
const now = new Date();
now.setMinutes(Math.ceil((now.getMinutes() + 1) / REFRESH_TIMEOUT) * REFRESH_TIMEOUT, 0, 0);
browser.alarms.create('fetchData', {
when: now.getTime(),
periodInMinutes: REFRESH_TIMEOUT,
});
}
init();