-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmaster.py
More file actions
219 lines (177 loc) · 6.2 KB
/
master.py
File metadata and controls
219 lines (177 loc) · 6.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
import requests
import socket
import json
import sys
from datetime import datetime
from collections import OrderedDict
from flask import Flask, request, make_response, jsonify, send_file
from flask_restful import Resource, Api, reqparse
from flask_cors import CORS
#=============<CONFIG>==================
proxy=True
hostport=80
KillTime=300
banfile="banlist.json"
#=============</CONFIG>=================
app = Flask(__name__)
CORS(app)
api = Api(app)
ServerList = []
class ohai(Resource):
#Simple healthcheck endpoint at the root url
def get(self):
banner = 'ZGAFv0.2'
response = make_response(banner, 200)
response.mimetype = "text/plain"
return banner
class banlist(Resource):
def get(self):
#Check for existence of user agent header
try:
u_agent = request.headers.getlist("User-Agent")[0]
except:
return make_response("", 200)
if proxy:
IP = request.headers.getlist("X-Real-IP")[0]
else:
IP = request.remote_addr
#Check for a valid ed server user agent, then quickly ping the game server api page for an extra layer of verification (could even go a step further and cross reference the json data with our master server api).
if u_agent == "ElDewrito/0.6.1":
try:
dew_request = requests.get('http://'+ IP + ':11775')
except:
return send_file("banlist.json")
#If the game server api is up then return the banlist
if dew_request.status_code == 200:
try:
banfile = json.load(open('banlist.json', 'r'), object_pairs_hook=OrderedDict)
except:
return make_response("", 200)
b_response = make_response(json.dumps(banfile, sort_keys=False), 200)
b_response.mimetype = "application/json"
return send_file("banlist.json")
else:
return send_file("banlist.json")
else:
return make_response("", 200)
class Announce(Resource):
def get(self):
#Proxy check, use x forwarder header for server ip
if proxy:
IP = request.headers.getlist("X-Forwarded-For")[0]
else:
IP = request.remote_addr
#F your regex
try:
socket.inet_aton(IP)
except:
return {
"result": {
"code": 5,
"msg": "🤡"
}
}
#Validate server user agent
try:
userAgent = request.headers.get("User-Agent")
if userAgent not in ("ElDewrito/0.6.1.0", "ElDewrito/0.5.1.1", "ElDewrito/0.7.0.0", "ElDewrito/0.7.1", "ElDewrito/0.7.2"):
return {
"result": {
"code": 5,
"msg": "🤡"
}
}
except:
return {
"result": {
"code": 5,
"msg": "🤡"
}
}
#Grab shutdown flag and validate as boolean
ShutdownFlag = request.args.get('shutdown')
ValidParam = ["1", "0", "true", "false", None]
if ShutdownFlag not in ValidParam:
return {
"result": {
"code": 1,
"msg": "🤡"
}
}
#Grab port query parameter and validate as a real port number
GameJsonPort = request.args.get('port')
if not 1 <= int(GameJsonPort) <= 65535:
return {
"result": {
"code": 4,
"msg": "🤡"
}
}
#Validate this is a real server
try:
resp = requests.get(url="http://" + IP + ":" + str(GameJsonPort), timeout=5)
except:
return {
"result": {
"code": 1,
"msg": "🤡"
}
}
if not resp:
return {
"result": {
"code": 1,
"msg": "🤡"
}
}
#If the server sends a shutdown flag then we remove it from our db. No futher need to hit the game api.
if ShutdownFlag == 1 or "true":
for server in ServerList:
if server[1] == IP:
ServerList.remove(server)
#Add our new server to the server list
DewritoServer = []
DewritoServer.append(datetime.now())
DewritoServer.append(IP)
DewritoServer.append(GameJsonPort)
#Find if our requesting server is in our master list. If so, update the entry.
for server in ServerList:
if DewritoServer[1] in server[1]:
if DewritoServer[2] in server[2]:
index = ServerList.index(server)
ServerList[index] = DewritoServer
else:
ServerList.append(DewritoServer)
return {
"result": {
"code": 0,
"msg": "Added server to list"
}
}
class List(Resource):
def get(self):
MasterList = []
#Find all servers in our list that are not outside the kill time then add them to a sperate list.
for server in ServerList:
LifeTime = datetime.now() - server[0]
if LifeTime.seconds < KillTime:
ServerRecord = str(server[1]) + ":" + str(server[2])
MasterList.append(ServerRecord)
#Build our return data payload with the master server list.
data = {
"listVersion": 1,
"result": {
"code": 0,
"servers": MasterList,
"msg": "OK"
},
"cache": 30,
"listVersion": 1
}
return data
api.add_resource(ohai, '/')
api.add_resource(Announce, '/announce')
api.add_resource(List, '/list')
api.add_resource(banlist, '/banlist')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=hostport)