From f5dd6bfda1eeae1f307f947456b77fd7a861ec8d Mon Sep 17 00:00:00 2001 From: Joscha Date: Thu, 23 Aug 2018 10:55:48 +0000 Subject: [PATCH] Create morse bot --- .gitignore | 3 + morse.conf.default | 9 ++ morse.py | 200 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 212 insertions(+) create mode 100644 .gitignore create mode 100644 morse.conf.default create mode 100644 morse.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..65f800f --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +**/__pycache__ +*.cookie +*.conf diff --git a/morse.conf.default b/morse.conf.default new file mode 100644 index 0000000..fbb26ca --- /dev/null +++ b/morse.conf.default @@ -0,0 +1,9 @@ +[general] +nick = morse +cookiefile = morse.cookie + +[rooms] +# Format: +# room +# room=password +test diff --git a/morse.py b/morse.py new file mode 100644 index 0000000..d85489d --- /dev/null +++ b/morse.py @@ -0,0 +1,200 @@ +import asyncio +import configparser +import logging +import re + +import yaboli +from yaboli.utils import * + + +class Morse: + SHORT_DESCRIPTION = "convert to and from morse code" + DESCRIPTION = ( + "'morse' converts to and from morse code.\n" + "In morse code, letters should be separated by spaces and words" + " separated by a slash '/'. Example: .... . .-.. .-.. --- / - .... . .-. .\n" + "Any other characters indicate the end of a morse code message." + " 'morse' will attempt to translate all morse code messages it finds.\n" + ) + COMMANDS = ( + "!demorse - convert the parent message from morse code\n" + "!demorse - convert the text from morse code\n" + "!morse - convert the parent message into morse code\n" + "!morse - convert some text into morse code\n" + ) + AUTHOR = "Created by @Garmy using github.com/Garmelon/yaboli\n" + CREDITS = "Original bot by Leidenfrost.\n" + + MORSE_RE = r"[\.\-\/ ]+" + + TO_MORSE = { + "a": ".-", + "b": "-...", + "c": "-.-.", + "d": "-..", + "e": ".", + "f": "..-.", + "g": "--.", + "h": "....", + "i": "..", + "j": ".---", + "k": "-.-", + "l": ".-..", + "m": "--", + "n": "-.", + "o": "---", + "p": ".--.", + "q": "--.-", + "r": ".-.", + "s": "...", + "t": "-", + "u": "..-", + "v": "...-", + "w": ".--", + "x": "-..-", + "y": "-.--", + "z": "--..", + "1": ".----", + "2": "..---", + "3": "...--", + "4": "....-", + "5": ".....", + "6": "-....", + "7": "--...", + "8": "---..", + "9": "----.", + "0": "-----", + ".": ".-.-.-", + ",": "--..--", + ":": "---...", + "?": "..--..", + "'": ".----.", + "-": "-....-", + "/": "-..-.", + "(": "-.--.", + ")": "-.--.-", + '"': ".-..-.", + "=": "-...-", + "+": ".-.-.", + "×": "-..-", + "@": ".--.-.", + } + FROM_MORSE = {v: i for i, v in TO_MORSE.items()} + + @classmethod + def from_morse(cls, text): + words = [word.strip() for word in text.split("/")] + words_trans = [] + for word in words: + letters = [letter for letter in word.split(" ") if letter] + trans = [cls.FROM_MORSE.get(letter, "�") for letter in letters] + words_trans.append("".join(trans)) + return " ".join(words_trans) + + def to_morse(cls, text): + words = [word for word in text.split(" ") if word] + words_trans = [] + for word in words: + untranslated = "" + result = [] + + # preserve untranslatable sequences of letters + for letter in word: + trans = cls.TO_MORSE.get(letter.lower()) + if trans: + if untranslated: + result.append(untranslated) + untranslated = "" + result.append(trans) + else: + untranslated += letter + if untranslated: + result.append(untranslated) + + words_trans.append(" ".join(result)) + + return " / ".join(words_trans) + + @yaboli.command("demorse") + async def command_demorse(self, room, message, argstr): + text = argstr.strip() + + if not text and message.parent: + msg = await room.get_message(message.parent) + text = msg.content.strip() + + if not text: + await room.send("Can't demorse nothing.", message.mid) + return + + matches = re.findall(self.MORSE_RE, text) + matches = [match.strip() for match in matches if match.strip()] + + if not matches: + await room.send("No morse code found.", message.mid) + return + + translated = [self.from_morse(match) for match in matches] + translated = [word for word in translated if len(word) > 1] + await room.send("\n".join(translated), message.mid) + + @yaboli.command("morse") + async def command_morse(self, room, message, argstr): + text = argstr.strip() + + if not text and message.parent: + msg = await room.get_message(message.parent) + text = msg.content.strip() + + if not text: + await room.send("Can't morse nothing.", message.mid) + return + + lines = text.split("\n") + translated = [self.to_morse(line) for line in lines] + await room.send("\n".join(translated), message.mid) + +class MorseBot(yaboli.Bot): + SHORT_HELP = Morse.SHORT_DESCRIPTION + LONG_HELP = Morse.DESCRIPTION + Morse.COMMANDS + Morse.AUTHOR + Morse.CREDITS + PING_TEXT = ".--. --- -. --." + + def __init__(self, nick, cookiefile=None): + super().__init__(nick, cookiefile=cookiefile) + self.morse = Morse() + + async def on_command_specific(self, room, message, command, nick, argstr): + if similar(nick, room.session.nick) and not argstr: + await self.botrulez_ping(room, message, command, text=self.PING_TEXT) + await self.botrulez_help(room, message, command, text=self.LONG_HELP) + await self.botrulez_uptime(room, message, command) + await self.botrulez_kill(room, message, command) + await self.botrulez_restart(room, message, command) + + async def on_command_general(self, room, message, command, argstr): + if not argstr: + await self.botrulez_ping(room, message, command, text=self.PING_TEXT) + await self.botrulez_help(room, message, command, text=self.SHORT_HELP) + + await self.morse.command_demorse(room, message, command, argstr) + await self.morse.command_morse(room, message, command, argstr) + +def main(configfile): + logging.basicConfig(level=logging.INFO) + + config = configparser.ConfigParser(allow_no_value=True) + config.read(configfile) + + nick = config.get("general", "nick") + cookiefile = config.get("general", "cookiefile", fallback=None) + bot = MorseBot(nick, cookiefile=cookiefile) + + for room, password in config.items("rooms"): + if not password: + password = None + bot.join_room(room, password=password) + + asyncio.get_event_loop().run_forever() + +if __name__ == "__main__": + main("morse.conf")