initial work

This commit is contained in:
Michcio 2022-09-26 00:47:25 +02:00
commit 51539a25d2
5 changed files with 259 additions and 0 deletions

6
.gitignore vendored Normal file
View file

@ -0,0 +1,6 @@
node_modules
.env.secret
*.d.ts
*.js
*.tsbuildinfo
image_cache

113
index.ts Normal file
View file

@ -0,0 +1,113 @@
import fs from 'fs/promises';
import path from 'path';
import notifier from 'node-notifier';
import ReconnectingWebSocket from 'reconnecting-websocket';
import { WebSocket } from 'ws';
const INSTANCE = process.env.FK_INSTANCE;
const TOKEN = process.env.FK_TOKEN;
const image_cache = path.resolve('image_cache');
await fs.mkdir(image_cache, { recursive: true });
const iconPath = path.join(image_cache, 'instance.jpg');
{
const resp = await fetch(`https://${INSTANCE}/api/meta`, { method: 'POST', headers: { authorization: `bearer ${TOKEN}` } });
const meta = await resp.json();
const iconResp = await fetch(meta.iconUrl);
const iconBuf = await iconResp.blob();
await fs.writeFile(iconPath, iconBuf.stream());
}
const socket = new ReconnectingWebSocket(`wss://${INSTANCE}/streaming?i=${TOKEN}`, undefined, { WebSocket });
socket.addEventListener('open', ({ type }) => console.log({ type }));
socket.addEventListener('close', ({ code, reason, wasClean, type }) => console.log({ code, reason, wasClean, type }));
socket.addEventListener('error', ({ error, message, type }) => console.log({ error, message, type }));
socket.addEventListener('open', (ev) => {
socket.send(JSON.stringify({ type: "connect", body: { channel: "main", id: "1" } }))
});
socket.addEventListener('message', ({ data }) => {
const payload = JSON.parse(data);
if (payload.type === 'channel' && payload.body.type === 'notification') {
const notification = payload.body.body;
const user = notification.user;
const note = notification.note;
const userName = user.host !== null ? `${user.username}@${user.host}` : user.username;
let title: string;
let body = 'note' in notification ? (note.cw != null ? note.cw : (note.text || '')) : undefined;
switch (notification.type) {
case 'pollEnded':
title = `${userName}'s poll has ended`;
break;
case 'follow':
title = `follow from ${userName}`;
break;
case 'followRequestAccepted':
title = `accept from ${userName}`;
break;
case 'mention':
title = `mention from ${userName}`;
break;
case 'pollVote':
title = `vote from ${userName}`;
break;
case 'quote':
title = `quote from ${userName}`;
break;
case 'reaction':
{
let reaction: string = notification.reaction;
reaction = reaction.split('@')[0];
if (reaction.startsWith(':'))
reaction = reaction.slice(1);
title = `${reaction} from ${userName}`;
}
break;
case 'receiveFollowRequest':
title = `follow req from ${userName}`;
break;
case 'renote':
title = `renote from ${userName}`;
break;
case 'reply':
title = `reply from ${userName}`;
break;
case 'groupInvited':
title = `group invite from ${userName}`;
break;
default:
console.log({ type: notification.type });
return;
}
const avatarUrl = new URL(user.avatarUrl);
const avatarServerPath = avatarUrl.pathname.split('/');
const avatarStem = avatarServerPath[avatarServerPath.length - 1];
const avatarFilename = `${avatarStem}.webp`;
const avatarPath = path.join(image_cache, avatarFilename);
(async () => {
try {
await fs.access(avatarPath);
} catch {
const resp = await fetch(avatarUrl);
if (!resp.ok) {
throw resp;
}
const buf = await resp.blob();
await fs.writeFile(avatarPath, buf.stream());
}
// console.log(user, userName, title, body);
notifier.notify({
title,
message: body,
icon: iconPath,
contentImage: avatarPath,
});
})()
}
});
await new Promise(() => { });

