var CACHE_NAME = 'pu-v2025-07-31'; var urlsToCache = [ 'index.html', 'game.v2025-07-31.bundle.js', 'css/bootstrap-4.5.0.pink.css', 'css/bootstrap-4.5.0.darkly.css', 'css/bootstrap-4.6.2.cosmo.css', 'css/bootstrap-4.6.2.minty.css', 'css/bootstrap-select-1.13.18.min.css', 'css/bootstrap-table-1.23.4.min.css', 'css/fontawesome-all-5.13.1.min.css', 'css/lato.css', 'css/shepherd-8.0.1.css', 'css/style.css', 'img/logo_192.jpg', 'img/logo_192.png', 'img/logo_512.jpg', 'img/logo_512.png', 'img/logo_complete.jpg', 'img/logo_gamemap.jpg', 'img/logo_map.jpg', 'img/logo_mono.png', 'img/logo_save.jpg', 'img/logo_task.jpg', 'img/logo_unix.png', 'img/logo.png', 'img/roulette.png', 'img/unknown.jpg', 'libs/privatebin/base-x-3.0.7.js', 'libs/privatebin/rawinflate-0.3.js', 'libs/privatebin/zlib-1.2.11.js', 'libs/privatebin/zlib-1.2.11.wasm', 'libs/bootstrap-4.6.2.bundle.min.js', 'libs/bootstrap-select-1.13.18.min.js', 'libs/bootstrap-table-1.23.4.min.js', 'libs/jquery-3.7.1.min.js', 'libs/kjua-0.9.0.min.js', 'libs/moment-2.30.1.min.js', 'libs/shepherd-8.0.1.min.js', 'libs/webpack-interface.js', 'webfonts/fa-brands-400.eot', 'webfonts/fa-brands-400.svg', 'webfonts/fa-brands-400.ttf', 'webfonts/fa-brands-400.woff', 'webfonts/fa-brands-400.woff2', 'webfonts/fa-regular-400.eot', 'webfonts/fa-regular-400.svg', 'webfonts/fa-regular-400.ttf', 'webfonts/fa-regular-400.woff', 'webfonts/fa-regular-400.woff2', 'webfonts/fa-solid-900.eot', 'webfonts/fa-solid-900.svg', 'webfonts/fa-solid-900.ttf', 'webfonts/fa-solid-900.woff', 'webfonts/fa-solid-900.woff2', 'webfonts/lato-bold-latin-ex.woff2', 'webfonts/lato-bold-latin.woff2', 'webfonts/lato-italic-latin-ex.woff2', 'webfonts/lato-italic-latin.woff2', 'webfonts/lato-regular-latin-ex.woff2', 'webfonts/lato-regular-latin.woff2', ]; self.addEventListener('install', function (event) { event.waitUntil( caches.open(CACHE_NAME) .then(function (cache) { return cache.addAll(urlsToCache); }) .then(() => { self.skipWaiting(); }) ); }); self.addEventListener('fetch', function (event) { if (event.request.method === 'POST') { return; } if (event.request.url.startsWith("https://save.projectuniversity.net")) { return; } if (event.request.url.startsWith("https://pu-saves.burrson.de")) { return; } const url = new URL(event.request.url); if (url.pathname.startsWith('/dynamic/')) { event.respondWith(generateDynamicFile(url.pathname.split('/').pop())); return; } event.respondWith( fetch(event.request).catch(() => caches.match(event.request, { "ignoreSearch": true })) ); }); self.addEventListener('activate', function (event) { event.waitUntil( caches.keys().then(function (cacheNames) { return Promise.all( cacheNames.map(function (cacheName) { if (cacheName !== CACHE_NAME) { return caches.delete(cacheName); } }) ); }) ); return self.clients.claim(); }); async function generateDynamicFile(filename) { const iclients = await self.clients.matchAll({ includeUncontrolled: true, type: 'window' }); //, visibilityState: "visible" if (iclients.length <= 0) { throw new Error('No clients found'); } const client = iclients[0]; const response = await new Promise((resolve, reject) => { const channel = new MessageChannel(); channel.port1.onmessage = (event) => { if (event.data.error) { reject(new Error(event.data.error)); } else { resolve(event.data); } }; client.postMessage({ type: 'GET_FILE_DATA', filename: filename }, [channel.port2]); }); return new Response(response.data, { headers: { 'Content-Type': response.type, 'Content-Disposition': `attachment; filename="${response.filename}"`, 'Cache-Control': 'no-cache' } }); }