dragon-bot/app/dragon-bot.py

432 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
from gtts import gTTS
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 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'):
await client.send_message(message.channel, "ok {}, check your private messages".format(message.author.mention))
await client.send_message(
message.author,
help_methods.parse_message(message.content)
)
if message.content.startswith('!homepage'):
await client.send_message(
message.channel,
embed=generate_embed(embed_url=wallpaper.fcking_homepage())
)
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,
"https://gitlab.com/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'):
myobj = gTTS(
text=' '.join(message.content.split()[1:]),
lang='en',
slow=False
)
file_path = '/tmp/memes.mp3'
myobj.save(file_path)
await client.send_file(
message.channel,
file_path,
)
os.remove(file_path)
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('!docker'):
# 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']
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 container 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 container? [!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 {} container".format(
minecraft_container.name
)
)
minecraft_container.restart()
if action == 'status':
await client.send_message(
message.channel,
"{} container 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 {} container".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)
)
client.run(tokens[dragon_environment])