package main import ( "encoding/json" "fmt" "net/http" "os/exec" "strings" "sync" "time" "github.com/mattermost/mattermost/server/public/model" "github.com/mattermost/mattermost/server/public/plugin" ) // Plugin implements the interface expected by the Mattermost server to communicate between the server and plugin processes. type Plugin struct { plugin.MattermostPlugin configurationLock sync.RWMutex configuration *configuration stopChannel chan struct{} apiRouter http.Handler } // Known game processes var knownGames = map[string]bool{ "FortniteClient-Win64-Shipping.exe": true, "OpenDental.exe": true, "chrome.exe": false, } // GetActiveGame scans processes to determine the active game based on known game names func (p *Plugin) GetActiveGame() (string, error) { cmd := exec.Command("ps", "-e") output, err := cmd.Output() if err != nil { return "", err } lines := strings.Split(string(output), "\n") for _, line := range lines { for gameName := range knownGames { if strings.Contains(line, gameName) { return gameName, nil } } } return "", nil } // SetUserGameStatus updates the user's custom status to reflect the game they are playing func (p *Plugin) SetUserGameStatus(userID, game string) error { status := fmt.Sprintf("playing: %s", game) user, appErr := p.API.GetUser(userID) if appErr != nil { return appErr } customStatus := model.CustomStatus{ Emoji: "video_game", Text: status, Duration: "0", } customStatusJSON, err := json.Marshal(customStatus) if err != nil { return err } user.Props = map[string]string{ "custom_status": string(customStatusJSON), } if _, appErr := p.API.UpdateUser(user); appErr != nil { return appErr } return nil } // MonitorGameStatus continuously monitors running processes and updates the user's status func (p *Plugin) MonitorGameStatus(userID string) { for { select { case <-p.stopChannel: return default: game, err := p.GetActiveGame() if err != nil { p.API.LogError("Failed to scan processes", "error", err.Error()) continue } if game != "" { if err := p.SetUserGameStatus(userID, game); err != nil { p.API.LogError("Failed to set user game status", "error", err.Error()) } } time.Sleep(30 * time.Second) } } } // OnActivate is called when the plugin is activated func (p *Plugin) OnActivate() error { p.stopChannel = make(chan struct{}) command := &model.Command{ Trigger: "setgame", AutoComplete: true, AutoCompleteDesc: "set the game you are currently playing", AutoCompleteHint: "[game]", } if err := p.API.RegisterCommand(command); err != nil { return err } // Initialize the router and start the HTTP server p.apiRouter = InitRoutes(p) // Set the API routes go StartHTTPServer(p) // Start the HTTP server return nil } // OnDeactivate is called when the plugin is deactivated func (p *Plugin) OnDeactivate() error { close(p.stopChannel) return nil }