-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrest.py
293 lines (218 loc) · 8.56 KB
/
rest.py
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
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
from flask import Flask, send_file, Response, jsonify, got_request_exception
from mimetypes import guess_type
from flask_restful import fields, Resource, Api, abort
from src.apis import db_api
from src.cogs.LeagueDisplays import LeagueDisplays
from playhouse.shortcuts import model_to_dict, dict_to_model
from flask_restful import reqparse
from datetime import datetime, timedelta
import base64
import time
from io import BytesIO
import json
import configparser
date_format = '%Y-%m-%d %H:%M:%S.%f'
#
# def log_exception(sender, exception, **extra):
# .debug('API got exception during processing: %s', exception)
#
# got_request_exception.connect(log_exception, app)
class InvalidBetCancel(Exception):
pass
class ResourceDoesNotExist(Exception):
pass
class InvalidBetCreation(Exception):
pass
errors = {
'ResourceDoesNotExist': {
'message': "A resource with that ID no longer exists.",
'status': 400,
},
'InvalidBetCancel': {
'message': "Bet cancellation window has expired.",
'status': 400,
},
'InvalidBetCreation': {
'message': "Cannot bet amount below 0.",
'status': 400,
}
}
config = configparser.ConfigParser()
config.read('config.ini')
app = Flask(__name__)
api = Api(app, errors=errors)
bet_window_ms = int(config['BETTING']['bet_window_ms'])
parser = reqparse.RequestParser()
parser.add_argument('user_id', fields.String)
parser.add_argument('bet_target_id', fields.String)
parser.add_argument('guild_id', fields.String)
parser.add_argument('amount', type=int)
parser.add_argument('will_win', type=bool)
parser.add_argument('game_id', fields.String)
parser.add_argument('bet_id', fields.String)
parser.add_argument('start_date', type=str)
def ids_to_strings(dictionary):
for key in dictionary.keys():
if isinstance(dictionary[key], dict):
ids_to_strings(dictionary[key])
else:
if key[-2:] == 'id':
dictionary[key] = str(dictionary[key])
return dictionary
def js_model_to_dict(obj, **kwargs):
dictionary = model_to_dict(obj, **kwargs)
return ids_to_strings(dictionary)
def to_json(func):
def wrapper(*args, **kwargs):
return json.dumps((func(*args, **kwargs)), default=str)
return wrapper
class Users(Resource):
@to_json
def get(self):
return [js_model_to_dict(user) for user in db_api.get_users_all()]
api.add_resource(Users, '/users')
class User(Resource):
@to_json
def get(self, user_id):
return js_model_to_dict(db_api.get_user_by_id(user_id))
api.add_resource(User, '/user/<string:user_id>')
class UserBetsMatch(Resource):
@to_json
def get(self, user_id, guild_id, match_id):
return [js_model_to_dict(bet) for bet in db_api.get_user_pending_bets_by_match(user_id, guild_id, match_id)]
api.add_resource(UserBetsMatch, '/user/<string:user_id>/<string:guild_id>/bets/<string:match_id>')
class UserBets(Resource):
@to_json
def get(self, user_id, guild_id):
return [js_model_to_dict(bet) for bet in db_api.get_user_new_bets(user_id, guild_id)]
api.add_resource(UserBets, '/user/<string:user_id>/<string:guild_id>/bets')
class UserGuild(Resource):
@to_json
def get(self, user_id):
return [js_model_to_dict(guild) for guild in db_api.get_user_guilds(user_id)]
api.add_resource(UserGuild, '/user/<string:user_id>/guilds')
class Guild(Resource):
@to_json
def get(self, guild_id):
return js_model_to_dict(db_api.get_guild_by_id(guild_id))
api.add_resource(Guild, '/guild/<string:guild_id>')
class GuildStat(Resource):
@to_json
def get(self, user_id, guild_id):
return js_model_to_dict(db_api.get_user_stats(user_id, guild_id))
api.add_resource(GuildStat, '/guildStat/<string:user_id>/<string:guild_id>')
class GuildStats(Resource):
@to_json
def get(self, guild_id):
return [js_model_to_dict(guild_stat) for guild_stat in db_api.get_guild_stats(guild_id)]
api.add_resource(GuildStats, '/guildStats/<string:guild_id>')
class GuildMembers(Resource):
@to_json
def get(self, guild_id):
return [js_model_to_dict(guild) for guild in db_api.get_guild_members(guild_id)]
api.add_resource(GuildMembers, '/guild/<string:guild_id>/members')
class GuildActiveGames(Resource):
@to_json
def get(self, guild_id):
return [js_model_to_dict(match_history) for match_history in db_api.get_guild_unresolved_games(guild_id)]
api.add_resource(GuildActiveGames, '/guild/<string:guild_id>/activeMatches')
class Match(Resource):
@to_json
def get(self, match_id):
return js_model_to_dict(db_api.get_match(match_id))
api.add_resource(Match, '/match/<string:match_id>')
class Bet(Resource):
@to_json
def get(self, bet_id):
return {'bet': 1}
@to_json
def post(self):
args = parser.parse_args()
if args['amount'] <= 0:
raise InvalidBetCreation
created_id = js_model_to_dict(db_api.create_bet(args))
db_api.sub_user_gold(args['user_id'], args['guild_id'], args['amount'])
return created_id
api.add_resource(Bet, '/bet')
class CancelBet(Resource):
def post(self):
args = parser.parse_args()
bet_id = args['bet_id']
bet = db_api.get_bet(bet_id)
if not bet:
raise ResourceDoesNotExist
active_match_data = json.loads(bet.game.active_match_data)
if bet_window_ms < ((round(time.time() * 1000)) - active_match_data['gameStartTime']):
raise InvalidBetCancel
deleted_bet = db_api.delete_bet(bet_id)
if not deleted_bet:
raise ResourceDoesNotExist
db_api.add_user_gold(deleted_bet.user.id, deleted_bet.guild.id, deleted_bet.amount)
return to_json(deleted_bet)
api.add_resource(CancelBet, '/delete/bet')
class MatchImage(Resource):
@to_json
def get(self, match_id):
match = db_api.get_match(match_id)
image = LeagueDisplays.get_game_image(json.loads(match.active_match_data))
buffered = BytesIO()
image.save(buffered, format="PNG")
img_str = base64.b64encode(buffered.getvalue())
return str(img_str)
api.add_resource(MatchImage, '/match/image/<string:match_id>')
class GuildBalanceHistory(Resource):
@to_json
def post(self, guild_id):
args = parser.parse_args()
start_date = args['start_date']
if start_date:
start_date = datetime.strptime(start_date, date_format)
else:
start_date = None
return [js_model_to_dict(history) for history in db_api.get_guild_balance_history(guild_id, start_date)]
api.add_resource(GuildBalanceHistory, '/guild/<string:guild_id>/balanceHistory')
class GuildBalanceBetCount(Resource):
@to_json
def post(self, guild_id):
args = parser.parse_args()
start_date = args['start_date']
if start_date:
start_date = datetime.strptime(start_date, date_format)
else:
start_date = None
return [js_model_to_dict(bet_count, extra_attrs=['wins', 'losses']) for bet_count in db_api.get_guild_bet_counts(guild_id, start_date)]
api.add_resource(GuildBalanceBetCount, '/guild/<string:guild_id>/betCounts')
class GuildWinRate(Resource):
@to_json
def post(self, guild_id):
args = parser.parse_args()
start_date = args['start_date']
if start_date:
start_date = datetime.strptime(start_date, date_format)
else:
start_date = None
return [js_model_to_dict(win_rate, extra_attrs=['win_rate', 'date']) for win_rate in db_api.get_guild_win_rate(guild_id, start_date)]
api.add_resource(GuildWinRate, '/guild/<string:guild_id>/winRate')
class GuildBetHistory(Resource):
@to_json
def post(self, guild_id):
args = parser.parse_args()
start_date = args['start_date']
if start_date:
start_date = datetime.strptime(start_date, date_format)
else:
start_date = None
return [js_model_to_dict(history) for history in db_api.get_guild_bet_history(guild_id, start_date)]
api.add_resource(GuildBetHistory, '/guild/<string:guild_id>/betHistory')
class GuildBetProfits(Resource):
@to_json
def post(self, guild_id):
args = parser.parse_args()
start_date = args['start_date']
if start_date:
start_date = datetime.strptime(start_date, date_format)
else:
start_date = None
return [js_model_to_dict(profit, extra_attrs=['profit']) for profit in db_api.get_guild_bet_profits(guild_id, start_date)]
api.add_resource(GuildBetProfits, '/guild/<string:guild_id>/betProfits')
app.run(debug=False)