package barertc import ( "strconv" "time" "git.kirsle.net/apps/barertc/pkg/log" "github.com/mattn/go-shellwords" ) // ProcessCommand parses a chat message for "/commands" func (s *Server) ProcessCommand(sub *Subscriber, msg Message) bool { if len(msg.Message) == 0 || msg.Message[0] != '/' { return false } // Line begins with a slash, parse it apart. words, err := shellwords.Parse(msg.Message) if err != nil { log.Error("ProcessCommands: parsing shell words: %s", err) return false } else if len(words) == 0 { return false } // Moderator commands. if sub.JWTClaims != nil && sub.JWTClaims.IsAdmin { switch words[0] { case "/kick": s.KickCommand(words, sub) return true case "/ban": s.BanCommand(words, sub) return true case "/nsfw": if len(words) == 1 { sub.ChatServer("Usage: `/nsfw username` to add the NSFW flag to their camera.") } username := words[1] other, err := s.GetSubscriber(username) if err != nil { sub.ChatServer("/nsfw: username not found: %s", username) } else { other.ChatServer("Your camera has been marked as NSFW by %s", sub.Username) other.VideoNSFW = true other.SendMe() s.SendWhoList() sub.ChatServer("%s has their camera marked as NSFW", username) } return true case "/help": sub.ChatServer(RenderMarkdown("Moderator commands are:\n\n" + "* `/kick ` to kick from chat\n" + "* `/nsfw ` to mark their camera NSFW\n" + "* `/help` to show this message\n\n" + "Note: shell-style quoting is supported, if a username has a space in it, quote the whole username, e.g.: `/kick \"username 2\"`", )) return true } } // Not handled. return false } // KickCommand handles the `/kick` operator command. func (s *Server) KickCommand(words []string, sub *Subscriber) { if len(words) == 1 { sub.ChatServer(RenderMarkdown( "Usage: `/kick username` to remove the user from the chat room.\n\nNote: if the username has spaces in it, quote the name (shell style), `/kick \"username 2\"`", )) return } username := words[1] other, err := s.GetSubscriber(username) if err != nil { sub.ChatServer("/kick: username not found: %s", username) } else if other.Username == sub.Username { sub.ChatServer("/kick: did you really mean to kick yourself?") } else { other.ChatServer("You have been kicked from the chat room by %s", sub.Username) other.SendJSON(Message{ Action: ActionKick, }) s.DeleteSubscriber(other) sub.ChatServer("%s has been kicked from the room", username) } } // BanCommand handles the `/ban` operator command. func (s *Server) BanCommand(words []string, sub *Subscriber) { if len(words) == 1 { sub.ChatServer(RenderMarkdown( "Usage: `/ban username` to remove the user from the chat room for 24 hours (default).\n\n" + "Set another duration (in hours, fractions supported) like: `/ban username 0.5` for a 30-minute ban.", )) return } // Parse the command. var ( username = words[1] duration = 24 * time.Hour ) if len(words) >= 3 { if dur, err := strconv.ParseFloat(words[2], 64); err == nil { if dur < 1 { duration = time.Duration(dur*60) * time.Second } else { duration = time.Duration(dur) * time.Hour } } } // TODO: banning, for now it just kicks. _ = duration other, err := s.GetSubscriber(username) if err != nil { sub.ChatServer("/ban: username not found: %s", username) } else { other.ChatServer("You have been kicked from the chat room by %s", sub.Username) other.SendJSON(Message{ Action: ActionKick, }) s.DeleteSubscriber(other) sub.ChatServer("%s has been kicked from the room", username) } }