Internalize Discord Bot (#31)

reminder
Etzelia 2019-08-30 20:03:12 +02:00 committed by Gitea
parent 8073765a57
commit c813535489
11 changed files with 184 additions and 169 deletions

View File

@ -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

View File

@ -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."

View File

@ -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()

View File

@ -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
;

View File

@ -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"

View File

@ -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())

View File

@ -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

4
external/views.py vendored
View File

@ -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:

View File

@ -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 %}

View File

@ -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):

View File

@ -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()})