Skip to content

Instantly share code, notes, and snippets.

@ILiedAboutCake
Created February 1, 2017 00:25
Show Gist options
  • Save ILiedAboutCake/a952c1eb830a1633e55e3bf2c13d6ed2 to your computer and use it in GitHub Desktop.
Save ILiedAboutCake/a952c1eb830a1633e55e3bf2c13d6ed2 to your computer and use it in GitHub Desktop.
Minecraft Forge server watchdog with discord integration for informing users and dumping logs
from mcstatus import MinecraftServer #pip install mcstatus https://github.com/Dinnerbone/mcstatus
from subprocess import call
from datetime import datetime
import requests, time, os, glob, sys
discordWebhookPrivate = "https://ptb.discordapp.com/api/webhooks/" #private channel, should be for admins only
discordWebhookPublic = "https://ptb.discordapp.com/api/webhooks/" #public game channel
forgeInstance = "localhost:25565" #forge instance name:port
forgeDirectory = "/minecraft/forge/" #forge folder
LASTCRASH = None
class colors(object): #you can customize colors for webhooks, or not thats fine too.
red = "#990000"
yellow = "#ffff00"
green = "#006400"
def webhook(endpoint, text, color, title, value): #we slack because lazy
value = value.replace(":", " port ")
hook = '{"username": "","icon_url": "","text": "' + text + '","attachments": [{"author_icon": "","author_name": "","color": "' + color + '","fields": [{"title": "' + title + '","value": "' + value + '"}]}]}'
r = requests.post(endpoint + "/slack", timeout=0.5, data=hook)
def serverFailure(): #called on a non-respoding server
global LASTCRASH
print "SERVER FAILURE"
newestCrash = max(glob.iglob(forgeDirectory + 'crash-reports/*.txt'), key=os.path.getctime) #gets latest crashlog
if newestCrash == LASTCRASH:
webhook(discordWebhookPublic, "Server Offline!", colors.yellow, "Forge server went offline in the last 30 seconds", forgeInstance + " considered offline. Attempting restart script.")
else:
webhook(discordWebhookPublic, "Server Crashed!", colors.yellow, "Forge server crashed sometime within the last 30 seconds", forgeInstance + " considered offline. Attempting restart script and dumping crashlogs to admins.")
webhook(discordWebhookPrivate, "Server Crashed!", colors.yellow, "Forge server crashed sometime within the last 30 seconds", forgeInstance + " considered offline. Attempting " + forgeDirectory + "/restartscript.sh")
crashLog = {'file': open(newestCrash, 'rb')} # https://discordapp.com/developers/docs/resources/webhook#execute-webhook
requests.post(discordWebhookPrivate, timeout=0.5, files=crashLog) #sends crashlog to Discord
call(["/bin/bash", forgeDirectory + "restartscript.sh"]) #restarts prod, runs startup script
time.sleep(30) #wait 30 seconds for server to start to get status
server = MinecraftServer.lookup(forgeInstance)
try: #super hacky way of checking if its online or not
status = server.status()
except:
status = False
if status is False:
webhook(discordWebhookPublic, "Server FAILURE!", colors.red, "Forge server did not respond in time.", forgeInstance + " is in a failed state. killing myself and waiting for admin intervention :(")
webhook(discordWebhookPrivate, "Server FAILURE!", colors.red, "Forge server did not respond in time.", forgeInstance + " is in a failed state. @ILiedAboutCake#2213")
time.sleep(1) #wait 1 second
sys.exit(0) #kill yourself, shoutout to RTBA
else:
webhook(discordWebhookPublic, "Server Restarted!", colors.green, "Forge server restarted and accepting connections.", 'Restart worked! Server latency: ' + str(status.latency) + 'ms')
while True:
server = MinecraftServer.lookup(forgeInstance)
try:
status = server.status()
except:
status = "fucked"
if status is "fucked":
serverFailure()
else:
print "SERVER IS FINE MOVE ALONG"
time.sleep(30)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment