Make discord bot external again

Signed-off-by: Etzelia <etzelia@hotmail.com>
external-bot
Etzelia 2020-04-04 22:21:53 -05:00
parent dcd1db1d4a
commit fa8908531c
No known key found for this signature in database
GPG Key ID: 708511AE7ABC5314
6 changed files with 62 additions and 118 deletions

View File

@ -1,8 +1,7 @@
import socket, logging, os, datetime, pytz, mcstatus, random, string import socket, requests, logging, os, datetime, pytz, mcstatus, random, string
from minecraft_manager.models import Alert from minecraft_manager.models import Alert
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.conf import settings from django.conf import settings
from minecraft_manager.bot.discord import send as discord_send, DestType
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -39,24 +38,35 @@ def plugin(key, command):
def discord_mcm(message='', embed=None, ping=False): def discord_mcm(message='', embed=None, ping=False):
channel_id = getattr(settings, 'DISCORD_MCM_CHANNEL', None) discord_mcm_webhook = getattr(settings, 'DISCORD_MCM_WEBHOOK', None)
if channel_id: if discord_mcm_webhook:
ping_list = getattr(settings, 'DISCORD_PING_LIST', []) ping_list = getattr(settings, 'DISCORD_PING_LIST', [])
if ping and ping_list: if ping and ping_list:
ping_list = ["<@&{0}>".format(ping) for ping in ping_list] ping_list = ["<@&{0}>".format(ping) for ping in ping_list]
message = "{0}\n{1}".format(" ".join(ping_list), message) message = "{0}\n{1}".format(" ".join(ping_list), message)
discord_send(DestType.CHANNEL, channel_id, message, embed) data = {}
if message:
data['content'] = message
if embed:
data['embeds'] = embed
return requests.post(discord_mcm_webhook, json=data)
return None
def discord_notification(message='', embed=None, ping=False): def discord_notification(message='', embed=None, ping=False):
channel_id = getattr(settings, 'DISCORD_NOTIFICATION_CHANNEL', None) discord_notification_webhook = getattr(settings, 'DISCORD_NOTIFICATION_WEBHOOK', None)
if channel_id: if discord_notification_webhook:
ping_list = getattr(settings, 'DISCORD_PING_LIST', []) ping_list = getattr(settings, 'DISCORD_PING_LIST', [])
if ping and ping_list: if ping and ping_list:
ping_list = ["<@&{0}>".format(ping) for ping in ping_list] ping_list = ["<@&{0}>".format(ping) for ping in ping_list]
message = "{0}\n{1}".format(" ".join(ping_list), message) message = "{0}\n{1}".format(" ".join(ping_list), message)
discord_send(DestType.CHANNEL, channel_id, message, embed) data = {}
if message:
data['content'] = message
if embed:
data['embeds'] = embed
return requests.post(discord_notification_webhook, json=data)
return None
def strip_format(message): def strip_format(message):

View File

