@ -1,34 +1,20 @@
import os
import asyncio
import sys
import logging
import logging.handlers
import traceback
import aiohttp
import config
import discord
from discord.ext import commands
script_name = os . path . basename ( __file__ ) . split ( ' . ' ) [ 0 ]
log_file_name = f " {script_name}.log "
# Limit of discord (non-nitro) is 8MB (not MiB)
max_file_size = 1000 * 1000 * 8
backup_count = 3
file_handler = logging . handlers . RotatingFileHandler (
filename = log_file_name , maxBytes = max_file_size , backupCount = backup_count )
stdout_handler = logging . StreamHandler ( sys . stdout )
log_format = logging . Formatter (
' [ %(asctime)s ] { %(filename)s : %(lineno)d } %(levelname)s - %(message)s ' )
file_handler . setFormatter ( log_format )
" [ %(asctime)s ] { %(filename)s : %(lineno)d } %(levelname)s - %(message)s "
)
stdout_handler . setFormatter ( log_format )
log = logging . getLogger ( ' discord ')
log = logging . getLogger ( " discord " )
log . setLevel ( logging . INFO )
log . addHandler ( file_handler )
log . addHandler ( stdout_handler )
@ -38,87 +24,49 @@ def get_prefix(bot, message):
return commands . when_mentioned_or ( * prefixes ) ( bot , message )
wanted_jsons = [ " data/restrictions.json " ,
" data/robocronptab.json " ,
" data/userlog.json " ,
" data/invites.json " ]
initial_extensions = [ ' cogs.common ' ,
' cogs.admin ' ,
' cogs.mod ' ,
' cogs.mod_mail ' ,
' cogs.mod_note ' ,
' cogs.mod_reacts ' ,
' cogs.mod_stats ' ,
' cogs.mod_userlog ' ,
' cogs.mod_timed ' ,
' cogs.mod_watch ' ,
' cogs.basic ' ,
' cogs.logs ' ,
' cogs.lockdown ' ,
' cogs.links ' ,
' cogs.lists ' ,
' cogs.lists_verification ' ,
' cogs.remind ' ,
' cogs.robocronp ' ,
' cogs.meme ' ,
' cogs.uwu ' ]
bot = commands . Bot ( command_prefix = get_prefix ,
description = config . bot_description , pm_help = True )
initial_extensions = [
" cogs.common " ,
" cogs.admin " ,
" cogs.basic " ,
" cogs.links " ,
" cogs.lists " ,
" cogs.meme " ,
" cogs.uwu " ,
]
bot = commands . Bot (
command_prefix = get_prefix , description = config . bot_description , pm_help = True
)
bot . log = log
bot . loop = asyncio . get_event_loop ( )
bot . config = config
bot . script_name = script_name
bot . wanted_jsons = wanted_jsons
if __name__ == ' __main__ ':
if __name__ == " __main__ " :
for extension in initial_extensions :
try :
bot . load_extension ( extension )
except Exception as e :
log . error ( f ' Failed to load extension {extension}. ')
log . error ( f " Failed to load extension {extension}. " )
log . error ( traceback . print_exc ( ) )
@bot.event
async def on_ready ( ) :
aioh = { " User-Agent " : f " {script_name}/1.0 ' " }
bot . aiosession = aiohttp . ClientSession ( headers = aioh )
bot . app_info = await bot . application_info ( )
bot . botlog_channel = bot . get_channel ( config . botlog_channel )
log . info ( f ' \n Logged in as: {bot.user.name} - '
f ' {bot.user.id} \n dpy version: {discord.__version__} \n ' )
log . info (
f " \n Logged in as: {bot.user.name} - "
f " {bot.user.id} \n dpy version: {discord.__version__} \n "
)
game_name = f " {config.prefixes[0]}help "
# Send "Robocop has started! x has y members!"
guild = bot . botlog_channel . guild
msg = f " {bot.user.name} has started! " \
f " {guild.name} has {guild.member_count} members! "
data_files = [ discord . File ( fpath ) for fpath in wanted_jsons ]
await bot . botlog_channel . send ( msg , files = data_files )
msg = f " {bot.user.name} has started! "
await bot . botlog_channel . send ( msg )
activity = discord . Activity ( name = game_name ,
type = discord . ActivityType . listening )
activity = discord . Activity ( name = game_name , type = discord . ActivityType . listening )
await bot . change_presence ( activity = activity )
@bot.event
async def on_command ( ctx ) :
log_text = f " {ctx.message.author} ({ctx.message.author.id}): " \
f " \" {ctx.message.content} \" "
if ctx . guild : # was too long for tertiary if
log_text + = f " on \" {ctx.channel.name} \" ({ctx.channel.id}) " \
f " at \" {ctx.guild.name} \" ({ctx.guild.id}) "
else :
log_text + = f " on DMs ({ctx.channel.id}) "
log . info ( log_text )
@bot.event
async def on_error ( event_method , * args , * * kwargs ) :
log . error ( f " Error on {event_method}: {sys.exc_info()} " )
@ -128,9 +76,11 @@ async def on_error(event_method, *args, **kwargs):
async def on_command_error ( ctx , error ) :
error_text = str ( error )
err_msg = f " Error with \" {ctx.message.content} \" from " \
f " \" {ctx.message.author} ({ctx.message.author.id}) " \
f " of type {type(error)}: {error_text} "
err_msg = (
f ' Error with " {ctx.message.content} " from '
f " {ctx.message.author} ({ctx.message.author.id}) "
f " of type {type(error)}: {error_text} "
)
log . error ( err_msg )
@ -141,71 +91,60 @@ async def on_command_error(ctx, error):
if isinstance ( error , commands . NoPrivateMessage ) :
return await ctx . send ( " This command doesn ' t work on DMs. " )
elif isinstance ( error , commands . MissingPermissions ) :
roles_needed = ' \n - ' . join ( error . missing_perms )
return await ctx . send ( f " {ctx.author.mention}: You don ' t have the right "
" permissions to run this command. You need: "
f " ```- {roles_needed}``` " )
roles_needed = " \n - " . join ( error . missing_perms )
return await ctx . send (
f " {ctx.author.mention}: You don ' t have the right "
" permissions to run this command. You need: "
f " ```- {roles_needed}``` "
)
elif isinstance ( error , commands . BotMissingPermissions ) :
roles_needed = ' \n - ' . join ( error . missing_perms )
return await ctx . send ( f " {ctx.author.mention}: Bot doesn ' t have "
" the right permissions to run this command. "
" Please add the following roles: "
f " ```- {roles_needed}``` " )
roles_needed = " \n - " . join ( error . missing_perms )
return await ctx . send (
f " {ctx.author.mention}: Bot doesn ' t have "
" the right permissions to run this command. "
" Please add the following roles: "
f " ```- {roles_needed}``` "
)
elif isinstance ( error , commands . CommandOnCooldown ) :
return await ctx . send ( f " {ctx.author.mention}: You ' re being "
" ratelimited. Try in "
f " {error.retry_after:.1f} seconds. " )
return await ctx . send (
f " {ctx.author.mention}: You ' re being "
" ratelimited. Try in "
f " {error.retry_after:.1f} seconds. "
)
elif isinstance ( error , commands . CheckFailure ) :
return await ctx . send ( f " {ctx.author.mention}: Check failed. "
" You might not have the right permissions "
" to run this command, or you may not be able "
" to run this command in the current channel. " )
elif isinstance ( error , commands . CommandInvokeError ) and \
( " Cannot send messages to this user " in error_text ) :
return await ctx . send ( f " {ctx.author.mention}: I can ' t DM you. \n "
" You might have me blocked or have DMs "
f " blocked globally or for {ctx.guild.name}. \n "
" Please resolve that, then "
" run the command again. " )
return await ctx . send (
f " {ctx.author.mention}: Check failed. "
" You might not have the right permissions "
" to run this command, or you may not be able "
" to run this command in the current channel. "
)
elif isinstance ( error , commands . CommandInvokeError ) and (
" Cannot send messages to this user " in error_text
) :
return await ctx . send (
f " {ctx.author.mention}: I can ' t DM you. \n "
" You might have me blocked or have DMs "
f " blocked globally or for {ctx.guild.name}. \n "
" Please resolve that, then "
" run the command again. "
)
elif isinstance ( error , commands . CommandNotFound ) :
# Nothing to do when command is not found.
return
help_text = f " Usage of this command is: ```{ctx.prefix} " \
f " {ctx.command.signature}``` \n Please see `{ctx.prefix}help " \
f " {ctx.command.name}` for more info about this command. "
help_text = (
f " Usage of this command is: ```{ctx.prefix} "
f " {ctx.command.signature}``` \n Please see `{ctx.prefix}help "
f " {ctx.command.name}` for more info about this command. "
)
if isinstance ( error , commands . BadArgument ) :
return await ctx . send ( f " {ctx.author.mention}: You gave incorrect "
f " arguments. {help_text} " )
return await ctx . send (
f " {ctx.author.mention}: You gave incorrect " f " arguments. {help_text} "
)
elif isinstance ( error , commands . MissingRequiredArgument ) :
return await ctx . send ( f " {ctx.author.mention}: You gave incomplete "
f " arguments. {help_text} " )
@bot.event
async def on_message ( message ) :
if message . author . bot :
return
if ( message . guild ) and ( message . guild . id not in config . guild_whitelist ) :
return
# Ignore messages in newcomers channel, unless it's potentially
# an allowed command
welcome_allowed = [ " reset " , " kick " , " ban " , " warn " ]
if message . channel . id == config . welcome_channel and \
not any ( cmd in message . content for cmd in welcome_allowed ) :
return
ctx = await bot . get_context ( message )
await bot . invoke ( ctx )
if not os . path . exists ( " data " ) :
os . makedirs ( " data " )
return await ctx . send (
f " {ctx.author.mention}: You gave incomplete " f " arguments. {help_text} "
)
for wanted_json in wanted_jsons :
if not os . path . exists ( wanted_json ) :
with open ( wanted_json , " w " ) as f :
f . write ( " {} " )
bot . run ( config . token , bot = True , reconnect = True )