Skip to content

Commit

Permalink
Merge branch 'master' into rewrite
Browse files Browse the repository at this point in the history
  • Loading branch information
Harmon758 committed Jun 2, 2017
2 parents 3e619f9 + 887a7d4 commit fc2072b
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 66 deletions.
2 changes: 1 addition & 1 deletion Discord/Harmonbot.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ async def on_command_error(error, ctx):
elif isinstance(error, errors.NotPermitted):
embed.description = ":no_entry: You don't have permission to use that command here"
elif isinstance(error, commands.errors.BadArgument):
embed.description = ":no_entry: Error: invalid input"
embed.description = ":no_entry: Error: Invalid Input: {}".format(error)
elif isinstance(error, commands.errors.CommandInvokeError) and isinstance(error.original, discord.errors.HTTPException) and str(error.original) == "BAD REQUEST (status code: 400): You can only bulk delete messages that are under 14 days old.":
embed.description = ":no_entry: Error: You can only bulk delete messages that are under 14 days old"
if embed.description:
Expand Down
5 changes: 3 additions & 2 deletions Discord/clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from utilities import errors
from utilities.help_formatter import CustomHelpFormatter

version = "0.35.0"
version = "0.35.16"
changelog = "https://discord.gg/a2rbZPu"
beta = any("beta" in arg.lower() for arg in sys.argv)
data_path = "data/beta" if beta else "data"
Expand Down Expand Up @@ -186,7 +186,8 @@ async def _update_discord_bots_stats():
async with aiohttp_session.post("https://bots.discord.pw/api/bots/{}/stats".format(client.user.id),
headers = {"authorization": credentials.discord_bots_api_token, "content-type": "application/json"},
data = json.dumps({"server_count": len(client.guilds)})) as resp:
if resp.status in (502, 504):
# Change to check for 200?
if resp.status in (500, 502, 504, 522):
return "Error: {}".format(resp.status)
response = await resp.json()
return response
Expand Down
1 change: 1 addition & 0 deletions Discord/cogs/discord.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,7 @@ async def servericon(self, ctx):
'''See a bigger version of the server icon'''
if not ctx.guild.icon:
await self.bot.embed_reply(":no_entry: This server doesn't have an icon")
return
await self.bot.embed_reply("This server's icon:", image_url = ctx.guild.icon_url)

