-
Notifications
You must be signed in to change notification settings - Fork 30
Expand file tree
/
Copy pathmcbe_log.py
More file actions
executable file
·109 lines (100 loc) · 3.52 KB
/
Copy pathmcbe_log.py
File metadata and controls
executable file
·109 lines (100 loc) · 3.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#!/usr/bin/env python3
"""
Post Minecraft Bedrock Edition server logs running in service to webhooks (Discord and
Rocket Chat).
"""
import argparse
import os
import pathlib
import re
import select
import signal
import subprocess
import sys
import requests
import systemd.journal
def send(msg: str):
"""
:param msg: Message to send to URLs in webhook files
"""
if DISCORD_FILE.is_file():
for url in DISCORD_FILE.read_text(encoding="utf-8").split(os.linesep)[:-1]:
try:
requests.post(
url,
json={"content": msg},
timeout=60,
)
except requests.exceptions.RequestException as err:
print(type(err), flush=True)
if ROCKET_FILE.is_file():
for url in ROCKET_FILE.read_text(encoding="utf-8").split(os.linesep)[:-1]:
try:
requests.post(
url,
json={"text": msg},
timeout=60,
)
except requests.exceptions.RequestException as err:
print(type(err), flush=True)
PARSER = argparse.ArgumentParser(
description=(
"Post Minecraft Bedrock Edition server logs running in service to webhooks "
+ "(Discord and Rocket Chat)."
),
epilog="Logs include server start/stop and player connect/disconnect/kick.",
)
PARSER.add_argument("SERVICE", type=str, help="systemd service")
ARGS = PARSER.parse_args()
SERVICE = ARGS.SERVICE
# Trim off SERVICE after last .service
if SERVICE.endswith(".service"):
SERVICE = SERVICE[: -len(".service")]
if subprocess.run(
["systemctl", "is-active", "-q", "--", SERVICE], check=False
).returncode:
sys.exit(f"Service {SERVICE} not active")
# Trim off SERVICE before last @
INSTANCE = SERVICE.split("@")[-1]
DISCORD_FILE = pathlib.Path(pathlib.Path.home(), ".mcbe_log", f"{INSTANCE}_discord.txt")
if DISCORD_FILE.is_file():
DISCORD_FILE.chmod(0o600)
ROCKET_FILE = pathlib.Path(pathlib.Path.home(), ".mcbe_log", f"{INSTANCE}_rocket.txt")
if ROCKET_FILE.is_file():
ROCKET_FILE.chmod(0o600)
send(f"Server {SERVICE} starting")
journal = systemd.journal.Reader()
journal.add_match(_SYSTEMD_UNIT=SERVICE + ".service")
journal.seek_tail()
journal.get_previous()
poll = select.poll()
poll.register(journal, journal.get_events())
signal.signal(signal.SIGTERM, lambda signalnum, currentframe: sys.exit())
try:
# Follow log for unit SERVICE
while poll.poll():
journal.process()
for entry in journal:
line = entry["MESSAGE"]
connect = re.search("Player connected: ([^,]+)", line)
if connect:
# Gamertags can have spaces if they're not leading/trailing/consecutive
player = connect.group(1)
send(f"{player} connected to {SERVICE}")
continue
disconnect = re.search("Player disconnected: ([^,]+)", line)
if disconnect:
player = disconnect.group(1)
send(f"{player} disconnected from {SERVICE}")
continue
kick = re.search("Kicked (.+) from the game: '(.*)'", line)
if kick:
player = kick.group(1)
reason = kick.group(2)
# Trim off leading space from reason
if reason.startswith(" "):
reason = reason[1:]
send(f"{player} was kicked from {SERVICE} because {reason}")
continue
finally:
send(f"Server {SERVICE} stopping")