Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitadf4422

Browse files
author
Mathias Sass Michno
committed
challonge tournament integration
1 parent874eecc commitadf4422

24 files changed

+1111
-63
lines changed

‎get5/__init__.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def config_setting(key):
6363

6464
# Setup database connection
6565
db=flask_sqlalchemy.SQLAlchemy(app)
66-
from .modelsimportUser,Team,GameServer,Match,MapStats,PlayerStats# noqa: E402
66+
from .modelsimportUser,Team,GameServer,Match,Tournament,MapStats,PlayerStats# noqa: E402
6767

6868
# Setup rate limiting
6969
limiter=flask_limiter.Limiter(
@@ -101,6 +101,9 @@ def register_blueprints():
101101
from .apiimportapi_blueprint
102102
app.register_blueprint(api_blueprint)
103103

104+
from .tournamentimporttournament_blueprint
105+
app.register_blueprint(tournament_blueprint)
106+
104107
from .matchimportmatch_blueprint
105108
app.register_blueprint(match_blueprint)
106109

@@ -220,10 +223,9 @@ def add_val(name, value):
220223
values.append((name,value))
221224

222225
add_val('Registered users',User.query.count())
226+
add_val('Tournaments created',Tournament.query.count())
223227
add_val('Saved teams',Team.query.count())
224228
add_val('Matches created',Match.query.count())
225-
add_val('Completed matches',Match.query.filter(
226-
Match.end_timeisnotNone).count())
227229
add_val('Servers added',GameServer.query.count())
228230
add_val('Maps with stats saved',MapStats.query.count())
229231
add_val('Unique players',PlayerStats.query.distinct().count())

‎get5/api.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
fromget5importapp,limiter,db,BadRequestError
22
from .utilimportas_int
3-
from .modelsimportMatch,MapStats,PlayerStats,GameServer
3+
from .modelsimportMatch,MapStats,PlayerStats,GameServer,Tournament,Team
4+
from .importchallonge
45

56
fromflaskimportBlueprint,request
67
importflask_limiter
@@ -10,6 +11,7 @@
1011

1112
api_blueprint=Blueprint('api',__name__)
1213

14+
chall=challonge.ChallongeClient()
1315

1416
_matchid_re=re.compile('/match/(\d*)/.*')
1517

@@ -70,6 +72,14 @@ def match_finish(matchid):
7072
server.in_use=False
7173

7274
db.session.commit()
75+
try:
76+
tournament=Tournament.query.get(match.tournament_id)
77+
scores_csv=','.join(['{}-{}'.format(s1,s2)fors1,s2inmatch.get_scores()])
78+
winner_team=Team.query.get(match.winner)
79+
chall.update_match(tournament.challonge_id,match.challonge_id,
80+
scores_csv=scores_csv,winner_id=winner_team.challonge_id)
81+
exceptchallonge.ChallongeExceptionase:
82+
pass
7383
app.logger.info('Finished match {}, winner={}'.format(match,winner))
7484

7585
return'Success'

‎get5/challonge.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
fromrequestsimportrequest,HTTPError
2+
importitertools
3+
4+
fromget5importconfig_setting
5+
6+
BASE_URL="https://api.challonge.com/v1/"
7+
8+
classChallongeException(Exception):
9+
pass
10+
11+
classChallongeClient(object):
12+
13+
deffetch(self,method,uri,params_prefix=None,**params):
14+
"""Fetch the given uri and return the contents of the response."""
15+
url="{}{}.json".format(BASE_URL,uri)
16+
params=self._prepare_params(params,params_prefix)
17+
ifmethod.lower()=='get':
18+
params['api_key']=config_setting('CHALLONGE_API_KEY')
19+
r_data= {"params":params}
20+
else:
21+
r_data= {"data":params,"params": {'api_key':config_setting('CHALLONGE_API_KEY')}}
22+
try:
23+
response=request(
24+
method,
25+
url,
26+
**r_data)
27+
response.raise_for_status()
28+
exceptHTTPError:
29+
# wrap up application-level errors
30+
doc=response.json()
31+
ifdoc.get("errors"):
32+
raiseChallongeException(*doc['errors'])
33+
34+
returnresponse.json()
35+
36+
37+
def_prepare_params(self,dirty_params,prefix=None):
38+
"""Prepares parameters to be sent to challonge.com.
39+
The `prefix` can be used to convert parameters with keys that
40+
look like ("name", "url", "tournament_type") into something like
41+
("tournament[name]", "tournament[url]", "tournament[tournament_type]"),
42+
which is how challonge.com expects parameters describing specific
43+
objects.
44+
"""
45+
ifprefixandprefix.endswith('[]'):
46+
keys= []
47+
values= []
48+
fork,vindirty_params.items():
49+
ifisinstance(v, (tuple,list)):
50+
keys.append(k)
51+
values.append(v)
52+
firstiter= ((k,v)forvalsinzip(*values)fork,vinzip(keys,vals))
53+
lastiter= ((k,v)fork,vindirty_params.items()ifknotinkeys)
54+
dpiter=itertools.chain(firstiter,lastiter)
55+
else:
56+
dpiter=dirty_params.items()
57+
58+
params= {}
59+
fork,vindpiter:
60+
ifisinstance(v, (tuple,list)):
61+
forvalinv:
62+
val=_prepare_value(val)
63+
ifprefix:
64+
params[f"{prefix}[{k}][]"]=val
65+
else:
66+
params[k+"[]"]=val
67+
else:
68+
v=self._prepare_value(v)
69+
ifprefix:
70+
params[f"{prefix}[{k}]"]=v
71+
else:
72+
params[k]=v
73+
74+
returnparams
75+
76+
def_prepare_value(self,val):
77+
ifhasattr(val,"isoformat"):
78+
val=val.isoformat()
79+
elifisinstance(val,bool):
80+
# challonge.com only accepts lowercase true/false
81+
val=str(val).lower()
82+
returnval
83+
84+
@property
85+
deftournaments(self):
86+
returnself.fetch('get','tournaments')
87+
88+
deftournament(self,id,include_participants=True,include_matches=True):
89+
include_participants=1ifinclude_participantselse0
90+
include_matches=1ifinclude_matcheselse0
91+
returnself.fetch('get',f'tournaments/{id}',
92+
include_matches=include_matches,
93+
include_participants=include_participants)
94+
95+
defcreate_tournament(self,name,url,private=True,open_signup=True,**kwargs):
96+
returnself.fetch('post','tournaments',
97+
params_prefix='tournament',
98+
name=name,url=url,private=private,
99+
open_signup=open_signup,game_id=194,**kwargs)
100+
101+
defdelete_tournament(self,id):
102+
val=self.fetch('delete',f'tournaments/{id}')
103+
returnval
104+
105+
defstart_tournament(self,id):
106+
val=self.fetch('post',f'tournaments/{id}/start',include_matches=1)
107+
returnval
108+
109+
defreset_tournament(self,id):
110+
val=self.fetch('post',f'tournaments/{id}/reset')
111+
returnval
112+
113+
defparticipants(self,tournament_id):
114+
returnself.fetch('get',f'tournaments/{tournament_id}/participants')
115+
116+
defparticipant(self,id):
117+
returnself.fetch('get',f'tournaments/{tournament_id}/participants')
118+
119+
defupdate_participant_misc(self,tournament_id,id,misc):
120+
returnself.fetch('put',f'tournaments/{tournament_id}/participants/{id}',
121+
params_prefix='participant',misc=str(misc))
122+
123+
defupdate_match(self,tournament_id,id,**kwargs):
124+
returnself.fetch('put',f'tournaments/{tournament_id}/matches/{id}',
125+
params_prefix='match',**kwargs)

‎get5/config.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
defaults= {
2+
'LOG_PATH':None,
3+
'DEBUG':False,
4+
'TESTING':False,
5+
'SQLALCHEMY_DATABASE_URI':'mysql://user:password@host/db',
6+
'SQLALCHEMY_TRACK_MODIFICATIONS':False,
7+
'STEAM_API_KEY':'???',
8+
'CHALLONGE_API_KEY':'???',
9+
'SECRET_KEY':'???',
10+
'USER_MAX_SERVERS':10,
11+
'USER_MAX_TEAMS':100,
12+
'USER_MAX_MATCHES':1000,
13+
'USER_MAX_TOURNAMENTS':100,
14+
'BRAND':'Get5 Web Panel',
15+
'DEFAULT_PAGE':'/matches',
16+
'DEFAULT_COUNTRY_CODE':'eu',
17+
'ADMINS_ACCESS_ALL_MATCHES':False,
18+
'ADMINS_ACCESS_ALL_TOURNAMENTS':True,
19+
'CREATE_MATCH_TITLE_TEXT':False,
20+
'CREATE_TOURNAMENT_NAME_TEXT':False,
21+
'WHITELISTED_IDS': [],
22+
'ADMIN_IDS': [],
23+
'MAPLIST': [
24+
'de_cache',
25+
'de_cbble',
26+
'de_inferno',
27+
'de_mirage',
28+
'de_nuke',
29+
'de_overpass',
30+
'de_train',
31+
'de_dust2',
32+
'de_season'
33+
],
34+
'DEFAULT_MAPLIST': [
35+
'de_cache',
36+
'de_cbble',
37+
'de_inferno',
38+
'de_mirage',
39+
'de_nuke',
40+
'de_overpass',
41+
'de_train',
42+
],
43+
}

‎get5/countries.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1+
fromget5importconfig_setting
2+
13
defget_flag_img_path(country_code):
4+
ifnotcountry_code:
5+
country_code=config_setting('DEFAULT_COUNTRY_CODE')
26
ifvalid_country(country_code):
37
return'/static/img/valve_flags/{}.png'.format(country_code.lower())
48
else:
@@ -13,6 +17,8 @@ def valid_country(country_code):
1317

1418

1519
defcountry_name(country_code):
20+
ifnotcountry_code:
21+
country_code=config_setting('DEFAULT_COUNTRY_CODE')
1622
ifnotvalid_country(country_code):
1723
returnNone
1824

‎get5/match.py

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
fromflaskimportBlueprint,request,render_template,flash,g,redirect,jsonify,Markup
1+
fromflaskimportBlueprint,request,render_template,flash,g,redirect,jsonify,Markup,url_for
22

33
from .importsteamid
44
importget5
55
fromget5importapp,db,BadRequestError,config_setting
6-
from .modelsimportUser,Team,Match,GameServer
6+
from .modelsimportUser,Team,Tournament,Match,GameServer
77
from .importutil
88

99
fromwtformsimport (
@@ -139,7 +139,7 @@ def match_create():
139139

140140
ifmax_matches>=0andnum_matches>=max_matchesandnotg.user.admin:
141141
flash('You already have the maximum number of matches ({}) created'.format(
142-
num_matches))
142+
num_matches),'danger')
143143

