backend.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. package main
  2. import (
  3. "encoding/json"
  4. "io/ioutil"
  5. "log"
  6. "math"
  7. "net"
  8. "net/http"
  9. "net/url"
  10. "strconv"
  11. "strings"
  12. "time"
  13. "github.com/go-redis/redis/v8"
  14. "github.com/oschwald/geoip2-golang"
  15. )
  16. var servers DCSServers
  17. func updateServers() {
  18. data := url.Values{
  19. "AUTH_FORM": {"Y"},
  20. "TYPE": {"AUTH"},
  21. "backurl": {"/en/personal/server/?ajax=y"},
  22. "USER_LOGIN": {AppConfig.EDUser},
  23. "USER_PASSWORD": {AppConfig.EDPass},
  24. "USER_REMEMBER": {"Y"},
  25. }
  26. for {
  27. t := time.Now()
  28. currDate := int(t.Unix())
  29. log.Println("Fetching server meta-data")
  30. resp, err := http.PostForm("https://www.digitalcombatsimulator.com/en/personal/server/?ajax=y", data)
  31. if err != nil {
  32. log.Fatalln(err)
  33. }
  34. body, _ := ioutil.ReadAll(resp.Body)
  35. err = json.Unmarshal(body, &servers)
  36. if err != nil {
  37. log.Fatalln(err)
  38. }
  39. log.Println("Fetched server meta-data")
  40. // serverID Unique identifier for a server
  41. var serverID string
  42. // Clean up first
  43. for _, server := range servers.Servers {
  44. serverID = server.IPAddress + ":" + server.Port
  45. GdcsstPlayers.WithLabelValues(serverID).Set(float64(0))
  46. }
  47. GdcsstOnline.WithLabelValues("servers").Set(math.Round(float64(len(servers.Servers))))
  48. GdcsstOnline.WithLabelValues("players").Set(math.Round(float64(servers.PlayersCount)))
  49. for _, server := range servers.Servers {
  50. p, _ := strconv.ParseFloat(server.Players, 32)
  51. serverID = server.IPAddress + ":" + server.Port
  52. GdcsstPlayers.WithLabelValues(serverID).Set(p)
  53. }
  54. //log.Println("Num Servers", len(servers.Servers))
  55. // Connect to the GeoIP2 database
  56. db, err := geoip2.Open(AppConfig.GeoIP2File)
  57. if err != nil {
  58. log.Fatal(err)
  59. }
  60. defer db.Close()
  61. // Connect to Redis
  62. RedisDB, _ := strconv.ParseInt(AppConfig.RedisDB, 10, 8)
  63. rdb := redis.NewClient(&redis.Options{
  64. Addr: AppConfig.RedisIP + ":" + AppConfig.RedisPort,
  65. Password: AppConfig.RedisPassword,
  66. DB: int(RedisDB),
  67. })
  68. defer db.Close()
  69. // Required for the next step
  70. cacheIgnored := 0
  71. cacheResolved := 0
  72. var ServerList []ServerMeta
  73. var metadata ServerMeta
  74. // Compare with Redis + Provide data for webpage
  75. for _, server := range servers.Servers {
  76. // Create the unique serverID
  77. serverID = server.IPAddress + ":" + server.Port
  78. // Server Password
  79. var serverPassword bool
  80. // Server stuff
  81. serverMissionTime, _ := strconv.ParseInt(server.MissionTime, 10, 8)
  82. serverPlayers, _ := strconv.ParseInt(server.Players, 10, 8)
  83. serverPlayersMax, _ := strconv.ParseInt(server.PlayersMax, 10, 8)
  84. if server.Password == "Yes" {
  85. serverPassword = true
  86. } else {
  87. serverPassword = false
  88. }
  89. // Do IP stuff
  90. ip := net.ParseIP(server.IPAddress)
  91. record, err := db.Country(ip)
  92. if err != nil {
  93. log.Fatal(err)
  94. }
  95. // Get record from Redis
  96. redisServer, err := rdb.Get(ctx, serverID).Result()
  97. if err == redis.Nil {
  98. metadata = ServerMeta{
  99. Name: server.Name,
  100. IPAddress: server.IPAddress,
  101. Port: server.Port,
  102. MissionName: server.MissionName,
  103. MissionTime: int(serverMissionTime),
  104. Players: int(serverPlayers),
  105. PlayersMax: int(serverPlayersMax),
  106. Password: serverPassword,
  107. Description: server.Description,
  108. MissionTimeFormatted: server.MissionTimeFormatted,
  109. CountryName: record.Country.Names["en"],
  110. ISO: strings.ToLower(record.Country.IsoCode),
  111. LastUpdate: currDate,
  112. }
  113. msg, errr := json.Marshal(metadata)
  114. if errr != nil {
  115. log.Fatal(errr)
  116. }
  117. err = rdb.Set(ctx, serverID, msg, 750*time.Hour).Err()
  118. if err != nil {
  119. panic(err)
  120. }
  121. cacheResolved++
  122. } else if err != nil {
  123. panic(err)
  124. } else {
  125. redisServerB := []byte(redisServer)
  126. json.Unmarshal(redisServerB, &metadata)
  127. metadata = ServerMeta{
  128. Name: server.Name,
  129. IPAddress: server.IPAddress,
  130. Port: server.Port,
  131. MissionName: server.MissionName,
  132. MissionTime: int(serverMissionTime),
  133. Players: int(serverPlayers),
  134. PlayersMax: int(serverPlayersMax),
  135. Password: serverPassword,
  136. Description: server.Description,
  137. MissionTimeFormatted: server.MissionTimeFormatted,
  138. CountryName: record.Country.Names["en"],
  139. ISO: strings.ToLower(record.Country.IsoCode),
  140. LastUpdate: currDate,
  141. }
  142. // Write stuff
  143. msg, errr := json.Marshal(metadata)
  144. if errr != nil {
  145. log.Fatal(errr)
  146. }
  147. err = rdb.Set(ctx, serverID, msg, 750*time.Hour).Err()
  148. if err != nil {
  149. panic(err)
  150. }
  151. cacheIgnored++
  152. }
  153. if strings.Contains(server.Name, AppConfig.BlackList) == false {
  154. ServerList = append(ServerList, metadata)
  155. }
  156. } // End of Server processing function
  157. log.Printf("Done processing servers: %d processed and %d ignored.", cacheResolved, cacheIgnored)
  158. msg, err := json.Marshal(ServerList)
  159. if err != nil {
  160. panic(err)
  161. }
  162. redisSet("metadata", msg, time.Hour)
  163. // Handle max:
  164. var maxPlayers int
  165. var maxServers int
  166. var maxUpdate int
  167. for _, server := range servers.Servers {
  168. players, _ := strconv.ParseInt(server.Players, 10, 8)
  169. maxPlayers += int(players)
  170. maxServers++
  171. }
  172. var localMaxims GlobalMaxims
  173. maximsJSON, err := rdb.Get(ctx, "maxims").Result()
  174. if err == redis.Nil {
  175. log.Println("Maxims not found. Initalizing.")
  176. localMaxims := GlobalMaxims{MaxServers: maxServers, MaxServersTime: currDate, MaxPlayers: maxPlayers, MaxPlayersTime: currDate}
  177. msg, errr := json.Marshal(localMaxims)
  178. if errr != nil {
  179. log.Fatal(errr)
  180. }
  181. err = rdb.Set(ctx, "maxims", msg, 0).Err()
  182. if err != nil {
  183. panic(err)
  184. }
  185. } else if err != nil {
  186. panic(err)
  187. } else {
  188. maximsB := []byte(maximsJSON)
  189. json.Unmarshal(maximsB, &localMaxims)
  190. if localMaxims.MaxServers < maxServers {
  191. log.Printf("Servers %d > %d", maxServers, localMaxims.MaxServers)
  192. localMaxims.MaxServers = maxServers
  193. localMaxims.MaxServersTime = currDate
  194. maxUpdate = 1
  195. }
  196. if localMaxims.MaxPlayers < maxPlayers {
  197. log.Printf("Players %d > %d", maxPlayers, localMaxims.MaxPlayers)
  198. localMaxims.MaxPlayers = maxPlayers
  199. localMaxims.MaxPlayersTime = currDate
  200. maxUpdate = 1
  201. }
  202. if maxUpdate == 1 {
  203. log.Println("New Maxims found, updating! \\o/")
  204. msg, errr := json.Marshal(localMaxims)
  205. if errr != nil {
  206. log.Fatal(errr)
  207. }
  208. err = rdb.Set(ctx, "maxims", msg, 0).Err()
  209. if err != nil {
  210. panic(err)
  211. }
  212. }
  213. }
  214. redisSet("LastUpdate", []byte(strconv.Itoa(currDate)), 0)
  215. // Sleep a minute
  216. time.Sleep(60 * time.Second)
  217. } // For-loop
  218. } // Function