@commands.command(aliases = ["serverinformation", "server_info", "server_information"], no_pm = True)
Expand Down
85 changes: 52 additions & 33 deletions Discord/cogs/games.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,53 +308,72 @@ async def woodcutting_rate(self, ctx, *, wood_type : str):
@commands.command()
@checks.not_forbidden()
async def blackjack(self, ctx):
'''Play a game of blackjack'''
'''
Play a game of blackjack
Manage Messages permission required for message cleanup
'''
# TODO: S17
deck = pydealer.Deck()
deck.shuffle()
dealer = deck.deal(2)
hand = deck.deal(2)
dealer_string = self.cards_to_string(dealer.cards)
hand_string = self.cards_to_string(hand.cards)
player = deck.deal(2)
dealer_string = ":grey_question: :{}: {}".format(dealer.cards[1].suit.lower(), dealer.cards[1].value)
player_string = self.cards_to_string(player.cards)
dealer_total = self.blackjack_total(dealer.cards)
hand_total = self.blackjack_total(hand.cards)
await self.bot.embed_say("Dealer: {} ({})\n{}: {} ({})".format(dealer_string, dealer_total, ctx.author.display_name, hand_string, hand_total))
await self.bot.embed_reply("Hit or Stay?")
player_total = self.blackjack_total(player.cards)
response = await ctx.embed_reply("Dealer: {} (?)\n{}: {} ({})\n".format(dealer_string, ctx.author.display_name, player_string, player_total), title = "Blackjack", footer_text = "Hit or Stay?")
embed = response.embeds[0]
await self.bot.attempt_delete_message(ctx.message)
while True:
action = await self.bot.wait_for_message(author = ctx.author, check = lambda msg: msg.content.lower() in ["hit", "stay"])
if action.content.lower() == "hit":
hand.add(deck.deal())
hand_string = self.cards_to_string(hand.cards)
hand_total = self.blackjack_total(hand.cards)
await self.bot.embed_say("Dealer: {} ({})\n{}: {} ({})\n".format(dealer_string, dealer_total, ctx.author.display_name, hand_string, hand_total))
if hand_total > 21:
await self.bot.embed_reply(":boom: You have busted\nYou lost :(")
return
else:
await self.bot.embed_reply("Hit or Stay?")
action = await self.bot.wait_for_message(author = ctx.author, check = lambda msg: msg.content.lower().strip('!') in ("hit", "stay"))
await self.bot.attempt_delete_message(action)
if action.content.lower().strip('!') == "hit":
player.add(deck.deal())
player_string = self.cards_to_string(player.cards)
player_total = self.blackjack_total(player.cards)
embed.description = "Dealer: {} (?)\n{}: {} ({})\n".format(dealer_string, ctx.author.display_name, player_string, player_total)
await self.bot.edit_message(response, embed = embed)
if player_total > 21:
embed.description += ":boom: You have busted"
embed.set_footer(text = "You lost :(")
break
else:
dealer_string = self.cards_to_string(dealer.cards)
embed.description = "Dealer: {} ({})\n{}: {} ({})\n".format(dealer_string, dealer_total, ctx.message.author.display_name, player_string, player_total)
if dealer_total > 21:
await self.bot.embed_reply("The dealer busted\nYou win!")
return
elif dealer_total > hand_total:
await self.bot.embed_reply("The dealer beat you\nYou lost :(")
return
embed.description += ":boom: The dealer busted"
embed.set_footer(text = "You win!")
break
elif dealer_total > player_total:
embed.description += "The dealer beat you"
embed.set_footer(text = "You lost :(")
break
embed.set_footer(text = "Dealer's turn..")
await self.bot.edit_message(response, embed = embed)
while True:
await asyncio.sleep(5)
dealer.add(deck.deal())
dealer_string = self.cards_to_string(dealer.cards)
dealer_total = self.blackjack_total(dealer.cards)
await self.bot.embed_say("Dealer: {} ({})\n{}: {} ({})\n".format(dealer_string, dealer_total, ctx.author.display_name, hand_string, hand_total))
embed.description = "Dealer: {} ({})\n{}: {} ({})\n".format(dealer_string, dealer_total, ctx.author.display_name, player_string, player_total)
await self.bot.edit_message(response, embed = embed)
if dealer_total > 21:
await self.bot.embed_reply("The dealer busted\nYou win!")
return
elif dealer_total > hand_total:
await self.bot.embed_reply("The dealer beat you\nYou lost :(")
return
await asyncio.sleep(5)
embed.description += ":boom: The dealer busted"
embed.set_footer(text = "You win!")
break
elif dealer_total > player_total:
embed.description += "The dealer beat you"
embed.set_footer(text = "You lost :(")
break
elif dealer_total == player_total == 21:
embed.set_footer(text = "It's a push (tie)")
break
break
await self.bot.edit_message(response, embed = embed)

def blackjack_total(self, cards):
total = sum([self.blackjack_ranks["values"][card.value] for card in cards])
if pydealer.tools.find_card(cards, term = "Ace", limit = 1) and total <= 11:
total += 10
total = sum(self.blackjack_ranks["values"][card.value] for card in cards)
if pydealer.tools.find_card(cards, term = "Ace", limit = 1) and total <= 11: total += 10
return total

@commands.group(invoke_without_command = True)
Expand Down
20 changes: 10 additions & 10 deletions Discord/cogs/meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ async def conversions(self, ctx):
await ctx.embed_reply("**Temperature Unit Conversions**: {0}[c, f, k, r, de]__to__[c, f, k, r, de, n, re, ro]\n"
"**Weight Unit Conversions**: {0}<unit>__to__<unit>\nunits: [amu, me, bagc, bagpc, barge, kt, ct, clove, crith, da, drt, drav, ev, gamma, gr, gv, longcwt, cwt, shcwt, kg, kip, mark, mite, mitem, ozt, ozav, oz, dwt, pwt, point, lb, lbav, lbm, lbt, quarterimp, quarterinf, quarterlinf, q, sap, sheet, slug, st, atl, ats, longtn, ton, shtn, t, wey, g]".format(ctx.prefix), title = "Conversion Commands")

