From 6da779d59fa6b7351cffdf888898fce8b40fa65f Mon Sep 17 00:00:00 2001 From: ojhern24 Date: Fri, 5 May 2023 18:52:09 -0400 Subject: Refresh of old repository --- bot.py | 239 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 239 insertions(+) create mode 100644 bot.py (limited to 'bot.py') diff --git a/bot.py b/bot.py new file mode 100644 index 0000000..5f5c4e8 --- /dev/null +++ b/bot.py @@ -0,0 +1,239 @@ +import logging +import subprocess +import time +import urllib.request +from os import path + +import discord +from discord.ext import commands +from discord.ext.commands import BucketType + +import botConfig + +# Log information +logger = logging.getLogger('discord') +logger.setLevel(logging.DEBUG) +handler = logging.FileHandler(filename='discord.log', encoding='utf-8', mode='w') +handler.setFormatter(logging.Formatter('%(asctime)s:%(levelname)s:%(name)s: %(message)s')) +logger.addHandler(handler) + + +# Functions + +def log(text): + print('[General]: ' + text) + + +# Bot Config +token = botConfig.token +guild = botConfig.guild + +# Links +botRepo = botConfig.bot_repo + +# Open Ports +minecraftPort = botConfig.minecraft_port + +# Scripts +minecraftServer = botConfig.minecraft_server_script + +# Sounds +hello = botConfig.hello_sound + +# Initialize bot +client = commands.Bot(command_prefix=botConfig.prefix) + +# Initialize extensions +extensions = ( + "cogs.minecraft", +) + +print('Loading cogs:') + +for extension in extensions: + try: + client.load_extension(extension) + except Exception as e: + print(f'Failed to load extension {extension}') + +print('\n') + + +# Events + +@client.event +async def on_ready(): + log('Logged on as: (' + str(client.user) + ').') + + +@client.event +async def on_message(message): + # don't respond to ourselves + if message.author == client.user: + return + + await client.process_commands(message) + + if message.content == 'hello mario': + await message.channel.send('Hello!') + try: + await message.channel.send(file=discord.File(hello)) + except Exception as e: + log('User has found an easter egg but no sound file was provided!') + + +# Easter Egg + + +# @client.event +# async def on_command_error(error, ctx): +# await error.send('An error has occurred.') + +# Commands + +# *General* + +@client.command(aliases=['github', 'repo', 'repository', 'source', 'download'], + brief='Links to the current repository for this bot!') +async def codebase(ctx): + await ctx.send(botRepo) + + +@client.command(brief='Outputs the latency between Discord and the bot') +async def ping(ctx): + await ctx.send(f'Pong! `{round(client.latency * 1000)}ms`') + + +# *Server* + +# Please check /scripts and configure .env and add your directories, otherwise this will not work +@client.command(aliases=['boot', 'start'], brief='Initializes a server for compatible games', + description='Initializes a server for compatible games, type {0}run usage for more info.'.format( + botConfig.prefix)) +@commands.cooldown(1, 30, BucketType.guild) +async def run(ctx, *, game): + if game == 'usage': + await ctx.send('```{0}run [game], Example: $run minecraft\n\n'.format(botConfig.prefix) + + 'List of compatible games:\n' + + '• Minecraft```') + + # Run a server if .running does not exist + elif not path.exists('.running'): + + if game == 'minecraft' or game == 'mc': + try: + await ctx.send( + 'The Minecraft server script has been executed, please wait a moment as the server initializes.') + subprocess.call(minecraftServer, shell=True) + log('A Minecraft server has been initialized.') + + except Exception as e: + await ctx.send('Could not successfully initialize the server, please contact bot administrator.') + log('A Minecraft server could not be initialized. Please check /scripts/runMinecraft.sh to make sure ' + 'everything is set correctly. You must also ensure the script has executable permissions.') + + # Start 50-second timer to inform server should now be in service + time.sleep(50) + await ctx.send('The Minecraft server should now be up and running!') + + # Otherwise, inform the user a server cannot be executed and give further instructions. + else: + await ctx.send( + 'A server is already running! Please contact a server administrator to request a restart or termination ' + 'of the current session.') + + +@client.command(aliases=['address'], brief='Displays the server\'s external IP and open ports') +@commands.cooldown(1, 30, BucketType.guild) +async def ip(ctx): + # Check if command is allowed by bot Administrator + if botConfig.ip_cmd_allowed: + # Contact URL stored in botConfig and store IP address as string + ext_ip = urllib.request.urlopen(botConfig.ip_grab_website).read().decode('utf8') + await ctx.send("Server IP: `" + ext_ip + "`" + + "\nOpen Ports:" + + "\n```Minecraft: " + minecraftPort + "```") + + else: + await ctx.send('Bot administrator has not authorized this command.') + log('IP grab attempt blocked. To change this behavior open botConfig.py and find the line: ' + + '\'ipCmdAllowed = False\'' + + '\nand replace False with True') + + +@client.command(aliases=['bandwidth'], brief='Perform a speedtest, powered by Ookla™') +@commands.cooldown(1, 90, BucketType.guild) +async def speedtest(ctx): + # Check if command is allowed by bot Administrator + if botConfig.speedtest_cmd_allowed: + import speedtest + + log('A user has just initiated a speedtest.') + await ctx.send('Attempting to perform Speedtest...') + + # https://github.com/sivel/speedtest-cli/wiki + + servers = [] + threads = None + + attempt = speedtest.Speedtest() + attempt.get_servers(servers) + attempt.get_best_server() + + await ctx.send('Performing download test...') + attempt.download(threads=threads) + + await ctx.send('Performing upload test...') + attempt.upload(threads=threads) + + log('Here are the results: ' + attempt.results.share()) + await ctx.send(attempt.results.share()) + + else: + await ctx.send('Bot administrator has not authorized this command.') + log('Speedtest attempt blocked. To change this behavior open botConfig.py and find the line: ' + + '\'speedtestCmdAllowed = False\'' + + '\nand replace False with True') + + +# Error Handlers + +@run.error +async def run_error(ctx, error): + # Check if currently on cooldown + if isinstance(error, commands.CommandOnCooldown): + await ctx.send( + 'This command has a 30 second cooldown. You may use it again in `{:.2f}`s'.format(error.retry_after)) + + else: + await ctx.send("You must specify a game!") + + +@ip.error +async def ip_error(ctx, error): + # Check if currently on cooldown + if isinstance(error, commands.CommandOnCooldown): + await ctx.send( + 'This command has a 30 second cooldown. You may use it again in `{:.2f}`s'.format(error.retry_after)) + + else: + await ctx.send("An unknown error has occurred.") + + +@speedtest.error +async def speedtest_error(ctx, error): + # Check if currently on cooldown + if isinstance(error, commands.CommandOnCooldown): + await ctx.send( + 'This command has a 90 second cooldown. You may use it again in `{:.2f}`s'.format(error.retry_after)) + + else: + await ctx.send("An unknown error has occurred.") + + +# Run bot with corresponding token +client.run(token) + +# To do list +# Disable Easter eggs if missing in config +# Make $run and $speedtest run asynchronously -- cgit v1.2.3-54-g00ecf