Mercurial > libervia-backend
diff src/plugins/plugin_misc_radiocol.py @ 450:afe9cfd2ddbb
plugins: radio collective first draft
author | Goffi <goffi@goffi.org> |
---|---|
date | Thu, 05 Jan 2012 00:21:30 +0100 |
parents | |
children | 5731b038fc7f |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/plugins/plugin_misc_radiocol.py Thu Jan 05 00:21:30 2012 +0100 @@ -0,0 +1,194 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" +SAT plugin for managing Radiocol +Copyright (C) 2009, 2010, 2011 Jérôme Poisson (goffi@goffi.org) + +This program 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 3 of the License, or +(at your option) any later version. + +This program 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +""" + +from logging import debug, info, warning, error +from twisted.words.xish import domish +from twisted.internet import protocol, defer, threads, reactor +from twisted.words.protocols.jabber import client, jid, xmlstream +from twisted.words.protocols.jabber import error as jab_error +from twisted.words.protocols.jabber.xmlstream import IQ +import random + +from zope.interface import implements + +from wokkel import disco, iwokkel, data_form +from sat.tools.xml_tools import dataForm2xml +from sat.tools.games import TarotCard + +from time import time + +try: + from twisted.words.protocols.xmlstream import XMPPHandler +except ImportError: + from wokkel.subprotocols import XMPPHandler + +MESSAGE = '/message' +NC_RADIOCOL = 'http://www.goffi.org/protocol/radiocol' +RADIOC_TAG = 'radiocol' +RADIOC_REQUEST = MESSAGE + '/' + RADIOC_TAG + '[@xmlns="' + NC_RADIOCOL + '"]' + +PLUGIN_INFO = { +"name": "Radio collective plugin", +"import_name": "Radiocol", +"type": "Exp", +"protocols": [], +"dependencies": ["XEP-0045", "XEP-0249"], +"main": "Radiocol", +"handler": "yes", +"description": _("""Implementation of radio collective""") +} + + +class Radiocol(): + + def __init__(self, host): + info(_("Radio collective initialization")) + self.host = host + self.radios={} + host.bridge.addMethod("radiocolLaunch", ".plugin", in_sign='ass', out_sign='', method=self.radiocolLaunch) #args: occupants, profile + host.bridge.addMethod("radiocolCreate", ".plugin", in_sign='ss', out_sign='', method=self.radiocolCreate) #args: room_jid, profile + host.bridge.addSignal("radiocolStarted", ".plugin", signature='ssass') #args: room_jid, referee, occupants, profile + host.trigger.add("MUC user joined", self.userJoinedTrigger) + + def createRadiocolElt(self, to_jid, type="normal"): + type = "normal" if to_jid.resource else "groupchat" + elt = domish.Element(('jabber:client','message')) + elt["to"] = to_jid.full() + elt["type"] = type + elt.addElement((NC_RADIOCOL, RADIOC_TAG)) + return elt + + def __create_started_elt(self): + """Create a game_started domish element""" + started_elt = domish.Element(('','started')) + return started_elt + + def userJoinedTrigger(self, room, user, profile): + """This trigger is used to check if we are waiting people in this room, + and to create a game if everybody is here""" + room_jid = room.occupantJID.userhostJID() + if self.radios.has_key(room_jid): + #we are in a radiocol room, let's start the party ! + mess = self.createRadiocolElt(jid.JID(room_jid.userhost()+'/'+occupant)) + mess.firstChildElement().addChild(self.__create_started_elt()) + self.host.profiles[profile].xmlstream.send(mess) + return True + + def radiocolLaunch(self, occupants, profile_key='@DEFAULT@'): + """Launch a game: helper method to create a room, invite occupants, and create the radiocol + @param occupants: list for occupants jid""" + debug(_('Launching radiocol')) + profile = self.host.memory.getProfileName(profile_key) + if not profile: + error(_("Unknown profile")) + return + + def radiocolRoomJoined(room): + print "radiocolRoomJoined" + _room_jid = room.occupantJID.userhostJID() + for occupant in occupants: + self.host.plugins["XEP-0249"].invite(jid.JID(occupant), room.occupantJID.userhostJID(), {"game":"Radiocol"}, profile) + self.radiocolCreate(_room_jid.userhost(), profile_key=profile) + + def after_init(ignore): + room_name = "sat_radiocol_%s" % self.host.plugins["XEP-0045"].getUniqueName(profile_key) + print "\n\n===> room_name:", room_name + muc_service = None + for service in self.host.memory.getServerServiceEntities("conference", "text", profile): + if not ".irc." in service.userhost(): + #FIXME: + #This awfull ugly hack is here to avoid an issue with openfire: the irc gateway + #use "conference/text" identity (instead of "conference/irc"), there is certainly a better way + #to manage this, but this hack fill do it for test purpose + muc_service = service + break + if not muc_service: + error(_("Can't find a MUC service")) + return + + _jid, xmlstream = self.host.getJidNStream(profile) + d = self.host.plugins["XEP-0045"].join(jid.JID("%s@%s" % (room_name, muc_service.userhost())), _jid.user, {}, profile) + d.addCallback(radiocolRoomJoined) + + client = self.host.getClient(profile) + if not client: + error(_('No client for this profile key: %s') % profile_key) + return + client.client_initialized.addCallback(after_init) + + def radiocolCreate(self, room_jid_param, profile_key='@DEFAULT@'): + """Create a new game + @param room_jid_param: jid of the room + @param profile_key: %(doc_profile_key)s""" + debug (_("Creating Radiocol")) + room_jid = jid.JID(room_jid_param) + profile = self.host.memory.getProfileName(profile_key) + if not profile: + error (_("profile %s is unknown") % profile_key) + return + if self.radios.has_key(room_jid): + warning (_("Radiocol already started in room %s") % room_jid.userhost()) + else: + room_nick = self.host.plugins["XEP-0045"].getRoomNick(room_jid.userhost(), profile) + if not room_nick: + error ('Internal error') + return + referee = room_jid.userhost() + '/' + room_nick + status = {} + occupants_data = {} + self.radios[room_jid.userhost()] = {'referee':referee, 'occupants_data':occupants_data} + mess = self.createRadiocolElt(jid.JID(room_jid.userhost())) + mess.firstChildElement().addChild(self.__create_started_elt()) + self.host.profiles[profile].xmlstream.send(mess) + + def radiocol_game_cmd(self, mess_elt, profile): + from_jid = jid.JID(mess_elt['from']) + room_jid = jid.JID(from_jid.userhost()) + radio_elt = mess_elt.firstChildElement() + radio_data = self.radios[room_jid.userhost()] + occupants_data = radio_data['occupants_data'] + + for elt in radio_elt.elements(): + + if elt.name == 'started': #new game created + self.host.bridge.radiocolStarted(room_jid.userhost(), from_jid.full(), [], profile) #FIXME: add occupants list here ? + else: + error (_('Unmanaged game element: %s') % elt.name) + + def getHandler(self, profile): + return RadiocolHandler(self) + +class RadiocolHandler (XMPPHandler): + implements(iwokkel.IDisco) + + def __init__(self, plugin_parent): + self.plugin_parent = plugin_parent + self.host = plugin_parent.host + + def connectionInitialized(self): + self.xmlstream.addObserver(RADIOC_REQUEST, self.plugin_parent.radiocol_game_cmd, profile = self.parent.profile) + + def getDiscoInfo(self, requestor, target, nodeIdentifier=''): + return [disco.DiscoFeature(NC_RADIOCOL)] + + def getDiscoItems(self, requestor, target, nodeIdentifier=''): + return [] +