Browse Source

merged mmServer class into Mumble model, changed channel viewer to use divs instead of a table (can be more cleanly generated), cleaned up views and removed a whole lot of bad(tm) code

Natenom/support-murmur-13-1446181288462
Michael Ziegler 16 years ago
parent
commit
61b80ddf72
  1. 31
      htdocs/mumble/style.css
  2. 139
      pyweb/mumble/mmobjects.py
  3. 184
      pyweb/mumble/models.py
  4. 22
      pyweb/mumble/templatetags/mumble_extras.py
  5. 75
      pyweb/mumble/views.py
  6. 17
      template/mumble/channel.htm
  7. 62
      template/mumble/content.htm
  8. 55
      template/mumble/mumble.htm
  9. 25
      template/mumble/player.htm
  10. 9
      template/mumble/server.htm

31
htdocs/mumble/style.css

@ -1,29 +1,26 @@
td.mumble img {
padding: 0px;
margin: 0px;
}
a.dingen:link, a.dingen:visited, a.dingen:hover, a.dingen:active {
a.mumble:link, a.mumble:visited, a.mumble:hover, a.mumble:active {
font-weight: bold; font-weight: bold;
font-size: 8pt; font-size: 8pt;
color: #283E53; color: #283E53;
text-decoration: none; text-decoration: none;
} }
td.mumble {
height: 20px;
div.mumble {
background-image: url( /static/mumble/linie_v.png );
background-repeat: repeat-y;
margin-left: 20px;
margin-bottom: 0;
padding-bottom: 0;
}
div.mumble img {
padding: 0px; padding: 0px;
margin: 0px; margin: 0px;
line-height: 6px;
border: none;
} }
div.mumble {
background-color: #FFFFFF;
color: #283E53;
padding: 10px;
margin-top: 20px;
margin-bottom: 20px;
width: 80%;
min-height: 250px;
span.mumble {
width: 10em;
float:right;
} }

139
pyweb/mumble/mmobjects.py