144144
ifform.validate():
145145
mock=config_setting('TESTING')
@@ -195,9 +195,9 @@ def match_create():
195195
ifmockormatch.send_to_server():
196196
returnredirect('/mymatches')
197197
else:
198-
flash('Failed to load match configs on server')
198+
flash('Failed to load match configs on server','danger')
199199
else:
200-
flash(message)
200+
flash(message,'warning')
201201

202202
else:
203203
get5.flash_errors(form)
@@ -249,6 +249,36 @@ def admintools_check(user, match):
249249
ifmatch.cancelled:
250250
raiseBadRequestError('Match is cancelled')
251251

252+
@match_blueprint.route('/match/<int:matchid>/start')
253+
defmatch_start(matchid):
254+
match=Match.query.get_or_404(matchid)
255+
admintools_check(g.user,match)
256+
257+
ifmatch.server_idisNone:
258+
tournament=Tournament.query.get_or_404(match.tournament_id)
259+
server=tournament.get_available_server()
260+
ifserver:
261+
match.server_id=server.id
262+
server.in_use=True
263+
else:
264+
flash('No server currently available in tournament server pool!','danger')
265+
returnredirect(url_for('match.match',matchid=matchid))
266+
else:
267+
server=GameServer.query.get(match.server_id)
268+
json_reply,message=util.check_server_avaliability(server)
269+
server_avaliable= (json_replyisnotNone)
270+
ifserver_avaliable:
271+
if'plugin_version'injson_reply.keys():
272+
match.plugin_version=json_reply['plugin_version']
273+
else:
274+
match.plugin_version='unknown'
275+
match.start_time=datetime.datetime.utcnow()
276+
ifmatch.send_to_server():
277+
db.session.commit()
278+
returnredirect('/mymatches')
279+
280+
flash("Failed to start match... "+message,'warning')
281+
returnredirect(url_for('match.match',matchid=matchid))
252282

