505 lines
12 KiB
Go
505 lines
12 KiB
Go
/*
|
|
mt-multiserver-chatcommands provides a useful chat command interface
|
|
for mt-multiserver-proxy.
|
|
*/
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"strings"
|
|
|
|
proxy "github.com/HimbeerserverDE/mt-multiserver-proxy"
|
|
)
|
|
|
|
func init() {
|
|
proxy.RegisterChatCmd(proxy.ChatCmd{
|
|
Name: "shutdown",
|
|
Perm: "cmd_shutdown",
|
|
Help: "Disconnect all clients and stop the server.",
|
|
Usage: "shutdown",
|
|
Handler: func(cc *proxy.ClientConn, w io.Writer, args ...string) string {
|
|
proc, err := os.FindProcess(os.Getpid())
|
|
if err != nil {
|
|
return "Could not find process: " + err.Error()
|
|
}
|
|
|
|
proc.Signal(os.Interrupt)
|
|
return ""
|
|
},
|
|
})
|
|
proxy.RegisterChatCmd(proxy.ChatCmd{
|
|
Name: "find",
|
|
Perm: "cmd_find",
|
|
Help: "Check whether a player is connected and report their upstream server if they are.",
|
|
Usage: "find <name>",
|
|
Handler: func(cc *proxy.ClientConn, w io.Writer, args ...string) string {
|
|
if len(args) != 1 {
|
|
return "Usage: find <name>"
|
|
}
|
|
|
|
clt := proxy.Find(args[0])
|
|
if clt != nil {
|
|
return fmt.Sprintf("%s is connected to %s", clt.Name(), clt.ServerName())
|
|
}
|
|
|
|
return "Player is not connected."
|
|
},
|
|
})
|
|
proxy.RegisterChatCmd(proxy.ChatCmd{
|
|
Name: "addr",
|
|
Perm: "cmd_addr",
|
|
Help: "Find the network address of a player if they're connected.",
|
|
Usage: "addr <name>",
|
|
Handler: func(cc *proxy.ClientConn, w io.Writer, args ...string) string {
|
|
if len(args) != 1 {
|
|
return "Usage: addr <name>"
|
|
}
|
|
|
|
clt := proxy.Find(args[0])
|
|
if clt != nil {
|
|
return fmt.Sprintf("%s is at %s", clt.Name(), clt.RemoteAddr())
|
|
}
|
|
|
|
return "Player is not connected."
|
|
},
|
|
})
|
|
proxy.RegisterChatCmd(proxy.ChatCmd{
|
|
Name: "alert",
|
|
Perm: "cmd_alert",
|
|
Help: "Send a message to all connected clients regardless of their upstream server.",
|
|
Usage: "alert <message>",
|
|
Handler: func(cc *proxy.ClientConn, w io.Writer, args ...string) string {
|
|
if len(args) <= 0 {
|
|
return "Usage: alert <message>"
|
|
}
|
|
|
|
msg := "[ALERT] "
|
|
msg += strings.Join(args, " ")
|
|
|
|
for clt := range proxy.Clts() {
|
|
clt.SendChatMsg(msg)
|
|
}
|
|
|
|
return ""
|
|
},
|
|
})
|
|
proxy.RegisterChatCmd(proxy.ChatCmd{
|
|
Name: "send",
|
|
Perm: "cmd_send",
|
|
Help: "Send player(s) to a new server. player causes a single player to be redirected, current affects all players that are on your current server and all affects everyone.",
|
|
Usage: "send <player <server> <name> | current <server> | all <server>>",
|
|
TelnetUsage: "send <player <server> <name> | all <server>>",
|
|
Handler: func(cc *proxy.ClientConn, w io.Writer, args ...string) string {
|
|
usage := func() string {
|
|
if cc != nil {
|
|
return "Usage: send <player <server> <name> | current <server> | all <server>>"
|
|
} else {
|
|
return "Usage: send <player <server> <name> | all <server>>"
|
|
}
|
|
}
|
|
|
|
if len(args) < 2 {
|
|
return usage()
|
|
}
|
|
|
|
if _, ok := proxy.Conf().Servers[args[1]]; !ok {
|
|
return "Server does not exist."
|
|
}
|
|
|
|
switch args[0] {
|
|
case "player":
|
|
if len(args) != 3 {
|
|
return usage()
|
|
}
|
|
|
|
clt := proxy.Find(args[2])
|
|
if clt == nil {
|
|
return "Player is not connected."
|
|
}
|
|
|
|
if args[1] == clt.ServerName() {
|
|
return "Player is already connected to this server."
|
|
}
|
|
|
|
if err := clt.Hop(args[1]); err != nil {
|
|
clt.SendChatMsg("Could not switch servers. Reconnect if you encounter any problems. Error:", err.Error())
|
|
}
|
|
case "current":
|
|
if cc == nil {
|
|
return usage()
|
|
}
|
|
|
|
if len(args) != 2 {
|
|
return usage()
|
|
}
|
|
|
|
if args[1] == cc.ServerName() {
|
|
return "Start and destination are identical."
|
|
}
|
|
|
|
for clt := range proxy.Clts() {
|
|
if clt.ServerName() == cc.ServerName() && clt.ServerName() != args[1] {
|
|
if err := clt.Hop(args[1]); err != nil {
|
|
clt.SendChatMsg("Could not switch servers. Reconnect if you encounter any problems. Error:", err.Error())
|
|
}
|
|
}
|
|
}
|
|
case "all":
|
|
if len(args) != 2 {
|
|
return usage()
|
|
}
|
|
|
|
for clt := range proxy.Clts() {
|
|
if clt.ServerName() != args[1] {
|
|
if err := clt.Hop(args[1]); err != nil {
|
|
clt.SendChatMsg("Could not switch servers. Reconnect if you encounter any problems. Error:", err.Error())
|
|
}
|
|
}
|
|
}
|
|
default:
|
|
return usage()
|
|
}
|
|
|
|
return ""
|
|
},
|
|
})
|
|
proxy.RegisterChatCmd(proxy.ChatCmd{
|
|
Name: "players",
|
|
Perm: "cmd_players",
|
|
Help: "Show the player list of every server.",
|
|
Usage: "players",
|
|
Handler: func(cc *proxy.ClientConn, w io.Writer, args ...string) string {
|
|
srvs := make(map[string][]*proxy.ClientConn)
|
|
for clt := range proxy.Clts() {
|
|
srv := clt.ServerName()
|
|
srvs[srv] = append(srvs[srv], clt)
|
|
}
|
|
|
|
b := &strings.Builder{}
|
|
for srv, clts := range srvs {
|
|
if srv != "" {
|
|
b.WriteString(srv + ":\n")
|
|
} else {
|
|
b.WriteString("--- No server ---\n")
|
|
}
|
|
|
|
for _, clt := range clts {
|
|
b.WriteString("- " + clt.Name() + "\n")
|
|
}
|
|
}
|
|
|
|
return strings.Trim(b.String(), "\n")
|
|
},
|
|
})
|
|
proxy.RegisterChatCmd(proxy.ChatCmd{
|
|
Name: "reload",
|
|
Perm: "cmd_reload",
|
|
Help: "Reload the configuration file. You should restart the proxy instead if possible.",
|
|
Usage: "reload",
|
|
Handler: func(cc *proxy.ClientConn, w io.Writer, args ...string) string {
|
|
if err := proxy.LoadConfig(); err != nil {
|
|
return "Configuration could not be reloaded. Old config is still active. Error: " + err.Error()
|
|
}
|
|
|
|
return "Configuration reloaded. You should restart if you encounter any problems."
|
|
},
|
|
})
|
|
proxy.RegisterChatCmd(proxy.ChatCmd{
|
|
Name: "group",
|
|
Perm: "cmd_group",
|
|
Help: "Display the group of a player. Display your group if no player name is specified.",
|
|
Usage: "group [name]",
|
|
TelnetUsage: "group <name>",
|
|
Handler: func(cc *proxy.ClientConn, w io.Writer, args ...string) string {
|
|
if len(args) > 0 {
|
|
if len(args) != 1 {
|
|
return "Usage: group [name]"
|
|
}
|
|
|
|
grp, ok := proxy.Conf().UserGroups[args[0]]
|
|
if !ok {
|
|
grp = "default"
|
|
}
|
|
|
|
return "Group: " + grp
|
|
}
|
|
|
|
if cc == nil {
|
|
return "Telnet usage: group <name>"
|
|
}
|
|
|
|
grp, ok := proxy.Conf().UserGroups[cc.Name()]
|
|
if !ok {
|
|
grp = "default"
|
|
}
|
|
|
|
return "Your group: " + grp
|
|
},
|
|
})
|
|
proxy.RegisterChatCmd(proxy.ChatCmd{
|
|
Name: "perms",
|
|
Perm: "cmd_perms",
|
|
Help: "Show the permissions of a player. Show your permissions if no player name is specified.",
|
|
Usage: "perms [name]",
|
|
TelnetUsage: "perms <name>",
|
|
Handler: func(cc *proxy.ClientConn, w io.Writer, args ...string) string {
|
|
if len(args) > 0 {
|
|
if len(args) != 1 {
|
|
return "Usage: perms [name]"
|
|
}
|
|
|
|
clt := proxy.Find(args[0])
|
|
if clt == nil {
|
|
return "Player is not connected."
|
|
}
|
|
|
|
return "Player permissions: " + strings.Join(clt.Perms(), ", ")
|
|
}
|
|
|
|
if cc == nil {
|
|
return "Telnet usage: perms <name>"
|
|
}
|
|
|
|
return "Your permissions: " + strings.Join(cc.Perms(), ", ")
|
|
},
|
|
})
|
|
proxy.RegisterChatCmd(proxy.ChatCmd{
|
|
Name: "gperms",
|
|
Perm: "cmd_gperms",
|
|
Help: "Show the permissions of a group.",
|
|
Usage: "gperms [group]",
|
|
TelnetUsage: "gperms <group>",
|
|
Handler: func(cc *proxy.ClientConn, w io.Writer, args ...string) string {
|
|
if len(args) > 0 {
|
|
if len(args) != 1 {
|
|
return "Usage: gperms [group]"
|
|
}
|
|
|
|
perms, ok := proxy.Conf().Groups[args[0]]
|
|
if !ok {
|
|
return "Group does not exist."
|
|
}
|
|
return "Group permissions: " + strings.Join(perms, ", ")
|
|
}
|
|
|
|
if cc == nil {
|
|
return "Telnet usage: gperms <group>"
|
|
}
|
|
|
|
grp, ok := proxy.Conf().UserGroups[cc.Name()]
|
|
if !ok {
|
|
grp = "default"
|
|
}
|
|
|
|
perms, _ := proxy.Conf().Groups[grp]
|
|
return "Group permissions: " + strings.Join(perms, ", ")
|
|
},
|
|
})
|
|
proxy.RegisterChatCmd(proxy.ChatCmd{
|
|
Name: "server",
|
|
Perm: "cmd_server",
|
|
Help: "Display your current upstream server and all other configured servers. If a valid server name is specified, switch to that server.",
|
|
Usage: "server [server]",
|
|
TelnetUsage: "server",
|
|
Handler: func(cc *proxy.ClientConn, w io.Writer, args ...string) string {
|
|
if len(args) != 1 {
|
|
if len(args) > 1 {
|
|
return "Usage: server [server]"
|
|
}
|
|
|
|
srvs := make([]string, 0, len(proxy.Conf().Servers))
|
|
for name := range proxy.Conf().Servers {
|
|
srvs = append(srvs, name)
|
|
}
|
|
|
|
if cc == nil {
|
|
return "Servers: " + strings.Join(srvs, ", ")
|
|
}
|
|
|
|
return fmt.Sprintf("Connected to: %s | Servers: %s", cc.ServerName(), strings.Join(srvs, ", "))
|
|
}
|
|
|
|
if cc == nil {
|
|
return "Telnet usage: server"
|
|
}
|
|
|
|
if _, ok := proxy.Conf().Servers[args[0]]; !ok {
|
|
return "Server does not exist."
|
|
}
|
|
|
|
if cc.ServerName() == args[0] {
|
|
return "Already connected to this server."
|
|
}
|
|
|
|
if err := cc.Hop(args[0]); err != nil {
|
|
return "Could not switch servers. Reconnect if you encounter any problems. Error: " + err.Error()
|
|
}
|
|
|
|
return ""
|
|
},
|
|
})
|
|
proxy.RegisterChatCmd(proxy.ChatCmd{
|
|
Name: "kick",
|
|
Perm: "cmd_kick",
|
|
Help: "Disconnect a player with an optional reason.",
|
|
Usage: "kick <name> [reason]",
|
|
Handler: func(cc *proxy.ClientConn, w io.Writer, args ...string) string {
|
|
if len(args) < 1 {
|
|
return "Usage: kick <name> [reason]"
|
|
}
|
|
|
|
reason := "Kicked by proxy. "
|
|
if len(args) >= 2 {
|
|
reason += strings.Join(args[1:], " ")
|
|
}
|
|
reason = strings.Trim(reason, " ")
|
|
|
|
clt := proxy.Find(args[0])
|
|
if clt == nil {
|
|
return "Player is not connected."
|
|
}
|
|
|
|
clt.Kick(reason)
|
|
return "Player kicked."
|
|
},
|
|
})
|
|
proxy.RegisterChatCmd(proxy.ChatCmd{
|
|
Name: "ban",
|
|
Perm: "cmd_ban",
|
|
Help: "Ban a player from using the proxy.",
|
|
Usage: "ban <name>",
|
|
Handler: func(cc *proxy.ClientConn, w io.Writer, args ...string) string {
|
|
if len(args) != 1 {
|
|
return "Usage: ban <name>"
|
|
}
|
|
|
|
clt := proxy.Find(args[0])
|
|
if clt == nil {
|
|
return "Player is not connected."
|
|
}
|
|
|
|
if err := clt.Ban(); err != nil {
|
|
return "Could not ban. Error: " + err.Error()
|
|
}
|
|
|
|
return "Player banned."
|
|
},
|
|
})
|
|
proxy.RegisterChatCmd(proxy.ChatCmd{
|
|
Name: "unban",
|
|
Perm: "cmd_unban",
|
|
Help: "Remove a player from the ban list. Accepts addresses and names.",
|
|
Usage: "unban <name | address>",
|
|
Handler: func(cc *proxy.ClientConn, w io.Writer, args ...string) string {
|
|
if len(args) != 1 {
|
|
return "Usage: unban <name | address>"
|
|
}
|
|
|
|
if err := proxy.Unban(args[0]); err != nil {
|
|
return "Could not unban. Error: " + err.Error()
|
|
}
|
|
|
|
return "Player unbanned."
|
|
},
|
|
})
|
|
proxy.RegisterChatCmd(proxy.ChatCmd{
|
|
Name: "uptime",
|
|
Perm: "cmd_uptime",
|
|
Help: "Show the uptime of the proxy.",
|
|
Usage: "uptime",
|
|
Handler: func(cc *proxy.ClientConn, w io.Writer, args ...string) string {
|
|
return fmt.Sprintf("Uptime: %fs", proxy.Uptime().Seconds())
|
|
},
|
|
})
|
|
|
|
proxy.RegisterChatCmd(proxy.ChatCmd{
|
|
Name: "help",
|
|
Perm: "cmd_help",
|
|
Help: "Show help for a command (all commands if unspecified).",
|
|
Usage: "help [command]",
|
|
Handler: func(cc *proxy.ClientConn, w io.Writer, args ...string) string {
|
|
cmds := proxy.ChatCmds()
|
|
|
|
help := func(name string) string {
|
|
str := name + ": "
|
|
if cc != nil {
|
|
str = proxy.Colorize(name+": ", "#6FF")
|
|
}
|
|
|
|
str += cmds[name].Help
|
|
return str
|
|
}
|
|
|
|
if len(args) != 1 {
|
|
if len(args) > 1 {
|
|
return "Usage: help [command]"
|
|
}
|
|
|
|
for cmd := range cmds {
|
|
if cc != nil {
|
|
cc.SendChatMsg(help(cmd))
|
|
} else {
|
|
io.WriteString(w, help(cmd))
|
|
}
|
|
}
|
|
} else {
|
|
if _, ok := cmds[args[0]]; !ok {
|
|
return "Inexistent command."
|
|
}
|
|
|
|
return help(args[0])
|
|
}
|
|
|
|
return ""
|
|
},
|
|
})
|
|
proxy.RegisterChatCmd(proxy.ChatCmd{
|
|
Name: "usage",
|
|
Perm: "cmd_usage",
|
|
Help: "Show the usage string of a command (all commands if unspecified).",
|
|
Usage: "usage [command]",
|
|
Handler: func(cc *proxy.ClientConn, w io.Writer, args ...string) string {
|
|
cmds := proxy.ChatCmds()
|
|
|
|
usage := func(name string) string {
|
|
str := name + ": "
|
|
if cc != nil {
|
|
str = proxy.Colorize(name+": ", "#6F3")
|
|
}
|
|
|
|
if cc != nil || cmds[name].TelnetUsage == "" {
|
|
str += cmds[name].Usage
|
|
} else {
|
|
str += cmds[name].TelnetUsage
|
|
}
|
|
|
|
return str
|
|
}
|
|
|
|
if len(args) != 1 {
|
|
if len(args) > 1 {
|
|
return "Usage: usage [command]"
|
|
}
|
|
|
|
for cmd := range cmds {
|
|
if cc != nil {
|
|
cc.SendChatMsg(usage(cmd))
|
|
} else {
|
|
io.WriteString(w, usage(cmd))
|
|
}
|
|
}
|
|
} else {
|
|
if _, ok := cmds[args[0]]; !ok {
|
|
return "Inexistent command."
|
|
}
|
|
|
|
return usage(args[0])
|
|
}
|
|
|
|
return ""
|
|
},
|
|
})
|
|
}
|