multiserver/serverlist.go

139 lines
2.7 KiB
Go

package main
import (
"bytes"
"encoding/json"
"log"
"mime/multipart"
"net"
"net/http"
"net/textproto"
"time"
)
const (
AnnounceStart = "start"
AnnounceUpdate = "update"
AnnounceDelete = "delete"
)
func Announce(action string) error {
listsrv, ok := ConfKey("serverlist_url").(string)
if !ok {
return nil
}
log.Print("Updating server list announcement")
host, ok := ConfKey("host").(string)
if !ok {
host = "0.0.0.0:33000"
}
addr, err := net.ResolveUDPAddr("udp", host)
if err != nil {
return err
}
conns := Conns()
mods, ok := ConfKey("serverlist_mods").([]string)
if !ok {
mods = make([]string, 0)
}
clients_list := make([]string, 0)
for _, conn := range conns {
clients_list = append(clients_list, conn.Username())
}
maxPeers, ok := ConfKey("player_limit").(int)
if !ok {
maxPeers = int(^uint(0) >> 1)
}
conf := func(key string) interface{} {
value, ok := ConfKey(key).(string)
if !ok {
return ""
}
return value
}
confBool := func(key string) interface{} {
value, ok := ConfKey(key).(bool)
if !ok {
return false
}
return value
}
data := make(map[string]interface{})
data["action"] = action
data["port"] = addr.Port
data["address"] = conf("serverlist_address")
if action != AnnounceDelete {
data["name"] = conf("serverlist_name")
data["description"] = conf("serverlist_desc")
data["version"] = "multiserver v1.13.2"
data["proto_min"] = ProtoMin
data["proto_max"] = ProtoLatest
data["url"] = conf("serverlist_display_url")
data["creative"] = confBool("serverlist_creative")
data["damage"] = confBool("serverlist_damage")
data["password"] = confBool("disallow_empty_passwords")
data["pvp"] = confBool("serverlist_pvp")
data["uptime"] = Uptime()
data["game_time"] = 0
data["clients"] = ConnCount()
data["clients_max"] = maxPeers
data["clients_list"] = clients_list
data["gameid"] = conf("serverlist_game")
}
if action == AnnounceStart {
data["can_see_far_names"] = confBool("serverlist_can_see_far_names")
data["mods"] = mods
}
s, err := json.Marshal(data)
if err != nil {
return err
}
rqBody := &bytes.Buffer{}
writer := multipart.NewWriter(rqBody)
mimeHeader := textproto.MIMEHeader{}
mimeHeader.Set("Content-Disposition", "form-data; name=\"json\"")
part, _ := writer.CreatePart(mimeHeader)
part.Write(s)
writer.Close()
_, err = http.Post(listsrv+"/announce", "multipart/form-data; boundary="+writer.Boundary(), rqBody)
if err != nil {
return err
}
return nil
}
func init() {
reannounce, ok := ConfKey("serverlist_announce_interval").(int)
if !ok {
reannounce = 300
}
go func() {
announce := time.NewTicker(time.Duration(reannounce) * time.Second)
for {
select {
case <-announce.C:
Announce(AnnounceUpdate)
}
}
}()
}