PageRenderTime 42ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/laddermanager.py

https://github.com/renemilk/SpringLadder
Python | 824 lines | 808 code | 13 blank | 3 comment | 42 complexity | 5fa551f75e2e84c905fee2a6e1cbb162 MD5 | raw file
Possible License(s): WTFPL
  1. # -*- coding: utf-8 -*-
  2. from customlog import *
  3. from ParseConfig import *
  4. import commands, thread, os, sys, signal, traceback, subprocess, platform
  5. from db_entities import *
  6. from ladderdb import *
  7. if platform.system() == "Windows":
  8. import win32api
  9. import helpstrings
  10. helpstring_ladder_admin = helpstrings.helpstring_ladder_admin_manager
  11. helpstring_global_admin = helpstrings.helpstring_global_admin_manager
  12. helpstring_user = helpstrings.helpstring_user_manager
  13. def mError( msg ):
  14. Log.Error( msg, '[LadderManager]' )
  15. def mInfo( msg ):
  16. Log.Info( msg, '[LadderManager]' )
  17. def pm(s,p,m):
  18. try:
  19. for line in m.split('\n'):
  20. mInfo( "PM To:%s, Message: %s" %(p,line))
  21. s.send("SAYPRIVATE %s %s\n" %(p,line))
  22. except:
  23. pass
  24. def saychannel( socket, channel, message ):
  25. for line in message.split('\n'):
  26. mInfo( "Channel :%s, Message: %s" %(channel,line) )
  27. socket.send("SAY %s %s\n" %(channel,line) )
  28. class Main:
  29. botpid = dict() # slot -> bot pid
  30. botstatus = [] # slot -> bot already spawned
  31. battleswithbots = [] # battle id -> bot already in
  32. ladderlist = dict() # id -> ladder name
  33. ladderoptions = dict() # id -> ladder options
  34. def botthread(self,slot,battleid,battlepassword,fromwho,ladderid):
  35. nick = self.app.config["nick"]+str(slot)
  36. try:
  37. d = dict()
  38. d.update([("serveraddr",self.app.config["serveraddr"])])
  39. d.update([("serverport",self.app.config["serverport"])])
  40. d.update([("admins",self.app.config["admins"])])
  41. d.update([("nick",nick)])
  42. d.update([("password",self.app.config["password"])])
  43. d.update([("plugins","ladderslave")])
  44. d.update( [ ( "bans", self.app.config["bans"] ) ] )
  45. d.update([("battleid",str(battleid))])
  46. d.update([("battlepassword",str(battlepassword))])
  47. d.update([("ladderid",str(ladderid))])
  48. d.update([("fromwho",fromwho)])
  49. d.update([("alchemy-uri",self.app.config["alchemy-uri"])])
  50. d.update([("alchemy-verbose",self.app.config["alchemy-verbose"])])
  51. d.update([("springdedclientpath",self.app.config["springdedclientpath"])])
  52. if "springdatapath" in self.app.config:
  53. d.update([("springdatapath",self.app.config["springdatapath"])])
  54. writeconfigfile(nick+".cfg",d)
  55. p = subprocess.Popen(("python","Main.py","-c", "%s" % (nick+".cfg")),stdout=sys.stdout)
  56. self.botpid[slot] = p.pid
  57. p.wait()
  58. except:
  59. mError(traceback.print_exc(file=sys.stdout))
  60. def onload(self,tasc):
  61. self.tsc = tasc
  62. self.bans = []
  63. self.app = tasc.main
  64. self.channels = parselist(self.app.config["channelautojoinlist"],",")
  65. self.admins = parselist(self.app.config["admins"],",")
  66. self.db = LadderDB( parselist(self.app.config["alchemy-uri"],",")[0], self.admins, parselist(self.app.config["alchemy-verbose"],",")[0] )
  67. self.closewhenempty = False
  68. self.enabled = True
  69. def notifyuser( self, socket, fromwho, fromwhere, ispm, message ):
  70. if fromwhere == "main" or fromwhere == "newbies":
  71. ispm = True
  72. if not ispm:
  73. saychannel( socket, fromwhere, message )
  74. else:
  75. pm( socket, fromwho, message )
  76. def sayPermissionDenied(self, socket, command, username,fromwhere, ispm ):
  77. msg = 'You do not have sufficient access right to execute %s on this bot\n' %( command )
  78. self.notifyuser( socket, username, fromwhere, ispm, msg )
  79. def spawnbot( self, socket, battleid, password, fromwho, ladderid ):
  80. slot = 0
  81. busyslot = slot in self.botstatus
  82. while busyslot:
  83. slot = slot+1
  84. busyslot = slot in self.botstatus
  85. notice("spawning " + self.app.config["nick"]+str(slot) + " to join battle " + str(battleid) + " with ladder " + str(ladderid))
  86. self.threads.append(thread.start_new_thread(self.botthread,(slot,battleid,password,fromwho,ladderid)))
  87. def oncommandfromuser(self,fromwho,fromwhere,ispm,command,args,socket):
  88. try:
  89. if fromwho == self.app.config["nick"]:
  90. return
  91. if len(command) > 0 and command[0] == "!":
  92. if not self.db.AccessCheck( -1, fromwho, Roles.User ):
  93. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  94. #log
  95. return
  96. else:
  97. return
  98. # !TODO refactor to use function dict
  99. if command == "!ladder":
  100. if not self.enabled and not self.db.AccessCheck( -1, fromwho, Roles.GlobalAdmin ):
  101. self.notifyuser( socket, fromwho, fromwhere, ispm, "Ladder functionality is temporarily disabled." )
  102. return
  103. ladderid = -1
  104. battleid = -2
  105. password = ""
  106. if len(args) > 0:
  107. if args[0].isdigit():
  108. ladderid = int(args[0])
  109. if len(args) > 1:
  110. password = " ".join(args[1:])
  111. else:
  112. password = " ".join(args[0:])
  113. try:
  114. battleid = self.tsc.users[fromwho].battleid
  115. except:
  116. bad("User " + fromwho + " not found")
  117. if ( battleid < 0 ):
  118. self.notifyuser( socket, fromwho, fromwhere, ispm, "You are not in a battle." )
  119. else:
  120. if not self.db.AccessCheck( ladderid, fromwho, Roles.User ):
  121. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  122. #log
  123. return
  124. if ( battleid in self.battleswithbots ):
  125. self.notifyuser( socket, fromwho, fromwhere, ispm, "A ladder bot is already present in your battle." )
  126. else:
  127. if ( ladderid == -1 or self.db.LadderExists( ladderid ) ):
  128. self.spawnbot( socket, battleid, password, fromwho, ladderid )
  129. else:
  130. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid ladder ID." )
  131. if command == "!ladderjoinchannel":
  132. if not self.db.AccessCheck( -1, fromwho, Roles.GlobalAdmin ):
  133. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  134. #log
  135. return
  136. if len(args) < 1:
  137. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  138. else:
  139. channel = " ".join(args[0:])
  140. socket.send("JOIN " + channel + "\n")
  141. if not channel in self.channels:
  142. self.channels.append(channel)
  143. self.app.config["channelautojoinlist"] = ','.join(self.channels)
  144. self.app.SaveConfig()
  145. if command == "!ladderleavechannel":
  146. if not self.db.AccessCheck( -1, fromwho, Roles.GlobalAdmin ):
  147. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  148. #log
  149. return
  150. if len(args) != 1:
  151. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  152. else:
  153. channel = args[0]
  154. if channel in self.channels:
  155. socket.send("LEAVE " + channel + "\n")
  156. self.channels.remove(channel)
  157. self.app.config["channelautojoinlist"] = ','.join(self.channels)
  158. self.app.SaveConfig()
  159. if command == "!ladderlist":
  160. self.notifyuser( socket, fromwho, fromwhere, ispm, "Available ladders, format name: ID:" )
  161. for l in self.db.GetLadderList(Ladder.name):
  162. self.notifyuser( socket, fromwho, fromwhere, ispm, "%s: %d" %(l.name, l.id ) )
  163. if command == "!ladderadd":
  164. if not self.db.AccessCheck( -1, fromwho, Roles.GlobalAdmin ):
  165. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  166. #log
  167. return
  168. if len(args) < 1:
  169. self.notifyuser( socket, fromwho, fromwhere, ispm, "Ladder name can't be empty." )
  170. else:
  171. try:
  172. laddername = " ".join(args[0:])
  173. ladderid = self.db.AddLadder( laddername )
  174. self.notifyuser( socket, fromwho, fromwhere, ispm, "New ladder created, ID: " + str(ladderid) )
  175. except ElementExistsException, e:
  176. error(e)
  177. if command == "!ladderremove":
  178. if not self.db.AccessCheck( -1, fromwho, Roles.GlobalAdmin ):
  179. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  180. #log
  181. return
  182. if len(args) != 1 or not args[0].isdigit():
  183. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  184. else:
  185. ladderid = int(args[0])
  186. try:
  187. self.db.RemoveLadder( args[0] )
  188. self.notifyuser( socket, fromwho, fromwhere, ispm, "Ladder removed." )
  189. except ElementNotFoundException, e:
  190. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid ladder ID." )
  191. if command == "!ladderchangeaicount":
  192. if len(args) > 3 or not args[0].isdigit() or not args[1].isdigit():
  193. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  194. else:
  195. ladderid = int(args[0])
  196. try:
  197. ladder = self.db.GetLadder( ladderid )
  198. if not self.db.AccessCheck( ladderid, fromwho, Roles.LadderAdmin ):
  199. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  200. #log
  201. return
  202. ladder.min_ai_count = int(args[1])
  203. if len(args) == 2: # min = max
  204. ladder.max_ai_count = int(args[1])
  205. elif len(args) == 3: # separate min & max
  206. if args[2] < args[1]:
  207. self.notifyuser( socket, fromwho, fromwhere, ispm, "max ai count < min! not changed." )
  208. return
  209. ladder.max_ai_count = int(args[2])
  210. self.db.SetLadder( ladder )
  211. self.notifyuser( socket, fromwho, fromwhere, ispm, "Ladder ai count changed." )
  212. except ElementNotFoundException, e:
  213. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid ladder ID." )
  214. if command == "!ladderchangecontrolteamsize":
  215. if len(args) > 3 or not args[0].isdigit() or not args[1].isdigit():
  216. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  217. else:
  218. ladderid = int(args[0])
  219. try:
  220. ladder = self.db.GetLadder( ladderid )
  221. if not self.db.AccessCheck( ladderid, fromwho, Roles.LadderAdmin ):
  222. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  223. #log
  224. return
  225. ladder.min_team_size = int(args[1])
  226. if len(args) == 2: # min = max
  227. ladder.max_team_size = int(args[1])
  228. elif len(args) == 3: # separate min & max
  229. if args[2] < args[1]:
  230. self.notifyuser( socket, fromwho, fromwhere, ispm, "max control team size < min! not changed." )
  231. return
  232. ladder.max_team_size = int(args[2])
  233. self.db.SetLadder( ladder )
  234. self.notifyuser( socket, fromwho, fromwhere, ispm, "Ladder control team size changed." )
  235. except ElementNotFoundException, e:
  236. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid ladder ID." )
  237. if command == "!ladderchangeallysize":
  238. if len(args) > 3 or not args[0].isdigit() or not args[1].isdigit():
  239. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  240. else:
  241. ladderid = int(args[0])
  242. try:
  243. ladder = self.db.GetLadder( ladderid )
  244. if not self.db.AccessCheck( ladderid, fromwho, Roles.LadderAdmin ):
  245. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  246. #log
  247. return
  248. ladder.min_ally_size = int(args[1])
  249. if len(args) == 2: # min = max
  250. ladder.max_ally_size = int(args[1])
  251. elif len(args) == 3: # separate min & max
  252. if args[2] < args[1]:
  253. self.notifyuser( socket, fromwho, fromwhere, ispm, "max ally size < min! not changed." )
  254. return
  255. ladder.max_ally_size = int(args[2])
  256. self.db.SetLadder( ladder )
  257. self.notifyuser( socket, fromwho, fromwhere, ispm, "Ladder ally size changed." )
  258. except ElementNotFoundException, e:
  259. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid ladder ID." )
  260. if command == "!ladderchangecontrolteamcount":
  261. if len(args) > 3 or not args[0].isdigit() or not args[1].isdigit():
  262. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  263. else:
  264. ladderid = int(args[0])
  265. try:
  266. ladder = self.db.GetLadder( ladderid )
  267. if not self.db.AccessCheck( ladderid, fromwho, Roles.LadderAdmin ):
  268. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  269. #log
  270. return
  271. ladder.min_team_count = int(args[1])
  272. if len(args) == 2: # min = max
  273. ladder.max_team_count = int(args[1])
  274. elif len(args) == 3: # separate min & max
  275. if args[2] < args[1]:
  276. self.notifyuser( socket, fromwho, fromwhere, ispm, "max control team count < min! not changed." )
  277. return
  278. ladder.max_team_count = int(args[2])
  279. self.db.SetLadder( ladder )
  280. self.notifyuser( socket, fromwho, fromwhere, ispm, "Ladder control team count changed." )
  281. except ElementNotFoundException, e:
  282. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid ladder ID." )
  283. if command == "!ladderchangeallycount":
  284. if len(args) > 3 or not args[0].isdigit() or not args[1].isdigit():
  285. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  286. else:
  287. ladderid = int(args[0])
  288. try:
  289. ladder = self.db.GetLadder( ladderid )
  290. if not self.db.AccessCheck( ladderid, fromwho, Roles.LadderAdmin ):
  291. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  292. #log
  293. return
  294. ladder.min_ally_count = int(args[1])
  295. if len(args) == 2: # min = max
  296. ladder.max_ally_count = int(args[1])
  297. elif len(args) == 3: # separate min & max
  298. if args[2] < args[1]:
  299. self.notifyuser( socket, fromwho, fromwhere, ispm, "max ally count < min! not changed." )
  300. return
  301. ladder.max_ally_count = int(args[2])
  302. self.db.SetLadder( ladder )
  303. self.notifyuser( socket, fromwho, fromwhere, ispm, "Ladder ally count changed." )
  304. except ElementNotFoundException, e:
  305. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid ladder ID." )
  306. if command == "!ladderaddoption":
  307. if len(args) < 4 or not args[0].isdigit() or not args[1].isdigit():
  308. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  309. else:
  310. ladderid = int(args[0])
  311. if self.db.LadderExists( ladderid ):
  312. if not self.db.AccessCheck( ladderid, fromwho, Roles.LadderAdmin ):
  313. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  314. #log
  315. return
  316. whitelist = int(args[1]) != 0
  317. keyname = args[2]
  318. value = " ".join(args[3:])
  319. if self.db.GetOptionKeyExists(ladderid, not whitelist, keyname ):
  320. self.notifyuser( socket, fromwho, fromwhere, ispm, "You cannot use blacklist and whitelist at the same time for the same option key." )
  321. else:
  322. try:
  323. self.db.AddOption( ladderid, whitelist, keyname, value )
  324. message = "blacklist"
  325. if whitelist:
  326. message = "whitelist"
  327. self.notifyuser( socket, fromwho, fromwhere, ispm, "Option added to the " + message + "." )
  328. except ElementExistsException, e:
  329. self.notifyuser( socket, fromwho, fromwhere, ispm, "Option already in db" )
  330. else:
  331. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid ladder ID." )
  332. if command == "!ladderremoveoption":
  333. if len(args) < 3 or not args[0].isdigit():
  334. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  335. else:
  336. ladderid = int(args[0])
  337. if self.db.LadderExists( ladderid ):
  338. if not self.db.AccessCheck( ladderid, fromwho, Roles.LadderAdmin ):
  339. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  340. #log
  341. return
  342. keyname = args[1]
  343. value = " ".join(args[2:])
  344. indisabledoptions = self.db.GetOptionKeyExists(ladderid, False, keyname )
  345. inenabledoptions = self.db.GetOptionKeyExists(ladderid, True, keyname )
  346. if not indisabledoptions and not inenabledoptions:
  347. self.notifyuser( socket, fromwho, fromwhere, ispm, "Key doesn't exist in either whitelist and blackist." )
  348. else:
  349. if not self.db.GetOptionKeyValueExists( ladderid, inenabledoptions, keyname, value ):
  350. message = "blacklisted"
  351. if inenabledoptions:
  352. message = "whitelisted"
  353. self.notifyuser( socket, fromwho, fromwhere, ispm, "Value doesn't exist in " + message + " options" )
  354. else:
  355. self.db.DeleteOption( ladderid, inenabledoptions, keyname, value )
  356. message = "blacklist"
  357. if inenabledoptions:
  358. message = "whitelist"
  359. self.notifyuser( socket, fromwho, fromwhere, ispm, "Option removed from the " + message + "." )
  360. else:
  361. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid ladder ID." )
  362. if command == "!ladderlistoptions":
  363. if len(args) != 1 or not args[0].isdigit():
  364. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  365. else:
  366. ladderid = int(args[0])
  367. if self.db.LadderExists( ladderid ):
  368. self.notifyuser( socket, fromwho, fromwhere, ispm, "Ladder: " + self.db.GetLadderName(ladderid) )
  369. self.notifyuser( socket, fromwho, fromwhere, ispm, "Min AIs in a Match ( how many AIs ): " + str(self.db.GetLadderOption( ladderid, "min_ai_count" )) )
  370. self.notifyuser( socket, fromwho, fromwhere, ispm, "Max Ais in a Match ( how many AIs ): " + str(self.db.GetLadderOption( ladderid, "max_ai_count" )) )
  371. self.notifyuser( socket, fromwho, fromwhere, ispm, "Min Players in a Team ( sharing control ): " + str(self.db.GetLadderOption( ladderid, "min_team_size" )) )
  372. self.notifyuser( socket, fromwho, fromwhere, ispm, "Max Players in a Team ( sharing control ): " + str(self.db.GetLadderOption( ladderid, "max_team_size" )) )
  373. self.notifyuser( socket, fromwho, fromwhere, ispm, "Min Teams in an Ally ( being allied ): " + str(self.db.GetLadderOption( ladderid, "min_ally_size" )) )
  374. self.notifyuser( socket, fromwho, fromwhere, ispm, "Max Teams in an Ally ( being allied ): " + str(self.db.GetLadderOption( ladderid, "max_ally_size" )) )
  375. self.notifyuser( socket, fromwho, fromwhere, ispm, "Min Teams in a Match ( how many Teams ): " + str(self.db.GetLadderOption( ladderid, "min_team_count" )) )
  376. self.notifyuser( socket, fromwho, fromwhere, ispm, "Max Teams in a Match ( how many Teams ): " + str(self.db.GetLadderOption( ladderid, "max_team_count" )) )
  377. self.notifyuser( socket, fromwho, fromwhere, ispm, "Min Alliances in a Match ( how many Allys ): " + str(self.db.GetLadderOption( ladderid, "min_ally_count" )) )
  378. self.notifyuser( socket, fromwho, fromwhere, ispm, "Max Alliances in a Match ( how many Allys ): " + str(self.db.GetLadderOption( ladderid, "max_ally_count" )) )
  379. self.notifyuser( socket, fromwho, fromwhere, ispm, "Whitelisted options ( if a key is present, no other value except for those listed will be allowed for such key ):" )
  380. for opt in self.db.GetFilteredOptions( ladderid, True ):
  381. self.notifyuser( socket, fromwho, fromwhere, ispm, opt.key + ": " + opt.value )
  382. self.notifyuser( socket, fromwho, fromwhere, ispm, "Blacklisted options ( if a value is present for a key, such value won't be allowed ):" )
  383. for opt in self.db.GetFilteredOptions( ladderid, False ):
  384. self.notifyuser( socket, fromwho, fromwhere, ispm, opt.key + ": " + opt.value )
  385. else:
  386. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid ladder ID." )
  387. if command == "!score":
  388. if not self.db.AccessCheck( -1, fromwho, Roles.User ):
  389. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  390. #log
  391. return
  392. if len(args) > 2:
  393. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  394. else:
  395. ladderid = -1
  396. playername = ""
  397. rep = ''
  398. if len(args) == 1:
  399. if args[0].isdigit():
  400. ladderid = int(args[0])
  401. rep = GlobalRankingAlgoSelector.GetPrintableRepresentation( self.db.GetRanks( ladderid ), self.db )
  402. else:
  403. playername = args[0]
  404. rep = GlobalRankingAlgoSelector.GetPrintableRepresentationPlayer( self.db.GetPlayerRanks( playername ), self.db )
  405. self.notifyuser( socket, fromwho, fromwhere, ispm, rep )
  406. elif len(args) == 2:
  407. if not args[0].isdigit():
  408. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  409. else:
  410. ladderid = int(args[0])
  411. playername = args[1]
  412. rep = GlobalRankingAlgoSelector.GetPrintableRepresentation( self.db.GetRanks( ladderid, playername ), self.db )
  413. self.notifyuser( socket, fromwho, fromwhere, ispm, rep )
  414. if command == "!ladderhelp":
  415. self.notifyuser( socket, fromwho, fromwhere, ispm, "Hello, I am a bot to manage and keep stats of ladder games.\nYou can use the following commands:")
  416. if self.db.AccessCheck( -1, fromwho, Roles.GlobalAdmin ):
  417. self.notifyuser( socket, fromwho, fromwhere, ispm, helpstring_global_admin )
  418. if self.db.AccessCheck( -1, fromwho, Roles.LadderAdmin ):
  419. self.notifyuser( socket, fromwho, fromwhere, ispm, helpstring_ladder_admin )
  420. self.notifyuser( socket, fromwho, fromwhere, ispm, helpstring_user )
  421. if command == "!help":
  422. ispm = True
  423. self.notifyuser( socket, fromwho, fromwhere, ispm, "Hello, I am a bot to manage and keep stats of ladder games.\nYou can use the following commands:")
  424. if self.db.AccessCheck( -1, fromwho, Roles.GlobalAdmin ):
  425. self.notifyuser( socket, fromwho, fromwhere, ispm, helpstring_global_admin )
  426. if self.db.AccessCheck( -1, fromwho, Roles.LadderAdmin ):
  427. self.notifyuser( socket, fromwho, fromwhere, ispm, helpstring_ladder_admin )
  428. self.notifyuser( socket, fromwho, fromwhere, ispm, helpstring_user )
  429. if command == "!laddercopy":
  430. if not self.db.AccessCheck( -1, fromwho, Roles.GlobalAdmin ):
  431. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  432. #log
  433. return
  434. if len(args) < 2:
  435. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  436. else:
  437. source_id = args[0]
  438. target_name = " ".join(args[1:])
  439. try:
  440. self.db.CopyLadder( source_id, target_name )
  441. except:
  442. self.notifyuser( socket, fromwho, fromwhere, ispm, "Couldn't copy ladder" )
  443. if command == "!ladderaddglobaladmin":
  444. if not self.db.AccessCheck( -1, fromwho, Roles.Owner ):
  445. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  446. #log
  447. return
  448. if len(args) < 1:
  449. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  450. else:
  451. username = args[0]
  452. try:
  453. self.db.AddGlobalAdmin( username )
  454. except:
  455. self.notifyuser( socket, fromwho, fromwhere, ispm, "Couldn't add global admin" )
  456. if command == "!ladderaddladderadmin":
  457. if not self.db.AccessCheck( -1, fromwho, Roles.GlobalAdmin ):
  458. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  459. #log
  460. return
  461. if len(args) < 2:
  462. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  463. else:
  464. ladderid = args[0]
  465. username = args[1]
  466. try:
  467. self.db.AddLadderAdmin( ladderid, username )
  468. except ElementNotFoundException, e:
  469. self.notifyuser( socket, fromwho, fromwhere, ispm, "Couldn't add ladder admin: " + str(e) )
  470. if command == "!ladderdeleteglobaladmin":
  471. if not self.db.AccessCheck( -1, fromwho, Roles.Owner ):
  472. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  473. #log
  474. return
  475. if len(args) < 1:
  476. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  477. else:
  478. username = args[0]
  479. try:
  480. self.db.DeleteGlobalAdmin( username )
  481. except:
  482. self.notifyuser( socket, fromwho, fromwhere, ispm, "Couldn't delete global admin" )
  483. if command == "!ladderdeleteladderadmin":
  484. if not self.db.AccessCheck( -1, fromwho, Roles.GlobalAdmin ):
  485. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  486. #log
  487. return
  488. if len(args) < 2:
  489. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  490. else:
  491. ladderid = args[0]
  492. username = args[1]
  493. try:
  494. self.db.DeleteLadderAdmin( ladderid, username )
  495. except:
  496. self.notifyuser( socket, fromwho, fromwhere, ispm, "Couldn't delete ladder admin" )
  497. if command == "!ladderlistrankingalgos":
  498. if len(args) > 0:
  499. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  500. else:
  501. self.notifyuser( socket, fromwho, fromwhere, ispm, GlobalRankingAlgoSelector.ListRegisteredAlgos() )
  502. if command == "!laddersetrankingalgo":
  503. if len(args) < 2:
  504. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  505. else:
  506. ladderid = args[0]
  507. algoname = args[1]
  508. try:
  509. GlobalRankingAlgoSelector.GetInstance( algoname ) # algo unknonw -> excpetion raised
  510. self.db.SetLadderRankingAlgo( ladderid, algoname )
  511. except ElementNotFoundException, e:
  512. self.notifyuser( socket, fromwho, fromwhere, ispm, "Couldn't set ranking algo: " + str(e) )
  513. if command == "!ladderlistmatches":
  514. if len(args) != 1:
  515. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  516. else:
  517. ladderid = args[0]
  518. try:
  519. matches = self.db.GetMatches( ladderid )
  520. res = ''
  521. for m in matches:
  522. res += 'Match no. %d (%s)\n'%(m.id,m.date)
  523. self.notifyuser( socket, fromwho, fromwhere, ispm, res )
  524. except ElementNotFoundException, e:
  525. self.notifyuser( socket, fromwho, fromwhere, ispm, "Error: " + str(e) )
  526. if command == "!ladderdeletematch":
  527. if len(args) != 2:
  528. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  529. else:
  530. ladderid = int(args[0])
  531. match_id = int(args[1])
  532. if not self.db.AccessCheck( ladderid, fromwho, Roles.LadderAdmin ):
  533. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  534. #log
  535. return
  536. try:
  537. self.db.DeleteMatch( ladderid, match_id )
  538. except ElementNotFoundException, e:
  539. self.notifyuser( socket, fromwho, fromwhere, ispm, "Error: " + str(e) )
  540. if command == "!ladderbanuserglobal":
  541. if len(args) < 1:
  542. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  543. else:
  544. username = args[0]
  545. if len(args) == 2:
  546. t_fields = args[1].split(':')
  547. if len( t_fields ) > 1:
  548. days = float(t_fields[0])
  549. hours = float(t_fields[1])
  550. else:
  551. days = 0
  552. hours = float(t_fields[0])
  553. t_delta = timedelta( days=days, hours=hours )
  554. else:
  555. t_delta = timedelta.max
  556. if not self.db.AccessCheck( -1, fromwho, Roles.GlobalAdmin ):
  557. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  558. #log
  559. return
  560. try:
  561. self.db.BanPlayer( -1, username, t_delta )
  562. except ElementNotFoundException, e:
  563. self.notifyuser( socket, fromwho, fromwhere, ispm, "Error: " + str(e) )
  564. if command == "!ladderunbanuserglobal":
  565. if len(args) != 1:
  566. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  567. else:
  568. username = args[0]
  569. if not self.db.AccessCheck( -1, fromwho, Roles.GlobalAdmin ):
  570. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  571. #log
  572. return
  573. try:
  574. self.db.UnbanPlayer( username )
  575. except ElementNotFoundException, e:
  576. self.notifyuser( socket, fromwho, fromwhere, ispm, "Error: " + str(e) )
  577. if command == "!ladderbanuser":
  578. if len(args) < 2:
  579. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  580. else:
  581. ladderid = args[0]
  582. username = args[1]
  583. if len(args) == 3:
  584. t_fields = args[2].split(':')
  585. if len( t_fields ) > 1:
  586. days = float(t_fields[0])
  587. hours = float(t_fields[1])
  588. else:
  589. days = 0
  590. hours = float(t_fields[0])
  591. t_delta = timedelta( days=days, hours=hours )
  592. else:
  593. t_delta = timedelta.max
  594. if not self.db.AccessCheck( ladderid, fromwho, Roles.LadderAdmin ):
  595. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  596. #log
  597. return
  598. try:
  599. self.db.BanPlayer( ladderid, username, t_delta )
  600. except ElementNotFoundException, e:
  601. self.notifyuser( socket, fromwho, fromwhere, ispm, "Error: " + str(e) )
  602. if command == "!ladderunbanuser":
  603. if len(args) < 2:
  604. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  605. else:
  606. ladderid = args[0]
  607. username = args[1]
  608. if not self.db.AccessCheck( ladderid, fromwho, Roles.LadderAdmin ):
  609. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  610. #log
  611. return
  612. try:
  613. self.db.UnbanPlayer( username, ladderid )
  614. except ElementNotFoundException, e:
  615. self.notifyuser( socket, fromwho, fromwhere, ispm, "Error: " + str(e) )
  616. if command == "!ladderlistbans":
  617. if len(args) < 1:
  618. ladderid = -1
  619. else:
  620. ladderid = args[0]
  621. if not self.db.AccessCheck( ladderid, fromwho, Roles.LadderAdmin ):
  622. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  623. #log
  624. return
  625. try:
  626. bans = self.db.GetBansPerLadder( ladderid )
  627. msg = ''
  628. s = self.db.sessionmaker() #not nice, but needed for lazy load?!?
  629. s.add_all( bans )
  630. for b in bans:
  631. msg += str(b) + '\n'
  632. self.notifyuser( socket, fromwho, fromwhere, ispm, msg )
  633. s.close()
  634. except ElementNotFoundException, e:
  635. self.notifyuser( socket, fromwho, fromwhere, ispm, "Error: " + str(e) )
  636. s.close()
  637. if command == "!ladderclosewhenempty":
  638. if not self.db.AccessCheck( -1, fromwho, Roles.GlobalAdmin ):
  639. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  640. #log
  641. return
  642. self.closewhenempty = True
  643. if len(self.botstatus) == 0:
  644. self.KillBot()
  645. if command == "!ladderdisable":
  646. if not self.db.AccessCheck( -1, fromwho, Roles.GlobalAdmin ):
  647. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  648. #log
  649. return
  650. self.enabled = False
  651. self.updatestatus( socket )
  652. self.notifyuser( socket, fromwho, fromwhere, ispm, "Ladder bot spawning is now disabled." )
  653. if command == "!ladderenable":
  654. if not self.db.AccessCheck( -1, fromwho, Roles.GlobalAdmin ):
  655. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  656. #log
  657. return
  658. self.enabled = True
  659. self.updatestatus( socket )
  660. self.notifyuser( socket, fromwho, fromwhere, ispm, "Ladder bot spawning is now enabled." )
  661. if command == "!ladderrecalculateranks":
  662. if len(args) != 1:
  663. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  664. ladderid = int(args[0])
  665. if not self.db.AccessCheck( ladderid, fromwho, Roles.LadderAdmin ):
  666. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  667. #log
  668. return
  669. else:
  670. self.notifyuser( socket, fromwho, fromwhere, ispm, "Beginning to recalculate rankings." )
  671. self.db.RecalcRankings(ladderid)
  672. self.notifyuser( socket, fromwho, fromwhere, ispm, "Done recalculating the ranks." )
  673. if command == "!laddermergeaccounts":
  674. if len(args) < 2 or len(args) > 3:
  675. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  676. return
  677. if not self.db.AccessCheck( -1, fromwho, Roles.GlobalAdmin ):
  678. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  679. #log
  680. return
  681. else:
  682. self.notifyuser( socket, fromwho, fromwhere, ispm, "Beginning to merge the accounts." )
  683. if len(args) == 2:
  684. answer = self.db.MergeAccounts( args[0], args[1] )
  685. else:
  686. answer = self.db.MergeAccounts( args[0], args[1], bool(args[2]) )
  687. self.notifyuser( socket, fromwho, fromwhere, ispm, answer )
  688. if command == "!ladderauth":
  689. if len(args) < 1 or len(args) > 2:
  690. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  691. return
  692. else:
  693. nick = fromwho
  694. if len(args) == 2:
  695. if not self.db.AccessCheck( -1, fromwho, Roles.GlobalAdmin ):
  696. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  697. #log
  698. return
  699. nick = args[1]
  700. ok = self.db.SetPassword( nick, args[0] )
  701. if ok:
  702. self.notifyuser( socket, fromwho, fromwhere, ispm, "Password sucessfully set" )
  703. else:
  704. self.notifyuser( socket, fromwho, fromwhere, ispm, "Password setting failed" )
  705. if command == "!ladderopponent":
  706. if len(args) != 1:
  707. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid command syntax, check !ladderhelp for usage." )
  708. return
  709. ladderid = int(args[0])
  710. if not self.db.AccessCheck( ladderid, fromwho, Roles.User ):
  711. self.sayPermissionDenied( socket, command, fromwho, fromwhere, ispm )
  712. #log
  713. return
  714. if not self.db.LadderExists( ladderid ):
  715. self.notifyuser( socket, fromwho, fromwhere, ispm, "Invalid ladderID." )
  716. return
  717. userlist, ranks = GlobalRankingAlgoSelector.GetCandidateOpponents( fromwho, ladderid, self.db )
  718. opponent_found = False
  719. for user in userlist:
  720. try:
  721. userstatus = self.tsc.users[user]
  722. except: # skip offline
  723. continue
  724. if userstatus.ingame:
  725. continue
  726. if userstatus.afk:
  727. continue
  728. opponent_found = True
  729. self.notifyuser( socket, fromwho, fromwhere, ispm, ranks[user] )
  730. if not opponent_found:
  731. self.notifyuser( socket, fromwho, fromwhere, ispm, "No suitable candidates as opponent are available currently, try again later." )
  732. except DbConnectionLostException, e:
  733. self.notifyuser( socket, fromwho, fromwhere, ispm, "Database temporarily lost in processing your command, please try again" )
  734. err = 'DbConnectionLostException: %s\nargs: %s\ncmd" %s\nwho: %s\nwhere" \n'%(e.getTrace(), args, command, fromwho,fromwhere )
  735. self.mError( err )
  736. self.saychannel( socket, 'ladder', err )
  737. def oncommandfromserver(self,command,args,socket):
  738. if command == "SAID" and len(args) > 2 and args[2].startswith("!"):
  739. self.oncommandfromuser(args[1],args[0],False,args[2],args[3:],socket)
  740. if command == "SAIDPRIVATE" and len(args) > 1 and args[1].startswith("!"):
  741. self.oncommandfromuser(args[0],"PM",True,args[1],args[2:],socket)
  742. if command == "FORCELEAVECHANNEL" and len(args) > 1:
  743. if args[0] in self.channels:
  744. self.channels.remove(args[0])
  745. self.app.config["channelautojoinlist"] = ','.join(self.channels)
  746. self.app.SaveConfig()
  747. if command == "ADDUSER" and len(args) > 0:
  748. name = args[0]
  749. basebotname = self.app.config["nick"]
  750. if name.startswith(basebotname):
  751. name = name[len(basebotname):] # truncate prefix
  752. if name.isdigit():
  753. self.botstatus.append(int(name))
  754. if len(args) > 2:
  755. serveraccountid = int(args[3])
  756. try: # if a player is already in the db, but lacks server_id, add it
  757. self.db.AssignServerID( name, serveraccountid )
  758. except ElementNotFoundException:
  759. pass
  760. try: # if player in the db with same server_id exists, rename it to the new nick
  761. self.db.RenamePlayer( serveraccountid, name )
  762. except ElementNotFoundException:
  763. pass
  764. if command == "REMOVEUSER" and len(args) > 0:
  765. name = args[0]
  766. basebotname = self.app.config["nick"]
  767. if name.startswith(basebotname):
  768. name = name[len(basebotname):] # truncate prefix
  769. if name.isdigit():
  770. self.botstatus.remove(int(name))
  771. if self.closewhenempty:
  772. if len(self.botstatus) == 0:
  773. self.KillBot()
  774. if command == "JOINEDBATTLE" and len(args) > 1:
  775. name = args[1]
  776. battleid = int(args[0])
  777. basebotname = self.app.config["nick"]
  778. if name.startswith(basebotname):
  779. name = name[len(basebotname):] # truncate prefix
  780. if name.isdigit():
  781. number = int(name)
  782. if number in self.botstatus:
  783. if not battleid in self.battleswithbots:
  784. self.battleswithbots.append(battleid)
  785. if command == "LEFTBATTLE" and len(args) > 1:
  786. name = args[1]
  787. battleid = int(args[0])
  788. basebotname = self.app.config["nick"]
  789. if name.startswith(basebotname):
  790. name = name[len(basebotname):] # truncate prefix
  791. if name.isdigit():
  792. number = int(name)
  793. if number in self.botstatus:
  794. if battleid in self.battleswithbots:
  795. self.battleswithbots.remove(battleid)
  796. def updatestatus(self,socket):
  797. socket.send("MYSTATUS %i\n" % int(int(0)+int(not self.enabled)*2))
  798. def onloggedin(self,socket):
  799. self.updatestatus(socket)
  800. def KillBot(self):
  801. if platform.system() == "Windows":
  802. handle = win32api.OpenProcess(1, 0, os.getpid())
  803. win32api.TerminateProcess(handle, 0)
  804. else:
  805. os.kill(os.getpid(),signal.SIGKILL)