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 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__)
|
||||
|
||||
|
@ -37,36 +38,24 @@ def plugin(key, command):
|
|||
return False
|
||||
|
||||
|
||||
def discord_mcm(message='', embeds=None, ping=False):
|
||||
discord_mcm_webhook = getattr(settings, 'DISCORD_MCM_WEBHOOK', None)
|
||||
if discord_mcm_webhook:
|
||||
def discord_mcm(message='', embed=None, ping=False):
|
||||
channel_id = getattr(settings, 'DISCORD_MCM_CHANNEL', None)
|
||||
if channel_id:
|
||||
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)
|
||||
data = {}
|
||||
if message:
|
||||
data['content'] = message
|
||||
if embeds:
|
||||
data['embeds'] = embeds
|
||||
return requests.post(discord_mcm_webhook, json=data)
|
||||
return None
|
||||
discord_send(DestType.CHANNEL, channel_id, message, embed)
|
||||
|
||||
|
||||
def discord_notification(message='', embeds=None, ping=False):
|
||||
discord_notification_webhook = getattr(settings, 'DISCORD_NOTIFICATION_WEBHOOK', None)
|
||||
if discord_notification_webhook:
|
||||
def discord_notification(message='', embed=None, ping=False):
|
||||
channel_id = getattr(settings, 'DISCORD_NOTIFICATION_CHANNEL', None)
|
||||
if channel_id:
|
||||
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)
|
||||
data = {}
|
||||
if message:
|
||||
data['content'] = message
|
||||
if embeds:
|
||||
data['embeds'] = embeds
|
||||
return requests.post(discord_notification_webhook, json=data)
|
||||
return None
|
||||
discord_send(DestType.CHANNEL, channel_id, message, embed)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -192,7 +192,7 @@ class PluginAPI(View):
|
|||
json['message'] = "{0}'s application was submitted.".format(application.username)
|
||||
json['extra'] = application.id
|
||||
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:
|
||||
if Application.objects.filter(id=post['application_id']).exists():
|
||||
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))
|
||||
msg = mcm_utils.build_ticket(ticket, 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:
|
||||
json['status'] = False
|
||||
json['message'] = "Error while submitting ticket."
|
||||
|
@ -311,7 +311,7 @@ class PluginAPI(View):
|
|||
json['message'] = "Warning issued."
|
||||
link = "{}".format(mcm_utils.url_path(settings.MCM_BASE_LINK, 'dashboard/note', warning.id))
|
||||
msg = mcm_utils.build_warning(warning, link)
|
||||
mcm_api.discord_mcm(embeds=msg)
|
||||
mcm_api.discord_mcm(embed=msg)
|
||||
except Exception as ex:
|
||||
json['status'] = False
|
||||
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 logging
|
||||
import sys
|
||||
import traceback
|
||||
import threading
|
||||
from enum import Enum
|
||||
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
from django.conf import settings
|
||||
|
||||
from minecraft_manager.bot.commands import Commands
|
||||
|
||||
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', '!')
|
||||
|
@ -23,12 +40,14 @@ class Discord(commands.Bot):
|
|||
superuser_roles = getattr(settings, 'DISCORD_SUPERUSER_ROLES', [])
|
||||
error_users = getattr(settings, 'DISCORD_ERROR_USERS', [])
|
||||
|
||||
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))
|
||||
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)
|
||||
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)
|
||||
|
@ -38,6 +57,10 @@ class Discord(commands.Bot):
|
|||
print('------')
|
||||
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):
|
||||
if isinstance(message, discord.Embed):
|
||||
for idx, field in enumerate(message.fields):
|
||||
|
@ -61,15 +84,77 @@ class Discord(commands.Bot):
|
|||
await self.discord_message(user, '```python\n{}```'.format(error))
|
||||
|
||||
def run_bot(self):
|
||||
loop = asyncio.get_event_loop()
|
||||
|
||||
global discord_loop
|
||||
try:
|
||||
loop.run_until_complete(self.start(self.token))
|
||||
discord_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...")
|
||||
|
||||
|
||||
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.
|
||||
|
||||
``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_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.
|
||||
|
||||
|
@ -51,14 +61,6 @@ Optional
|
|||
|
||||
``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
|
||||
|
||||
``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:
|
||||
app = form.save()
|
||||
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))
|
||||
else:
|
||||
for error in captcha.errors:
|
||||
|
@ -109,7 +109,7 @@ class Ticket(View):
|
|||
# Create the message to send to Discord
|
||||
link = "{}".format(mcm_utils.url_path(settings.MCM_BASE_LINK, 'dashboard/ticket', ticket.id))
|
||||
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))
|
||||
else:
|
||||
for error in captcha.errors:
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
{% extends "minecraft_manager/dashboard.html" %}
|
||||
{% load csrf_html %}
|
||||
{% load getattribute %}
|
||||
{% block title %}Bots{% endblock %}
|
||||
{% block section %}
|
||||
<div id="content">
|
||||
<!-- {{ form.status }} -->
|
||||
{% for bot in form.bots %}
|
||||
<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>
|
||||
{% for bot in bots %}
|
||||
<p>{{ bot.name }}: <span class="label {% if bot.status is True %}label-success{% else %}label-danger{% endif %}">{{ bot.display }}</span></p>
|
||||
<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 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 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 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 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 bot.status is False %} disabled{% endif %}" type="submit" name="{{ bot.name }}" value="restart" {% if bot.status is False %}disabled="disabled"{% endif %}>Restart</button>
|
||||
</form>
|
||||
<br/>
|
||||
{% 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="Date", value=application.date_display)
|
||||
embed.add_field(name="Status", value=application.status)
|
||||
return [embed.to_dict()]
|
||||
return embed
|
||||
|
||||
|
||||
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="Message", value=ticket.message)
|
||||
embed.add_field(name="Link", value=link)
|
||||
return [embed.to_dict()]
|
||||
return embed
|
||||
|
||||
|
||||
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="Message", value=warning.message)
|
||||
embed.add_field(name="Link", value=link)
|
||||
return [embed.to_dict()]
|
||||
return embed
|
||||
|
||||
|
||||
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.utils import resolve_player
|
||||
import minecraft_manager.api.api as API
|
||||
|
||||
import subprocess
|
||||
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):
|
||||
|
@ -452,11 +453,6 @@ class Chat(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):
|
||||
bot_dir = getattr(settings, 'BOT_DIR', None)
|
||||
bots = []
|
||||
|
@ -466,41 +462,24 @@ class Bots(View):
|
|||
ve = file.replace('.bot.py', '')
|
||||
py = os.path.join(bot_dir, ve, 'bin/python')
|
||||
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:
|
||||
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
|
||||
for file in os.listdir(self.assets()):
|
||||
if file.endswith('.bot.py'):
|
||||
bots.append({'name': file.replace('.bot.py', ''), 'asset': True, 'executable': sys.executable})
|
||||
bots.append(Bot("Discord-MCM", True, None, discord_start, discord_stop, discord_restart, discord_status, discord_display))
|
||||
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):
|
||||
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):
|
||||
post = request.POST
|
||||
plugin_port = getattr(settings, 'PLUGIN_PORT', None)
|
||||
for bot in self.get_bots():
|
||||
if bot['name'] in post:
|
||||
if post[bot['name']] == "stop":
|
||||
subprocess.run('screen -X -S "{0}_{1}" quit'.format(plugin_port, bot['name']), shell=True)
|
||||
elif post[bot['name']] in ('start', 'restart'):
|
||||
subprocess.run('screen -X -S "{0}_{1}" quit'.format(plugin_port, bot['name']), shell=True)
|
||||
path = self.assets() if bot['asset'] else getattr(settings, 'BOT_DIR', "")
|
||||
if not path.endswith("/"):
|
||||
path += "/"
|
||||
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()})
|
||||
if bot.name in post:
|
||||
if post[bot.name] == "stop":
|
||||
bot.stop()
|
||||
elif post[bot.name] == "start":
|
||||
bot.start()
|
||||
elif post[bot.name] == "restart":
|
||||
bot.restart()
|
||||
return render(request, 'minecraft_manager/bots.html', {'current_app': 'bots', 'bots': self.get_bots()})
|
||||
|
|
Loading…
Reference in New Issue