2016-07-08 01:05:42 +12:00
|
|
|
#!/usr/local/bin/python3.5
|
2016-07-09 11:26:43 +12:00
|
|
|
import discord
|
2016-07-19 07:57:23 +12:00
|
|
|
import traceback
|
2016-07-31 02:59:35 +12:00
|
|
|
import logging
|
|
|
|
import datetime
|
2016-08-07 10:20:16 +12:00
|
|
|
import pendulum
|
2016-08-12 14:13:02 +12:00
|
|
|
import os
|
|
|
|
|
2016-08-26 16:56:16 +12:00
|
|
|
os.chdir(os.path.dirname(os.path.realpath(__file__)))
|
2016-07-09 11:26:43 +12:00
|
|
|
|
2016-08-27 01:23:02 +12:00
|
|
|
from discord.ext import commands
|
|
|
|
from cogs.utils import config
|
|
|
|
|
2016-07-09 13:27:19 +12:00
|
|
|
extensions = ['cogs.interaction',
|
|
|
|
'cogs.core',
|
|
|
|
'cogs.mod',
|
|
|
|
'cogs.owner',
|
|
|
|
'cogs.stats',
|
2016-07-11 05:28:16 +12:00
|
|
|
'cogs.playlist',
|
2016-07-14 16:00:30 +12:00
|
|
|
'cogs.twitch',
|
2016-08-10 14:13:53 +12:00
|
|
|
'cogs.picarto',
|
2016-07-24 00:04:33 +12:00
|
|
|
'cogs.overwatch',
|
|
|
|
'cogs.links',
|
2016-08-01 03:25:17 +12:00
|
|
|
'cogs.tags',
|
2016-08-02 01:57:09 +12:00
|
|
|
'cogs.roles',
|
2016-08-15 14:10:12 +12:00
|
|
|
'cogs.strawpoll',
|
|
|
|
'cogs.tictactoe',
|
2016-09-01 07:48:07 +12:00
|
|
|
'cogs.hangman',
|
|
|
|
'cogs.statsupdate']
|
2016-07-08 10:10:24 +12:00
|
|
|
|
2016-08-31 10:33:46 +12:00
|
|
|
opts = {'command_prefix': config.command_prefix,
|
|
|
|
'description': config.bot_description,
|
2016-08-31 07:16:24 +12:00
|
|
|
'pm_help': None,
|
|
|
|
'shard_count': config.shard_count,
|
|
|
|
'shard_id': config.shard_id}
|
2016-08-31 07:51:04 +12:00
|
|
|
|
2016-08-31 07:16:24 +12:00
|
|
|
bot = commands.Bot(**opts)
|
2016-08-31 09:21:02 +12:00
|
|
|
logging.basicConfig(level=logging.INFO, filename='bonfire.log')
|
2016-07-08 10:10:24 +12:00
|
|
|
|
2016-07-31 12:20:55 +12:00
|
|
|
|
2016-07-08 01:05:42 +12:00
|
|
|
@bot.event
|
|
|
|
async def on_ready():
|
2016-07-08 10:10:24 +12:00
|
|
|
# Change the status upon connection to the default status
|
2016-08-31 07:51:04 +12:00
|
|
|
await bot.change_status(discord.Game(name=config.default_status, type=0))
|
2016-08-31 13:48:30 +12:00
|
|
|
channel_id = await config.get_content('restart_server')
|
|
|
|
channel_id = channel_id or 0
|
2016-08-11 12:46:23 +12:00
|
|
|
|
2016-09-01 09:19:39 +12:00
|
|
|
if not hasattr(bot, 'uptime'):
|
|
|
|
bot.uptime = pendulum.utcnow()
|
|
|
|
|
2016-08-11 12:46:23 +12:00
|
|
|
# Just in case the bot was restarted while someone was battling, clear it so they do not get stuck
|
2016-08-31 12:11:25 +12:00
|
|
|
await config.save_content('battling', {})
|
2016-08-16 08:43:18 +12:00
|
|
|
# Check if the bot was restarted, if so send a message to the channel the bot was restarted from
|
2016-07-18 05:17:42 +12:00
|
|
|
if channel_id != 0:
|
|
|
|
destination = discord.utils.find(lambda m: m.id == channel_id, bot.get_all_channels())
|
2016-07-09 13:27:19 +12:00
|
|
|
await bot.send_message(destination, "I have just finished restarting!")
|
2016-08-31 12:11:25 +12:00
|
|
|
await config.save_content('restart_server', 0)
|
2016-07-08 01:05:42 +12:00
|
|
|
|
2016-08-04 13:31:38 +12:00
|
|
|
|
2016-08-02 03:28:00 +12:00
|
|
|
@bot.event
|
|
|
|
async def on_member_join(member):
|
2016-08-31 13:48:30 +12:00
|
|
|
notifications = await config.get_content('user_notifications')
|
2016-08-02 03:28:00 +12:00
|
|
|
server_notifications = notifications.get(member.server.id)
|
2016-08-26 16:56:16 +12:00
|
|
|
|
2016-08-16 08:43:18 +12:00
|
|
|
# By default, notifications should be off unless explicitly turned on
|
2016-08-02 03:28:00 +12:00
|
|
|
if not server_notifications:
|
|
|
|
return
|
2016-08-04 13:31:38 +12:00
|
|
|
|
|
|
|
channel = discord.utils.get(member.server.channels, id=server_notifications)
|
2016-08-02 04:10:20 +12:00
|
|
|
await bot.send_message(channel, "Welcome to the '{0.server.name}' server {0.mention}!".format(member))
|
2016-08-02 03:28:00 +12:00
|
|
|
|
|
|
|
|
|
|
|
@bot.event
|
|
|
|
async def on_member_remove(member):
|
2016-08-31 13:48:30 +12:00
|
|
|
notifications = await config.get_content('user_notifications')
|
2016-08-02 03:28:00 +12:00
|
|
|
server_notifications = notifications.get(member.server.id)
|
2016-08-26 16:56:16 +12:00
|
|
|
|
2016-08-16 08:43:18 +12:00
|
|
|
# By default, notifications should be off unless explicitly turned on
|
2016-08-02 03:28:00 +12:00
|
|
|
if not server_notifications:
|
|
|
|
return
|
2016-08-04 13:31:38 +12:00
|
|
|
|
|
|
|
channel = discord.utils.get(member.server.channels, id=server_notifications)
|
2016-08-02 04:10:20 +12:00
|
|
|
await bot.send_message(channel,
|
2016-08-04 13:31:38 +12:00
|
|
|
"{0} has left the server, I hope it wasn't because of something I said :c".format(
|
|
|
|
member.display_name))
|
2016-08-02 03:28:00 +12:00
|
|
|
|
2016-07-11 09:57:52 +12:00
|
|
|
|
2016-07-10 04:40:27 +12:00
|
|
|
@bot.event
|
|
|
|
async def on_message(message):
|
|
|
|
if message.author.bot:
|
|
|
|
return
|
|
|
|
await bot.process_commands(message)
|
2016-07-08 10:10:24 +12:00
|
|
|
|
2016-09-24 14:38:58 +12:00
|
|
|
@bot.event
|
|
|
|
async def on_command_completion(command, ctx):
|
|
|
|
# There's no reason to continue waiting for this to complete, so lets immediately lanch this in a new future
|
|
|
|
bot.loop.create_task(process_command(command, ctx))
|
|
|
|
|
|
|
|
async def process_command(command, ctx):
|
|
|
|
# This try catch is only here while this is first being implemented
|
|
|
|
# It will be removed once I ensure this is working correctly
|
|
|
|
try:
|
|
|
|
author = ctx.message.author
|
|
|
|
server = ctx.message.server
|
|
|
|
|
|
|
|
total_command_usage = await config.get_content('command_usage')
|
|
|
|
command_usage = total_command_usage.get(command.qualified_name, {})
|
|
|
|
# Add one to the total usage for this command, basing it off 0 to start with (obviously)
|
|
|
|
total_usage = command_usage.get('total_usage', 0) + 1
|
|
|
|
command_usage['total_usage'] = total_usage
|
|
|
|
|
|
|
|
# Add one to the author's usage for this command
|
|
|
|
total_member_usage = command_usage.get('member_usage',{})
|
|
|
|
member_usage = total_member_usage.get(author.id, 0) + 1
|
|
|
|
command_usage['member_usage'] = member_usage
|
|
|
|
|
|
|
|
# Add one to the server's usage for this command
|
|
|
|
total_server_usage = command_usage.get('server_usage', {})
|
|
|
|
server_usage = total_server_usage.get(server.id, 0) + 1
|
|
|
|
command_usage['server_usage'] = server_usage
|
|
|
|
|
|
|
|
# Save all the changes
|
|
|
|
total_command_usage[command.qualified_name] = command_usage
|
|
|
|
await config.save_content('command_usage', total_command_usage)
|
|
|
|
except Exception as error:
|
|
|
|
with open("error_log", 'a') as f:
|
|
|
|
traceback.print_tb(error.__traceback__, file=f)
|
|
|
|
print('{0.__class__.__name__}: {0}'.format(error), file=f)
|
2016-08-04 13:31:38 +12:00
|
|
|
|
2016-09-01 07:09:47 +12:00
|
|
|
|
2016-07-09 13:42:33 +12:00
|
|
|
@bot.event
|
|
|
|
async def on_command_error(error, ctx):
|
2016-09-18 13:29:48 +12:00
|
|
|
if isinstance(error, commands.CommandNotFound):
|
|
|
|
return
|
2016-09-23 13:48:18 +12:00
|
|
|
try:
|
|
|
|
if isinstance(error.original, discord.Forbidden):
|
|
|
|
return
|
|
|
|
except AttributeError:
|
|
|
|
pass
|
|
|
|
|
2016-08-02 01:10:52 +12:00
|
|
|
if isinstance(error, commands.BadArgument):
|
2016-07-12 03:01:59 +12:00
|
|
|
fmt = "Please provide a valid argument to pass to the command: {}".format(error)
|
2016-07-12 00:40:03 +12:00
|
|
|
await bot.send_message(ctx.message.channel, fmt)
|
2016-07-14 09:16:47 +12:00
|
|
|
elif isinstance(error, commands.CheckFailure):
|
2016-07-14 09:24:21 +12:00
|
|
|
fmt = "You can't tell me what to do!"
|
2016-07-14 09:16:47 +12:00
|
|
|
await bot.send_message(ctx.message.channel, fmt)
|
2016-07-24 04:39:25 +12:00
|
|
|
elif isinstance(error, commands.CommandOnCooldown):
|
2016-08-04 13:40:35 +12:00
|
|
|
m, s = divmod(error.retry_after, 60)
|
2016-08-07 10:20:16 +12:00
|
|
|
fmt = "This command is on cooldown! Hold your horses! >:c\nTry again in {} minutes and {} seconds" \
|
2016-08-04 13:40:35 +12:00
|
|
|
.format(round(m), round(s))
|
2016-07-24 04:39:25 +12:00
|
|
|
await bot.send_message(ctx.message.channel, fmt)
|
2016-08-07 23:53:41 +12:00
|
|
|
elif isinstance(error, commands.NoPrivateMessage):
|
2016-08-07 23:52:20 +12:00
|
|
|
fmt = "This command cannot be used in a private message"
|
|
|
|
await bot.send_message(ctx.message.channel, fmt)
|
2016-08-09 11:57:33 +12:00
|
|
|
elif isinstance(error, commands.MissingRequiredArgument):
|
|
|
|
await bot.send_message(ctx.message.channel, error)
|
2016-09-12 10:34:28 +12:00
|
|
|
else:
|
2016-08-07 00:16:49 +12:00
|
|
|
now = datetime.datetime.now()
|
2016-08-12 14:13:02 +12:00
|
|
|
with open("error_log", 'a') as f:
|
2016-08-07 10:20:16 +12:00
|
|
|
print("In server '{0.message.server}' at {1}\nFull command: `{0.message.content}`".format(ctx, str(now)),
|
|
|
|
file=f)
|
2016-08-07 23:47:42 +12:00
|
|
|
try:
|
|
|
|
traceback.print_tb(error.original.__traceback__, file=f)
|
2016-08-07 23:49:01 +12:00
|
|
|
print('{0.__class__.__name__}: {0}'.format(error.original), file=f)
|
2016-08-07 23:47:42 +12:00
|
|
|
except:
|
2016-08-07 23:52:20 +12:00
|
|
|
traceback.print_tb(error.__traceback__, file=f)
|
2016-08-07 23:49:01 +12:00
|
|
|
print('{0.__class__.__name__}: {0}'.format(error), file=f)
|
2016-07-31 12:20:55 +12:00
|
|
|
|
2016-07-18 09:10:12 +12:00
|
|
|
|
2016-07-09 13:27:19 +12:00
|
|
|
if __name__ == '__main__':
|
|
|
|
for e in extensions:
|
|
|
|
bot.load_extension(e)
|
2016-08-31 07:51:04 +12:00
|
|
|
bot.run(config.bot_token)
|