Forked mumble-django project from https://bitbucket.org/Svedrin/mumble-django
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

723 lines
25 KiB

  1. # -*- coding: utf-8 -*-
  2. # kate: space-indent on; indent-width 4; replace-tabs on;
  3. """
  4. * Copyright © 2009, withgod <withgod@sourceforge.net>
  5. * 2009-2010, Michael "Svedrin" Ziegler <diese-addy@funzt-halt.net>
  6. *
  7. * Mumble-Django is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This package is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. """
  17. from time import time
  18. from functools import wraps
  19. from StringIO import StringIO
  20. from os.path import exists, join
  21. from os import unlink, name as os_name
  22. from PIL import Image
  23. from struct import pack, unpack
  24. from zlib import compress, decompress, error
  25. from mctl import MumbleCtlBase
  26. from utils import ObjectInfo
  27. import Ice, IcePy, tempfile
  28. def loadSlice( slicefile ):
  29. """ Load the slice file with the correct include dir set, if possible. """
  30. if hasattr( Ice, "getSliceDir" ):
  31. icepath = Ice.getSliceDir()
  32. else:
  33. icepath = None
  34. # Ice returns '' in getSliceDir() sometimes. (I kid you not.)
  35. if not icepath:
  36. try:
  37. from django.conf import settings
  38. except ImportError:
  39. # CTL is being used independently from MD
  40. icepath = None
  41. else:
  42. icepath = settings.SLICEDIR
  43. if not exists( join( icepath, "Ice", "SliceChecksumDict.ice" ) ):
  44. icepath = None
  45. if not icepath:
  46. # last resort when getSliceDir fails AND settings are wrong/unavailable, won't work for >=1.2.3
  47. Ice.loadSlice( slicefile )
  48. else:
  49. Ice.loadSlice( '', ['-I' + icepath, slicefile ] )
  50. def protectDjangoErrPage( func ):
  51. """ Catch and reraise Ice exceptions to prevent the Django page from failing.
  52. Since I need to "import Murmur", Django would try to read a murmur.py file
  53. which doesn't exist, and thereby produce an IndexError exception. This method
  54. erases the exception's traceback, preventing Django from trying to read any
  55. non-existant files and borking.
  56. """
  57. @wraps(func)
  58. def protection_wrapper( self, *args, **kwargs ):
  59. """ Call the original function and catch Ice exceptions. """
  60. try:
  61. return func( self, *args, **kwargs )
  62. except Ice.Exception, err:
  63. raise err
  64. protection_wrapper.innerfunc = func
  65. return protection_wrapper
  66. @protectDjangoErrPage
  67. def MumbleCtlIce( connstring, slicefile=None, icesecret=None ):
  68. """ Choose the correct Ice handler to use (1.1.8 or 1.2.x), and make sure the
  69. Murmur version matches the slice Version.
  70. Optional parameters are the path to the slice file and the Ice secret
  71. necessary to authenticate to Murmur.
  72. The path can be omitted only if running Murmur 1.2.3 or later, which
  73. exports a getSlice method to retrieve the Slice from.
  74. """
  75. prop = Ice.createProperties([])
  76. prop.setProperty("Ice.ImplicitContext", "Shared")
  77. prop.setProperty("Ice.MessageSizeMax", "65535")
  78. idd = Ice.InitializationData()
  79. idd.properties = prop
  80. ice = Ice.initialize(idd)
  81. if icesecret:
  82. ice.getImplicitContext().put( "secret", icesecret.encode("utf-8") )
  83. prx = ice.stringToProxy( connstring.encode("utf-8") )
  84. try:
  85. prx.ice_ping()
  86. except Ice.Exception:
  87. raise EnvironmentError( "Murmur does not appear to be listening on this address (Ice ping failed)." )
  88. try:
  89. import Murmur
  90. except ImportError:
  91. # Try loading the Slice from Murmur directly via its getSlice method.
  92. # See scripts/testdynamic.py in Mumble's Git repository.
  93. try:
  94. slice = IcePy.Operation( 'getSlice',
  95. Ice.OperationMode.Idempotent, Ice.OperationMode.Idempotent,
  96. True, (), (), (), IcePy._t_string, ()
  97. ).invoke(prx, ((), None))
  98. except (TypeError, Ice.OperationNotExistException):
  99. if not slicefile:
  100. raise EnvironmentError(
  101. "You didn't configure a slice file. Please set the SLICE variable in settings.py." )
  102. if not exists( slicefile ):
  103. raise EnvironmentError(
  104. "The slice file does not exist: '%s' - please check the settings." % slicefile )
  105. if " " in slicefile:
  106. raise EnvironmentError(
  107. "You have a space char in your Slice path. This will confuse Ice, please check." )
  108. if not slicefile.endswith( ".ice" ):
  109. raise EnvironmentError( "The slice file name MUST end with '.ice'." )
  110. try:
  111. loadSlice( slicefile )
  112. except RuntimeError:
  113. raise RuntimeError( "Slice preprocessing failed. Please check your server's error log." )
  114. else:
  115. if os_name == "nt":
  116. # It weren't Windows if it didn't need to be treated differently. *sigh*
  117. temppath = join( tempfile.gettempdir(), "Murmur.ice" )
  118. slicetemp = open( temppath, "w+b" )
  119. try:
  120. slicetemp.write( slice )
  121. finally:
  122. slicetemp.close()
  123. try:
  124. loadSlice( temppath )
  125. except RuntimeError:
  126. raise RuntimeError( "Slice preprocessing failed. Please check your server's error log." )
  127. finally:
  128. unlink(temppath)
  129. else:
  130. slicetemp = tempfile.NamedTemporaryFile( suffix='.ice' )
  131. try:
  132. slicetemp.write( slice )
  133. slicetemp.flush()
  134. loadSlice( slicetemp.name )
  135. except RuntimeError:
  136. raise RuntimeError( "Slice preprocessing failed. Please check your server's error log." )
  137. finally:
  138. slicetemp.close()
  139. import Murmur
  140. meta = Murmur.MetaPrx.checkedCast(prx)
  141. murmurversion = meta.getVersion()[:3]
  142. if murmurversion == (1, 1, 8):
  143. return MumbleCtlIce_118( connstring, meta )
  144. elif murmurversion[:2] == (1, 2):
  145. if murmurversion[2] < 2:
  146. return MumbleCtlIce_120( connstring, meta )
  147. elif murmurversion[2] == 2:
  148. return MumbleCtlIce_122( connstring, meta )
  149. elif murmurversion[2] >= 3:
  150. return MumbleCtlIce_123( connstring, meta )
  151. elif murmurversion[:2] == (1, 3):
  152. return MumbleCtlIce_123( connstring, meta )
  153. raise NotImplementedError( "No ctl object available for Murmur version %d.%d.%d" % tuple(murmurversion) )
  154. class MumbleCtlIce_118(MumbleCtlBase):
  155. method = "ICE"
  156. def __init__( self, connstring, meta ):
  157. self.proxy = connstring
  158. self.meta = meta
  159. @protectDjangoErrPage
  160. def _getIceServerObject(self, srvid):
  161. return self.meta.getServer(srvid)
  162. @protectDjangoErrPage
  163. def getBootedServers(self):
  164. ret = []
  165. for x in self.meta.getBootedServers():
  166. ret.append(x.id())
  167. return ret
  168. @protectDjangoErrPage
  169. def getVersion( self ):
  170. return self.meta.getVersion()
  171. @protectDjangoErrPage
  172. def getAllServers(self):
  173. ret = []
  174. for x in self.meta.getAllServers():
  175. ret.append(x.id())
  176. return ret
  177. @protectDjangoErrPage
  178. def getRegisteredPlayers(self, srvid, filter = ''):
  179. users = self._getIceServerObject(srvid).getRegisteredPlayers( filter.encode( "UTF-8" ) )
  180. ret = {}
  181. for user in users:
  182. ret[user.playerid] = ObjectInfo(
  183. userid = int( user.playerid ),
  184. name = unicode( user.name, "utf8" ),
  185. email = unicode( user.email, "utf8" ),
  186. pw = unicode( user.pw, "utf8" )
  187. )
  188. return ret
  189. @protectDjangoErrPage
  190. def getChannels(self, srvid):
  191. return self._getIceServerObject(srvid).getChannels()
  192. @protectDjangoErrPage
  193. def getTree(self, srvid):
  194. return self._getIceServerObject(srvid).getTree()
  195. @protectDjangoErrPage
  196. def getPlayers(self, srvid):
  197. users = self._getIceServerObject(srvid).getPlayers()
  198. ret = {}
  199. for useridx in users:
  200. user = users[useridx]
  201. ret[ user.session ] = ObjectInfo(
  202. session = user.session,
  203. userid = user.playerid,
  204. mute = user.mute,
  205. deaf = user.deaf,
  206. suppress = user.suppressed,
  207. selfMute = user.selfMute,
  208. selfDeaf = user.selfDeaf,
  209. channel = user.channel,
  210. name = user.name,
  211. onlinesecs = user.onlinesecs,
  212. bytespersec = user.bytespersec
  213. )
  214. return ret
  215. @protectDjangoErrPage
  216. def getDefaultConf(self):
  217. return self.setUnicodeFlag(self.meta.getDefaultConf())
  218. @protectDjangoErrPage
  219. def getAllConf(self, srvid):
  220. conf = self.setUnicodeFlag(self._getIceServerObject(srvid).getAllConf())
  221. info = {}
  222. for key in conf:
  223. if key == "playername":
  224. info['username'] = conf[key]
  225. else:
  226. info[str(key)] = conf[key]
  227. return info
  228. @protectDjangoErrPage
  229. def newServer(self):
  230. return self.meta.newServer().id()
  231. @protectDjangoErrPage
  232. def isBooted( self, srvid ):
  233. return bool( self._getIceServerObject(srvid).isRunning() )
  234. @protectDjangoErrPage
  235. def start( self, srvid ):
  236. self._getIceServerObject(srvid).start()
  237. @protectDjangoErrPage
  238. def stop( self, srvid ):
  239. self._getIceServerObject(srvid).stop()
  240. @protectDjangoErrPage
  241. def deleteServer( self, srvid ):
  242. if self._getIceServerObject(srvid).isRunning():
  243. self._getIceServerObject(srvid).stop()
  244. self._getIceServerObject(srvid).delete()
  245. @protectDjangoErrPage
  246. def setSuperUserPassword(self, srvid, value):
  247. self._getIceServerObject(srvid).setSuperuserPassword( value.encode( "UTF-8" ) )
  248. @protectDjangoErrPage
  249. def getConf(self, srvid, key):
  250. if key == "username":
  251. key = "playername"
  252. return self._getIceServerObject(srvid).getConf( key )
  253. @protectDjangoErrPage
  254. def setConf(self, srvid, key, value):
  255. if key == "username":
  256. key = "playername"
  257. if value is None:
  258. value = ''
  259. self._getIceServerObject(srvid).setConf( key, value.encode( "UTF-8" ) )
  260. @protectDjangoErrPage
  261. def registerPlayer(self, srvid, name, email, password):
  262. mumbleid = self._getIceServerObject(srvid).registerPlayer( name.encode( "UTF-8" ) )
  263. self.setRegistration( srvid, mumbleid, name, email, password )
  264. return mumbleid
  265. @protectDjangoErrPage
  266. def unregisterPlayer(self, srvid, mumbleid):
  267. self._getIceServerObject(srvid).unregisterPlayer(mumbleid)
  268. @protectDjangoErrPage
  269. def getRegistration(self, srvid, mumbleid):
  270. user = self._getIceServerObject(srvid).getRegistration(mumbleid)
  271. return ObjectInfo(
  272. userid = mumbleid,
  273. name = user.name,
  274. email = user.email,
  275. pw = '',
  276. )
  277. @protectDjangoErrPage
  278. def setRegistration(self, srvid, mumbleid, name, email, password):
  279. import Murmur
  280. user = Murmur.RegisteredPlayer()
  281. user.playerid = mumbleid
  282. user.name = name.encode( "UTF-8" )
  283. user.email = email.encode( "UTF-8" )
  284. user.pw = password.encode( "UTF-8" )
  285. # update*r*egistration r is lowercase...
  286. return self._getIceServerObject(srvid).updateregistration(user)
  287. @protectDjangoErrPage
  288. def getACL(self, srvid, channelid):
  289. # need to convert acls to say "userid" instead of "playerid". meh.
  290. raw_acls, raw_groups, raw_inherit = self._getIceServerObject(srvid).getACL(channelid)
  291. acls = [ ObjectInfo(
  292. applyHere = rule.applyHere,
  293. applySubs = rule.applySubs,
  294. inherited = rule.inherited,
  295. userid = rule.playerid,
  296. group = rule.group,
  297. allow = rule.allow,
  298. deny = rule.deny,
  299. )
  300. for rule in raw_acls
  301. ]
  302. return acls, raw_groups, raw_inherit
  303. @protectDjangoErrPage
  304. def setACL(self, srvid, channelid, acls, groups, inherit):
  305. import Murmur
  306. ice_acls = []
  307. for rule in acls:
  308. ice_rule = Murmur.ACL()
  309. ice_rule.applyHere = rule.applyHere
  310. ice_rule.applySubs = rule.applySubs
  311. ice_rule.inherited = rule.inherited
  312. ice_rule.playerid = rule.userid
  313. ice_rule.group = rule.group
  314. ice_rule.allow = rule.allow
  315. ice_rule.deny = rule.deny
  316. ice_acls.append(ice_rule)
  317. return self._getIceServerObject(srvid).setACL( channelid, ice_acls, groups, inherit )
  318. @protectDjangoErrPage
  319. def getTexture(self, srvid, mumbleid):
  320. texture = self._getIceServerObject(srvid).getTexture(mumbleid)
  321. if len(texture) == 0:
  322. raise ValueError( "No Texture has been set." )
  323. # this returns a list of bytes.
  324. try:
  325. decompressed = decompress( texture )
  326. except error, err:
  327. raise ValueError( err )
  328. # iterate over 4 byte chunks of the string
  329. imgdata = ""
  330. for idx in range( 0, len(decompressed), 4 ):
  331. # read 4 bytes = BGRA and convert to RGBA
  332. # manual wrote getTexture returns "Textures are stored as zlib compress()ed 600x60 32-bit RGBA data."
  333. # http://mumble.sourceforge.net/slice/Murmur/Server.html#getTexture
  334. # but return values BGRA X(
  335. bgra = unpack( "4B", decompressed[idx:idx+4] )
  336. imgdata += pack( "4B", bgra[2], bgra[1], bgra[0], bgra[3] )
  337. # return an 600x60 RGBA image object created from the data
  338. return Image.fromstring( "RGBA", ( 600, 60 ), imgdata )
  339. @protectDjangoErrPage
  340. def setTexture(self, srvid, mumbleid, infile):
  341. # open image, convert to RGBA, and resize to 600x60
  342. img = infile.convert( "RGBA" ).transform( ( 600, 60 ), Image.EXTENT, ( 0, 0, 600, 60 ) )
  343. # iterate over the list and pack everything into a string
  344. bgrastring = ""
  345. for ent in list( img.getdata() ):
  346. # ent is in RGBA format, but Murmur wants BGRA (ARGB inverse), so stuff needs
  347. # to be reordered when passed to pack()
  348. bgrastring += pack( "4B", ent[2], ent[1], ent[0], ent[3] )
  349. # compress using zlib
  350. compressed = compress( bgrastring )
  351. # pack the original length in 4 byte big endian, and concat the compressed
  352. # data to it to emulate qCompress().
  353. texture = pack( ">L", len(bgrastring) ) + compressed
  354. # finally call murmur and set the texture
  355. self._getIceServerObject(srvid).setTexture(mumbleid, texture)
  356. @protectDjangoErrPage
  357. def verifyPassword(self, srvid, username, password):
  358. return self._getIceServerObject(srvid).verifyPassword(username, password)
  359. @staticmethod
  360. def setUnicodeFlag(data):
  361. ret = ''
  362. if isinstance(data, tuple) or isinstance(data, list) or isinstance(data, dict):
  363. ret = {}
  364. for key in data.keys():
  365. ret[MumbleCtlIce_118.setUnicodeFlag(key)] = MumbleCtlIce_118.setUnicodeFlag(data[key])
  366. else:
  367. ret = unicode(data, 'utf-8')
  368. return ret
  369. def getUptime(self, srvid):
  370. return None
  371. @protectDjangoErrPage
  372. def getBans( self, srvid ):
  373. return self._getIceServerObject(srvid).getBans()
  374. @protectDjangoErrPage
  375. def getLog( self, srvid, first=0, last=100 ):
  376. return self._getIceServerObject(srvid).getLog( first, last )
  377. @protectDjangoErrPage
  378. def addChannel( self, srvid, name, parentid ):
  379. return self._getIceServerObject(srvid).addChannel( name.encode( "UTF-8" ), parentid )
  380. @protectDjangoErrPage
  381. def removeChannel( self, srvid, channelid ):
  382. return self._getIceServerObject(srvid).removeChannel( channelid )
  383. @protectDjangoErrPage
  384. def renameChannel( self, srvid, channelid, name, description ):
  385. srv = self._getIceServerObject(srvid)
  386. state = srv.getChannelState(channelid)
  387. state.name = name.encode("UTF-8")
  388. srv.setChannelState(state)
  389. @protectDjangoErrPage
  390. def moveChannel(self, srvid, channelid, parentid):
  391. srv = self._getIceServerObject(srvid)
  392. state = srv.getChannelState(channelid)
  393. state.parent = parentid
  394. srv.setChannelState(state)
  395. @protectDjangoErrPage
  396. def moveUser(self, srvid, sessionid, channelid):
  397. srv = self._getIceServerObject(srvid)
  398. state = srv.getState(sessionid)
  399. state.channel = channelid
  400. srv.setState(state)
  401. @protectDjangoErrPage
  402. def muteUser(self, srvid, sessionid, mute=True):
  403. srv = self._getIceServerObject(srvid)
  404. state = srv.getState(sessionid)
  405. state.mute = mute
  406. srv.setState(state)
  407. @protectDjangoErrPage
  408. def deafenUser(self, srvid, sessionid, deaf=True):
  409. srv = self._getIceServerObject(srvid)
  410. state = srv.getState(sessionid)
  411. state.deaf = deaf
  412. srv.setState(state)
  413. @protectDjangoErrPage
  414. def kickUser(self, srvid, userid, reason=""):
  415. return self._getIceServerObject(srvid).kickPlayer( userid, reason.encode("UTF-8") )
  416. @protectDjangoErrPage
  417. def sendMessage(self, srvid, sessionid, message):
  418. return self._getIceServerObject(srvid).sendMessage( sessionid, message.encode( "UTF-8" ) )
  419. @protectDjangoErrPage
  420. def sendMessageChannel(self, srvid, channelid, tree, message):
  421. return self._getIceServerObject(srvid).sendMessageChannel( channelid, tree, message.encode( "UTF-8" ) )
  422. class MumbleCtlIce_120(MumbleCtlIce_118):
  423. @protectDjangoErrPage
  424. def getRegisteredPlayers(self, srvid, filter = ''):
  425. users = self._getIceServerObject( srvid ).getRegisteredUsers( filter.encode( "UTF-8" ) )
  426. ret = {}
  427. for id in users:
  428. ret[id] = ObjectInfo(
  429. userid = id,
  430. name = unicode( users[id], "utf8" ),
  431. email = '',
  432. pw = ''
  433. )
  434. return ret
  435. @protectDjangoErrPage
  436. def getPlayers(self, srvid):
  437. userdata = self._getIceServerObject(srvid).getUsers()
  438. for key in userdata:
  439. if isinstance( userdata[key], str ):
  440. userdata[key] = userdata[key].decode( "UTF-8" )
  441. return userdata
  442. @protectDjangoErrPage
  443. def getState(self, srvid, sessionid):
  444. userdata = self._getIceServerObject(srvid).getState(sessionid)
  445. for key in userdata.__dict__:
  446. attr = getattr( userdata, key )
  447. if isinstance( attr, str ):
  448. setattr( userdata, key, attr.decode( "UTF-8" ) )
  449. return userdata
  450. @protectDjangoErrPage
  451. def registerPlayer(self, srvid, name, email, password):
  452. # To get the real values of these ENUM entries, try
  453. # Murmur.UserInfo.UserX.value
  454. import Murmur
  455. user = {
  456. Murmur.UserInfo.UserName: name.encode( "UTF-8" ),
  457. Murmur.UserInfo.UserEmail: email.encode( "UTF-8" ),
  458. Murmur.UserInfo.UserPassword: password.encode( "UTF-8" ),
  459. }
  460. return self._getIceServerObject(srvid).registerUser( user )
  461. @protectDjangoErrPage
  462. def unregisterPlayer(self, srvid, mumbleid):
  463. self._getIceServerObject(srvid).unregisterUser(mumbleid)
  464. @protectDjangoErrPage
  465. def getRegistration(self, srvid, mumbleid):
  466. reg = self._getIceServerObject( srvid ).getRegistration( mumbleid )
  467. user = ObjectInfo( userid=mumbleid, name="", email="", comment="", hash="", pw="" )
  468. import Murmur
  469. if Murmur.UserInfo.UserName in reg: user.name = reg[Murmur.UserInfo.UserName]
  470. if Murmur.UserInfo.UserEmail in reg: user.email = reg[Murmur.UserInfo.UserEmail]
  471. if Murmur.UserInfo.UserComment in reg: user.comment = reg[Murmur.UserInfo.UserComment]
  472. if Murmur.UserInfo.UserHash in reg: user.hash = reg[Murmur.UserInfo.UserHash]
  473. return user
  474. @protectDjangoErrPage
  475. def setRegistration(self, srvid, mumbleid, name, email, password):
  476. import Murmur
  477. user = {
  478. Murmur.UserInfo.UserName: name.encode( "UTF-8" ),
  479. Murmur.UserInfo.UserEmail: email.encode( "UTF-8" ),
  480. Murmur.UserInfo.UserPassword: password.encode( "UTF-8" ),
  481. }
  482. return self._getIceServerObject( srvid ).updateRegistration( mumbleid, user )
  483. @protectDjangoErrPage
  484. def getAllConf(self, srvid):
  485. conf = self.setUnicodeFlag(self._getIceServerObject(srvid).getAllConf())
  486. info = {}
  487. for key in conf:
  488. if key == "playername" and conf[key]:
  489. # Buggy database transition from 1.1.8 -> 1.2.0
  490. # Store username as "username" field and set playername field to empty
  491. info['username'] = conf[key]
  492. self.setConf( srvid, "playername", "" )
  493. self.setConf( srvid, "username", conf[key] )
  494. else:
  495. info[str(key)] = conf[key]
  496. return info
  497. @protectDjangoErrPage
  498. def getConf(self, srvid, key):
  499. return self._getIceServerObject(srvid).getConf( key )
  500. @protectDjangoErrPage
  501. def setConf(self, srvid, key, value):
  502. if value is None:
  503. value = ''
  504. self._getIceServerObject(srvid).setConf( key, value.encode( "UTF-8" ) )
  505. @protectDjangoErrPage
  506. def getACL(self, srvid, channelid):
  507. return self._getIceServerObject(srvid).getACL(channelid)
  508. @protectDjangoErrPage
  509. def setACL(self, srvid, channelid, acls, groups, inherit):
  510. return self._getIceServerObject(srvid).setACL( channelid, acls, groups, inherit )
  511. @protectDjangoErrPage
  512. def getBans(self, srvid):
  513. return self._getIceServerObject(srvid).getBans()
  514. @protectDjangoErrPage
  515. def setBans(self, srvid, bans):
  516. return self._getIceServerObject(srvid).setBans(bans)
  517. @protectDjangoErrPage
  518. def addBanForSession(self, srvid, sessionid, **kwargs):
  519. session = self.getState(srvid, sessionid)
  520. if "bits" not in kwargs:
  521. kwargs["bits"] = 128
  522. if "start" not in kwargs:
  523. kwargs["start"] = int(time())
  524. if "duration" not in kwargs:
  525. kwargs["duration"] = 3600
  526. return self.addBan(srvid, address=session.address, **kwargs)
  527. @protectDjangoErrPage
  528. def addBan(self, srvid, **kwargs):
  529. for key in kwargs:
  530. if isinstance( kwargs[key], unicode ):
  531. kwargs[key] = kwargs[key].encode("UTF-8")
  532. from Murmur import Ban
  533. srvbans = self.getBans(srvid)
  534. srvbans.append( Ban( **kwargs ) )
  535. return self.setBans(srvid, srvbans)
  536. @protectDjangoErrPage
  537. def removeBan(self, srvid, **kwargs):
  538. return self.setBans(srvid, [
  539. # keep all bans which don't match exactly the one we're looking for
  540. ban for ban in self.getBans(srvid)
  541. # if one of those attr checks fails (-> False), min() is False -> keep the thing
  542. if not min([ getattr(ban, kw) == kwargs[kw] for kw in kwargs ])
  543. ])
  544. @protectDjangoErrPage
  545. def kickUser(self, srvid, userid, reason=""):
  546. return self._getIceServerObject(srvid).kickUser( userid, reason.encode("UTF-8") )
  547. @protectDjangoErrPage
  548. def renameChannel( self, srvid, channelid, name, description ):
  549. srv = self._getIceServerObject(srvid)
  550. state = srv.getChannelState(channelid)
  551. state.name = name.encode("UTF-8")
  552. state.description = description.encode("UTF-8")
  553. srv.setChannelState(state)
  554. @protectDjangoErrPage
  555. def getUptime(self, srvid):
  556. return None
  557. class MumbleCtlIce_122(MumbleCtlIce_120):
  558. @protectDjangoErrPage
  559. def getTexture(self, srvid, mumbleid):
  560. raise ValueError( "This method is buggy in 1.2.2, sorry dude." )
  561. @protectDjangoErrPage
  562. def setTexture(self, srvid, mumbleid, infile):
  563. buf = StringIO()
  564. infile.save( buf, "PNG" )
  565. buf.seek(0)
  566. self._getIceServerObject(srvid).setTexture(mumbleid, buf.read())
  567. @protectDjangoErrPage
  568. def getUptime(self, srvid):
  569. return self._getIceServerObject(srvid).getUptime()
  570. class MumbleCtlIce_123(MumbleCtlIce_120):
  571. @protectDjangoErrPage
  572. def getRawTexture(self, srvid, mumbleid):
  573. return self._getIceServerObject(srvid).getTexture(mumbleid)
  574. @protectDjangoErrPage
  575. def getTexture(self, srvid, mumbleid):
  576. texture = self.getRawTexture(srvid, mumbleid)
  577. if len(texture) == 0:
  578. raise ValueError( "No Texture has been set." )
  579. from StringIO import StringIO
  580. try:
  581. return Image.open( StringIO( texture ) )
  582. except IOError, err:
  583. raise ValueError( err )
  584. @protectDjangoErrPage
  585. def setTexture(self, srvid, mumbleid, infile):
  586. buf = StringIO()
  587. infile.save( buf, "PNG" )
  588. buf.seek(0)
  589. self._getIceServerObject(srvid).setTexture(mumbleid, buf.read())
  590. @protectDjangoErrPage
  591. def getUptime(self, srvid):
  592. return self._getIceServerObject(srvid).getUptime()