@ -1,5 +1,5 @@
from django.conf import settings from django.conf import settings
import subprocess import subprocess, os
class Bot: class Bot:
@ -17,10 +17,11 @@ class Bot:
self.restart = restart if restart else self._restart self.restart = restart if restart else self._restart
self.status = status if status else self._status self.status = status if status else self._status
self.display = display if display else self._display self.display = display if display else self._display
self.dir = "{}/assets/".format(os.path.dirname(os.path.abspath(__file__))) if self.asset else self.bot_dir
def _start(self): def _start(self):
screen = 'screen -S {0}_{1} -d -m {2} {3}{1}.bot.py' screen = 'screen -S {0}_{1} -d -m {2} {3}{1}.bot.py'
subprocess.run(screen.format(self.plugin_port, self.name, self.executable, self.bot_dir), subprocess.run(screen.format(self.plugin_port, self.name, self.executable, self.dir),
shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
def _stop(self): def _stop(self):

View File

@ -0,0 +1,21 @@
import os
import sys
import django
sep = os.sep
path = os.path.dirname(os.path.abspath(__file__))
path = path.split(sep)[:-3]
project = path[-1]
path = sep.join(path)
sys.path.append(path)
print("Setting path for {0}: {1}".format(project, path))
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{}.settings".format(project))
django.setup()
from django.conf import settings
from minecraft_manager.bot.discord import Discord
token = getattr(settings, 'DISCORD_BOT_TOKEN', None)
bot = Discord(token)
bot.run_bot()

View File

@ -13,29 +13,11 @@ from minecraft_manager.utils import url_path
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
discord_loop = None
discord_bot = None
description = ''' description = '''
A Discord bot connected to an MCM instance. A Discord bot connected to an MCM instance.
''' '''
class DiscordStatus(Enum):
STOPPED = 0
STARTING = 1
STARTED = 2
STOPPING = 3
def __str__(self):
return self.name.title()
def is_running(self):
return self != DiscordStatus.STOPPED
discord_status = DiscordStatus.STOPPED
class Discord(commands.Bot): class Discord(commands.Bot):
discord_game = 'MCM' discord_game = 'MCM'
prefix = getattr(settings, 'DISCORD_BOT_PREFIX', '!') prefix = getattr(settings, 'DISCORD_BOT_PREFIX', '!')
@ -43,14 +25,13 @@ class Discord(commands.Bot):
superuser_roles = getattr(settings, 'DISCORD_SUPERUSER_ROLES', []) superuser_roles = getattr(settings, 'DISCORD_SUPERUSER_ROLES', [])
error_users = getattr(settings, 'DISCORD_ERROR_USERS', []) error_users = getattr(settings, 'DISCORD_ERROR_USERS', [])
def __init__(self, token, loop): def __init__(self, token):
super().__init__(command_prefix=self.prefix, description=description, case_insensitive=True, help_command=None, activity=discord.Game(name=self.discord_game), loop=loop) super().__init__(command_prefix=self.prefix, description=description, case_insensitive=True, help_command=None,
activity=discord.Game(name=self.discord_game))
self.token = token self.token = token
self.load_extension("minecraft_manager.bot.commands") self.load_extension("minecraft_manager.bot.commands")
async def on_ready(self): async def on_ready(self):
global discord_status
discord_status = DiscordStatus.STARTED
print('Logged in as') print('Logged in as')
print(self.user.name) print(self.user.name)
print(self.user.id) print(self.user.id)
@ -80,10 +61,6 @@ class Discord(commands.Bot):
embed.description = content embed.description = content
await self.discord_message(channel, embed) await self.discord_message(channel, embed)
async def on_disconnect(self):
global discord_status
discord_status = DiscordStatus.STOPPED
async def discord_message(self, dest, message): async def discord_message(self, dest, message):
if isinstance(message, discord.Embed): if isinstance(message, discord.Embed):
for idx, field in enumerate(message.fields): for idx, field in enumerate(message.fields):
@ -107,81 +84,14 @@ class Discord(commands.Bot):
await self.discord_message(user, '```python\n{}```'.format(error)) await self.discord_message(user, '```python\n{}```'.format(error))
def run_bot(self): def run_bot(self):
global discord_loop loop = asyncio.get_event_loop()
loop = True
while loop:
try: try:
discord_loop.run_until_complete(self.start(self.token)) loop.run_until_complete(self.start(self.token))
except KeyboardInterrupt: except KeyboardInterrupt:
logger.info("Bot received keyboard interrupt") logger.info("Bot received keyboard interrupt")
loop = False
except Exception as e: except Exception as e:
print(e) print(e)
logger.info('Bot encountered the following unhandled exception %s', e) logger.info('Bot encountered the following unhandled exception %s', e)
loop = False finally:
loop.run_until_complete(self.logout())
logger.info("Bot shutting down...")
def start():
global discord_loop, discord_bot, discord_status
if discord_status != DiscordStatus.STOPPED:
return
token = getattr(settings, 'DISCORD_BOT_TOKEN', None)
discord_loop = asyncio.new_event_loop()
discord_bot = Discord(token, discord_loop)
thread = threading.Thread(target=discord_bot.run_bot)
thread.start()
discord_status = DiscordStatus.STARTING
def stop():
global discord_loop, discord_bot, discord_status
if discord_status == DiscordStatus.STARTED:
discord_loop.create_task(discord_bot.close())
discord_status = DiscordStatus.STOPPING
discord_loop = None
discord_bot = None
def restart():
def _restart():
stop()
while discord_status.is_running():
pass
start()
if discord_status != DiscordStatus.STARTED:
return
thread = threading.Thread(target=_restart)
thread.start()
def status():
return discord_status.is_running()
def display():
return str(discord_status)
class DestType(Enum):
CHANNEL = 1
USER = 2
def send(dest_type: DestType, dest_id: int, message: str = "", embed: discord.Embed = None):
async def _send():
if dest_type == DestType.CHANNEL:
dest = discord_bot.get_channel(dest_id)
elif dest_type == DestType.USER:
dest = discord_bot.get_user(dest_id)
else:
return
if message is not None:
await dest.send(message)
if embed is not None:
for idx, field in enumerate(embed.fields):
if not field.value:
embed.set_field_at(idx, name=field.name, value="N/A")
await dest.send(embed=embed)
global discord_loop, discord_bot
if discord_loop:
discord_loop.create_task(_send())

View File

@ -23,6 +23,10 @@ Optional
``BOT_DIR`` - The path to your bot directory. ``BOT_DIR`` - The path to your bot directory.
``DISCORD_NOTIFICATION_WEBHOOK`` - The URL for the webhook used for notifications.
``DISCORD_MCM_WEBHOOK`` - The URL for the webhook used for Applications, Tickets, and Warnings.
``DISCORD_BOT_TOKEN`` - The token to use to run the Discord bot. This must be generated by you in the Discord developer area. ``DISCORD_BOT_TOKEN`` - The token to use to run the Discord bot. This must be generated by you in the Discord developer area.
``DISCORD_PING_LIST`` - A list of Discord Role IDs to ping whenever certain messages are sent. ``DISCORD_PING_LIST`` - A list of Discord Role IDs to ping whenever certain messages are sent.

View File

@ -18,8 +18,6 @@ from minecraft_manager.overview import overview_data
from minecraft_manager.utils import resolve_player from minecraft_manager.utils import resolve_player
import minecraft_manager.api.api as API import minecraft_manager.api.api as API
from minecraft_manager.bot import Bot from minecraft_manager.bot import Bot
from minecraft_manager.bot.discord import start as discord_start, stop as discord_stop, restart as discord_restart, \
status as discord_status, display as discord_display
class Overview(View): class Overview(View):
@ -467,7 +465,7 @@ class Bots(View):
bots.append(Bot(file.replace('.bot.py', ''), False, sys.executable)) bots.append(Bot(file.replace('.bot.py', ''), False, sys.executable))
# Also get packaged MCM bots # Also get packaged MCM bots
if getattr(settings, 'DISCORD_BOT_TOKEN', None): if getattr(settings, 'DISCORD_BOT_TOKEN', None):
bots.append(Bot("Discord-MCM", True, None, discord_start, discord_stop, discord_restart, discord_status, discord_display)) bots.append(Bot("Discord-MCM", True, sys.executable))
return bots return bots
def get(self, request): def get(self, request):