dragon-bot/app/dragon-bot.py
Luke c941b892cc Merge branch 'john' into 'master'
!help command Fixes #2

Closes #2

See merge request ldooks/dragon-bot!2
2018-06-22 02:50:24 +00:00

437 lines
14 KiB
Python

"""
dragon-bot
Our discord bot. Many of its actions are handled by separate modules which are
then imported into the main bot
"""
import os
import requests
import core_utils
import decide
import define_word
import discord
import docker
import doggos
import eight_ball
import excuse
import get_from_reddit
import help_methods
import lewds
import questions
import role_check
import set_avatar
import stock
import tts
import wallpaper
import weather
# Client object
client = discord.Client()
tokens = {
'test': 'MzQ1MjkwMTI5OTQ4Mjc4Nzg0.DG5IBw._9umb82PrL22bPe7GjmHClU-NtU',
'prod': 'MzkxNzgxMzAxNDE5NjM4Nzg0.DbGAqg.z29jiet7iKBBznb5GCqlxJTzNfY'
}
dragon_environment = os.getenv('DRAGON_ENV')
debug = dragon_environment == 'test'
@client.event
async def on_ready():
# Update the bot's status
await client.change_presence(
game=discord.Game(name='Type !help to see what I can do')
)
if not debug:
await client.edit_profile(avatar=set_avatar.change_bots_avatar())
print("\n********************************")
print("\nDRAGON BOT RUNNING IN {} MODE".format(dragon_environment.upper()))
print("\n********************************")
if debug:
print("\nPress control+c to exit the bot")
print("Followed by control+d or by typing")
print("'exit' to exit the docker container\n\n")
@client.event
async def on_message(message):
def is_me(m):
"""
is_me(m)
Takes a message as an argument and checks that the author of the message
is the same as the person who initiated the command
"""
return m.author == message.author
def generate_embed(embed_url=None, embed_title=None, embed_description=None, embed_color=None):
"""
generate_embed(embed_url=None, embed_title=None, embed_description=None, embed_color=None)
Generates a discord embed object based on the URL passed in
Optionally, you can set the title and description text for the embed object.
"""
if not embed_description and embed_url:
embed_description="[Direct Link]({})".format(embed_url)
if not embed_color:
embed_color=discord.Color.gold()
embed = discord.Embed(
title=embed_title,
description=embed_description,
color=embed_color,
type='rich'
)
if embed_url:
embed.set_image(url=embed_url)
return embed
if client.user.mentioned_in(message):
await client.send_message(
message.channel,
"{} ```{}```".format(
message.author.mention,
questions.answer_question(message.content)
)
)
# Read messages and look for mentions of subreddits
for word in message.content.split():
if message.author != client.user:
if '/r/' in word or 'r/' in word:
try:
subreddit = word.split('/')[-1]
# Try and request the page to check that it actually exists
get_from_reddit.get_image(boards=subreddit, nsfw=True)
await client.send_message(message.channel, "https://reddit.com/r/{}".format(subreddit))
except:
pass
if message.content.startswith('!8ball'):
await client.send_message(
message.channel,
eight_ball.check_8ball(message.content)
)
if message.content.startswith('!avatar'):
profile = [message.author]
if len(message.mentions):
profile = message.mentions
# Code stolen from this reddit post
# https://www.reddit.com/r/discordapp/comments/74bb4z/retrieve_a_mentioned_users_avatar_using_discordpy
for user in profile:
await client.send_message(
message.channel,
embed=generate_embed(
embed_title="{}#{}".format(user.name, user.discriminator),
embed_url=user.avatar_url.replace('.webp', '.png'),
embed_description="[Direct Link]({})".format(user.avatar_url.replace('.webp', '.png'))
)
)
if message.content.startswith('!clap'):
await client.delete_message(message)
await client.send_message(
message.channel,
"{}".format(':clap:'.join(message.content.split()[1:]))
)
if message.content.startswith('!cleanup'):
if not role_check.cleanup_permissions(message.author.roles):
await client.send_message(message.channel, 'You cant do that')
return
def is_bot(m):
return m.author == client.user
await client.purge_from(message.channel, limit=10, check=is_bot)
if message.content.startswith('!decide'):
await client.send_message(
message.channel,
"{} {}".format(
message.author.mention,
decide.decide(message.content)
)
)
if message.content.startswith('!define'):
await client.send_message(
message.channel,
define_word.get_definition(message.content)
)
if message.content.startswith('!dog'):
await client.send_message(
message.channel,
embed=generate_embed(embed_url=doggos.get_dog())
)
if message.content.startswith('!excuse'):
await client.send_message(message.channel, excuse.get_excuse())
if message.content.startswith('!emoji'):
if not role_check.is_admin(message.author.roles):
await client.send_message(
message.channel,
"You dont have permission to create emojis"
)
return
emoji_staging = '/tmp/emoji'
try:
command, url, emoji_name = message.content.split()
except Exception:
await client.send_message(
message.channel,
help_methods.get_help_message('emoji')
)
return
try:
# Attempt to upload the emoji
await client.delete_message(message)
await client.send_message(
message.channel,
"emoji successfully uploaded! Heres how it looks in a sentence {}\nUse it with `:{}:`".format(
await client.create_custom_emoji(
server=message.server,
name=emoji_name,
image=open(core_utils.download_image(url, emoji_staging), "rb").read()
), emoji_name
)
)
except Exception:
await client.send_message(
message.channel,
"I wasnt able to upload that image as an emoji. Sorry"
)
os.remove(emoji_staging)
return
if message.content.startswith('!greentext'):
await client.send_message(
message.channel,
embed=generate_embed(
embed_title='>implying this actually happened',
embed_color=discord.Color.green(),
embed_url=get_from_reddit.get_image(boards=['classic4chan', 'greentext', '4chan'])
)
)
if message.content.startswith('!help'):
if len(message.content.split()) > 1:
await client.send_message(message.channel, help_methods.parse_message(message.content))
else:
await client.send_message(message.channel, embed=help_methods.get_help_embed(client))
if message.content.startswith('!homepage'):
await client.send_message(
message.channel,
embed=generate_embed(embed_url=wallpaper.fcking_homepage())
)
if message.content.startswith('!invite'):
# 43200 = 12 hours
invite = await client.create_invite(
destination=message.channel, max_uses=1, max_age=43200
)
await client.send_message(message.channel, invite)
if message.content.startswith('!lewd'):
if 'nsfw' in message.channel.name:
await client.send_message(
message.channel,
embed=generate_embed(
embed_url=lewds.get_lewd(),
embed_title="{} is being lewd".format(message.author.name)
)
)
else:
await client.send_message(
message.channel,
'You can only use this command in NSFW channels'
)
if message.content.startswith('!weather'):
await client.send_message(
message.channel,
weather.parse_loc(message.content)
)
if message.content.startswith('!stock'):
await client.send_message(
message.channel,
stock.parse_share(message.content)
)
if message.content.startswith('!pout'):
await client.send_message(
message.channel,
embed=generate_embed(embed_url=get_from_reddit.get_image('pout'))
)
if message.content.startswith('!smug'):
await client.send_message(
message.channel,
embed=generate_embed(embed_url=get_from_reddit.get_image('smuganimegirls'))
)
if message.content.startswith('!source'):
await client.send_message(
message.channel,
"http://luker.zzzz.io/gitlab/ldooks/dragon-bot"
)
if message.content.startswith('!purge'):
num = 20
if len(message.content.split()) > 1:
try:
num = int(message.content.split()[1])
except ValueError:
await client.send_message(
message.channel,
"You need to give me a number, you entered {}".format(
message.content.split()[1]
)
)
return
await client.purge_from(message.channel, limit=num, check=is_me)
if message.content.startswith('!roles'):
await client.send_message(
message.channel,
"ok {}. Check your PMs".format(message.author.mention)
)
await client.send_message(
message.author,
"```{}```".format(' '.join(list(map(lambda x: x.name, message.author.roles))))
)
if message.content.startswith('!tts'):
await client.send_file(
message.channel,
tts.text_to_speech(message.content),
filename="A Message From {}.mp3".format(message.author.name)
)
os.remove('/tmp/memes.mp3')
if message.content.startswith('!wallpaper'):
await client.send_message(
message.channel,
embed=generate_embed(embed_url=wallpaper.get_wall(message.content))
)
if message.content.startswith('!minecraft'):
# Check permissions
if not role_check.docker_permissions(message.author.roles):
await client.send_message(
message.channel,
"You dont have permission to run docker commands"
)
return
if len(message.content.split()) == 1:
actions = ['restart', 'status', 'logs', 'map']
await client.send_message(
message.channel,
"\nSupported actions:```\n{}```".format(", ".join(actions))
)
else:
docker_client = docker.from_env()
try:
minecraft_container = docker_client.containers.get('beyondreality')
except:
await client.send_message(
message.channel,
"The minecraft server is not running"
)
return
# Figure out what action they want to take
action = message.content.split()[1]
if action == 'restart':
await client.send_message(
message.channel,
"{}, restart the server? [!yes/!no]".format(
message.author.mention)
)
confirm_restart = await client.wait_for_message(
author=message.author,
channel=message.channel,
content='!yes'
)
if confirm_restart:
await client.send_message(
message.channel,
"Sending restart action to {} server".format(
minecraft_container.name
)
)
minecraft_container.restart()
if action == 'status':
await client.send_message(
message.channel,
"{} server is {}".format(
minecraft_container.name,
minecraft_container.status
)
)
if action == 'logs':
if len(message.content.split()) == 3:
num_lines = int(message.content.split()[2])
else:
num_lines = 10
log_stream = minecraft_container.logs(
tail=num_lines
).decode('utf-8')
if len(log_stream) >= num_lines:
await client.send_message(
message.channel,
"Pulling last {} lines from the {} server ".format(
num_lines,
minecraft_container.name
)
)
await client.send_message(
message.channel,
"```{}```".format(
minecraft_container.logs(
tail=num_lines
).decode('utf-8')
)
)
else:
await client.send_message(
message.channel,
"There arent {} lines of output yet".format(num_lines)
)
if action == 'map':
await client.send_message(
message.channel,
"http://luker.zzzz.io/minecraft"
)
client.run(tokens[dragon_environment])