From 977aa63b047f5cc93b649d350bb0d34b3d5efde9 Mon Sep 17 00:00:00 2001 From: GrigoriyPA <79596613+GrigoriyPA@users.noreply.github.com> Date: Tue, 5 Jul 2022 21:21:30 +0500 Subject: [PATCH 1/6] Delete client_classes directory --- client_classes/DiscordClient.py | 19 ------------ client_classes/Message.py | 24 --------------- client_classes/TelegramClient.py | 29 ------------------ client_classes/VkClient.py | 51 -------------------------------- 4 files changed, 123 deletions(-) delete mode 100644 client_classes/DiscordClient.py delete mode 100644 client_classes/Message.py delete mode 100644 client_classes/TelegramClient.py delete mode 100644 client_classes/VkClient.py diff --git a/client_classes/DiscordClient.py b/client_classes/DiscordClient.py deleted file mode 100644 index 8b59058..0000000 --- a/client_classes/DiscordClient.py +++ /dev/null @@ -1,19 +0,0 @@ -import discord -from client_classes.Message import Message - - -class DiscordClient(discord.Client): - def __init__(self, compute_message_func): - super(DiscordClient, self).__init__() - self.compute_massage = compute_message_func - - async def on_message(self, message): - if message.author != self.user: - author_name = message.author.name - chat_name = None - if type(message.channel) != discord.channel.DMChannel: - chat_name = message.author.guild.name + "/" + message.channel.name - self.compute_massage(Message((message.channel.id, "DS"), message.content, message.author.id, author_name, chat_name)) - - def send_msg(self, id, text): - self.loop.create_task(self.get_channel(id).send(text)) diff --git a/client_classes/Message.py b/client_classes/Message.py deleted file mode 100644 index c302741..0000000 --- a/client_classes/Message.py +++ /dev/null @@ -1,24 +0,0 @@ -class Message: - def __init__(self, from_id, text, author_id, author_name, chat_name): - self.from_id = from_id - self.text = text - self.author_id = author_id - self.author_name = author_name - self.chat_name = chat_name - - def is_chat_command(self): - return len(self.text) > 0 and self.text[0] == "!" - - def get_author_id(self): - return str(self.author_id) + self.from_id[1] - - def get_chat_command(self): - if not self.is_chat_command(): - return None - return self.text[1:].strip().lower() - - def get_text_to_forwarding(self): - description = "" - if self.author_name is not None: - description += self.author_name + ":\n" - return description + self.text diff --git a/client_classes/TelegramClient.py b/client_classes/TelegramClient.py deleted file mode 100644 index 5bf2e01..0000000 --- a/client_classes/TelegramClient.py +++ /dev/null @@ -1,29 +0,0 @@ -import threading -import telebot -from client_classes.Message import Message - - -class TelegramClient: - def __init__(self, compute_message_func): - self.client = None - self.handler_thread = None - self.compute_massage = compute_message_func - - def __handler(self): - @self.client.message_handler(content_types=["text"]) - def on_message(message): - author_name = message.from_user.last_name + " " + message.from_user.first_name - chat_name = None - if message.from_user.id != message.chat.id: - chat_name = message.chat.title - self.compute_massage(Message((message.chat.id, "TG"), message.text, message.from_user.id, author_name, chat_name)) - - self.client.infinity_polling() - - def send_msg(self, id, text): - self.client.send_message(id, text) - - def run(self, token): - self.client = telebot.TeleBot(token) - self.handler_thread = threading.Thread(target=self.__handler) - self.handler_thread.start() diff --git a/client_classes/VkClient.py b/client_classes/VkClient.py deleted file mode 100644 index 8b40e5b..0000000 --- a/client_classes/VkClient.py +++ /dev/null @@ -1,51 +0,0 @@ -import threading -import vk_api -from vk_api.bot_longpoll import VkBotLongPoll, VkBotEventType -from client_classes.Message import Message - - -class VkClient: - def __init__(self, compute_message_func): - self.client = None - self.group_id = None - self.handler_thread = None - self.compute_massage = compute_message_func - - def __get_peer_id_by_id(self, id): - return id + 2000000000 - - def __get_user(self, id): - return self.client.method("users.get", {"user_ids": id})[0] - - def __get_chat(self, id): - chat = self.client.method("messages.getConversationsById", {"peer_ids": self.__get_peer_id_by_id(id)}) - if chat["count"] == 0: - return {"chat_settings": {"title": "NULL"}} - return chat["items"][0] - - def __handler(self): - longpoll = VkBotLongPoll(self.client, self.group_id) - - for event in longpoll.listen(): - if event.type == VkBotEventType.MESSAGE_NEW: - author = self.__get_user(event.object["message"]["from_id"]) - author_name = author["last_name"] + " " + author["first_name"] - chat_id = event.object["message"]["from_id"] - chat_name = None - if event.from_chat: - chat_id = event.chat_id - chat = self.__get_chat(event.chat_id) - chat_name = chat["chat_settings"]["title"] - self.compute_massage(Message((chat_id, "VK"), event.object["message"]["text"], event.object["message"]["from_id"], author_name, chat_name)) - - def send_msg(self, id, text, to_chat): - if to_chat: - self.client.method("messages.send", {"chat_id": id, "message": text, "random_id": 0}) - else: - self.client.method("messages.send", {"user_id": id, "message": text, "random_id": 0}) - - def run(self, token, group_id): - self.client = vk_api.VkApi(token=token) - self.group_id = group_id - self.handler_thread = threading.Thread(target=self.__handler) - self.handler_thread.start() From 0ecc6e65a28be70344b7758acb74da478cfdddfe Mon Sep 17 00:00:00 2001 From: GrigoriyPA <79596613+GrigoriyPA@users.noreply.github.com> Date: Tue, 5 Jul 2022 21:21:39 +0500 Subject: [PATCH 2/6] Delete data directory --- data/error_log.txt | 0 data/graph.txt | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 data/error_log.txt delete mode 100644 data/graph.txt diff --git a/data/error_log.txt b/data/error_log.txt deleted file mode 100644 index e69de29..0000000 diff --git a/data/graph.txt b/data/graph.txt deleted file mode 100644 index e69de29..0000000 From e0f7a4862aa609baa5b3897afbb6ae92caade16e Mon Sep 17 00:00:00 2001 From: GrigoriyPA <79596613+GrigoriyPA@users.noreply.github.com> Date: Tue, 5 Jul 2022 21:21:47 +0500 Subject: [PATCH 3/6] Delete main_classes directory --- main_classes/Graph.py | 84 ---------- main_classes/UsersHandler.py | 302 ----------------------------------- 2 files changed, 386 deletions(-) delete mode 100644 main_classes/Graph.py delete mode 100644 main_classes/UsersHandler.py diff --git a/main_classes/Graph.py b/main_classes/Graph.py deleted file mode 100644 index 11e7a13..0000000 --- a/main_classes/Graph.py +++ /dev/null @@ -1,84 +0,0 @@ -import queue - - -class Graph: - def __init__(self, graph_storage_name): - graph_storage = open(graph_storage_name, "r") - self.graph_storage_name = graph_storage_name - self.adjacency_list = dict() - self.graph_storage_size = 0 - for line in graph_storage.readlines(): - type_operation, vertex1, vertex2 = self.__convert_text_to_operation(line) - - if type_operation == "+": - self.add_edge(vertex1, vertex2, save_operation=False) - else: - self.erase_edge(vertex1, vertex2, save_operation=False) - self.graph_storage_size += 1 - - def __convert_text_to_operation(self, text): - text = text.split() - return text[0], (int(text[1]), text[2]), (int(text[3]), text[4]) - - def __convert_operation_to_text(self, type_operation, vertex1, vertex2): - return type_operation + " " + str(vertex1[0]) + " " + vertex1[1] + " " + str(vertex2[0]) + " " + vertex2[1] + "\n" - - def __reset_graph_storage(self): - graph_storage = open(self.graph_storage_name, "w") - used = set() - self.graph_storage_size = 0 - for vertex1 in self.adjacency_list: - for vertex2 in self.adjacency_list[vertex1]: - if (vertex1, vertex2) in used or (vertex2, vertex1) in used: - continue - - used.add((vertex1, vertex2)) - graph_storage.write(self.__convert_operation_to_text("+", vertex1, vertex2)) - self.graph_storage_size += 1 - graph_storage.close() - - def __add_operation_to_storage(self, type_operation, vertex1, vertex2): - graph_storage = open(self.graph_storage_name, "a") - graph_storage.write(self.__convert_operation_to_text(type_operation, vertex1, vertex2)) - graph_storage.close() - - self.graph_storage_size += 1 - if self.graph_storage_size >= len(self.adjacency_list) ** 2: - self.__reset_graph_storage() - - def get_reachable_vertices(self, vertex_start): - used = set() - used.add(vertex_start) - q = queue.Queue() - q.put(vertex_start) - while not q.empty(): - v = q.get() - for to in self.adjacency_list[v]: - if to in used: - continue - - used.add(to) - q.put(to) - - used.discard(vertex_start) - return list(used) - - def add_vertex(self, vertex): - if not (vertex in self.adjacency_list): - self.adjacency_list[vertex] = set() - - def add_edge(self, vertex1, vertex2, save_operation=True): - self.add_vertex(vertex1) - self.add_vertex(vertex2) - self.adjacency_list[vertex1].add(vertex2) - self.adjacency_list[vertex2].add(vertex1) - if save_operation: - self.__add_operation_to_storage("+", vertex1, vertex2) - - def erase_edge(self, vertex1, vertex2, save_operation=True): - if vertex1 in self.adjacency_list: - self.adjacency_list[vertex1].discard(vertex2) - if vertex2 in self.adjacency_list: - self.adjacency_list[vertex2].discard(vertex1) - if save_operation: - self.__add_operation_to_storage("-", vertex1, vertex2) diff --git a/main_classes/UsersHandler.py b/main_classes/UsersHandler.py deleted file mode 100644 index 4322c79..0000000 --- a/main_classes/UsersHandler.py +++ /dev/null @@ -1,302 +0,0 @@ -import threading -import sqlite3 -import hashlib -import random -from main_classes.Graph import Graph -from client_classes.VkClient import VkClient -from client_classes.TelegramClient import TelegramClient -from client_classes.DiscordClient import DiscordClient - - -class UsersHandler: - def __init__(self, graph_storage_name, users_information_db_name, token_length=1, error_log_name=None): - self.error_log_name = error_log_name - self.graph = Graph(graph_storage_name) - self.select_chat = {"chat_name": None, "chat_id": (None, None)} - self.token_length = token_length - - self.vk_client = VkClient(self.compute_message) - self.discord_client = DiscordClient(self.compute_message) - self.telegram_client = TelegramClient(self.compute_message) - - self.users_information_db_name = users_information_db_name - conn = sqlite3.connect(users_information_db_name) - cursor = conn.cursor() - cursor.execute("CREATE TABLE IF NOT EXISTS users(user_id TEXT PRIMARY KEY, account_id INT);") - cursor.execute("CREATE TABLE IF NOT EXISTS names(name TEXT PRIMARY KEY, account_id INT);") - cursor.execute("CREATE TABLE IF NOT EXISTS accounts(account_id INT PRIMARY KEY, name TEXT, token TEXT, count INT);") - conn.commit() - - self.free_id = 0 - cursor.execute("SELECT * FROM accounts;") - for account in cursor.fetchall(): - self.free_id = max(self.free_id, account[0] + 1) - - def __create_token(self): - token = "" - for i in range(self.token_length): - cur = random.randint(0, 63) - if cur <= 9: - token += str(cur) - elif cur <= 35: - token += chr(ord("a") + cur - 10) - elif cur <= 61: - token += chr(ord("A") + cur - 36) - elif cur == 62: - token += "_" - else: - token += "-" - return token - - def __add_user(self, msg): - conn = sqlite3.connect(self.users_information_db_name) - cursor = conn.cursor() - cursor.execute("SELECT * FROM users WHERE user_id='" + msg.get_author_id() + "';") - if cursor.fetchone() is None: - entry = (msg.get_author_id(), -1) - cursor.execute("INSERT INTO users VALUES(?, ?);", entry) - conn.commit() - - def __get_user_name(self, msg): - conn = sqlite3.connect(self.users_information_db_name) - cursor = conn.cursor() - cursor.execute("SELECT * FROM users WHERE user_id='" + msg.get_author_id() + "';") - info = cursor.fetchone() - if info[1] == -1: - return None - cursor.execute("SELECT * FROM accounts WHERE account_id=" + str(info[1]) + ";") - return cursor.fetchone()[1] - - def __is_login(self, msg): - conn = sqlite3.connect(self.users_information_db_name) - cursor = conn.cursor() - cursor.execute("SELECT * FROM users WHERE user_id='" + msg.get_author_id() + "';") - return cursor.fetchone()[1] != -1 - - def __add_error_to_log(self, text): - if self.error_log_name is not None: - error_log = open(self.error_log_name, "a") - error_log.write(text + "\n\n") - error_log.close() - - def __send(self, id, text, to_chat=True): - try: - if id[1] == "VK": - self.vk_client.send_msg(id[0], text, to_chat) - elif id[1] == "DS": - self.discord_client.send_msg(id[0], text) - elif id[1] == "TG": - self.telegram_client.send_msg(id[0], text) - else: - self.__add_error_to_log("Error: Unknown system to send message.") - except Exception as error: - self.__add_error_to_log("Error: Unknown error while sending the message.\nDescription:\n" + str(error)) - - def __compute_command_select(self, msg): - self.select_chat["chat_id"] = msg.from_id - self.select_chat["chat_name"] = msg.chat_name - self.__send(msg.from_id, "Chat is selected.") - - def __compute_command_connect(self, msg): - select_id = self.select_chat["chat_id"] - if select_id == (None, None): - self.__send(msg.from_id, "Error: No selected chat.") - elif select_id == msg.from_id: - self.__send(msg.from_id, "Error: Attempting to connect a chat with itself.") - elif select_id in self.graph.adjacency_list[msg.from_id]: - self.__send(msg.from_id, "Error: Chats already connected.") - else: - self.graph.add_edge(msg.from_id, select_id) - self.__send(msg.from_id, select_id[1] + " chat with name " + self.select_chat["chat_name"] + " is connected.") - self.__send(select_id, msg.from_id[1] + " chat with name " + msg.chat_name + " is connected.") - - def __compute_command_disconnect(self, msg): - select_id = self.select_chat["chat_id"] - if select_id == (None, None): - self.__send(msg.from_id, "Error: No selected chat.") - elif not (select_id in self.graph.adjacency_list[msg.from_id]): - self.__send(msg.from_id, "Error: Chats are not connected.") - else: - self.graph.erase_edge(msg.from_id, select_id) - self.__send(msg.from_id, select_id[1] + " chat with name " + self.select_chat["chat_name"] + " is disconnected.") - self.__send(select_id, msg.from_id[1] + " chat with name " + msg.chat_name + " is disconnected.") - - def __compute_command_create(self, msg): - if self.__is_login(msg): - return self.__send(msg.from_id, "To create a new account, you must log out of your current account.", to_chat=False) - - command = msg.text.split() - if len(command) == 1: - return self.__send(msg.from_id, "Error: To create an account, you need to provide an account name.", to_chat=False) - name = " ".join(command[1:]) - - conn = sqlite3.connect(self.users_information_db_name) - cursor = conn.cursor() - cursor.execute("SELECT * FROM names WHERE name='" + name + "';") - if cursor.fetchone() is not None: - return self.__send(msg.from_id, "Error: An account with the name '" + name + "' already exists.", to_chat=False) - - cursor.execute("UPDATE users SET account_id=" + str(self.free_id) + " WHERE user_id='" + msg.get_author_id() + "';") - entry = (name, self.free_id) - cursor.execute("INSERT INTO names VALUES(?, ?);", entry) - entry = (self.free_id, name, "?", 1) - cursor.execute("INSERT INTO accounts VALUES(?, ?, ?, ?);", entry) - conn.commit() - self.free_id += 1 - self.__send(msg.from_id, "An account with the name '" + name + "' has been created.", to_chat=False) - - def __compute_command_login(self, msg): - if self.__is_login(msg): - return self.__send(msg.from_id, "To login, you must log out of your current account.", to_chat=False) - - command = msg.text.split() - if len(command) == 1: - return self.__send(msg.from_id, "Error: To enter an account, you need to provide a token.", to_chat=False) - if len(command) == 2: - return self.__send(msg.from_id, "Error: To enter an account, you need to provide an account name.", to_chat=False) - token = command[1] - name = " ".join(command[2:]) - - conn = sqlite3.connect(self.users_information_db_name) - cursor = conn.cursor() - cursor.execute("SELECT * FROM names WHERE name='" + name + "';") - names_info = cursor.fetchone() - if names_info is None: - return self.__send(msg.from_id, "Error: There is no account with the name '" + name + "'.", to_chat=False) - cursor.execute("SELECT * FROM accounts WHERE account_id=" + str(names_info[1]) + ";") - account_info = cursor.fetchone() - if account_info[2] == "?" or account_info[2] != hashlib.sha512(token.encode()).hexdigest(): - return self.__send(msg.from_id, "Error: Incorrect token.", to_chat=False) - - cursor.execute("UPDATE users SET account_id=" + str(account_info[0]) + " WHERE user_id='" + msg.get_author_id() + "';") - cursor.execute("UPDATE accounts SET count=" + str(account_info[3] + 1) + " WHERE account_id=" + str(account_info[0]) + ";") - conn.commit() - self.__send(msg.from_id, "You are connected to the '" + name + "' account.", to_chat=False) - - def __compute_command_logout(self, msg): - if not self.__is_login(msg): - return self.__send(msg.from_id, "Error: Your account has not been logged in.", to_chat=False) - - conn = sqlite3.connect(self.users_information_db_name) - cursor = conn.cursor() - cursor.execute("SELECT * FROM users WHERE user_id='" + msg.get_author_id() + "';") - user_info = cursor.fetchone() - cursor.execute("SELECT * FROM accounts WHERE account_id=" + str(user_info[1]) + ";") - account_info = cursor.fetchone() - - cursor.execute("UPDATE users SET account_id=-1 WHERE user_id='" + msg.get_author_id() + "';") - cursor.execute("UPDATE accounts SET count=" + str(account_info[3] - 1) + " WHERE account_id=" + str(account_info[0]) + ";") - conn.commit() - self.__send(msg.from_id, "You are disconnected from the account '" + account_info[1] + "'.", to_chat=False) - if account_info[3] == 1: - cursor.execute("DELETE FROM accounts WHERE account_id=" + str(account_info[0]) + ";") - cursor.execute("DELETE FROM names WHERE name='" + str(account_info[1]) + "';") - conn.commit() - self.__send(msg.from_id, "Account '" + account_info[1] + "' has been deleted.", to_chat=False) - - def __compute_command_rename(self, msg): - if not self.__is_login(msg): - return self.__send(msg.from_id, "Error: Your account has not been logged in.", to_chat=False) - - command = msg.text.split() - if len(command) == 1: - return self.__send(msg.from_id, "Error: To rename an account, you need to provide an new account name.", to_chat=False) - name = " ".join(command[1:]) - - conn = sqlite3.connect(self.users_information_db_name) - cursor = conn.cursor() - cursor.execute("SELECT * FROM users WHERE user_id='" + msg.get_author_id() + "';") - user_info = cursor.fetchone() - cursor.execute("SELECT * FROM names WHERE name='" + name + "';") - if cursor.fetchone() is not None: - return self.__send(msg.from_id, "Error: An account with the name '" + name + "' already exists.", to_chat=False) - cursor.execute("SELECT * FROM accounts WHERE account_id=" + str(user_info[1]) + ";") - account_info = cursor.fetchone() - - cursor.execute("UPDATE names SET name='" + name + "' WHERE name='" + account_info[1] + "';") - cursor.execute("UPDATE accounts SET name='" + name + "' WHERE account_id=" + str(account_info[0]) + ";") - conn.commit() - self.__send(msg.from_id, "The account name has been changed from '" + account_info[1] + "' to '" + name + "'.", to_chat=False) - - def __compute_command_get_token(self, msg): - if not self.__is_login(msg): - return self.__send(msg.from_id, "Error: Your account has not been logged in.", to_chat=False) - - conn = sqlite3.connect(self.users_information_db_name) - cursor = conn.cursor() - cursor.execute("SELECT * FROM users WHERE user_id='" + msg.get_author_id() + "';") - user_info = cursor.fetchone() - - token = self.__create_token() - cursor.execute("UPDATE accounts SET token='" + hashlib.sha512(token.encode()).hexdigest() + "' WHERE account_id=" + str(user_info[1]) + ";") - conn.commit() - self.__send(msg.from_id, "Token to connect to the account: " + token, to_chat=False) - - def __compute_command_delete_token(self, msg): - if not self.__is_login(msg): - return self.__send(msg.from_id, "Error: Your account has not been logged in.", to_chat=False) - - conn = sqlite3.connect(self.users_information_db_name) - cursor = conn.cursor() - cursor.execute("SELECT * FROM users WHERE user_id='" + msg.get_author_id() + "';") - user_info = cursor.fetchone() - - cursor.execute("UPDATE accounts SET token='?' WHERE account_id=" + str(user_info[1]) + ";") - conn.commit() - self.__send(msg.from_id, "The token for connecting to the account has been deleted.", to_chat=False) - - def __compute_chat_command(self, msg): - command = msg.get_chat_command() - if command == "select": - self.__compute_command_select(msg) - elif command == "connect": - self.__compute_command_connect(msg) - elif command == "disconnect": - self.__compute_command_disconnect(msg) - else: - self.__send(msg.from_id, "Error: Unknown instruction.") - - def __compute_user_command(self, msg): - self.__add_user(msg) - command = msg.text.split() - if len(command) >= 1 and command[0].lower() == "create": - self.__compute_command_create(msg) - elif len(command) >= 1 and command[0].lower() == "login": - self.__compute_command_login(msg) - elif len(command) >= 1 and command[0].lower() == "logout": - self.__compute_command_logout(msg) - elif len(command) >= 1 and command[0].lower() == "rename": - self.__compute_command_rename(msg) - elif len(command) >= 2 and command[0].lower() == "get" and command[1].lower() == "token": - self.__compute_command_get_token(msg) - elif len(command) >= 2 and command[0].lower() == "delete" and command[1].lower() == "token": - self.__compute_command_delete_token(msg) - else: - self.__send(msg.from_id, "Error: Unknown instruction.", to_chat=False) - - def run(self, vk_token=None, vk_group_id=None, telegram_token=None, discord_token=None): - if vk_token is not None and vk_group_id is not None: - self.vk_client.run(vk_token, vk_group_id) - if telegram_token is not None: - self.telegram_client.run(telegram_token) - if discord_token is not None: - self.discord_client.run(discord_token) - - def compute_message(self, msg): - if msg.text == "": - return None - - if msg.chat_name is None: - thread = threading.Thread(target=self.__compute_user_command, args=(msg, )) - thread.start() - return None - - self.graph.add_vertex(msg.from_id) - if msg.is_chat_command(): - return self.__compute_chat_command(msg) - - name = self.__get_user_name(msg) - if name is not None: - msg.author_name = name - for send_id in self.graph.get_reachable_vertices(msg.from_id): - self.__send(send_id, msg.get_text_to_forwarding()) From 53877a5ea5429d97265105b19cbc3a2c7b68b545 Mon Sep 17 00:00:00 2001 From: GrigoriyPA <79596613+GrigoriyPA@users.noreply.github.com> Date: Tue, 5 Jul 2022 21:21:59 +0500 Subject: [PATCH 4/6] Delete config.py --- config.py | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 config.py diff --git a/config.py b/config.py deleted file mode 100644 index e8e7e2b..0000000 --- a/config.py +++ /dev/null @@ -1,12 +0,0 @@ -VK_TOKEN = "" -VK_GROUP_ID = 0 - -DISCORD_TOKEN = "" - -TELEGRAM_TOKEN = "" - -TOKEN_LENGTH = 10 - -GRAPH_STORAGE_NAME = "data/graph.txt" -ERROR_LOG_NAME = "data/error_log.txt" -USERS_INFORMATION_DB_NAME = "data/users_inf.db" From 84a940152854a6bb5aefed87dc7eff7fb0929491 Mon Sep 17 00:00:00 2001 From: GrigoriyPA <79596613+GrigoriyPA@users.noreply.github.com> Date: Tue, 5 Jul 2022 21:22:05 +0500 Subject: [PATCH 5/6] Delete main.py --- main.py | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 main.py diff --git a/main.py b/main.py deleted file mode 100644 index 0a5a709..0000000 --- a/main.py +++ /dev/null @@ -1,11 +0,0 @@ -import config -from main_classes.UsersHandler import UsersHandler - - -def main(): - bot = UsersHandler(config.GRAPH_STORAGE_NAME, config.USERS_INFORMATION_DB_NAME, token_length=config.TOKEN_LENGTH, error_log_name=config.ERROR_LOG_NAME) - bot.run(vk_token=config.VK_TOKEN, vk_group_id=config.VK_GROUP_ID, telegram_token=config.TELEGRAM_TOKEN, discord_token=config.DISCORD_TOKEN) - - -if __name__ == "__main__": - main() From dbf891e5507fea4595098e8236aac6daf54f295f Mon Sep 17 00:00:00 2001 From: GrigoriyPA <79596613+GrigoriyPA@users.noreply.github.com> Date: Tue, 5 Jul 2022 21:23:06 +0500 Subject: [PATCH 6/6] Add files via upload --- client_classes/DiscordClient.py | 46 ++++++ client_classes/Message.py | 29 ++++ client_classes/TelegramClient.py | 63 ++++++++ client_classes/VkClient.py | 88 +++++++++++ config.py | 13 ++ data/error_log.txt | 0 data/graph.txt | 0 main.py | 11 ++ main_classes/Graph.py | 92 +++++++++++ main_classes/UsersHandler.py | 258 +++++++++++++++++++++++++++++++ 10 files changed, 600 insertions(+) create mode 100644 client_classes/DiscordClient.py create mode 100644 client_classes/Message.py create mode 100644 client_classes/TelegramClient.py create mode 100644 client_classes/VkClient.py create mode 100644 config.py create mode 100644 data/error_log.txt create mode 100644 data/graph.txt create mode 100644 main.py create mode 100644 main_classes/Graph.py create mode 100644 main_classes/UsersHandler.py diff --git a/client_classes/DiscordClient.py b/client_classes/DiscordClient.py new file mode 100644 index 0000000..5a21307 --- /dev/null +++ b/client_classes/DiscordClient.py @@ -0,0 +1,46 @@ +import discord +import requests +import config +from client_classes.Message import Message + + +class DiscordClient(discord.Client): + def __init__(self, compute_message_func): + super(DiscordClient, self).__init__() + self.compute_massage = compute_message_func + + def __get_photo(self, attachments): + url = [] + for el in attachments: + link = str(el) + ext = link[link.rfind(".") + 1:] + if ext in config.PHOTO_EXT: + url.append(link) + return url + + async def on_ready(self): + print("DS client started.") + + async def on_message(self, message): + if message.author != self.user: + photo = self.__get_photo(message.attachments) + from_id = message.channel.id + text = message.content + author_id = message.author.id + author_name = message.author.name + if type(message.channel) != discord.channel.DMChannel: + chat_name = message.author.guild.name + "/" + message.channel.name + is_owner = message.author.guild_permissions.administrator + self.compute_massage(Message((from_id, "DS"), text, author_id, author_name, chat_name=chat_name, is_owner=is_owner, photos=photo)) + else: + self.compute_massage(Message((from_id, "DS"), text, author_id, author_name, photos=photo)) + + def send_msg(self, id, text, photo): + files = [] + for i in range(len(photo)): + out = open(config.TEMP_IMAGE_FOLDER + str(i) + ".jpg", "wb") + out.write(requests.get(photo[i]).content) + out.close() + files.append(discord.File(config.TEMP_IMAGE_FOLDER + str(i) + ".jpg")) + + self.loop.create_task(self.get_channel(id).send(content=text, files=files)) diff --git a/client_classes/Message.py b/client_classes/Message.py new file mode 100644 index 0000000..d1a3b41 --- /dev/null +++ b/client_classes/Message.py @@ -0,0 +1,29 @@ +class Message: + def __init__(self, from_id, text, author_id, author_name, chat_name=None, is_owner=None, photos=None): + self.from_id = from_id + self.text = text + self.author_id = author_id + self.author_name = author_name + self.chat_name = chat_name + self.is_owner = is_owner + self.photos = photos + + def is_chat_command(self): + return len(self.text) > 0 and self.text[0] == "!" + + def get_chat_id(self): + return str(self.from_id[0]) + self.from_id[1] + + def get_author_id(self): + return str(self.author_id) + self.from_id[1] + + def get_chat_command(self): + if not self.is_chat_command(): + return None + return self.text[1:].strip() + + def get_content_to_forwarding(self): + description = "" + if self.author_name is not None: + description += self.author_name + ":\n" + return description + self.text, self.photos diff --git a/client_classes/TelegramClient.py b/client_classes/TelegramClient.py new file mode 100644 index 0000000..4fc4d13 --- /dev/null +++ b/client_classes/TelegramClient.py @@ -0,0 +1,63 @@ +import threading +import telebot +import requests +import config +from client_classes.Message import Message + + +class TelegramClient: + def __init__(self, compute_message_func): + self.token = None + self.client = None + self.handler_thread = None + self.compute_massage = compute_message_func + + def __get_photo(self, message): + if message.content_type == "photo": + return ["https://api.telegram.org/file/bot" + self.token + "/" + self.client.get_file(message.photo[-1].file_id).file_path] + elif message.content_type == "document": + link = "https://api.telegram.org/file/bot" + self.token + "/" + self.client.get_file(message.document.file_id).file_path + ext = link[link.rfind(".") + 1:] + if ext in config.PHOTO_EXT: + return [link] + return [] + + def __handler(self): + print("TG client started.") + + @self.client.message_handler(content_types=["text", "photo", "document"]) + def on_message(message): + photo = self.__get_photo(message) + from_id = message.chat.id + text = "" + if message.content_type == "text": + text = message.text + elif message.caption is not None: + text = message.caption + author_id = message.from_user.id + author = self.client.get_chat_member(from_id, author_id) + author_name = message.from_user.last_name + " " + message.from_user.first_name + if from_id != author_id: + chat_name = message.chat.title + is_owner = author.status == "creator" + self.compute_massage(Message((from_id, "TG"), text, author_id, author_name, chat_name=chat_name, is_owner=is_owner, photos=photo)) + else: + self.compute_massage(Message((from_id, "TG"), text, author_id, author_name, photos=photo)) + + self.client.infinity_polling() + + def send_msg(self, id, text, photo): + if photo == []: + return self.client.send_message(id, text) + + self.client.send_photo(id, requests.get(photo[0]).content, caption=text) + if len(photo) > 1: + self.client.send_message(id, "Other photos:") + for i in range(1, len(photo)): + self.client.send_photo(id, requests.get(photo[i]).content) + + def run(self, token): + self.token = token + self.client = telebot.TeleBot(token) + self.handler_thread = threading.Thread(target=self.__handler) + self.handler_thread.start() diff --git a/client_classes/VkClient.py b/client_classes/VkClient.py new file mode 100644 index 0000000..07a2213 --- /dev/null +++ b/client_classes/VkClient.py @@ -0,0 +1,88 @@ +import threading +import requests +import vk_api +from vk_api.bot_longpoll import VkBotLongPoll, VkBotEventType +import config +from client_classes.Message import Message + + +class VkClient: + def __init__(self, compute_message_func): + self.client = None + self.upload = None + self.group_id = None + self.handler_thread = None + self.compute_massage = compute_message_func + + def __get_peer_id_by_id(self, id): + return id + 2000000000 + + def __get_user(self, id): + return self.client.method("users.get", {"user_ids": id})[0] + + def __get_chat(self, id): + chat = self.client.method("messages.getConversationsById", {"peer_ids": self.__get_peer_id_by_id(id)}) + if chat["count"] == 0: + return {"chat_settings": {"title": "NULL", "owner_id": "NULL"}} + return chat["items"][0] + + def __get_photo(self, attachments): + url = [] + for el in attachments: + if el["type"] == "photo": + for photo in el["photo"]["sizes"]: + if photo["type"] != "z": + continue + + url.append(photo["url"]) + break + elif el["type"] == "doc" and el["doc"]["ext"] in config.PHOTO_EXT: + url.append(el["doc"]["url"]) + return url + + def __handler(self): + print("VK client started.") + longpoll = VkBotLongPoll(self.client, self.group_id) + + for event in longpoll.listen(): + if event.type == VkBotEventType.MESSAGE_NEW: + photo = self.__get_photo(event.object.message["attachments"]) + text = event.object.message["text"] + author = self.__get_user(event.object.message["from_id"]) + author_id = event.object.message["from_id"] + author_name = author["last_name"] + " " + author["first_name"] + if event.from_chat: + from_id = event.chat_id + chat = self.__get_chat(event.chat_id) + chat_name = chat["chat_settings"]["title"] + is_owner = author_id == chat["chat_settings"]["owner_id"] + self.compute_massage(Message((from_id, "VK"), text, author_id, author_name, chat_name=chat_name, is_owner=is_owner, photos=photo)) + else: + from_id = event.object.message["from_id"] + self.compute_massage(Message((from_id, "VK"), text, author_id, author_name, photos=photo)) + + def send_msg(self, id, text, photo, to_chat): + files = [] + for i in range(len(photo)): + out = open(config.TEMP_IMAGE_FOLDER + str(i) + ".jpg", "wb") + out.write(requests.get(photo[i]).content) + out.close() + files.append(config.TEMP_IMAGE_FOLDER + str(i) + ".jpg") + response = self.upload.photo_messages(photos=files, peer_id=self.__get_peer_id_by_id(id)) + + attachment = "" + for el in response: + attachment += "photo" + str(el["owner_id"]) + "_" + str(el["id"]) + "_" + str(el["access_key"]) + "," + attachment = attachment[:-1] + + if to_chat: + self.client.method("messages.send", {"chat_id": id, "message": text, "attachment": attachment, "random_id": 0}) + else: + self.client.method("messages.send", {"user_id": id, "message": text, "attachment": attachment, "random_id": 0}) + + def run(self, token, group_id): + self.client = vk_api.VkApi(token=token) + self.upload = vk_api.VkUpload(self.client) + self.group_id = group_id + self.handler_thread = threading.Thread(target=self.__handler) + self.handler_thread.start() diff --git a/config.py b/config.py new file mode 100644 index 0000000..eb9303e --- /dev/null +++ b/config.py @@ -0,0 +1,13 @@ +VK_TOKEN = "" +VK_GROUP_ID = 0 + +DISCORD_TOKEN = "" + +TELEGRAM_TOKEN = "" + +GRAPH_STORAGE_NAME = "data/graph.txt" +ERROR_LOG_NAME = "data/error_log.txt" +USERS_INFORMATION_DB_NAME = "data/users_inf.db" +TEMP_IMAGE_FOLDER = "data/temp_img/" + +PHOTO_EXT = {"jpeg", "jpg", "png"} diff --git a/data/error_log.txt b/data/error_log.txt new file mode 100644 index 0000000..e69de29 diff --git a/data/graph.txt b/data/graph.txt new file mode 100644 index 0000000..e69de29 diff --git a/main.py b/main.py new file mode 100644 index 0000000..3359941 --- /dev/null +++ b/main.py @@ -0,0 +1,11 @@ +import config +from main_classes.UsersHandler import UsersHandler + + +def main(): + bot = UsersHandler(config.GRAPH_STORAGE_NAME, config.USERS_INFORMATION_DB_NAME, error_log_name=config.ERROR_LOG_NAME) + bot.run(vk_token=config.VK_TOKEN, vk_group_id=config.VK_GROUP_ID, telegram_token=config.TELEGRAM_TOKEN, discord_token=config.DISCORD_TOKEN) + + +if __name__ == "__main__": + main() diff --git a/main_classes/Graph.py b/main_classes/Graph.py new file mode 100644 index 0000000..0ba0a20 --- /dev/null +++ b/main_classes/Graph.py @@ -0,0 +1,92 @@ +import queue + + +class Graph: + def __init__(self, graph_storage_name): + graph_storage = open(graph_storage_name, "r") + self.graph_storage_name = graph_storage_name + self.adjacency_list = dict() + self.rules = dict() + self.graph_storage_size = 0 + for line in graph_storage.readlines(): + type_operation, vertex1, vertex2 = self.__convert_text_to_operation(line) + + if type_operation == "+": + self.add_edge(vertex1, vertex2, save_operation=False) + else: + self.erase_edge(vertex1, vertex2, save_operation=False) + self.graph_storage_size += 1 + + def __check_rule(self, vertex, text): + rule = self.rules[vertex] + return len(text) >= len(rule) and text[:len(rule)] == rule + + def __convert_text_to_operation(self, text): + text = text.split() + return text[0], (int(text[1]), text[2]), (int(text[3]), text[4]) + + def __convert_operation_to_text(self, type_operation, vertex1, vertex2): + return type_operation + " " + str(vertex1[0]) + " " + vertex1[1] + " " + str(vertex2[0]) + " " + vertex2[1] + "\n" + + def __reset_graph_storage(self): + graph_storage = open(self.graph_storage_name, "w") + self.graph_storage_size = 0 + for vertex1 in self.adjacency_list: + for vertex2 in self.adjacency_list[vertex1]: + graph_storage.write(self.__convert_operation_to_text("+", vertex1, vertex2)) + self.graph_storage_size += 1 + graph_storage.close() + + def __add_operation_to_storage(self, type_operation, vertex1, vertex2): + graph_storage = open(self.graph_storage_name, "a") + graph_storage.write(self.__convert_operation_to_text(type_operation, vertex1, vertex2)) + graph_storage.close() + + self.graph_storage_size += 1 + if self.graph_storage_size >= 2 * len(self.adjacency_list) ** 2: + self.__reset_graph_storage() + + def get_reachable_vertices(self, vertex_start, text): + used = set() + used.add(vertex_start) + q = queue.Queue() + q.put(vertex_start) + while not q.empty(): + v = q.get() + if not self.__check_rule(v, text): + continue + + for to in self.adjacency_list[v]: + if to in used: + continue + + used.add(to) + q.put(to) + + used.discard(vertex_start) + return list(used) + + def add_vertex(self, vertex): + if not (vertex in self.adjacency_list): + self.rules[vertex] = "" + self.adjacency_list[vertex] = set() + + def set_rule(self, id, rule): + vertex = (int(id[:-2]), id[-2:]) + self.add_vertex(vertex) + self.rules[vertex] = rule + + def add_edge(self, vertex1, vertex2, save_operation=True): + self.add_vertex(vertex1) + self.add_vertex(vertex2) + self.adjacency_list[vertex1].add(vertex2) + if save_operation: + self.__add_operation_to_storage("+", vertex1, vertex2) + + def erase_edge(self, vertex1, vertex2, save_operation=True): + if vertex1 in self.adjacency_list: + self.adjacency_list[vertex1].discard(vertex2) + if vertex2 in self.adjacency_list: + self.adjacency_list[vertex2].discard(vertex1) + if save_operation: + self.__add_operation_to_storage("-", vertex1, vertex2) diff --git a/main_classes/UsersHandler.py b/main_classes/UsersHandler.py new file mode 100644 index 0000000..5b16dbc --- /dev/null +++ b/main_classes/UsersHandler.py @@ -0,0 +1,258 @@ +import sqlite3 +from main_classes.Graph import Graph +from client_classes.VkClient import VkClient +from client_classes.TelegramClient import TelegramClient +from client_classes.DiscordClient import DiscordClient + + +class UsersHandler: + def __init__(self, graph_storage_name, users_information_db_name, error_log_name=None): + self.error_log_name = error_log_name + self.graph = Graph(graph_storage_name) + self.select_chat = {"chat_name": None, "chat_id": (None, None)} + self.orient = False + + self.vk_client = VkClient(self.compute_message) + self.discord_client = DiscordClient(self.compute_message) + self.telegram_client = TelegramClient(self.compute_message) + + self.users_information_db_name = users_information_db_name + conn = sqlite3.connect(users_information_db_name) + cursor = conn.cursor() + cursor.execute("CREATE TABLE IF NOT EXISTS users(id TEXT PRIMARY KEY, name TEXT, is_admin INT);") + cursor.execute("CREATE TABLE IF NOT EXISTS chat_rules(id TEXT PRIMARY KEY, rule TEXT);") + conn.commit() + + cursor.execute("SELECT * FROM chat_rules;") + for rule in cursor.fetchall(): + self.graph.set_rule(rule[0], rule[1]) + + def __add_user(self, id): + conn = sqlite3.connect(self.users_information_db_name) + cursor = conn.cursor() + cursor.execute("SELECT * FROM users WHERE id='" + id + "';") + if cursor.fetchone() is None: + entry = (id, "None", 0) + cursor.execute("INSERT INTO users VALUES(?, ?, ?);", entry) + conn.commit() + + def __get_user_name(self, msg): + conn = sqlite3.connect(self.users_information_db_name) + cursor = conn.cursor() + cursor.execute("SELECT * FROM users WHERE id='" + msg.get_author_id() + str(msg.from_id[0]) + "';") + return cursor.fetchone()[1] + + def __is_admin(self, msg): + if msg.is_owner: + return True + + conn = sqlite3.connect(self.users_information_db_name) + cursor = conn.cursor() + cursor.execute("SELECT * FROM users WHERE id='" + msg.get_author_id() + str(msg.from_id[0]) + "';") + return cursor.fetchone()[2] + + def __add_error_to_log(self, text): + if self.error_log_name is not None: + error_log = open(self.error_log_name, "a") + error_log.write(text + "\n\n") + error_log.close() + + def __send(self, id, text, to_chat=True, photo=[]): + try: + if id[1] == "VK": + self.vk_client.send_msg(id[0], text, photo, to_chat) + elif id[1] == "DS": + self.discord_client.send_msg(id[0], text, photo) + elif id[1] == "TG": + self.telegram_client.send_msg(id[0], text, photo) + else: + self.__add_error_to_log("Error: Unknown system to send message.") + except Exception as error: + self.__add_error_to_log("Error: Unknown error while sending the message.\nDescription:\n" + str(error)) + + def __compute_command_orient(self, msg): + if not self.__is_admin(msg): + return self.__send(msg.from_id, "Error: You must be an administrator to use this command.") + + self.orient = True + self.__send(msg.from_id, "All new connections from this chat will be oriented.") + + def __compute_command_select(self, msg): + if not self.__is_admin(msg): + return self.__send(msg.from_id, "Error: You must be an administrator to use this command.") + + self.orient = False + self.select_chat["chat_id"] = msg.from_id + self.select_chat["chat_name"] = msg.chat_name + self.__send(msg.from_id, "Chat is selected.") + + def __compute_command_connect(self, msg): + if not self.__is_admin(msg): + return self.__send(msg.from_id, "Error: You must be an administrator to use this command.") + + select_id = self.select_chat["chat_id"] + if select_id == (None, None): + self.__send(msg.from_id, "Error: No selected chat.") + elif select_id == msg.from_id: + self.__send(msg.from_id, "Error: Attempting to connect a chat with itself.") + elif select_id in self.graph.adjacency_list[msg.from_id]: + self.__send(msg.from_id, "Error: Chats already connected.") + else: + self.graph.add_edge(select_id, msg.from_id) + if not self.orient: + self.graph.add_edge(msg.from_id, select_id) + self.__send(msg.from_id, select_id[1] + " chat with name " + self.select_chat["chat_name"] + " is connected.") + self.__send(select_id, msg.from_id[1] + " chat with name " + msg.chat_name + " is connected.") + + def __compute_command_disconnect(self, msg): + if not self.__is_admin(msg): + return self.__send(msg.from_id, "Error: You must be an administrator to use this command.") + + select_id = self.select_chat["chat_id"] + if select_id == (None, None): + self.__send(msg.from_id, "Error: No selected chat.") + elif not (select_id in self.graph.adjacency_list[msg.from_id]): + self.__send(msg.from_id, "Error: Chats are not connected.") + else: + self.graph.erase_edge(msg.from_id, select_id) + self.__send(msg.from_id, select_id[1] + " chat with name " + self.select_chat["chat_name"] + " is disconnected.") + self.__send(select_id, msg.from_id[1] + " chat with name " + msg.chat_name + " is disconnected.") + + def __compute_command_get_id(self, msg): + self.__send(msg.from_id, "User id: " + msg.get_author_id(), to_chat=msg.chat_name is not None) + + def __compute_command_set_admin(self, msg): + if not msg.is_owner: + return self.__send(msg.from_id, "Error: You must be an owner to use this command.") + + command = msg.get_chat_command().split() + if len(command) == 2: + return self.__send(msg.from_id, "Error: An user id is required.") + user_id = " ".join(command[2:]) + self.__add_user(user_id + str(msg.from_id[0])) + + conn = sqlite3.connect(self.users_information_db_name) + cursor = conn.cursor() + cursor.execute("SELECT * FROM users WHERE id='" + user_id + str(msg.from_id[0]) + "';") + if cursor.fetchone()[2]: + return self.__send(msg.from_id, "Error: The account with id '" + user_id + "' already has administrator rights.") + + cursor.execute("UPDATE users SET is_admin=1 WHERE id='" + user_id + str(msg.from_id[0]) + "';") + conn.commit() + self.__send(msg.from_id, "The account with id '" + user_id + "' has been granted administrative rights.") + + def __compute_command_delete_admin(self, msg): + if not msg.is_owner: + return self.__send(msg.from_id, "Error: You must be an owner to use this command.") + + command = msg.get_chat_command().split() + if len(command) == 2: + return self.__send(msg.from_id, "Error: An user id is required.") + user_id = " ".join(command[2:]) + self.__add_user(user_id + str(msg.from_id[0])) + + conn = sqlite3.connect(self.users_information_db_name) + cursor = conn.cursor() + cursor.execute("SELECT * FROM users WHERE id='" + user_id + str(msg.from_id[0]) + "';") + if not cursor.fetchone()[2]: + return self.__send(msg.from_id, "Error: The account with id '" + user_id + "' does not have administrative rights.") + + cursor.execute("UPDATE users SET is_admin=0 WHERE id='" + user_id + str(msg.from_id[0]) + "';") + conn.commit() + self.__send(msg.from_id, "The account with id '" + user_id + "' no longer has administrative rights.") + + def __compute_command_rename(self, msg): + if not self.__is_admin(msg): + return self.__send(msg.from_id, "Error: You must be an administrator to use this command.") + + command = msg.get_chat_command().split() + if len(command) == 1: + return self.__send(msg.from_id, "Error: An user id is required.") + if len(command) == 2: + return self.__send(msg.from_id, "Error: A new name is required.") + user_id = command[1] + if user_id == "self": + user_id = msg.get_author_id() + name = " ".join(command[2:]) + self.__add_user(user_id + str(msg.from_id[0])) + + conn = sqlite3.connect(self.users_information_db_name) + cursor = conn.cursor() + cursor.execute("SELECT * FROM users WHERE id='" + user_id + str(msg.from_id[0]) + "';") + if user_id != msg.get_author_id() and cursor.fetchone()[2]: + return self.__send(msg.from_id, "Error: Forbidden to rename administrators.") + + cursor.execute("UPDATE users SET name='" + name + "' WHERE id='" + user_id + str(msg.from_id[0]) + "';") + conn.commit() + self.__send(msg.from_id, "The account name has been changed to '" + name + "'.") + + def __compute_command_set_rule(self, msg): + if not self.__is_admin(msg): + return self.__send(msg.from_id, "Error: You must be an administrator to use this command.") + + command = msg.get_chat_command() + if len(command.split()) == 2 or command.count("\"") < 2: + return self.__send(msg.from_id, "Error: A new rule is required.") + rule = command[command.find("\"") + 1:command.rfind("\"")] + + conn = sqlite3.connect(self.users_information_db_name) + cursor = conn.cursor() + cursor.execute("UPDATE chat_rules SET rule='" + rule + "' WHERE id='" + msg.get_chat_id() + "';") + conn.commit() + self.graph.set_rule(msg.get_chat_id(), rule) + self.__send(msg.from_id, "The chat rule has been changed to '" + rule + "'.") + + def __compute_chat_command(self, msg): + command = msg.get_chat_command().split() + if len(command) >= 1 and command[0].lower() == "select": + self.__compute_command_select(msg) + elif len(command) >= 1 and command[0].lower() == "orient": + self.__compute_command_orient(msg) + elif len(command) >= 1 and command[0].lower() == "connect": + self.__compute_command_connect(msg) + elif len(command) >= 1 and command[0].lower() == "disconnect": + self.__compute_command_disconnect(msg) + elif len(command) >= 2 and command[0].lower() == "set" and command[1].lower() == "admin": + self.__compute_command_set_admin(msg) + elif len(command) >= 2 and command[0].lower() == "delete" and command[1].lower() == "admin": + self.__compute_command_delete_admin(msg) + elif len(command) >= 2 and command[0].lower() == "get" and command[1].lower() == "id": + self.__compute_command_get_id(msg) + elif len(command) >= 1 and command[0].lower() == "rename": + self.__compute_command_rename(msg) + elif len(command) >= 2 and command[0].lower() == "set" and command[1].lower() == "rule": + self.__compute_command_set_rule(msg) + else: + self.__send(msg.from_id, "Error: Unknown instruction.") + + def __compute_user_command(self, msg): + command = msg.text.split() + if len(command) >= 2 and command[0].lower() == "get" and command[1].lower() == "id": + self.__compute_command_get_id(msg) + else: + self.__send(msg.from_id, "Error: Unknown instruction.", to_chat=False) + + def run(self, vk_token=None, vk_group_id=None, telegram_token=None, discord_token=None): + if vk_token is not None and vk_group_id is not None: + self.vk_client.run(vk_token, vk_group_id) + if telegram_token is not None: + self.telegram_client.run(telegram_token) + if discord_token is not None: + self.discord_client.run(discord_token) + + def compute_message(self, msg): + if msg.chat_name is None: + return self.__compute_user_command(msg) + + self.__add_user(msg.get_author_id() + str(msg.from_id[0])) + self.graph.add_vertex(msg.from_id) + if msg.is_chat_command(): + return self.__compute_chat_command(msg) + + name = self.__get_user_name(msg) + if name != "None": + msg.author_name = name + + text, photo = msg.get_content_to_forwarding() + for send_id in self.graph.get_reachable_vertices(msg.from_id, msg.text): + self.__send(send_id, text, photo=photo)