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. 41
      htdocs/mumble/style.css
  2. 141
      pyweb/mumble/mmobjects.py
  3. 218
      pyweb/mumble/models.py
  4. 24
      pyweb/mumble/templatetags/mumble_extras.py
  5. 77
      pyweb/mumble/views.py
  6. 17
      template/mumble/channel.htm
  7. 62
      template/mumble/content.htm
  8. 79
      template/mumble/mumble.htm
  9. 25
      template/mumble/player.htm
  10. 9
      template/mumble/server.htm

41
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-size: 8pt;
color: #283E53;
text-decoration: none;
}
td.mumble {
height: 20px;
padding: 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;
}
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;
margin: 0px;
}
span.mumble {
width: 10em;
float:right;
}

141
pyweb/mumble/mmobjects.py

@ -17,99 +17,10 @@
import mctl
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 ):
@ -121,7 +32,8 @@ class mmChannel( object ):
# linked = list();
# linkedIDs = list();
def __init__( self, channelObj, parentChan = None ):
def __init__( self, server, channelObj, parentChan = None ):
self.server = server;
self.players = list();
self.subchans = list();
self.linked = list();
@ -131,19 +43,18 @@ class mmChannel( object ):
self.parent = parentChan;
if self.parent is not None:
self.parent.subchans.append( self );
self.serverId = self.parent.serverId;
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 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(
lambda self: len( self.players ) + sum( [ chan.playerCount for chan in self.subchans ] ),
@ -161,6 +72,25 @@ class mmChannel( object ):
sc.visit( callback, lvl + 1 );
for pl in self.players:
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 );
@ -206,12 +136,9 @@ class mmPlayer( object ):
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)
playerCount = property( lambda self: -1, None );

218
pyweb/mumble/models.py

@ -14,20 +14,19 @@
* GNU General Public License for more details.
"""
from PIL import Image
from struct import pack, unpack
from zlib import compress, decompress
import socket
from PIL import Image
from struct import pack, unpack
from zlib import compress, decompress
from django.contrib.auth.models import User
from django.db import models
from mmobjects import mmServer, mmACL
from django.db import models
from django.conf import settings
from mctl import *
from mmobjects import *
from mctl import *
import socket
class Mumble( models.Model ):
name = models.CharField( 'Server Name', max_length = 200 );
@ -48,71 +47,89 @@ class Mumble( models.Model ):
channel= models.CharField( 'Channel name regex', max_length=200, default=r'[ \-=\w\#\[\]\{\}\(\)\@\|]+' );
defchan= models.IntegerField( 'Default channel', default=0 );
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 ):
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 ):
if dontConfigureMurmur:
# skip murmur configuration, e.g. because we're inserting models for existing servers.
return models.Model.save( self );
# 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:
self.srvid = 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.srvid = self.ctl.newServer();
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:
ctl.setConf( self.srvid, 'port', str(self.port) );
self.ctl.setConf( self.srvid, 'port', str(self.port) );
else:
ctl.setConf( self.srvid, 'port', '' );
self.ctl.setConf( self.srvid, 'port', '' );
if self.users is not None:
ctl.setConf( self.srvid, 'users', str(self.users) );
self.ctl.setConf( self.srvid, 'users', str(self.users) );
else:
ctl.setConf( self.srvid, 'users', '' );
self.ctl.setConf( self.srvid, 'users', '' );
if self.bwidth is not None:
ctl.setConf( self.srvid, 'bandwidth', str(self.bwidth) );
self.ctl.setConf( self.srvid, 'bandwidth', str(self.bwidth) );
else:
ctl.setConf( self.srvid, 'bandwidth', '' );
self.ctl.setConf( self.srvid, 'bandwidth', '' );
# registerHostname needs to take the port no into account
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:
ctl.setConf( self.srvid, 'registerhostname', self.addr );
self.ctl.setConf( self.srvid, 'registerhostname', self.addr );
if self.supw:
ctl.setSuperUserPassword( self.srvid, self.supw );
self.ctl.setSuperUserPassword( self.srvid, self.supw );
self.supw = '';
if self.booted != ctl.isBooted( self.srvid ):
if self.booted != self.ctl.isBooted( self.srvid ):
if self.booted:
ctl.start( self.srvid );
self.ctl.start( self.srvid );
else:
ctl.stop( self.srvid );
self.ctl.stop( self.srvid );
# Now allow django to save the record set
return models.Model.save( self );
def isUserAdmin( self, user ):
if user.is_authenticated():
try:
@ -120,15 +137,83 @@ class Mumble( models.Model ):
except MumbleUser.DoesNotExist:
return False;
return False;
# Deletion handler
def deleteServer( self ):
# Unregister this player in Murmur via ctroller.
#print MumbleCtlBase.newInstance()
MumbleCtlBase.newInstance( self.dbus ).deleteServer(self.srvid)
self.ctl.deleteServer(self.srvid)
@staticmethod
def pre_delete_listener( **kwargs ):
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 ):
mumbleid = models.IntegerField( 'Mumble player_id', editable = False, default = -1 );
@ -137,18 +222,26 @@ class MumbleUser( models.Model ):
server = models.ForeignKey( Mumble );
owner = models.ForeignKey( User, null=True, blank=True );
isAdmin = models.BooleanField( 'Admin on root channel', default = False );
is_server = False;
is_channel = False;
is_player = True;
def __unicode__( self ):
return u"Mumble user %s on %s owned by Django user %s" % ( self.name, self.server, self.owner );
def save( self, dontConfigureMurmur=False ):
if dontConfigureMurmur:
# skip murmur configuration, e.g. because we're inserting models for existing players.
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:
# This is a new user record, so Murmur doesn't know about it yet
self.mumbleid = ctl.registerPlayer(self.server.srvid, self.name);
@ -177,9 +270,11 @@ class MumbleUser( models.Model ):
return models.Model.save( self );
# Admin handlers
def getAdmin( self ):
# 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" ):
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 ):
# 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) );
if not hasattr( acl, "admingroup" ):
@ -202,20 +297,29 @@ class MumbleUser( models.Model ):
ctl.setACL(self.server.srvid, acl);
return value;
# Texture handlers
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 ):
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
def pre_delete_listener( **kwargs ):
kwargs['instance'].unregister();
def unregister( self ):
# 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 ):
if name == 'server':
if self.id is not None and self.server != value:
@ -224,6 +328,8 @@ class MumbleUser( models.Model ):
models.Model.__setattr__( self, name, value );
from django.db.models import signals
signals.pre_delete.connect( Mumble.pre_delete_listener, sender=Mumble );

24
pyweb/mumble/templatetags/mumble_extras.py

@ -13,7 +13,8 @@
* GNU General Public License for more details.
"""
from django import template
from django import template
from django.template.loader import render_to_string
register = template.Library();
@ -35,3 +36,24 @@ def trunc( string, maxlen = 50 ):
return string[:(maxlen - 3)] + "...";
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 );

