Initial Upload of Geeksbot Files

This commit is contained in:
Dusty.P
2018-04-13 23:10:36 -08:00
parent eb4110e1e6
commit 465e22163f
41 changed files with 2999 additions and 0 deletions
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+269
View File
@@ -0,0 +1,269 @@
import discord
from discord.ext import commands
import json
from srcds import rcon as rcon_con
import time, logging, math
from datetime import datetime, timedelta
import asyncio, inspect
import aiohttp, async_timeout
from bs4 import BeautifulSoup as bs
import traceback
import os, sys
from .imports import checks
config_dir = 'config/'
admin_id_file = 'admin_ids'
extension_dir = 'extensions'
owner_id = 351794468870946827
embed_color = discord.Colour.from_rgb(49,107,111)
bot_config_file = 'bot_config.json'
invite_match = '(https?://)?(www.)?discord(app.com/(invite|oauth2)|.gg|.io)/[\w\d_\-?=&/]+'
admin_log = logging.getLogger('admin')
class admin():
def __init__(self, bot):
self.bot = bot
def _get_config_string(self, guild_config):
config_str = ''
for config in guild_config:
if isinstance(guild_config[config], dict):
config_str = f'{config_str}\n{" "*4}{config}'
for item in guild_config[config]:
config_str = f'{config_str}\n{" "*8}{item}: {guild_config[config][item]}'
elif isinstance(guild_config[config], list):
config_str = f'{config_str}\n{" "*4}{config}'
for item in guild_config[config]:
config_str = f'{config_str}\n{" "*8}{item}'
else:
config_str = f'{config_str}\n{" "*4}{config}: {guild_config[config]}'
return config_str
@commands.command(hidden=True)
@commands.is_owner()
async def reload_bot_config(self, ctx):
with open(f'{config_dir}{bot_config_file}') as file:
self.bot.bot_config = json.load(file)
del self.bot.bot_config['token']
del self.bot.bot_config['db_con']
await ctx.send('Config reloaded.')
@commands.command(hidden=True)
@commands.is_owner()
async def reboot(self, ctx):
await ctx.send('Geeksbot is restarting.')
with open(f'{config_dir}reboot', 'w') as f:
f.write(f'1\n{ctx.channel.id}')
os._exit(1)
@commands.command(hidden=True)
@commands.is_owner()
async def get_bot_config(self, ctx):
n = 2000
config = [str(self.bot.bot_config)[i:i+n] for i in range(0, len(str(self.bot.bot_config)), n)]
for conf in config:
await ctx.message.author.send(conf)
await ctx.send(f'{ctx.message.author.mention} check your DMs.')
@commands.command(hidden=True)
@commands.is_owner()
async def update_emojis(self, ctx):
emojis = self.bot.emojis
for emoji in emojis:
if emoji.animated:
emoji_code = f'<a:{emoji.name}:{emoji.id}>'
else:
emoji_code = f'<:{emoji.name}:{emoji.id}>'
if self.bot.con.all(f'select id from geeksbot_emojis where id = %(id)s', {'id':emoji.id}):
self.bot.con.run(f"update geeksbot_emojis set id = %(id)s, name = %(name)s, code = %(emoji_code)s where name = %(name)s", {'name':emoji.name,'id':emoji.id,'emoji_code':emoji_code})
else:
self.bot.con.run(f"insert into geeksbot_emojis(id,name,code) values (%(id)s,%(name)s,%(emoji_code)s)", {'name':emoji.name,'id':emoji.id,'emoji_code':emoji_code})
await ctx.message.add_reaction('')
await ctx.send(f'Emojis have been updated in the database.')
@commands.command(hidden=True)
@commands.check(checks.is_guild_owner)
async def get_guild_config(self, ctx):
config = self.bot.con.one(f'select * from guild_config where guild_id = {ctx.guild.id}')
configs = [str(config)[i:i+1990] for i in range(0, len(config), 1990)]
await ctx.message.author.send(f'The current config for the {ctx.guild.name} guild is:\n')
admin_log.info(configs)
for config in configs:
await ctx.message.author.send(f'```{config}```')
await ctx.send(f'{ctx.message.author.mention} check your DMs.')
@commands.group(case_insensitive=True)
async def set(self, ctx):
'''Run help set for more info'''
pass
@commands.group(case_insensitive=True)
async def add(self, ctx):
'''Run help set for more info'''
pass
@commands.group(case_insensitive=True)
async def remove(self, ctx):
'''Run help set for more info'''
pass
@set.command(name='admin_chan', aliases=['ac', 'admin_chat', 'admin chat'])
async def _admin_channel(self, ctx, channel:discord.TextChannel=None):
if ctx.guild:
if checks.is_admin(self.bot, ctx):
if channel != None:
self.bot.con.run(f'update guild_config set admin_chat = %(chan)s where guild_id = {ctx.guild.id}', {'chan': channel.id})
await ctx.send(f'{channel.name} is now set as the Admin Chat channel for this guild.')
@set.command(name='channel_lockdown', aliases=['lockdown', 'restrict_access', 'cl'])
async def _channel_lockdown(self, ctx, config='true'):
if ctx.guild:
if checks.is_admin(self.bot, ctx):
if str(config).lower() == 'true':
if self.bot.con.one(f'select allowed_channels from guild_config where guild_id = {ctx.guild.id}') == []:
await ctx.send('Please set at least one allowed channel before running this command.')
else:
self.bot.con.run(f'update guild_config set channel_lockdown = True where guild_id = {ctx.guild.id}')
await ctx.send('Channel Lockdown is now active.')
elif str(config).lower() == 'false':
if self.bot.con.one(f'select channel_lockdown from guild_config where guild_id = {ctx.guild.id}'):
self.bot.con.run(f'update guild_config set channel_lockdown = False where guild_id = {ctx.guild.id}')
await ctx.send('Channel Lockdown has been deactivated.')
else:
await ctx.send('Channel Lockdown is already deactivated.')
else:
await ctx.send(f'You are not authorized to run this command.')
else:
await ctx.send('This command must be run from inside a guild.')
@add.command(name='allowed_channels', aliases=['channel','ac'])
async def _allowed_channels(self, ctx, *, channels):
if ctx.guild:
if checks.is_admin(self.bot, ctx):
channels = channels.lower().replace(' ','').split(',')
added = ''
for channel in channels:
chnl = discord.utils.get(ctx.guild.channels, name=channel)
if chnl == None:
await ctx.send(f'{channel} is not a valid text channel in this guild.')
else:
admin_log.info('Chan found')
if self.bot.con.one(f'select allowed_channels from guild_config where guild_id = {ctx.guild.id}'):
if chnl.id in json.loads(self.bot.con.one(f'select allowed_channels from guild_config where guild_id = {ctx.guild.id}')):
admin_log.info('Chan found in config')
await ctx.send(f'{channel} is already in the list of allowed channels. Skipping...')
else:
admin_log.info('Chan not found in config')
allowed_channels = json.loads(self.bot.con.one(f'select allowed_channels from guild_config where guild_id = {ctx.guild.id}')).append(chnl.id)
self.bot.con.run(f"update guild_config set allowed_channels = %(channels)s where guild_id = {ctx.guild.id}", {'channels':allowed_channels})
added = f'{added}\n{channel}'
else:
admin_log.info('Chan not found in config')
allowed_channels = [chnl.id]
self.bot.con.run(f"update guild_config set allowed_channels = %(channels)s where guild_id = {ctx.guild.id}", {'channels':allowed_channels})
added = f'{added}\n{channel}'
if added != '':
await ctx.send(f'The following channels have been added to the allowed channel list: {added}')
await ctx.message.add_reaction('')
else:
await ctx.send(f'You are not authorized to run this command.')
else:
await ctx.send('This command must be run from inside a guild.')
@commands.command()
@commands.is_owner()
async def view_code(self, ctx, code_name):
await ctx.send(f"```py\n{inspect.getsource(self.bot.get_command(code_name).callback)}\n```")
@add.command(aliases=['prefix','p'])
@commands.cooldown(1, 5, type=commands.BucketType.guild)
async def add_prefix(self, ctx, *, prefix=None):
if ctx.guild:
if checks.is_admin(self.bot, ctx):
prefixes = self.bot.con.one(f'select prefix from guild_config where guild_id = {ctx.guild.id}')
if prefix == None:
await ctx.send(prefixes)
return
elif prefixes == None:
prefixes = prefix.replace(' ',',').split(',')
else:
for p in prefix.replace(' ',',').split(','):
prefixes.append(p)
if len(prefixes) > 10:
await ctx.send(f'Only 10 prefixes are allowed per guild.\nPlease remove some before adding more.')
prefixes = prefixes[:10]
self.bot.con.run(f"update guild_config set prefix = %(prefixes)s where guild_id = {ctx.guild.id}", {'prefixes':prefixes})
await ctx.guild.me.edit(nick=f'[{prefixes[0]}] Geeksbot')
await ctx.send(f"Updated. You currently have {len(prefixes)} {'prefix' if len(prefixes) == 1 else 'prefixes'} in your config.\n{', '.join(prefixes)}")
else:
await ctx.send(f'You are not authorized to run this command.')
else:
await ctx.send(f'This command must be run from inside a guild.')
@remove.command(aliases=['prefix','p'])
@commands.cooldown(1, 5, type=commands.BucketType.guild)
async def remove_prefix(self, ctx, *, prefix=None):
if ctx.guild:
if checks.is_admin(self.bot, ctx):
prefixes = []
prefixes = self.bot.con.one(f'select prefix from guild_config where guild_id = {ctx.guild.id}')
found = 0
if prefix == None:
await ctx.send(prefixes)
return
elif prefixes == None or prefixes == []:
await ctx.send('There are no custom prefixes setup for this guild.')
return
else:
prefix = prefix.replace(' ',',').split(',')
for p in prefix:
if p in prefixes:
prefixes.remove(p)
found = 1
else:
await ctx.send(f'The prefix {p} is not in the config for this guild.')
if found:
self.bot.con.run(f"update guild_config set prefix = %(prefixes)s where guild_id = {ctx.guild.id}", {'prefixes':prefixes})
await ctx.guild.me.edit(nick=f'[{prefixes[0] if len(prefixes) != 0 else self.bot.default_prefix}] Geeksbot')
await ctx.send(f"Updated. You currently have {len(prefixes)} {'prefix' if len(prefixes) == 1 else 'prefixes'} in your config.\n{', '.join(prefixes)}")
else:
await ctx.send(f'You are not authorized to run this command.')
else:
await ctx.send(f'This command must be run from inside a guild.')
@add.command(name='admin_role', aliases=['admin'])
@commands.cooldown(1, 5, type=commands.BucketType.guild)
@commands.check(checks.is_guild_owner)
async def _add_admin_role(self, ctx, role=None):
role = discord.utils.get(ctx.guild.roles, name=role)
if role != None:
roles = json.loads(self.bot.con.one(f'select admin_roles from guild_config where guild_id = {ctx.guild.id}'))
if role.name in roles:
await ctx.send(f'{role.name} is already registered as an admin role in this guild.')
else:
roles[role.name] = role.id
self.bot.con.run(f"update guild_config set admin_roles = %(roles)s where guild_id = {ctx.guild.id}", {'roles':json.dumps(roles)})
await ctx.send(f'{role.name} has been added to the list of admin roles for this guild.')
else:
await ctx.send('You must include a role with this command.')
@remove.command(name='admin_role', aliases=['admin'])
@commands.cooldown(1, 5, type=commands.BucketType.guild)
@commands.check(checks.is_guild_owner)
async def _remove_admin_role(self, ctx, role=None):
role = discord.utils.get(ctx.guild.roles, name=role)
if role != None:
roles = json.loads(self.bot.con.one(f'select admin_roles from guild_config where guild_id = {ctx.guild.id}'))
if role.name in roles:
del roles[role.name]
self.bot.con.run(f"update guild_config set admin_roles = %(roles)s where guild_id = {ctx.guild.id}", {'roles':roles})
await ctx.send(f'{role.name} has been removed from the list of admin roles for this guild.')
else:
await ctx.send(f'{role.name} is not registered as an admin role in this guild.')
else:
await ctx.send('You must include a role with this command.')
def setup(bot):
bot.add_cog(admin(bot))
+245
View File
@@ -0,0 +1,245 @@
import discord
from discord.ext import commands
import logging
from datetime import datetime, timedelta
import json, asyncio, traceback
import os, re
from .imports import checks, utils
config_dir = 'config/'
admin_id_file = 'admin_ids'
extension_dir = 'extensions'
owner_id = 351794468870946827
guild_config_dir = 'guild_config/'
rcon_config_file = 'server_rcon_config'
dododex_url = 'http://www.dododex.com'
embed_color = discord.Colour.from_rgb(49,107,111)
red_color = discord.Colour.from_rgb(142,29,31)
bot_config_file = 'bot_config'
default_guild_config_file = 'default_guild_config.json'
events_log = logging.getLogger('events')
emojis = {
'x': '',
'y': '',
'poop': '💩',
'crown': '👑',
'eggplant': '🍆',
'sob': '😭',
'trident':'🔱'
}
class bot_events():
def __init__(self, bot):
self.bot = bot
def _get_config_string(self, guild_config):
config_str = ''
for config in guild_config:
if isinstance(guild_config[config], dict):
config_str = f'{config_str}\n{" "*4}{config}'
for item in guild_config[config]:
config_str = f'{config_str}\n{" "*8}{item}: {guild_config[config][item]}'
elif isinstance(guild_config[config], list):
config_str = f'{config_str}\n{" "*4}{config}'
for item in guild_config[config]:
config_str = f'{config_str}\n{" "*8}{item}'
else:
config_str = f'{config_str}\n{" "*4}{config}: {guild_config[config]}'
return config_str
async def on_raw_message_delete(self, msg_id, chan_id):
self.bot.con.run('update messages set deleted_at = %(time)s where id = %(id)s', {'time': datetime.utcnow(), 'id': msg_id})
async def on_raw_bulk_message_delete(self, msg_ids, chan_id):
sql = ''
for msg_id in msg_ids:
sql += f';update messages set deleted_at = %(time)s where id = {msg_id}'
self.bot.con.run(sql, {'time': datetime.utcnow()})
async def on_message(self, ctx):
try:
if ctx.author in self.bot.infected:
if datetime.now().timestamp() > self.bot.infected[ctx.author][1] + 300:
del self.bot.infected[ctx.author]
# await ctx.channel.send(f'{ctx.author.mention} You have been healed.')
else:
await ctx.add_reaction(self.bot.infected[ctx.author][0])
except:
pass
sql = 'insert into messages (id, tts, type, content, embeds, channel, mention_everyone, mentions, channel_mentions, role_mentions, webhook, attachments, pinned, reactions, guild, created_at, system_content, author) \
values (%(id)s, %(tts)s, %(type)s, %(content)s, %(embeds)s, %(channel)s, %(mention_everyone)s, %(mentions)s, %(channel_mentions)s, %(role_mentions)s, %(webhook)s, %(attachments)s, %(pinned)s, %(reactions)s, %(guild)s, %(created_at)s, %(system_content)s, %(author)s)'
msg_data = {}
msg_data['id'] = ctx.id
msg_data['tts'] = ctx.tts
msg_data['type'] = str(ctx.type)
msg_data['content'] = ctx.content
msg_data['embeds'] = [json.dumps(e.to_dict()) for e in ctx.embeds]
msg_data['channel'] = ctx.channel.id
msg_data['mention_everyone'] = ctx.mention_everyone
msg_data['mentions'] = [user.id for user in ctx.mentions]
msg_data['channel_mentions'] = [channel.id for channel in ctx.channel_mentions]
msg_data['role_mentions'] = [role.id for role in ctx.role_mentions]
msg_data['webhook'] = ctx.webhook_id
msg_data['attachments'] = [json.dumps({'id': a.id, 'size': a.size, 'height': a.height, 'width': a.width, 'filename': a.filename, 'url': a.url}) for a in ctx.attachments]
msg_data['pinned'] = ctx.pinned
msg_data['guild'] = ctx.guild.id
msg_data['created_at'] = ctx.created_at
msg_data['system_content'] = ctx.system_content
msg_data['author'] = ctx.author.id
msg_data['reactions'] = [json.dumps({'emoji': r.emoji, 'count': r.count}) for r in ctx.reactions]
self.bot.con.run(sql, msg_data)
if ctx.guild:
if ctx.author != ctx.guild.me:
if self.bot.con.one(f"select pg_filter from guild_config where guild_id = {ctx.guild.id}"):
profane = 0
for word in self.bot.con.one(f'select profane_words from guild_config where guild_id = {ctx.guild.id}'):
word = word.strip()
if word in ctx.content.lower():
events_log.info(f'Found non PG word {word}')
repl_str = '\*' * (len(word) - 1)
re_replace = re.compile(re.escape(word), re.IGNORECASE)
ctx.content = re_replace.sub(f'{word[:1]}{repl_str}', ctx.content)
profane = 1
if profane:
hook = await ctx.channel.create_webhook(name="PG Filter")
await ctx.delete()
if len(ctx.author.display_name) < 2:
username = f'{ctx.author.display_name}'
else:
username = ctx.author.display_name
await hook.send(ctx.content, username=username, avatar_url=ctx.author.avatar_url)
await hook.delete()
async def on_reaction_add(self,react,user):
if react.emoji == emojis['poop'] and react.message.author.id == 351794468870946827:
await react.message.remove_reaction(emojis['poop'],user)
await react.message.channel.send(f"You can't Poop on my Owner {user.mention} :P")
if react.emoji == emojis['poop'] and react.message.author.id == 396588996706304010:
await react.message.remove_reaction(emojis['poop'],user)
await react.message.channel.send(f"You can't Poop on me {user.mention} :P")
reactions = react.message.reactions
reacts = [json.dumps({'emoji': r.emoji, 'count': r.count}) for r in reactions]
self.bot.con.run(f'update messages set reactions = %(reacts)s where id = {react.message.id}', {'reacts': reacts})
async def on_message_edit(self, before, ctx):
previous_content = self.bot.con.one(f'select previous_content from messages where id = {ctx.id}')
if previous_content:
previous_content.append(before.content)
else:
previous_content = [before.content]
previous_embeds = self.bot.con.one(f'select previous_embeds from messages where id = {ctx.id}')
if previous_embeds:
previous_embeds.append([json.dumps(e.to_dict()) for e in before.embeds])
else:
previous_embeds = [[json.dumps(e.to_dict()) for e in before.embeds]]
sql = 'update messages set (edited_at, previous_content, previous_embeds, tts, type, content, embeds, channel, mention_everyone, mentions, channel_mentions, role_mentions, webhook, attachments, pinned, reactions, guild, created_at, system_content, author) \
= (%(edited_at)s, %(previous_content)s, %(previous_embeds)s, %(tts)s, %(type)s, %(content)s, %(embeds)s, %(channel)s, %(mention_everyone)s, %(mentions)s, %(channel_mentions)s, %(role_mentions)s, %(webhook)s, %(attachments)s, %(pinned)s, %(reactions)s, %(guild)s, %(created_at)s, %(system_content)s, %(author)s) \
where id = %(id)s'
msg_data = {}
msg_data['id'] = ctx.id
msg_data['tts'] = ctx.tts
msg_data['type'] = str(ctx.type)
msg_data['content'] = ctx.content
msg_data['embeds'] = [json.dumps(e.to_dict()) for e in ctx.embeds]
msg_data['channel'] = ctx.channel.id
msg_data['mention_everyone'] = ctx.mention_everyone
msg_data['mentions'] = [user.id for user in ctx.mentions]
msg_data['channel_mentions'] = [channel.id for channel in ctx.channel_mentions]
msg_data['role_mentions'] = [role.id for role in ctx.role_mentions]
msg_data['webhook'] = ctx.webhook_id
msg_data['attachments'] = ctx.attachments
msg_data['pinned'] = ctx.pinned
msg_data['guild'] = ctx.guild.id
msg_data['created_at'] = ctx.created_at
msg_data['system_content'] = ctx.system_content
msg_data['author'] = ctx.author.id
msg_data['reactions'] = [json.dumps({'emoji': r.emoji, 'count': r.count}) for r in ctx.reactions]
msg_data['previous_content'] = previous_content
msg_data['previous_embeds'] = previous_embeds
msg_data['edited_at'] = datetime.utcnow()
self.bot.con.run(sql, msg_data)
async def on_command_error(self,ctx,error):
if ctx.channel.id == 418452585683484680 and type(error) == discord.ext.commands.errors.CommandNotFound:
return
for page in utils.paginate(error):
await ctx.send(page)
async def on_guild_join(self, guild):
with open(f"{config_dir}{default_guild_config_file}",'r') as file:
default_config = json.loads(file.read())
admin_role = guild.role_hierarchy[0]
default_config['admin_roles'] = {admin_role.name: admin_role.id}
default_config['name'] = guild.name.replace("'","\\'")
default_config['guild_id'] = guild.id
events_log.info(default_config)
self.bot.con.run(f"insert into guild_config(guild_id,guild_name,admin_roles,rcon_enabled,channel_lockdown,raid_status,pg_filter,patreon_enabled,referral_enabled)\
values ({default_config['guild_id']},E'{default_config['name']}','{json.dumps(default_config['admin_roles'])}',{default_config['rcon_enabled']},{default_config['channel_lockdown']},{default_config['raid_status']},{default_config['pg_filter']},{default_config['patreon_enabled']},{default_config['referral_enabled']})")
events_log.info(f'Entry Created for {guild.name}')
config_str = self._get_config_string(default_config)
self.bot.recent_msgs[guild.id] = deque(maxlen=50)
await guild.me.edit(nick='[g$] Geeksbot')
# await guild.owner.send(f'Geeksbot has joined your guild {guild.name}!\nYour current configuration is:\n```{config_str}```\nEnjoy!')
async def on_guild_remove(self, guild):
self.bot.con.run(f'delete from guild_config where guild_id = {guild.id}')
events_log.info(f'Left the {guild.name} guild.')
async def on_member_join(self, member):
events_log.info(f'Member joined: {member.name} {member.id} Guild: {member.guild.name} {member.guild.id}')
join_chan = self.bot.con.one(f'select join_leave_chat from guild_config where guild_id = {member.guild.id}')
if join_chan:
em = discord.Embed( style='rich',
color=embed_color
)
em.set_thumbnail(url=member.avatar_url)
em.add_field(name=f'Welcome {member.name}#{member.discriminator}', value=member.id, inline=False)
em.add_field(name='User created on:', value=member.created_at.strftime('%Y-%m-%d at %H:%M:%S GMT'), inline=True)
em.add_field(name='Bot:', value=str(member.bot))
em.set_footer(text=f"{member.guild.name} | {member.joined_at.strftime('%Y-%m-%d at %H:%M:%S GMT')}", icon_url=member.guild.icon_url)
await discord.utils.get(member.guild.channels, id=join_chan).send(embed=em)
mem_data = {'id': member.id,
'name': member.name,
'discriminator': member.discriminator,
'bot': member.bot
}
mem = self.bot.con.one(f'select guilds,nicks from user_data where id = {member.id}')
if mem:
mem[1].append(json.dumps({member.guild.id: member.display_name}))
mem[0].append(member.guild.id)
mem_data['nicks'] = mem[1]
mem_data['guilds'] = mem[0]
self.bot.con.run(f'update user_data set (name, discriminator, bot, nicks, guilds) = (%(name)s, %(discriminator)s, %(bot)s, %(nicks)s, %(guilds)s) where id = %(id)s',mem_data)
else:
mem_data['nicks'] = [json.dumps({member.guild.id: member.display_name})]
mem_data['guilds'] = [member.guild.id]
self.bot.con.run(f'insert into user_data (id, name, discriminator, bot, nicks, guilds) values (%(id)s, %(name)s, %(discriminator)s, %(bot)s, %(nicks)s, %(guilds)s)',mem_data)
async def on_member_remove(self, member):
leave_time = datetime.utcnow()
events_log.info(f'Member left: {member.name} {member.id} Guild: {member.guild.name} {member.guild.id}')
join_chan = self.bot.con.one(f'select join_leave_chat from guild_config where guild_id = {member.guild.id}')
if join_chan:
em = discord.Embed( style='rich',
color=red_color
)
em.set_thumbnail(url=member.avatar_url)
em.add_field(name=f'RIP {member.name}#{member.discriminator}', value=member.id, inline=False)
join_time = member.joined_at
em.add_field(name='Joined on:', value=join_time.strftime('%Y-%m-%d at %H:%M:%S GMT'), inline=True)
em.add_field(name='Bot:', value=str(member.bot), inline=True)
em.add_field(name='Left on:', value=leave_time.strftime('%Y-%m-%d at %H:%M:%S GMT'), inline=False)
total_time = leave_time - join_time
days, remainder = divmod(total_time.total_seconds(), 86400)
hours, remainder = divmod(remainder, 3600)
minutes, seconds = divmod(remainder, 60)
time_str = f"{str(int(days)) + ' days, ' if days != 0 else ''}{str(int(hours)) + ' hours, ' if hours != 0 else ''}{str(int(minutes)) + ' minutes and ' if minutes != 0 else ''}{int(seconds)} seconds"
em.add_field(name='Total time in Guild:', value=time_str, inline=False)
em.set_footer(text=f"{member.guild.name} | {datetime.utcnow().strftime('%Y-%m-%d at %H:%M:%S GMT')}", icon_url=member.guild.icon_url)
await discord.utils.get(member.guild.channels, id=join_chan).send(embed=em)
def setup(bot):
bot.add_cog(bot_events(bot))
+143
View File
@@ -0,0 +1,143 @@
import discord
from discord.ext import commands
import logging
from datetime import datetime
import json, asyncio
import os, re, aiohttp, async_timeout
config_dir = 'config/'
admin_id_file = 'admin_ids'
extension_dir = 'extensions'
owner_id = 351794468870946827
guild_config_dir = 'guild_config/'
rcon_config_file = 'server_rcon_config'
dododex_url = 'http://www.dododex.com'
embed_color = discord.Colour.from_rgb(49,107,111)
bot_config_file = 'bot_config'
default_guild_config_file = 'default_guild_config.json'
emoji_guild = 408524303164899338
events_log = logging.getLogger('events')
emojis = {
'x': '',
'y': '',
'poop': '💩'
}
class fun():
def __init__(self, bot):
self.bot = bot
@commands.command()
@commands.cooldown(1, 30, type=commands.BucketType.user)
async def infect(self, ctx, member:discord.Member, emoji):
if member.id == self.bot.user.id and ctx.author.id != owner_id:
await ctx.send(f'You rolled a Critical Fail...\nInfection bounces off and rebounds on the attacker.')
member = ctx.author
if member in self.bot.infected:
await ctx.send(f'{member.display_name} is already infected. Please wait until they are healed before infecting them again...')
else:
emoji = self.bot.get_emoji(int(emoji.split(':')[2].strip('>'))) if '<:' in emoji or '<a:' in emoji else emoji
self.bot.infected[member] = [emoji,datetime.now().timestamp()]
await ctx.send(f"{member.display_name} has been infected with {emoji}")
@commands.command()
@commands.cooldown(1, 5, type=commands.BucketType.user)
async def heal(self, ctx, member:discord.Member):
if ctx.author == member and ctx.author.id != owner_id:
await ctx.send('You can\'t heal yourself silly...')
else:
if member in self.bot.infected:
del self.bot.infected[member]
await ctx.send(f'{member.mention} You have been healed by {ctx.author.display_name}.')
else:
await ctx.send(f'{member.display_name} is not infected...')
@commands.command()
@commands.is_owner()
async def print_infections(self, ctx):
await ctx.author.send(f'```{self.bot.infected}```')
@commands.command()
@commands.cooldown(1, 5, type=commands.BucketType.user)
async def slap(self, ctx, member:discord.Member):
if member.id == self.bot.user.id and ctx.author.id != owner_id:
await ctx.send(f'You rolled a Critical Fail...\nThe trout bounces off and rebounds on the attacker.')
member = ctx.author
await ctx.send(f'{ctx.author.mention} You slap yourself in the face with a large trout <:trout:408543365085397013>')
else:
await ctx.send(f'{ctx.author.display_name} slaps {member.mention} around a bit with a large trout <:trout:408543365085397013>')
def get_factorial(self,number):
a = 1
for i in range(1,int(number)):
a = a * (i + 1)
return a
# @commands.command()
# @commands.cooldown(1, 5, type=commands.BucketType.user)
# async def fact(self, ctx, number:int):
# if number < 20001 and number > 0:
# n = 1990
# with ctx.channel.typing():
# a = await self.bot.loop.run_in_executor(None, self.get_factorial, number)
# if len(str(a)) > 6000:
# for b in [str(a)[i:i+n] for i in range(0, len(str(a)), n)]:
# await ctx.author.send(f'```py\n{b}```')
# await ctx.send(f"{ctx.author.mention} Check your DMs.")
# else:
# for b in [str(a)[i:i+n] for i in range(0, len(str(a)), n)]:
# await ctx.send(f'```py\n{b}```')
# else:
# await ctx.send("Invalid number. Please enter a number between 0 and 20,000")
@commands.command(hidden=True)
@commands.is_owner()
async def play(self, ctx, url=None):
if ctx.author.voice.channel.name in self.bot.voice_chans:
if self.bot.voice_chans[ctx.author.voice.channel.name].is_playing():
await ctx.send('There is currently a song playing. Please wait until it is done...')
return
else:
self.bot.voice_chans[ctx.author.voice.channel.name] = await ctx.author.voice.channel.connect()
asyncio.sleep(5)
if url:
import youtube_dl
opts = {"format": 'webm[abr>0]/bestaudio/best',"ignoreerrors": True,"default_search": "auto","source_address": "0.0.0.0",'quiet': True}
ydl = youtube_dl.YoutubeDL(opts)
info = ydl.extract_info(url, download=False)
self.bot.player = discord.FFmpegPCMAudio(info['url'])
else:
self.bot.player = discord.FFmpegPCMAudio('dead_puppies.mp3')
self.bot.player = discord.PCMVolumeTransformer(self.bot.player, volume=0.3)
self.bot.voice_chans[ctx.author.voice.channel.name].play(self.bot.player)
@commands.command(hidden=True)
@commands.is_owner()
async def stop(self, ctx):
if ctx.author.voice.channel.name in self.bot.voice_chans:
if self.bot.voice_chans[ctx.author.voice.channel.name].is_playing():
self.bot.voice_chans[ctx.author.voice.channel.name].stop()
else:
await ctx.send('Nothing is playing...')
else:
await ctx.send('Not connected to that voice channel.')
@commands.command(hidden=True)
@commands.is_owner()
async def disconnect(self, ctx):
if ctx.author.voice.channel.name in self.bot.voice_chans:
await self.bot.voice_chans[ctx.author.voice.channel.name].disconnect()
del self.bot.voice_chans[ctx.author.voice.channel.name]
else:
await ctx.send('Not connected to that voice channel.')
@commands.command(hidden=True)
@commands.is_owner()
async def volume(self, ctx, volume:float):
self.bot.player.volume = volume
def setup(bot):
bot.add_cog(fun(bot))
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
+64
View File
@@ -0,0 +1,64 @@
import discord, json, asyncio
from . import utils
owner_id = 351794468870946827
def check_admin_role(bot, ctx, member):
admin_roles = json.loads(bot.con.one(f"select admin_roles from guild_config where guild_id = {ctx.guild.id}"))
for role in admin_roles:
if discord.utils.get(ctx.guild.roles, id=admin_roles[role]) in member.roles:
return True
return member.id == ctx.guild.owner.id or member.id == owner_id
def check_rcon_role(bot, ctx, member):
rcon_admin_roles = json.loads(bot.con.one(f"select rcon_admin_roles from guild_config where guild_id = {ctx.guild.id}"))
for role in rcon_admin_roles:
if discord.utils.get(ctx.guild.roles, id=rcon_admin_roles[role]) in member.roles:
return True
return member.id == ctx.guild.owner.id or member.id == owner_id
def is_admin(bot, ctx):
admin_roles = json.loads(bot.con.one(f"select admin_roles from guild_config where guild_id = {ctx.guild.id}"))
for role in admin_roles:
if discord.utils.get(ctx.guild.roles, id=admin_roles[role]) in ctx.message.author.roles:
return True
return ctx.message.author.id == ctx.guild.owner.id or ctx.message.author.id == owner_id
def is_guild_owner(ctx):
if ctx.guild:
return ctx.message.author.id == ctx.guild.owner.id or ctx.message.author.id == owner_id
return False
def is_rcon_admin(bot, ctx):
rcon_admin_roles = json.loads(bot.con.one(f"select rcon_admin_roles from guild_config where guild_id = {ctx.guild.id}"))
for role in rcon_admin_roles:
if discord.utils.get(ctx.guild.roles, id=rcon_admin_roles[role]) in ctx.message.author.roles:
return True
return ctx.message.author.id == ctx.guild.owner.id or ctx.message.author.id == owner_id
def is_restricted_chan(ctx):
if ctx.guild:
if ctx.channel.overwrites_for(ctx.guild.default_role).read_messages == False:
return True
return False
return False
async def is_spam(bot, ctx):
max_rep = 5
rep_time = 20
spam_rep = 5
spam_time = 3
spam_check = 0
msg_check = 0
for msg in bot.recent_msgs[ctx.guild.id]:
if msg['author'] == ctx.author:
if msg['time'] > ctx.message.created_at.timestamp() - spam_time:
spam_check += 1
if msg['content'].lower() == ctx.content.lower() and msg['time'] > ctx.message.created_at.timestamp() - rep_time:
msg_check += 1
if spam_check == spam_rep - 1 or msg_check == max_rep - 1:
await utils.mute(bot, ctx, admin=1, member=ctx.author.id)
return True
return False
+87
View File
@@ -0,0 +1,87 @@
from io import StringIO
import sys, asyncio
from discord.ext.commands.formatter import Paginator
from . import checks
class Capturing(list):
def __enter__(self):
self._stdout = sys.stdout
sys.stdout = self._stringio = StringIO()
return self
def __exit__(self, *args):
self.extend(self._stringio.getvalue().splitlines())
del self._stringio # free up some memory
sys.stdout = self._stdout
async def mute(bot, ctx, admin=0, member_id=None):
mute_role = self.bot.con.one(f'select muted_role from guild_config where guild_id = {ctx.guild.id}')
if muted_role:
if admin or checks.is_admin(bot, ctx):
if ctx.guild.me.guild_permissions.manage_roles:
if member:
ctx.guild.get_member(member_id).edit(roles=[discord.utils.get(ctx.guild.roles, id=mute_role)])
def to_list_of_str(items, out:list=[], level=1, recurse=0):
def rec_loop(item, key, out, level):
quote = '"'
if type(item) == list:
out.append(f'{" "*level}{quote+key+quote+": " if key else ""}[')
new_level = level + 1
out = to_list_of_str(item, out, new_level, 1)
out.append(f'{" "*level}]')
elif type(item) == dict:
out.append(f'{" "*level}{quote+key+quote+": " if key else ""}{{')
new_level = level + 1
out = to_list_of_str(item, out, new_level, 1)
out.append(f'{" "*level}}}')
else:
out.append(f'{" "*level}{quote+key+quote+": " if key else ""}{repr(item)},')
if type(items) == list:
if not recurse:
out = []
out.append('[')
for item in items:
rec_loop(item, None, out, level)
if not recurse:
out.append(']')
elif type(items) == dict:
if not recurse:
out = []
out.append('{')
for key in items:
rec_loop(items[key], key, out, level)
if not recurse:
out.append('}')
return out
def paginate(text):
data = []
paginator = Paginator(prefix='```py')
if type(text) == list:
data = to_list_of_str(text)
elif type(text) == dict:
data = to_list_of_str(text)
else:
data = str(text).split('\n')
for line in data:
if len(line) > 1900:
n = 1900
for l in [line[i:i+n] for i in range(0, len(line), n)]:
paginator.add_line(l)
else:
paginator.add_line(line)
return paginator.pages
async def run_command(*args):
# Create subprocess
process = await asyncio.create_subprocess_exec(
*args,
# stdout must a pipe to be accessible as process.stdout
stdout=asyncio.subprocess.PIPE)
# Wait for the subprocess to finish
stdout, stderr = await process.communicate()
# Return stdout
return stdout.decode().strip()
+112
View File
@@ -0,0 +1,112 @@
import discord
from discord.ext import commands
import json
from .imports import checks
config_dir = 'config'
extension_dir = 'extensions'
owner_id = 351794468870946827
class patreon():
def __init__(self, bot):
self.bot = bot
@commands.command(aliases=['get_patreon','patreon'])
@commands.cooldown(1, 5, type=commands.BucketType.user)
async def get_patreon_links(self, ctx, target: discord.Member=None):
'Prints Patreon information for creators on the server.'
if self.bot.con.one(f'select patreon_enabled from guild_config where guild_id = {ctx.guild.id}'):
patreon_info = self.bot.con.one(f'select patreon_message,patreon_links from guild_config where guild_id = {ctx.guild.id}')
message = patreon_info[0].replace('\\n','\n')
patreon_links = json.loads(patreon_info[1])
for key in patreon_links:
message = message + '\n{0}: {1}'.format(key, patreon_links[key])
if target == None:
await ctx.send(message)
else:
await ctx.send('{0}\n{1}'.format(target.mention, message))
else:
await ctx.send('Patreon links are not enabled on this guild.')
@commands.command(aliases=['patreon_message'])
async def set_patreon_message(self, ctx, message):
if checks.is_admin(self.bot, ctx):
patreon_message = self.bot.con.one(f'select patreon_message from guild_config where guild_id = {ctx.guild.id}')
if message == patreon_message:
await ctx.send('That is already the current message for this guild.')
else:
self.bot.con.run(f'update guild_config set patreon_message = %(message)s where guild_id = {ctx.guild.id}', {'message': message})
await ctx.send(f'The patreon message for this guild has been set to:\n{message}')
else:
await ctx.send(f'You are not authorized to run this command.')
@commands.command(aliases=['add_patreon', 'set_patreon'])
async def add_patreon_info(self, ctx, name, url):
if checks.is_admin(self.bot, ctx):
patreon_info = self.bot.con.one(f'select patreon_links from guild_config where guild_id = {ctx.guild.id}')
patreon_links = {}
update = 0
if patreon_info:
patreon_links = json.loads(patreon_info)
if name in patreon_links:
update = 1
patreon_links[name] = url
self.bot.con.run(f'update guild_config set patreon_links = %(links)s where guild_id = {ctx.guild.id}', {'links': json.dumps(patreon_links)})
await ctx.send(f"The Patreon link for {name} has been {'updated to the new url.' if update else'added to the config for this guild.'}")
else:
await ctx.send(f'You are not authorized to run this command.')
@commands.command(aliases=['remove_patreon'])
async def remove_patreon_info(self, ctx, name):
if checks.is_admin(self.bot, ctx):
patreon_info = self.bot.con.one(f'select patreon_links from guild_config where guild_id = {ctx.guild.id}')
patreon_links = {}
if patreon_info:
patreon_links = json.loads(patreon_info)
if name in patreon_links:
del patreon_links[name]
self.bot.con.run(f'update guild_config set patreon_links = %(links)s where guild_id = {ctx.guild.id}', {'links': json.dumps(patreon_links)})
await ctx.send(f'The Patreon link for {name} has been removed from the config for this guild.')
return
else:
await ctx.send(f'{name} is not in the Patreon config for this guild.')
else:
await ctx.send(f'There is no Patreon config for this guild.')
else:
await ctx.send(f'You are not authorized to run this command.')
@commands.command()
async def enable_patreon(self, ctx, state:bool=True):
if checks.is_admin(self.bot, ctx):
patreon_status = self.bot.con.one(f'select patreon_enabled from guild_config where guild_id = {ctx.guild.id}')
if patreon_status and state:
await ctx.send('Patreon is already enabled for this guild.')
elif patreon_status and not state:
self.bot.con.run(f'update guild_config set patreon_enabled = %(state)s where guild_id = {ctx.guild.id}', {'state': state})
await ctx.send('Patreon has been disabled for this guild.')
elif not patreon_status and state:
self.bot.con.run(f'update guild_config set patreon_enabled = %(state)s where guild_id = {ctx.guild.id}', {'state': state})
await ctx.send('Patreon has been enabled for this guild.')
elif not patreon_status and not state:
await ctx.send('Patreon is already disabled for this guild.')
@commands.command(aliases=['referral','ref'])
@commands.cooldown(1, 5, type=commands.BucketType.user)
async def referral_links(self, ctx, target: discord.Member=None):
'Prints G-Portal Referral Links.'
if self.bot.con.one(f'select referral_enabled from guild_config where guild_id = {ctx.guild.id}'):
referral_info = self.bot.con.one(f'select referral_message,referral_links from guild_config where guild_id = {ctx.guild.id}')
message = referral_info[0]
referral_links = json.loads(referral_info[1])
for key in referral_links:
message = message + '\n{0}: {1}'.format(key, referral_links[key])
if target == None:
await ctx.send(message)
else:
await ctx.send('{0}\n{1}'.format(target.mention, message))
else:
await ctx.send('Referrals are not enabled on this guild.')
def setup(bot):
bot.add_cog(patreon(bot))
+489
View File
@@ -0,0 +1,489 @@
import discord
from discord.ext import commands
import json
from srcds import rcon as rcon_con
import time, logging
from datetime import datetime
import asyncio
import traceback
from .imports import checks
config_dir = 'config'
admin_id_file = 'admin_ids'
extension_dir = 'extensions'
owner_id = 351794468870946827
guild_config_file = 'guild_config'
rcon_config_file = 'server_rcon_config'
guild_config_dir = 'guild_config/'
rcon_log = logging.getLogger('rcon')
game_commands = ['admin',]
game_prefix = '$'
class rcon():
def __init__(self, bot):
self.bot = bot
def _listplayers(self, con_info):
con = rcon_con.RconConnection(con_info['ip'], con_info['port'], con_info['password'])
asyncio.sleep(5)
response = con.exec_command('listplayers')
rcon_log.info(response)
while response == b'Keep Alive\x00\x00':
asyncio.sleep(5)
response = con.exec_command('listplayers')
rcon_log.info(response)
return response.strip(b'\n \x00\x00').decode('ascii').strip()
def _saveworld(self, con_info):
con = rcon_con.RconConnection(con_info['ip'], con_info['port'], con_info['password'])
asyncio.sleep(5)
response = con.exec_command('saveworld')
rcon_log.info(response)
while response == b'Keep Alive\x00\x00':
asyncio.sleep(5)
response = con.exec_command('saveworld')
rcon_log.info(response)
return response.strip(b'\n \x00\x00').decode('ascii').strip()
def _whitelist(self, con_info, steam_ids):
messages = []
con = rcon_con.RconConnection(con_info['ip'], con_info['port'], con_info['password'])
asyncio.sleep(5)
for steam_id in steam_ids:
response = con.exec_command('AllowPlayerToJoinNoCheck {0}'.format(steam_id))
rcon_log.info(response)
while response == b'Keep Alive\x00\x00':
asyncio.sleep(5)
response = con.exec_command('AllowPlayerToJoinNoCheck {0}'.format(steam_id))
rcon_log.info(response)
messages.append(response.strip(b'\n \x00\x00').decode('ascii').strip())
return messages
def _broadcast(self, con_info, message):
messages = []
con = rcon_con.RconConnection(con_info['ip'], con_info['port'], con_info['password'])
asyncio.sleep(5)
response = con.exec_command('broadcast {0}'.format(message))
rcon_log.info(response)
while response == b'Keep Alive\x00\x00':
asyncio.sleep(5)
response = con.exec_command('broadcast {0}'.format(message))
rcon_log.info(response)
messages.append(response.strip(b'\n \x00\x00').decode('ascii').strip())
return messages
def _get_current_chat(self, con):
response = con.exec_command('getchat')
rcon_log.debug(response)
return response.strip(b'\n \x00\x00').decode('ascii').strip()
def server_chat_background_process(self, guild_id, con):
return_messages = []
try:
message = 'Server received, But no response!!'
time_now = datetime.now().timestamp()
while 'Server received, But no response!!' in message and time_now + 20 > datetime.now().timestamp():
message = self._get_current_chat(con)
rcon_log.debug(message)
time.sleep(1)
if 'Server received, But no response!!' not in message:
for msg in message.split('\n'):
msg = '{0} ||| {1}'.format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'),msg.strip())
return_messages.append(msg)
except rcon_con.RconError as e:
rcon_log.error('RCON Error {0}\n{1}'.format(guild_id,traceback.format_exc()))
return_messages.append('RCON Error')
except Exception as e:
rcon_log.error('Exception {0}\n{1}'.format(guild_id,traceback.format_exc()))
return_messages.append('Exception')
return_messages.append(e)
rcon_log.debug(return_messages)
return return_messages
def admin(self, ctx, msg, rcon_server, admin_roles):
player = msg.split(' ||| ')[1].split(' (')[0]
con = rcon_con.RconConnection( rcon_server['ip'],
rcon_server['port'],
rcon_server['password'],
True)
con.exec_command('ServerChatToPlayer "{0}" GeeksBot: Admin Geeks have been notified you need assistance. Please be patient.'.format(player))
con._sock.close()
for role in admin_roles:
msg = '{0} {1}'.format(msg,discord.utils.get(ctx.guild.roles, id=admin_roles[role]).mention)
return msg
@commands.command()
@commands.guild_only()
async def monitor_chat(self, ctx, *, server=None):
'''Begins monitoring the specified ARK server for chat messages and other events.
The specified server must already be in the current guild\'s configuration.
To add and remove ARK servers from the guild see add_rcon_server and remove_rcon_server.
The server argument is not case sensitive and if the server name has 2 words it can be in one of the following forms:
first last
first_last
"first last"
To view all the valid ARK servers for this guild see list_ark_servers.'''
if checks.is_rcon_admin(self.bot, ctx):
if server != None:
rcon_connections = json.loads(self.bot.con.one(f"select rcon_connections from guild_config where guild_id = {ctx.guild.id}"))
server = server.replace('_',' ').title()
if server in rcon_connections:
rcon_connections[server]["monitoring_chat"] = 1
self.bot.con.run(f"update guild_config set rcon_connections = '{json.dumps(rcon_connections)}' where guild_id = {ctx.guild.id}")
channel = self.bot.get_channel(rcon_connections[server]['game_chat_chan_id'])
await channel.send('Started monitoring on the {0} server.'.format(server))
await ctx.message.add_reaction('')
rcon_log.debug('Started monitoring on the {0} server.'.format(server))
while rcon_connections[server]["monitoring_chat"] == 1:
try:
con = rcon_con.RconConnection( rcon_connections[server]['ip'],
rcon_connections[server]['port'],
rcon_connections[server]['password'],
True)
messages = await self.bot.loop.run_in_executor(None, self.server_chat_background_process, ctx.guild.id, con)
con._sock.close()
except TimeoutError:
rcon_log.error(traceback.format_exc())
await channel.send('TimeoutError')
await asyncio.sleep(30)
else:
rcon_log.debug('Got chat from {0}.'.format(server))
for message in messages:
rcon_log.info(message)
message = '```{0}```'.format(message)
for command in game_commands:
prefix_command = '{0}{1}'.format(game_prefix,command)
if prefix_command in message:
try:
func = getattr(self, command)
except AttributeError:
rcon_log.warning('Function not found "{0}"'.format(command))
else:
rcon_log.info(f'Sending to {command}')
message = func(ctx, message, rcon_connections['server'])
await channel.send('{0}'.format(message))
await asyncio.sleep(1)
rcon_connections = json.loads(self.bot.con.one(f"select rcon_connections from guild_config where guild_id = {ctx.guild.id}"))
await channel.send('Monitoring Stopped')
else:
await ctx.send(f'Server not found: {server}')
else:
await ctx.send(f'You must include a server in this command.')
else:
await ctx.send(f'You are not authorized to run this command.')
@commands.command()
@commands.guild_only()
async def end_monitor_chat(self, ctx, *, server=None):
'''Ends chat monitoring on the specified server.
Context is the same as monitor_chat'''
if checks.is_rcon_admin(self.bot, ctx):
if server != None:
rcon_connections = json.loads(self.bot.con.one(f"select rcon_connections from guild_config where guild_id = {ctx.guild.id}"))
server = server.replace('_',' ').title()
if server in rcon_connections:
rcon_connections[server]["monitoring_chat"] = 0
self.bot.con.run(f"update guild_config set rcon_connections = '{json.dumps(rcon_connections)}' where guild_id = {ctx.guild.id}")
else:
await ctx.send(f'Server not found: {server}')
else:
await ctx.send(f'You must include a server in this command.')
else:
await ctx.send(f'You are not authorized to run this command.')
@commands.command()
@commands.guild_only()
async def listplayers(self, ctx, *, server=None):
'''Lists the players currently connected to the specified ARK server.
The specified server must already be in the current guild\'s configuration.
To add and remove ARK servers from the guild see add_rcon_server and remove_rcon_server.
The server argument is not case sensitive and if the server name has 2 words it can be in one of the following forms:
first last
first_last
"first last"
To view all the valid ARK servers for this guild see list_ark_servers.'''
if checks.is_rcon_admin(self.bot, ctx):
rcon_connections = json.loads(self.bot.con.one(f"select rcon_connections from guild_config where guild_id = {ctx.guild.id}"))
if server != None:
server = server.replace('_',' ').title()
if server in rcon_connections:
connection_info = rcon_connections[server]
msg = await ctx.send('Getting Data for the {0} server'.format(server.title()))
await ctx.channel.trigger_typing()
message = self._listplayers(connection_info)
await ctx.channel.trigger_typing()
await msg.delete()
await ctx.send('Players currently on the {0} server:\n{1}'.format(server.title(), message))
else:
await ctx.send('That server is not in my configuration.\nPlease add it via !add_rcon_server "{0}" "ip" port "password" if you would like to get info from it.'.format(server))
else:
for server in rcon_connections:
try:
connection_info = rcon_connections[server]
msg = await ctx.send('Getting Data for the {0} server'.format(server.title()))
async with ctx.channel.typing():
message = self._listplayers(connection_info)
except Exception as e:
await msg.delete()
await ctx.send(f'Player listing failed on the {server.title()}\n{e}')
else:
await msg.delete()
await ctx.send('Players currently on the {0} server:\n{1}'.format(server.title(), message))
else:
await ctx.send(f'You are not authorized to run this command.')
@commands.command()
@commands.guild_only()
async def add_rcon_server(self, ctx, server, ip, port, password):
'''Adds the specified server to the current guild\'s rcon config.
All strings (<server>, <ip>, <password>) must be contained inside double quotes.'''
if checks.is_rcon_admin(self.bot, ctx):
server = server.title()
rcon_connections = json.loads(self.bot.con.one(f"select rcon_connections from guild_config where guild_id = {ctx.guild.id}"))
if server not in rcon_connections:
rcon_connections[server] = {
'ip': ip,
'port': port,
'password': password,
'name': server.lower().replace(' ','_'),
'game_chat_chan_id': 0,
'msg_chan_id': 0,
'monitoring_chat': 0
}
self.bot.con.run(f"update guild_config set rcon_connections = %(connections)s where guild_id = {ctx.guild.id}", {'connections':json.dumps(rcon_connections)})
await ctx.send('{0} server has been added to my configuration.'.format(server))
else:
await ctx.send('This server name is already in my configuration. Please choose another.')
else:
await ctx.send(f'You are not authorized to run this command.')
await ctx.message.delete()
await ctx.send('Command deleted to prevent password leak.')
@commands.command()
@commands.guild_only()
async def remove_rcon_server(self, ctx, server):
'''removes the specified server from the current guild\'s rcon config.
All strings <server> must be contained inside double quotes.'''
if checks.is_rcon_admin(self.bot, ctx):
server = server.title()
rcon_connections = json.loads(self.bot.con.one(f"select rcon_connections from guild_config where guild_id = {ctx.guild.id}"))
if server in rcon_connections:
del rcon_connections[server]
self.bot.con.run(f"update guild_config set rcon_connections = %(connections)s where guild_id = {ctx.guild.id}", {'connections':json.dumps(rcon_connections)})
await ctx.send('{0} has been removed from my configuration.'.format(server))
else:
await ctx.send('{0} is not in my configuration.'.format(server))
else:
await ctx.send(f'You are not authorized to run this command.')
@commands.command()
@commands.guild_only()
async def add_whitelist(self, ctx, *, steam_ids=None):
'''Adds the included Steam 64 IDs to the running whitelist on all the ARK servers in the current guild\'s rcon config.
Steam 64 IDs should be a comma seperated list of IDs.
Example: 76561198024193239,76561198024193239,76561198024193239'''
if checks.is_rcon_admin(self.bot, ctx):
if steam_ids != None:
rcon_connections = json.loads(self.bot.con.one(f"select rcon_connections from guild_config where guild_id = {ctx.guild.id}"))
error = 0
error_msg = ''
success_msg = 'Adding to the running whitelist on all servers.'
steam_ids = steam_ids.replace(', ',',').replace(' ',',').split(',')
for (i, steam_id) in enumerate(steam_ids):
try:
steam_id = int(steam_id)
except ValueError:
error = 1
error_msg = '{0}\n__**ERROR:**__ {1} is not a valid Steam64 ID'.format(error_msg, steam_id)
else:
steam_ids[i] = steam_id
if error == 0:
msg = await ctx.send(success_msg)
for server in rcon_connections:
try:
success_msg = '{0}\n\n{1}:'.format(success_msg, server.title())
await msg.edit(content=success_msg.strip())
messages = await self.bot.loop.run_in_executor(None, self._whitelist, rcon_connections[server], steam_ids)
except Exception as e:
success_msg = '{0}\n{1}'.format(success_msg, e.strip())
await msg.edit(content=success_msg.strip())
else:
for message in messages:
success_msg = '{0}\n{1}'.format(success_msg, message.strip())
await msg.edit(content=success_msg.strip())
await msg.add_reaction('')
else:
await ctx.send(error_msg)
else:
await ctx.send('I need a list of steam IDs to add to the whitelist.')
else:
await ctx.send(f'You are not authorized to run this command.')
@commands.command()
@commands.guild_only()
async def saveworld(self, ctx, *, server=None):
'''Runs SaveWorld on the specified ARK server.
If a server is not specified it will default to running saveworld on all servers in the guild\'s config.
Will print out "World Saved" for each server when the command completes sucessfully.'''
if checks.is_rcon_admin(self.bot, ctx):
rcon_connections = json.loads(self.bot.con.one(f"select rcon_connections from guild_config where guild_id = {ctx.guild.id}"))
success_msg = 'Running saveworld'
if server == None:
success_msg += ' on all the servers:'
# server = server.replace('_',' ').title()
if server in rcon_connections:
connection_info = rcon_connections[server]
msg = await ctx.send(success_msg)
for server in rcon_connections:
try:
success_msg = '{0}\n\n{1}:'.format(success_msg, server.title())
await msg.edit(content=success_msg.strip())
message = await self.bot.loop.run_in_executor(None, self._saveworld, rcon_connections[server])
except Exception as e:
success_msg = '{0}\n{1}'.format(success_msg, e.strip())
await msg.edit(content=success_msg.strip())
else:
success_msg = '{0}\n{1}'.format(success_msg, message.strip())
await msg.edit(content=success_msg.strip())
await msg.add_reaction('')
elif server.title() in rcon_connections:
success_msg = '{0} {1}:'.format(success_msg, server.title())
msg = await ctx.send(success_msg)
message = await self.bot.loop.run_in_executor(None, self._saveworld, rcon_connections[server.title()])
success_msg = '{0}\n{1}'.format(success_msg, message.strip())
await msg.edit(content=success_msg.strip())
await msg.add_reaction('')
else:
await ctx.send(f'{server.title()} is not currently in the configuration for this guild.')
else:
await ctx.send(f'You are not authorized to run this command.')
@commands.group(case_insensitive=True)
async def broadcast(self, ctx):
'''Run help broadcast for more info'''
pass
@broadcast.command(name='all')
@commands.guild_only()
async def broadcast_all(self, ctx, *, message=None):
'''Sends a broadcast message to all servers in the guild config.
The message will be prefixed with the Discord name of the person running the command.
Will print "Success" for each server once the broadcast is sent.'''
if checks.is_rcon_admin(self.bot, ctx):
rcon_connections = json.loads(self.bot.con.one(f"select rcon_connections from guild_config where guild_id = {ctx.guild.id}"))
if message != None:
message = f'{ctx.author.display_name}: {message}'
success_msg = f'Broadcasting "{message}" to all servers.'
msg = await ctx.send(success_msg)
for server in rcon_connections:
try:
success_msg = '{0}\n\n{1}:'.format(success_msg, server.title())
await msg.edit(content=success_msg.strip())
messages = await self.bot.loop.run_in_executor(None, self._broadcast, rcon_connections[server], message)
except Exception as e:
success_msg = '{0}\n{1}'.format(success_msg, e.strip())
await msg.edit(content=success_msg.strip())
else:
for mesg in messages:
if mesg == 'Server received, But no response!!':
mesg = 'Success'
success_msg = '{0}\n{1}'.format(success_msg, mesg.strip())
await msg.edit(content=success_msg.strip())
await msg.add_reaction('')
else:
await ctx.send('You must include a message with this command.')
else:
await ctx.send(f'You are not authorized to run this command.')
@broadcast.command(name='server')
@commands.guild_only()
async def broadcast_server(self, ctx, server, *, message=None):
'''Sends a broadcast message to the specified server that is in the guild's config.
The message will be prefixed with the Discord name of the person running the command.
If <server> has more than one word in it's name it will either need to be sorrounded by double quotes or the words seperated by _'''
if checks.is_rcon_admin(self.bot, ctx):
rcon_connections = json.loads(self.bot.con.one(f"select rcon_connections from guild_config where guild_id = {ctx.guild.id}"))
if server != None:
server = server.replace('_',' ').title()
if message != None:
message = f'{ctx.author.display_name}: {message}'
success_msg = f'Broadcasting "{message}" to {server}.'
msg = await ctx.send(success_msg)
if server in rcon_connections:
messages = await self.bot.loop.run_in_executor(None, self._broadcast, rcon_connections[server], message)
for mesg in messages:
if mesg != 'Server received, But no response!!':
success_msg = '{0}\n{1}'.format(success_msg, mesg.strip())
await msg.edit(content=success_msg.strip())
await msg.add_reaction('')
else:
await ctx.send(f'{server} is not in the config for this guild')
else:
await ctx.send('You must include a message with this command.')
else:
await ctx.send('You must include a server with this command')
else:
await ctx.send(f'You are not authorized to run this command.')
@commands.command()
@commands.guild_only()
async def create_server_chat_chans(self, ctx):
'''Creates a category and server chat channels in the current guild.
The category will be named "Server Chats" and read_messages is disabled for the guild default role (everyone)
This can be overridden by modifying the category's permissions.
Inside this category a channel will be created for each server in the current guild's rcon config and these channel's permissions will be synced to the category.
These channels will be added to the guild's rcon config and are where the server chat messages will be sent when monitor_chat is run.'''
if checks.is_rcon_admin(self.bot, ctx):
rcon_connections = json.loads(self.bot.con.one(f"select rcon_connections from guild_config where guild_id = {ctx.guild.id}"))
edited = 0
category = discord.utils.get(ctx.guild.categories, name='Server Chats')
if category == None:
overrides = {ctx.guild.default_role: discord.PermissionOverwrite(read_messages=False)}
category = await ctx.guild.create_category('Server Chats', overwrites = overrides)
channels = ctx.guild.channels
cat_chans = []
for channel in channels:
if channel.category_id == category.id:
cat_chans.append(channel)
for server in rcon_connections:
exists = 0
if cat_chans != []:
for channel in cat_chans:
if rcon_connections[server]['game_chat_chan_id'] == channel.id:
exists = 1
if exists == 0:
print('Creating {}'.format(server))
chan = await ctx.guild.create_text_channel(rcon_connections[server]['name'],category=category)
rcon_connections[server]['game_chat_chan_id'] = chan.id
edited = 1
if edited == 1:
self.bot.con.run(f"update guild_config set rcon_connections = '{json.dumps(rcon_connections)}' where guild_id = {ctx.guild.id}")
await ctx.message.add_reaction('')
else:
await ctx.send(f'You are not authorized to run this command.')
@commands.command(aliases=['servers','list_servers'])
@commands.guild_only()
@commands.check(checks.is_restricted_chan)
async def list_ark_servers(self, ctx):
'''Returns a list of all the ARK servers in the current guild\'s config.'''
servers = json.loads(self.bot.con.one(f"select rcon_connections from guild_config where guild_id = {ctx.guild.id}"))
em = discord.Embed( style='rich',
title=f'__**There are currently {len(servers)} ARK servers in my config:**__',
color=discord.Colour.green()
)
if ctx.guild.icon:
em.set_thumbnail(url=f'{ctx.guild.icon_url}')
for server in servers:
description = f" **IP:** {servers[server]['ip']}:{servers[server]['port']}\n **Steam Connect:** [steam://connect/{servers[server]['ip']}:{servers[server]['port']}](steam://connect/{servers[server]['ip']}:{servers[server]['port']})"
em.add_field(name=f'__***{server}***__', value=description, inline=False)
await ctx.send(embed=em)
def setup(bot):
bot.add_cog(rcon(bot))
+175
View File
@@ -0,0 +1,175 @@
from discord.ext import commands
import time
import datetime
import math
import asyncio
import traceback
import discord
import inspect
import textwrap
from contextlib import redirect_stdout
import io
import os, sys
import subprocess
import async_timeout
from .imports.utils import paginate, run_command
ownerids = [351794468870946827,275280442884751360]
ownerid = 351794468870946827
class REPL():
def __init__(self, bot):
self.bot = bot
self._last_result = None
self.sessions = set()
def cleanup_code(self, content):
'Automatically removes code blocks from the code.'
if content.startswith('```') and content.endswith('```'):
return '\n'.join(content.split('\n')[1:(- 1)])
return content.strip('` \n')
def get_syntax_error(self, e):
if e.text is None:
return '```py\n{0.__class__.__name__}: {0}\n```'.format(e)
return '```py\n{0.text}{1:>{0.offset}}\n{2}: {0}```'.format(e, '^', type(e).__name__)
@commands.command(hidden=True, name='exec')
async def _eval(self, ctx, *, body: str):
if ctx.author.id != ownerid:
return
env = {
'bot': self.bot,
'ctx': ctx,
'channel': ctx.channel,
'author': ctx.author,
'server': ctx.guild,
'message': ctx.message,
'_': self._last_result,
}
env.update(globals())
body = self.cleanup_code(body)
stdout = io.StringIO()
to_compile = 'async def func():\n%s' % textwrap.indent(body, ' ')
try:
exec(to_compile, env)
except SyntaxError as e:
return await ctx.send(self.get_syntax_error(e))
func = env['func']
try:
with redirect_stdout(stdout):
ret = await func()
except Exception as e:
value = stdout.getvalue()
await ctx.send('```py\n{}{}\n```'.format(value, traceback.format_exc()))
else:
value = stdout.getvalue()
try:
await ctx.message.add_reaction('')
except:
pass
if ret is None:
if value:
for page in paginate(value):
await ctx.send(page)
else:
self._last_result = ret
if value:
for page in paginate(value):
await ctx.send(page)
for page in paginate(ret):
await ctx.send(page)
@commands.command(hidden=True)
async def repl(self, ctx):
if ctx.author.id != ownerid:
return
msg = ctx.message
variables = {
'ctx': ctx,
'bot': self.bot,
'message': msg,
'server': msg.guild,
'channel': msg.channel,
'author': msg.author,
'_': None,
}
if msg.channel.id in self.sessions:
await ctx.send('Already running a REPL session in this channel. Exit it with `quit`.')
return
self.sessions.add(msg.channel.id)
await ctx.send('Enter code to execute or evaluate. `exit()` or `quit` to exit.')
while True:
response = await self.bot.wait_for('message', check=(lambda m: m.content.startswith('`')))
if response.author.id == ownerid:
cleaned = self.cleanup_code(response.content)
if cleaned in ('quit', 'exit', 'exit()'):
await response.channel.send('Exiting.')
self.sessions.remove(msg.channel.id)
return
executor = exec
if cleaned.count('\n') == 0:
try:
code = compile(cleaned, '<repl session>', 'eval')
except SyntaxError:
pass
else:
executor = eval
if executor is exec:
try:
code = compile(cleaned, '<repl session>', 'exec')
except SyntaxError as e:
await response.channel.send(self.get_syntax_error(e))
continue
variables['message'] = response
fmt = None
stdout = io.StringIO()
try:
with redirect_stdout(stdout):
result = executor(code, variables)
if inspect.isawaitable(result):
result = await result
except Exception as e:
value = stdout.getvalue()
fmt = '{}{}'.format(value, traceback.format_exc())
else:
value = stdout.getvalue()
if result is not None:
fmt = '{}{}'.format(value, result)
variables['_'] = result
elif value:
fmt = '{}'.format(value)
try:
if fmt is not None:
if len(fmt) > 1990:
for page in paginate(fmt):
await response.channel.send(page)
await ctx.send(response.channel)
else:
await response.channel.send(f'```py\n{fmt}\n```')
except discord.Forbidden:
pass
except discord.HTTPException as e:
await msg.channel.send('Unexpected error: `{}`'.format(e))
@commands.command(hidden=True)
async def os(self, ctx, *, body: str):
if ctx.author.id != ownerid:
return
try:
body = self.cleanup_code(body).split(' ')
result = await asyncio.wait_for(self.bot.loop.create_task(run_command(*body)),10)
value = result
for page in paginate(value):
await ctx.send(page)
await ctx.message.add_reaction('')
except asyncio.TimeoutError:
value = f"Command did not complete in the time allowed."
for page in paginate(value):
await ctx.send(page)
await ctx.message.add_reaction('')
def setup(bot):
bot.add_cog(REPL(bot))
+445
View File
@@ -0,0 +1,445 @@
import discord
from discord.ext import commands
import json
from srcds import rcon as rcon_con
import time, logging, math, psutil
from datetime import datetime, timedelta
import asyncio, inspect
import aiohttp, async_timeout
from bs4 import BeautifulSoup as bs
import traceback
from .imports import checks
from .imports.utils import paginate
import pytz
import gspread
from oauth2client.service_account import ServiceAccountCredentials
config_dir = 'config/'
admin_id_file = 'admin_ids'
extension_dir = 'extensions'
owner_id = 351794468870946827
embed_color = discord.Colour.from_rgb(49,107,111)
bot_config_file = 'bot_config.json'
invite_match = '(https?://)?(www.)?discord(app.com/(invite|oauth2)|.gg|.io)/[\w\d_\-?=&/]+'
utils_log = logging.getLogger('utils')
clock_emojis = ['🕛','🕐','🕑','🕒','🕓','🕔','🕕','🕖','🕗','🕘','🕙','🕚']
class utils():
def __init__(self, bot):
self.bot = bot
async def _4_hour_ping(self, channel, message, wait_time):
channel = self.bot.get_channel(channel)
time_now = datetime.utcnow()
await channel.send(message)
while True:
if time_now < datetime.utcnow() - timedelta(seconds=wait_time+10):
await channel.send(message)
time_now = datetime.utcnow()
await asyncio.sleep(wait_time/100)
async def background_ping(self, ctx, i):
def check(message):
return message.author == ctx.guild.me and 'ping_test' in message.content
msg = await self.bot.wait_for('message', timeout=5, check=check)
self.bot.ping_times[i]['rec'] = msg
@commands.command()
async def channel_ping(self, ctx, wait_time:float=10, message:str='=bump', channel:int=265828729970753537):
await ctx.send('Starting Background Process.')
self.bot.loop.create_task(self._4_hour_ping(channel, message, wait_time))
@commands.command()
@commands.is_owner()
async def sysinfo(self, ctx):
await ctx.send(f'```ml\nCPU Percentages: {psutil.cpu_percent(percpu=True)}\nMemory Usage: {psutil.virtual_memory().percent}%\nDisc Usage: {psutil.disk_usage("/").percent}%```')
@commands.command(hidden=True)
async def role(self, ctx, role):
if ctx.guild.id == 396156980974059531 and role != 'Admin' and role != 'Admin Geeks':
try:
role = discord.utils.get(ctx.guild.roles, name=role)
except:
await ctx.send('Unknown Role')
else:
if role != None:
await ctx.message.author.add_roles(role)
await ctx.send("Roles Updated")
else:
await ctx.send('Unknown Role')
else:
await ctx.send("You are not authorized to send this command.")
@commands.command(aliases=['oauth', 'link'])
@commands.cooldown(1, 5, type=commands.BucketType.user)
async def invite(self, ctx, guy:discord.User=None):
'''Shows you the bot's invite link.
If you pass in an ID of another bot, it gives you the invite link to that bot.
'''
guy = guy or self.bot.user
url = discord.utils.oauth_url(guy.id)
await ctx.send(f'**{url}**')
def create_date_string(self, time, time_now):
diff = (time_now - time)
date_str = time.strftime('%Y-%m-%d %H:%M:%S')
return f"{diff.days} {'day' if diff.days == 1 else 'days'} {diff.seconds // 3600} {'hour' if diff.seconds // 3600 == 1 else 'hours'} {diff.seconds % 3600 // 60} {'minute' if diff.seconds % 3600 // 60 == 1 else 'minutes'} {diff.seconds % 3600 % 60} {'second' if diff.seconds % 3600 % 60 == 1 else 'seconds'} ago.\n{date_str}"
@commands.command()
@commands.cooldown(1, 5, type=commands.BucketType.user)
async def me(self, ctx):
'Prints out your user information.'
em = discord.Embed( style='rich',
title=f'{ctx.author.name}#{ctx.author.discriminator} ({ctx.author.display_name})',
description=f'({ctx.author.id})',
color=embed_color)
em.set_thumbnail(url=f'{ctx.author.avatar_url}')
em.add_field(name=f'Highest Role:', value=f'{ctx.author.top_role}', inline=True)
em.add_field(name=f'Bot:', value=f'{ctx.author.bot}', inline=True)
em.add_field(name=f'Joined Guild:', value=f'{self.create_date_string(ctx.author.joined_at,ctx.message.created_at)}', inline=False)
em.add_field(name=f'Joined Discord:', value=f'{self.create_date_string(ctx.author.created_at,ctx.message.created_at)}', inline=False)
em.add_field(name=f'Current Status:', value=f'{ctx.author.status}', inline=True)
em.add_field(name=f"Currently{' '+ctx.author.activity.type.name.title() if ctx.author.activity else ''}:", value=f"{ctx.author.activity.name if ctx.author.activity else 'Not doing anything important.'}", inline=True)
count = 0
async for message in ctx.channel.history(after=(ctx.message.created_at - timedelta(hours = 1))):
if message.author == ctx.author:
count += 1
em.add_field(name=f'Activity:', value=f'You have sent {count} {"message" if count == 1 else "messages"} in the last hour to this channel.', inline=False)
await ctx.send(embed=em)
@commands.command()
@commands.cooldown(1, 5, type=commands.BucketType.user)
async def user(self, ctx, member: discord.Member):
'''Prints User information.
<member> should be in the form @Dusty.P#0001'''
em = discord.Embed( style='rich',
title=f'{member.name}#{member.discriminator} ({member.display_name})',
description=f'({member.id})',
color=embed_color)
em.set_thumbnail(url=f'{member.avatar_url}')
em.add_field(name=f'Highest Role:', value=f'{member.top_role}', inline=True)
em.add_field(name=f'Bot:', value=f'{member.bot}', inline=True)
em.add_field(name=f'Joined Guild:', value=f'{self.create_date_string(member.joined_at,ctx.message.created_at)}', inline=False)
em.add_field(name=f'Joined Discord:', value=f'{self.create_date_string(member.created_at,ctx.message.created_at)}', inline=False)
em.add_field(name=f'Current Status:', value=f'{member.status}', inline=True)
em.add_field(name=f"Currently{' '+member.activity.type.name.title() if member.activity else ''}:", value=f"{member.activity.name if member.activity else 'Not doing anything important.'}", inline=True)
count = 0
async for message in ctx.channel.history(after=(ctx.message.created_at - timedelta(hours = 1))):
if message.author == member:
count += 1
em.add_field(name=f'Activity:', value=f'{member.display_name} has sent {count} {"message" if count == 1 else "messages"} in the last hour to this channel.', inline=False)
await ctx.send(embed=em)
@commands.command()
@commands.cooldown(1, 5, type=commands.BucketType.user)
async def ping(self, ctx, mode='normal', count:int=2):
'Check the Bot\'s connection to Discord'
em = discord.Embed( style='rich',
title=f'Pong 🏓',
color=discord.Colour.green()
)
msg = await ctx.send(embed=em)
time1 = ctx.message.created_at
time = (msg.created_at - time1).total_seconds() * 1000
em.description = f'Response Time: **{math.ceil(time)}ms**\nDiscord Latency: **{math.ceil(self.bot.latency*1000)}ms**'
await msg.edit(embed=em)
if mode == 'comp':
try:
count = int(count)
except:
await ctx.send('Not a valid count. Must be a whole number.')
else:
if count > 24:
await ctx.send('24 Pings is the max allowed. Setting count to 24.',delete_after=5)
count = 24
self.bot.ping_times = []
times = []
for i in range(count):
self.bot.ping_times.append({})
self.bot.loop.create_task(self.background_ping(ctx, i))
await asyncio.sleep(0.1)
self.bot.ping_times[i]['snd'] = await ctx.send('ping_test')
now = datetime.utcnow()
while 'rec' not in self.bot.ping_times[i]:
now = datetime.utcnow()
if now.timestamp() > self.bot.ping_times[i]['snd'].created_at.timestamp()+5:
break
if 'rec' in self.bot.ping_times[i]:
time = now - self.bot.ping_times[i]['snd'].created_at
time = time.total_seconds()
times.append(time)
value = f"Message Sent: {datetime.strftime(self.bot.ping_times[i]['snd'].created_at, '%H:%M:%S.%f')}\nResponse Received: {datetime.strftime(now, '%H:%M:%S.%f')}\nTotal Time: {math.ceil(time * 1000)}ms"
await self.bot.ping_times[i]['rec'].delete()
em.add_field(name=f'Ping Test {i}', value=value, inline=True)
else:
em.add_field(name=f'Ping Test {i}', value='Timeout...', inline=True)
total_time = 0
print(times)
for time in times:
total_time += time * 1000
em.add_field(value=f'Total Time for Comprehensive test: {math.ceil(total_time)}ms', name=f'Average: **{round(total_time/count,1)}ms**', inline=False)
await msg.edit(embed=em)
@commands.group(case_insensitive=True)
async def admin(self, ctx):
'''Run help admin for more info'''
pass
@admin.command(name='new', aliases=['nr'])
@commands.cooldown(1, 30, type=commands.BucketType.user)
async def new_admin_request(self, ctx, *, request_msg=None):
'''Submit a new request for admin assistance.
The admin will be notified when your request is made and it will be added to the request list for this guild.
'''
if ctx.guild:
if request_msg != None:
if len(request_msg) < 1000:
self.bot.con.run('insert into admin_requests (issuing_member_id, guild_orig, request_text, request_time) values (%(member_id)s, %(guild_id)s, %(text)s, %(time)s)',
{'member_id': ctx.author.id, 'guild_id': ctx.guild.id, 'text': request_msg, 'time': ctx.message.created_at})
channel = self.bot.con.one(f'select admin_chat from guild_config where guild_id = {ctx.guild.id}')
if channel:
chan = discord.utils.get(ctx.guild.channels, id=channel)
msg = ''
admin_roles = []
roles = self.bot.con.one(f'select admin_roles,rcon_admin_roles from guild_config where guild_id = {ctx.guild.id}')
request_id = self.bot.con.one(f'select id from admin_requests where issuing_member_id = %(member_id)s and request_time = %(time)s', {'member_id': ctx.author.id, 'time': ctx.message.created_at})
for item in roles:
i = json.loads(item)
for j in i:
if i[j] not in admin_roles:
admin_roles.append(i[j])
for role in admin_roles:
msg = '{0} {1}'.format(msg,discord.utils.get(ctx.guild.roles, id=role).mention)
msg += f" New Request ID: {request_id}\n{ctx.author.mention} has requested assistance:\n```{request_msg}```\nRequested on: {datetime.strftime(ctx.message.created_at, '%Y-%m-%d at %H:%M:%S')} GMT"
await chan.send(msg)
await ctx.send('The Admin have received your request.')
else:
await ctx.send('Request is too long, please keep your message to less than 1000 characters.')
else:
await ctx.send('Please include a message containing information about your request.')
else:
await ctx.send('This command must be run from inside a guild.')
@admin.command(name='list', aliases=['lr'])
@commands.cooldown(1, 5, type=commands.BucketType.user)
async def list_admin_requests(self, ctx, assigned_to:discord.Member=None):
'''Returns a list of all active Admin help requests for this guild
If a user runs this command it will return all the requests that they have submitted and are still open.
- The [assigned_to] argument is ignored but will still give an error if an incorrect value is entered.
If an admin runs this command it will return all the open requests for this guild.
- If the [assigned_to] argument is included it will instead return all open requests that are assigned to the specified admin.
'''
em = discord.Embed( style='rich',
title=f'Admin Help Requests',
color=discord.Colour.green()
)
if checks.is_admin(self.bot, ctx) or checks.is_rcon_admin(self.bot, ctx):
if assigned_to == None:
requests = self.bot.con.all(f'select * from admin_requests where guild_orig = %(guild_id)s and completed_time is null', {'guild_id': ctx.guild.id})
em.title = f'Admin help requests for {ctx.guild.name}'
if requests:
for request in requests:
member = discord.utils.get(ctx.guild.members, id=request[1])
admin = discord.utils.get(ctx.guild.members, id=request[2])
title = f"{'Request ID':^12}{'Requested By':^20}{'Assigned to':^20}\n{request[0]:^12}{member.display_name if member else 'None':^20}{admin.display_name if admin else 'None':^20}"
em.add_field(name='', value=f"```{title}\n\n{request[4]}\n\nRequested on: {datetime.strftime(request[5], '%Y-%m-%d at %H:%M:%S')} GMT```", inline=False)
else:
em.add_field(name='There are no pending requests for this guild.', value='', inline=False)
else:
if checks.check_admin_role(self.bot, ctx, assigned_to) or checks.check_rcon_role(self.bot, ctx, assigned_to):
requests = self.bot.con.all('select * from admin_requests where assigned_to = %(admin_id)s and guild_orig = %(guild_id)s and completed_time is null',
{'admin_id': assigned_to.id, 'guild_id': ctx.guild.id})
em.title = f'Admin help requests asigned to {assigned_to.display_name} in {ctx.guild.name}'
if requests:
for request in requests:
member = discord.utils.get(ctx.guild.members, id=request[1])
em.add_field(name=f"Request ID: {request[0]} Requested By: {member.display_name if member else 'None'}", value=f"{request[4]}\nRequested on: {datetime.strftime(request[5], '%Y-%m-%d at %H:%M:%S')} GMT\n", inline=False)
else:
em.add_field(name=f'There are no pending requests for {assigned_to.display_name} this guild.', value='', inline=False)
else:
em.title = f'{assigned_to.display_name} is not an admin in this guild.'
else:
requests = self.bot.con.all('select * from admin_requests where issuing_member_id = %(member_id)s and guild_orig = %(guild_id)s and completed_time is null',
{'member_id': ctx.author.id, 'guild_id': ctx.guild.id})
em.title = f'Admin help requests for {ctx.author.display_name}'
if requests:
for request in requests:
admin = discord.utils.get(ctx.guild.members, id=request[2])
em.add_field(name=f"Request ID: {request[0]}{' Assigned to: ' + admin.display_name if admin else ''}", value=f"{request[4]}\nRequested on: {datetime.strftime(request[5], '%Y-%m-%d at %H:%M:%S')} GMT\n", inline=False)
else:
em.add_field(name='You have no pending Admin Help requests.', value='To submit a request please use `admin new <message>`', inline=False)
await ctx.send(embed=em)
@admin.command(name='close')
async def close_request(self, ctx, *, request_ids=None):
'''Allows Admin to close admin help tickets.
[request_id] must be a valid integer pointing to an open Request ID
'''
if checks.is_admin(self.bot, ctx) or checks.is_rcon_admin(self.bot, ctx):
if request_ids:
request_ids = request_ids.replace(' ','').split(',')
for request_id in request_ids:
try:
request_id = int(request_id)
except:
await ctx.send(f'{request_id} is not a valid request id.')
else:
request = self.bot.con.one(f'select * from admin_requests where id = %(request_id)s', {'request_id': request_id})
if request:
if request[3] == ctx.guild.id:
if request[6] == None:
self.bot.con.run('update admin_requests set completed_time = %(time_now)s where id = %(request_id)s', {'time_now': ctx.message.created_at, 'request_id': request_id})
await ctx.send(f'Request {request_id} by {ctx.guild.get_member(request[1]).display_name} has been marked complete.')
else:
await ctx.send(f'Request {request_id} is already marked complete.')
else:
await ctx.send(f'Request {request_id} is not registered to this guild.')
else:
await ctx.send(f'{request_id} is not a valid request id.')
else:
await ctx.send('You must include at least one request id to close.')
else:
await ctx.send(f'You are not authorized to run this command.')
@commands.command(name='weather', aliases=['wu'])
@commands.cooldown(5, 15, type=commands.BucketType.default)
async def get_weather(self, ctx, *, location='palmer ak'):
'''Gets the weather data for the location provided,
If no location is included then it will get the weather for the Bot's home location.
'''
try:
url = f'http://autocomplete.wunderground.com/aq?query={location}&format=JSON'
with async_timeout.timeout(10):
async with self.bot.aio_session.get(url) as response:
data = await response.json()
link = data['RESULTS'][0]['l']
url = f'http://api.wunderground.com/api/88e14343b2dd6d8e/geolookup/conditions/{link}.json'
with async_timeout.timeout(10):
async with self.bot.aio_session.get(url) as response:
data = json.loads(await response.text())
utils_log.info(data)
em = discord.Embed()
em.title = f"Weather for {data['current_observation']['display_location']['full']}"
em.url = data['current_observation']['forecast_url']
em.description = data['current_observation']['observation_time']
em.set_thumbnail(url=data['current_observation']['icon_url'])
em.set_footer(text='Data provided by wunderground.com', icon_url=data['current_observation']['image']['url'])
value_str = f'''```
{'Temp:':<20}{data['current_observation']['temperature_string']:<22}
{'Feels Like:':<20}{data['current_observation']['feelslike_string']:<22}
{'Relative Humidity:':<20}{data['current_observation']['relative_humidity']:<22}
{'Wind:':<5}{data['current_observation']['wind_string']:^44}
```'''
em.add_field(name=f"Current Conditions: {data['current_observation']['weather']}", value=value_str, inline=False)
await ctx.send(embed=em)
except IndexError:
await ctx.send('Can\'t find that location, please try again.')
@commands.command(name='localtime', aliases=['time','lt'])
@commands.cooldown(1, 3, type=commands.BucketType.user)
async def get_localtime(self, ctx, timezone:str='Anchorage'):
em = discord.Embed()
try:
tz = pytz.timezone(timezone)
localtime = datetime.now(tz=tz)
em.title = f'{clock_emojis[(localtime.hour % 12)]} {tz}'
em.description = localtime.strftime('%c')
em.colour = embed_color
await ctx.send(embed=em)
except pytz.exceptions.UnknownTimeZoneError:
for tz in pytz.all_timezones:
if timezone.lower() in tz.lower():
localtime = datetime.now(tz=pytz.timezone(tz))
em.title = f'{clock_emojis[(localtime.hour % 12)]} {tz}'
em.description = localtime.strftime('%c')
em.colour = embed_color
await ctx.send(embed=em)
return
em.title = 'Unknown Timezone.'
em.colour = discord.Colour.red()
await ctx.send(embed=em)
@commands.command(name='purge', aliases=['clean', 'erase'])
@commands.cooldown(1, 3, type=commands.BucketType.user)
async def purge_messages(self, ctx, number:int=20, member:discord.Member=None):
def is_me(message):
if message.author == self.bot.user:
return True
prefixes = self.bot.con.one(f'select prefix from guild_config where guild_id = {ctx.guild.id}')
if prefixes:
for prefix in prefixes:
if message.content.startswith(prefix):
return True
return False
return message.content.startswith(self.bot.default_prefix)
def is_member(message):
return message.author == member
def is_author(message):
return message.author == ctx.author
if checks.is_admin(self.bot, ctx):
if member:
deleted = await ctx.channel.purge(limit=number, check=is_member)
if member != ctx.author:
await ctx.message.delete()
else:
deleted = await ctx.channel.purge(limit=number, check=is_me)
else:
deleted = await ctx.channel.purge(limit=number, check=is_author)
em = discord.Embed(title='❌ Purge', colour=discord.Colour.red())
em.description = f'Deleted {len(deleted)} messages.'
await ctx.send(embed=em, delete_after=5)
@commands.command(name='purge_all', aliases=['cls','clear'])
@commands.cooldown(1, 3, type=commands.BucketType.user)
async def purge_all(self, ctx, number:int=20, contents:str='all'):
if checks.is_admin(self.bot, ctx):
if contents != 'all':
deleted = await ctx.channel.purge(limit=number, check=lambda message: message.content == contents)
else:
deleted = await ctx.channel.purge(limit=number)
em = discord.Embed(title='❌ Purge', colour=discord.Colour.red())
em.description = f'Deleted {len(deleted)} messages.'
if contents != ctx.message.content and contents != 'all':
await ctx.message.delete()
await ctx.send(embed=em, delete_after=5)
@commands.command(name='google', aliases=['g', 'search'])
async def google_search(self, ctx, *, search):
res = self.bot.gcs_service.cse().list(q=search, cx='012214819999548252842:tarnolfyw44').execute()
results = res['items'][:4]
em = discord.Embed()
em.title = f'Google Search'
em.description = f'Top 4 results for "{search}"'
em.colour = embed_color
for result in results:
em.add_field(name=f'{result["title"]}', value=f'{result["snippet"]}\n{result["link"]}')
await ctx.send(embed=em)
@commands.command(hidden=True, name='sheets')
async def google_sheets(self, ctx, member: discord.Member):
if checks.is_admin(self.bot, ctx):
scope = ['https://spreadsheets.google.com/feeds',
'https://www.googleapis.com/auth/drive']
credentials = ServiceAccountCredentials.from_json_keyfile_name('config/google_client_secret.json', scope)
gc = gspread.authorize(credentials)
sh = gc.open_by_key('128GnQPOx0u7oPGvu5nAJks_Qv2R0Ru9ILAniICoxhJ8')
ws = sh.worksheet('Current Whitelist')
names = ws.col_values('3')
steam = ws.col_values('6')
tier = ws.col_values('5')
patron = ws.col_values('4')
em = discord.Embed()
em.title = f'User Data from Whitelist Sheet'
em.colour = embed_color
for i,name in enumerate(names):
if member.name.lower() in name.lower() or member.display_name.lower() in name.lower() or name.lower() in member.name.lower() or name.lower() in member.display_name.lower():
em.add_field(name=name, value=f'Steam ID: {steam[i]}\nPatreon Level: {tier[i]}\nPatron of: {patron[i]}')
await ctx.send(embed=em)
def setup(bot):
bot.add_cog(utils(bot))