import asyncio import random import extradiscord import database import lol import royalbotconfig import telegram loop = asyncio.get_event_loop() b = telegram.Bot(royalbotconfig.telegram_token) d = extradiscord.ExtraClient(royalbotconfig.discord_token) async def answer(bot, thing, text): """Rispondi al messaggio con il canale corretto.""" # Answer on Telegram if isinstance(thing, telegram.Update): await thing.message.reply(bot, text, parse_mode="Markdown") # Answer on Discord elif isinstance(thing, extradiscord.discord.Message): await bot.send_message(thing.channel, text) else: raise TypeError("thing must be either a telegram.Update or a discord.Message") async def status_typing(bot, thing): """Imposta lo stato a Bot sta scrivendo...""" # Set typing status on Telegram if isinstance(thing, telegram.Update): await thing.message.chat.set_chat_action(bot, "typing") # Set typing status on Discord elif isinstance(thing, extradiscord.discord.Message): await bot.send_typing(thing.channel) else: raise TypeError("thing must be either a telegram.Update or a discord.Message") async def display_help(bot, thing, func): """Display the help command of a function""" # Telegram bot commands start with / if isinstance(thing, telegram.Update): symbol = "/" # Discord bot commands start with ! elif isinstance(thing, extradiscord.discord.Message): symbol = "!" # Unknown service else: raise TypeError("thing must be either a telegram.Update or a discord.Message") # Display the help message await answer(bot, thing, func.__doc__.format(symbol=symbol)) def find_date(thing): """Find the date of a message.""" if isinstance(thing, telegram.Update): date = thing.message.date elif isinstance(thing, extradiscord.discord.Message): date = thing.timestamp else: raise TypeError("thing must be either a telegram.Update or a discord.Message") return date async def diario(bot, thing, arguments): """Aggiungi una frase al diario Royal Games. Devi essere un Royal per poter eseguire questo comando. Sintassi: `{symbol}diario `""" # Set status to typing await status_typing(bot, thing) # Check the command syntax if len(arguments) == 0: await display_help(bot, thing, diario) return # Prepare the text text = " ".join(arguments).strip() # Add the new entry database.new_diario_entry(find_date(thing), text) # Answer on Telegram await answer(bot, thing, "✅ Aggiunto al diario!") async def leggi(bot, thing, arguments): """Leggi una frase con un id specifico dal diario Royal Games. Sintassi: {symbol}leggi """ # Set status to typing await status_typing(bot, thing) # Create a new database session session = database.Session() # Cast the number to an int try: n = int(arguments[0]) except ValueError: await answer(bot, thing, "⚠ Il numero specificato non è valido.") return # Query the diario table for the entry with the specified id entry = session.query(database.Diario).filter_by(id=n).first() # Check if the entry exists if entry is None: await answer(bot, thing, "⚠ Non esiste una frase del diario con quel numero.") return # Display the entry await answer(bot, thing, f"*Dal diario Royal Games, il {entry.date}*:\n" f"{entry.text}") async def helpme(bot, thing, arguments): """Visualizza il messaggio di aiuto di un comando. Sintassi: `{symbol}helpme [comando]`""" # Set status to typing await status_typing(bot, thing) # If no command is specified, show the help message for this command. if len(arguments) == 0 or len(arguments) > 1: await display_help(bot, thing, helpme) return # Check the list of telegram commands if the message was sent from Telegram if isinstance(thing, telegram.Update): if arguments[0] in b.commands: await display_help(bot, thing, b.commands[arguments[0]]) else: await answer(bot, thing, "⚠ Il comando specificato non esiste.") # Check the list of discord commands if the message was sent from Discord if isinstance(thing, extradiscord.discord.Message): if arguments[0] in d.commands: await display_help(bot, thing, d.commands[arguments[0]]) else: await answer(bot, thing, "⚠ Il comando specificato non esiste.") async def cv(bot, thing, arguments): """Visualizza lo stato attuale della chat vocale Discord. Sintassi: `{symbol}cv`""" # Set status to typing await status_typing(bot, thing) # Check command syntax if len(arguments) != 0: await display_help(bot, thing, cv) return # Wait for the Discord bot to login while not d.client.is_logged_in: await asyncio.sleep(1) # Find all the users in the server # Change this if the bot is logged in more than one server at once? users = list(d.client.get_all_members()) # Find all the channels channels = dict() for user in users: if user.voice_channel is not None: if user.voice_channel.name not in channels: channels[user.voice_channel.name] = list() channels[user.voice_channel.name].append(user) # Create the string to send to Telegram to_send = str() for channel in channels: # Channel header to_send += f"*{channel}:*\n" # Users in channel for user in channels[channel]: # Online status if user.status.name == "online": # Online status = "🔵" elif user.status.name == "dnd" or (user.game is not None and user.game.type == 1): # Do not disturb or streaming status = "🔴" elif user.status.name == "idle": # Idle status = "⚫" elif user.status.name == "offline": # Invisible status = "⚪" else: # Unknown status = "❓" # Voice status if user.bot: # Music bot volume = "🎵" elif user.voice.deaf or user.voice.self_deaf: # Deafened volume = "🔇" elif user.voice.mute or user.voice.self_mute: # Muted volume = "🔈" else: # Speaking volume = "🔊" # Game, is formatted if user.game is not None: # Playing if user.game.type == 0: # Game name game = f"- *{user.game.name}*" # Streaming elif user.game.type == 1: # Stream name and url game = f"- [{user.game.name}]({user.game.url})" else: game = "" # Nickname if available, otherwise use the username if user.nick is not None: name = user.nick else: name = user.name # Add the user to_send += f"{volume} {status} {name} {game}\n" # Channel footer to_send += "\n" await answer(bot, thing, to_send) async def roll(bot, thing, arguments): """Lancia un dado a N facce. Sintassi: `{symbol}roll `""" # Set status to typing await status_typing(bot, thing) # Check the command syntax if len(arguments) != 1: await display_help(bot, thing, roll) return # Roll the dice! await answer(bot, thing, f"*Numero generato:* {random.randrange(0, int(arguments[0])) + 1}") # DISCORD ONLY! async def syncdiscord(bot, thing: extradiscord.discord.Message, arguments): """Crea un nuovo account usando il tuo ID di Discord. Sintassi: `{symbol}syncdiscord`""" # Set status to typing await status_typing(bot, thing) # Check the command syntax if len(arguments) != 0: await display_help(bot, thing, syncdiscord) return # Open a new database session session = database.Session() # Check if the user already exists user = session.query(database.Account).filter_by(id=thing.author.id).first() if user is not None: await answer(bot, thing, "⚠ L'account è già stato registrato.") return # Create a new user user = database.Account(id=thing.author.id) session.add(user) session.commit() # Notify the sender await answer(bot, thing, "✅ Account registrato con successo!") # DISCORD ONLY! async def synclol(bot, thing: extradiscord.discord.Message, arguments): """Connetti il tuo account di LoL all'account Royal Games! Sintassi: `{symbol}synclol `""" # Set status to typing await status_typing(bot, thing) # Check the command syntax if len(arguments) < 1: await display_help(bot, thing, synclol) return # Open a new database session session = database.Session() # Create a new lol account and connect it to the user user = session.query(database.Account).filter_by(id=thing.author.id).first() if user is None: await answer(bot, thing, "⚠ Fai il login prima di sincronizzare l'account di LoL.") return # Check if there are other LoL account registered with the user user = session.query(database.Account).filter_by(id=thing.author.id).join(database.LoL).all() if len(user) > 0: await answer(bot, thing, "⚠ Hai già un account connesso.\n_Se stai cercando di registrare uno smurf, chiedi a Steffo._") # Get data about the user summoner_name = " ".join(arguments) data = await lol.get_summoner_data("euw", summoner_name=summoner_name) # Create a new database entry for the account lolaccount = database.LoL(id=data["id"], summoner_name=summoner_name) lolaccount.parent_id = thing.author.id session.add(lolaccount) # Update the newly added user lolaccount.update_data() # Send some info to Discord await d.client.send_message(thing.channel, "Connessione riuscita!", embed=lolaccount.generate_discord_embed()) # Commit the changes to the database session.commit() async def job_updatelol(singletimeout=1, alltimeout=1800): await d.client.wait_until_ready() while True: # Open a new database session session = database.Session() # Query all the LoL accounts users = session.query(database.LoL).all() # Update all the users' stats for user in users: updates = await user.update_data() if updates: # Send some info to Discord await d.client.send_message(d.client.get_channel(247426005537390592), "Account aggiornato!", embed=user.generate_discord_embed()) await asyncio.sleep(singletimeout) session.commit() await asyncio.sleep(alltimeout) if __name__ == "__main__": # Init universal bot commands b.commands["diario"] = diario d.commands["diario"] = diario b.commands["d"] = diario b.commands["help"] = helpme b.commands["helpme"] = helpme d.commands["help"] = helpme d.commands["helpme"] = helpme b.commands["cv"] = cv d.commands["syncdiscord"] = syncdiscord d.commands["synclol"] = synclol # Init Telegram bot loop.create_task(b.run()) print("Telegram bot start scheduled!") # Init Discord bot loop.create_task(d.run()) print("Discord bot start scheduled!") # Init LoL stats updater loop.create_task(job_updatelol()) print("LoL database updater scheduled!") # Run everything! loop.run_forever()