77
pyweb/mumble/views.py

@ -24,13 +24,8 @@ from django.contrib.auth.decorators import login_required
from models import Mumble, MumbleUser
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 ):
@ -51,7 +46,7 @@ def mumbles( request ):
def show( request, server ):
"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 );
@ -109,17 +104,25 @@ def show( request, server ):
return HttpResponseRedirect( '/mumble/%d' % int(server) );
else:
textureform = MumbleTextureForm();
else:
regform = 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(
'mumble/mumble.htm',
{
'DBaseObject': srv,
'ServerObject': o,
'ChannelTable': Storage.s,
'ChannelTable': channelTable,
'CurrentUserIsAdmin': isAdmin,
'AdminForm': adminform,
'RegForm': regform,
@ -147,59 +150,5 @@ def showTexture( request, server ):
return HttpResponse( buffer.getvalue(), "image/png" );
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>

79
template/mumble/mumble.htm

@ -1,12 +1,10 @@
{% extends "index.htm" %}
{% block headtags %}
<meta http-equiv="refresh" content="30" />
{% endblock %}
{% load mumble_extras %}
{% block Headline %}
{{ ServerObject.rootName }}
{{ DBaseObject.name }}
{% endblock %}
{% block LeftColumn %}
{% include "mumble/content.htm" %}
{{ DBaseObject|chanview:MumbleAccount }}
{% endblock %}
{% block Content %}
<noscript>
@ -34,28 +32,28 @@
<input type="submit" />
</form>
{% 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 %}
</div>
{% if Registered %}
<div id="mumble_texture">
<h2>User Texture</h2>
<p>
You can upload an image that you would like to use as your user texture here.<br />
Your current texture is:<br />
<img src="/mumble/{{DBaseObject.id}}/texture.png" alt="user texture" /><br />
Hint: The texture image <b>needs</b> to be 600x60 in size. If you upload an image with
a different size, it will be resized accordingly.<br />
</p>
<form action="" method="post" enctype="multipart/form-data">
<table>
{{ TextureForm }}
<h2>User Texture</h2>
<p>
You can upload an image that you would like to use as your user texture here.<br />
Your current texture is:<br />
<img src="/mumble/{{DBaseObject.id}}/texture.png" alt="user texture" /><br />
Hint: The texture image <b>needs</b> to be 600x60 in size. If you upload an image with
a different size, it will be resized accordingly.<br />
</p>
<form action="" method="post" enctype="multipart/form-data">
<table>
{{ TextureForm }}
</table>
<input type="hidden" name="mode" value="texture" />
<input type="submit" />
</form>
</div>
</div>
{% endif %}
{% if CurrentUserIsAdmin %}
@ -72,33 +70,33 @@
{% endif %}
{% 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>
<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>
{% 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>
{% 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 %}
<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>
{% endif %}
</div>
{% 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>
{% endif %}
{% endfor %}
@ -138,7 +136,7 @@
]
},
{% for item in ChannelTable %}
{ contentEl: 'mumble_{{ item.1.id }}', id: 'carditem_{{ item.1.id }}' },
{ contentEl: 'mumble_{{ item.id }}', id: 'carditem_{{ item.id }}' },
{% endfor %}
],
});
@ -148,11 +146,12 @@
event.preventDefault();
});
{% 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();
});
{% endfor %}
} );
</script>
<meta http-equiv="refresh" content="300" />
{% 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