From e65bb333d372e72ec6220258a6d519e697e0fe54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Helge-Mikael=20Nordg=C3=A5rd?= Date: Mon, 12 Aug 2024 04:52:16 +0200 Subject: [PATCH] first commit --- base-config.yaml | 49 +++++++++++++++++++ maubot.yaml | 11 +++++ welcome_bot.py | 119 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 179 insertions(+) create mode 100644 base-config.yaml create mode 100644 maubot.yaml create mode 100644 welcome_bot.py diff --git a/base-config.yaml b/base-config.yaml new file mode 100644 index 0000000..075cfec --- /dev/null +++ b/base-config.yaml @@ -0,0 +1,49 @@ +announcement_room: '!cJQ12313dsSD33pciZAy:example.com' +watch_rooms: + - '!hZaqgiasAsdXPEeuXd:example.com' + - '!otherroom:example.com' +invite_codes: + - key: 'example-invitation' + value: '!kXT5F2Csds2BbYQPSzB:example.com' + - key: 'another-example-invitation' + value: '!otherroom:example.com' +notification_message: | + {userName} has joined the server ({userId}) 🥳 Everyone give them a warm welcome and say hello! +pm_message: | + Welcome to our Matrix server! We're glad to have you here. + For 🏴󠁧󠁢󠁥󠁮󠁧󠁿 English, type 'english'. For 🇳🇴 Norwegian, type 'norsk'. + + Velkommen til vår Matrix-server! Vi er glade for å ha deg her. + For 🏴󠁧󠁢󠁥󠁮󠁧󠁿 engelsk, skriv 'english'. For 🇳🇴 norsk, skriv 'norsk'. +en_pm: | + Hello {user} ! 👋 + + Welcome to our Matrix server! We're glad to have you here. I am + your friendly, neighbourhood bot, created by Helge to welcome you + to our community and server. + + Here are a few things to help you get started: + 1. Check out our server rules and guidelines in the #rules room. + 2. Introduce yourself in the #introductions room. + 3. If you need any help, feel free to ask in the #help room. + 4. If you have an 🎫invite code🎫, copy and paste it here, and I + will verify and then invite you to join more rooms! + + Enjoy your stay and happy chatting! 😊 +no_pm: | + Hei {user} ! 👋 + + Velkommen til vår Matrix-server! Vi er glade for å ha deg her. Jeg er + din vennlige, lokale bot, skapt av Helge for å ønske deg velkommen + til vårt fellesskap og vår server. + + Her er noen ting som kan hjelpe deg i gang: + 1. Sjekk ut våre serverregler og retningslinjer i #rules-rommet. + 2. Introduser deg selv i #introductions-rommet. + 3. Hvis du trenger hjelp, ikke nøl med å spørre i #help-rommet. + 4. Hvis du har en 🎫invitasjonskode🎫, kopier og lim den inn her, + så vil jeg verifisere den og invitere deg til flere rom! + + Kos deg og god chatting! 😊 +seen_users: + - '@exampleuser:example.com' \ No newline at end of file diff --git a/maubot.yaml b/maubot.yaml new file mode 100644 index 0000000..efe4500 --- /dev/null +++ b/maubot.yaml @@ -0,0 +1,11 @@ +maubot: 0.1.0 +id: no.zuul.welcomebot +version: 0.2.2 +license: MIT +modules: + - welcome_bot +config: true +extra_files: + - base-config.yaml +main_class: WelcomeBot +database: false \ No newline at end of file diff --git a/welcome_bot.py b/welcome_bot.py new file mode 100644 index 0000000..c68343a --- /dev/null +++ b/welcome_bot.py @@ -0,0 +1,119 @@ +from typing import Awaitable, Type, Optional, Tuple +import json +import time + +from mautrix.client import Client, InternalEventType, MembershipEventDispatcher, SyncStream +from mautrix.types import (Event, StateEvent, EventID, UserID, EventType, + RoomID, RoomAlias, ReactionEvent, RedactionEvent) +from mautrix.util.config import BaseProxyConfig, ConfigUpdateHelper +from maubot import Plugin, MessageEvent +from maubot.handlers import command, event + +class Config(BaseProxyConfig): + def do_update(self, helper: ConfigUpdateHelper) -> None: + helper.copy("watch_rooms") + helper.copy("announcement_room") + helper.copy("notification_message") + helper.copy("seen_users") + helper.copy("pm_message") + helper.copy("en_pm") + helper.copy("no_pm") + helper.copy("invite_codes") + +class WelcomeBot(Plugin): + async def start(self) -> None: + await super().start() + self.config.load_and_update() + self.client.add_dispatcher(MembershipEventDispatcher) + self.pm_rooms = set() + + def get_watched_rooms(self) -> list: + return self.config["watch_rooms"] + + def get_notification_message(self) -> str: + return self.config["notification_message"] + + def get_notification_room(self) -> str: + return self.config["announcement_room"] + + def get_seen_users(self) -> list: + return self.config["seen_users"] + + def get_pm_message(self) -> str: + return self.config["pm_message"] + + def get_en_pm(self) -> str: + return self.config["en_pm"] + + def get_no_pm(self) -> str: + return self.config["no_pm"] + + def get_invite_codes(self) -> list: + return self.config["invite_codes"] + + async def process_pm(self, evt: MessageEvent) -> None: + # Get the content of the message + message = evt.content.body + + # Check what type of message this is + + if "english" in message.lower(): + nick = self.client.parse_user_id(evt.sender)[0] + response = self.get_en_pm().format(user=nick) + elif "norsk" in message.lower(): + nick = self.client.parse_user_id(evt.sender)[0] + response = self.get_no_pm().format(user=nick) + else: + response = "I'm sorry Dave, I'm afraid I can't do that" + hasInvite = False + inviteTo = '' + + # Check if the message is an invite code for a channel or room + invites = {item['key']: item['value'] for item in self.get_invite_codes()} + for key, value in invites.items(): + if key in message: + hasInvite = True + inviteTo = value + + # If invite was found, invite the user to the room/channel and set the appropriate response + if hasInvite: + response = "Invite found for channel or room {room}. I have sent you the invite, please accept 🙌".format(room=inviteTo) + await self.client.invite_user(inviteTo, evt.sender, "Invited through invitation code") + + await self.client.send_text(evt.room_id, html=response) + + @event.on(EventType.ROOM_MESSAGE) + async def handle_pm(self, evt: MessageEvent) -> None: + # Check if this is direct chat (PM) we created and that the message is not from the bot itself + if evt.room_id in self.pm_rooms and evt.sender != self.client.mxid: + await self.process_pm(evt) + + @event.on(InternalEventType.JOIN) + async def greet(self, evt: StateEvent) -> None: + if evt.room_id in self.get_watched_rooms(): + if evt.source & SyncStream.STATE: + return + else: + # Check if the user is in seen users + if evt.sender in self.get_seen_users(): + return # We don't want to send a welcome message to a user which has already recieved one + + nick = self.client.parse_user_id(evt.sender)[0] + msg = self.get_notification_message().format(userName=nick, userId=evt.sender) + await self.client.send_notice(self.get_notification_room(), msg) + + # Send PM to user + pm_room = await self.client.create_room(is_direct=True, invitees=[evt.sender]) + self.pm_rooms.add(pm_room) # Add the id of the pm room to the list + pm = self.get_pm_message() + await self.client.send_text(pm_room, pm) + + # In the end, we add the user to the seen_users list so to not duplicate the welcome + self.config["seen_users"].append(evt.sender) + self.config.save() + else: + self.log.warning(f"No {evt.room_id} in {self.get_watched_rooms()}") + + @classmethod + def get_config_class(cls) -> Type[BaseProxyConfig]: + return Config \ No newline at end of file