Compare commits

..

1 Commits

8 changed files with 28 additions and 1834 deletions

View File

@ -2,7 +2,7 @@
<p>Doorbell bot for matrix</p> <p>Doorbell bot for matrix</p>
<p>The bot will only respond & join in authorized rooms (add authorized room IDs in `config.json` => `rooms`). <p>The bot will only respond & join in authorized rooms (add authorized room IDs in `config.json` => `rooms`).
NOTE: The bot needs to have the room authorized before being invited. If the bot is invited, then has the room authorized in the config, it <b>will not</b> join!</p> NOTE: The bot needs to have the room authorized before being invited. If the bot is invited, then has the room authorized in the config, it <b>will not</b> join!</p>
<p>The commands to trigger the doorbell is: "doorbell", "open", "ring", "knock", "ding", "dong" & "dingdong"</p> <p>The commands to trigger the doorbell are defined in the config file</p>
# How to run: # How to run:
## Step 1: Getting an access token ## Step 1: Getting an access token
@ -20,6 +20,7 @@ NOTE: The bot needs to have the room authorized before being invited. If the bot
- Fill in: `homeserver` (`config.json`) (This should already be filled if step `1.1` was done) - Fill in: `homeserver` (`config.json`) (This should already be filled if step `1.1` was done)
- Fill in: `token` (`config.json`) (This is the token you got in step `1.2`) - Fill in: `token` (`config.json`) (This is the token you got in step `1.2`)
- Fill in: `prefix` (`config.json`) - Fill in: `prefix` (`config.json`)
- Fill in: `commands` (`config.json`) (Commands are case insensitive, and should not include the prefix)
- Fill in: `rooms` (`config.json`) - Fill in: `rooms` (`config.json`)
- Fill in: `doorbellWebhook` (`config.json`) - Fill in: `doorbellWebhook` (`config.json`)
### Step 2.2: Actually running the bot ### Step 2.2: Actually running the bot

View File

@ -2,6 +2,7 @@
"homeserver": "HOME_SERVER", "homeserver": "HOME_SERVER",
"token": "ACCESS_TOKEN", "token": "ACCESS_TOKEN",
"prefix": "BOT_PREFIX", "prefix": "BOT_PREFIX",
"commands": ["COMMAND1", "COMMAND2"],
"rooms": ["AUTHORIZED_ROOM_ID", "ANOTHER_AUTHORIZED_ID"], "rooms": ["AUTHORIZED_ROOM_ID", "ANOTHER_AUTHORIZED_ID"],
"doorbellWebhook": "https://GOOGLE.ASSISTANT.WEBHOOK.URL/" "doorbellWebhook": "https://GOOGLE.ASSISTANT.WEBHOOK.URL/"
} }

View File

@ -23,23 +23,19 @@
src = lib.fileset.toSource { src = lib.fileset.toSource {
root = ./.; root = ./.;
fileset = lib.fileset.difference ./. (lib.fileset.unions [ fileset = lib.fileset.difference ./. (lib.fileset.unions [
./module.nix
./flake.lock
./flake.nix ./flake.nix
./flake.lock
]); ]);
}; };
npmDepsHash = "sha256-518ln/eAlgnKcubOTquBP8gj9Q/lT5bhpJGWOeuUKmY="; npmDepsHash = "sha256-UNc902yMkoWfpun1RrLYlEtOXcFd7uxlwKFWoM0/nTE=";
postInstall = ''
ln -vs /run/secrets/pvv-doorbell-config.json $out/lib/node_modules/$pname/config.json
'';
dontNpmBuild = true; dontNpmBuild = true;
}; };
}); });
overlays = forAllSystems (system: {
default = prevPackages: finalPackages: {
pvv-doorbell-bot = self.packages.${system}.default;
};
});
nixosModules.default = import ./module.nix;
}; };
} }

View File

