1const PDB_NAME = "PlaytimeDB"; 2const PSTORE_NAME = "playtimeLogs"; 3const PDB_VERSION = 1; 4 5// Open (or create) IndexedDB database 6function PopenB() { 7 return new Promise((resolve, reject) => { 8 let request = indexedDB.open(PDB_NAME, PDB_VERSION); 9 10 request.onupgradeneeded = (event) => { 11 let db = event.target.result; 12 if (!db.objectStoreNames.contains(PSTORE_NAME)) { 13 db.createObjectStore(PSTORE_NAME, { keyPath: "gameId" }); 14 } 15 }; 16 17 request.onsuccess = (event) => resolve(event.target.result); 18 request.onerror = (event) => reject(event.target.error); 19 }); 20} 21 22// Log playtime in IndexedDB 23async function PlogPlaytime() { 24 const currentUrl = window.location.href; 25 let pageName, nonHashedPageName; 26 27 if (currentUrl.includes("/games")) { 28 if (currentUrl.includes("#")) { 29 pageName = currentUrl.split("#").pop(); 30 } else { 31 const queryPart = currentUrl.split("?")[1]; 32 pageName = queryPart ? queryPart : "unknown"; 33 } 34 nonHashedPageName = pageName; 35 } else { 36 pageName = typeof playtimeName !== "undefined" ? playtimeName : "unknown"; 37 nonHashedPageName = pageName; 38 } 39 40 const now = new Date(); 41 const timestamp = now.toLocaleString("en-GB", { 42 day: "2-digit", month: "2-digit", year: "numeric", 43 hour: "2-digit", minute: "2-digit", hour12: false 44 }); 45 46 let db = await PopenB(); 47 let transaction = db.transaction(PSTORE_NAME, "readwrite"); 48 let store = transaction.objectStore(PSTORE_NAME); 49 50 let request = store.get(pageName); 51 52 request.onsuccess = () => { 53 let entry = request.result || { gameId: pageName, logs: [] }; 54 entry.logs.push(timestamp); 55 let putRequest = store.put(entry); 56 57 putRequest.onsuccess = () => { 58 console.log(`Logged playtime for ${pageName}: ${timestamp}`); 59 }; 60 putRequest.onerror = () => { 61 console.error("Error saving entry:", putRequest.error); 62 }; 63 }; 64 65 request.onerror = () => { 66 console.error("Error fetching entry:", request.error); 67 }; 68 69 // Also log the non-hashed version if different 70 if (pageName !== nonHashedPageName) { 71 let nonHashedRequest = store.get(nonHashedPageName); 72 nonHashedRequest.onsuccess = () => { 73 let entry = nonHashedRequest.result || { gameId: nonHashedPageName, logs: [] }; 74 entry.logs.push(timestamp); 75 let nonHashedPutRequest = store.put(entry); 76 77 nonHashedPutRequest.onsuccess = () => { 78 console.log(`Logged playtime for ${nonHashedPageName}: ${timestamp}`); 79 }; 80 nonHashedPutRequest.onerror = () => { 81 console.error("Error saving non-hashed entry:", nonHashedPutRequest.error); 82 }; 83 }; 84 85 nonHashedRequest.onerror = () => { 86 console.error("Error fetching non-hashed entry:", nonHashedRequest.error); 87 }; 88 } 89 90 transaction.oncomplete = () => { 91 console.log("Playtime Transaction completed successfully"); 92 }; 93} 94 95// Start logging at minute start 96function startLoggingAtMinuteStart() { 97 const now = new Date(); 98 const msUntilNextMinute = 60000 - (now.getSeconds() * 1000 + now.getMilliseconds()); 99 100 setTimeout(() => { 101 PlogPlaytime(); // Log at the start of the next minute 102 setInterval(() => { 103 PlogPlaytime(); // Log every minute 104 }, 60000); 105 }, msUntilNextMinute); 106} 107 108// Start logging process 109startLoggingAtMinuteStart();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.