@commands.command(aliases = ["oauth"], hidden = True)
@commands.command(aliases = ["oauth"])
async def invite(self, ctx):
'''Link to invite me to a server'''
from clients import application_info
Expand Down Expand Up @@ -302,24 +302,24 @@ async def stats(self, ctx):
avatar = ctx.author.avatar_url or ctx.author.default_avatar_url
embed.set_author(name = ctx.author.display_name, icon_url = avatar) # url?
embed.add_field(name = "Uptime", value = uptime)
embed.add_field(name = "Total Recorded Uptime", value = total_uptime) # since 2016-04-17, fixed 2016-05-10
embed.add_field(name = "Recorded Restarts", value = stats["restarts"]) # since 2016-04-17, fixed 2016-05-10
embed.add_field(name = "Total Recorded Uptime", value = total_uptime) ## since 2016-04-17, fixed 2016-05-10
embed.add_field(name = "Recorded Restarts", value = "{:,}".format(stats["restarts"])) ## since 2016-04-17, fixed 2016-05-10
embed.add_field(name = "Main Commands", value = len(set(self.bot.commands.values())))
embed.add_field(name = "Commands Executed",
value = "{} this session\n{} total recorded".format(session_commands_executed, stats["commands_executed"]))
value = "{} this session\n{:,} total recorded".format(session_commands_executed, stats["commands_executed"]))
# since 2016-06-10 (cog commands)
embed.add_field(name = "Cogs Reloaded", value = stats["cogs_reloaded"]) # since 2016-06-10 - implemented cog reloading
embed.add_field(name = "Cogs Reloaded", value = "{:,}".format(stats["cogs_reloaded"])) ## since 2016-06-10 - implemented cog reloading
# TODO: cogs reloaded this session
embed.add_field(name = "Servers", value = len(self.bot.guilds))
embed.add_field(name = "Channels", value = "{} text\n{} voice (playing in {}/{})".format(text_count, voice_count, playing_in_voice_count, in_voice_count))
embed.add_field(name = "Members",
value = "{} total\n{} online\n{} unique\n{} unique online".format(total_members, total_members_online, len(unique_members), unique_members_online))
value = "{:,} total\n({:,} online)\n{:,} unique\n({:,} online)".format(total_members, total_members_online, len(unique_members), unique_members_online))
embed.add_field(name = "Top Commands Executed",
value = "\n".join(["{} {}".format(uses, command) for command, uses in top_commands[:5]])) # since 2016-11-14
value = "\n".join("{:,} {}".format(uses, command) for command, uses in top_commands[:5])) ## since 2016-11-14
embed.add_field(name = "(Total Recorded)",
value = "\n".join(["{} {}".format(uses, command) for command, uses in top_commands[5:10]])) # since 2016-11-14
value = "\n".join("{:,} {}".format(uses, command) for command, uses in top_commands[5:10])) ## since 2016-11-14
if session_top_5: embed.add_field(name = "(This Session)",
value = "\n".join(["{} {}".format(uses, command) for command, uses in session_top_5]))
value = "\n".join("{:,} {}".format(uses, command) for command, uses in session_top_5))
await self.bot.send_message(ctx.message.channel, embed = embed)

@commands.command()
Expand Down Expand Up @@ -478,7 +478,7 @@ async def do(self, ctx, times : int, *, command):
for _ in range(times):
await self.bot.process_commands(msg)