@ -18,98 +18,9 @@ import mctl
import datetime import datetime
from time import time from time import time
from os.path import join
# base = ice.stringToProxy( "Meta:tcp -h 127.0.0.1 -p 6502" );
# srv = Murmur.ServerPrx.checkedCast( base );
# met = Murmur.MetaPrx.checkedCast( base );
class mmServer( object ):
# channels = dict();
# players = dict();
# id = int();
# rootName = str();
def __init__( self, model, ctl ):
#self.dbusObj = serverObj;
self.channels = dict();
self.players = dict();
self.id = model.srvid;
self.rootName = model.name;
self.model = model;
links = dict();
chanlist = ctl.getChannels(model.srvid);
# sometimes, ICE seems to return the Channel list in a weird order.
# itercount prevents infinite loops.
itercount = 0;
maxiter = len(chanlist) * 3;
while len(chanlist) and itercount < maxiter:
itercount += 1;
#print len(chanlist)
for theChan in chanlist:
# Channels - Fields: 0 = ID, 1 = Name, 2 = Parent-ID, 3 = Links
if( theChan[2] == -1 ):
# No parent
self.channels[theChan[0]] = mmChannel( theChan );
elif theChan[2] in self.channels:
# parent already known
self.channels[theChan[0]] = mmChannel( theChan, self.channels[theChan[2]] );
else:
continue;
chanlist.remove( theChan );
self.channels[theChan[0]].serverId = self.id;
# process links - if the linked channels are known, link; else save their ids to link later
for linked in theChan[3]:
if linked in self.channels:
self.channels[theChan[0]].linked.append( self.channels[linked] );
else:
if linked not in links:
links[linked] = list();
links[linked].append( self.channels[theChan[0]] );
#print "Saving link: %s <- %s" % ( linked, self.channels[theChan[0]] );
# check if earlier round trips saved channel ids to be linked to the current channel
if theChan[0] in links:
for targetChan in links[theChan[0]]:
targetChan.linked.append( self.channels[theChan[0]] );
if self.rootName:
self.channels[0].name = self.rootName;
for thePlayer in ctl.getPlayers(model.srvid):
# in DBus
# Players - Fields: 0 = UserID, 6 = ChannelID
self.players[ thePlayer[0] ] = mmPlayer( self.model, thePlayer, self.channels[ thePlayer[6] ] );
playerCount = property(
lambda self: len( self.players ),
None
);
def is_server( self ):
return True;
def is_channel( self ):
return False;
def is_player( self ):
return False;
def __str__( self ):
return '<Server "%s" (%d)>' % ( self.rootName, self.id );
def visit( self, callback, lvl = 0 ):
if not callable( callback ):
raise Exception, "a callback should be callable...";
# call callback first on myself, then visit my root chan
callback( self, lvl );
self.channels[0].visit( callback, lvl + 1 );
from django.utils.http import urlquote
class mmChannel( object ): class mmChannel( object ):
@ -121,7 +32,8 @@ class mmChannel( object ):
# linked = list(); # linked = list();
# linkedIDs = list(); # linkedIDs = list();
def __init__( self, channelObj, parentChan = None ):
def __init__( self, server, channelObj, parentChan = None ):
self.server = server;
self.players = list(); self.players = list();
self.subchans = list(); self.subchans = list();
self.linked = list(); self.linked = list();
@ -131,19 +43,18 @@ class mmChannel( object ):
self.parent = parentChan; self.parent = parentChan;
if self.parent is not None: if self.parent is not None:
self.parent.subchans.append( self ); self.parent.subchans.append( self );
self.serverId = self.parent.serverId;
def parentChannels( self ): def parentChannels( self ):
if self.parent is None or self.parent.is_server() or self.parent.chanid == 0:
if self.parent is None or self.parent.is_server or self.parent.chanid == 0:
return []; return [];
return self.parent.parentChannels() + [self.parent.name]; return self.parent.parentChannels() + [self.parent.name];
def is_server( self ):
return False;
def is_channel( self ):
return True;
def is_player( self ):
return False;
is_server = False;
is_channel = True;
is_player = False;
playerCount = property( playerCount = property(
lambda self: len( self.players ) + sum( [ chan.playerCount for chan in self.subchans ] ), lambda self: len( self.players ) + sum( [ chan.playerCount for chan in self.subchans ] ),
@ -163,6 +74,25 @@ class mmChannel( object ):
pl.visit( callback, lvl + 1 ); pl.visit( callback, lvl + 1 );
def getURL( self, forUser = None ):
# mumble://username@host:port/parentchans/self.name
userstr = "";
if forUser is not None:
userstr = "%s@" % forUser.name;
# create list of all my parents and myself
chanlist = self.parentChannels() + [self.name];
# urlencode channel names
chanlist = [ urlquote( chan ) for chan in chanlist ];
# create a path by joining the channel names
chanpath = join( *chanlist );
return "mumble://%s%s:%d/%s" % ( userstr, self.server.addr, self.server.port, chanpath );
url = property( getURL, None );
class mmPlayer( object ): class mmPlayer( object ):
# muted = bool; # muted = bool;
@ -206,12 +136,9 @@ class mmPlayer( object ):
None None
); );
def is_server( self ):
return False;
def is_channel( self ):
return False;
def is_player( self ):
return True;
is_server = False;
is_channel = False;
is_player = True;
# kept for compatibility to mmChannel (useful for traversal funcs) # kept for compatibility to mmChannel (useful for traversal funcs)
playerCount = property( lambda self: -1, None ); playerCount = property( lambda self: -1, None );

184
pyweb/mumble/models.py

