Last active
May 29, 2025 12:18
-
-
Save egorovli/d27bda00bcc075cbb8cfbe064a0b5ead to your computer and use it in GitHub Desktop.
Inbox Zero, mobiDziennik edition • Automatically read all unread messages in mobiDziennik
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 JavaScript snippet automates achieving "inbox zero" in the mobiDziennik | |
school system by systematically opening all unread messages across multiple | |
pages. It runs in the browser console and automatically navigates through | |
paginated message lists, opening each individual message to mark it as read. | |
The script includes rate limiting and error handling to avoid overwhelming the | |
server while processing all messages. | |
Usage: | |
1. Open your browser and navigate to the mobiDziennik page for your school. | |
2. Open the browser console (usually F12 or right-click and select "Inspect" | |
then go to the "Console" tab). | |
3. Copy and paste the entire code snippet below into the console. | |
4. Replace '[school]' in the baseUrl with your actual school's subdomain. | |
5. Press Enter to execute the script. | |
--- | |
Ten fragment kodu JavaScript automatyzuje osiągnięcie "inbox zero" w systemie | |
szkolnym mobiDziennik poprzez systematyczne otwieranie wszystkich | |
nieprzeczytanych wiadomości na wielu stronach. Uruchamia się w konsoli | |
przeglądarki i automatycznie nawiguje przez paginowane listy wiadomości, | |
otwierając każdą pojedynczą wiadomość, aby oznaczyć ją jako przeczytaną. | |
Skrypt zawiera ograniczenie szybkości i obsługę błędów, aby uniknąć | |
przeciążenia serwera podczas przetwarzania wszystkich wiadomości. | |
Sposób użycia: | |
1. Otwórz przeglądarkę i przejdź do strony mobiDziennik dla swojej szkoły. | |
2. Otwórz konsolę przeglądarki (zwykle F12 lub kliknij prawym przyciskiem | |
myszy i wybierz "Zbadaj element", a następnie przejdź do karty "Konsola"). | |
3. Skopiuj i wklej cały fragment kodu poniżej do konsoli. | |
4. Zamień '[school]' w baseUrl na rzeczywistą subdomenę swojej szkoły. | |
5. Naciśnij Enter, aby wykonać skrypt. | |
*/ | |
await (async function readAll({ | |
baseUrl, | |
timeout = 5000, | |
delay = 200 | |
} = {}) { | |
let seenPages = new Set() | |
let currentPage = 1 | |
let mainWindow = window | |
async function visitPage({ page }) { | |
await new Promise(resolve => { | |
setTimeout(resolve, delay) | |
}) | |
let url = `${baseUrl}/dziennik/wiadomosci/?sortuj_wg=otrzymano&sortuj_typ=desc&odebrane=${page}` | |
let win = window.open(url, '_blank') | |
if (!win) { | |
return | |
} | |
let promise = Promise.race([ | |
new Promise((resolve, reject) => { | |
setTimeout(reject, timeout, new Error(`Timeout while waiting for page ${page}`)) | |
}), | |
new Promise((resolve, reject) => { | |
win.addEventListener('load', resolve, { once: true }) | |
win.addEventListener('error', reject, { once: true }) | |
}) | |
]) | |
win.blur() | |
mainWindow.focus() | |
try { | |
await promise | |
} catch (err) { | |
console.error(err.message) | |
win.close() | |
return | |
} | |
let hasNextPage = [...win.document.querySelectorAll('.stronnicowanie a')] | |
.map(el => el.textContent.trim()) | |
.map(el => Number.parseInt(el, 10)) | |
.filter(Boolean) | |
.filter(el => !Number.isNaN(el)) | |
.sort((a, b) => a - b) | |
.some(el => el > currentPage) | |
let messageIds = [...win.document.querySelectorAll('table.spis tr.zielony1')] | |
.map(el => el.attributes.rel?.value) | |
.filter(Boolean) | |
.sort((a, b) => Number.parseInt(a, 10) - Number.parseInt(b, 10)) | |
.filter((v, i, a) => a.indexOf(v) === i) | |
let processesMessageIds = [] | |
for (let id of messageIds) { | |
let result = await visitMessage({ id }) | |
if (result) { | |
processesMessageIds.push(result) | |
} | |
} | |
win.close() | |
return { | |
hasNextPage, | |
processesMessageIds | |
} | |
} | |
async function visitMessage({ id }) { | |
await new Promise(resolve => { | |
setTimeout(resolve, delay) | |
}) | |
let url = `https://wpssuchylas.mobidziennik.pl/dziennik/wiadodebrana/?id=${id}` | |
let win = window.open(url, '_blank') | |
if (!win) { | |
return | |
} | |
let promise = Promise.race([ | |
new Promise((resolve, reject) => { | |
setTimeout(reject, timeout, new Error(`Timeout while waiting for message ${id}`)) | |
}), | |
new Promise((resolve, reject) => { | |
win.addEventListener('load', resolve, { once: true }) | |
win.addEventListener('error', reject, { once: true }) | |
}) | |
]) | |
win.blur() | |
mainWindow.focus() | |
try { | |
await promise | |
} catch (err) { | |
console.error(err.message) | |
win.close() | |
return | |
} | |
win.close() | |
return id | |
} | |
while (true) { | |
if (seenPages.has(currentPage)) { | |
break | |
} | |
seenPages.add(currentPage) | |
let result = await visitPage({ page: currentPage }) | |
if (!result) { | |
break | |
} | |
console.log(`Processed page ${currentPage}:`, result.processesMessageIds) | |
if (!result.hasNextPage) { | |
break | |
} | |
currentPage += 1 | |
} | |
})({ | |
baseUrl: 'https://[school].mobidziennik.pl' | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment