forked from Minecraft/minecraft_manager
Make discord bot external again
Signed-off-by: Etzelia <etzelia@hotmail.com>external-bot
parent
dcd1db1d4a
commit
fa8908531c
28
api/api.py
28
api/api.py
|
@ -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 django.contrib.auth.models import User
|
||||
from django.conf import settings
|
||||
from minecraft_manager.bot.discord import send as discord_send, DestType
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -39,24 +38,35 @@ def plugin(key, command):
|
|||
|
||||
|
||||
def discord_mcm(message='', embed=None, ping=False):
|
||||
channel_id = getattr(settings, 'DISCORD_MCM_CHANNEL', None)
|
||||
if channel_id:
|
||||
discord_mcm_webhook = getattr(settings, 'DISCORD_MCM_WEBHOOK', None)
|
||||
if discord_mcm_webhook:
|
||||
ping_list = getattr(settings, 'DISCORD_PING_LIST', [])
|
||||
if ping and ping_list:
|
||||
ping_list = ["<@&{0}>".format(ping) for ping in ping_list]
|
||||
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):
|
||||
channel_id = getattr(settings, 'DISCORD_NOTIFICATION_CHANNEL', None)
|
||||
if channel_id:
|
||||
discord_notification_webhook = getattr(settings, 'DISCORD_NOTIFICATION_WEBHOOK', None)
|
||||
if discord_notification_webhook:
|
||||
ping_list = getattr(settings, 'DISCORD_PING_LIST', [])
|
||||
if ping and ping_list:
|
||||
ping_list = ["<@&{0}>".format(ping) for ping in ping_list]
|
||||
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):
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from django.conf import settings
|
||||
import subprocess
|
||||
import subprocess, os
|
||||
|
||||
|
||||
class Bot:
|
||||
|
@ -17,10 +17,11 @@ class Bot:
|
|||
self.restart = restart if restart else self._restart
|
||||
self.status = status if status else self._status
|
||||
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):
|
||||
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)
|
||||
|
||||
def _stop(self):
|
||||
|
|
|
@ -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()
|
118
bot/discord.py
118
bot/discord.py
|
@ -13,29 +13,11 @@ from minecraft_manager.utils import url_path
|
|||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
discord_loop = None
|
||||
discord_bot = None
|
||||
description = '''
|
||||
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):
|
||||
discord_game = 'MCM'
|
||||
prefix = getattr(settings, 'DISCORD_BOT_PREFIX', '!')
|
||||
|
@ -43,14 +25,13 @@ class Discord(commands.Bot):
|
|||
superuser_roles = getattr(settings, 'DISCORD_SUPERUSER_ROLES', [])
|
||||
error_users = getattr(settings, 'DISCORD_ERROR_USERS', [])
|
||||
|
||||
def __init__(self, token, loop):
|
||||
super().__init__(command_prefix=self.prefix, description=description, case_insensitive=True, help_command=None, activity=discord.Game(name=self.discord_game), loop=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))
|
||||
self.token = token
|
||||
self.load_extension("minecraft_manager.bot.commands")
|
||||
|
||||
async def on_ready(self):
|
||||
global discord_status
|
||||
discord_status = DiscordStatus.STARTED
|
||||
print('Logged in as')
|
||||
print(self.user.name)
|
||||
print(self.user.id)
|
||||
|
@ -80,10 +61,6 @@ class Discord(commands.Bot):
|
|||
embed.description = content
|
||||
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):
|
||||
if isinstance(message, discord.Embed):
|
||||
for idx, field in enumerate(message.fields):
|
||||
|
@ -107,81 +84,14 @@ class Discord(commands.Bot):
|
|||
await self.discord_message(user, '```python\n{}```'.format(error))
|
||||
|
||||
def run_bot(self):
|
||||
global discord_loop
|
||||
loop = True
|
||||
while loop:
|
||||
try:
|
||||
discord_loop.run_until_complete(self.start(self.token))
|
||||
except KeyboardInterrupt:
|
||||
logger.info("Bot received keyboard interrupt")
|
||||
loop = False
|
||||
except Exception as e:
|
||||
print(e)
|
||||
logger.info('Bot encountered the following unhandled exception %s', e)
|
||||
loop = False
|
||||
|
||||
|
||||
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())
|
||||
loop = asyncio.get_event_loop()
|
||||
try:
|
||||
loop.run_until_complete(self.start(self.token))
|
||||
except KeyboardInterrupt:
|
||||
logger.info("Bot received keyboard interrupt")
|
||||
except Exception as e:
|
||||
print(e)
|
||||
logger.info('Bot encountered the following unhandled exception %s', e)
|
||||
finally:
|
||||
loop.run_until_complete(self.logout())
|
||||
logger.info("Bot shutting down...")
|
||||
|
|
|
@ -23,6 +23,10 @@ Optional
|
|||
|
||||
``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_PING_LIST`` - A list of Discord Role IDs to ping whenever certain messages are sent.
|
||||
|
|
4
views.py
4
views.py
|
@ -18,8 +18,6 @@ from minecraft_manager.overview import overview_data
|
|||
from minecraft_manager.utils import resolve_player
|
||||
import minecraft_manager.api.api as API
|
||||
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):
|
||||
|
@ -467,7 +465,7 @@ class Bots(View):
|
|||
bots.append(Bot(file.replace('.bot.py', ''), False, sys.executable))
|
||||
# Also get packaged MCM bots
|
||||
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
|
||||
|
||||
def get(self, request):
|
||||
|
|
Loading…
Reference in New Issue