@ -14,6 +14,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
""" """
import socket
from PIL import Image from PIL import Image
from struct import pack, unpack from struct import pack, unpack
from zlib import compress, decompress from zlib import compress, decompress
@ -21,13 +22,11 @@ from zlib import compress, decompress
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.db import models from django.db import models
from mmobjects import mmServer, mmACL
from django.conf import settings from django.conf import settings
from mmobjects import *
from mctl import * from mctl import *
import socket
class Mumble( models.Model ): class Mumble( models.Model ):
name = models.CharField( 'Server Name', max_length = 200 ); name = models.CharField( 'Server Name', max_length = 200 );
@ -49,12 +48,30 @@ class Mumble( models.Model ):
defchan= models.IntegerField( 'Default channel', default=0 ); defchan= models.IntegerField( 'Default channel', default=0 );
booted = models.BooleanField( 'Boot Server', default = True ); booted = models.BooleanField( 'Boot Server', default = True );
def getServerObject( self ):
return mmServer( self, MumbleCtlBase.newInstance( self.dbus ) );
def __init__( self, *args, **kwargs ):
models.Model.__init__( self, *args, **kwargs );
self._ctl = None;
self._channels = None;
self._rootchan = None;
def __unicode__( self ): def __unicode__( self ):
return u'Murmur "%s" (%d)' % ( self.name, self.srvid ); return u'Murmur "%s" (%d)' % ( self.name, self.srvid );
is_server = True;
is_channel = False;
is_player = False;
# Ctl instantiation
def getCtl( self ):
if not self._ctl:
self._ctl = MumbleCtlBase.newInstance( self.dbus );
return self._ctl;
ctl = property( getCtl, None );
def save( self, dontConfigureMurmur=False ): def save( self, dontConfigureMurmur=False ):
if dontConfigureMurmur: if dontConfigureMurmur:
# skip murmur configuration, e.g. because we're inserting models for existing servers. # skip murmur configuration, e.g. because we're inserting models for existing servers.
@ -62,57 +79,57 @@ class Mumble( models.Model ):
# check if this server already exists, if not call newServer and set my srvid first # check if this server already exists, if not call newServer and set my srvid first
ctl = MumbleCtlBase.newInstance( self.dbus );
if self.id is None: if self.id is None:
self.srvid = ctl.newServer();
self.srvid = self.ctl.newServer();
ctl.setConf( self.srvid, 'host', socket.gethostbyname( self.addr ) );
ctl.setConf( self.srvid, 'registername', self.name );
ctl.setConf( self.srvid, 'registerurl', self.url );
ctl.setConf( self.srvid, 'welcometext', self.motd );
ctl.setConf( self.srvid, 'password', self.passwd );
ctl.setConf( self.srvid, 'certificate', self.sslcrt );
ctl.setConf( self.srvid, 'key', self.sslkey );
ctl.setConf( self.srvid, 'obfuscate', str(self.obfsc).lower() );
ctl.setConf( self.srvid, 'playername', self.player );
ctl.setConf( self.srvid, 'channelname', self.channel );
ctl.setConf( self.srvid, 'defaultchannel', str(self.defchan) );
self.ctl.setConf( self.srvid, 'host', socket.gethostbyname( self.addr ) );
self.ctl.setConf( self.srvid, 'registername', self.name );
self.ctl.setConf( self.srvid, 'registerurl', self.url );
self.ctl.setConf( self.srvid, 'welcometext', self.motd );
self.ctl.setConf( self.srvid, 'password', self.passwd );
self.ctl.setConf( self.srvid, 'certificate', self.sslcrt );
self.ctl.setConf( self.srvid, 'key', self.sslkey );
self.ctl.setConf( self.srvid, 'obfuscate', str(self.obfsc).lower() );
self.ctl.setConf( self.srvid, 'playername', self.player );
self.ctl.setConf( self.srvid, 'channelname', self.channel );
self.ctl.setConf( self.srvid, 'defaultchannel', str(self.defchan) );
if self.port is not None: if self.port is not None:
ctl.setConf( self.srvid, 'port', str(self.port) );
self.ctl.setConf( self.srvid, 'port', str(self.port) );
else: else:
ctl.setConf( self.srvid, 'port', '' );
self.ctl.setConf( self.srvid, 'port', '' );
if self.users is not None: if self.users is not None:
ctl.setConf( self.srvid, 'users', str(self.users) );
self.ctl.setConf( self.srvid, 'users', str(self.users) );
else: else:
ctl.setConf( self.srvid, 'users', '' );
self.ctl.setConf( self.srvid, 'users', '' );
if self.bwidth is not None: if self.bwidth is not None:
ctl.setConf( self.srvid, 'bandwidth', str(self.bwidth) );
self.ctl.setConf( self.srvid, 'bandwidth', str(self.bwidth) );
else: else:
ctl.setConf( self.srvid, 'bandwidth', '' );
self.ctl.setConf( self.srvid, 'bandwidth', '' );
# registerHostname needs to take the port no into account # registerHostname needs to take the port no into account
if self.port and self.port != 64738: if self.port and self.port != 64738:
ctl.setConf( self.srvid, 'registerhostname', "%s:%d" % ( self.addr, self.port ) );
self.ctl.setConf( self.srvid, 'registerhostname', "%s:%d" % ( self.addr, self.port ) );
else: else:
ctl.setConf( self.srvid, 'registerhostname', self.addr );
self.ctl.setConf( self.srvid, 'registerhostname', self.addr );
if self.supw: if self.supw:
ctl.setSuperUserPassword( self.srvid, self.supw );
self.ctl.setSuperUserPassword( self.srvid, self.supw );
self.supw = ''; self.supw = '';
if self.booted != ctl.isBooted( self.srvid ):
if self.booted != self.ctl.isBooted( self.srvid ):
if self.booted: if self.booted:
ctl.start( self.srvid );
self.ctl.start( self.srvid );
else: else:
ctl.stop( self.srvid );
self.ctl.stop( self.srvid );
# Now allow django to save the record set # Now allow django to save the record set
return models.Model.save( self ); return models.Model.save( self );
def isUserAdmin( self, user ): def isUserAdmin( self, user ):
if user.is_authenticated(): if user.is_authenticated():
try: try:
@ -121,15 +138,83 @@ class Mumble( models.Model ):
return False; return False;
return False; return False;
# Deletion handler
def deleteServer( self ): def deleteServer( self ):
# Unregister this player in Murmur via ctroller. # Unregister this player in Murmur via ctroller.
#print MumbleCtlBase.newInstance()
MumbleCtlBase.newInstance( self.dbus ).deleteServer(self.srvid)
self.ctl.deleteServer(self.srvid)
@staticmethod @staticmethod
def pre_delete_listener( **kwargs ): def pre_delete_listener( **kwargs ):
kwargs['instance'].deleteServer(); kwargs['instance'].deleteServer();
# Channel lists: flat list
def getChannels( self ):
if self._channels is None:
self._channels = {};
chanlist = self.ctl.getChannels(self.srvid);
links = {};
# sometimes, ICE seems to return the Channel list in a weird order.
# itercount prevents infinite loops.
itercount = 0;
maxiter = len(chanlist) * 3;
while len(chanlist) and itercount < maxiter:
itercount += 1;
for theChan in chanlist:
# Channels - Fields: 0 = ID, 1 = Name, 2 = Parent-ID, 3 = Links
if( theChan[2] == -1 ):
# No parent
self._channels[theChan[0]] = mmChannel( self, theChan );
elif theChan[2] in self.channels:
# parent already known
self._channels[theChan[0]] = mmChannel( self, theChan, self.channels[theChan[2]] );
else:
continue;
chanlist.remove( theChan );
self._channels[theChan[0]].serverId = self.id;
# process links - if the linked channels are known, link; else save their ids to link later
for linked in theChan[3]:
if linked in self._channels:
self._channels[theChan[0]].linked.append( self._channels[linked] );
else:
if linked not in links:
links[linked] = list();
links[linked].append( self._channels[theChan[0]] );
# check if earlier round trips saved channel ids to be linked to the current channel
if theChan[0] in links:
for targetChan in links[theChan[0]]:
targetChan.linked.append( self._channels[theChan[0]] );
self._channels[0].name = self.name;
self.players = {};
for thePlayer in self.ctl.getPlayers(self.srvid):
# Players - Fields: 0 = UserID, 6 = ChannelID
self.players[ thePlayer[0] ] = mmPlayer( self, thePlayer, self._channels[ thePlayer[6] ] );
return self._channels;
channels = property( getChannels, None );
rootchan = property( lambda self: self.channels[0], None );
def getURL( self, forUser = None ):
# mumble://username@host:port/
userstr = "";
if forUser is not None:
userstr = "%s@" % forUser.name;
return "mumble://%s%s:%d/" % ( userstr, self.addr, self.port );
url = property( getURL, None );
class MumbleUser( models.Model ): class MumbleUser( models.Model ):
mumbleid = models.IntegerField( 'Mumble player_id', editable = False, default = -1 ); mumbleid = models.IntegerField( 'Mumble player_id', editable = False, default = -1 );
name = models.CharField( 'User name and Login', max_length = 200 ); name = models.CharField( 'User name and Login', max_length = 200 );
@ -138,16 +223,24 @@ class MumbleUser( models.Model ):
owner = models.ForeignKey( User, null=True, blank=True ); owner = models.ForeignKey( User, null=True, blank=True );
isAdmin = models.BooleanField( 'Admin on root channel', default = False ); isAdmin = models.BooleanField( 'Admin on root channel', default = False );
is_server = False;
is_channel = False;
is_player = True;
def __unicode__( self ): def __unicode__( self ):
return u"Mumble user %s on %s owned by Django user %s" % ( self.name, self.server, self.owner ); return u"Mumble user %s on %s owned by Django user %s" % ( self.name, self.server, self.owner );
def save( self, dontConfigureMurmur=False ): def save( self, dontConfigureMurmur=False ):
if dontConfigureMurmur: if dontConfigureMurmur:
# skip murmur configuration, e.g. because we're inserting models for existing players. # skip murmur configuration, e.g. because we're inserting models for existing players.
return models.Model.save( self ); return models.Model.save( self );
# Before the record set is saved, update Murmur via ctroller.
ctl = MumbleCtlBase.newInstance( self.server.dbus );
# Before the record set is saved, update Murmur via controller.
ctl = self.server.ctl;
if self.id is None: if self.id is None:
# This is a new user record, so Murmur doesn't know about it yet # This is a new user record, so Murmur doesn't know about it yet
@ -177,9 +270,11 @@ class MumbleUser( models.Model ):
return models.Model.save( self ); return models.Model.save( self );
# Admin handlers
def getAdmin( self ): def getAdmin( self ):
# Get ACL of root Channel, get the admin group and see if I'm in it # Get ACL of root Channel, get the admin group and see if I'm in it
acl = mmACL( 0, MumbleCtlBase.newInstance( self.server.dbus ).getACL(self.server.srvid, 0) );
acl = mmACL( 0, self.server.ctl.getACL(self.server.srvid, 0) );
if not hasattr( acl, "admingroup" ): if not hasattr( acl, "admingroup" ):
raise ValueError( "The admin group was not found in the ACL's groups list!" ); raise ValueError( "The admin group was not found in the ACL's groups list!" );
@ -187,7 +282,7 @@ class MumbleUser( models.Model ):
def setAdmin( self, value ): def setAdmin( self, value ):
# Get ACL of root Channel, get the admin group and see if I'm in it # Get ACL of root Channel, get the admin group and see if I'm in it
ctl = MumbleCtlBase.newInstance( self.server.dbus );
ctl = self.server.ctl;
acl = mmACL( 0, ctl.getACL(self.server.srvid, 0) ); acl = mmACL( 0, ctl.getACL(self.server.srvid, 0) );
if not hasattr( acl, "admingroup" ): if not hasattr( acl, "admingroup" ):
@ -202,11 +297,17 @@ class MumbleUser( models.Model ):
ctl.setACL(self.server.srvid, acl); ctl.setACL(self.server.srvid, acl);
return value; return value;
# Texture handlers
def getTexture( self ): def getTexture( self ):
return MumbleCtlBase.newInstance( self.server.dbus ).getTexture(self.server.srvid, self.mumbleid);
return self.server.ctl.getTexture(self.server.srvid, self.mumbleid);
def setTexture( self, infile ): def setTexture( self, infile ):
MumbleCtlBase.newInstance( self.server.dbus ).setTexture(self.server.srvid, self.mumbleid, infile)
self.server.ctl.setTexture(self.server.srvid, self.mumbleid, infile)
# Deletion handler
@staticmethod @staticmethod
def pre_delete_listener( **kwargs ): def pre_delete_listener( **kwargs ):
@ -214,7 +315,10 @@ class MumbleUser( models.Model ):
def unregister( self ): def unregister( self ):
# Unregister this player in Murmur via dbus. # Unregister this player in Murmur via dbus.
MumbleCtlBase.newInstance( self.server.dbus ).unregisterPlayer(self.server.srvid, self.mumbleid)
self.server.ctl.unregisterPlayer(self.server.srvid, self.mumbleid)
# "server" field protection
def __setattr__( self, name, value ): def __setattr__( self, name, value ):
if name == 'server': if name == 'server':
@ -224,6 +328,8 @@ class MumbleUser( models.Model ):
models.Model.__setattr__( self, name, value ); models.Model.__setattr__( self, name, value );
from django.db.models import signals from django.db.models import signals
signals.pre_delete.connect( Mumble.pre_delete_listener, sender=Mumble ); signals.pre_delete.connect( Mumble.pre_delete_listener, sender=Mumble );

