[Python] I want to manage 7DaysToDie from Discord! 2/3

Overview

[Python] I want to manage 7DaysToDie from Discord! 1/3 (Environment construction) [Python] I want to manage 7DaysToDie from Discord! 2/3 (Creating a BOT that can be managed from Discord) [Python] I want to manage 7DaysToDie from Discord! 3/3 (operation check)

Creating a BOT that can be managed from Discord

Following Last time, this time we will create a program that can be managed from the main Discord.

Creating sdtd_run.py

$ cd
$ mkdir -p $HOME/python/discord/Sdtd
$ cd $HOME/python/discord/
$ vim sdtd_run.py

** Next, sdtd_run.py has two points to check. ** **

sdtd_run.py


#!/bin/env python
import discord
import threading
import os
import re
import time
import subprocess as prc
from Sdtd import command

API = "Please enter the Discord API here."
ADMIN = "Enter the name of the Discord server administrator here. Example:Dream"
#SubADMIN ="Adjutant's name if necessary"

client = discord.Client()
@client.event
async def on_message(message):
    #Specify the server administrator. If you have an adjutant, please connect with or as follows.
    #if message.author.name == (ADMIN) or message.author.name == ("SubADMIN"):
    if message.author.name == (ADMIN):
        cmd = command.SDTD()
        if message.content.startswith('/help'):
            cmdhelp = cmd.command_help()
            await message.channel.send(cmdhelp)

        elif message.content.startswith('/member'):
            await message.channel.send(cmd.player_joined_check())

        elif message.content.startswith('/server-start'):
            timemsg = time.strftime("%Y/%m/%d %H:%M:%S ", time.strptime(time.ctime()))
            await message.channel.send(timemsg + "---Start the server.(It may take up to 5 minutes to start.)")
            thread = threading.Thread(target=cmd.start)
            thread.start()

        elif message.content.startswith('/server-stop'):
            timemsg = time.strftime("%Y/%m/%d %H:%M:%S ", time.strptime(time.ctime()))
            await message.channel.send(timemsg + "---Stop the server.")
            thread = threading.Thread(target=cmd.stop)
            thread.start()

        elif message.content.startswith('/server-restart'):
            timemsg = time.strftime("%Y/%m/%d %H:%M:%S ", time.strptime(time.ctime()))
            await message.channel.send(timemsg + "---Reboot the server.")
            thread = threading.Thread(target=cmd.stop)
            thread.start()
            time.sleep(15)
            timemsg = time.strftime("%Y/%m/%d %H:%M:%S ", time.strptime(time.ctime()))
            await message.channel.send(timemsg + "---Start the server.(It may take up to 5 minutes to start.)")
            thread = threading.Thread(target=cmd.start)
            thread.start()

        elif message.content.startswith('/server-status'):
            timemsg = time.strftime("%Y/%m/%d %H:%M:%S ", time.strptime(time.ctime()))
            await message.channel.send(timemsg + "---Shows the status of the server.")
            await message.channel.send(cmd.status())

client.run(API)

Then create command.py.

$ cd Sdtd
$ vim command.py

** Next, command.py has three points to check. ** **

--filling out the webhooks API --Check the location of the game directory. (If it's vanilla, it's OK by default) --Check the location of the screen (probably OK by default)

command.py


#!/bin/env python
import os
import re
import sys
import requests
import subprocess as prc
import time
import glob as g
from telnetlib import Telnet

