add docフォルダの追加
This commit is contained in:
BIN
doc/ExMenu1.png
Normal file
BIN
doc/ExMenu1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 140 KiB |
BIN
doc/ExMenu2.png
Normal file
BIN
doc/ExMenu2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 139 KiB |
BIN
doc/VRC_Log.png
Normal file
BIN
doc/VRC_Log.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 56 KiB |
@@ -73,10 +73,11 @@ param(
|
|||||||
[string]$Message
|
[string]$Message
|
||||||
)
|
)
|
||||||
|
|
||||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
$Payload = @{ content = $Message } | ConvertTo-Json -Compress
|
$Payload = @{ content = $Message } | ConvertTo-Json -Compress
|
||||||
$Body = [System.Text.Encoding]::UTF8.GetBytes($Payload)
|
$Body = [System.Text.Encoding]::UTF8.GetBytes($Payload)
|
||||||
Invoke-WebRequest -Uri $WebhookUrl -Method Post -ContentType 'application/json; charset=utf-8' -Body $Body -UseBasicParsing | Out-Null
|
$Response = Invoke-WebRequest -Uri $WebhookUrl -Method Post -ContentType 'application/json; charset=utf-8' -Body $Body -UseBasicParsing
|
||||||
|
Write-Output ("STATUS=" + $Response.StatusCode)
|
||||||
'''
|
'''
|
||||||
|
|
||||||
ps_path = None
|
ps_path = None
|
||||||
@@ -124,6 +125,9 @@ Invoke-WebRequest -Uri $WebhookUrl -Method Post -ContentType 'application/json;
|
|||||||
log("ERROR", f"Discord webhook PowerShell failed code={result.returncode} stderr={stderr} stdout={stdout}")
|
log("ERROR", f"Discord webhook PowerShell failed code={result.returncode} stderr={stderr} stdout={stdout}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
stdout = (result.stdout or "").strip()
|
||||||
|
if stdout:
|
||||||
|
log("INFO", f"Discord webhook PowerShell stdout={stdout}")
|
||||||
log("INFO", "Discord webhook sent via PowerShell")
|
log("INFO", "Discord webhook sent via PowerShell")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -274,6 +278,17 @@ def appendNoticeIfNeeded(output_lines, state):
|
|||||||
state["last_notice_key"] = notice_key
|
state["last_notice_key"] = notice_key
|
||||||
|
|
||||||
|
|
||||||
|
def debug(message):
|
||||||
|
log("DEBUG", message)
|
||||||
|
|
||||||
|
|
||||||
|
def formatJoinLeaveLine(line_time, action, name, state, guest_names):
|
||||||
|
staff_count = len(state["staff_present_set"])
|
||||||
|
member_count = len(state["member_present_set"])
|
||||||
|
guest_count = len(state["guest_names"])
|
||||||
|
return f'[{formatClock(line_time)}][{action}] {name} {member_count - staff_count}/{guest_count}'
|
||||||
|
|
||||||
|
|
||||||
def parseVrchatEvents(text, config):
|
def parseVrchatEvents(text, config):
|
||||||
start_time = getLogStartTime(datetime.now())
|
start_time = getLogStartTime(datetime.now())
|
||||||
guest_names = config["guest_names"]
|
guest_names = config["guest_names"]
|
||||||
@@ -316,8 +331,10 @@ def parseVrchatEvents(text, config):
|
|||||||
state["member_present_set"].clear()
|
state["member_present_set"].clear()
|
||||||
state["last_notice_key"] = None
|
state["last_notice_key"] = None
|
||||||
output_lines = []
|
output_lines = []
|
||||||
output_lines.append(f"ワールド入室: {formatWorldLabel(world_id, world_name_map)}")
|
world_label = formatWorldLabel(world_id, world_name_map)
|
||||||
output_lines.append(f"現在Guest: 0/{len(guest_names)}")
|
if world_label != "不明":
|
||||||
|
output_lines.append(f"ワールド入室: {world_label}")
|
||||||
|
debug(f"world changed world_id={world_id} label={world_label}")
|
||||||
|
|
||||||
join_match = JOIN_PATTERN.search(raw_line)
|
join_match = JOIN_PATTERN.search(raw_line)
|
||||||
if join_match and state["world_id"]:
|
if join_match and state["world_id"]:
|
||||||
@@ -325,9 +342,7 @@ def parseVrchatEvents(text, config):
|
|||||||
if isSelf(name, self_name):
|
if isSelf(name, self_name):
|
||||||
self_state = "joined"
|
self_state = "joined"
|
||||||
state["member_present_set"].add(name)
|
state["member_present_set"].add(name)
|
||||||
output_lines.append(
|
output_lines.append(formatJoinLeaveLine(line_time, "join", name, state, guest_names))
|
||||||
f'[{formatClock(line_time)}] [join] [self] {name} {len(state["member_present_set"])}/{len(guest_names)}'
|
|
||||||
)
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
role = classifyUser(name, state["guest_name_set"], state["staff_names"])
|
role = classifyUser(name, state["guest_name_set"], state["staff_names"])
|
||||||
@@ -335,20 +350,14 @@ def parseVrchatEvents(text, config):
|
|||||||
if role == "guest":
|
if role == "guest":
|
||||||
state["guest_present_set"].add(name)
|
state["guest_present_set"].add(name)
|
||||||
state["member_present_set"].add(name)
|
state["member_present_set"].add(name)
|
||||||
output_lines.append(
|
output_lines.append(formatJoinLeaveLine(line_time, "join", name, state, guest_names))
|
||||||
f'[{formatClock(line_time)}] [join] {name} {len(state["member_present_set"])}/{len(guest_names)}'
|
|
||||||
)
|
|
||||||
appendNoticeIfNeeded(output_lines, state)
|
appendNoticeIfNeeded(output_lines, state)
|
||||||
elif role == "staff":
|
elif role == "staff":
|
||||||
state["staff_present_set"].add(name)
|
state["staff_present_set"].add(name)
|
||||||
output_lines.append(
|
output_lines.append(formatJoinLeaveLine(line_time, "join", name, state, guest_names))
|
||||||
f'[{formatClock(line_time)}] [join] [staff] {name} {len(state["member_present_set"])}/{len(guest_names)}'
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
state["member_present_set"].add(name)
|
state["member_present_set"].add(name)
|
||||||
output_lines.append(
|
output_lines.append(formatJoinLeaveLine(line_time, "join", name, state, guest_names))
|
||||||
f'[{formatClock(line_time)}] [join] {name} {len(state["member_present_set"])}/{len(guest_names)}'
|
|
||||||
)
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
left_match = LEFT_PATTERN.search(raw_line)
|
left_match = LEFT_PATTERN.search(raw_line)
|
||||||
@@ -357,9 +366,7 @@ def parseVrchatEvents(text, config):
|
|||||||
if isSelf(name, self_name):
|
if isSelf(name, self_name):
|
||||||
self_state = "left"
|
self_state = "left"
|
||||||
state["member_present_set"].discard(name)
|
state["member_present_set"].discard(name)
|
||||||
output_lines.append(
|
output_lines.append(formatJoinLeaveLine(line_time, "leave", name, state, guest_names))
|
||||||
f'[{formatClock(line_time)}] [leave] [self] {name} {len(state["member_present_set"])}/{len(guest_names)}'
|
|
||||||
)
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
role = classifyUser(name, state["guest_name_set"], state["staff_names"])
|
role = classifyUser(name, state["guest_name_set"], state["staff_names"])
|
||||||
@@ -367,20 +374,14 @@ def parseVrchatEvents(text, config):
|
|||||||
if role == "guest":
|
if role == "guest":
|
||||||
state["guest_present_set"].discard(name)
|
state["guest_present_set"].discard(name)
|
||||||
state["member_present_set"].discard(name)
|
state["member_present_set"].discard(name)
|
||||||
output_lines.append(
|
output_lines.append(formatJoinLeaveLine(line_time, "leave", name, state, guest_names))
|
||||||
f'[{formatClock(line_time)}] [leave] {name} {len(state["member_present_set"])}/{len(guest_names)}'
|
|
||||||
)
|
|
||||||
appendNoticeIfNeeded(output_lines, state)
|
appendNoticeIfNeeded(output_lines, state)
|
||||||
elif role == "staff":
|
elif role == "staff":
|
||||||
state["staff_present_set"].discard(name)
|
state["staff_present_set"].discard(name)
|
||||||
output_lines.append(
|
output_lines.append(formatJoinLeaveLine(line_time, "leave", name, state, guest_names))
|
||||||
f'[{formatClock(line_time)}] [leave] [staff] {name} {len(state["member_present_set"])}/{len(guest_names)}'
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
state["member_present_set"].discard(name)
|
state["member_present_set"].discard(name)
|
||||||
output_lines.append(
|
output_lines.append(formatJoinLeaveLine(line_time, "leave", name, state, guest_names))
|
||||||
f'[{formatClock(line_time)}] [leave] {name} {len(state["member_present_set"])}/{len(guest_names)}'
|
|
||||||
)
|
|
||||||
|
|
||||||
return output_lines, self_state
|
return output_lines, self_state
|
||||||
|
|
||||||
@@ -417,12 +418,17 @@ def collectVrchatLog(pattern=None, notify_changed=True):
|
|||||||
text = readTextSafe(latest_log)
|
text = readTextSafe(latest_log)
|
||||||
lines, self_state = parseVrchatEvents(text, config)
|
lines, self_state = parseVrchatEvents(text, config)
|
||||||
|
|
||||||
|
has_join_leave = any("[join]" in line or "[leave]" in line for line in lines)
|
||||||
|
if has_join_leave:
|
||||||
|
lines = ["[DEBUG] 入退出イベント検出"] + lines
|
||||||
|
|
||||||
output_text = "\n".join(lines) if lines else "[INFO] 対象イベントなし"
|
output_text = "\n".join(lines) if lines else "[INFO] 対象イベントなし"
|
||||||
output_path = appendRuntimeLog("VRC LOG", output_text)
|
output_path = appendRuntimeLog("VRC LOG", output_text)
|
||||||
|
|
||||||
if notify_changed:
|
if notify_changed:
|
||||||
global _last_sent_output
|
global _last_sent_output
|
||||||
if output_text != _last_sent_output:
|
should_send = output_text != _last_sent_output or has_join_leave
|
||||||
|
if should_send:
|
||||||
try:
|
try:
|
||||||
ok = sendWebhook(output_text)
|
ok = sendWebhook(output_text)
|
||||||
if ok:
|
if ok:
|
||||||
@@ -434,8 +440,11 @@ def collectVrchatLog(pattern=None, notify_changed=True):
|
|||||||
log("ERROR", f"Discord webhook failed detail={e}")
|
log("ERROR", f"Discord webhook failed detail={e}")
|
||||||
|
|
||||||
log("INFO", f"result appended={output_path}")
|
log("INFO", f"result appended={output_path}")
|
||||||
for line in lines or ["[INFO] 対象イベントなし"]:
|
if lines:
|
||||||
print(line, flush=True)
|
for line in lines:
|
||||||
|
print(line, flush=True)
|
||||||
|
else:
|
||||||
|
debug("対象イベントなし")
|
||||||
|
|
||||||
return output_path
|
return output_path
|
||||||
|
|
||||||
@@ -479,9 +488,7 @@ def _watchVrchatLogChanges(stop_event, label, on_relevant_change):
|
|||||||
|
|
||||||
if latest_size > offset:
|
if latest_size > offset:
|
||||||
text, offset = _readNewText(latest_log, offset)
|
text, offset = _readNewText(latest_log, offset)
|
||||||
|
on_relevant_change(text)
|
||||||
if RELEVANT_LOG_PATTERN.search(text):
|
|
||||||
on_relevant_change(text)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log("ERROR", f"{label} realtime watcher failed detail={e}")
|
log("ERROR", f"{label} realtime watcher failed detail={e}")
|
||||||
|
|
||||||
@@ -491,7 +498,10 @@ def _watchVrchatLogChanges(stop_event, label, on_relevant_change):
|
|||||||
|
|
||||||
|
|
||||||
def _monitor_loop():
|
def _monitor_loop():
|
||||||
def on_relevant_change(_text):
|
def on_relevant_change(text):
|
||||||
|
preview = " ".join(text.splitlines()[:3]).strip()
|
||||||
|
if preview:
|
||||||
|
debug(f"VRC log monitor change preview={preview[:180]}")
|
||||||
collectVrchatLog(notify_changed=True)
|
collectVrchatLog(notify_changed=True)
|
||||||
|
|
||||||
_watchVrchatLogChanges(
|
_watchVrchatLogChanges(
|
||||||
|
|||||||
Reference in New Issue
Block a user