21
package.json Normal file
View file

@ -0,0 +1,21 @@
{
"name": "fk-macos-notif",
"version": "1.0.0",
"main": "index.ts",
"type": "module",
"license": "MIT",
"scripts": {
"start": "node index.js",
"prestart": "tsc -b"
},
"dependencies": {
"node-notifier": "^10.0.1",
"reconnecting-websocket": "^4.4.0",
"typescript": "^4.8.3",
"ws": "^8.9.0"
},
"devDependencies": {
"@types/node-notifier": "^8.0.2",
"@types/ws": "^8.5.3"
}
}

12
tsconfig.json Normal file
View file

@ -0,0 +1,12 @@
{
"compilerOptions": {
"resolveJsonModule": true,
"esModuleInterop": true,
"target": "ES2022",
"module": "ES2022",
"moduleResolution": "node",
"strict": true,
"composite": true,
"noEmitOnError": false
}
}

107
yarn.lock Normal file
View file

@ -0,0 +1,107 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@types/node-notifier@^8.0.2":
version "8.0.2"
resolved "https://registry.yarnpkg.com/@types/node-notifier/-/node-notifier-8.0.2.tgz#77c5de29c6e8adb915222b01864128cc3e78d553"
integrity sha512-5v0PhPv0AManpxT7W25Zipmj/Lxp1WqfkcpZHyqSloB+gGoAHRBuzhrCelFKrPvNF5ki3gAcO4kxaGO2/21u8g==
dependencies:
"@types/node" "*"
"@types/node@*":
version "18.7.21"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.21.tgz#63ee6688070e456325b6748dc492a7b948593871"
integrity sha512-rLFzK5bhM0YPyCoTC8bolBjMk7bwnZ8qeZUBslBfjZQou2ssJdWslx9CZ8DGM+Dx7QXQiiTVZ/6QO6kwtHkZCA==
"@types/ws@^8.5.3":
version "8.5.3"
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.3.tgz#7d25a1ffbecd3c4f2d35068d0b283c037003274d"
integrity sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==
dependencies:
"@types/node" "*"
growly@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
integrity sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw==
is-docker@^2.0.0:
version "2.2.1"
resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa"
integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==
is-wsl@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271"
integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==
dependencies:
is-docker "^2.0.0"
isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
lru-cache@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
dependencies:
yallist "^4.0.0"
node-notifier@^10.0.1:
version "10.0.1"
resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-10.0.1.tgz#0e82014a15a8456c4cfcdb25858750399ae5f1c7"
integrity sha512-YX7TSyDukOZ0g+gmzjB6abKu+hTGvO8+8+gIFDsRCU2t8fLV/P2unmt+LGFaIa4y64aX98Qksa97rgz4vMNeLQ==
dependencies:
growly "^1.3.0"
is-wsl "^2.2.0"
semver "^7.3.5"
shellwords "^0.1.1"
uuid "^8.3.2"
which "^2.0.2"
reconnecting-websocket@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/reconnecting-websocket/-/reconnecting-websocket-4.4.0.tgz#3b0e5b96ef119e78a03135865b8bb0af1b948783"
integrity sha512-D2E33ceRPga0NvTDhJmphEgJ7FUYF0v4lr1ki0csq06OdlxKfugGzN0dSkxM/NfqCxYELK4KcaTOUOjTV6Dcng==
semver@^7.3.5:
version "7.3.7"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f"
integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==
dependencies:
lru-cache "^6.0.0"
shellwords@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b"
integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==
typescript@^4.8.3:
version "4.8.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.3.tgz#d59344522c4bc464a65a730ac695007fdb66dd88"
integrity sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==
uuid@^8.3.2:
version "8.3.2"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
which@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
dependencies:
isexe "^2.0.0"
ws@^8.9.0:
version "8.9.0"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.9.0.tgz#2a994bb67144be1b53fe2d23c53c028adeb7f45e"
integrity sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==
yallist@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==