2024/04/06 更新
ログ取得ロジックを変更
Minecraftサーバーのログイン通知をwebhookで送る方法
Minecraftサーバーのlosgsフォルダ内のlatest.logにログイン情報などが記載される。
そのため、logsフォルダのlatest.logファイルが更新されたタイミングでファイルの中身を送信すれば、ログイン通知になるはずである。
今回は例としてdiscordのwebhookを使用するが、Slackなどでも同じ事が出来るので、
使用する場合は下記のソースの一部を書き換えて欲しい
なぜPythonなのか
多くのマイクラサーバはWindowsもしくはLinuxで運用されていると思う。
その中でLinuxで一番使われているubuntuはデフォルトでPythonがインストールされている為、採用した。
そしてPythonのフォルダ監視ライブラリであるwatchdog使用して簡易的なログイン通知システムを作成した。
動作環境
Python 3.11.0
watchdog 4.0.0
ソース
main.py
import os
import re
import time
import requests
from watchdog.events import FileSystemEventHandler
from watchdog.observers.polling import PollingObserver
from config.app import TARGET_DIR, TARGET_FILE, WEBHOOK_URL
from utils.log_message_parser import message_creation
class MinecraftLogMonitor:
def __init__(self, target_dir, target_file, webhook_url):
self.target_dir = target_dir
self.target_file = target_file
self.webhook_url = webhook_url
self.log_position = 0
def send_message(self, message: str) -> None:
main_content = {"content": message}
response = requests.post(self.webhook_url, json=main_content)
response.raise_for_status()
def get_log(self, filepath: str):
with open(filepath, "r", errors="ignore") as f:
f.seek(self.log_position)
logs = f.readlines()
self.log_position = f.tell()
for log in logs:
text = message_creation(log)
if text:
self.send_message(text)
class ChangeHandler(FileSystemEventHandler):
def __init__(self, monitor: MinecraftLogMonitor):
self.monitor = monitor
def on_modified(self, event):
filepath = event.src_path
if (
os.path.isfile(filepath)
and os.path.basename(filepath) == self.monitor.target_file
):
self.monitor.get_log(filepath)
if __name__ == "__main__":
monitor = MinecraftLogMonitor(TARGET_DIR, TARGET_FILE, WEBHOOK_URL)
event_handler = ChangeHandler(monitor)
observer = PollingObserver()
observer.schedule(event_handler, monitor.target_dir, recursive=True)
observer.start()
try:
while True:
time.sleep(0.1)
except KeyboardInterrupt:
observer.stop()
observer.join()
utils/log_message_parser.py
import re
MESSAGE_PATTERNS = [
(": (.*) joined the game", "{0} が参加しました"),
(": (.*) left the game", "{0} が退出しました"),
# イベントを追加したい場合はここに追加する
]
def message_creation(text: str):
for pattern, message_format in MESSAGE_PATTERNS:
match = re.search(pattern, text)
if match:
return message_format.format(*match.groups())
return None
config/__init__.py
from dotenv import load_dotenv
load_dotenv()
config/app.py
import os
WEBHOOK_URL = os.getenv("WEBHOOK_URL")
TARGET_DIR = os.getenv("TARGET_DIR")
TARGET_FILE = os.getenv("TARGET_FILE")
.env
WEBHOOK_URL=discordのwebhookのURL
TARGET_DIR=監視対象のフォルダ
TARGET_FILE=latest.log
__init__.pyを使ってload_dotenv()を使うのは綺麗なのでかなり気に入っている
Githubにもソースをおいています。
https://github.com/somakai-sumasi/Send-Minecraft-notifications