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.
 
 
 
 
 
 

515 lines
12 KiB

#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
* Copyright (C) 2009, Michael "Svedrin" Ziegler <diese-addy@funzt-halt.net>
*
* Mumble-Django is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
"""
# Set this to the same path you used in settings.py, or None for auto-detection.
MUMBLE_DJANGO_ROOT = None;
### DO NOT CHANGE ANYTHING BELOW THIS LINE ###
import os, sys
from os.path import join, dirname, abspath, exists
# Path auto-detection
if not MUMBLE_DJANGO_ROOT or not exists( MUMBLE_DJANGO_ROOT ):
MUMBLE_DJANGO_ROOT = dirname(abspath(__file__));
# environment variables
sys.path.append( MUMBLE_DJANGO_ROOT )
sys.path.append( join( MUMBLE_DJANGO_ROOT, 'pyweb' ) )
os.environ['DJANGO_SETTINGS_MODULE'] = 'pyweb.settings'
# If you get an error about Python not being able to write to the Python
# egg cache, the egg cache path might be set awkwardly. This should not
# happen under normal circumstances, but every now and then, it does.
# Uncomment this line to point the egg cache to /tmp.
#os.environ['PYTHON_EGG_CACHE'] = '/tmp/pyeggs'
import locale
import curses
from curses.textpad import Textbox
from django.db.models.fields.related import ForeignKey
from django.db import models
from mumble.models import *
from mumble.forms import *
locale.setlocale(locale.LC_ALL, '')
def getNum( prompt, **kwargs ):
id = None;
while type(id) != int:
print
try:
id = raw_input( "%s >>> " % prompt ).strip();
if id == 'q':
return None;
elif id in kwargs:
return kwargs[id];
id = int( id );
except Exception, instance:
print "Error reading input. Did you type a number?";
print instance;
return id;
def util_editModel( model, blacklist = None ):
while True:
print "Current settings"
print "================"
for field in model._meta.fields:
if blacklist and field.name in blacklist:
continue;
print "#%-5d %-30s %s" % ( model._meta.fields.index( field ), field.verbose_name, getattr( model, field.name ) );
print "================"
print "Enter the index of the parameter you would like to change,"
print "or q to return."
idx = getNum( "Index" );
if idx is None:
save = raw_input( "save? Y/n >>> " );
if not save or save.lower() == 'y':
print "saving changes.";
model.save();
else:
print "NOT saving changes."
return;
field = model._meta.fields[idx];
if blacklist and field.name in blacklist:
print "This field can not be changed.";
elif isinstance( field, ForeignKey ):
print "This is a ForeignKey.";
print field.rel.to.objects.all();
else:
value = None;
while value is None:
print
try:
value = field.to_python( raw_input( "%s >>> " % field.name ).strip() );
except Exception, instance:
print instance;
setattr( model, field.name, value );
def act_serverDetails( server ):
"View or edit server settings."
util_editModel( server, ( "id", "sslcrt", "sslkey" ) );
def act_registeredUsers( server ):
"View or edit user registrations."
mumbleusers_list = server.mumbleuser_set.all();
print "Currently registered accounts";
print "=============================";
for mu in mumbleusers_list:
if mu.owner is not None:
print "#%-5d %-20s Owner: %-20s Admin: %s" % ( mu.id, mu.name, mu.owner.username, mu.getAdmin() );
else:
print "#%-5d %-20s" % ( mu.id, mu.name );
print "=============================";
print "Enter the ID of the account you would like to change, n to create a new one, or q to return."
while True:
idx = getNum( "ID", n=-1 );
if idx is None:
return;
if idx == -1:
mu = MumbleUser();
mu.server = server;
else:
mu = mumbleusers_list.get( id=idx );
util_editModel( mu, ( "id", "mumbleid", "server" ) );
def act_listChannels( server ):
"Display a channel tree."
def printItem( item, level ):
print "%s%s" % ( " "*level, item );
server.rootchan.visit( printItem );
def act_chanDetails( server ):
"Display detailed information about one specific channel."
print "Please choose the channel by entering the according ID (the number in parentheses)."
act_listChannels( server );
id = getNum( "ID" );
if id is None: return;
print "Channel name: %s" % server.channels[id].name
print "Channel ID: %d" % server.channels[id].chanid
print "Users online: %d" % len( server.channels[id].players )
print "Linked chans: %d" % len( server.channels[id].linked )
def cli_chooseServer():
mumble_all = Mumble.objects.all().order_by( 'name', 'id' );
print "Please choose a Server instance by typing the corresponding ID.\n";
for mm in mumble_all:
print "#%d\t%s" % ( mm.id, mm.name );
print "n: Create new instance";
print "q: Exit";
id = getNum( "ID", n = -1 );
if id is None:
return;
elif id == -1:
return Mumble();
return Mumble.objects.get( id=id );
def cli_chooseAction( server ):
actions = {
"LISTCHAN": act_listChannels,
"CHANINFO": act_chanDetails,
"EDITSERVER": act_serverDetails,
"EDITUSERS": act_registeredUsers,
};
while True:
print "What do you want to do?"
keys = actions.keys();
for act in keys:
print "#%-5d %-20s %s" % ( keys.index(act), act, actions[act].__doc__ );
print "q: Return to server selection";
idx = getNum( "Index" );
if idx is None:
return;
# call action function
func = actions[ keys[idx] ]
func( server );
print
def oldmain():
print
while True:
mumble = cli_chooseServer();
if mumble is None:
print "Bye.";
return;
print "Selected %s." % mumble;
print
cli_chooseAction( mumble );
print
class BaseWindow( object ):
tabName = "tehBasez";
def __init__( self, parentwin, mumble, pos_x, pos_y ):
self.pos = ( pos_x, pos_y );
self.win = parentwin.subwin( pos_y, pos_x );
self.mm = mumble;
self.win.keypad(1);
def draw( self ):
self.win.addstr( 1, 1, self.tabName );
def border( self ):
self.win.border();
def enter( self ):
while( True ):
key = self.win.getch();
if key == curses.KEY_UP:
return;
class WndChannels( BaseWindow ):
tabName = 'Channels';
def printItem( self, item, level ):
str = "";
if item.is_server or item.is_channel:
str = "%s (Channel)" % item.name;
else:
str = "%s (Player)" % item.name
self.win.addstr( self.curr_y, 4*level+1, str.encode(locale.getpreferredencoding()) )
self.curr_y += 1;
def draw( self ):
self.curr_y = 1;
self.mm.rootchan.visit( self.printItem );
class WndSettings( BaseWindow ):
tabName = 'Server settings';
blacklist = ( 'id', 'sslkey', 'sslcrt' );
def __init__( self, parentwin, mumble, pos_x, pos_y ):
BaseWindow.__init__( self, parentwin, mumble, pos_x, pos_y );
self.form = MumbleAdminForm( instance=mumble );
self.editors = {};
self.fields = [ mf for mf in mumble._meta.fields if mf.name not in self.blacklist ];
def getFieldHeight( self, field ):
if isinstance( field, models.TextField ):
return 10;
return 1;
def getFieldYPos( self, field ):
ypos = 3;
for curr_field in self.fields:
if curr_field is field:
return ypos;
ypos += self.getFieldHeight( curr_field );
raise ReferenceError( "Field not found!" );
def draw( self ):
curr_y = 3;
for field in self.fields:
value = unicode( getattr( self.mm, field.name ) );
self.win.addstr( curr_y, 1, field.verbose_name.encode(locale.getpreferredencoding()) );
height = self.getFieldHeight( field );
winsize = self.win.getmaxyx();
editwin = self.win.subwin( height, winsize[1]-31, self.pos[1] + curr_y, self.pos[0] + 30 );
editwin.keypad(1);
editwin.addstr( value.encode(locale.getpreferredencoding()) );
editbox = Textbox( editwin );
self.editors[field.name] = ( editwin, editbox );
curr_y += height;
def enter( self ):
self.selIdx = 0;
self.selMax = len( self.fields ) - 1;
while( True ):
# Highlight selected field label
field = self.fields[self.selIdx];
self.win.addstr(
self.getFieldYPos(field), 1,
field.verbose_name.encode(locale.getpreferredencoding()),
curses.A_STANDOUT
);
self.win.refresh();
key = self.win.getch();
if key == curses.KEY_UP and self.selIdx > 0:
self.selIdx -= 1;
elif key == curses.KEY_DOWN and self.selIdx < self.selMax:
self.selIdx += 1;
elif key in ( ord('q'), ord('Q') ):
return;
elif key in ( ord('s'), ord('S') ):
try:
self.mm.save();
except Exception, instance:
msg = unicode( instance );
else:
msg = "Your settings have been saved.";
self.win.addstr( 1, 5, msg.encode(locale.getpreferredencoding()) );
elif key in ( curses.KEY_RIGHT, curses.KEY_ENTER, ord('\n') ):
self.editors[field.name][1].edit();
setattr( self.mm, field.name, field.to_python( self.editors[field.name][1].gather().strip() ) );
self.editors[field.name][0].refresh();
self.win.addstr(
self.getFieldYPos(field), 1,
field.verbose_name.encode(locale.getpreferredencoding())
);
class WndUsers( BaseWindow ):
tabName = 'Registered users';
class MumbleForm( object ):
def __init__( self, parentwin, mumble, pos_x, pos_y ):
self.pos = ( pos_x, pos_y );
self.win = parentwin.subwin( pos_y, pos_x );
self.mm = mumble;
self.win.keypad(1);
self.windows = (
WndChannels( self.win, mumble, pos_x + 2, pos_y + 2 ),
WndSettings( self.win, mumble, pos_x + 2, pos_y + 2 ),
WndUsers( self.win, mumble, pos_x + 2, pos_y + 2 ),
);
self.curridx = 0;
self.currmax = len( self.windows ) - 1;
currwin = property( lambda self: self.windows[self.curridx], None );
def mvwin( self, pos_x, pos_y ):
self.win.mvwin( pos_y, pos_x );
def mvdefault( self ):
self.win.mvwin( self.pos[1], self.pos[0] );
def draw( self ):
self.win.addstr( 0, 0, self.mm.name.encode(locale.getpreferredencoding()) );
def drawTabs( self ):
first = True;
for subwin in self.windows:
flags = 0;
if subwin is self.currwin: flags |= curses.A_STANDOUT;
if first:
self.win.addstr( 1, 2, "%-20s" % subwin.tabName, flags );
first = False;
else:
self.win.addstr( "%-20s" % subwin.tabName, flags );
def enter( self ):
self.drawTabs();
self.currwin.draw();
self.currwin.border();
while( True ):
key = self.win.getch();
if key == curses.KEY_LEFT and self.curridx > 0:
self.curridx -= 1;
elif key == curses.KEY_RIGHT and self.curridx < self.currmax:
self.curridx += 1;
elif key in ( ord('q'), ord('Q'), curses.KEY_UP ):
return;
elif key in ( curses.KEY_ENTER, curses.KEY_DOWN, ord('\n') ):
self.currwin.enter();
self.win.clear();
self.draw();
self.drawTabs();
self.currwin.draw();
self.currwin.border();
self.win.refresh();
def main( stdscr ):
first_y = 3;
curr_y = first_y;
mumbles = list();
for mm in Mumble.objects.all().order_by( "name", "id" ):
mwin = MumbleForm( stdscr, mm, pos_x=5, pos_y=curr_y );
mumbles.append( mwin );
mwin.draw();
curr_y += 1;
selectedIdx = 0;
selectedMax = len(mumbles) - 1;
while( True ):
selectedObj = mumbles[selectedIdx];
# Draw selection marker
stdscr.addstr( first_y + selectedIdx, 3, '*' );
stdscr.refresh();
key = stdscr.getch();
if key == curses.KEY_UP:
stdscr.addstr( first_y + selectedIdx, 3, ' ' );
selectedIdx -= 1;
elif key == curses.KEY_DOWN:
stdscr.addstr( first_y + selectedIdx, 3, ' ' );
selectedIdx += 1;
elif key in ( curses.KEY_RIGHT, curses.KEY_ENTER, ord('\n') ):
stdscr.clear();
selectedObj.mvwin( 5, first_y );
selectedObj.draw();
stdscr.refresh();
selectedObj.enter();
stdscr.clear();
selectedObj.mvdefault();
for mwin in mumbles:
mwin.draw();
elif key in ( ord('q'), ord('Q') ):
return;
if selectedIdx < 0: selectedIdx = 0;
elif selectedIdx > selectedMax: selectedIdx = selectedMax;
if __name__ == '__main__':
#parser = OptionParser();
#parser.add_option( "-v", "--verbose", help="verbose output messages", default=False, action="store_true" );
#parser.add_option( "-n", "--num", help="size of the Matrix", default=4, type = 'int' );
#parser.add_option( "-s", "--sure", help="don't prompt if num >= 10", default=False, action="store_true" );
#options, args = parser.parse_args();
curses.wrapper( main );