できた https://youtu.be/x85oTw5-ZGg

仕組み

  • ボタンを押すとコマンドブロックがwebhooks execute post-like xを実行(x部分は任意の名前)
  • SimpleWebhookshttp://localhost:5000/に名前をPOST
  • localhostで動いてるFlaskがリクエストを受け取ってRCONでコマンド実行
    • command = f"data get storage likes {name}"
      • storageからいいねの数を取得
      • 1増やす
    • command = f"data modify storage likes {name} set value {value}"
      • 増やした値をstorageに書き込む
    • command = f"hd setLine likes_{name} 1 LIKE: {value}"

SimpleWebhooks/config.yaml

post-like:
  url: http://localhost:5000/
  json:
    name: "{COMMAND_PARAM_1}"

server.py

from flask import Flask, request
from aiomcrcon import Client
import asyncio
import re
import threading
from secret import PASSWORD, HOST, PORT

app = Flask(__name__)
client = Client(HOST, PORT, PASSWORD)


def create_app():
    return app


async def update_likes(name):
    await client.connect()

    command = f"data get storage likes {name}"
    response = await client.send_cmd(command)
    if "Found no elements matching" in response[0]:
        value = 0
    else:
        value = int(re.search("\d+", response[0]).group())

    value += 1
    command = f"data modify storage likes {name} set value {value}"
    response = await client.send_cmd(command)

    command = f"hd setLine likes_{name} 1 LIKE: {value}"
    response = await client.send_cmd(command)
    
    await client.close()


@app.route('/', methods=['GET', 'POST'])
def root():
    if request.method == "GET":
        return "OK"
    else:
        name = request.json["name"]

    x = threading.Thread(target=lambda: asyncio.run(update_likes(name)), args=()).start()
    return "OK"

ハマりどころ

  • Webhookに対してRCONを実行する前にOKを返す必要がある
    • RCONパケットを送っても実行されずタイムアウトする
    • おそらくWebhookコマンドがロックをつかんでいる
    • そこでスレッドを作る形にした

元ネタ