class SDTD(object):

    def __init__(self):
        #Fill in the Discord Webhooks API.
        self.discord = "Discord_Webhooks_API"
        #Check the screen generation directory.
        self.screendir = "/var/run/screen/S-" + os.environ['USER']
        #This time/Since it is created with sdtd, set it below. Change timely when using mod mackerel.
        self.gamedir = os.environ['HOME'] + "/steamcmd/sdtd"

    def port_check(self):
        p1 = prc.Popen(["lsof"], stdout=prc.PIPE)
        p2 = prc.Popen(["grep", "7Days"], stdin=p1.stdout, stdout=prc.PIPE)
        p3 = prc.Popen(["grep","-E","TCP..:"], stdin=p2.stdout, stdout=prc.PIPE)
        p4 = prc.Popen(["awk", "-F:", "NR==1 {print $2}"], stdin=p3.stdout, stdout=prc.PIPE)
        p5 = prc.Popen(["awk", "{print $1}"], stdin=p4.stdout, stdout=prc.PIPE)
        p1.stdout.close()
        p2.stdout.close()
        p3.stdout.close()
        p4.stdout.close()
        output = p5.communicate()[0].decode('utf-8')
        return output[:-1]

    def proc_check(self):
        p1 = prc.Popen(['ps', 'x'], stdout=prc.PIPE)
        p2 = prc.Popen(["grep", "-v","grep"], stdin=p1.stdout, stdout=prc.PIPE)
        p3 = prc.Popen(["grep", "7DaysToDieServer.x86_64"], stdin=p2.stdout, stdout=prc.PIPE)
        p4 = prc.Popen(["awk","{print $1}"], stdin=p3.stdout,stdout=prc.PIPE)
        p1.stdout.close()
        p2.stdout.close()
        p3.stdout.close()
        output = p4.communicate()[0].decode('utf-8')
        return output[:-1]

    def screen_check(self):
        p1 = prc.Popen(['ps', 'x'], stdout=prc.PIPE)
        p2 = prc.Popen(["grep", "-v","grep"], stdin=p1.stdout, stdout=prc.PIPE)
        p3 = prc.Popen(["grep", "SCREEN"], stdin=p2.stdout, stdout=prc.PIPE)
        p4 = prc.Popen(["awk","{print $1}"], stdin=p3.stdout, stdout=prc.PIPE)
        p1.stdout.close()
        p2.stdout.close()
        p3.stdout.close()
        output = p4.communicate()[0].decode('utf-8')
        return output[:-1]

    def command_help(self):
        lists = (
 "` `/ help Show this content. \ N"
 "/ server-stop 7Days to Die Stop the server. \ N"
 "/ server-start 7Days to Die Start the server. \ N"
 "/ server-restart 7Days to Die Restart the server. \ N"
 "/ server-status 7Days to Die Shows server status. \ N"
        "/member Check the currently connected user.\n```"
        )
        return lists

    def server_status(self):
        init = 0
        port = self.port_check()
        if port != "":
            port_status_msg = "port[" + port + "]Is released at."
            init += 1
        else:
            port_status_msg = "The port has not been released."
            init -= 1

        process = self.proc_check()
        if process != "":
            proc_status_msg = "GAME PID [" + process[:-1] + "]It is operating in."
            init += 1
        else:
            proc_status_msg = "The process is not running."
            init -= 1

        screen = self.screen_check()
        if screen != "":
            screen_status_msg = "SCREEN PID [" + screen[:-1] + "]It is operating in."
            init += 1
        else:
            screen_status_msg = "The screen is not working."
            init -= 1

        message = port_status_msg + "\n" + proc_status_msg + "\n" + screen_status_msg + "\n"

        return message,init

    def status(self):
        message = self.server_status()[0]
        return message

    def player_joined_check(self):
        status = self.server_status()[1]
        sts_msg = self.server_status()[0]
        if status <= 0:
            msg = "The server has not started normally.\n" + sts_msg
            return msg
        login_status = []
        member = ""
        with Telnet('localhost',8081) as tn:
            tn.write(b'lp\n')
            time.sleep(1)
            tn.write(b'exit\n')
            login_mem = tn.read_all().decode().split("\n")[16:-1]

            for i in range(len(login_mem)):
                login_status += [login_mem[i].replace('\r','\n')]
                member += login_status[i]

        return member[:-1]

    def start_check(self):
        for i in range(420):
            status = self.server_status()[1]
            if status == 3:
                timemsg = time.strftime("%Y/%m/%d %H:%M:%S ", time.strptime(time.ctime()))
                payload = {
                    "content" : timemsg + "---The server startup is complete."
                }
                requests.post(self.discord, data=payload)
                sys.exit()

            time.sleep(1)

        else:
            status = self.server_status()[0]
            timemsg = time.strftime("%Y/%m/%d %H:%M:%S ", time.strptime(time.ctime()))
            payload = {
                "content" : timemsg + "---Failed to start the server. Please check the situation.\n" + status
            }
            requests.post(self.discord, data=payload)
            sys.exit()

    def stop_check(self):
        for i in range(30):
            status = self.server_status()[1]
            if status == -3:
                timemsg = time.strftime("%Y/%m/%d %H:%M:%S ", time.strptime(time.ctime()))
                payload = {
                    "content" : timemsg + "---The server stop is complete."
                }
                requests.post(self.discord, data=payload)
                sys.exit()

            time.sleep(1)

        else:
            status = self.server_status()[0]
            timemsg = time.strftime("%Y/%m/%d %H:%M:%S ", time.strptime(time.ctime()))
            payload = {
                "content" : timemsg + "---Failed to stop the server. Please check the situation.\n" + status
            }
            requests.post(self.discord, data=payload)
            sys.exit()

    def start(self):
        status = self.server_status()[1]
        if status == 3:
            timemsg = time.strftime("%Y/%m/%d %H:%M:%S ", time.strptime(time.ctime()))
            payload = {
                "content" : timemsg + "---The server is already up."
            }
            requests.post(self.discord, data=payload)
            sys.exit()

        os.chdir(self.gamedir)
        com1 = prc.run(["screen", "-dmS", "sdtd"], stdout=prc.PIPE)
        time.sleep(2)
        com2 = prc.run(['screen','-S','sdtd','-p','0','-X','exec','/bin/bash','startserver.sh'], stdout=prc.PIPE)
        sys.stdout.buffer.write(com1.stdout)
        time.sleep(2)
        sys.stdout.buffer.write(com2.stdout)

        self.start_check()

    def stop(self):
        prc_chk = self.proc_check()
        scn_chk = self.screen_check()
        status = self.server_status()[1]
        if status == 3:
            message = "say Stop the server after 10 seconds.\n\n".encode('utf-8')
            with Telnet('localhost',8081) as tn:
                tn.write(message)
                time.sleep(10)
                tn.write(b'shutdown\n')
                try:
                    tn.interact()
                except: pass

        if status == -3:
            timemsg = time.strftime("%Y/%m/%d %H:%M:%S ", time.strptime(time.ctime()))
            payload = {
                "content" : timemsg + "---The server is already stopped."
            }
            requests.post(self.discord, data=payload)
            sys.exit()

        if prc_chk != "":
            prc.Popen(['kill', '-9',prc_chk], stdout=prc.PIPE)

        if scn_chk != "":
            prc.Popen(['kill', '-9',scn_chk], stdout=prc.PIPE)
            os.chdir(self.screendir)
            for remove in g.glob("*"):
                os.remove(remove)

        self.stop_check()

