Ready for backend hook
Client-side script 'start.py' is now ready for a backend hook. The only thing remaining to do on the client-side is to add the actual initializer of labylib. Added support for "us.mineplex.com" in 'servers.json'
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
.cache.png
|
BIN
backend/background.png
Normal file
After Width: | Height: | Size: 713 B |
0
backend/render.php
Normal file
0
backend/servers.json
Normal file
BIN
backend/tags/us.mineplex.com/rank_admin.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
BIN
backend/tags/us.mineplex.com/rank_eternal.png
Normal file
After Width: | Height: | Size: 7.5 KiB |
BIN
backend/tags/us.mineplex.com/rank_hero.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
BIN
backend/tags/us.mineplex.com/rank_immortal.png
Normal file
After Width: | Height: | Size: 9.1 KiB |
BIN
backend/tags/us.mineplex.com/rank_leader.png
Normal file
After Width: | Height: | Size: 7.1 KiB |
BIN
backend/tags/us.mineplex.com/rank_legend.png
Normal file
After Width: | Height: | Size: 7.2 KiB |
BIN
backend/tags/us.mineplex.com/rank_mod.png
Normal file
After Width: | Height: | Size: 7 KiB |
BIN
backend/tags/us.mineplex.com/rank_owner.png
Normal file
After Width: | Height: | Size: 7.1 KiB |
BIN
backend/tags/us.mineplex.com/rank_srmod.png
Normal file
After Width: | Height: | Size: 7.5 KiB |
BIN
backend/tags/us.mineplex.com/rank_titan.png
Normal file
After Width: | Height: | Size: 6.5 KiB |
BIN
backend/tags/us.mineplex.com/rank_trainee.png
Normal file
After Width: | Height: | Size: 8.5 KiB |
BIN
backend/tags/us.mineplex.com/rank_ultra.png
Normal file
After Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 239 B |
40
servers.json
|
@ -1,5 +1,39 @@
|
|||
{
|
||||
"us.mineplex.net": [
|
||||
"/(?<=\\[CHAT\\])(.*)(?=ULTRA|HERO|LEGEND|TITAN|ETERNAL|IMMORTAL|TRAINEE|MOD)/g"
|
||||
]
|
||||
"us.mineplex.com": {
|
||||
"pattern": "([abcef0-9])\\w+ ",
|
||||
"lookup": {
|
||||
"start": 1,
|
||||
"ignore": [
|
||||
"MPS",
|
||||
"Host",
|
||||
"Co-Host",
|
||||
"el?"
|
||||
],
|
||||
"tag": [
|
||||
"ULTRA",
|
||||
"HERO",
|
||||
"LEGEND",
|
||||
"TITAN",
|
||||
"ETERNAL",
|
||||
"IMMORTAL",
|
||||
"YT",
|
||||
"STREAM",
|
||||
"YOUTUBE",
|
||||
"TRAINEE",
|
||||
"MOD",
|
||||
"SR.MOD",
|
||||
"ADMIN",
|
||||
"LEADER",
|
||||
"OWNER"
|
||||
]
|
||||
}
|
||||
},
|
||||
"vanilla": {
|
||||
"pattern": "\\<(?s)(.*)\\>",
|
||||
"lookup": {
|
||||
"start": 0,
|
||||
"ignore": [],
|
||||
"tag": []
|
||||
}
|
||||
}
|
||||
}
|
119
start.py
|
@ -2,13 +2,12 @@ from labylib import Cape
|
|||
from threading import Thread, Event
|
||||
from pathlib import Path
|
||||
|
||||
from PIL import Image
|
||||
from PIL import ImageFont
|
||||
from PIL import ImageDraw
|
||||
|
||||
import re
|
||||
import json
|
||||
import platform
|
||||
import getpass
|
||||
import subprocess
|
||||
import requests
|
||||
|
||||
# Chattycape daemon
|
||||
class Chattycape(Thread):
|
||||
|
@ -16,26 +15,91 @@ class Chattycape(Thread):
|
|||
pollRate = 1 # Logfile pollrate
|
||||
updateRate = 1 # Update rate of Labylib cosmetic
|
||||
|
||||
def __init__(self,event,phpsessid,logfile):
|
||||
def __init__(self,event,phpsessid,endpoint,logfile,me = "None"):
|
||||
Thread.__init__(self)
|
||||
self.stopped = event
|
||||
self.params = (phpsessid,endpoint,logfile,me) # Create tuple from params
|
||||
|
||||
self.phpsessid = phpsessid
|
||||
self.logfile = logfile
|
||||
|
||||
self.line = ""
|
||||
self.server = None # Connected to server (hostname)
|
||||
self.config = None # Chat config for current server
|
||||
|
||||
self.line = "[21:42:25] [main/INFO]: [CHAT] 725 IMMORTAL VicW test"
|
||||
self.i = 0
|
||||
|
||||
# Poll last line from logfile
|
||||
# Read last line from logfile
|
||||
def linefeed(self):
|
||||
self.line = subprocess.check_output(['tail','-1',self.logfile])
|
||||
# tail last line from logfile
|
||||
line = subprocess.check_output(['tail','-1',self.params[2]]).decode("utf-8","ignore")[:-2]
|
||||
|
||||
match = re.search(self.config["pattern"],line)
|
||||
|
||||
if match:
|
||||
self.line = line
|
||||
return
|
||||
|
||||
# Extract Minecraft username and tag from current line
|
||||
def getUser(self):
|
||||
line = self.line[31:].split() # Split current line. Offset (31) for log-prefixes
|
||||
|
||||
username = tag = "None"
|
||||
|
||||
start = self.config["lookup"]["start"] # List offset for iterator
|
||||
ignoreList = self.config["lookup"]["ignore"] # Jumps to next index if match
|
||||
tagList = self.config["lookup"]["tag"] # 'tag' set if match
|
||||
|
||||
for substr in line[start:]: # Start at offset
|
||||
if substr in ignoreList:
|
||||
continue
|
||||
|
||||
if substr in tagList:
|
||||
tag = substr
|
||||
continue
|
||||
|
||||
# Not ignored, and not a tag, so assume we've reached the username
|
||||
username = substr
|
||||
break
|
||||
|
||||
return (username,tag)
|
||||
|
||||
# Update labylib cosmetic
|
||||
def update(self):
|
||||
print(self.line)
|
||||
args = self.getUser() # Get minecraft username and tag
|
||||
|
||||
urlparams = f"?server={self.server}&ign={args[0]}&rank={args[1]}"
|
||||
|
||||
# Save cape texture from endpoint to disk
|
||||
with open(".cache.png","wb") as handle:
|
||||
fetch = requests.get(self.params[1] + urlparams,stream=True)
|
||||
|
||||
if not fetch.ok:
|
||||
print(fetch)
|
||||
|
||||
for block in fetch.iter_content(1024):
|
||||
if not block:
|
||||
break
|
||||
|
||||
handle.write(block)
|
||||
|
||||
# TODO: Labylib here
|
||||
|
||||
# ----------------------------
|
||||
|
||||
# Import RegEx patterns for current server
|
||||
def loadConfig(self):
|
||||
self.server = "us.mineplex.com"
|
||||
|
||||
with open("./servers.json") as config:
|
||||
data = json.load(config)
|
||||
|
||||
self.config = data[self.server]
|
||||
self.config["pattern"] = r"\[CHAT\]+ " + self.config["pattern"]
|
||||
|
||||
# Start the thread
|
||||
def run(self):
|
||||
print("\nRunning..")
|
||||
self.loadConfig()
|
||||
|
||||
# Start the chat 'listener'
|
||||
while not self.stopped.wait(Chattycape.pollRate):
|
||||
self.linefeed() # Poll logfile
|
||||
|
||||
|
@ -53,10 +117,28 @@ class Main:
|
|||
def __init__(self):
|
||||
print("-- Labylib Chattycape --")
|
||||
self.logfile = self.locate()
|
||||
self.phpsessid = input("\nhttps://github.com/VictorWesterlund/labylib#find-your-phpsessid-cookie\nPaste your PHPSESSID here:\n")
|
||||
|
||||
self.endpoint = self.prompt("Cape render endpoint","http://192.168.86.21/victor-westerlund/labylib-chattycape/back-end/render.php")
|
||||
self.me = self.prompt("My Minecraft in-game name (Case Sensitive)","Don't exclude me")
|
||||
self.phpsessid = self.prompt("PHPSESSID cookie")
|
||||
|
||||
self.start()
|
||||
|
||||
# Prompt user to enter information
|
||||
def prompt(self,message,default = "None"):
|
||||
# Add '[default]' flag if present
|
||||
if(default != "None"):
|
||||
message += f" [{default}]"
|
||||
message += ":"
|
||||
|
||||
value = default
|
||||
userinput = input(message + "\n")
|
||||
|
||||
if(userinput):
|
||||
value = userinput
|
||||
|
||||
return value
|
||||
|
||||
# Attempt to locate '.minecraft' automatically, otherwise prompt user
|
||||
def locate(self):
|
||||
sys = platform.system() # Get operating system
|
||||
|
@ -86,7 +168,7 @@ class Main:
|
|||
|
||||
# Failed to locate Minecraft-installation automatically
|
||||
|
||||
path = input("Please paste the path to your '.minecraft'-folder:\n")
|
||||
path = self.prompt("Path to your '.minecraft'-folder","/mnt/c/Users/victo/AppData/Roaming/.minecraft")
|
||||
|
||||
if(Path(path).exists()):
|
||||
return path + mclog
|
||||
|
@ -98,12 +180,11 @@ class Main:
|
|||
stop = Event()
|
||||
|
||||
# Start the daemon
|
||||
chattycape = Chattycape(stop,self.phpsessid,self.logfile)
|
||||
chattycape = Chattycape(stop,self.phpsessid,self.endpoint,self.logfile,self.me)
|
||||
chattycape.start()
|
||||
|
||||
interrupt = input("\nRunning! Press enter to stop\n")
|
||||
input("Press enter to stop the daemon")
|
||||
stop.set() # Stop the daemon
|
||||
print("Bye!")
|
||||
print("Stopped!")
|
||||
|
||||
main = Main()
|
||||
print(main.file)
|
||||
Main()
|