@ -7,13 +7,12 @@ import {
import axios from "axios"; import axios from "axios";
import { env } from 'node:process'; import config from "./config.json" assert {type: "json"};
const config = await import (env.DOORBELL_CONFIG_FILE || "./config.json"); // assert {type: "json"};
const homeserverUrl = config.homeserver; const homeserverUrl = config.homeserver;
const token = config.token; const token = config.token;
const prefix = config.prefix; const prefix = config.prefix;
const commandsRaw = config.commands;
const rooms = config.rooms; const rooms = config.rooms;
const doorbellWebhook = config.doorbellWebhook; const doorbellWebhook = config.doorbellWebhook;
@ -24,9 +23,12 @@ function configNotFound(name) {
if (!homeserverUrl) configNotFound("homeserver"); if (!homeserverUrl) configNotFound("homeserver");
if (!token) configNotFound("token"); if (!token) configNotFound("token");
if (!prefix) configNotFound("prefix"); if (!prefix) configNotFound("prefix");
if (!commandsRaw) configNotFound("commands");
if (!rooms) configNotFound("rooms"); if (!rooms) configNotFound("rooms");
if (!doorbellWebhook) configNotFound("doorbellWebhook"); if (!doorbellWebhook) configNotFound("doorbellWebhook");
const commands = commandsRaw.map(cmd => cmd.toLowerCase());
// We'll want to make sure the bot doesn't have to do an initial sync every // We'll want to make sure the bot doesn't have to do an initial sync every
// time it restarts, so we need to prepare a storage provider. Here we use // time it restarts, so we need to prepare a storage provider. Here we use
// a simple JSON database. // a simple JSON database.
@ -50,6 +52,12 @@ client.on("room.invite", (roomId) => {
// client up. This will start it syncing. // client up. This will start it syncing.
client.start().then(() => console.log("Client started!")); client.start().then(() => console.log("Client started!"));
function noDingDong(client, roomId, event, error) {
console.log("No ding dong :(");
console.log(error);
client.replyNotice(roomId, event, "Couldn't dingdong the doorbell :(");
}
// This is our event handler for dealing with commands. // This is our event handler for dealing with commands.
async function handleCommand(roomId, event) { async function handleCommand(roomId, event) {
// Don't handle events that don't have contents (they were probably redacted) // Don't handle events that don't have contents (they were probably redacted)
@ -71,16 +79,16 @@ async function handleCommand(roomId, event) {
if (!rawText || !rawText.startsWith(prefix)) return; if (!rawText || !rawText.startsWith(prefix)) return;
const text = rawText.substring(prefix.length); const text = rawText.substring(prefix.length);
if (["doorbell", "open", "ring", "knock", "ding", "dong", "dingdong"].includes(text)) { if (commands.some(cmd => text.toLowerCase().startsWith(cmd))) {
fetch(doorbellWebhook, { method: 'POST' }).then(response => { fetch(doorbellWebhook, { method: 'POST' }).then(response => {
if (response.ok) { if (response.ok) {
console.log("DING DONG!"); console.log("DING DONG!");
client.replyNotice(roomId, event, "Doorbell dingdonged!");
} else { } else {
console.log("No ding dong :("); noDingDong(client, roomId, event, response);
console.log(response);
} }
}); }).catch(err => noDingDong(client, roomId, event, err));
} }
var tags = []; var tags = [];
@ -132,4 +140,4 @@ async function handleCommand(roomId, event) {
}; };
client.sendMessage(roomId, event); client.sendMessage(roomId, event);
} }

View File

@ -1,61 +0,0 @@
{ config, lib, pkgs, ... }:
let
cfg = config.services.pvv-doorbell-bot;
inherit (lib) mkDefault mkEnableOption mkPackageOption mkIf mkOption types mdDoc;
in
{
options.services.pvv-doorbell-bot = {
enable = mkEnableOption (lib.mdDoc "Enable the doorbell service that alerts on matrix/discord pings");
package = mkPackageOption pkgs "pvv-doorbell-bot" { };
nodePackage = mkPackageOption pkgs "nodejs_20" { };
user = mkOption {
type = types.str;
default = "pvv-doorbell-bot";
};
group = mkOption {
type = types.str;
default = "pvv-doorbell-bot";
};
settings = {
configFile = mkOption {
type = types.path;
description = mdDoc "Path to secret config.json file that sets the options defined in `config.json.template`";
};
};
};
config = mkIf cfg.enable {
users.users = mkIf (cfg.user == "pvv-doorbell-bot") {
pvv-doorbell-bot = {
description = "PVV Doorbell Matrix Bot User";
isSystemUser = true;
group = cfg.group;
};
};
users.groups = mkIf (cfg.group == "pvv-doorbell-bot") {
pvv-doorbell-bot = { };
};
systemd.services."pvv-doorbell-bot" = {
serviceConfig = let
appDir = "${cfg.package}/lib/node_modules/doorbell-matrix-bot";
in {
ExecStart = "${lib.getExe cfg.nodePackage} ${appDir}/index.mjs";
WorkingDirectory = appDir;
RuntimeDirectory = "pvv-doorbell-bot";
User = cfg.user;
Group = cfg.group;
};
environment = {
DOORBELL_CONFIG_FILE = cfg.settings.configFile;
};
};
};
}

1751
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,6 @@
"author": "henrkgr", "author": "henrkgr",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"axios": "^1.7.4", "axios": "^1.7.4"
"matrix-bot-sdk": "^0.7.1"
} }
} }

1
result
View File

@ -1 +0,0 @@
/nix/store/4688vk323al998nig45cs94mxj5rjf9k-doorbell-matrix-bot-1.0.0