2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonでマイクラ鯖のログイン通知をwebhookで行う

Last updated at Posted at 2023-05-09

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

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?