22
pyweb/mumble/templatetags/mumble_extras.py

@ -14,6 +14,7 @@
""" """
from django import template from django import template
from django.template.loader import render_to_string
register = template.Library(); register = template.Library();
@ -35,3 +36,24 @@ def trunc( string, maxlen = 50 ):
return string[:(maxlen - 3)] + "..."; return string[:(maxlen - 3)] + "...";
register.filter( 'trunc', trunc ); register.filter( 'trunc', trunc );
### FILTER: chanview -- renders an mmChannel / mmPlayer object with the correct template.
def chanview( obj, user = None ):
if obj.is_server:
return render_to_string( 'mumble/server.htm', { 'Server': obj, 'MumbleAccount': user } );
elif obj.is_channel:
return render_to_string( 'mumble/channel.htm', { 'Channel': obj, 'MumbleAccount': user } );
elif obj.is_player:
return render_to_string( 'mumble/player.htm', { 'Player': obj, 'MumbleAccount': user } );
register.filter( 'chanview', chanview );
### FILTER: chanurl -- creates a connection URL and takes the user's login into account
def chanurl( obj, user ):
return obj.getURL( user );
register.filter( 'chanurl', chanurl );

75
pyweb/mumble/views.py

@ -24,13 +24,8 @@ from django.contrib.auth.decorators import login_required
from models import Mumble, MumbleUser from models import Mumble, MumbleUser
from forms import * from forms import *
from mmobjects import mmServer, mmChannel
from mmobjects import *
# Handler class for all Server specific views
class Storage( object ):
s = list();
r = None;
def mumbles( request ): def mumbles( request ):
@ -51,7 +46,7 @@ def mumbles( request ):
def show( request, server ): def show( request, server ):
"Displays the channel list for the given Server ID." "Displays the channel list for the given Server ID."
srv, o = createChannelList( server );
srv = get_object_or_404( Mumble, id=server );
isAdmin = srv.isUserAdmin( request.user ); isAdmin = srv.isUserAdmin( request.user );
@ -114,12 +109,20 @@ def show( request, server ):
regform = None; regform = None;
textureform = None; textureform = None;
# ChannelTable is a somewhat misleading name, as it actually contains channels and players.
channelTable = [];
for id in srv.channels:
if id != 0:
channelTable.append( srv.channels[id] );
for id in srv.players:
channelTable.append( srv.players[id] );
return render_to_response( return render_to_response(
'mumble/mumble.htm', 'mumble/mumble.htm',
{ {
'DBaseObject': srv, 'DBaseObject': srv,
'ServerObject': o,
'ChannelTable': Storage.s,
'ChannelTable': channelTable,
'CurrentUserIsAdmin': isAdmin, 'CurrentUserIsAdmin': isAdmin,
'AdminForm': adminform, 'AdminForm': adminform,
'RegForm': regform, 'RegForm': regform,
@ -147,59 +150,5 @@ def showTexture( request, server ):
return HttpResponse( buffer.getvalue(), "image/png" ); return HttpResponse( buffer.getvalue(), "image/png" );
raise Http404(); raise Http404();
def showContent( server, user = None ):
"Renders and returns the channel list for the given Server ID."
from django.template import Context, loader
srv, o = createChannelList( server );
mumbleAcc = None;
if user.is_authenticated():
mmUsers = MumbleUser.objects.filter( owner = user );
if mmUsers:
mumbleAcc = mmUsers[0];
t_content = loader.get_template( 'mumble/content.htm' );
c_content = Context( {
'DBaseObject': srv,
'ServerObject': o,
'ChannelTable': Storage.s,
'user': user,
'mumbleAccount': mumbleAcc,
"CurrentUserIsAdmin": srv.isUserAdmin( request.user ),
'MumbleActive': True,
} );
r_content = t_content.render( c_content );
return r_content;
def createChannelList( server ):
"Renders the channel list."
srv = get_object_or_404( Mumble, id=server );
o = srv.getServerObject();
Storage.s = list();
Storage.r = o.channels[0];
o.channels[0].visit( renderListItem, 0 );
return srv, o;
def renderListItem( item, level ):
"Stores a line in the channel list."
if item == Storage.r:
return;
# Filter channels that don't have players in them and are not a subchannel of root
if level > 1 and item.playerCount == 0:
# I used to test if item is an instance of mmChannel here. For some reason, that doesn't work. Dunno why.
return;
if isinstance( item, mmChannel ):
Storage.s.append( ( level, item, item.parentChannels() ) );
else:
Storage.s.append( ( level, item ) );

17
template/mumble/channel.htm

@ -0,0 +1,17 @@
{% load mumble_extras %}
<div class="mumble">
<img src="/static/mumble/knoten_v.png" />
{% if Channel.linked %}
<img src="/static/mumble/channel_linked.png" alt="linked channel" />
{% else %}
<img src="/static/mumble/channel.png" alt="channel" />
{% endif %}
<a href="{{ Channel|chanurl:MumbleAccount }}" class="mumble" id="link_{{ Channel.id }}" title="{{ Channel.name }}">
{{ Channel.name|trunc:30 }}
</a>
{% for sub in Channel.subchans %}
{{ sub|chanview:MumbleAccount }}
{% endfor %}
{% for player in Channel.players %}{{ player|chanview }}{% endfor %}
</div>

62
template/mumble/content.htm

@ -1,62 +0,0 @@
{% load mumble_extras %}
<div class="mumble">
<table cellspacing="0" cellpadding="0" style="width:100%; border:none">
<tr>
<td class="mumble" id="server" colspan="2">
<img src="/static/mumble/mumble.16x16.png" alt="mumble" />
<a href="mumble://{% if MumbleAccount %}{{ MumbleAccount.name }}@{% endif %}{{ DBaseObject.addr }}:{{ DBaseObject.port }}/" class="dingen" id="link_server">
{{ ServerObject.rootName }}
</a>
</tr>
{% for item in ChannelTable %}
<tr>
<td class="mumble" id="{{ item.1.id }}">
<span {% spaceless %}
{% if item.1.is_channel %}
class="mumble_channel"
{% else %}
class="mumble_player"
{% endif %}
{% endspaceless %} title="{{ item.1.name }}">
{% spaceless %}
{% for num in item.0|mrange %}
<img src="/static/mumble/linie_v_trans.png" alt="|" />
{% endfor %}
<img src="/static/mumble/knoten_v_trans.png" alt="+-" />
{% endspaceless %}
{% if item.1.is_player %}
<img src="/static/mumble/talking_off.png" alt="player" />
<a id="link_{{ item.1.id }}" class="dingen" href="#" title="{{ item.1.name }}">{{ item.1.name|trunc:30 }}</a>
{% else %}
{% if item.1.linked %}
<img src="/static/mumble/channel_linked.png" alt="linked channel"/>
{% else %}
<img src="/static/mumble/channel.png" alt="channel"/>
{% endif %}
<a href="mumble://{% if MumbleAccount %}{{ MumbleAccount.name }}@{% endif %}{{ DBaseObject.addr }}:{{ DBaseObject.port }}/{% for chan in item.2 %}{{ chan|urlencode }}/{% endfor %}{{ item.1.name|urlencode }}" class="dingen" id="link_{{ item.1.id }}" title="{{ item.1.name }}">{{ item.1.name|trunc:30 }}</a>
{% endif %}
</span>
</td>
<td class="mumble">
{% if item.1.userid %}
{% if item.1.isAuthed %}
<img src="/static/mumble/authenticated.png" alt="authed" title="Authenticated" />
{% endif %}
{% if item.1.muted %}
<img src="/static/mumble/muted_server.png" alt="muted" title="Muted by server" />
{% endif %}
{% if item.1.deafened %}
<img src="/static/mumble/deafened_server.png" alt="deafened" title="Deafened by server" />
{% endif %}
{% if item.1.selfmuted %}
<img src="/static/mumble/muted_self.png" alt="self-muted" title="Muted by themselves" />
{% endif %}
{% if item.1.selfdeafened %}
<img src="/static/mumble/deafened_self.png" alt="self-deafened" title="Deafened by themselves" />
{% endif %}
{% endif %}
</td>
</tr>
{% endfor %}
</table>
</div>

55
template/mumble/mumble.htm

@ -1,12 +1,10 @@
{% extends "index.htm" %} {% extends "index.htm" %}
{% block headtags %}
<meta http-equiv="refresh" content="30" />
{% endblock %}
{% load mumble_extras %}
{% block Headline %} {% block Headline %}
{{ ServerObject.rootName }}
{{ DBaseObject.name }}
{% endblock %} {% endblock %}
{% block LeftColumn %} {% block LeftColumn %}
{% include "mumble/content.htm" %}
{{ DBaseObject|chanview:MumbleAccount }}
{% endblock %} {% endblock %}
{% block Content %} {% block Content %}
<noscript> <noscript>
@ -34,7 +32,7 @@
<input type="submit" /> <input type="submit" />
</form> </form>
{% else %} {% else %}
<p>You need to be <a href="/accounts/login">logged in</a> to be able to register an account on this Mumble server.</p>
<p>You need to be <a href="/accounts/login?next=%2Fmumble%2F{{ DBaseObject.id }}">logged in</a> to be able to register an account on this Mumble server.</p>
{% endif %} {% endif %}
</div> </div>
@ -72,33 +70,33 @@
{% endif %} {% endif %}
{% for item in ChannelTable %} {% for item in ChannelTable %}
{% if item.1.is_player %}
<div id="mumble_{{ item.1.id }}" class="x-hide-display">
<h2>Player {{ item.1.name }}</h2>
{% if item.is_player %}
<div id="mumble_{{ item.id }}" class="x-hide-display">
<h2>Player {{ item.name }}</h2>
<ul> <ul>
<li>Online since {{item.1.onlinesince|time:"H:i"}}</li>
<li>Authenticated: {% if item.1.isAuthed %}Yes{% else %}No{% endif %}</li>
<li>Admin: {% if item.1.isAdmin %}Yes{% else %}No{% endif %}</li>
<li>Muted: {% if item.1.muted %}Yes{% else %}No{% endif %}</li>
<li>Deafened: {% if item.1.deafened %}Yes{% else %}No{% endif %}</li>
<li>Self-Muted: {% if item.1.selfmuted %}Yes{% else %}No{% endif %}</li>
<li>Self-Deafened: {% if item.1.selfdeafened %}Yes{% else %}No{% endif %}</li>
<li>Online since {{item.onlinesince|time:"H:i"}}</li>
<li>Authenticated: {% if item.isAuthed %}Yes{% else %}No{% endif %}</li>
<li>Admin: {% if item.isAdmin %}Yes{% else %}No{% endif %}</li>
<li>Muted: {% if item.muted %}Yes{% else %}No{% endif %}</li>
<li>Deafened: {% if item.deafened %}Yes{% else %}No{% endif %}</li>
<li>Self-Muted: {% if item.selfmuted %}Yes{% else %}No{% endif %}</li>
<li>Self-Deafened: {% if item.selfdeafened %}Yes{% else %}No{% endif %}</li>
</ul> </ul>
{% if item.1.mumbleuser and item.1.mumbleuser.owner %}
<h2>User {{ item.1.mumbleuser.owner.username|capfirst }}</h2>
{% if item.mumbleuser and item.mumbleuser.owner %}
<h2>User {{ item.mumbleuser.owner.username|capfirst }}</h2>
<ul> <ul>
{% if item.1.mumbleuser.owner.first_name and item.1.mumbleuser.owner.last_name %}
<li>Full Name: {{ item.1.mumbleuser.owner.first_name }} {{ item.1.mumbleuser.owner.last_name }}</li>
{% if item.mumbleuser.owner.first_name and item.mumbleuser.owner.last_name %}
<li>Full Name: {{ item.mumbleuser.owner.first_name }} {{ item.mumbleuser.owner.last_name }}</li>
{% endif %} {% endif %}
<li>Admin: {% if item.1.mumbleuser.owner.is_staff %}Yes{% else %}No{% endif %}</li>
<li>Sign-up date: {{ item.1.mumbleuser.owner.date_joined }}</li>
<li>Admin: {% if item.mumbleuser.owner.is_staff %}Yes{% else %}No{% endif %}</li>
<li>Sign-up date: {{ item.mumbleuser.owner.date_joined }}</li>
</ul> </ul>
{% endif %} {% endif %}
</div> </div>
{% else %} {% else %}
<div id="mumble_{{ item.1.id }}" class="x-hide-display">
<h2>Channel {{ item.1.name }}</h2>
<a href="mumble://{% if MumbleAccount %}{{ MumbleAccount.name }}@{% endif %}{{ DBaseObject.addr }}:{{ DBaseObject.port }}/{% for chan in item.2 %}{{ chan|urlencode }}/{% endfor %}{{ item.1.name|urlencode }}" class="dingen">Connect</a>
<div id="mumble_{{ item.id }}" class="x-hide-display">
<h2>Channel {{ item.name }}</h2>
<a href="{{ item|chanurl:MumbleAccount }}" class="mumble">Connect</a>
</div> </div>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
@ -138,7 +136,7 @@
] ]
}, },
{% for item in ChannelTable %} {% for item in ChannelTable %}
{ contentEl: 'mumble_{{ item.1.id }}', id: 'carditem_{{ item.1.id }}' },
{ contentEl: 'mumble_{{ item.id }}', id: 'carditem_{{ item.id }}' },
{% endfor %} {% endfor %}
], ],
}); });
@ -148,11 +146,12 @@
event.preventDefault(); event.preventDefault();
}); });
{% for item in ChannelTable %} {% for item in ChannelTable %}
Ext.get( 'link_{{ item.1.id }}' ).on( 'click', function( event, target ){
cardpanel.layout.setActiveItem( 'carditem_{{ item.1.id }}' );
Ext.get( 'link_{{ item.id }}' ).on( 'click', function( event, target ){
cardpanel.layout.setActiveItem( 'carditem_{{ item.id }}' );
event.preventDefault(); event.preventDefault();
}); });
{% endfor %} {% endfor %}
} ); } );
</script> </script>
<meta http-equiv="refresh" content="300" />
{% endblock %} {% endblock %}

