diff --git a/data/settings.json b/data/settings.json index c45113c..bcbd20a 100644 --- a/data/settings.json +++ b/data/settings.json @@ -8,6 +8,8 @@ "cache_path": "./data/cache", "prefix": "!", "ratelimit": 10, + "libretranslate_api": "https://translate.argosopentech.com/", + "libretranslate_api_key": "", "admin_command_list": [ "shrug", "emoji_size", diff --git a/main.py b/main.py index af3ca48..89fd218 100644 --- a/main.py +++ b/main.py @@ -17,6 +17,11 @@ import datetime # Ratelimiting # External dependencies import nio # Matrix library, matirx-nio[e2e] from PIL import Image # Resizing images, pillow +try: + from libretranslatepy import LibreTranslateAPI # Translation functionality + translate_available = True +except Exception: + translate_available = False # Set the settings path settings_path = "./data/settings.json" @@ -64,6 +69,19 @@ def filter_xkcd_title(title): filtered_title += char return filtered_title +# Takes in a country (US, CA, AU), outputs the "flag emoji"/regional indicator emojis +def flag_emoji(country): + regional_indicator_offset = 127397 + return chr(ord(country.upper()[0]) + regional_indicator_offset) + chr(ord(country.upper()[1]) + regional_indicator_offset) + +# Takes in a flag emoji, outputs as text instead of regional indicators +def flag_decode(emoji): + regional_indicator_offset = 127397 + try: + return chr(ord(emoji[0]) - regional_indicator_offset) + chr(ord(emoji[1]) - regional_indicator_offset) + except Exception: + return None + # Grab a list of all emojis on disk def list_emojis(): global settings @@ -293,6 +311,50 @@ async def aw(args, room, event): else: return await send_text(room.room_id, "Please provide a search term.") +async def unknown_callback(room: nio.MatrixRoom, event: nio.UnknownEvent) -> None: + if event.type == "m.reaction": + # Get the ID of the event this was a reaction to + relation_dict = event.source.get("content", {}).get("m.relates_to", {}) + + reacted_to = relation_dict.get("event_id") + if reacted_to and relation_dict.get("rel_type") == "m.annotation": + await reaction_callback(room, event, reacted_to) + return + +async def reaction_callback(room: nio.MatrixRoom, event: nio.UnknownEvent, reacted_to_id: str) -> None: + global client, settings, translate_available + if settings["debug"]: + print(f"Got reaction in {room.room_id} from {event.sender}.") + + # Get the original event that was reacted to + event_response = await client.room_get_event(room.room_id, reacted_to_id) + if isinstance(event_response, nio.RoomGetEventError): + return + reacted_to_event = event_response.event + + # Only acknowledge reactions that we sent + if event.sender != client.user_id: + return + + # Get the reaction + reaction_content = (event.source.get("content", {}).get("m.relates_to", {}).get("key")) + + if translate_available and len(reaction_content) == 2: + if flag_decode(reaction_content): + country = flag_decode(reaction_content).lower() + if country == "us" or country == "gb": + # Translate from auto to English + from_lang = "auto" + else: + # Translate from lang to English + from_lang = country + lt = LibreTranslateAPI(settings["libretranslate_api"], settings["libretranslate_api_key"] if "libretranslate_api_key" in settings.keys() and settings["libretranslate_api_key"] else None) + if from_lang not in [x["code"] for x in lt.languages()] and from_lang != "auto": + return await send_text(room.room_id, "Language " + from_lang + " is not supported!") + translated = lt.translate(reacted_to_event.body, from_lang, "en") + lang = lt.detect(reacted_to_event.body)[0]["language"].upper() if from_lang == "auto" else from_lang.upper() + return await send_text(room.room_id, "Translated from " + lang + " (" + flag_emoji("US" if lang == "EN" else lang) + "):\n" + translated) + async def message_callback(room: nio.MatrixRoom, event: nio.RoomMessageText) -> None: global client, settings, emojis if settings["debug"]: @@ -419,6 +481,7 @@ async def main() -> None: print(f"Logged in as: {client.user_id} with device {client.device_id}") await client.sync(timeout=60000, full_state=True) # Ignore any messages sent before now. client.add_event_callback(message_callback, nio.RoomMessageText) + client.add_event_callback(unknown_callback, nio.UnknownEvent) client.add_event_callback(decryption_failure_callback, (nio.MegolmEvent,)) if client.should_upload_keys: await client.keys_upload()