Really big PR.\nBuilding out a role check module and linting a lot of the bot for cleanliness. Fixes #22

This commit is contained in:
Luke Robles 2017-08-18 16:51:34 -05:00
parent ba72688d8d
commit 8264a780cc
3 changed files with 147 additions and 59 deletions

View File

@ -1,6 +1,10 @@
import random
import sys
import requests
"""
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 decide
@ -11,6 +15,7 @@ import eight_ball
import excuse
import help_methods
import lewds
import role_check
import wallpaper
import wolfram
@ -29,12 +34,14 @@ async def on_ready():
print("\nDRAGON BOT RUNNING IN {} MODE".format(dragon_environment.upper()))
print("\n********************************")
await client.change_presence(game=discord.Game(name='Type !help to see how to use me'))
await client.change_presence(
game=discord.Game(name='Type !help to see what I can do')
)
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")
print("'exit' to exit the docker container\n\n")
@client.event
@ -43,13 +50,11 @@ async def on_message(message):
"""
is_me(m)
takes a message as an argument and checks that the author of the message
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
##### Looks like discord supports mentioning the bot.
#### Need to think of something to do here
if client.user.mentioned_in(message):
await client.send_message(
message.channel,
@ -65,7 +70,11 @@ async def on_message(message):
eight_ball.check_8ball(message.content)
)
if message.content.startswith('!cleanup') and message.author.id == '144986109804412928':
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=100, check=is_bot)
@ -95,7 +104,10 @@ async def on_message(message):
)
if message.content.startswith('!lewd'):
await client.send_message(message.channel, lewds.get_lewd(channel_name=message.channel.name))
await client.send_message(
message.channel,
lewds.get_lewd(channel_name=message.channel.name)
)
if message.content.startswith('!purge'):
num = 20
@ -103,8 +115,12 @@ async def on_message(message):
try:
num = int(message.content.split()[1])
except ValueError:
# If they dont enter a number, show them an error and return out of the function
await client.send_message(message.channel, "You need to give me a number, you entered {}".format(message.content.split()[1]))
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)
@ -112,56 +128,94 @@ async def on_message(message):
await client.send_message(
message.channel,
wallpaper.get_wall(message.content)
)
)
###################################
###### +-------------------+ ######
###### | | ######
###### | Docker Functions | ######
###### | | ######
###### +-------------------+ ######
###################################
if message.content.startswith('!docker') and (message.author != client.user):
if message.content.startswith('!docker'):
# Check permissions
roles = []
allowed_roles = ['MOD', 'Greasemonkey', 'Adminimodistrator']
for role in message.author.roles:
roles.append(role.name)
docker_privleges = not set(roles).isdisjoint(allowed_roles)
if not docker_privleges:
await client.send_message(message.channel, "Sorry {}, You dont have permission to run docker commands".format(message.author.mention))
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)))
await client.send_message(
message.channel,
"\nSupported actions:\n{}".format(", ".join(actions))
)
else:
docker_client = docker.from_env()
minecraft_container = docker_client.containers.get('skyfactory')
# Figure out what action they want to take
action = message.content.split()[1]
if action == 'restart':
await client.send_message(message.channel, "{}, Are you sure you want to restart the container? [!yes/!no]".format(message.author.mention))
confirm_restart = await client.wait_for_message(author=message.author, channel=message.channel, content='!yes')
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))
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, "{} is {}".format(minecraft_container.name, minecraft_container.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')
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')))
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))
await client.send_message(
message.channel,
"There arent {} lines of output yet".format(num_lines)
)
client.run(tokens[dragon_environment])

56
app/role_check.py Normal file
View File

@ -0,0 +1,56 @@
"""
role_check
This module's purpose is to handle permissions for interacting with the bot.
The end goal is to be able to lock certain actions down to certain roles
"""
def check_permissions(user, roles_to_check):
"""
check_permissions(user)
Parses the list object that is passed in and returns true or false if
the user has the correct roles
"""
users_roles = []
for role in user:
users_roles.append(role.name)
# Returns true if the user contains a role in the roles_to_check list
return not set(users_roles).isdisjoint(roles_to_check)
def is_admin(user):
"""
is_admin(user)
Returns true if the user contains the Adminimodistrator role
"""
return check_permissions(user, ['Adminimodistrator'])
def is_mod(user):
"""
is_admin(user)
Returns true if the user contains the MOD or Greasemonkey role
"""
return check_permissions(user, ['MOD', 'Greasemonkey'])
def docker_permissions(user):
"""
docker_permissions(user)
Checks that the user has permissions to have dragon-bot run docker commands
"""
return is_mod(user) or is_admin(user)
def cleanup_permissions(user):
"""
cleanup_permissions(user)
Who has rights to make dragon-bot purge its messages
"""
return is_admin(user) or user.id == '144986109804412928'

View File

@ -1,25 +1,3 @@
# Add the git hooks to the local repo. This prevents pushes on master
SCRIPTDIR="$(dirname "$0")"
HOOKDIR="$SCRIPTDIR/.git/hooks"
SCRIPT="$HOOKDIR/pre-push"
cat << EOF > $SCRIPT
#!/bin/bash
protected_branch='master'
# check each branch being pushed
while read local_ref local_sha remote_ref remote_sha
do
remote_branch=$(echo $remote_ref | sed -e 's,.*/\(.*\),\1,')
if [ $protected_branch = $remote_branch ]
then
echo "ABORT PUSH: Not allowed to push directly to $protected_branch. Use --no-verify to force."
exit 1 # push will not execute
fi
done
exit 0
EOF
chmod +x $SCRIPT
# Remove the running container so we cna re-use the container name 'dragon-bot'
printf "\n[-] Deleting old dragon-bot container from system\n"
docker rm -f dragon-bot-test