Restore VRTW_Tool title; note discord mute regression

This commit is contained in:
every_holiday
2026-06-24 03:08:30 +09:00
parent ab9551c241
commit 63700d9d29
7 changed files with 202 additions and 42 deletions

View File

@@ -29,7 +29,7 @@ func Run(configPath string, mode string) error {
if err != nil {
return err
}
SetGuestTracker(NewGuestTracker(cfg.VrcLog.GuestNames))
InitGuestTracker(NewGuestTracker(cfg.VrcLog.GuestNames))
log.Printf("vrc_osc_go starting osc=%s:%d config=%s", cfg.OSC.Host, cfg.OSC.Port, configPath)
server := osc.NewServer(cfg.OSC.Host, cfg.OSC.Port)

View File

@@ -1,7 +1,6 @@
package app
import (
"bytes"
"fmt"
"log"
"os/exec"
@@ -9,13 +8,68 @@ import (
func pressDiscordMuteHotkey() error {
script := `
$p = Get-Process | Where-Object { $_.MainWindowTitle -match 'Discord' } | Select-Object -First 1
if ($null -eq $p) { exit 2 }
[void][System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
$ErrorActionPreference = "Stop"
function Get-DiscordWindows {
$windows = foreach ($p in Get-Process) {
$title = ($p.MainWindowTitle | Out-String).Trim()
if (-not $title) { continue }
if (-not $title.ToLower().Contains('discord')) { continue }
$p
}
if (-not $windows) { return @() }
return $windows
}
function Get-BestDiscordWindow {
$windows = Get-DiscordWindows
if (-not $windows -or $windows.Count -eq 0) { return $null }
$browserKeywords = @('google chrome', 'microsoft edge', 'mozilla firefox', 'brave', 'opera')
$ranked = $windows | Sort-Object {
$title = ($_.MainWindowTitle | Out-String).Trim().ToLower()
$score = 0
foreach ($keyword in $browserKeywords) {
if ($title.Contains($keyword)) { $score += 10 }
}
if ($title -match '^\(\d+\)\s*discord') { $score += 20 }
if ($title.Contains('discord')) { $score += 5 }
$score
} -Descending
return $ranked | Select-Object -First 1
}
function Get-VRChatWindow {
$windows = Get-Process | Where-Object {
$_.MainWindowTitle -and (
$_.MainWindowTitle -eq 'VRChat' -or $_.MainWindowTitle.ToLower().StartsWith('vrchat ')
)
}
if (-not $windows) { return $null }
return $windows | Sort-Object { $_.MainWindowHandle } -Descending | Select-Object -First 1
}
function Activate-Window($p) {
if ($null -eq $p) { return }
$wshell = New-Object -ComObject WScript.Shell
try { $null = $wshell.AppActivate($p.Id) } catch {}
Start-Sleep -Milliseconds 200
}
$discord = Get-BestDiscordWindow
if ($null -eq $discord) { exit 2 }
Activate-Window $discord
$wshell = New-Object -ComObject WScript.Shell
$null = $wshell.AppActivate($p.Id)
Start-Sleep -Milliseconds 150
Start-Sleep -Milliseconds 200
$wshell.SendKeys('^+m')
Start-Sleep -Milliseconds 200
$vrchat = Get-VRChatWindow
if ($null -ne $vrchat) {
Activate-Window $vrchat
}
`
cmd := exec.Command("powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", script)
@@ -28,9 +82,3 @@ $wshell.SendKeys('^+m')
}
return nil
}
func pressDiscordMuteHotkeyLegacy() error {
var buf bytes.Buffer
_ = buf
return pressDiscordMuteHotkey()
}

View File

@@ -57,7 +57,6 @@ func handleDiscordSend(state *discordMuteState, args []osc.Value) error {
} else {
log.Printf("INFO already muted")
}
return nil
}
return nil

View File

@@ -2,9 +2,14 @@ package app
import (
"fmt"
"encoding/json"
"os"
"path/filepath"
"sort"
"sync"
"time"
"vrc_osc_go/internal/common"
)
type GuestStatus struct {
@@ -48,6 +53,7 @@ func (t *GuestTracker) MarkJoin(name string, at time.Time) {
s.Present = true
s.LastJoin = at
s.AbsentFor = ""
_ = t.persistLocked()
}
func (t *GuestTracker) MarkLeave(name string, at time.Time) {
@@ -59,6 +65,7 @@ func (t *GuestTracker) MarkLeave(name string, at time.Time) {
if !s.LastJoin.IsZero() {
s.AbsentFor = humanSince(at)
}
_ = t.persistLocked()
}
func (t *GuestTracker) Snapshot(now time.Time) []GuestStatus {
@@ -76,6 +83,26 @@ func (t *GuestTracker) Snapshot(now time.Time) []GuestStatus {
return out
}
func (t *GuestTracker) persistLocked() error {
dir := filepath.Join(common.RootDir(), "runtime")
if err := os.MkdirAll(dir, 0o755); err != nil {
return err
}
snapshot := make([]GuestStatus, 0, len(t.items))
for _, s := range t.items {
cp := *s
snapshot = append(snapshot, cp)
}
f, err := os.Create(filepath.Join(dir, "guest_snapshot.json"))
if err != nil {
return err
}
defer f.Close()
enc := json.NewEncoder(f)
enc.SetIndent("", " ")
return enc.Encode(snapshot)
}
func (t *GuestTracker) ensure(name string) *GuestStatus {
if s, ok := t.items[name]; ok {
return s

View File

@@ -1,6 +1,14 @@
package app
import "sync"
import (
"encoding/json"
"os"
"path/filepath"
"sync"
"time"
"vrc_osc_go/internal/common"
)
type RuntimeState struct {
mu sync.RWMutex
@@ -14,30 +22,42 @@ var runtimeState = &RuntimeState{}
var guestTracker *GuestTracker
func SetGuestTracker(t *GuestTracker) { guestTracker = t }
func InitGuestTracker(t *GuestTracker) {
guestTracker = t
if guestTracker != nil {
guestTracker.mu.Lock()
_ = guestTracker.persistLocked()
guestTracker.mu.Unlock()
}
}
func GetGuestTracker() *GuestTracker { return guestTracker }
func SetDiscordMuted(v bool) {
runtimeState.mu.Lock()
defer runtimeState.mu.Unlock()
runtimeState.DiscordMuted = v
runtimeState.mu.Unlock()
_ = persistRuntimeState()
}
func SetOCRText(v string) {
runtimeState.mu.Lock()
defer runtimeState.mu.Unlock()
runtimeState.LastOCRText = v
runtimeState.mu.Unlock()
_ = persistRuntimeState()
}
func SetTranslateText(v string) {
runtimeState.mu.Lock()
defer runtimeState.mu.Unlock()
runtimeState.LastTranslate = v
runtimeState.mu.Unlock()
_ = persistRuntimeState()
}
func SetCurrentWorld(v string) {
runtimeState.mu.Lock()
defer runtimeState.mu.Unlock()
runtimeState.CurrentWorld = v
runtimeState.mu.Unlock()
_ = persistRuntimeState()
}
func SnapshotRuntime() RuntimeState {
@@ -45,3 +65,25 @@ func SnapshotRuntime() RuntimeState {
defer runtimeState.mu.RUnlock()
return *runtimeState
}
func persistRuntimeState() error {
s := SnapshotRuntime()
dir := filepath.Join(common.RootDir(), "runtime")
if err := os.MkdirAll(dir, 0o755); err != nil {
return err
}
f, err := os.Create(filepath.Join(dir, "state.json"))
if err != nil {
return err
}
defer f.Close()
enc := json.NewEncoder(f)
enc.SetIndent("", " ")
return enc.Encode(map[string]any{
"discord_muted": s.DiscordMuted,
"ocr": s.LastOCRText,
"translate": s.LastTranslate,
"world": s.CurrentWorld,
"updated_at": time.Now().Format(time.RFC3339),
})
}