** * About the following parts of port_check (either is OK) ** p3 = prc.Popen(["grep","-E","TCP..:"], stdin=p2.stdout, stdout=prc.PIPE) Originally p3 = prc.Popen (["grep "," TCP \ *: "], stdin = p2.stdout, stdout = prc.PIPE) However, when I posted it, the text color of Python was broken, so I have to change it.

Creating sdtd_start.sh

$ cd $HOME/python/discord
$ vim sdtd_start.sh

Contents of sdtd_start.sh

Next, write a shell script for startup.

sdtd_start.sh


#!/bin/sh
DIR=$(cd $(dirname $0); pwd)
PID=$(ps x |grep sdtd_run.py |grep -v grep |awk '{print $1}')

case "$1" in
  "start" )
        if [[ $PID == "" ]]; then
            env python $DIR/sdtd_run.py > /dev/null &
            sleep 3
            PID=$(ps x |grep sdtd_run.py |grep -v grep |awk '{print $1}')
            date +"%Y-%m-%d %H:%M:%S --- [$PID] start"
        else
            echo "pid already exists.[$PID]"
        fi
        ;;

  "restart" )
        if [[ $PID != "" ]]; then
                kill -9 $PID
                sleep 2
                date +"%Y-%m-%d %H:%M:%S --- [$PID] kill ok"
        fi
        env python $DIR/sdtd_run.py > /dev/null &
        sleep 3
        PID=$(ps x |grep sdtd_run.py |grep -v grep |awk '{print $1}')
        date +"%Y-%m-%d %H:%M:%S ---[$PID] start"
        ;;

  "stop" )
        if [[ $PID != "" ]]; then
                kill -9 $PID
                sleep 2
                date +"%Y-%m-%d %H:%M:%S --- [$PID] kill ok"
        else
                echo "pid does not exist."
        fi
        ;;

  "status" )
        if [[ $PID != "" ]]; then
                echo "running PID:"$PID
        else
                echo "not running."
        fi
        ;;

  * )
        if [[ $PID != "" ]]; then
            kill -9 $PID
            sleep 2
            date +"%Y-%m-%d %H:%M:%S --- [$PID] kill ok"
        fi
        env python $DIR/sdtd_run.py > /dev/null &
        sleep 3
        PID=$(ps x |grep sdtd_run.py |grep -v grep |awk '{print $1}')
        date +"%Y-%m-%d %H:%M:%S --- [$PID] start"
