1
1
package api
2
2
3
3
import (
4
- "net/http"
5
-
4
+ "archive/zip"
5
+ "bytes"
6
+ "encoding/json"
7
+ "encoding/xml"
8
+ "errors"
9
+ "io"
6
10
"meteor-server/pkg/core"
7
11
"meteor-server/pkg/db"
12
+ "net/http"
13
+ "strconv"
14
+ "strings"
15
+ "sync"
16
+ "time"
8
17
)
9
18
10
19
type Stats struct {
@@ -15,6 +24,22 @@ type Stats struct {
15
24
Downloads int `json:"downloads"`
16
25
OnlinePlayers int `json:"onlinePlayers"`
17
26
OnlineUUIDs int `json:"onlineUUIDs"`
27
+
28
+ Builds map [string ]int `json:"builds"`
29
+ }
30
+
31
+ var builds map [string ]int
32
+
33
+ func InitStats () {
34
+ t := time .NewTicker (time .Minute )
35
+
36
+ go func () {
37
+ for {
38
+ builds = getBuildNumbers ()
39
+
40
+ <- t .C
41
+ }
42
+ }()
18
43
}
19
44
20
45
func StatsHandler (w http.ResponseWriter , r * http.Request ) {
@@ -23,7 +48,14 @@ func StatsHandler(w http.ResponseWriter, r *http.Request) {
23
48
if date == "" {
24
49
g := db .GetGlobal ()
25
50
26
- core .Json (w , Stats {Config : core .GetConfig (), Date : core .GetDate (), DevBuild : g .DevBuild , Downloads : g .Downloads , OnlinePlayers : GetPlayingCount ()})
51
+ core .Json (w , Stats {
52
+ Config : core .GetConfig (),
53
+ Date : core .GetDate (),
54
+ DevBuild : g .DevBuild ,
55
+ Downloads : g .Downloads ,
56
+ OnlinePlayers : GetPlayingCount (),
57
+ Builds : builds ,
58
+ })
27
59
} else {
28
60
stats , err := db .GetJoinStats (date )
29
61
@@ -35,3 +67,147 @@ func StatsHandler(w http.ResponseWriter, r *http.Request) {
35
67
core .Json (w , stats )
36
68
}
37
69
}
70
+
71
+ func RecheckMavenHandler (w http.ResponseWriter , _ * http.Request ) {
72
+ builds = getBuildNumbers ()
73
+
74
+ core .Json (w , struct {}{})
75
+ }
76
+
77
+ // Maven
78
+
79
+ type MavenSnapshotVersion struct {
80
+ Extension string `xml:"extension"`
81
+ Classifier string `xml:"classifier"`
82
+ Value string `xml:"value"`
83
+ }
84
+
85
+ type MavenVersioning struct {
86
+ Versions []string `xml:"versions>version"`
87
+ SnapshotVersions []MavenSnapshotVersion `xml:"snapshotVersions>snapshotVersion"`
88
+ }
89
+
90
+ type MavenMetadata struct {
91
+ Versioning MavenVersioning `xml:"versioning"`
92
+ }
93
+
94
+ type FabricMod struct {
95
+ Version string `json:"version"`
96
+ }
97
+
98
+ func getBuildNumbers () map [string ]int {
99
+ builds := make (map [string ]int )
100
+
101
+ res , err := http .Get ("https://maven.meteordev.org/snapshots/meteordevelopment/meteor-client/maven-metadata.xml" )
102
+ if err != nil {
103
+ return builds
104
+ }
105
+
106
+ var metadata MavenMetadata
107
+ err = xml .NewDecoder (res .Body ).Decode (& metadata )
108
+ if err != nil {
109
+ return builds
110
+ }
111
+
112
+ mutex := sync.Mutex {}
113
+ group := sync.WaitGroup {}
114
+
115
+ for _ , version := range metadata .Versioning .Versions {
116
+ version := version
117
+ group .Add (1 )
118
+
119
+ go func () {
120
+ i := strings .IndexRune (version , '-' )
121
+ mcVersion := version [:i ]
122
+
123
+ if ! strings .HasPrefix (mcVersion , "0" ) {
124
+ build , err := getBuildNumber (version )
125
+
126
+ if err == nil {
127
+ mutex .Lock ()
128
+ builds [mcVersion ] = build
129
+ mutex .Unlock ()
130
+ }
131
+ }
132
+
133
+ group .Done ()
134
+ }()
135
+ }
136
+
137
+ group .Wait ()
138
+
139
+ return builds
140
+ }
141
+
142
+ func getBuildNumber (version string ) (int , error ) {
143
+ res , err := http .Get ("https://maven.meteordev.org/snapshots/meteordevelopment/meteor-client/" + version + "/maven-metadata.xml" )
144
+ if err != nil {
145
+ return - 1 , err
146
+ }
147
+
148
+ //goland:noinspection GoUnhandledErrorResult
149
+ defer res .Body .Close ()
150
+
151
+ var metadata MavenMetadata
152
+ err = xml .NewDecoder (res .Body ).Decode (& metadata )
153
+ if err != nil {
154
+ return - 1 , err
155
+ }
156
+
157
+ var filename = ""
158
+
159
+ for _ , version := range metadata .Versioning .SnapshotVersions {
160
+ if version .Classifier == "" && version .Extension == "jar" {
161
+ filename = "meteor-client-" + version .Value + ".jar"
162
+ break
163
+ }
164
+ }
165
+
166
+ res , err = http .Get ("https://maven.meteordev.org/snapshots/meteordevelopment/meteor-client/" + version + "/" + filename )
167
+ if err != nil {
168
+ return - 1 , err
169
+ }
170
+
171
+ //goland:noinspection GoUnhandledErrorResult
172
+ defer res .Body .Close ()
173
+
174
+ body , err := io .ReadAll (res .Body )
175
+ if err != nil {
176
+ return - 1 , err
177
+ }
178
+
179
+ jar , err := zip .NewReader (bytes .NewReader (body ), int64 (len (body )))
180
+ if err != nil {
181
+ return - 1 , err
182
+ }
183
+
184
+ var mod FabricMod
185
+
186
+ for _ , file := range jar .File {
187
+ if file .Name == "fabric.mod.json" {
188
+ reader , err := file .Open ()
189
+ if err != nil {
190
+ continue
191
+ }
192
+
193
+ _ = json .NewDecoder (reader ).Decode (& mod )
194
+
195
+ _ = reader .Close ()
196
+
197
+ break
198
+ }
199
+ }
200
+
201
+ if mod .Version != "" {
202
+ i := strings .IndexRune (mod .Version , '-' )
203
+
204
+ build , err := strconv .ParseInt (mod .Version [i + 1 :], 10 , 32 )
205
+ if err != nil {
206
+ return - 1 , err
207
+ }
208
+
209
+ return int (build ), nil
210
+ }
211
+
212
+ return - 1 , errors .New ("unknown build" )
213
+ }
0 commit comments