euphoria-morse/morse.py

207 lines
5.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 <text> - convert the text from morse code\n"
"!morse - convert the parent message into morse code\n"
"!morse <text> - 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, "<EFBFBD>") 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
whole = re.fullmatch(self.MORSE_RE, text.strip())
if whole:
translated = self.from_morse(whole.group(0))
await room.send(translated, message.mid)
return
matches = re.findall(self.MORSE_RE, text)
matches = [match for match in matches
if match.strip(" /") not in {"", ".", "-", "..."}]
translated = [self.from_morse(match) for match in matches]
if not translated:
await room.send("No morse code found.", message.mid)
return
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")