253283
@match_blueprint.route('/match/<int:matchid>/cancel')
254284
defmatch_cancel(matchid):
@@ -265,7 +295,7 @@ def match_cancel(matchid):
265295
try:
266296
server.send_rcon_command('get5_endmatch',raise_errors=True)
267297
exceptutil.RconErrorase:
268-
flash('Failed to cancel match: '+str(e))
298+
flash('Failed to cancel match: '+str(e),'danger')
269299

270300
returnredirect('/mymatches')
271301

@@ -289,7 +319,7 @@ def match_rcon(matchid):
289319
flash(rcon_response)
290320
exceptutil.RconErrorase:
291321
print(e)
292-
flash('Failed to send command: '+str(e))
322+
flash('Failed to send command: '+str(e),'danger')
293323

294324
returnredirect('/match/{}'.format(matchid))
295325

@@ -304,7 +334,7 @@ def match_pause(matchid):
304334
server.send_rcon_command('sm_pause',raise_errors=True)
305335
flash('Paused match')
306336
exceptutil.RconErrorase:
307-
flash('Failed to send pause command: '+str(e))
337+
flash('Failed to send pause command: '+str(e),'danger')
308338

309339
returnredirect('/match/{}'.format(matchid))
310340

@@ -319,7 +349,7 @@ def match_unpause(matchid):
319349
server.send_rcon_command('sm_unpause',raise_errors=True)
320350
flash('Unpaused match')
321351
exceptutil.RconErrorase:
322-
flash('Failed to send unpause command: '+str(e))
352+
flash('Failed to send unpause command: '+str(e),'danger')
323353

324354
returnredirect('/match/{}'.format(matchid))
325355

@@ -344,7 +374,7 @@ def match_adduser(matchid):
344374
flash('Failed to send command: '+str(e))
345375

346376
else:
347-
flash('Invalid steamid: {}'.format(auth))
377+
flash('Invalid steamid: {}'.format(auth),'warning')
348378

349379
returnredirect('/match/{}'.format(matchid))
350380

@@ -388,9 +418,9 @@ def match_backup(matchid):
388418
command='get5_loadbackup {}'.format(file)
389419
response=server.send_rcon_command(command)
390420
ifresponse:
391-
flash('Restored backup file {}'.format(file))
421+
flash('Restored backup file {}'.format(file),'success')
392422
else:
393-
flash('Failed to restore backup file {}'.format(file))
423+
flash('Failed to restore backup file {}'.format(file),'danger')
394424
returnredirect('match/{}/backup'.format(matchid))
395425

396426
returnredirect('match/{}'.format(matchid))

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp