From fc56adaaa725005203b87a53dcc49c556fad8817 Mon Sep 17 00:00:00 2001 From: Raatty Date: Sat, 7 Jul 2018 23:25:54 +1200 Subject: [PATCH] first public commit --- .drone.yml | 11 ++ .gitignore | 3 + Dockerfile | 5 + Procfile | 1 + bot.py | 53 +++++++++ bot_commands.py | 304 +++++++++++++++++++++++++++++++++++++++++++++++ discordinfo.py | 47 ++++++++ dogs.py | 67 +++++++++++ repl.py | 190 +++++++++++++++++++++++++++++ requirements.txt | 3 + rs_emojis.json | 30 +++++ runescape.py | 118 ++++++++++++++++++ runtime.txt | 1 + 13 files changed, 833 insertions(+) create mode 100644 .drone.yml create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 Procfile create mode 100644 bot.py create mode 100644 bot_commands.py create mode 100644 discordinfo.py create mode 100644 dogs.py create mode 100644 repl.py create mode 100644 requirements.txt create mode 100644 rs_emojis.json create mode 100644 runescape.py create mode 100644 runtime.txt diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..e713ea7 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,11 @@ +platform: linux/arm32v6 +clone: + git: + image: "arm32v6local:dronegit" +pipeline: + build: + image: arm32v6/python:3.6-alpine3.6 + commands: + - pip3 install -r requirements.txt + - pip3 install pycodestyle + - python3 -m pycodestyle . \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b11dc48 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +__pycache__ +b64.txt +.env diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..f9ddccb --- /dev/null +++ b/Dockerfile @@ -0,0 +1,5 @@ +FROM arm32v6/python:3.6.4-alpine3.7 +COPY . /code +WORKDIR /code +RUN pip install -Ur requirements.txt +CMD [ "python3", "bot.py" ] \ No newline at end of file diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..29cff6d --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +worker: python bot.py diff --git a/bot.py b/bot.py new file mode 100644 index 0000000..2bf2c46 --- /dev/null +++ b/bot.py @@ -0,0 +1,53 @@ +import logging +import os +import discord +from discord.ext import commands +import datetime + +logging.basicConfig(level=logging.INFO, style='{', datefmt="%d.%m.%Y %H:%M:%S", + format="{asctime} - {levelname} - {name} - {message}") + +bot = commands.Bot(description="🧀 Accepting Cheese!!! 🧀", command_prefix='&') + + +@bot.command(pass_context=True) +async def load(ctx, module): + if ctx.message.author.id == '140652945032216576': + bot.load_extension(module) + await bot.say('{} loaded'.format(module)) + + +@bot.command(pass_context=True) +async def unload(ctx, module): + if ctx.message.author.id == '140652945032216576': + bot.unload_extension(module) + await bot.say('{} unloaded'.format(module)) + + +@bot.command(pass_context=True) +async def reload(ctx, module): + if ctx.message.author.id == '140652945032216576': + bot.load_extension(module) + bot.unload_extension(module) + await bot.say('{} reloaded'.format(module)) + + +@bot.event +async def on_ready(): + bot.load_extension("repl") + bot.load_extension("runescape") + bot.load_extension("dogs") + bot.load_extension("bot_commands") + bot.load_extension('discordinfo') + await bot.change_presence(game=discord.Game(name='CHEESE', type=2)) + await bot.send_message(discord.Object(id="408902143119196161"), + "**Im ready!** " + str(datetime.datetime.now())) + + +@bot.event +async def on_message(message): + if message.server.get_member('140652945032216576') in message.mentions: + await bot.add_reaction(message, '🐀') + await bot.process_commands(message) + +bot.run(os.getenv('TOKEN')) diff --git a/bot_commands.py b/bot_commands.py new file mode 100644 index 0000000..092e441 --- /dev/null +++ b/bot_commands.py @@ -0,0 +1,304 @@ +import discord +from discord.ext import commands +import random +import os +from datetime import datetime +import requests +import wikia +import base64 +import aiohttp +import runescapeapi + + +class bots_commands: + def __init__(self, bot: commands.Bot): + self.bot = bot + self.picked_wikis = {} + + @commands.command(pass_context=True) + async def ping(self, ctx): + """bot replys with pong""" + now = ctx.message.timestamp + msg = await self.bot.say("Pong! 🏓") + msg_timestamp = msg.timestamp + sub = msg_timestamp - now + await self.bot.edit_message(msg, new_content="Pong! 🏓 **took {}ms**" + .format(sub.total_seconds()*1000)) + + @commands.command(pass_context=True) + async def say(self, ctx, *, something): + """bot echos what you say then deletes your message""" + await self.bot.say("**{ctx.message.author} said:** {something}") + await self.bot.delete_message(ctx.message) + + @commands.command(pass_context=True) + async def am_i_cool(self, ctx): + """decides whether ur cool or not""" + mention = ctx.message.author.mention + if ctx.message.author.id == "140652945032216576": + await self.bot.say(f"yes you are {mention}") + else: + n = random.randint(0, 1) + if n == 1: + await self.bot.say("only my master is cool") + else: + await self.bot.say(f"i guess ill let you be cool this time \ + {mention}") + + @commands.command(pass_context=True) + async def echo(self, ctx, *, something): + """bot echos what you say""" + await self.bot.say("{}".format(something)) + + @commands.cooldown(rate=3, per=300, type=commands.BucketType.channel) + @commands.command(pass_context=True) + async def spam(self, ctx, n, *, something): + """&spam number message, max 20""" + if int(n) > 10: + await self.bot.say("not aloud") + else: + times = int(n) - 1 + while (times >= 0): + await self.bot.say("{}".format(something)) + times = times - 1 + + @commands.command(pass_context=True) + async def embed(self, ctx, *, message): + """bot says what you type in embeded text""" + em = discord.Embed(title=str(ctx.message.author), description=message, + colour=discord.Colour.green()) + await self.bot.say(embed=em) + + @commands.command(name='8ball') + async def eight_ball(self, *, quest=None): + responses = ['🧀The cheese says it is certain', + '🧀The cheese says it is decidedly so', + '🧀The cheese says without a doubt', + '🧀The cheese says yes definitely', + '🧀The cheese says you may rely on it', + '🧀The cheese says as I see it, yes', + '🧀The cheese says most likely', + '🧀The cheese says outlook good', + '🧀The cheese says yes', + '🧀The cheese says sighns point to yes', + '🧀The cheese says reply hazy try again', + '🧀The cheese says ask again later', + '🧀The cheese says better not tell you now', + '🧀The cheese says cannot predict now', + '🧀The cheese says concentrate and ask again', + '🧀The cheese says don\'t count on it', + '🧀The cheese says my reply is no', + '🧀The cheese says my sources say no', + '🧀The cheese says outlook not so good', + '🧀The cheese says very doubtful'] + if quest is None: + await self.bot.say('Ask me a question noob!') + else: + await self.bot.say(random.choice(responses)) + + @commands.command(pass_context=True, aliases=['crc']) + async def cat_rat_cheese(self, ctx): + msg = await self.bot.say('react with your choice, ' + 'wait for the 3 reactions to load tho') + await self.bot.add_reaction(msg, '🐀') + await self.bot.add_reaction(msg, '🧀') + await self.bot.add_reaction(msg, '🐱') + bot_score = 0 + usr_score = 0 + author = ctx.message.author + while True: + scorestr = f'your score: {usr_score} my score: {bot_score}\n' + if bot_score == 3 or usr_score == 3: + if usr_score > bot_score: + await self.bot.edit_message(msg, scorestr + + 'you won best out of 3') + break + else: + await self.bot.edit_message(msg, scorestr + + 'bot won best out of 3') + break + response = await self.bot.wait_for_reaction( + emoji=['🐀', '🧀', '🐱'], user=author, timeout=10, message=msg) + bot_choice = random.choice(['🐀', '🧀', '🐱']) + + try: + response = response.reaction.emoji + if response == bot_choice: + await self.bot.edit_message(msg, scorestr + 'draw') + await self.bot.remove_reaction(msg, response, author) + continue + elif response == '🐀': + if bot_choice == '🧀': + usr_score = usr_score + 1 + message = 'bot picked 🧀 your rat eats ' \ + 'the cheese and you win' + await self.bot.edit_message(msg, scorestr + message) + await self.bot.remove_reaction(msg, '🐀', author) + continue + else: + bot_score = bot_score + 1 + message = 'bot picked 🐱 my cat eats your rat and i win' + await self.bot.edit_message(msg, scorestr + message) + await self.bot.remove_reaction(msg, '🐀', author) + continue + elif response == '🧀': + if bot_choice == '🐀': + bot_score = bot_score + 1 + message = 'bot picked 🐀 bots rat eats the cheese ' \ + 'and u lose' + await self.bot.edit_message(msg, scorestr + message) + await self.bot.remove_reaction(msg, '🧀', author) + continue + else: + usr_score = usr_score + 1 + message = 'bot picked 🐱 bots cat eats your cheese ' \ + 'but its poisonous so you win' + await self.bot.edit_message(msg, scorestr + message) + await self.bot.remove_reaction(msg, '🧀', author) + continue + elif response == '🐱': + if bot_choice == '🐀': + usr_score = usr_score + 1 + message = 'bot picked 🐀 your cat eats the rat so ' \ + 'you win' + await self.bot.edit_message(msg, scorestr + message) + await self.bot.remove_reaction(msg, '🐱', author) + continue + else: + bot_score = bot_score + 1 + message = 'bot picked 🧀 your cat eats the cheese ' \ + 'but gets poisoned and dies i win' + await self.bot.edit_message(msg, scorestr + message) + await self.bot.remove_reaction(msg, '🐱', author) + continue + except AttributeError: + await self.bot.edit_message(msg, 'too slow') + break + + @commands.group() + async def invite(self): + pass + + @commands.has_permissions(administrator=True) + @invite.command(pass_context=True) + async def temp(self, ctx): + inv = await self.bot.create_invite(ctx.message.channel, max_age=600, + max_uses=1, temporary=True, + unique=True) + await self.bot.say(inv) + + @commands.has_permissions(administrator=True) + @invite.command(pass_context=True) + async def perm(self, ctx): + inv = await self.bot.create_invite(ctx.message.channel, max_age=600, + max_uses=1, temporary=False, + unique=True) + await self.bot.say(inv) + + class patched_wikia(runescapeapi.runescapeapi._Wikia): + def isearch(self, searchTerm: str): + ''' + returns a generator that iterates though + the search results pages + ''' + for i in wikia.search(self.wiki, searchTerm): + if not i.startswith('Transcript'): + yield wikia.page(self.wiki, i) + + # wikia stuffs + @commands.group(pass_context=True) + async def wikia(self, ctx): + pass + + @wikia.command(pass_context=True) + async def setwiki(self, ctx, wiki): + self.picked_wikis[ctx.message.author.id] = wiki + await self.bot.say('Successfully set your current wikia to: ' + f'**{wiki}**') + + @wikia.command(pass_context=True) + async def search(self, ctx, *, query): + try: + s = self.patched_wikia(self.picked_wikis[ctx.message.author.id]) \ + .isearch(query) + + def next_page(page): + em = discord.Embed(title=page.title, description=page.summary, + url=page.url.replace(' ', '_')) + if page.images != []: + em.set_image(url=page.images[0]) + return em + + msg = await self.bot.say(embed=next_page(next(s))) + await self.bot.add_reaction(msg, '▶') + while True: + try: + await self.bot.wait_for_reaction(emoji='▶', + user=ctx.message.author) + await self.bot.remove_reaction(msg, '▶', + ctx.message.author) + await self.bot.edit_message(msg, embed=next_page(next(s))) + except StopIteration: + await self.bot.say('Thats all the results') + break + except KeyError: + err_msg = 'Please set your current wikia using: ' \ + '&wikia setwiki ' \ + '' + await self.bot.say(err_msg) + + @wikia.command(pass_context=True) + async def page(self, ctx, *, query): + try: + q = wikia.page(self.picked_wikis[ctx.message.author.id], query) + em = discord.Embed(title=q.title, description=q.summary, + url=q.url.replace(' ', '_')) + if q.images != []: + em.set_image(url=q.images[0]) + await self.bot.say(embed=em) + except KeyError: + err_msg = 'Please set your current wikia using: ' \ + '&wikia setwiki ' \ + '' + await self.bot.say(err_msg) + + @commands.command(pass_context=True) + async def b64(self, ctx: commands.context, *, text=None): + if text is None: + url = ctx.message.attachments[0]['url'] + async with aiohttp.ClientSession() as session: + async with session.get(url) as r: + print(dir(r)) + image = await r.read() + with open('b64.txt', 'wb') as file: + file.write(base64.b64encode(image)) + file.close() + await self.bot.upload('b64.txt') + else: + await self.bot.say(base64.b64encode(text.encode('utf-8')) + .decode('utf-8')) + + @commands.command(pass_context=True) + async def shutup(self, ctx): + def check(msg): + return msg.author.id == '388859625585508376' + await self.bot.purge_from(ctx.message.channel, check=check) + await self.bot.say('**:(**') + + @commands.command(pass_context=True) + async def shell(self, ctx, *, command): + if ctx.message.author.id == '140652945032216576': + pag = commands.Paginator() + out = os.popen(command).read().split('\n') + for i in out: + try: + pag.add_line(line=i) + except RuntimeError: + pag.close_page() + pag.add_line(line=i) + for i in pag.pages: + await self.bot.say(i) + + +def setup(bot): + bot.add_cog(bots_commands(bot)) diff --git a/discordinfo.py b/discordinfo.py new file mode 100644 index 0000000..9699338 --- /dev/null +++ b/discordinfo.py @@ -0,0 +1,47 @@ +import discord +from discord.ext import commands + + +class discordinfo: + def __init__(self, bot): + self.bot = bot + + @commands.command(pass_context=True) + async def user(self, ctx): + em = discord.Embed(title=f"**{ctx.message.author}**", + color=discord.Color(4359924)) + em.set_thumbnail(url=ctx.message.author.avatar_url) + em.add_field(value=[i.name for i in ctx.message.author.roles + if i.name != '@everyone'], name='Roles') + await self.bot.say(embed=em) + + @commands.group(pass_context=True) + async def server(self, ctx): + if ctx.invoked_subcommand is None: + out = f'{ctx.message.server.name}\n' + humans = {"online": 0, "offline": 0, "idle": 0, "dnd": 0} + bots = {"online": 0, "offline": 0, "idle": 0, "dnd": 0} + for m in ctx.message.server.members: + if m.bot: + bots[str(m.status)] = bots[str(m.status)] + 1 + else: + humans[str(m.status)] = humans[str(m.status)] + 1 + out += f'**Bots**: {bots["online"]}**online**, ' \ + f'{bots["offline"]}**offline**, {bots["idle"]}**idle**, ' \ + f'{bots["dnd"]}**dnd**\n' \ + f'**Humans**: {humans["online"]}**online**, ' \ + f'{humans["offline"]}**offline**, ' \ + f'{humans["idle"]}**idle**, {humans["dnd"]}**dnd**\n' + await self.bot.say(out) + + @server.command(pass_context=True) + async def roles(self, ctx): + out = f'**{ctx.message.server.name}, roles**\n' + for r in ctx.message.server.roles: + if r.name != '@everyone': + out = out + f'**{r.name}**: {r.id}\n' + await self.bot.say(out) + + +def setup(bot): + bot.add_cog(discordinfo(bot)) diff --git a/dogs.py b/dogs.py new file mode 100644 index 0000000..1fccb1d --- /dev/null +++ b/dogs.py @@ -0,0 +1,67 @@ +import discord +from discord.ext import commands +import requests +import aiohttp + +import random +import asyncio + +durls = {"random": "https://dog.ceo/api/breeds/image/random", + "list": "https://dog.ceo/api/breeds/list", + "breed": "https://dog.ceo/api/breed/{}/images/random"} + + +class wp: + @staticmethod + async def jsondecoder(url, req): + req = req.replace(' ', '%20') + url = url.format(req) + async with aiohttp.ClientSession() as session: + async with session.get(url) as r: + if r.status == 200: + return await r.json() + + +class dogs: + def __init__(self, bot, breeds): + self.bot = bot + self.bot.breeds = breeds + + @commands.command() + async def pug(self): + '''generates a random pug''' + em = discord.Embed(color=discord.Color(value=random.randint(000000, + 999999))) + p = await wp.jsondecoder(durls["breed"], "pug") + em.set_image(url=p["message"]) + await self.bot.say(embed=em) + + @commands.command() + async def dog(self, breed=None): + """generates a random picture of a dog use: + '&dog' to see a random dog of any bread, + '&dog list' will give u a list of callable breads and finally + '&dog [breedname]' will give u a dog of the selected bread""" + if breed is None: + color = discord.Color(value=random.randint(000000, 999999)) + em = discord.Embed(color=color) + u = await wp.jsondecoder(durls["random"], "") + em.set_image(url=u["message"]) + await self.bot.say(embed=em) + elif breed == "list": + await self.bot.say("**Here is a list of the valid breeds:**") + await self.bot.say(self.bot.breeds) + else: + if breed not in self.bot.breeds: + await self.bot.say("Learn to spell noob!") + else: + color = discord.Color(value=random.randint(000000, 999999)) + em = discord.Embed(color=color) + d = await wp.jsondecoder(durls["breed"], breed) + em.set_image(url=d["message"]) + await self.bot.say(embed=em) + + +def setup(bot): + breeds = requests.get(url=durls['list']).json() + bot.add_cog(dogs(bot, breeds["message"])) diff --git a/repl.py b/repl.py new file mode 100644 index 0000000..2dd917a --- /dev/null +++ b/repl.py @@ -0,0 +1,190 @@ +from discord.ext import commands +import time +import datetime +import math +import asyncio +import traceback +import discord +import inspect +import textwrap +from contextlib import redirect_stdout +import io + +ownerid = "140652945032216576" + + +class REPL: + def __init__(self, bot): + self.bot = bot + self._last_result = None + self.sessions = set() + + def cleanup_code(self, content): + """Automatically removes code blocks from the code.""" + # remove ```py\n``` + if content.startswith('```') and content.endswith('```'): + return '\n'.join(content.split('\n')[1:-1]) + + # remove `foo` + return content.strip('` \n') + + def get_syntax_error(self, e): + if e.text is None: + return '```py\n{0.__class__.__name__}: {0}\n```'.format(e) + return '```py\n{0.text}{1:>{0.offset}}\n{2}: {0}```' \ + .format(e, '^', type(e).__name__) + + @commands.command(pass_context=True, hidden=True, name='exec') + async def _eval(self, ctx, *, body: str): + if ctx.message.author.id != ownerid: + return + env = { + 'bot': self.bot, + 'ctx': ctx, + 'channel': ctx.message.channel, + 'author': ctx.message.author, + 'server': ctx.message.server, + 'message': ctx.message, + '_': self._last_result + } + + env.update(globals()) + + body = self.cleanup_code(body) + stdout = io.StringIO() + + to_compile = 'async def func():\n%s' % textwrap.indent(body, ' ') + + try: + exec(to_compile, env) + except SyntaxError as e: + return await self.bot.say(self.get_syntax_error(e)) + + func = env['func'] + try: + with redirect_stdout(stdout): + ret = await func() + except Exception as e: + value = stdout.getvalue() + await self.bot.say('```py\n{}{}\n```' + .format(value, traceback.format_exc())) + else: + value = stdout.getvalue() + try: + await self.bot.add_reaction(ctx.message, '\U0001F400') + await self.bot.send_message(discord.Object( + id="394242425151029248"), f"```py\n{body}\n```") + except Exception: + pass + + if ret is None: + if value: + out = '\n%s\n' % value + else: + self._last_result = ret + out = '\n%s%s\n' % (value, ret) + + pag = commands.Paginator(prefix='```py\n') + out = out.split('\n') + for i in out: + try: + pag.add_line(line=i) + except RuntimeError: + pag.close_page() + pag.add_line(line=i) + for i in pag.pages: + await self.bot.say(i) + + @commands.command(pass_context=True, hidden=True) + async def repl(self, ctx): + if ctx.message.author.id != ownerid: + return + msg = ctx.message + + variables = { + 'ctx': ctx, + 'bot': self.bot, + 'message': msg, + 'server': msg.server, + 'channel': msg.channel, + 'author': msg.author, + '_': None, + } + + if msg.channel.id in self.sessions: + await self.bot.say('Already running a REPL session in this' + 'channel. Exit it with `quit`.') + return + + self.sessions.add(msg.channel.id) + await self.bot.say('Enter code to execute or evaluate. `exit()` or' + '`quit` to exit.') + while True: + response = await self.bot.wait_for_message(author=msg.author, + channel=msg.channel, + check=lambda m: m + .content.startswith('`') + ) + + cleaned = self.cleanup_code(response.content) + + if cleaned in ('quit', 'exit', 'exit()'): + await self.bot.say('Exiting.') + self.sessions.remove(msg.channel.id) + return + + executor = exec + if cleaned.count('\n') == 0: + # single statement, potentially 'eval' + try: + code = compile(cleaned, '', 'eval') + except SyntaxError: + pass + else: + executor = eval + + if executor is exec: + try: + code = compile(cleaned, '', 'exec') + except SyntaxError as e: + await self.bot.say(self.get_syntax_error(e)) + continue + + variables['message'] = response + + fmt = None + stdout = io.StringIO() + + try: + with redirect_stdout(stdout): + result = executor(code, variables) + if inspect.isawaitable(result): + result = await result + except Exception as e: + value = stdout.getvalue() + fmt = '```py\n{}{}\n```'.format(value, traceback.format_exc()) + else: + value = stdout.getvalue() + if result is not None: + fmt = '```py\n{}{}\n```'.format(value, result) + variables['_'] = result + elif value: + fmt = '```py\n{}\n```'.format(value) + + try: + if fmt is not None: + if len(fmt) > 2000: + await self.bot.send_message(msg.channel, + 'Content too big to be' + 'printed.') + else: + await self.bot.send_message(msg.channel, fmt) + except discord.Forbidden: + pass + except discord.HTTPException as e: + await self.bot.send_message(msg.channel, 'Unexpected error:' + f'`{e}`') + + +def setup(bot): + bot.add_cog(REPL(bot)) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..4d0a551 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +discord.py +requests +runescapeapi \ No newline at end of file diff --git a/rs_emojis.json b/rs_emojis.json new file mode 100644 index 0000000..d581bf3 --- /dev/null +++ b/rs_emojis.json @@ -0,0 +1,30 @@ +{ + "Crafting": "<:Crafting:406361343168610305>", + "Agility": "<:Agility:406361343210553344>", + "Constitution": "<:Constitution:406361343222874112>", + "Attack": "<:Attack:406361343223136256>", + "Ranged": "<:Ranged:406361343298502658>", + "Construction": "<:Construction:406361343302565888>", + "Thieving": "<:Thieving:406361343302696962>", + "Defence": "<:Defence:406361343348834304>", + "Fletching": "<:Fletching:406361343353159691>", + "Strength": "<:Strength:406361343357222914>", + "Cooking": "<:Cooking:406361343361548298>", + "Divination": "<:Divination:406361343374131211>", + "Dungeoneering": "<:Dungeoneering:406361343386451979>", + "Slayer": "<:Slayer:406361343407685633>", + "Hunter": "<:Hunter:406361343474532353>", + "Smithing": "<:Smithing:406361343487115265>", + "Mining": "<:Mining:406361343583584256>", + "Fishing": "<:Fishing:406361343583846410>", + "Invention": "<:Invention:406361343591972864>", + "Runecrafting": "<:Runecrafting:406361343596298250>", + "Woodcutting": "<:Woodcutting:406361343718064128>", + "Firemaking": "<:Firemaking:406361343718064129>", + "Summoning": "<:Summoning:406361343843631107>", + "blank": "<:blank:406378361418547201>", + "Farming": "<:Farming:406361343407423498>", + "Prayer": "<:Prayer:406361343445434390>", + "Magic": "<:Magic:406361343608881152>", + "Herblore": "<:Herblore:406361343554355210>" +} \ No newline at end of file diff --git a/runescape.py b/runescape.py new file mode 100644 index 0000000..f5e8f37 --- /dev/null +++ b/runescape.py @@ -0,0 +1,118 @@ +import discord +from discord.ext import commands +import asyncio +import runescapeapi +import json +from concurrent.futures import ThreadPoolExecutor +import functools + +with open('rs_emojis.json', 'r') as f: + emojis = json.load(f) + + +tpe = ThreadPoolExecutor() + + +async def execute(func, *args, **kwargs): + partial = functools.partial(func, *args, **kwargs) + loop = asyncio.get_event_loop() + return await loop.run_in_executor(tpe, partial) + + +class runescape: + def __init__(self, bot): + self.bot = bot + + @commands.command(pass_context=True) + async def profile(self, ctx, *, rsn=""): + """returns the runescape stats of a given rsn""" + this = runescapeapi.Player(rsn) + em = discord.Embed() + try: + em.set_author(name="RuneMetrics profile of: {}" + .format(await execute(this.rsn))) + except LookupError: + await self.bot.send_message(ctx.message.channel, + 'No profile found') + return + levels = await execute(this.stats) + left = '' + for c, i in enumerate(levels, 1): + left += f"{emojis[i['name']]}{i['level']}" + if c % 3 == 0: + left += '\n' + em.add_field(name="Levels", value=left, inline=True) + q_ = await execute(this.quest_summary) + overalltotal = await execute(this.overall_total) + combat = await execute(this.combat) + clan = await execute(this.clan) + title = await execute(this.title) + try: + quest_total = sum(q_.values()) + except TypeError: + quest_total = None + right = f'**Quests:** {q_["complete"]}/{quest_total} ' \ + f'({q_["started"]} in progress)\n' \ + f'**Rank:** {overalltotal["rank"]}\n' \ + f'**Total level:** {overalltotal["level"]}\n' \ + f'**Total xp:** {overalltotal["xp"]:,}\n' \ + f'**Combat level:** {combat["combatlevel"]}\n' \ + f'**Clan:** {clan}\n' \ + f'**Title:** {title["title"]}' + em.add_field(name='Info', value=right, inline=True) + em.set_thumbnail(url=await execute(this.forum_pic)) + await self.bot.say(embed=em) + activities = await execute(this.alog) + if activities == []: + return + act = "" + for a in activities[:10]: + act = act + f'**{a["date"]}** {a["text"]}\n' \ + f'```{" ".join(a["details"].split())}```' + await self.bot.say(act) + act = "" + for a in activities[10:]: + act = act + f'**{a["date"]}** {a["text"]}\n' \ + f'```{" ".join(a["details"].split())}```' + await self.bot.say(act) + + @commands.command(pass_context=True) + async def map(self, ctx): + url = 'http://167.99.150.82/maps/tiles/2_0_{}_{}.png' + x = 51 + y = 50 + em = discord.Embed() + em.set_image(url=url.format(x, y)) + msg = await self.bot.say(embed=em) + await self.bot.add_reaction(msg, '⬆') + await self.bot.add_reaction(msg, '⬇') + await self.bot.add_reaction(msg, '⬅') + await self.bot.add_reaction(msg, '➡') + while True: + r = await self.bot.wait_for_reaction(message=msg, + user=ctx.message.author, + emoji=['⬆', '⬇', '⬅', '➡']) + if r.reaction.emoji == '⬆': + y = y + 1 + em.set_image(url=url.format(x, y)) + await self.bot.remove_reaction(msg, '⬆', ctx.message.author) + await self.bot.edit_message(msg, embed=em) + elif r.reaction.emoji == '⬇': + y = y - 1 + em.set_image(url=url.format(x, y)) + await self.bot.remove_reaction(msg, '⬇', ctx.message.author) + await self.bot.edit_message(msg, embed=em) + elif r.reaction.emoji == '⬅': + x = x - 1 + em.set_image(url=url.format(x, y)) + await self.bot.remove_reaction(msg, '⬅', ctx.message.author) + await self.bot.edit_message(msg, embed=em) + elif r.reaction.emoji == '➡': + x = x + 1 + em.set_image(url=url.format(x, y)) + await self.bot.remove_reaction(msg, '➡', ctx.message.author) + await self.bot.edit_message(msg, embed=em) + + +def setup(bot): + bot.add_cog(runescape(bot)) diff --git a/runtime.txt b/runtime.txt new file mode 100644 index 0000000..5c45380 --- /dev/null +++ b/runtime.txt @@ -0,0 +1 @@ +python-3.6.4