forked from Minecraft/minecraft_manager
Internalize Discord Bot (#31)
parent
8073765a57
commit
c813535489
31
api/api.py
31
api/api.py
|
@ -1,7 +1,8 @@
|
||||||
import socket, requests, logging, os, datetime, pytz, mcstatus, random, string
|
import socket, 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__)
|
||||||
|
|
||||||
|
@ -37,36 +38,24 @@ def plugin(key, command):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def discord_mcm(message='', embeds=None, ping=False):
|
def discord_mcm(message='', embed=None, ping=False):
|
||||||
discord_mcm_webhook = getattr(settings, 'DISCORD_MCM_WEBHOOK', None)
|
channel_id = getattr(settings, 'DISCORD_MCM_CHANNEL', None)
|
||||||
if discord_mcm_webhook:
|
if channel_id:
|
||||||
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)
|
||||||
data = {}
|
discord_send(DestType.CHANNEL, channel_id, message, embed)
|
||||||
if message:
|
|
||||||
data['content'] = message
|
|
||||||
if embeds:
|
|
||||||
data['embeds'] = embeds
|
|
||||||
return requests.post(discord_mcm_webhook, json=data)
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def discord_notification(message='', embeds=None, ping=False):
|
def discord_notification(message='', embed=None, ping=False):
|
||||||
discord_notification_webhook = getattr(settings, 'DISCORD_NOTIFICATION_WEBHOOK', None)
|
channel_id = getattr(settings, 'DISCORD_NOTIFICATION_CHANNEL', None)
|
||||||
if discord_notification_webhook:
|
if channel_id:
|
||||||
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)
|
||||||
data = {}
|
discord_send(DestType.CHANNEL, channel_id, message, embed)
|
||||||
if message:
|
|
||||||
data['content'] = message
|
|
||||||
if embeds:
|
|
||||||
data['embeds'] = embeds
|
|
||||||
return requests.post(discord_notification_webhook, json=data)
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -192,7 +192,7 @@ class PluginAPI(View):
|
||||||
json['message'] = "{0}'s application was submitted.".format(application.username)
|
json['message'] = "{0}'s application was submitted.".format(application.username)
|
||||||
json['extra'] = application.id
|
json['extra'] = application.id
|
||||||
msg = mcm_utils.build_application(application)
|
msg = mcm_utils.build_application(application)
|
||||||
mcm_api.discord_mcm(message='New Application!', embeds=msg)
|
mcm_api.discord_mcm(message='New Application!', embed=msg)
|
||||||
elif "application_action" == keyword:
|
elif "application_action" == keyword:
|
||||||
if Application.objects.filter(id=post['application_id']).exists():
|
if Application.objects.filter(id=post['application_id']).exists():
|
||||||
application = Application.objects.get(id=post['application_id'])
|
application = Application.objects.get(id=post['application_id'])
|
||||||
|
@ -298,7 +298,7 @@ class PluginAPI(View):
|
||||||
link = "{}".format(mcm_utils.url_path(settings.MCM_BASE_LINK, 'dashboard/ticket', ticket.id))
|
link = "{}".format(mcm_utils.url_path(settings.MCM_BASE_LINK, 'dashboard/ticket', ticket.id))
|
||||||
msg = mcm_utils.build_ticket(ticket, link)
|
msg = mcm_utils.build_ticket(ticket, link)
|
||||||
json['extra'] = {'id': ticket.id, 'link': link}
|
json['extra'] = {'id': ticket.id, 'link': link}
|
||||||
mcm_api.discord_mcm(embeds=msg, ping=True)
|
mcm_api.discord_mcm(embed=msg, ping=True)
|
||||||
except:
|
except:
|
||||||
json['status'] = False
|
json['status'] = False
|
||||||
json['message'] = "Error while submitting ticket."
|
json['message'] = "Error while submitting ticket."
|
||||||
|
@ -311,7 +311,7 @@ class PluginAPI(View):
|
||||||
json['message'] = "Warning issued."
|
json['message'] = "Warning issued."
|
||||||
link = "{}".format(mcm_utils.url_path(settings.MCM_BASE_LINK, 'dashboard/note', warning.id))
|
link = "{}".format(mcm_utils.url_path(settings.MCM_BASE_LINK, 'dashboard/note', warning.id))
|
||||||
msg = mcm_utils.build_warning(warning, link)
|
msg = mcm_utils.build_warning(warning, link)
|
||||||
mcm_api.discord_mcm(embeds=msg)
|
mcm_api.discord_mcm(embed=msg)
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
json['status'] = False
|
json['status'] = False
|
||||||
json['message'] = "Error while issuing warning."
|
json['message'] = "Error while issuing warning."
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
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()
|
|
|
@ -1,55 +0,0 @@
|
||||||
-- Alerts
|
|
||||||
insert into minecraft_manager_alert (select * from whitelist_alert);
|
|
||||||
|
|
||||||
-- Applications
|
|
||||||
insert into minecraft_manager_application (select * from whitelist_application);
|
|
||||||
|
|
||||||
-- Players
|
|
||||||
insert into minecraft_manager_player (uuid, username, application_id, auth_user_id, last_seen, first_seen)
|
|
||||||
select wp.uuid, wp.username, (
|
|
||||||
select mma.id from minecraft_manager_application mma where mma.username = (
|
|
||||||
select wa.username from whitelist_application wa where wp.application_id = wa.id
|
|
||||||
)
|
|
||||||
), wp.auth_user_id, wp.last_seen, wp.first_seen from whitelist_player wp
|
|
||||||
;
|
|
||||||
|
|
||||||
-- Tickets
|
|
||||||
insert into minecraft_manager_ticket (message, priority, resolved, world, x, y, z, date, player_id, staff_id)
|
|
||||||
select wt.message, wt.priority, wt.resolved, wt.world, wt.x, wt.y, wt.z, wt.date, (
|
|
||||||
select mmp.id from minecraft_manager_player mmp where mmp.uuid = (
|
|
||||||
select wp.uuid from whitelist_player wp where wp.id = wt.player_id
|
|
||||||
)
|
|
||||||
), (
|
|
||||||
select au.id from auth_user au where au.username = (
|
|
||||||
select wp2.username from whitelist_player wp2 where wp2.id = wt.staff_id
|
|
||||||
)
|
|
||||||
) from whitelist_ticket wt
|
|
||||||
;
|
|
||||||
|
|
||||||
-- Warnings
|
|
||||||
insert into minecraft_manager_warning (message, severity, date, player_id, staff_id)
|
|
||||||
select ww.message, ww.severity, ww.date, (
|
|
||||||
select mmp.id from minecraft_manager_player mmp where mmp.uuid = (
|
|
||||||
select wp.uuid from whitelist_player wp where wp.id = ww.player_id
|
|
||||||
)
|
|
||||||
), (
|
|
||||||
select au.id from auth_user au where au.username = (
|
|
||||||
select wp2.username from whitelist_player wp2 where wp2.id = ww.staff_id
|
|
||||||
)
|
|
||||||
) from whitelist_warning ww
|
|
||||||
;
|
|
||||||
|
|
||||||
-- User Settings
|
|
||||||
insert into minecraft_manager_usersettings (default_results, default_theme, default_timezone, search_player_ip, show_timestamp_chat, last_ip, auth_user_id)
|
|
||||||
select default_results, default_theme, default_timezone, search_player_ip, show_timestamp_chat, last_ip, auth_user_id from whitelist_usersettings wu
|
|
||||||
;
|
|
||||||
|
|
||||||
-- Notes (This migration ONLY works if you are using standard whitelist app, aka only Tickets had notes)
|
|
||||||
-- The ignore is because there were some incorrectly encoded characters giving MySQL a hard time
|
|
||||||
insert ignore into minecraft_manager_note (ref_table, ref_id, message, last_update, author_id)
|
|
||||||
select wn.ref_table, (
|
|
||||||
select mmt.id from minecraft_manager_ticket mmt where mmt.message = (
|
|
||||||
select wt.message from whitelist_ticket wt where wt.id = wn.ref_id
|
|
||||||
)
|
|
||||||
), wn.message, wn.last_update, wn.author_id from whitelist_note wn where (select count(*) from whitelist_ticket wt2 where wt2.id = wn.ref_id) > 0
|
|
||||||
;
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
from django.conf import settings
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
|
class Bot:
|
||||||
|
plugin_port = getattr(settings, 'PLUGIN_PORT', None)
|
||||||
|
bot_dir = getattr(settings, 'BOT_DIR', "")
|
||||||
|
if not bot_dir.endswith("/"):
|
||||||
|
bot_dir += "/"
|
||||||
|
|
||||||
|
def __init__(self, name, asset, executable=None, start=None, stop=None, restart=None, status=None, display=None):
|
||||||
|
self.name = name
|
||||||
|
self.asset = asset
|
||||||
|
self.executable = executable
|
||||||
|
self.start = start if start else self._start
|
||||||
|
self.stop = stop if stop else self._stop
|
||||||
|
self.restart = restart if restart else self._restart
|
||||||
|
self.status = status if status else self._status
|
||||||
|
self.display = display if display else self._display
|
||||||
|
|
||||||
|
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),
|
||||||
|
shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
|
||||||
|
def _stop(self):
|
||||||
|
subprocess.run('screen -X -S "{0}_{1}" quit'.format(self.plugin_port, self.name), shell=True)
|
||||||
|
|
||||||
|
def _restart(self):
|
||||||
|
self.stop()
|
||||||
|
self.start()
|
||||||
|
|
||||||
|
def _status(self):
|
||||||
|
screens = subprocess.getoutput("screen -ls")
|
||||||
|
return True if "{0}_{1}".format(self.plugin_port, self.name) in screens else False
|
||||||
|
|
||||||
|
def _display(self):
|
||||||
|
return "Started" if self.status() else "Stopped"
|
107
bot/discord.py
107
bot/discord.py
|
@ -1,21 +1,38 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
import sys
|
|
||||||
import traceback
|
import traceback
|
||||||
|
import threading
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from minecraft_manager.bot.commands import Commands
|
|
||||||
|
|
||||||
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', '!')
|
||||||
|
@ -23,12 +40,14 @@ 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):
|
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))
|
super().__init__(command_prefix=self.prefix, description=description, case_insensitive=True, help_command=None, activity=discord.Game(name=self.discord_game), loop=loop)
|
||||||
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)
|
||||||
|
@ -38,6 +57,10 @@ class Discord(commands.Bot):
|
||||||
print('------')
|
print('------')
|
||||||
print('Logged in as {0} ({1}) with discord.py v{2}'.format(self.user.name, self.user.id, discord.__version__))
|
print('Logged in as {0} ({1}) with discord.py v{2}'.format(self.user.name, self.user.id, discord.__version__))
|
||||||
|
|
||||||
|
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):
|
||||||
|
@ -61,15 +84,77 @@ 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):
|
||||||
loop = asyncio.get_event_loop()
|
global discord_loop
|
||||||
|
|
||||||
try:
|
try:
|
||||||
loop.run_until_complete(self.start(self.token))
|
discord_loop.run_until_complete(self.start(self.token))
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
logger.info("Bot received keyboard interrupt")
|
logger.info("Bot received keyboard interrupt")
|
||||||
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)
|
||||||
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())
|
||||||
|
|
|
@ -23,11 +23,21 @@ 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_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.
|
||||||
|
|
||||||
``DISCORD_MCM_WEBHOOK`` - The URL for the webhook used for Applications, Tickets, and Warnings.
|
``DISCORD_BOT_PREFIX`` - The prefix to use for Discord bot commands. Set to ``!`` by default.
|
||||||
|
|
||||||
|
``DISCORD_BOT_ROLES`` - A list of Discord Roles allowed to use the bot. If this list is empty, no one can use the bot!
|
||||||
|
|
||||||
|
``DISCORD_SUPERUSER_ROLES`` - A list of Discord Roles allowed to use the superuser commands.
|
||||||
|
|
||||||
|
``DISCORD_ERROR_USERS`` - A list of user IDs to send errors to.
|
||||||
|
|
||||||
|
``DISCORD_MCM_CHANNEL`` - The ID for the channel used for Applications, Tickets, and Warnings.
|
||||||
|
|
||||||
|
``DISCORD_NOTIFICATION_CHANNEL`` - The ID for the channel used for notifications.
|
||||||
|
|
||||||
``DISCORD_INVITE`` - The invite code to your Discord, for after a player applies on the web form.
|
``DISCORD_INVITE`` - The invite code to your Discord, for after a player applies on the web form.
|
||||||
|
|
||||||
|
@ -51,14 +61,6 @@ Optional
|
||||||
|
|
||||||
``COREPROTECT_ACTIVITY_URL`` - The URL to your CoreProtect Activity Web UI, if it exists.
|
``COREPROTECT_ACTIVITY_URL`` - The URL to your CoreProtect Activity Web UI, if it exists.
|
||||||
|
|
||||||
``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_PREFIX`` - The prefix to use for Discord bot commands. Set to ``!`` by default.
|
|
||||||
|
|
||||||
``DISCORD_BOT_ROLES`` - A list of Discord Roles allowed to use the bot. If this list is empty, no one can use the bot!
|
|
||||||
|
|
||||||
``DISCORD_BOT_NEW_MEMBER_ROLES`` - A list of Discord Roles to give new players when they register.
|
|
||||||
|
|
||||||
``CAPTCHA_SECRET`` - Your secret key used for reCAPTCHA
|
``CAPTCHA_SECRET`` - Your secret key used for reCAPTCHA
|
||||||
|
|
||||||
``STATS_FILTER`` - A python list of partial strings used to filter out stats. e.g. ``['broken', 'dropped', 'picked_up']`` to filter out broken, dropped and picked up stats
|
``STATS_FILTER`` - A python list of partial strings used to filter out stats. e.g. ``['broken', 'dropped', 'picked_up']`` to filter out broken, dropped and picked up stats
|
|
@ -70,7 +70,7 @@ class Apply(View):
|
||||||
if valid and valid_username and captcha.success:
|
if valid and valid_username and captcha.success:
|
||||||
app = form.save()
|
app = form.save()
|
||||||
msg = mcm_utils.build_application(app)
|
msg = mcm_utils.build_application(app)
|
||||||
mcm_api.discord_mcm(message='New Application!', embeds=msg)
|
mcm_api.discord_mcm(message='New Application!', embed=msg)
|
||||||
mcm_api.plugin("application", "{0} {1}".format(form.data['username'], app.id))
|
mcm_api.plugin("application", "{0} {1}".format(form.data['username'], app.id))
|
||||||
else:
|
else:
|
||||||
for error in captcha.errors:
|
for error in captcha.errors:
|
||||||
|
@ -109,7 +109,7 @@ class Ticket(View):
|
||||||
# Create the message to send to Discord
|
# Create the message to send to Discord
|
||||||
link = "{}".format(mcm_utils.url_path(settings.MCM_BASE_LINK, 'dashboard/ticket', ticket.id))
|
link = "{}".format(mcm_utils.url_path(settings.MCM_BASE_LINK, 'dashboard/ticket', ticket.id))
|
||||||
msg = mcm_utils.build_ticket(ticket, link)
|
msg = mcm_utils.build_ticket(ticket, link)
|
||||||
mcm_api.discord_mcm(message="New Ticket", embeds=msg, ping=True)
|
mcm_api.discord_mcm(message="New Ticket", embed=msg, ping=True)
|
||||||
mcm_api.plugin("ticket", "{0} {1} {2}".format(username, ticket.id, link))
|
mcm_api.plugin("ticket", "{0} {1} {2}".format(username, ticket.id, link))
|
||||||
else:
|
else:
|
||||||
for error in captcha.errors:
|
for error in captcha.errors:
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
{% extends "minecraft_manager/dashboard.html" %}
|
{% extends "minecraft_manager/dashboard.html" %}
|
||||||
{% load csrf_html %}
|
{% load csrf_html %}
|
||||||
{% load getattribute %}
|
|
||||||
{% block title %}Bots{% endblock %}
|
{% block title %}Bots{% endblock %}
|
||||||
{% block section %}
|
{% block section %}
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<!-- {{ form.status }} -->
|
{% for bot in bots %}
|
||||||
{% for bot in form.bots %}
|
<p>{{ bot.name }}: <span class="label {% if bot.status is True %}label-success{% else %}label-danger{% endif %}">{{ bot.display }}</span></p>
|
||||||
<p>{{ bot.name }}: <span class="label {% if form|getattribute:bot.name is True %}label-success{% else %}label-danger{% endif %}">{% if form|getattribute:bot.name is True %}Started{% else %}Stopped{% endif %}</span></p>
|
|
||||||
<form action="" method="post">{% autoescape off %}{% get_csrf_html request %}{% endautoescape %}
|
<form action="" method="post">{% autoescape off %}{% get_csrf_html request %}{% endautoescape %}
|
||||||
<button class="btn btn-primary{% if form|getattribute:bot.name is True %} disabled{% endif %}" type="submit" name="{{ bot.name }}" value="start" {% if form|getattribute:bot.name is True %} disabled="disabled"{% endif %}>Start</button>
|
<button class="btn btn-primary{% if bot.status is True %} disabled{% endif %}" type="submit" name="{{ bot.name }}" value="start" {% if bot.status is True %} disabled="disabled"{% endif %}>Start</button>
|
||||||
<button class="btn btn-primary{% if form|getattribute:bot.name is False %} disabled{% endif %}" type="submit" name="{{ bot.name }}" value="stop" {% if form|getattribute:bot.name is False %}disabled="disabled"{% endif %}>Stop</button>
|
<button class="btn btn-primary{% if bot.status is False %} disabled{% endif %}" type="submit" name="{{ bot.name }}" value="stop" {% if bot.status is False %}disabled="disabled"{% endif %}>Stop</button>
|
||||||
<button class="btn btn-primary{% if form|getattribute:bot.name is False %} disabled{% endif %}" type="submit" name="{{ bot.name }}" value="restart" {% if form|getattribute:bot.name is False %}disabled="disabled"{% endif %}>Restart</button>
|
<button class="btn btn-primary{% if bot.status is False %} disabled{% endif %}" type="submit" name="{{ bot.name }}" value="restart" {% if bot.status is False %}disabled="disabled"{% endif %}>Restart</button>
|
||||||
</form>
|
</form>
|
||||||
<br/>
|
<br/>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
6
utils.py
6
utils.py
|
@ -38,7 +38,7 @@ def build_application(application):
|
||||||
embed.add_field(name="Read the Rules", value=application.read_rules)
|
embed.add_field(name="Read the Rules", value=application.read_rules)
|
||||||
embed.add_field(name="Date", value=application.date_display)
|
embed.add_field(name="Date", value=application.date_display)
|
||||||
embed.add_field(name="Status", value=application.status)
|
embed.add_field(name="Status", value=application.status)
|
||||||
return [embed.to_dict()]
|
return embed
|
||||||
|
|
||||||
|
|
||||||
def build_ticket(ticket, link):
|
def build_ticket(ticket, link):
|
||||||
|
@ -53,7 +53,7 @@ def build_ticket(ticket, link):
|
||||||
embed.add_field(name="Location", value=ticket.location)
|
embed.add_field(name="Location", value=ticket.location)
|
||||||
embed.add_field(name="Message", value=ticket.message)
|
embed.add_field(name="Message", value=ticket.message)
|
||||||
embed.add_field(name="Link", value=link)
|
embed.add_field(name="Link", value=link)
|
||||||
return [embed.to_dict()]
|
return embed
|
||||||
|
|
||||||
|
|
||||||
def build_warning(warning, link):
|
def build_warning(warning, link):
|
||||||
|
@ -66,7 +66,7 @@ def build_warning(warning, link):
|
||||||
embed.add_field(name="Importance", value=warning.importance_display)
|
embed.add_field(name="Importance", value=warning.importance_display)
|
||||||
embed.add_field(name="Message", value=warning.message)
|
embed.add_field(name="Message", value=warning.message)
|
||||||
embed.add_field(name="Link", value=link)
|
embed.add_field(name="Link", value=link)
|
||||||
return [embed.to_dict()]
|
return embed
|
||||||
|
|
||||||
|
|
||||||
def validate_username(username):
|
def validate_username(username):
|
||||||
|
|
51
views.py
51
views.py
|
@ -17,8 +17,9 @@ from minecraft_manager.forms import TicketNoteForm, NoteForm
|
||||||
from minecraft_manager.overview import overview_data
|
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
|
||||||
import subprocess
|
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):
|
||||||
|
@ -452,11 +453,6 @@ class Chat(View):
|
||||||
|
|
||||||
class Bots(View):
|
class Bots(View):
|
||||||
|
|
||||||
def assets(self):
|
|
||||||
path = os.path.abspath(os.path.dirname(__file__))
|
|
||||||
bot_dir = os.path.join(path, 'assets/bots')
|
|
||||||
return bot_dir
|
|
||||||
|
|
||||||
def get_bots(self):
|
def get_bots(self):
|
||||||
bot_dir = getattr(settings, 'BOT_DIR', None)
|
bot_dir = getattr(settings, 'BOT_DIR', None)
|
||||||
bots = []
|
bots = []
|
||||||
|
@ -466,41 +462,24 @@ class Bots(View):
|
||||||
ve = file.replace('.bot.py', '')
|
ve = file.replace('.bot.py', '')
|
||||||
py = os.path.join(bot_dir, ve, 'bin/python')
|
py = os.path.join(bot_dir, ve, 'bin/python')
|
||||||
if os.path.isfile(py):
|
if os.path.isfile(py):
|
||||||
bots.append({'name': file.replace('.bot.py', ''), 'asset': False, 'executable': py})
|
bots.append(Bot(file.replace('.bot.py', ''), False, py))
|
||||||
else:
|
else:
|
||||||
bots.append({'name': file.replace('.bot.py', ''), 'asset': False, 'executable': sys.executable})
|
bots.append(Bot(file.replace('.bot.py', ''), False, sys.executable))
|
||||||
# Also get packaged MCM bots
|
# Also get packaged MCM bots
|
||||||
for file in os.listdir(self.assets()):
|
bots.append(Bot("Discord-MCM", True, None, discord_start, discord_stop, discord_restart, discord_status, discord_display))
|
||||||
if file.endswith('.bot.py'):
|
|
||||||
bots.append({'name': file.replace('.bot.py', ''), 'asset': True, 'executable': sys.executable})
|
|
||||||
return bots
|
return bots
|
||||||
|
|
||||||
def get_form(self):
|
|
||||||
bots = self.get_bots()
|
|
||||||
plugin_port = getattr(settings, 'PLUGIN_PORT', None)
|
|
||||||
screens = subprocess.getoutput("screen -ls")
|
|
||||||
form = {'screens': screens, 'bots': bots}
|
|
||||||
for bot in bots:
|
|
||||||
form[bot['name']] = True if "{0}_{1}".format(plugin_port, bot['name']) in screens else False
|
|
||||||
return form
|
|
||||||
|
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
return render(request, 'minecraft_manager/bots.html', {'current_app': 'bots', 'form': self.get_form()})
|
return render(request, 'minecraft_manager/bots.html', {'current_app': 'bots', 'bots': self.get_bots()})
|
||||||
|
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
post = request.POST
|
post = request.POST
|
||||||
plugin_port = getattr(settings, 'PLUGIN_PORT', None)
|
|
||||||
for bot in self.get_bots():
|
for bot in self.get_bots():
|
||||||
if bot['name'] in post:
|
if bot.name in post:
|
||||||
if post[bot['name']] == "stop":
|
if post[bot.name] == "stop":
|
||||||
subprocess.run('screen -X -S "{0}_{1}" quit'.format(plugin_port, bot['name']), shell=True)
|
bot.stop()
|
||||||
elif post[bot['name']] in ('start', 'restart'):
|
elif post[bot.name] == "start":
|
||||||
subprocess.run('screen -X -S "{0}_{1}" quit'.format(plugin_port, bot['name']), shell=True)
|
bot.start()
|
||||||
path = self.assets() if bot['asset'] else getattr(settings, 'BOT_DIR', "")
|
elif post[bot.name] == "restart":
|
||||||
if not path.endswith("/"):
|
bot.restart()
|
||||||
path += "/"
|
return render(request, 'minecraft_manager/bots.html', {'current_app': 'bots', 'bots': self.get_bots()})
|
||||||
print('screen -S {0}_{1} -d -m {2} {3}{1}.bot.py'.format(plugin_port, bot['name'], bot['executable'], path))
|
|
||||||
subprocess.run(
|
|
||||||
'screen -S {0}_{1} -d -m {2} {3}{1}.bot.py'.format(plugin_port, bot['name'], bot['executable'], path),
|
|
||||||
shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
||||||
return render(request, 'minecraft_manager/bots.html', {'current_app': 'bots', 'form': self.get_form()})
|
|
||||||
|
|
Loading…
Reference in New Issue