diff --git a/README.md b/README.md index fda6a41..293b7bc 100644 --- a/README.md +++ b/README.md @@ -15,11 +15,15 @@
-![](chat_record1.gif) +![](assets/chat_record1.gif)
-![](rank_record.gif) +![](assets/rank_record.gif) + +
+ +![](assets/osu_record.gif)
@@ -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