You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

525 lines
12 KiB

package main
import (
"log"
"strconv"
"strings"
)
func privs(args ...string) map[string]bool {
m := make(map[string]bool)
for _, priv := range args {
m[priv] = true
}
return m
}
func SendChatMsg(c *Conn, msg string) {
if c != nil {
c.SendChatMsg(msg)
} else {
log.Print(msg)
}
}
func init() {
disable, ok := ConfKey("disable_builtin").(bool)
if ok && disable {
return
}
RegisterChatCommand("help",
"Shows the help for a command. Shows the help for all commands if executed without arguments. Usage: help [command]",
nil,
true,
func(c *Conn, param string) {
showHelp := func(name string) {
cmd := chatCommands[name]
if help := cmd.Help(); help != "" {
if c != nil {
color := "#F00"
if has, err := c.CheckPrivs(cmd.privs); (err == nil && has) || cmd.privs == nil {
color = "#0F0"
}
c.SendChatMsg(Colorize(name, color) + ": " + help)
} else {
parts := strings.Split(help, "\n")
for _, part := range parts {
log.Print(name + ": " + part)
}
}
} else {
SendChatMsg(c, "No help available for "+name+".")
}
}
if param == "" {
for cmd := range chatCommands {
showHelp(cmd)
}
} else {
showHelp(param)
}
})
RegisterChatCommand("send",
"Sends a player to a server. Usage: send <playername> <servername>",
privs("send"),
true,
func(c *Conn, param string) {
if param == "" {
SendChatMsg(c, "Usage: send <playername> <servername>")
return
}
name := strings.Split(param, " ")[0]
if name == "" || len(strings.Split(param, " ")) < 2 {
SendChatMsg(c, "Usage: send <playername> <servername>")
return
}
tosrv := strings.Split(param, " ")[1]
if tosrv == "" {
SendChatMsg(c, "Usage: send <playername> <servername>")
return
}
servers := ConfKey("servers").(map[interface{}]interface{})
if servers[tosrv] == nil {
SendChatMsg(c, "Unknown servername "+tosrv)
return
}
c2 := ConnByUsername(name)
if c2 == nil {
SendChatMsg(c, name+" is not online")
return
}
srv := c2.ServerName()
if srv == tosrv {
SendChatMsg(c, name+" is already connected to this server!")
return
}
go c2.Redirect(tosrv)
})
RegisterChatCommand("sendcurrent",
"Sends all players on the current server to a new server. Usage: sendcurrent <servername>",
privs("send"),
false,
func(c *Conn, param string) {
if param == "" {
c.SendChatMsg("Usage: sendcurrent <servername>")
return
}
servers := ConfKey("servers").(map[interface{}]interface{})
if servers[param] == nil {
c.SendChatMsg("Unknown servername " + param)
return
}
srv := c.ServerName()
if srv == param {
c.SendChatMsg("All targets are already connected to this server!")
return
}
go func() {
for _, c := range Conns() {
if c.ServerName() == srv {
go c.Redirect(param)
}
}
}()
})
RegisterChatCommand("sendall",
"Sends all players to a server. Usage: sendall <servername>",
privs("send"),
true,
func(c *Conn, param string) {
if param == "" {
SendChatMsg(c, "Usage: sendall <servername>")
return
}
servers := ConfKey("servers").(map[interface{}]interface{})
if servers[param] == nil {
SendChatMsg(c, "Unknown servername "+param)
return
}
go func() {
for _, c := range Conns() {
if psrv := c.ServerName(); psrv != param {
go c.Redirect(param)
}
}
}()
})
RegisterChatCommand("alert",
"Sends a message to all players that are connected to the network. Usage: alert [message]",
privs("alert"),
true,
func(c *Conn, param string) {
ChatSendAll("[ALERT] " + param)
})
RegisterChatCommand("server",
`Prints your current server and a list of all servers if executed without arguments.
Sends you to a server if executed with arguments and the required privilege. Usage: server [servername]"`,
nil,
false,
func(c *Conn, param string) {
if param == "" {
var r string
servers := ConfKey("servers").(map[interface{}]interface{})
for server := range servers {
r += server.(string) + " "
}
var r2 string
groups, ok := ConfKey("groups").(map[interface{}]interface{})
if ok {
for group := range groups {
r2 += group.(string) + " "
}
}
c.SendChatMsg("Current server: " + c.ServerName() + " | All servers: " + r + "| All server groups: " + r2)
} else {
servers := ConfKey("servers").(map[interface{}]interface{})
srv := c.ServerName()
if srv == param {
c.SendChatMsg("You are already connected to this server!")
return
}
nogrp := true
groups, ok := ConfKey("groups").(map[interface{}]interface{})
if ok {
for grp := range groups {
name, ok := grp.(string)
if !ok {
continue
}
if name == param {
nogrp = false
}
}
}
if servers[param] == nil && nogrp {
c.SendChatMsg("Unknown servername " + param)
return
}
reqprivs := make(map[string]bool)
reqpriv, ok := ConfKey("servers:" + param + ":priv").(string)
if ok {
reqprivs[reqpriv] = true
}
reqpriv, ok = ConfKey("group_privs:" + param).(string)
if ok {
reqprivs[reqpriv] = true
}
allow, err := c.CheckPrivs(reqprivs)
if err != nil {
log.Print(err)
c.SendChatMsg("An internal error occured while attempting to check your privileges")
return
}
if !allow {
c.SendChatMsg("You do not have permission to join this server! Required privilege: " + reqpriv)
return
}
go c.Redirect(param)
c.SendChatMsg("Redirecting you to " + param)
}
})
RegisterChatCommand("find",
"Prints the online status and the current server of a player. Usage: find <playername>",
privs("find"),
true,
func(c *Conn, param string) {
if param == "" {
SendChatMsg(c, "Usage: find <playername>")
return
}
c2 := ConnByUsername(param)
if c2 == nil {
SendChatMsg(c, param+" is not online")
} else {
srv := c2.ServerName()
SendChatMsg(c, param+" is connected to server "+srv)
}
})
RegisterChatCommand("addr",
"Prints the network address (including the port) of a connected player. Usage: addr <playername>",
privs("addr"),
true,
func(c *Conn, param string) {
if param == "" {
SendChatMsg(c, "Usage: addr <playername>")
return
}
c2 := ConnByUsername(param)
if c2 == nil {
SendChatMsg(c, param+" is not online")
} else {
SendChatMsg(c, param+"'s address is "+c2.Addr().String())
}
})
RegisterChatCommand("end",
"Kicks all connected clients and stops the proxy. Usage: end",
privs("end"),
true,
func(c *Conn, param string) {
End(false, false)
})
RegisterChatCommand("privs",
`Prints your privileges if executed without arguments.
Prints a connected player's privileges if executed with arguments. Usage: privs [playername]`,
nil,
true,
func(c *Conn, param string) {
var r string
name := param
if name == "" {
if c == nil {
log.Print("Cannot read privileges of console!")
return
}
name = c.Username()
r += "Your privileges: "
} else {
r += name + "'s privileges: "
}
privs, err := Privs(name)
if err != nil {
log.Print(err)
SendChatMsg(c, "An internal error occured while attempting to get the privileges")
return
}
eprivs := encodePrivs(privs)
SendChatMsg(c, r+strings.Replace(eprivs, "|", " ", -1))
})
RegisterChatCommand("grant",
`Grants privileges to a connected player. The privileges need to be comma-seperated.
If the playername is omitted, privileges are granted to you. Usage: grant [playername] <privileges>`,
privs("privs"),
true,
func(c *Conn, param string) {
name := strings.Split(param, " ")[0]
var privnames string
if len(strings.Split(param, " ")) < 2 {
if c == nil {
log.Print("Cannot write privileges of console!")
return
}
privnames = name
name = c.Username()
} else {
privnames = strings.Split(param, " ")[1]
}
privs, err := Privs(name)
if err != nil {
log.Print(err)
SendChatMsg(c, "An internal error occured while attempting to get the privileges")
return
}
splitprivs := strings.Split(strings.Replace(privnames, " ", "", -1), ",")
for i := range splitprivs {
privs[splitprivs[i]] = true
}
err = SetPrivs(name, privs)
if err != nil {
log.Print(err)
SendChatMsg(c, "An internal error occured while attempting to set the privileges")
return
}
SendChatMsg(c, "Privileges updated")
})
RegisterChatCommand("revoke",
`Revokes privileges from a connected player. The privileges need to be comma-seperated.
If the playername is omitted, privileges are revoked from you. Usage: revoke [playername] <privileges>`,
privs("privs"),
true,
func(c *Conn, param string) {
name := strings.Split(param, " ")[0]
var privnames string
if len(strings.Split(param, " ")) < 2 {
if c == nil {
log.Print("Cannot write privileges of console!")
return
}
privnames = name
name = c.Username()
} else {
privnames = strings.Split(param, " ")[1]
}
privs, err := Privs(name)
if err != nil {
log.Print(err)
SendChatMsg(c, "An internal error occured while attempting to get the privileges")
return
}
splitprivs := strings.Split(strings.Replace(privnames, " ", "", -1), ",")
for i := range splitprivs {
privs[splitprivs[i]] = false
}
err = SetPrivs(name, privs)
if err != nil {
log.Print(err)
SendChatMsg(c, "An internal error occured while attempting to set the privileges")
return
}
SendChatMsg(c, "Privileges updated")
})
RegisterChatCommand("banlist",
"Prints the list of banned IP address and associated players. Usage: banlist",
privs("ban"),
true,
func(c *Conn, param string) {
bans, err := BanList()
if err != nil {
SendChatMsg(c, "An internal error occured while attempting to read the ban list")
return
}
msg := "Address | Name\n"
for addr, name := range bans {
msg += addr + " | " + name + "\n"
}
SendChatMsg(c, msg)
})
RegisterChatCommand("kick",
"Kicks a connected player. Usage: kick <playername> [reason]",
privs("kick"),
true,
func(c *Conn, param string) {
if param == "" {
SendChatMsg(c, "Usage: kick <playername> [reason]")
return
}
name := strings.Split(param, " ")[0]
r := "Kicked. " + strings.Join(strings.Split(param, " ")[1:], " ") + "."
if c2 := ConnByUsername(name); c2 != nil {
c2.CloseWith(AccessDeniedCustomString, r, false)
SendChatMsg(c, "Kicked "+name)
} else {
SendChatMsg(c, name+" is not online")
}
})
RegisterChatCommand("ban",
"Bans an IP address or a connected player. Usage: ban <playername | IP address>",
privs("ban"),
true,
func(c *Conn, param string) {
if param == "" {
SendChatMsg(c, "Usage: ban <playername | IP address>")
return
}
err := Ban(param, "not known")
if err != nil {
c2 := ConnByUsername(param)
if c2 == nil {
SendChatMsg(c, param+" is not online")
return
}
if err := c2.Ban(); err != nil {
SendChatMsg(c, "An internal error occured while attempting to ban the player")
return
}
}
SendChatMsg(c, "Banned "+param)
})
RegisterChatCommand("unban",
"Unbans an IP address or a playername. Usage: unban <playername | IP address>",
privs("ban"),
true,
func(c *Conn, param string) {
if param == "" {
SendChatMsg(c, "Usage: unban <playername | IP address>")
return
}
if err := Unban(param); err != nil {
SendChatMsg(c, "An internal error occured while attempting to unban the player")
return
}
SendChatMsg(c, "Unbanned "+param)
})
RegisterChatCommand("uptime",
"Prints the uptime of the proxy. Usage: uptime",
nil,
true,
func(c *Conn, param string) {
SendChatMsg(c, "Uptime: "+strconv.FormatFloat(Uptime(), 'f', -1, 64)+"s")
})
RegisterOnRedirectDone(func(c *Conn, newsrv string, success bool) {
if success {
err := SetStorageKey("server:"+c.Username(), newsrv)
if err != nil {
log.Print(err)
return
}
} else {
c.SendChatMsg("Could not connect you to " + newsrv + "!")
}
})
go func() {
<-LogReady()
log.Print("Loaded builtin")
}()
}