25
template/mumble/player.htm

@ -0,0 +1,25 @@
{% load mumble_extras %}
<div class="mumble">
<span class="mumble">
{% if Player.isAuthed %}
<img src="/static/mumble/authenticated.png" alt="authed" title="Authenticated" />
{% endif %}
{% if Player.muted %}
<img src="/static/mumble/muted_server.png" alt="muted" title="Muted by server" />
{% endif %}
{% if Player.deafened %}
<img src="/static/mumble/deafened_server.png" alt="deafened" title="Deafened by server" />
{% endif %}
{% if Player.selfmuted %}
<img src="/static/mumble/muted_self.png" alt="self-muted" title="Muted by themselves" />
{% endif %}
{% if Player.selfdeafened %}
<img src="/static/mumble/deafened_self.png" alt="self-deafened" title="Deafened by themselves" />
{% endif %}
</span>
<span>
<img src="/static/mumble/knoten_v.png" />
<img src="/static/mumble/talking_off.png" alt="Player" />
<a id="link_{{ Player.id }}" class="mumble" href="#" title="{{ Player.name }}">{{ Player.name|trunc:30 }}</a>
</span>
</div>

9
template/mumble/server.htm

@ -0,0 +1,9 @@
{% load mumble_extras %}
<div style="margin-left: 20px">
<img src="/static/mumble/mumble.16x16.png" alt="server" />
<a class="mumble" id="link_server" href="{{ Server|chanurl:MumbleAccount }}">{{ Server.name|trunc:30 }}</a>
</div>
{% for sub in Server.rootchan.subchans %}
{{ sub|chanview:MumbleAccount }}
{% endfor %}
{% for player in Server.rootchan.players %}{{ player|chanview }}{% endfor %}
Loading…
Cancel
Save