@commands.group(invoke_without_command = True)
@commands.group(aliases = ["say"], invoke_without_command = True)
@checks.is_owner()
async def echo(self, ctx, *, message):
'''Echoes the message'''
Expand Down
13 changes: 7 additions & 6 deletions Discord/cogs/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,14 @@ async def poke(self, ctx, *, user : str):
with open(clients.data_path + "/user_data/{}/pokes.json".format(ctx.author.id), 'r') as pokes_file:
pokes_data = json.load(pokes_file)
pokes_data[to_poke.id] = pokes_data.get(to_poke.id, 0) + 1
with open(clients.data_path + "/user_data/{}/pokes.json".format(ctx.author.id), 'w') as pokes_file:
json.dump(pokes_data, pokes_file, indent = 4)
embed = discord.Embed(color = clients.bot_color)
avatar = ctx.author.avatar_url or ctx.author.default_avatar_url
embed.set_author(name = ctx.author, icon_url = avatar)
embed.set_author(name = ctx.author, icon_url = ctx.author.avatar_url or ctx.author.default_avatar_url)
embed.description = "Poked you for the {} time!".format(clients.inflect_engine.ordinal(pokes_data[to_poke.id]))
await self.bot.send_message(to_poke, embed = embed)
await self.bot.embed_reply("You have poked {} for the {} time!".format(to_poke.mention, clients.inflect_engine.ordinal(pokes_data[to_poke.id])))
with open("data/user_data/{}/pokes.json".format(ctx.author.id), 'w') as pokes_file:
json.dump(pokes_data, pokes_file, indent = 4)
await ctx.embed_reply("You have poked {} for the {} time!".format(to_poke.mention, clients.inflect_engine.ordinal(pokes_data[to_poke.id])), footer_text = "In response to: {}".format(ctx.message.clean_content))
await self.bot.attempt_delete_message(ctx.message)

def emote_wrapper(name, emote = None):
if emote is None: emote = name
Expand All @@ -123,8 +123,9 @@ async def emote_command(self, ctx):
await ctx.embed_reply(":{}:".format(emote))
return emote_command

for emote in ("fish", "frog", "turtle", "gun", "tomato", "cucumber", "eggplant", "lizard", "minidisc"):
for emote in ("fish", "frog", "turtle", "gun", "tomato", "cucumber", "eggplant", "lizard", "minidisc", "horse"):
setattr(Misc, emote, emote_wrapper(emote))
setattr(Misc, "dog", emote_wrapper("dog", emote = "dog2"))
setattr(Misc, "bunny", emote_wrapper("bunny", emote = "rabbit2"))
setattr(Misc, "cow", emote_wrapper("cow", emote = "cow2"))

26 changes: 19 additions & 7 deletions Discord/cogs/random.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from bs4 import BeautifulSoup
import calendar
import concurrent.futures
import csv
import datetime
import dice
import inspect
Expand Down Expand Up @@ -41,6 +42,15 @@ def __init__(self, bot):
self.random_subcommands = ((self.color, "Resources.color"), (self.giphy, "Resources.giphy"), (self.map, "Resources.map"), (self.streetview, "Resources.streetview"), (self.uesp, "Search.uesp"), (self.wikipedia, "Search.wikipedia"), (self.xkcd, "Resources.xkcd"))
for command, parent_name in self.random_subcommands:
utilities.add_as_subcommand(self, command, parent_name, "random")
# Import jokes
self.jokes = []
try:
with open(clients.data_path + "/jokes.csv", newline = "") as jokes_file:
jokes_reader = csv.reader(jokes_file)
for row in jokes_reader:
self.jokes.append(row[0])
except FileNotFoundError:
pass

def __unload(self):
for command, parent_name in self.random_subcommands:
Expand Down Expand Up @@ -193,9 +203,9 @@ async def dice(self, ctx, *, input : str = '6'):
except discord.errors.HTTPException:
await ctx.embed_reply(":no_entry: Output too long")
except pyparsing.ParseException:
await self.bot.embed_reply(":no_entry: Invalid input")
except concurrent.futures.TimeoutError:
await self.bot.embed_reply(":no_entry: Execution exceeded time limit")
await ctx.embed_reply(":no_entry: Invalid input")
except (concurrent.futures.TimeoutError, multiprocessing.context.TimeoutError):
await ctx.embed_reply(":no_entry: Execution exceeded time limit")

@commands.command()
@checks.not_forbidden()
Expand All @@ -219,7 +229,8 @@ async def day(self, ctx):
@checks.not_forbidden()
async def fact(self, ctx):
'''Random fact'''
async with clients.aiohttp_session.get("http://mentalfloss.com/api/1.0/views/amazing_facts.json?limit=1&bypass=1") as resp:
url = "http://mentalfloss.com/api/1.0/views/amazing_facts.json?limit=1&bypass={}".format(random.random())
async with clients.aiohttp_session.get(url) as resp:
data = await resp.json()
await ctx.embed_reply(BeautifulSoup(data[0]["nid"]).text)

