Преглед на файлове

Fix indents and checking role in func instead of before

Lucas Villeneuve преди 5 години
родител
ревизия
d287afa4a6
променени са 3 файла, в които са добавени 388 реда и са изтрити 383 реда
  1. 1 1
      myanimebot.py
  2. 30 0
      myanimebot/commands.py
  3. 357 382
      myanimebot/discord.py

+ 1 - 1
myanimebot.py

@@ -26,7 +26,7 @@ import myanimebot.globals as globals
 import myanimebot.utils as utils
 import myanimebot.myanimelist as myanimelist
 import myanimebot.commands as commands
-from myanimebot.discord import send_embed_wrapper, build_embed, in_allowed_role, MyAnimeBot
+from myanimebot.discord import send_embed_wrapper, build_embed, MyAnimeBot
 
 
 if not sys.version_info[:2] >= (3, 7):

+ 30 - 0
myanimebot/commands.py

@@ -61,6 +61,27 @@ def get_service_filters_list(filters : str) -> List[utils.Service]:
     return filters_list
 
 
+def in_allowed_role(user : discord.Member, server : int) -> bool :
+    ''' Check if a user has the permissions to configure the bot on a specific server '''
+
+    targetRole = utils.get_allowed_role(server.id)
+    globals.logger.debug ("Role target: " + str(targetRole))
+
+    if user.guild_permissions.administrator:
+        globals.logger.debug (str(user) + " is server admin on " + str(server) + "!")
+        return True
+    elif (targetRole is None):
+        globals.logger.debug ("No group specified for " + str(server))
+        return True
+    else:
+        for role in user.roles:
+            if str(role.id) == str(targetRole):
+                globals.logger.debug ("Permissions validated for " + str(user))
+                return True
+
+    return False
+
+
 def check_user_name_validity(user_name: str, service : utils.Service) -> Tuple[bool, str]:
     """ Check if user_name exists on a specific service.
         
@@ -96,6 +117,10 @@ async def add_user_cmd(words, message):
             return await message.channel.send("Usage: {} add **{}**/**{}** **username**".format(globals.prefix, globals.SERVICE_MAL, globals.SERVICE_ANILIST))
         return await message.channel.send("Too many arguments! You have to specify only one username.")
 
+    # Verify that the user is allowed
+    if in_allowed_role(message.author, message.guild) is False:
+        return await message.channel.send("Only allowed users can use this command!")
+
     try:
         service = utils.Service.from_str(words[2])
     except NotImplementedError:
@@ -140,6 +165,11 @@ async def delete_user_cmd(words, message):
         if (len(words) < 4):
             return await message.channel.send("Usage: {} delete **{}**/**{}** **username**".format(globals.prefix, globals.SERVICE_MAL, globals.SERVICE_ANILIST))
         return await message.channel.send("Too many arguments! You have to specify only one username.")
+
+    # Verify that the user is allowed
+    if in_allowed_role(message.author, message.guild) is False:
+        return await message.channel.send("Only allowed users can use this command!")
+
     try:
         service = utils.Service.from_str(words[2])
     except NotImplementedError:

+ 357 - 382
myanimebot/discord.py

@@ -21,183 +21,179 @@ import myanimebot.utils as utils
 
 
 class MyAnimeBot(discord.Client):
-	async def on_ready(self):
-		globals.logger.info("Logged in as " + globals.client.user.name + " (" + str(globals.client.user.id) + ")")
-
-		globals.logger.info("Starting all tasks...")
-
-		if globals.MAL_ENABLED:
-			globals.task_feed = globals.client.loop.create_task(background_check_feed(globals.client.loop))
-
-		if globals.ANI_ENABLED:
-			globals.task_feed_anilist = globals.client.loop.create_task(anilist.background_check_feed(globals.client.loop))
-
-		globals.task_thumbnail = globals.client.loop.create_task(update_thumbnail_catalog(globals.client.loop))
-		globals.task_gameplayed = globals.client.loop.create_task(change_gameplayed(globals.client.loop))
-
-	async def on_error(self, event, *args, **kwargs):
-		globals.logger.exception("Crap! An unknown Discord error occured...")
-
-	async def on_message(self, message):
-		if message.author == globals.client.user: return
-
-		words = message.content.split(" ")
-		channel = message.channel
-		author = str('{0.author.mention}'.format(message))
-
-		# A user is trying to get help
-		if words[0] == globals.prefix:
-			if len(words) > 1:
-				if words[1] == "ping":
-					await commands.ping_cmd(message, channel)
-				
-				elif words[1] == "here":
-					if in_allowed_role(message.author, message.guild):
-						cursor = globals.conn.cursor(buffered=True)
-						cursor.execute("SELECT server, channel FROM t_servers WHERE server=%s", [str(message.guild.id)])
-						data = cursor.fetchone()
-						
-						if data is None:
-							cursor.execute("INSERT INTO t_servers (server, channel) VALUES (%s,%s)", [str(message.guild.id), str(message.channel.id)])
-							globals.conn.commit()
-							
-							await message.channel.send("Channel **" + str(message.channel) + "** configured for **" + str(message.guild) + "**.")
-						else:
-							if(data[1] == str(message.channel.id)): await message.channel.send("Channel **" + str(message.channel) + "** already in use for this server.")
-							else:
-								cursor.execute("UPDATE t_servers SET channel = %s WHERE server = %s", [str(message.channel.id), str(message.guild.id)])
-								globals.conn.commit()
-								
-								await message.channel.send("Channel updated to: **" + str(message.channel) + "**.")
-								
-						cursor.close()
-					else: await message.channel.send("Only allowed users can use this command!")
-					
-				elif words[1] == "add":
-					if in_allowed_role(message.author, message.guild):
-						await commands.add_user_cmd(words, message)
-					else: await message.channel.send("Only allowed users can use this command!")
-					
-				elif words[1] == "delete":
-					if in_allowed_role(message.author, message.guild):
-						await commands.delete_user_cmd(words, message)
-					else: await message.channel.send("Only allowed users can use this command!")
-					
-				elif words[1] == "stop":
-					if in_allowed_role(message.author, message.guild):
-						if (len(words) == 2):
-							cursor = globals.conn.cursor(buffered=True)
-							cursor.execute("SELECT server FROM t_servers WHERE server=%s", [str(message.guild.id)])
-							data = cursor.fetchone()
-						
-							if data is None: await message.channel.send("The server **" + str(message.guild) + "** is not in our database.")
-							else:
-								cursor.execute("DELETE FROM t_servers WHERE server = %s", [message.guild.id])
-								globals.conn.commit()
-								await message.channel.send("Server **" + str(message.guild) + "** deleted from our database.")
-							
-							cursor.close()
-						else: await message.channel.send("Too many arguments! Only type *stop* if you want to stop this bot on **" + message.guild + "**")
-					else: await message.channel.send("Only allowed users can use this command!")
-					
-				elif words[1] == "info":
-					await commands.info_cmd(message, words)
-
-				elif words[1] == "about":
-					await commands.about_cmd(channel)
-				
-				elif words[1] == "help":
-					await commands.help_cmd(channel)
-				
-				elif words[1] == "top":
-					if len(words) == 2:
-						try:
-							cursor = globals.conn.cursor(buffered=True)
-							cursor.execute("SELECT * FROM v_Top")
-							data = cursor.fetchone()
-							
-							if data is None: await message.channel.send("It seems that there is no statistics... (what happened?!)")
-							else:
-								topText = "**__Here is the global statistics of this bot:__**\n\n"
-								
-								while data is not None:
-									topText += " - " + str(data[0]) + ": " + str(data[1]) + "\n"
-										
-									data = cursor.fetchone()
-									
-								cursor = globals.conn.cursor(buffered=True)
-								cursor.execute("SELECT * FROM v_TotalFeeds")
-								data = cursor.fetchone()
-								
-								topText += "\n***Total user entry***: " + str(data[0])
-								
-								cursor = globals.conn.cursor(buffered=True)
-								cursor.execute("SELECT * FROM v_TotalAnimes")
-								data = cursor.fetchone()
-								
-								topText += "\n***Total unique manga/anime***: " + str(data[0])
-								
-								await message.channel.send(topText)
-							
-							cursor.close()
-						except Exception as e:
-							globals.logger.warning("An error occured while displaying the global top: " + str(e))
-							await message.channel.send("Unable to reply to your request at the moment...")
-					elif len(words) > 2:
-						keyword = str(' '.join(words[2:]))
-						globals.logger.info("Displaying the global top for the keyword: " + keyword)
-						
-						try:
-							cursor = globals.conn.cursor(buffered=True)
-							cursor.callproc('sp_UsersPerKeyword', [str(keyword), '20'])
-							for result in cursor.stored_results():
-								data = result.fetchone()
-								
-								if data is None: await message.channel.send("It seems that there is no statistics for the keyword **" + keyword + "**.")
-								else:
-									topKeyText = "**__Here is the statistics for the keyword " + keyword + ":__**\n\n"
-									
-									while data is not None:
-										topKeyText += " - " + str(data[0]) + ": " + str(data[1]) + "\n"
-											
-										data = result.fetchone()
-										
-									await message.channel.send(topKeyText)
-								
-							cursor.close()
-						except Exception as e:
-							globals.logger.warning("An error occured while displaying the global top for keyword '" + keyword + "': " + str(e))
-							await message.channel.send("Unable to reply to your request at the moment...")
-				
-				elif words[1] == "role":
-					if len(words) > 2:
-						if message.author.guild_permissions.administrator:
-							cursor = globals.conn.cursor(buffered=True)
-
-							if (words[2] == "everyone") | (words[2] == "@everyone"):
-								cursor.execute("UPDATE t_servers SET admin_group = NULL WHERE server = %s", [str(message.guild.id)])
-								globals.conn.commit()
-
-								await message.channel.send("Everybody is now allowed to use the bot!")
-							else:
-								rolesFound = message.role_mentions
-
-								if (len(rolesFound) > 1): await message.channel.send("Please specify only 1 group!")
-								elif (len(rolesFound) == 0): await message.channel.send("Please specify a correct group.")
-								else: 
-									cursor.execute("UPDATE t_servers SET admin_group = %s WHERE server = %s", [str(rolesFound[0].id), str(message.guild.id)])
-									globals.conn.commit()
-
-									await message.channel.send("The role **" + str(rolesFound[0].name) + "** is now allowed to use this bot!")
-
-							cursor.close()
-						else: await message.channel.send("Only server's admins can use this command!")
-					else:
-						await message.channel.send("You have to specify a role!")
-
-		# If mentioned
-		elif globals.client.user in message.mentions:
-			await channel.send(":heart:")
+    async def on_ready(self):
+        globals.logger.info("Logged in as " + globals.client.user.name + " (" + str(globals.client.user.id) + ")")
+
+        globals.logger.info("Starting all tasks...")
+
+        if globals.MAL_ENABLED:
+            globals.task_feed = globals.client.loop.create_task(background_check_feed(globals.client.loop))
+
+        if globals.ANI_ENABLED:
+            globals.task_feed_anilist = globals.client.loop.create_task(anilist.background_check_feed(globals.client.loop))
+
+        globals.task_thumbnail = globals.client.loop.create_task(update_thumbnail_catalog(globals.client.loop))
+        globals.task_gameplayed = globals.client.loop.create_task(change_gameplayed(globals.client.loop))
+
+    async def on_error(self, event, *args, **kwargs):
+        globals.logger.exception("Crap! An unknown Discord error occured...")
+
+    async def on_message(self, message):
+        if message.author == globals.client.user: return
+
+        words = message.content.split(" ")
+        channel = message.channel
+        author = str('{0.author.mention}'.format(message))
+
+        # A user is trying to get help
+        if words[0] == globals.prefix:
+            if len(words) > 1:
+                if words[1] == "ping":
+                    await commands.ping_cmd(message, channel)
+                
+                elif words[1] == "here":
+                    if in_allowed_role(message.author, message.guild):
+                        cursor = globals.conn.cursor(buffered=True)
+                        cursor.execute("SELECT server, channel FROM t_servers WHERE server=%s", [str(message.guild.id)])
+                        data = cursor.fetchone()
+                        
+                        if data is None:
+                            cursor.execute("INSERT INTO t_servers (server, channel) VALUES (%s,%s)", [str(message.guild.id), str(message.channel.id)])
+                            globals.conn.commit()
+                            
+                            await message.channel.send("Channel **" + str(message.channel) + "** configured for **" + str(message.guild) + "**.")
+                        else:
+                            if(data[1] == str(message.channel.id)): await message.channel.send("Channel **" + str(message.channel) + "** already in use for this server.")
+                            else:
+                                cursor.execute("UPDATE t_servers SET channel = %s WHERE server = %s", [str(message.channel.id), str(message.guild.id)])
+                                globals.conn.commit()
+                                
+                                await message.channel.send("Channel updated to: **" + str(message.channel) + "**.")
+                                
+                        cursor.close()
+                    else: await message.channel.send("Only allowed users can use this command!")
+                    
+                elif words[1] == "add":
+                    await commands.add_user_cmd(words, message)
+                    
+                elif words[1] == "delete":
+                    await commands.delete_user_cmd(words, message)
+                    
+                elif words[1] == "stop":
+                    if in_allowed_role(message.author, message.guild):
+                        if (len(words) == 2):
+                            cursor = globals.conn.cursor(buffered=True)
+                            cursor.execute("SELECT server FROM t_servers WHERE server=%s", [str(message.guild.id)])
+                            data = cursor.fetchone()
+                        
+                            if data is None: await message.channel.send("The server **" + str(message.guild) + "** is not in our database.")
+                            else:
+                                cursor.execute("DELETE FROM t_servers WHERE server = %s", [message.guild.id])
+                                globals.conn.commit()
+                                await message.channel.send("Server **" + str(message.guild) + "** deleted from our database.")
+                            
+                            cursor.close()
+                        else: await message.channel.send("Too many arguments! Only type *stop* if you want to stop this bot on **" + message.guild + "**")
+                    else: await message.channel.send("Only allowed users can use this command!")
+                    
+                elif words[1] == "info":
+                    await commands.info_cmd(message, words)
+
+                elif words[1] == "about":
+                    await commands.about_cmd(channel)
+                
+                elif words[1] == "help":
+                    await commands.help_cmd(channel)
+                
+                elif words[1] == "top":
+                    if len(words) == 2:
+                        try:
+                            cursor = globals.conn.cursor(buffered=True)
+                            cursor.execute("SELECT * FROM v_Top")
+                            data = cursor.fetchone()
+                            
+                            if data is None: await message.channel.send("It seems that there is no statistics... (what happened?!)")
+                            else:
+                                topText = "**__Here is the global statistics of this bot:__**\n\n"
+                                
+                                while data is not None:
+                                    topText += " - " + str(data[0]) + ": " + str(data[1]) + "\n"
+                                        
+                                    data = cursor.fetchone()
+                                    
+                                cursor = globals.conn.cursor(buffered=True)
+                                cursor.execute("SELECT * FROM v_TotalFeeds")
+                                data = cursor.fetchone()
+                                
+                                topText += "\n***Total user entry***: " + str(data[0])
+                                
+                                cursor = globals.conn.cursor(buffered=True)
+                                cursor.execute("SELECT * FROM v_TotalAnimes")
+                                data = cursor.fetchone()
+                                
+                                topText += "\n***Total unique manga/anime***: " + str(data[0])
+                                
+                                await message.channel.send(topText)
+                            
+                            cursor.close()
+                        except Exception as e:
+                            globals.logger.warning("An error occured while displaying the global top: " + str(e))
+                            await message.channel.send("Unable to reply to your request at the moment...")
+                    elif len(words) > 2:
+                        keyword = str(' '.join(words[2:]))
+                        globals.logger.info("Displaying the global top for the keyword: " + keyword)
+                        
+                        try:
+                            cursor = globals.conn.cursor(buffered=True)
+                            cursor.callproc('sp_UsersPerKeyword', [str(keyword), '20'])
+                            for result in cursor.stored_results():
+                                data = result.fetchone()
+                                
+                                if data is None: await message.channel.send("It seems that there is no statistics for the keyword **" + keyword + "**.")
+                                else:
+                                    topKeyText = "**__Here is the statistics for the keyword " + keyword + ":__**\n\n"
+                                    
+                                    while data is not None:
+                                        topKeyText += " - " + str(data[0]) + ": " + str(data[1]) + "\n"
+                                            
+                                        data = result.fetchone()
+                                        
+                                    await message.channel.send(topKeyText)
+                                
+                            cursor.close()
+                        except Exception as e:
+                            globals.logger.warning("An error occured while displaying the global top for keyword '" + keyword + "': " + str(e))
+                            await message.channel.send("Unable to reply to your request at the moment...")
+                
+                elif words[1] == "role":
+                    if len(words) > 2:
+                        if message.author.guild_permissions.administrator:
+                            cursor = globals.conn.cursor(buffered=True)
+
+                            if (words[2] == "everyone") | (words[2] == "@everyone"):
+                                cursor.execute("UPDATE t_servers SET admin_group = NULL WHERE server = %s", [str(message.guild.id)])
+                                globals.conn.commit()
+
+                                await message.channel.send("Everybody is now allowed to use the bot!")
+                            else:
+                                rolesFound = message.role_mentions
+
+                                if (len(rolesFound) > 1): await message.channel.send("Please specify only 1 group!")
+                                elif (len(rolesFound) == 0): await message.channel.send("Please specify a correct group.")
+                                else: 
+                                    cursor.execute("UPDATE t_servers SET admin_group = %s WHERE server = %s", [str(rolesFound[0].id), str(message.guild.id)])
+                                    globals.conn.commit()
+
+                                    await message.channel.send("The role **" + str(rolesFound[0].name) + "** is now allowed to use this bot!")
+
+                            cursor.close()
+                        else: await message.channel.send("Only server's admins can use this command!")
+                    else:
+                        await message.channel.send("You have to specify a role!")
+
+        # If mentioned
+        elif globals.client.user in message.mentions:
+            await channel.send(":heart:")
 
 
 def build_embed(feed : utils.Feed):
@@ -231,218 +227,197 @@ def build_embed(feed : utils.Feed):
 
 
 async def send_embed_wrapper(asyncioloop, channelid, client, embed):
-	''' Send an embed message to a channel '''
-
-	channel = client.get_channel(int(channelid))
-	
-	try:
-		await channel.send(embed=embed)
-		globals.logger.info("Message sent in channel: {}".format(channelid))
-	except Exception as e:
-		globals.logger.debug("Impossible to send a message on '{}': {}".format(channelid, e)) 
-		return
-
-def in_allowed_role(user : discord.Member, server : int) -> bool :
-	''' Check if a user has the permissions to configure the bot on a specific server '''
-
-	targetRole = utils.get_allowed_role(server.id)
-	globals.logger.debug ("Role target: " + str(targetRole))
-
-	if user.guild_permissions.administrator:
-		globals.logger.debug (str(user) + " is server admin on " + str(server) + "!")
-		return True
-	elif (targetRole is None):
-		globals.logger.debug ("No group specified for " + str(server))
-		return True
-	else:
-		for role in user.roles:
-			if str(role.id) == str(targetRole):
-				globals.logger.debug ("Permissions validated for " + str(user))
-				return True
-
-	return False
-
-
-	# Main function that check the RSS feeds from MyAnimeList
+    ''' Send an embed message to a channel '''
+
+    channel = client.get_channel(int(channelid))
+
+    try:
+        await channel.send(embed=embed)
+        globals.logger.info("Message sent in channel: {}".format(channelid))
+    except Exception as e:
+        globals.logger.debug("Impossible to send a message on '{}': {}".format(channelid, e)) 
+        return
+
+    # Main function that check the RSS feeds from MyAnimeList
 async def background_check_feed(asyncioloop):
-	globals.logger.info("Starting up background_check_feed")
-	
-	# We configure the http header
-	http_headers = { "User-Agent": "MyAnimeBot Discord Bot v" + globals.VERSION, }
-	timeout = aiohttp.ClientTimeout(total=5)
-	
-	await globals.client.wait_until_ready()
-	
-	globals.logger.debug("Discord client connected, unlocking background_check_feed...")
-	
-	while not globals.client.is_closed():
-		try:
-			db_user = globals.conn.cursor(buffered=True, dictionary=True)
-			db_user.execute("SELECT mal_user, servers FROM t_users WHERE service=%s", [globals.SERVICE_MAL])
-			data_user = db_user.fetchone()
-		except Exception as e:
-			globals.logger.critical("Database unavailable! (" + str(e) + ")")
-			quit()
-
-		while data_user is not None:
-			user = utils.User(id=None,
-								service_id=None,
-								name=data_user[globals.DB_USER_NAME],
-								servers=data_user["servers"].split(','))
-			stop_boucle = 0
-			feed_type = 1
-
-			try:
-				while stop_boucle == 0 :
-					try:
-						async with aiohttp.ClientSession() as httpclient:
-							if feed_type == 1 :
-								http_response = await httpclient.request("GET", "https://myanimelist.net/rss.php?type=rm&u=" + user.name, headers=http_headers, timeout=timeout)
-								media = "manga"
-							else : 
-								http_response = await httpclient.request("GET", "https://myanimelist.net/rss.php?type=rw&u=" + user.name, headers=http_headers, timeout=timeout)
-								media = "anime"
-						http_data = await http_response.read()
-					except asyncio.TimeoutError:
-						globals.logger.error("Error while loading RSS of '{}': Timeout".format(user.name))
-						break
-					except Exception as e:
-						globals.logger.exception("Error while loading RSS ({}) of '{}':\n".format(feed_type, user.name))
-						break
-
-					feeds_data = feedparser.parse(http_data)
-					
-					for feed_data in feeds_data.entries:
-						pubDateRaw = datetime.strptime(feed_data.published, '%a, %d %b %Y %H:%M:%S %z').astimezone(globals.timezone)
-						pubDate = pubDateRaw.strftime("%Y-%m-%d %H:%M:%S")
-						if feed_type == 1:
-							media_type = utils.MediaType.MANGA
-						else:
-							media_type = utils.MediaType.ANIME
-
-						feed = myanimelist.build_feed_from_data(feed_data, user, None, pubDateRaw.timestamp(), media_type)
-						
-						cursor = globals.conn.cursor(buffered=True)
-						cursor.execute("SELECT published, title, url, type FROM t_feeds WHERE published=%s AND title=%s AND user=%s AND type=%s AND obsolete=0 AND service=%s", [pubDate, feed.media.name, user.name, feed.get_status_str(), globals.SERVICE_MAL])
-						data = cursor.fetchone()
-
-						if data is None:
-							var = datetime.now(globals.timezone) - pubDateRaw
-							
-							globals.logger.debug(" - " + feed.media.name + ": " + str(var.total_seconds()))
-						
-							if var.total_seconds() < globals.secondMax:
-								globals.logger.info(user.name + ": Item '" + feed.media.name + "' not seen, processing...")
-								
-								cursor.execute("SELECT thumbnail FROM t_animes WHERE guid=%s AND service=%s LIMIT 1", [feed.media.url, globals.SERVICE_MAL]) # TODO Change that ?
-								data_img = cursor.fetchone()
-								
-								if data_img is None:
-									try:
-										image = myanimelist.get_thumbnail(feed.media.url)
-										
-										globals.logger.info("First time seeing this " + media + ", adding thumbnail into database: " + image)
-									except Exception as e:
-										globals.logger.warning("Error while getting the thumbnail: " + str(e))
-										image = ""
-										
-									cursor.execute("INSERT INTO t_animes (guid, service, title, thumbnail, found, discoverer, media) VALUES (%s, %s, %s, %s, NOW(), %s, %s)", [feed.media.url, globals.SERVICE_MAL, feed.media.name, image, user.name, media])
-									globals.conn.commit()
-								else: image = data_img[0]
-								feed.media.image = image
-
-								cursor.execute("UPDATE t_feeds SET obsolete=1 WHERE published=%s AND title=%s AND user=%s AND service=%s", [pubDate, feed.media.name, user.name, globals.SERVICE_MAL])
-								cursor.execute("INSERT INTO t_feeds (published, title, service, url, user, found, type) VALUES (%s, %s, %s, %s, %s, NOW(), %s)", (pubDate, feed.media.name, globals.SERVICE_MAL, feed.media.url, user.name, feed.get_status_str()))
-								globals.conn.commit()
-								
-								for server in user.servers:
-									db_srv = globals.conn.cursor(buffered=True)
-									db_srv.execute("SELECT channel FROM t_servers WHERE server = %s", [server])
-									data_channel = db_srv.fetchone()
-									
-									while data_channel is not None:
-										for channel in data_channel: await send_embed_wrapper(asyncioloop, channel, globals.client, build_embed(feed))
-										
-										data_channel = db_srv.fetchone()
-					if feed_type == 1:
-						feed_type = 0
-						await asyncio.sleep(globals.MYANIMELIST_SECONDS_BETWEEN_REQUESTS)
-					else:
-						stop_boucle = 1
-					
-			except Exception as e:
-				globals.logger.exception("Error when parsing RSS for '{}':\n".format(user.name))
-			
-			await asyncio.sleep(globals.MYANIMELIST_SECONDS_BETWEEN_REQUESTS)
-
-			data_user = db_user.fetchone()
+    globals.logger.info("Starting up background_check_feed")
+    
+    # We configure the http header
+    http_headers = { "User-Agent": "MyAnimeBot Discord Bot v" + globals.VERSION, }
+    timeout = aiohttp.ClientTimeout(total=5)
+    
+    await globals.client.wait_until_ready()
+    
+    globals.logger.debug("Discord client connected, unlocking background_check_feed...")
+    
+    while not globals.client.is_closed():
+        try:
+            db_user = globals.conn.cursor(buffered=True, dictionary=True)
+            db_user.execute("SELECT mal_user, servers FROM t_users WHERE service=%s", [globals.SERVICE_MAL])
+            data_user = db_user.fetchone()
+        except Exception as e:
+            globals.logger.critical("Database unavailable! (" + str(e) + ")")
+            quit()
+
+        while data_user is not None:
+            user = utils.User(id=None,
+                                service_id=None,
+                                name=data_user[globals.DB_USER_NAME],
+                                servers=data_user["servers"].split(','))
+            stop_boucle = 0
+            feed_type = 1
+
+            try:
+                while stop_boucle == 0 :
+                    try:
+                        async with aiohttp.ClientSession() as httpclient:
+                            if feed_type == 1 :
+                                http_response = await httpclient.request("GET", "https://myanimelist.net/rss.php?type=rm&u=" + user.name, headers=http_headers, timeout=timeout)
+                                media = "manga"
+                            else : 
+                                http_response = await httpclient.request("GET", "https://myanimelist.net/rss.php?type=rw&u=" + user.name, headers=http_headers, timeout=timeout)
+                                media = "anime"
+                        http_data = await http_response.read()
+                    except asyncio.TimeoutError:
+                        globals.logger.error("Error while loading RSS of '{}': Timeout".format(user.name))
+                        break
+                    except Exception as e:
+                        globals.logger.exception("Error while loading RSS ({}) of '{}':\n".format(feed_type, user.name))
+                        break
+
+                    feeds_data = feedparser.parse(http_data)
+                    
+                    for feed_data in feeds_data.entries:
+                        pubDateRaw = datetime.strptime(feed_data.published, '%a, %d %b %Y %H:%M:%S %z').astimezone(globals.timezone)
+                        pubDate = pubDateRaw.strftime("%Y-%m-%d %H:%M:%S")
+                        if feed_type == 1:
+                            media_type = utils.MediaType.MANGA
+                        else:
+                            media_type = utils.MediaType.ANIME
+
+                        feed = myanimelist.build_feed_from_data(feed_data, user, None, pubDateRaw.timestamp(), media_type)
+                        
+                        cursor = globals.conn.cursor(buffered=True)
+                        cursor.execute("SELECT published, title, url, type FROM t_feeds WHERE published=%s AND title=%s AND user=%s AND type=%s AND obsolete=0 AND service=%s", [pubDate, feed.media.name, user.name, feed.get_status_str(), globals.SERVICE_MAL])
+                        data = cursor.fetchone()
+
+                        if data is None:
+                            var = datetime.now(globals.timezone) - pubDateRaw
+                            
+                            globals.logger.debug(" - " + feed.media.name + ": " + str(var.total_seconds()))
+                        
+                            if var.total_seconds() < globals.secondMax:
+                                globals.logger.info(user.name + ": Item '" + feed.media.name + "' not seen, processing...")
+                                
+                                cursor.execute("SELECT thumbnail FROM t_animes WHERE guid=%s AND service=%s LIMIT 1", [feed.media.url, globals.SERVICE_MAL]) # TODO Change that ?
+                                data_img = cursor.fetchone()
+                                
+                                if data_img is None:
+                                    try:
+                                        image = myanimelist.get_thumbnail(feed.media.url)
+                                        
+                                        globals.logger.info("First time seeing this " + media + ", adding thumbnail into database: " + image)
+                                    except Exception as e:
+                                        globals.logger.warning("Error while getting the thumbnail: " + str(e))
+                                        image = ""
+                                        
+                                    cursor.execute("INSERT INTO t_animes (guid, service, title, thumbnail, found, discoverer, media) VALUES (%s, %s, %s, %s, NOW(), %s, %s)", [feed.media.url, globals.SERVICE_MAL, feed.media.name, image, user.name, media])
+                                    globals.conn.commit()
+                                else: image = data_img[0]
+                                feed.media.image = image
+
+                                cursor.execute("UPDATE t_feeds SET obsolete=1 WHERE published=%s AND title=%s AND user=%s AND service=%s", [pubDate, feed.media.name, user.name, globals.SERVICE_MAL])
+                                cursor.execute("INSERT INTO t_feeds (published, title, service, url, user, found, type) VALUES (%s, %s, %s, %s, %s, NOW(), %s)", (pubDate, feed.media.name, globals.SERVICE_MAL, feed.media.url, user.name, feed.get_status_str()))
+                                globals.conn.commit()
+                                
+                                for server in user.servers:
+                                    db_srv = globals.conn.cursor(buffered=True)
+                                    db_srv.execute("SELECT channel FROM t_servers WHERE server = %s", [server])
+                                    data_channel = db_srv.fetchone()
+                                    
+                                    while data_channel is not None:
+                                        for channel in data_channel: await send_embed_wrapper(asyncioloop, channel, globals.client, build_embed(feed))
+                                        
+                                        data_channel = db_srv.fetchone()
+                    if feed_type == 1:
+                        feed_type = 0
+                        await asyncio.sleep(globals.MYANIMELIST_SECONDS_BETWEEN_REQUESTS)
+                    else:
+                        stop_boucle = 1
+                    
+            except Exception as e:
+                globals.logger.exception("Error when parsing RSS for '{}':\n".format(user.name))
+            
+            await asyncio.sleep(globals.MYANIMELIST_SECONDS_BETWEEN_REQUESTS)
+
+            data_user = db_user.fetchone()
 
 
 async def fetch_activities_anilist():
-	await anilist.check_new_activities()
+    await anilist.check_new_activities()
 
 
 # Get a random anime name and change the bot's activity
 async def change_gameplayed(asyncioloop):
-	globals.logger.info("Starting up change_gameplayed")
-	
-	await globals.client.wait_until_ready()
-	await asyncio.sleep(1)
-
-	while not globals.client.is_closed():
-		# Get a random anime name from the users' list
-		cursor = globals.conn.cursor(buffered=True)
-		cursor.execute("SELECT title FROM t_animes ORDER BY RAND() LIMIT 1")
-		data = cursor.fetchone()
-		anime = utils.truncate_end_show(data[0])
-		
-		# Try to change the bot's activity
-		try:
-			if data is not None: await globals.client.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name=anime))
-		except Exception as e:
-			globals.logger.warning("An error occured while changing the displayed anime title: " + str(e))
-			
-		cursor.close()
-		# Do it every minute
-		await asyncio.sleep(60)
+    globals.logger.info("Starting up change_gameplayed")
+    
+    await globals.client.wait_until_ready()
+    await asyncio.sleep(1)
+
+    while not globals.client.is_closed():
+        # Get a random anime name from the users' list
+        cursor = globals.conn.cursor(buffered=True)
+        cursor.execute("SELECT title FROM t_animes ORDER BY RAND() LIMIT 1")
+        data = cursor.fetchone()
+        anime = utils.truncate_end_show(data[0])
+        
+        # Try to change the bot's activity
+        try:
+            if data is not None: await globals.client.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name=anime))
+        except Exception as e:
+            globals.logger.warning("An error occured while changing the displayed anime title: " + str(e))
+            
+        cursor.close()
+        # Do it every minute
+        await asyncio.sleep(60)
 
 async def update_thumbnail_catalog(asyncioloop):
-	globals.logger.info("Starting up update_thumbnail_catalog")
-	
-	while not globals.client.is_closed():
-		await asyncio.sleep(43200)
-		
-		globals.logger.info("Automatic check of the thumbnail database on going...")
-		reload = 0
-		
-		cursor = globals.conn.cursor(buffered=True)
-		cursor.execute("SELECT guid, title, thumbnail FROM t_animes")
-		data = cursor.fetchone()
-
-		while data is not None:
-			try:
-				if (data[2] != "") : urllib.request.urlopen(data[2])
-				else: reload = 1
-			except urllib.error.HTTPError as e:
-				globals.logger.warning("HTTP Error while getting the current thumbnail of '" + str(data[1]) + "': " + str(e))
-				reload = 1
-			except Exception as e:
-				globals.logger.debug("Error while getting the current thumbnail of '" + str(data[1]) + "': " + str(e))
-			
-			if (reload == 1) :
-				try:
-					image = myanimelist.get_thumbnail(data[0])
-						
-					cursor.execute("UPDATE t_animes SET thumbnail = %s WHERE guid = %s", [image, data[0]])
-					globals.conn.commit()
-						
-					globals.logger.info("Updated thumbnail found for \"" + str(data[1]) + "\": %s", image)
-				except Exception as e:
-					globals.logger.warning("Error while downloading updated thumbnail for '" + str(data[1]) + "': " + str(e))
-
-			await asyncio.sleep(3)
-			data = cursor.fetchone()
-
-		cursor.close()
-
-		globals.logger.info("Thumbnail database checked.")
+    globals.logger.info("Starting up update_thumbnail_catalog")
+    
+    while not globals.client.is_closed():
+        await asyncio.sleep(43200)
+        
+        globals.logger.info("Automatic check of the thumbnail database on going...")
+        reload = 0
+        
+        cursor = globals.conn.cursor(buffered=True)
+        cursor.execute("SELECT guid, title, thumbnail FROM t_animes")
+        data = cursor.fetchone()
+
+        while data is not None:
+            try:
+                if (data[2] != "") : urllib.request.urlopen(data[2])
+                else: reload = 1
+            except urllib.error.HTTPError as e:
+                globals.logger.warning("HTTP Error while getting the current thumbnail of '" + str(data[1]) + "': " + str(e))
+                reload = 1
+            except Exception as e:
+                globals.logger.debug("Error while getting the current thumbnail of '" + str(data[1]) + "': " + str(e))
+            
+            if (reload == 1) :
+                try:
+                    image = myanimelist.get_thumbnail(data[0])
+                        
+                    cursor.execute("UPDATE t_animes SET thumbnail = %s WHERE guid = %s", [image, data[0]])
+                    globals.conn.commit()
+                        
+                    globals.logger.info("Updated thumbnail found for \"" + str(data[1]) + "\": %s", image)
+                except Exception as e:
+                    globals.logger.warning("Error while downloading updated thumbnail for '" + str(data[1]) + "': " + str(e))
+
+            await asyncio.sleep(3)
+            data = cursor.fetchone()
+
+        cursor.close()
+
+        globals.logger.info("Thumbnail database checked.")