esac

Permission change of sdtd_start.sh

$ chmod +x sdtd_start.sh

Thank you for your hard work. Let's check it by executing Last.

Recommended Posts

[Python] I want to manage 7DaysToDie from Discord! 1/3
[Python] I want to manage 7DaysToDie from Discord! 2/3
I want to use jar from python
I want to email from Gmail using Python.
I want to make C ++ code from Python code!
[Python3] I want to generate harassment names from Japanese!
I want to debug with Python
I want to start a lot of processes from python
I want to send a message from Python to LINE Bot
I want to build a Python environment
I want to analyze logs with Python
I want to play with aws with python
I want to connect to PostgreSQL from various languages
I want to do Dunnett's test in Python
I want to use MATLAB feval with python
Changes from Python 3.0 to Python 3.5
Changes from Python 2 to Python 3.0
I want to create a window in Python
I want to perform SageMaker inference from PHP
I want to make a game with Python
[Python memo] I want to get a 2-digit hexadecimal number from a decimal number
I want to merge nested dicts in Python
I want to make fits from my head
I want to manage systemd by time zone! !!
I want to use Temporary Directory with Python2
#Unresolved I want to compile gobject-introspection with Python3
I want to solve APG4b with Python (Chapter 2)
I want to sell Mercari by scraping python
I want to write to a file with Python
I want to display the progress in Python!
I want to get / execute variables / functions / classes of external files from Python
I want to write in Python! (1) Code format check
I want to see the file name from DataLoader
Even beginners want to say "I fully understand Python"
I want to embed a variable in a Python string
I want to easily implement a timeout in python
I want to detect images of cats from Instagram
I want to iterate a Python generator many times
I want to generate a UUID quickly (memorandum) ~ Python ~
I want to handle optimization with python and cplex
[Python] I want to merge Excel files anyway (pandas.merge)
I want to write in Python! (2) Let's write a test
Even in JavaScript, I want to see Python `range ()`!
I want to randomly sample a file in Python
I want to inherit to the back with python dataclass
I want to work with a robot in python.
I want to write in Python! (3) Utilize the mock
I want to AWS Lambda with Python on Mac!
[ML Ops] I want to do multi-project with Python
I want to use the R dataset in python
I want to run a quantum computer with Python
I want to do something in Python when I finish
I want to manipulate strings in Kotlin like Python!
Post from Python to Slack
Cheating from PHP to Python
I want to solve Sudoku (Sudoku)
Switch from python2.7 to python3.6 (centos7)
Connect to sqlite from python
[Python] I made a system to introduce "recipes I really want" from the recipe site!
I want to tell people who want to import from a higher directory with Python direnv
I want to be able to analyze data with Python (Part 3)