Compare commits

...

2 Commits

Author SHA1 Message Date
lamp 709ef9885b Merge branch 'master' of ssh.gitea.moe:lamp/who-fuck-ping 2026-04-10 19:26:46 -07:00
lamp 001173037e configurable interval 2026-04-10 19:13:10 -07:00
4 changed files with 91 additions and 90 deletions
+1 -1
View File
@@ -1,2 +1,2 @@
conf.js conf.js
last_ts last_ts
+2 -2
View File
@@ -1,3 +1,3 @@
{ {
"deno.enable": true "deno.enable": true
} }
+1
View File
@@ -6,6 +6,7 @@ create conf.js and paste values
export const ACCESS_TOKEN = ""; // your access token you can get it from element settings export const ACCESS_TOKEN = ""; // your access token you can get it from element settings
export const SERVER_URL = ""; // your matrix server url without trailing slash i.e. https://matrix-client.matrix.org export const SERVER_URL = ""; // your matrix server url without trailing slash i.e. https://matrix-client.matrix.org
export const ROOM_ID = ""; // make a private room and put its id here export const ROOM_ID = ""; // make a private room and put its id here
export const INTERVAL = 30; // how often to check for new notifications
``` ```
run run
+87 -87
View File
@@ -1,87 +1,87 @@
import { ACCESS_TOKEN, SERVER_URL, ROOM_ID } from "./conf.js"; import { ACCESS_TOKEN, SERVER_URL, ROOM_ID, INTERVAL } from "./conf.js";
try { try {
var last_ts = Number(Deno.readTextFileSync("last_ts")); var last_ts = Number(Deno.readTextFileSync("last_ts"));
} catch (error) { } catch (error) {
var last_ts = 0; var last_ts = 0;
} }
async function fetchMatrix(url, options = {}) { async function fetchMatrix(url, options = {}) {
options.headers ||= {}; options.headers ||= {};
options.headers.Authorization ||= `Bearer ${ACCESS_TOKEN}`; options.headers.Authorization ||= `Bearer ${ACCESS_TOKEN}`;
url = SERVER_URL + url; url = SERVER_URL + url;
do { do {
console.debug("fetch", url); console.debug("fetch", url);
try { try {
var res = await fetch(url, options); var res = await fetch(url, options);
if (res.ok) break; if (res.ok) break;
console.warn("status:", res.status); console.warn("status:", res.status);
if (res.status == 429) { if (res.status == 429) {
var {retry_after_ms} = await res.json(); var {retry_after_ms} = await res.json();
} }
} catch (error) { } catch (error) {
console.error(error); console.error(error);
} }
await new Promise(r => setTimeout(r, retry_after_ms || 60000)); await new Promise(r => setTimeout(r, retry_after_ms || 60000));
} while (true) } while (true)
if (!res.ok) throw new Error(`HTTP ${res.status} ${await res.text()}`); if (!res.ok) throw new Error(`HTTP ${res.status} ${await res.text()}`);
return res; return res;
} }
async function checkNotifications() { async function checkNotifications() {
var new_notifications = []; var new_notifications = [];
var next_token; var next_token;
var limit = 5; var limit = 5;
l: do { l: do {
var data = await fetchMatrix(`/_matrix/client/v3/notifications?limit=${limit}${next_token ? `&from=${next_token}` : ''}`).then(res => res.json()); var data = await fetchMatrix(`/_matrix/client/v3/notifications?limit=${limit}${next_token ? `&from=${next_token}` : ''}`).then(res => res.json());
for (let n of data.notifications) { for (let n of data.notifications) {
if (n.ts <= last_ts) break l; if (n.ts <= last_ts) break l;
new_notifications.unshift(n); new_notifications.unshift(n);
} }
next_token = data.next_token; next_token = data.next_token;
limit = 50; limit = 50;
} while (next_token !== null) } while (next_token !== null)
console.debug("new notifications:", new_notifications); console.debug("new notifications:", new_notifications);
if (!new_notifications.length) return; if (!new_notifications.length) return;
for (let n of new_notifications) { for (let n of new_notifications) {
try { try {
await addNotificationToRoom(n); await addNotificationToRoom(n);
last_ts = n.ts; last_ts = n.ts;
Deno.writeTextFileSync("last_ts", String(last_ts)); Deno.writeTextFileSync("last_ts", String(last_ts));
} catch (error) { } catch (error) {
console.error(error); console.error(error);
} }
} }
} }
async function addNotificationToRoom(notification) { async function addNotificationToRoom(notification) {
var text = `https://matrix.to/#/${encodeURIComponent(notification.room_id)}/${encodeURIComponent(notification.event.event_id)} ${new Date(notification.ts).toLocaleString()}`; var text = `https://matrix.to/#/${encodeURIComponent(notification.room_id)}/${encodeURIComponent(notification.event.event_id)} ${new Date(notification.ts).toLocaleString()}`;
await fetchMatrix(`/_matrix/client/v3/rooms/${encodeURIComponent(ROOM_ID)}/send/m.room.message/${Math.random()}`, { await fetchMatrix(`/_matrix/client/v3/rooms/${encodeURIComponent(ROOM_ID)}/send/m.room.message/${Math.random()}`, {
method: "PUT", method: "PUT",
headers: { headers: {
"Content-Type": "application/json" "Content-Type": "application/json"
}, },
body: JSON.stringify({ body: JSON.stringify({
msgtype: "m.text", msgtype: "m.text",
format: "org.matrix.custom.html", format: "org.matrix.custom.html",
body: text, body: text,
formatted_body: `<p>${text}</p>\n<pre><code class=\"language-json\">${JSON.stringify(notification.event, null, '\t')}\n</code></pre>\n` formatted_body: `<p>${text}</p>\n<pre><code class=\"language-json\">${JSON.stringify(notification.event, null, '\t')}\n</code></pre>\n`
}) })
}); });
} }
while (true) { while (true) {
try { try {
await checkNotifications(); await checkNotifications();
} catch (error) { } catch (error) {
console.error(error); console.error(error);
} }
await new Promise(r => setTimeout(r, 10000)); await new Promise(r => setTimeout(r, (INTERVAL || 30) * 1000));
} }