Browse Source

Merge branch 'master' into development

# Conflicts:
#	roxbot/utils.py
tags/v1.8.0
Roxie Gibson 6 years ago
parent
commit
b8f6a9d685
4 changed files with 96 additions and 11 deletions
  1. +74
    -0
      roxbot/cogs/fun.py
  2. +18
    -7
      roxbot/http.py
  3. +1
    -1
      roxbot/settings/preferences_example.ini
  4. +3
    -3
      roxbot/utils.py

+ 74
- 0
roxbot/cogs/fun.py View File

import datetime import datetime


import discord import discord
from discord import Embed
from discord.ext import commands
from discord.ext.commands import bot from discord.ext.commands import bot


import roxbot import roxbot
embed.set_footer(text=base_url) embed.set_footer(text=base_url)
return await ctx.send(embed=embed) return await ctx.send(embed=embed)


@bot.command()
@commands.has_permissions(add_reactions=True)
@commands.bot_has_permissions(add_reactions=True)
async def xkcd(self, ctx, *, query=None):
"""
Grabs the image & metadata of the given xkcd comic
Example:
{command_prefix}xkcd 666
{command_prefix}xkcd Silent Hammer
{command_prefix}xkcd latest
"""
msg = ""
title_query_url = "http://www.explainxkcd.com/wiki/api.php?format=json&action=query&redirects&titles={}"
xkcd_site = "https://xkcd.com/{}"
random_url = "https://c.xkcd.com/random/comic"

async def xkcd_lookup_num(num):
return await roxbot.http.api_request(xkcd_site.format(str(num) + "/info.0.json"))

async def xkcd_lookup_latest():
return await roxbot.http.api_request(xkcd_site.format("/info.0.json"))

async def xkcd_lookup_title(title):
api = await roxbot.http.api_request(title_query_url.format(title.replace(" ", "_")))
# if valid, query.redirects.to is the full & proper page title, including the actual number.
try:
full_page_title = api["query"]["redirects"][0]["to"]
num = full_page_title.split(":")[0]
return await xkcd_lookup_num(num)
except KeyError: # this means query,redirects... didn't exist, done like this to save a massive if statement.
return None

async def random_xkcd():
resp = await roxbot.http.request(random_url, **{"allow_redirects": False})
comic_url = resp.headers["Location"]
num = comic_url.split("/")[-2] # there's always a trailing / so it's the 2nd last segment
return await xkcd_lookup_num(num)

async with ctx.typing():
# Check if passed a valid number
if query in (None, "random"):
# Get a random comic
msg = "Showing a random xkcd"
comic = await random_xkcd()
elif query.isdigit():
# If so, use that to look up
comic = await xkcd_lookup_num(query)
elif query == "latest":
msg = "Showing the latest xkcd"
# Get the latest comic
comic = await xkcd_lookup_latest()
else:
# Otherwise, assume it's meant to be a name & look up from that.
# Case insensitive, or at least as close as we can get it.
# Titles tend to be in title case so this shouldn't be a problem
query = query.title()
comic = await xkcd_lookup_title(query)

# If we couldn't find anything, return an error.
if not comic:
return await ctx.send("Couldn't find that comic.".format(ctx.message.author.mention))
else:
# Otherwise, show the comic
embed = Embed(title=comic["safe_title"], description="xkcd #{} by Randall Munroe".format(comic["num"]))
embed.set_image(url=comic["img"])
embed.set_footer(text=comic["alt"])
embed.url = xkcd_site.format(comic["num"])
output = await ctx.send(msg, embed=embed)
await roxbot.utils.delete_option(self.bot, ctx, output, self.bot.get_emoji(444410658101002261) or "❌")



def setup(bot_client): def setup(bot_client):
bot_client.add_cog(Fun(bot_client)) bot_client.add_cog(Fun(bot_client))

+ 18
- 7
roxbot/http.py View File

import aiohttp import aiohttp




async def api_request(url, *, headers=None):
async def request(url, *, headers=None, **kwargs):
"""
Base GET request.
:param url:
:param headers:
:param kwargs:
:return:
"""
async with aiohttp.ClientSession() as session:
return await session.get(url, headers=headers, **kwargs)


async def api_request(url, *, headers=None, **kwargs):
""" """
Returns a JSON dict object for most api calls in RoxBot. Returns a JSON dict object for most api calls in RoxBot.
:param url: URL Should be a api endpoint that will return :param url: URL Should be a api endpoint that will return
headers = {'User-agent': 'RoxBot Discord Bot'} headers = {'User-agent': 'RoxBot Discord Bot'}
else: else:
headers = {'User-agent': 'RoxBot Discord Bot', **headers} headers = {'User-agent': 'RoxBot Discord Bot', **headers}
async with aiohttp.ClientSession() as session:
async with session.get(url, headers=headers) as resp:
try:
return json.loads(await resp.read())
except json.JSONDecodeError:
return None
resp = await request(url, headers=headers, **kwargs)
try:
return json.loads(await resp.read())
except json.JSONDecodeError:
return None




async def download_file(url, filename=None): async def download_file(url, filename=None):

+ 1
- 1
roxbot/settings/preferences_example.ini View File

[Roxbot] [Roxbot]
OwnerID=142735312626515979
OwnerID=451192272349036545
Token=TokenHere Token=TokenHere
Command_Prefix=r; Command_Prefix=r;
Tatsumaki_Token=TokenHere Tatsumaki_Token=TokenHere

+ 3
- 3
roxbot/utils.py View File

""" """




from asyncio import TimeoutError
import asyncio




async def delete_option(bot, ctx, message, delete_emoji, timeout=20): async def delete_option(bot, ctx, message, delete_emoji, timeout=20):
await bot.wait_for("reaction_add", timeout=timeout, check=check) await bot.wait_for("reaction_add", timeout=timeout, check=check)
await message.remove_reaction(delete_emoji, bot.user) await message.remove_reaction(delete_emoji, bot.user)
await message.remove_reaction(delete_emoji, ctx.author) await message.remove_reaction(delete_emoji, ctx.author)
return await message.edit(content="{} requested output be deleted.".format(ctx.author))
except TimeoutError:
return await message.edit(content="{} requested output be deleted.".format(ctx.author), embed=None)
except asyncio.TimeoutError:
await message.remove_reaction(delete_emoji, bot.user) await message.remove_reaction(delete_emoji, bot.user)





Loading…
Cancel
Save