diff --git a/README.md b/README.md
index fda6a41..293b7bc 100644
--- a/README.md
+++ b/README.md
@@ -15,11 +15,15 @@
-
+
-
+
+
+
+
+
@@ -54,6 +58,13 @@ $rank {lol_username}
```
This command will display a message with the current League of Legend rank of the EUW account you ask for. Make sure to use quotes if there is spaces in the LoL username.
+
+### **osu_profile**
+```
+$osu_profile {osu_username}
+```
+This command will display a message with all the (basics) stats from the Osu! profile you ask for.
+
# ⚙ Configuration
diff --git a/chat_record1.gif b/assets/chat_record1.gif
similarity index 100%
rename from chat_record1.gif
rename to assets/chat_record1.gif
diff --git a/issou.mp3 b/assets/issou.mp3
similarity index 100%
rename from issou.mp3
rename to assets/issou.mp3
diff --git a/assets/osu_record.gif b/assets/osu_record.gif
new file mode 100644
index 0000000..b75cda6
Binary files /dev/null and b/assets/osu_record.gif differ
diff --git a/rank_record.gif b/assets/rank_record.gif
similarity index 100%
rename from rank_record.gif
rename to assets/rank_record.gif
diff --git a/main.py b/python/main.py
similarity index 65%
rename from main.py
rename to python/main.py
index f86e8eb..667bbdd 100644
--- a/main.py
+++ b/python/main.py
@@ -1,166 +1,196 @@
-import asyncio
-import socket
-import re
-import discord
-from private import *
-from discord.ext import tasks, commands
-from riot_api import rank_track, WATCHER, REGION
-from riotwatcher import ApiError
-from emoji import demojize
-from twitch import TwitchClient
-
-bot = commands.Bot(command_prefix='$')
-twitch_client = TwitchClient(client_id=ID_TWITCH, oauth_token=TOKEN_TWITCH)
-chats = dict()
-
-
-class ChatObj:
- def __init__(self, twitch_user, discord_channel):
- self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- self.twitch_user = twitch_user
- self.discord_channel = discord_channel
- chats[discord_channel] = self
-
- def chat_init(self):
- try:
- self.sock.connect((SERVER, PORT))
- self.sock.send(f"PASS {TOKEN_TWITCH}\n".encode('utf-8'))
- self.sock.send(f"NICK {NICKNAME}\n".encode('utf-8'))
- self.sock.send(f"JOIN {'#' + self.twitch_user}\n".encode('utf-8'))
- self.sock.settimeout(0.0)
- self.sock.setblocking(False)
- return 1
- except OSError:
- return 0
-
- @tasks.loop(seconds=1)
- async def twitch(self):
- await bot.wait_until_ready()
- try:
- resp = self.sock.recv(2048).decode('utf-8')
- except socket.error:
- resp = ''
-
- if resp.startswith('PING'):
- self.sock.send("PONG\n".encode('utf-8'))
-
- elif len(resp) > 0:
- try:
- chain = re.search(r':(.*)\!.*@.*\.tmi\.twitch\.tv PRIVMSG #(.*) :(.*)', demojize(resp))
- username = chain.group(1)
- message = chain.group(3)
- msg = f"**__{username}__ :** {message}"
- await self.discord_channel.send(msg)
- except discord.DiscordException:
- pass
- except AttributeError:
- pass
-
- @twitch.after_loop
- async def after_twitch(self):
- self.sock.shutdown(1)
- try:
- self.sock.close()
- except OSError:
- pass
-
-
-def check_user(name):
- user = twitch_client.users.translate_usernames_to_ids([name])
- if not user:
- return False
- return True
-
-
-async def del_message(ctx):
- try:
- await ctx.message.delete()
- except discord.errors.Forbidden:
- pass
-
-
-@bot.event
-async def on_ready():
- default_activity = discord.Activity(type=discord.ActivityType.listening, name="$help")
- await bot.change_presence(activity=default_activity)
- print('We have logged in as {0.user}'.format(bot))
-
-
-@bot.command()
-async def chat_set(ctx, arg1):
- await del_message(ctx)
- what_channel = ctx.channel
- if what_channel in list(chats):
- await ctx.send("```A chat is already active, you have to stop it before with the cmd $chat_stop !```")
- else:
- if check_user(arg1):
- obj = ChatObj(arg1, what_channel)
- if obj.chat_init():
- await ctx.send(f'```Now connected to {arg1}\'s twitch channel !```')
- obj.twitch.start()
- else:
- await ctx.send('```Something went wrong when trying to access Twitch IRC.```')
- else:
- await ctx.send('```This twitch channel doesn\'t seems to exist.```')
-
-
-@bot.command()
-async def chat_stop(ctx):
- await del_message(ctx)
- chan = ctx.channel
- if chan in list(chats):
- chats[chan].twitch.stop()
- del chats[chan]
- await asyncio.sleep(1)
- message = '```The chat was successfully stopped !```'
- else:
- message = '```There is no active chat in this channel.```'
- await ctx.send(message)
-
-
-@bot.command()
-async def rank(ctx, arg, argf=None):
- await del_message(ctx)
- if argf is None:
- try:
- player = WATCHER.summoner.by_name(REGION, arg)
- ranks = rank_track(player)
- embed = discord.Embed(title=arg, url="https://www.youtube.com/watch?v=dQw4w9WgXcQ")
- embed.set_thumbnail(url="http://ddragon.leagueoflegends.com/cdn/11.2.1/img/profileicon/" + str(
- player['profileIconId']) + ".png")
- if isinstance(ranks, list):
- for rank_s in ranks:
- embed.add_field(name=rank_s[0], value=str(rank_s[1]) + ' ' + str(rank_s[2]) + ' ' + str(
- rank_s[3]) + ' LP' + '\n' + str(rank_s[4]) + 'W/' + str(rank_s[5]) + 'L', inline=False)
- else:
- embed.description = ranks
- await ctx.send(embed=embed)
- except ApiError:
- await ctx.send("The nickname is unknown.")
- else:
- await ctx.send("If you are trying to use a nickname with spaces, please surround it with quotes.")
-
-
-@bot.command()
-async def issou(ctx, arg1: discord.User = None):
- if arg1 is not None:
- user = arg1
- else:
- user = ctx.message.author
- await del_message(ctx)
- try:
- voice_channel = user.voice.channel
- except AttributeError:
- voice_channel = None
-
- if voice_channel is not None:
- voice = await voice_channel.connect()
- voice.play(discord.FFmpegPCMAudio('issou.mp3'))
- if voice.is_playing():
- await asyncio.sleep(1)
- await voice.disconnect()
- else:
- await ctx.send('You or the targeted person are not connected to any channel.')
-
-
-bot.run(TOKEN_BOT)
+import asyncio
+import socket
+import re
+import discord
+from private import *
+from discord.ext import tasks, commands
+from riot_api import rank_track, WATCHER, REGION
+from riotwatcher import ApiError
+from emoji import demojize
+from twitch import TwitchClient
+from osu_api import ask_osu
+
+bot = commands.Bot(command_prefix='$')
+twitch_client = TwitchClient(client_id=ID_TWITCH, oauth_token=TOKEN_TWITCH)
+chats = dict()
+
+
+class ChatObj:
+ def __init__(self, twitch_user, discord_channel):
+ self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ self.twitch_user = twitch_user
+ self.discord_channel = discord_channel
+ chats[discord_channel] = self
+
+ def chat_init(self):
+ try:
+ self.sock.connect((SERVER, PORT))
+ self.sock.send(f'PASS {TOKEN_TWITCH}\n'.encode('utf-8'))
+ self.sock.send(f'NICK {NICKNAME}\n'.encode('utf-8'))
+ self.sock.send(f"JOIN {'#' + self.twitch_user}\n".encode('utf-8'))
+ self.sock.settimeout(0.0)
+ self.sock.setblocking(False)
+ return 1
+ except OSError:
+ return 0
+
+ @tasks.loop(seconds=1)
+ async def twitch(self):
+ await bot.wait_until_ready()
+ try:
+ resp = self.sock.recv(2048).decode('utf-8')
+ except socket.error:
+ resp = ''
+
+ if resp.startswith('PING'):
+ self.sock.send('PONG\n'.encode('utf-8'))
+
+ elif len(resp) > 0:
+ try:
+ chain = re.search(r':(.*)\!.*@.*\.tmi\.twitch\.tv PRIVMSG #(.*) :(.*)', demojize(resp))
+ username = chain.group(1)
+ message = chain.group(3)
+ msg = f'**__{username}__ :** {message}'
+ await self.discord_channel.send(msg)
+ except discord.DiscordException:
+ pass
+ except AttributeError:
+ pass
+
+ @twitch.after_loop
+ async def after_twitch(self):
+ self.sock.shutdown(1)
+ try:
+ self.sock.close()
+ except OSError:
+ pass
+
+
+def check_user(name):
+ user = twitch_client.users.translate_usernames_to_ids([name])
+ if not user:
+ return False
+ return True
+
+
+async def del_message(ctx):
+ try:
+ await ctx.message.delete()
+ except discord.errors.Forbidden:
+ pass
+
+
+@bot.event
+async def on_ready():
+ default_activity = discord.Activity(type=discord.ActivityType.listening, name='$help')
+ await bot.change_presence(activity=default_activity)
+ print('We have logged in as {0.user}'.format(bot))
+
+
+@bot.command()
+async def chat_set(ctx, arg1):
+ await del_message(ctx)
+ what_channel = ctx.channel
+ if what_channel in list(chats):
+ await ctx.send("```A chat is already active, you have to stop it before with the cmd $chat_stop !```")
+ else:
+ if check_user(arg1):
+ obj = ChatObj(arg1, what_channel)
+ if obj.chat_init():
+ await ctx.send(f'```Now connected to {arg1}\'s twitch channel !```')
+ obj.twitch.start()
+ else:
+ await ctx.send('```Something went wrong when trying to access Twitch IRC.```')
+ else:
+ await ctx.send('```This twitch channel doesn\'t seems to exist.```')
+
+
+@bot.command()
+async def chat_stop(ctx):
+ await del_message(ctx)
+ chan = ctx.channel
+ if chan in list(chats):
+ chats[chan].twitch.stop()
+ del chats[chan]
+ await asyncio.sleep(1)
+ message = '```The chat was successfully stopped !```'
+ else:
+ message = '```There is no active chat in this channel.```'
+ await ctx.send(message)
+
+
+@bot.command()
+async def rank(ctx, arg, argf=None):
+ await del_message(ctx)
+ if argf is None:
+ try:
+ player = WATCHER.summoner.by_name(REGION, arg)
+ ranks = rank_track(player)
+ embed = discord.Embed(title=arg, url='https://www.youtube.com/watch?v=dQw4w9WgXcQ')
+ embed.set_thumbnail(url='http://ddragon.leagueoflegends.com/cdn/11.2.1/img/profileicon/' + str(
+ player['profileIconId']) + '.png')
+ embed.set_author(name='League Of Legend', url='https://euw.leagueoflegends.com/en-gb/',
+ icon_url='https://static.wikia.nocookie.net/leagueoflegends/images/0/07/' +
+ 'League_of_Legends_icon.png/revision/latest?cb=20191018194326')
+ if isinstance(ranks, list):
+ for rank_s in ranks:
+ embed.add_field(name=rank_s[0], value=str(rank_s[1]) + ' ' + str(rank_s[2]) + ' ' + str(
+ rank_s[3]) + ' LP' + '\n' + str(rank_s[4]) + 'W/' + str(rank_s[5]) + 'L', inline=False)
+ else:
+ embed.description = ranks
+ await ctx.send(embed=embed)
+ except ApiError:
+ await ctx.send('The username you entered is unknown.')
+ else:
+ await ctx.send('If you are trying to use a username you entered with spaces, please surround it with quotes.')
+
+
+@bot.command()
+async def issou(ctx, arg1: discord.User = None):
+ if arg1 is not None:
+ user = arg1
+ else:
+ user = ctx.message.author
+ await del_message(ctx)
+ try:
+ voice_channel = user.voice.channel
+ except AttributeError:
+ voice_channel = None
+
+ if voice_channel is not None:
+ voice = await voice_channel.connect()
+ voice.play(discord.FFmpegPCMAudio('../assets/issou.mp3'))
+ if voice.is_playing():
+ await asyncio.sleep(1)
+ await voice.disconnect()
+ else:
+ await ctx.send('You or the targeted person are not connected to any channel.')
+
+
+@bot.command()
+async def osu_profile(ctx, arg):
+ await del_message(ctx)
+ lst = await ask_osu(arg)
+ if lst == 1:
+ await ctx.send('The username you entered is unknown.')
+ else:
+ embed = discord.Embed(title=arg, url='https://osu.ppy.sh/users/' + str(lst[0]))
+ embed.set_thumbnail(url='https://a.ppy.sh/' + str(lst[0]))
+ embed.set_author(name='Osu!', url='https://osu.ppy.sh/home',
+ icon_url=r'https://upload.wikimedia.org/wikipedia/commons/4/44/Osu%21Logo_%282019%29.png')
+ embed.add_field(name='Global Ranking', value='#'+str('{:,}'.format(lst[8])))
+ embed.add_field(name='Total Play Time', value=
+ str("%.0f" % ((lst[6] % (86400 * 30)) / 86400))+'d '+
+ str("%.0f" % ((lst[6] % 86400) / 3600))+'h '+
+ str("%.0f" % ((lst[6] % 3600) / 60))+'m ')
+ embed.add_field(name='Level', value=str("%.0f" % lst[7]))
+ embed.add_field(name='Ranked Score', value=str('{:,}'.format(lst[1])))
+ embed.add_field(name='Hit Accuracy', value=str("%.2f" % lst[2])+'%')
+ embed.add_field(name='Play Count', value=str('{:,}'.format(lst[3])))
+ embed.add_field(name='Total Score', value=str('{:,}'.format(lst[4])))
+ embed.add_field(name='Total Hits', value=str('{:,}'.format(lst[5])))
+
+ await ctx.send(embed=embed)
+
+
+bot.run(TOKEN_BOT)
diff --git a/python/osu_api.py b/python/osu_api.py
new file mode 100644
index 0000000..3490486
--- /dev/null
+++ b/python/osu_api.py
@@ -0,0 +1,15 @@
+from osuapi import OsuApi, ReqConnector
+from private import TOKEN_OSU
+import requests
+
+api = OsuApi(TOKEN_OSU, connector=ReqConnector())
+
+async def ask_osu(username):
+ results = api.get_user(username)
+ if not results:
+ return 1
+ r = results[0]
+ liste = [r.user_id, r.ranked_score, r.accuracy, r.playcount,
+ r.total_score, (r.count300 + r.count100 + r.count50),
+ r.total_seconds_played, r.level, r.pp_rank]
+ return liste
diff --git a/riot_api.py b/python/riot_api.py
similarity index 97%
rename from riot_api.py
rename to python/riot_api.py
index 11eb05c..c72e7f4 100644
--- a/riot_api.py
+++ b/python/riot_api.py
@@ -1,21 +1,21 @@
-from riotwatcher import LolWatcher
-from private import TOKEN_RIOT
-
-WATCHER = LolWatcher(TOKEN_RIOT)
-REGION = 'EUW1'
-
-def rank_track(player):
- '''function that communicate with Riot API'''
- ranked_stats = WATCHER.league.by_summoner(REGION, player['id'])
-
- if not ranked_stats:
- return 'Unranked cette saison.'
-
- liste = []
- for infos in ranked_stats:
- if infos['queueType'] == 'RANKED_SOLO_5x5':
- what_rank = 'Solo Queue'
- elif infos['queueType'] == 'RANKED_FLEX_SR':
- what_rank = 'Flexible'
- liste.append([what_rank, infos['tier'], infos['rank'], infos['leaguePoints'], infos['wins'], infos['losses']])
- return liste
+from riotwatcher import LolWatcher
+from private import TOKEN_RIOT
+
+WATCHER = LolWatcher(TOKEN_RIOT)
+REGION = 'EUW1'
+
+def rank_track(player):
+ '''function that communicate with Riot API'''
+ ranked_stats = WATCHER.league.by_summoner(REGION, player['id'])
+
+ if not ranked_stats:
+ return 'Unranked cette saison.'
+
+ liste = []
+ for infos in ranked_stats:
+ if infos['queueType'] == 'RANKED_SOLO_5x5':
+ what_rank = 'Solo Queue'
+ elif infos['queueType'] == 'RANKED_FLEX_SR':
+ what_rank = 'Flexible'
+ liste.append([what_rank, infos['tier'], infos['rank'], infos['leaguePoints'], infos['wins'], infos['losses']])
+ return liste