1
0
Fork 0
mirror of synced 2024-05-20 12:32:26 +12:00
Bonfire/cogs/misc.py

348 lines
13 KiB
Python
Raw Normal View History

import discord
2016-07-09 13:27:19 +12:00
from discord.ext import commands
from . import utils
2016-07-09 13:27:19 +12:00
import random
2016-07-11 01:58:46 +12:00
import re
2016-07-19 11:25:03 +12:00
import calendar
import pendulum
2016-07-19 11:25:03 +12:00
import datetime
2017-04-21 15:03:52 +12:00
import psutil
2016-07-09 13:27:19 +12:00
2016-07-19 11:29:40 +12:00
class Miscallaneous:
"""Core commands, these are the miscallaneous commands that don't fit into other categories'"""
2016-07-09 13:27:19 +12:00
def __init__(self, bot):
self.bot = bot
self.help_embeds = []
self.results_per_page = 10
self.commands = None
2017-04-21 15:03:52 +12:00
self.process = psutil.Process()
self.process.cpu_percent()
@commands.command()
@utils.custom_perms(send_messages=True)
@utils.check_restricted()
2017-05-19 13:41:41 +12:00
async def help(self, ctx, *, command=None):
"""This command is used to provide a link to the help URL.
This can be called on a command to provide more information about that command
You can also provide a page number to pull up that page instead of the first page
EXAMPLE: !help help
RESULT: This information"""
groups = {}
entries = []
2017-05-19 13:41:41 +12:00
if command is not None:
command = self.bot.get_command(command)
2017-05-08 13:42:42 +12:00
2017-05-19 13:42:42 +12:00
if command is None:
2017-05-19 13:41:41 +12:00
for cmd in utils.get_all_commands(self.bot):
2017-06-07 20:30:19 +12:00
if not await cmd.can_run(ctx) or not cmd.enabled:
2017-05-19 13:41:41 +12:00
continue
cog = cmd.cog_name
if cog in groups:
groups[cog].append(cmd)
else:
groups[cog] = [cmd]
for cog, cmds in groups.items():
entry = {'title': "{} Commands".format(cog),
'fields': []}
for cmd in cmds:
if not cmd.help:
# Assume if there's no description for a command, it's not supposed to be used
# I.e. the !command command. It's just a parent
continue
2017-05-19 13:41:41 +12:00
description = cmd.help.partition('\n')[0]
name_fmt = "{ctx.prefix}**{cmd.qualified_name}** {aliases}".format(
ctx=ctx,
cmd=cmd,
aliases=cmd.aliases if len(cmd.aliases) > 0 else ""
)
entry['fields'].append({
'name': name_fmt,
'value': description,
'inline': False
})
entries.append(entry)
entries = sorted(entries, key=lambda x: x['title'])
try:
pages = utils.DetailedPages(self.bot, message=ctx.message, entries=entries)
pages.embed.set_thumbnail(url=self.bot.user.avatar_url)
await pages.paginate()
except utils.CannotPaginate as e:
await ctx.send(str(e))
else:
2017-06-07 20:30:19 +12:00
# Get the description for a command
2017-05-19 13:44:28 +12:00
description = command.help
2017-05-19 13:41:41 +12:00
if description is not None:
# Split into examples, results, and the description itself based on the string
2017-05-19 14:04:33 +12:00
description, _, rest = command.help.partition('EXAMPLE:')
example, _, result = rest.partition('RESULT:')
else:
2017-05-19 13:41:41 +12:00
example = None
result = None
# Also get the subcommands for this command, if they exist
subcommands = [x.qualified_name for x in utils.get_all_subcommands(command) if x != command]
2017-05-19 13:41:41 +12:00
# The rest is simple, create the embed, set the thumbail to me, add all fields if they exist
2017-05-19 13:44:28 +12:00
embed = discord.Embed(title=command.qualified_name)
2017-05-19 13:41:41 +12:00
embed.set_thumbnail(url=self.bot.user.avatar_url)
if description:
embed.add_field(name="Description", value=description.strip(), inline=False)
2017-05-19 13:41:41 +12:00
if example:
embed.add_field(name="Example", value=example.strip(), inline=False)
2017-05-19 13:41:41 +12:00
if result:
embed.add_field(name="Result", value=result.strip(), inline=False)
2017-05-19 13:41:41 +12:00
if subcommands:
embed.add_field(name='Subcommands', value="\n".join(subcommands), inline=False)
2017-05-19 13:41:41 +12:00
await ctx.send(embed=embed)
@commands.command()
@utils.custom_perms(send_messages=True)
@utils.check_restricted()
async def say(self, ctx, *, msg: str):
"""Tells the bot to repeat what you say
EXAMPLE: !say I really like orange juice
RESULT: I really like orange juice"""
fmt = "\u200B{}".format(msg)
await ctx.send(fmt)
try:
await ctx.message.delete()
except:
pass
2016-11-29 16:52:45 +13:00
2016-07-19 11:25:03 +12:00
@commands.command()
@utils.custom_perms(send_messages=True)
@utils.check_restricted()
async def calendar(self, ctx, month: str = None, year: int = None):
"""Provides a printout of the current month's calendar
Provide month and year to print the calendar of that year and month
EXAMPLE: !calendar january 2011"""
# calendar takes in a number for the month, not the words
# so we need this dictionary to transform the word to the number
2016-07-19 11:25:03 +12:00
months = {
"january": 1,
"february": 2,
"march": 3,
"april": 4,
"may": 5,
"june": 6,
"july": 7,
"august": 8,
"september": 9,
"october": 10,
"november": 11,
"december": 12
}
# In month was not passed, use the current month
2016-07-19 11:25:03 +12:00
if month is None:
month = datetime.date.today().month
else:
month = months.get(month.lower())
2016-07-19 11:25:03 +12:00
if month is None:
await ctx.send("Please provide a valid Month!")
2016-07-19 11:25:03 +12:00
return
# If year was not passed, use the current year
2016-07-19 11:25:03 +12:00
if year is None:
year = datetime.datetime.today().year
# Here we create the actual "text" calendar that we are printing
2016-07-19 11:25:03 +12:00
cal = calendar.TextCalendar().formatmonth(year, month)
await ctx.send("```\n{}```".format(cal))
@commands.command(aliases=['about'])
@utils.custom_perms(send_messages=True)
@utils.check_restricted()
async def info(self, ctx):
"""This command can be used to print out some of my information"""
# fmt is a dictionary so we can set the key to it's output, then print both
# The only real use of doing it this way is easier editing if the info
# in this command is changed
# Create the original embed object
opts = {'title': 'Dev Server',
2016-11-29 21:05:22 +13:00
'description': 'Join the server above for any questions/suggestions about me.',
'url': utils.dev_server}
embed = discord.Embed(**opts)
# Add the normal values
2017-03-08 12:56:24 +13:00
embed.add_field(name='Total Servers', value=len(self.bot.guilds))
2017-03-21 11:27:34 +13:00
embed.add_field(name='Total Members', value=len(self.bot.users))
2017-05-05 10:33:10 +12:00
hm = self.bot.get_cog('Hangman')
ttt = self.bot.get_cog('TicTacToe')
bj = self.bot.get_cog('Blackjack')
interaction = self.bot.get_cog('Blackjack')
music = self.bot.get_cog('Music')
# Count the variable values; hangman, tictactoe, etc.
2017-05-05 10:33:10 +12:00
if hm:
hm_games = len(hm.games)
if hm_games:
embed.add_field(name='Total Hangman games running', value=hm_games)
if ttt:
ttt_games = len(ttt.boards)
if ttt_games:
embed.add_field(name='Total TicTacToe games running', value=ttt_games)
if bj:
bj_games = len(bj.games)
if bj_games:
embed.add_field(name='Total blackjack games running', value=bj_games)
if interaction:
count_battles = 0
for battles in self.bot.get_cog('Interaction').battles.values():
count_battles += len(battles)
if count_battles:
embed.add_field(name='Total battles games running', value=count_battles)
if music:
songs = len([x for x in music.voice_states.values() if x.playing])
if songs:
embed.add_field(name='Total songs playing', value=songs)
if hasattr(self.bot, 'uptime'):
embed.add_field(name='Uptime', value=(pendulum.utcnow() - self.bot.uptime).in_words())
2017-04-21 15:03:52 +12:00
2017-06-07 20:30:19 +12:00
memory_usage = self.process.memory_full_info().uss / 1024 ** 2
2017-04-21 15:03:52 +12:00
cpu_usage = self.process.cpu_percent() / psutil.cpu_count()
embed.add_field(name='Memory Usage', value='{:.2f} MiB'.format(memory_usage))
2017-04-21 15:04:48 +12:00
embed.add_field(name='CPU Usage', value='{}%'.format(cpu_usage))
embed.set_footer(text=self.bot.description)
await ctx.send(embed=embed)
2016-07-31 02:59:35 +12:00
@commands.command()
@utils.custom_perms(send_messages=True)
@utils.check_restricted()
async def uptime(self, ctx):
"""Provides a printout of the current bot's uptime
EXAMPLE: !uptime
RESULT: A BAJILLION DAYS"""
if hasattr(self.bot, 'uptime'):
await ctx.send("Uptime: ```\n{}```".format((pendulum.utcnow() - self.bot.uptime).in_words()))
else:
await ctx.send("I've just restarted and not quite ready yet...gimme time I'm not a morning pony :c")
2016-07-19 11:25:03 +12:00
@commands.command(aliases=['invite'])
@utils.custom_perms(send_messages=True)
@utils.check_restricted()
async def addbot(self, ctx):
"""Provides a link that you can use to add me to a server
EXAMPLE: !addbot
RESULT: http://discord.gg/yo_mama"""
perms = discord.Permissions.none()
perms.read_messages = True
perms.send_messages = True
perms.manage_roles = True
perms.ban_members = True
perms.kick_members = True
perms.manage_messages = True
perms.embed_links = True
perms.read_message_history = True
perms.attach_files = True
perms.speak = True
perms.connect = True
perms.attach_files = True
perms.add_reactions = True
app_info = await self.bot.application_info()
2017-07-03 15:18:33 +12:00
await ctx.send("Use this URL to add me to a server that you'd like!\n<{}>"
2017-03-08 11:35:30 +13:00
.format(discord.utils.oauth_url(app_info.id, perms)))
2017-06-07 20:30:19 +12:00
@commands.command(enabled=False)
@utils.custom_perms(send_messages=True)
@utils.check_restricted()
async def joke(self, ctx):
"""Prints a random riddle
EXAMPLE: !joke
RESULT: An absolutely terrible joke."""
2017-06-07 20:30:19 +12:00
# Currently disabled until I can find a free API
pass
2016-07-09 13:27:19 +12:00
@commands.command()
@utils.custom_perms(send_messages=True)
@utils.check_restricted()
2017-06-29 10:43:28 +12:00
async def roll(self, ctx, *, notation: str = "d6"):
"""Rolls a die based on the notation given
Format should be #d#
EXAMPLE: !roll d50
RESULT: 51 :^)"""
# Use regex to get the notation based on what was provided
try:
# We do not want to try to convert the dice, because we want d# to
# be a valid notation
dice = re.search("(\d*)d(\d*)", notation).group(1)
num = int(re.search("(\d*)d(\d*)", notation).group(2))
2017-06-29 10:43:28 +12:00
# Attempt to get addition/subtraction
add = re.search("\+ ?(\d+)", notation)
subtract = re.search("- ?(\d+)", notation)
# Check if something like ed3 was provided, or something else entirely
# was provided
except (AttributeError, ValueError):
await ctx.send("Please provide the die notation in #d#!")
return
2016-07-17 02:20:17 +12:00
# Dice will be None if d# was provided, assume this means 1d#
dice = dice or 1
# Since we did not try to convert to int before, do it now after we
# have it set
dice = int(dice)
if dice > 10:
await ctx.send("I'm not rolling more than 10 dice, I have tiny hands")
return
if num > 100:
await ctx.send("What die has more than 100 sides? Please, calm down")
return
if num <= 1:
await ctx.send("A {} sided die? You know that's impossible right?".format(num))
return
2017-03-08 11:35:30 +13:00
nums = [random.SystemRandom().randint(1, num) for _ in range(0, int(dice))]
2017-06-29 10:43:28 +12:00
subtotal = total = sum(nums)
# After totalling, if we have add/subtract seperately, apply them
if add:
add = int(add.group(1))
total += add
if subtract:
subtract = int(subtract.group(1))
total -= subtract
value_str = ", ".join("{}".format(x) for x in nums)
if dice == 1:
2017-06-29 10:43:28 +12:00
fmt = '{0.message.author.name} has rolled a {1} sided die and got the number {2}!'.format(ctx, num, value_str)
if add or subtract:
fmt += "\nTotal: {} ({}".format(total, subtotal)
if add:
fmt += " + {}".format(add)
if subtract:
fmt += " - {}".format(subtract)
fmt += ")"
else:
2017-06-29 10:43:28 +12:00
fmt = '{0.message.author.name} has rolled {1}, {2} sided dice and got the numbers {3}!'.format(ctx, dice, num, value_str)
if add or subtract:
fmt += "\nTotal: {} ({}".format(total, subtotal)
if add:
fmt += " + {}".format(add)
if subtract:
fmt += " - {}".format(subtract)
fmt += ")"
else:
fmt += "\nTotal: {}".format(total)
await ctx.send(fmt)
2016-07-09 13:27:19 +12:00
2016-07-13 03:58:57 +12:00
2016-07-09 13:27:19 +12:00
def setup(bot):
bot.add_cog(Miscallaneous(bot))