Erickpro720

Discordbot.py

Jan 23rd, 2022
1,421
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 24.67 KB | None | 0 0
  1. from typing import List
  2. from urllib import parse
  3. import asyncio
  4. import discord
  5. from discord.ext import commands
  6. from discord.utils import escape_markdown
  7. from discord.errors import Forbidden, HTTPException
  8.  
  9. import oyaml as yaml  # ordered yaml
  10. from collections import OrderedDict
  11.  
  12. import os
  13. from PIL import Image
  14.  
  15. import sys
  16. import io
  17. import time
  18.  
  19. #from urllib.request import requests
  20. import shutil
  21. from threading import Thread
  22.  
  23. class Bridgebot(commands.Bot):
  24.     """
  25.    The AO2 Discord bridge self.
  26.    """
  27.  
  28.     def __init__(self, server, target_chanel, hub_id, area_id):
  29.         self.prefix: str = "e!"
  30.         super().__init__(command_prefix=self.prefix)
  31.         self.server = server
  32.         self.pending_messages: List[list] = []
  33.         self.hub_id: int = hub_id
  34.         self.area_id: int = area_id
  35.         self.target_channel: discord.abc.Messageable = target_chanel
  36.  
  37.         self.was_my_message = False # If the bot was the last than sended a message in the channel
  38.         #self.last_char = ""
  39.         #self.last_emote = ""
  40.         self.last_chars: list[str] = ["", ""]
  41.         self.last_emotes: list[str] = ["", ""]
  42.         self.last_index: int = 0
  43.  
  44.         self.default_user: dict = {
  45.             "discord_id": -1,
  46.             "avatar_url": self.server.config["bridgebot"]["avatar_url"],
  47.             "char_name": self.server.config["bridgebot"]["character"],
  48.             "emote_name": self.server.config["bridgebot"]["emote"],
  49.             "position": self.server.config["bridgebot"]["pos"],
  50.             "ao_showname": "",
  51.             "footer_url": "",
  52.            
  53.         }
  54.  
  55.         self.image_URLs: dict = {}
  56.         # Formatting {"{char_name}/{emote_name}", "Discord_URL"}
  57.        
  58.         self.opened: bool = True
  59.        
  60.         #self.discord_users = {407268594360254475: {'avatar_url': 'https://cdn.discordapp.com/avatars/407268594360254475/44cdc1ad5843d00f495d5d53ca8e396e.webp?size=4096', 'char_name': 'Franny', 'emote_name': 'hmph', 'position': '', 'ao_showname': ''}}
  61.         self.discord_users: dict = {}
  62.         self.can_save_data: bool = False
  63.         self.need_to_save: bool = False
  64.         self.need_to_save_url: bool = False
  65.         self.time: float = 0
  66.         self.max_save_time: float = 5.0
  67.  
  68.         self.start_time_image: float = 0.0
  69.         self.start_time_message: float = 0.0
  70.  
  71.         self.tickspeed: float = max(0.1, self.server.config["bridgebot"]["tickspeed"])
  72.         self.can_send_message: bool = False
  73.  
  74.         self.has_pillow: bool = False
  75.         try:
  76.             import PIL
  77.             #self.has_pillow = True
  78.         except ModuleNotFoundError:
  79.             print("module 'Pillow' is not installed... Using not Pillow version of the code.")
  80.             #self.has_pillow = False
  81.  
  82.        
  83.  
  84.     async def init(self, token):
  85.         """Starts the actual bot"""
  86.         print("Trying to start the Discord Bridge bot...")
  87.         try:
  88.             await self.start(token)
  89.         except Exception as e:
  90.             print(e)
  91.             raise
  92.    
  93.     async def on_close(self):
  94.         """When the server is shutting down"""
  95.         self.save_cached_url_data()
  96.         self.save_user_data()
  97.         self.opened = False #Stop the while loop
  98.         await self.close() #Disconnects the Discord bot from Discord servers.
  99.  
  100.        
  101.  
  102.     def load_user_data(self):
  103.  
  104.         path: str = "storage/discord_bot"
  105.  
  106.         arg: str = f"{path}/users_data.yaml"
  107.  
  108.         if not os.path.isfile(arg):
  109.             #raise ArgumentError(f"File not found: {arg}")
  110.             print ("File not found: {arg}\nLoading default data")
  111.         else:
  112.             with open(arg, "r", encoding="utf-8") as stream:
  113.                 self.discord_users = yaml.safe_load(stream)
  114.                
  115.  
  116.     def save_user_data(self):
  117.  
  118.         path = "storage/discord_bot"
  119.  
  120.         arg = f"{path}/users_data.yaml"
  121.  
  122.         with open(arg, "w", encoding="utf-8") as stream:
  123.            
  124.  
  125.             #yaml.safe_dump(stream)
  126.            # hub = OrderedDict()
  127.  
  128.             yaml.dump(
  129.                 self.discord_users,
  130.                 stream,
  131.                 default_flow_style=False,
  132.             )
  133.         #user_data_str: str = str(self.discord_users).replace(", ", "\n ")
  134.         #print(f"Saved user data successfully with data: {user_data_str}")
  135.         print(f"Saved user data successfully.")
  136.    
  137.     def load_cached_url_data(self):
  138.  
  139.         path: str = "storage/discord_bot"
  140.  
  141.         arg: str = f"{path}/url_cached_data.yaml"
  142.  
  143.         if not os.path.isfile(arg):
  144.             #raise ArgumentError(f"File not found: {arg}")
  145.             print ("File not found: {arg}\nLoading default data")
  146.         else:
  147.             with open(arg, "r", encoding="utf-8") as stream:
  148.                 self.image_URLs = yaml.safe_load(stream)
  149.     def save_cached_url_data(self):
  150.  
  151.         path: str = "storage/discord_bot"
  152.  
  153.         arg: str = f"{path}/url_cached_data.yaml"
  154.  
  155.         with open(arg, "w", encoding="utf-8") as stream:
  156.            
  157.  
  158.             #yaml.safe_dump(stream)
  159.            # hub = OrderedDict()
  160.  
  161.             yaml.dump(
  162.                 self.image_URLs,
  163.                 stream,
  164.                 default_flow_style=False,
  165.             )
  166.         #user_data_str = str(self.discord_users).replace(", ", "\n ")
  167.         #print(f"Saved user data successfully with data: {user_data_str}")
  168.         print(f"Saved image url data successfully.")
  169.  
  170.     def get_discord_equivalent(self, showname):
  171.        # values = self.discord_users.values()
  172.         #for x in range(len(self.discord_users)):
  173.         #    if showname == values[x].get("ao_showname"):
  174.         #        return values[x]
  175.         for user in self.discord_users.values():
  176.             if user.get("ao_showname") == showname:
  177.                 return user
  178.                 #return self.discord_values.values()
  179.                 #return self.discord_users.get(self.discord_users.get("discord_id"))
  180.         # If we didn't find any matching users'
  181.         return None
  182.  
  183.            
  184.  
  185.     def get_discord_user(self, search_id) -> dict:
  186.         #keys = self.discord_users.keys()
  187.         #for x in range(len(keys)):
  188.         #    if search_id == list(keys)[x]:
  189.                
  190.                 #return list(self.discord_users.values()[x])
  191.                 #print(f"get_discord_user is: {str(self.discord_users.values()[x])}")
  192.                 #return self.discord_users.values()[x]
  193.         for user_id in self.discord_users.keys():
  194.             if user_id == search_id:
  195.                 #print(f'get_discord_user is: {self.discord_users.get(user_id)}')
  196.                 return self.discord_users.get(user_id)
  197.         # If we didn't find any users create a new one
  198.         return self.create_discord_user(search_id)
  199.  
  200.     def create_discord_user(self, creation_id):
  201.         created_user_data: dict = self.default_user
  202.  
  203.         #self.discord_users.append(creation_id, created_user_data)
  204.         self.discord_users[creation_id] = created_user_data
  205.        
  206.         return created_user_data
  207.            
  208.  
  209.     def queue_message(self, name, message, charname, anim, showname, args, bg):
  210.         base = None
  211.         avatar_url = None
  212.         anim_url = None
  213.         embed_emotes = False
  214.  
  215.         #bg = args[]
  216.         pos = args[5]
  217.  
  218.         if "base_url" in self.server.config["bridgebot"]:
  219.             base = self.server.config["bridgebot"]["base_url"]
  220.         if "embed_emotes" in self.server.config["bridgebot"]:
  221.             embed_emotes = self.server.config["bridgebot"]["embed_emotes"]
  222.         if base != None:
  223.             avatar_url = base + parse.quote("characters/" + charname + "/char_icon.png")
  224.             if embed_emotes:
  225.                 anim_url = base + parse.quote(
  226.                     "characters/" + charname + "/" + anim + ".png"
  227.                 )
  228.         elif self.server.config["bridgebot"]["avatar_url"] != None:
  229.             user_data = self.get_discord_equivalent(showname)
  230.             if user_data != None:
  231.                 avatar_url = user_data.get("avatar_url")
  232.             else:
  233.                 avatar_url = self.server.config["bridgebot"]["avatar_url"]
  234.        
  235.         character_path = "characters"
  236.         character_path_cache = "storage/base_data/characters"
  237.  
  238.         final_path = ""
  239.  
  240.         #png_path = f'/' + charname + "/" + anim + ".png"
  241.         #gif_path = f'/' + charname + "/(a)" + anim + ".gif"
  242.         #gif_path_alt = f'/' + charname + "/" + anim + ".gif"
  243.  
  244.         file_paths = [  f'/' + charname + "/" + anim + ".png",
  245.                         f'/' + charname + "/(a)" + anim + ".gif",
  246.                         f'/' + charname + "/(a)/" + anim + ".gif",
  247.                         f'/' + charname + "/(b)" + anim + ".gif",
  248.                         f'/' + charname + "/(b)/" + anim + ".gif",
  249.                         f'/' + charname + "/" + anim + ".gif",
  250.                         f'/' + charname + "/" + anim + ".webp"]
  251.        
  252.         #character_info_path = f'{charname}/{anim}.webp'
  253.        
  254.         bg_cache_paths = [
  255.             f'{bg}/{anim}.webp'
  256.         ]
  257.  
  258.         bg_info_path: str = ""
  259.  
  260.         for path in bg_cache_paths:
  261.             if self.image_URLs.get(path, None) != None:
  262.                 bg_info_path = path
  263.                 cached_url = self.image_URLs.get(path, None) # Get the URL from the image_URLs dictionary
  264.                 #print(f"Got the bg cached path and is: {final_path}")
  265.                 break
  266.             #print(f'Cached path is: {path}')
  267.  
  268.         file_cache_paths = [
  269.             f'{charname}/{anim}.webp',
  270.             f'{charname}/(a){anim}.webp',
  271.             f'{charname}/(b){anim}.webp',
  272.             f'{charname}/{anim}.png',
  273.             f'{charname}/{anim}.gif',
  274.             f'{charname}/(a){anim}.gif',
  275.             f'{charname}/(b){anim}.gif',
  276.             f'{charname}/(a)/{anim}.gif',
  277.             f'{charname}/(b)/{anim}.gif',
  278.         ]
  279.         #character_info_path = ""
  280.         cached_url = None
  281.         for path in file_cache_paths:
  282.             if self.image_URLs.get(path, None) != None:
  283.                 #character_info_path = path
  284.                 cached_url = self.image_URLs.get(path, None)
  285.                 print(f"Got the cached path and is: {final_path}")
  286.                 break
  287.             #print(f'Cached path is: {path}')
  288.        
  289.         #print("character_info_path: " + character_info_path)
  290.        
  291.  
  292.         if cached_url != None:
  293.             anim_url = cached_url
  294.             #print(f'Got the anime_url and is: {anim_url}')
  295.         else:
  296.             webp_cache_path = f'{character_path_cache}/{charname}/{anim}.webp'
  297.  
  298.             if os.path.isfile(webp_cache_path):
  299.                 final_path = webp_cache_path
  300.                 #print(f' Got the webp path and is: {final_path}')
  301.             else:
  302.                 for path in file_paths:
  303.                     #if os.path.isfile(f'{character_path_cache}{path}'):
  304.                     #    final_path = f'{character_path_cache}{path}{path}'
  305.                     if os.path.isfile(f'{character_path}{path}'):
  306.                         final_path = f'{character_path}{path}'
  307.                         #print(f"Got the normal path and is: {final_path}")
  308.                         break
  309.                     #print(f'Path is: {path}')
  310.         #if os.path.isfile(png_path):
  311.         #    final_path = png_path
  312.         #elif os.path.isfile(gif_path):
  313.         #    final_path = gif_path
  314.         #elif os.path.isfile(gif_path_alt):
  315.         #    final_path = gif_path_alt
  316.  
  317.         #self.last_char = charname
  318.         #self.last_emote = anim
  319.         self.last_chars[self.last_index] = charname
  320.         self.last_emotes[self.last_index] = anim
  321.         if self.last_index == 1:    self.last_index = 0
  322.         else:                       self.last_index = 1
  323.  
  324.  
  325.         if self.can_send_message == True:
  326.             self.can_send_message = False
  327.             asyncio.ensure_future(self.send_char_message(name, message, avatar_url, anim_url, final_path, args, bg))
  328.             #asyncio.ensure_future(self.send_char_message(name, message, avatar_url, anim_url, final_path))
  329.             #self.loop.run_until_complete(self.send_char_message(name, message, avatar_url, anim_url, final_path))
  330.             #self.send_char_message(name, message, avatar_url, anim_url, final_path)
  331.         else:
  332.             self.pending_messages.append([name, message, avatar_url, anim_url, final_path, args, bg])
  333.  
  334.     async def on_ready(self):
  335.         print("Discord Bridge Successfully logged in.")
  336.         print("Username -> " + self.user.display_name)
  337.         print("ID -> " + str(self.user.id))
  338.         self.guild = self.guilds[0]
  339.         self.channel = discord.utils.get(
  340.             self.guild.text_channels, name=self.target_channel
  341.         )
  342.  
  343.         sys.setrecursionlimit(255)
  344.  
  345.         self.load_user_data()
  346.         self.load_cached_url_data()
  347.        
  348.         #tickspeed: float = 1.0
  349.         #tickspeed: float = max(0.1, self.server.config["bridgebot"]["tickspeed"])
  350.  
  351.         await self.wait_until_ready()
  352.  
  353.         delta: float = 0.0
  354.         last_time: float = 0.0
  355.         start_time: float = 0.0
  356.  
  357.         while self.opened: # Check if bot still opened in the loop
  358.             start_time = time.time()
  359.             delta = last_time - start_time # More precise time than the fixed tickrate
  360.            
  361.             if len(self.pending_messages) > 0:
  362.                 self.can_send_message = False
  363.                 #await self.send_char_message(*self.pending_messages.pop())
  364.                 asyncio.ensure_future(self.send_char_message(*self.pending_messages.pop()))
  365.            
  366.             else:
  367.                 self.can_send_message = True
  368.             #print(f'can_send_message: {self.can_send_message}')
  369.             # Save_loop
  370.             if self.time >= self.max_save_time:
  371.                 self.time -= self.max_save_time
  372.                 self.can_save_data = True
  373.                
  374.                 if self.need_to_save_url == True:
  375.                     self.try_to_save_url()
  376.                 elif self.need_to_save == True:
  377.                     self.try_to_save()
  378.  
  379.             # End Save_loop
  380.             self.time += delta
  381.             last_time = time.time()
  382.             #await asyncio.sleep(self.tickspeed)
  383.             await asyncio.sleep(self.tickspeed - (last_time - start_time)) # Ensure constant tickspeed
  384.    
  385.     async def on_message(self, message): # Discord to AO2
  386.         # Screw these loser bots
  387.         if message.author.bot or message.webhook_id != None:
  388.             return
  389.  
  390.         if message.channel != self.channel:
  391.             return
  392.        
  393.         self.was_my_message = False
  394.  
  395.         if not message.content.startswith(self.prefix):
  396.             try:
  397.                 max_char: int = int(self.server.config["max_chars_ic"])
  398.             except:
  399.                 max_char: int = 256
  400.             if len(message.clean_content) > max_char:
  401.                 await self.channel.send(
  402.                     "Your message was too long - it was not received by the client. (The limit is 256 characters)"
  403.                 )
  404.                 return
  405.             text: str = message.clean_content
  406.  
  407.             if len(message.attachments) > 0:
  408.                 text = f'[`Attachment`] {text}'
  409.  
  410.             self.server.send_discord_chat(
  411.                 message.author.display_name,
  412.                 escape_markdown(text),
  413.                 self.hub_id,
  414.                 self.area_id,
  415.                 self.get_discord_user(message.author.id)
  416.             )
  417.         else: # simple commands (Temporal)  If has the discord_prefix
  418.             text: str = message.content
  419.  
  420.             text = text.replace(self.prefix, "", 1)
  421.  
  422.             command: str = text.split(" ")[0]
  423.  
  424.             #args = text.lstrip(f'{command}').split(" ")
  425.             args = text.split()[1:]
  426.  
  427.             user_data: int = self.get_discord_user(message.author.id)
  428.  
  429.             changed_atribute: str = ""
  430.  
  431.             if command == "avatar_url" or command == "avatar":
  432.                 user_data["avatar_url"] = " ".join(args)
  433.                 changed_atribute = "avatar"
  434.             elif command == "char_name" or command == "char":
  435.                 user_data["char_name"] = " ".join(args)
  436.                 changed_atribute = "char"
  437.             elif command == "emote_name" or command == "emote":
  438.                 user_data["emote_name"] = " ".join(args)
  439.                 changed_atribute = "emote"
  440.             elif command == "position" or command == "pos":
  441.                 user_data["position"] = " ".join(args)
  442.                 changed_atribute = "pos"
  443.             elif command == "ao_showname" or command == "showname" or command == "name":
  444.                 user_data["ao_showname"] = " ".join(args)
  445.                 changed_atribute = "showname"
  446.             elif command == "footer_url" or command == "footer":
  447.                 user_data["footer_url"] = " ".join()
  448.                 changed_atribute = "footer"
  449.             if changed_atribute != "":
  450.                 msg = f"{message.author.mention} changed {changed_atribute} to ({' '.join(args)})"
  451.             else:
  452.                 msg = f"{message.author.mention} your command doesn't exists, u baka.\nYou can use 'avatar', 'name', 'emote', 'pos', 'showname', 'footer'"
  453.             #await message.channel.send(msg)
  454.             await message.reply(msg)
  455.             await self.try_to_save()
  456.  
  457.  
  458.  
  459.         # await self.process_commands(message)
  460.  
  461.     async def try_to_save(self):
  462.         if self.can_save_data:
  463.             self.save_user_data()
  464.             self.can_save_data = False
  465.             self.need_to_save = False
  466.         else:
  467.             self.need_to_save = True
  468.    
  469.     async def try_to_save_url(self):
  470.         if self.can_save_data:
  471.             self.save_cached_url_data()
  472.             self.can_save_data = False
  473.             self.need_to_save_url = False
  474.         else:
  475.             self.need_to_save_url = True
  476.            
  477.     async def is_url_image(image_url):
  478.         #image_formats = ("image/png", "image/jpeg", "image/jpg", "image/webp")
  479.         #r = requests.head(image_url)
  480.         #if r.headers["content-type"] in image_formats:
  481.         #    return True
  482.         #return False#
  483.         return True
  484.  
  485.     #def send_char_message_threaded(self, *args: List[list]):
  486.     #    loop = asyncio.new_event_loop()
  487.     #    asyncio.set_event_loop(loop)
  488.  
  489.     #    loop.run_until_complete(self.send_char_message(*args))
  490.     #    #loop.run_until_complete(self.test_thread())
  491.     #    loop.close()
  492.    
  493.     async def test_thread(self):
  494.         print("Thread started succesfully!")
  495.  
  496.     async def send_char_message(self, name, message, avatar=None, image=None, image_alt_path=None, args=None, bg=None): #Discord to AO2
  497.         print("Sended char message")
  498.         self.start_time_message = time.time()
  499.         webhook = None
  500.         embed = None
  501.         try:
  502.             webhooks = await self.channel.webhooks()
  503.             for hook in webhooks:
  504.                 if hook.user == self.user or hook.name == "AO2_Bridgebot":
  505.                     webhook = hook
  506.                     break
  507.             if webhook == None:
  508.                 webhook = await self.channel.create_webhook(name="AO2_Bridgebot")
  509.            
  510.             is_from_cache = image_alt_path.startswith("storage/base_data/")
  511.             send_directly = image_alt_path.endswith(".gif")
  512.            
  513.             if image != None:
  514.                 send_image: bool = (
  515.                 self.was_my_message == False
  516.                 or self.last_chars[0] != self.last_chars[1]
  517.                 or self.last_emotes[0] != self.last_emotes[1]
  518.                 )
  519.                 if send_image:
  520.  
  521.                     embed = discord.Embed()
  522.                     embed.set_image(url=image)
  523.                     #current_footer_url: str = self.user_data["footer_url"]
  524.                     if args != None:
  525.                         emote_name = args[3]
  526.                         char_name = args[2]
  527.                     current_footer_url: str = ""
  528.                     footer_text = f"{char_name}/{emote_name}"
  529.                     if current_footer_url != None and current_footer_url != "":
  530.                         embed.set_footer(text=footer_text, icon_url=current_footer_url)
  531.                     else: embed.set_footer(text=footer_text)
  532.                    
  533.                    
  534.                     #print(avatar, image)
  535.  
  536.             webhook_message = await webhook.send(message, username=name, avatar_url=avatar, embed=embed, wait=True)
  537.             print("--- %s seconds (message [Partial]) ---" % (time.time() - self.start_time_message))
  538.             print(
  539.                 f'[DiscordBridge] Sending message from "{name}" to "{self.channel.name}"'
  540.             )
  541.  
  542.             if image == None:
  543.                 img = None
  544.                 is_binary_image: bool = False
  545.                 image_binary: io.BytesIO = None
  546.                 character_info_path: str = ""
  547.                 await self.channel.trigger_typing()
  548.                 self.start_time_image = time.time()
  549.                 final_image_path: str = ""
  550.                 if is_from_cache == False and send_directly == False and self.has_pillow:
  551.                     #if self.has_pillow: # If have the pillow module installed activated it
  552.                     with open(image_alt_path, "rb") as f:
  553.                         img = Image.open(io.BytesIO(f.read()))
  554.                
  555.                     # Resize thing
  556.                     #wanted_height: int = 256
  557.                     #width, height = img.size
  558.                     #if height > wanted_height:
  559.                         #final_size: tuple = ( int(wanted_height * (width / height)) , wanted_height)
  560.                     # img = img.resize(final_size)
  561.                     # End resize
  562.  
  563.                     is_binary_image = True
  564.  
  565.                
  566.                     #character_info_path = final_image_path.split("characters/", 1)[1]
  567.                 else: # Send the image directly without converting it
  568.                     final_image_path = image_alt_path
  569.                # if is_from_cache: final_image_path = image_alt_path
  570.  
  571.                 sended_file_message = None
  572.                 if is_binary_image:
  573.                     with io.BytesIO() as image_binary:
  574.                         img.save(image_binary, "webp", lossless=False, method=6, quality=100, resample=Image.LANCZOS)
  575.                         image_binary.seek(0) #Put it  in the start point
  576.  
  577.                         print("--- %s seconds (image) ---" % (time.time() - self.start_time_image))
  578.  
  579.                         sended_file_message = await webhook_message.reply(file=discord.File(fp=image_binary, filename=character_info_path.split("/")[-1]))
  580.                         # Ended sending the image
  581.  
  582.                         final_image_path = f"storage/base_data/{image_alt_path.rsplit('.', 1)[0]}.webp"
  583.                         if os.path.isdir(os.path.dirname(final_image_path)) == False:
  584.                             os.makedirs(os.path.dirname(final_image_path))
  585.  
  586.                         with open(final_image_path, "wb") as f:
  587.                             shutil.copyfileobj(image_binary, f)
  588.                         img.close() # Erase the image from memory manually (More efficient)
  589.                 else:
  590.                     sended_file_message = await webhook_message.reply(file = discord.File(final_image_path))
  591.                 character_info_path = final_image_path.split("characters/", 1)[1]
  592.  
  593.                 print(f'character_info_path: {character_info_path}')
  594.  
  595.                 attachment_url = sended_file_message.attachments[0].url # Get attachment url of the image
  596.                 # Save URL for later use
  597.                 if character_info_path != None and character_info_path != "":
  598.                     self.image_URLs[character_info_path] = attachment_url
  599.                     await self.try_to_save_url() # Async function
  600.                     #print(f"Image_URLs: {self.image_URLs}")
  601.             self.was_my_message = True
  602.             print("--- %s seconds (message [Total]) ---" % (time.time() - self.start_time_message))
  603.  
  604.         except Forbidden:
  605.             print(
  606.                 f'[DiscordBridge] Insufficient permissions - couldnt send char message "{name}: {message}" with avatar "{avatar}" to "{self.channel.name}"'
  607.             )
  608.         except HTTPException:
  609.             print(
  610.                 f'[DiscordBridge] HTTP Failure - couldnt send char message "{name}: {message}" with avatar "{avatar}" to "{self.channel.name}"'
  611.             )
  612.         except Exception as ex:
  613.             # This is a workaround to a problem - [Errno 104] Connection reset by peer occurs due to too many calls for this func.
  614.             # Simple solution is to increase the tickspeed config so it waits longer between messages sent.
  615.             print(f"[DiscordBridge] Exception - {ex}")
  616.  
  617.  
  618.     async def save_binary_image(self, binary_data, path):
  619.        
  620.        
  621.        
  622.         pass
  623.  
  624.     async def save_image(self, image, path):
  625.         pass
  626.  
Advertisement
Add Comment
Please, Sign In to add comment