Expand Down Expand Up @@ -293,9 +304,10 @@ async def insult(self, ctx):
@checks.not_forbidden()
async def joke(self, ctx):
'''Random joke'''
async with clients.aiohttp_session.get("http://tambal.azurewebsites.net/joke/random") as resp:
data = await resp.json()
await self.bot.embed_reply(data["joke"])
# Sources:
# https://github.com/KiaFathi/tambalAPI
# https://www.kaggle.com/abhinavmoudgil95/short-jokes (https://github.com/amoudgl/short-jokes-dataset)
await ctx.embed_reply(random.choice(self.jokes))

@commands.command()
@checks.not_forbidden()
Expand Down
8 changes: 4 additions & 4 deletions Discord/cogs/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -1199,11 +1199,11 @@ async def translate_to(self, ctx, language_code : str, *, text : str):
'''
await self.process_translate(ctx, text, language_code)

async def process_translate(self, text, to_language_code, from_language_code = None):
url = "https://translate.yandex.net/api/v1.5/tr.json/translate?key={}&lang={}&text={}&options=1".format(credentials.yandex_translate_api_key, to_language_code if not from_language_code else "{}-{}".format(from_language_code, to_language_code), text)
async def process_translate(self, ctx, text, to_language_code, from_language_code = None):
url = "https://translate.yandex.net/api/v1.5/tr.json/translate?key={}&lang={}&text={}&options=1".format(credentials.yandex_translate_api_key, to_language_code if not from_language_code else "{}-{}".format(from_language_code, to_language_code), text.replace(' ', '+'))
async with clients.aiohttp_session.get(url) as resp:
if resp.status == 400:
await self.bot.embed_reply(":no_entry: Error")
if resp.status == 400: # Bad Request
await ctx.embed_reply(":no_entry: Error")
return
data = await resp.json()
if data["code"] != 200:
Expand Down
2 changes: 1 addition & 1 deletion Discord/cogs/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ async def youtube_error(self, error, ctx):
@checks.not_forbidden()
async def amazon(self, ctx, *search : str):
'''Search with Amazon'''
await self.bot.embed_reply("[Amazon search for \"{}\"](https://www.amazon.com/s/?field-keywords={})".format(' '.join(search), '+'.join(search)))
await ctx.embed_reply("[Amazon search for \"{}\"](https://smile.amazon.com/s/?field-keywords={})".format(' '.join(search), '+'.join(search)))

@commands.command()
@checks.not_forbidden()
Expand Down
21 changes: 19 additions & 2 deletions Discord/cogs/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -596,11 +596,28 @@ async def tag_delete(self, ctx, tag : str):
'''Delete one of your tags'''
if (await self.check_no_tags(ctx)): return
if (await self.check_no_tag(ctx, tag)): return
del self.tags_data[ctx.author.id]["tags"][tag]
with open("data/tags.json", 'w') as tags_file:
try:
del self.tags_data[ctx.author.id]["tags"][tag]
except KeyError:
await ctx.embed_reply(":no_entry: Tag not found")
return
with open(clients.data_path + "/tags.json", 'w') as tags_file:
json.dump(self.tags_data, tags_file, indent = 4)
await ctx.embed_reply(":ok_hand::skin-tone-2: Your tag has been deleted")

@tag.command(name = "expunge", pass_context = True)
@checks.is_owner()
async def tag_expunge(self, ctx, owner : discord.Member, tag : str):
'''Delete someone else's tags'''
try:
del self.tags_data[owner.id]["tags"][tag]
except KeyError:
await ctx.embed_reply(":no_entry: Tag not found")
return
with open(clients.data_path + "/tags.json", 'w') as tags_file:
json.dump(self.tags_data, tags_file, indent = 4)
await ctx.embed_reply(":ok_hand::skin-tone-2: {}'s tag has been deleted".format(owner.mention))

@tag.command(name = "search", aliases = ["contains", "find"])
async def tag_search(self, ctx, *, search : str):
'''Search your tags'''
Expand Down

0 comments on commit fc2072b

Please sign in to comment.