コード例 #1
0
ファイル: conversation.py プロジェクト: c0ns0le/droned
class ChatRoom(Entity):
    """models the actions needed to interact in a chatroom"""
    implements(IDroneModelChatRoom)
    jabber = property(lambda s: services.getService('jabber'))
    jabber_config = property(lambda s: s.jabber.SERVICECONFIG)
    room = property(lambda s: s._room)
    jid = property(lambda s: '%s@%s' % \
            (s.room, s.jabber_config.JABBER_CHAT_SERVICE))
    nick = property(lambda s: s.jabber_config.JABBER_CHAT_NICK)

    def __init__(self, room):
        self._room = room
        self.conversation = Conversation(self.jid)
        self.conversation.groupChat = True

    def join(self):
        """join the chat room"""
        self.jabber.joinChatRoom(self.room)

    def leave(self):
        """leave the chat room"""
        self.jabber.leaveChatRoom(self.jid)

    def hear(self, message):
        """Only pay attention to messages that start with my chat nick"""
        if message.lower().split()[0] == self.nick:
            message = message[len(self.nick):].strip()
            self.conversation.hear(message)
コード例 #2
0
ファイル: __init__.py プロジェクト: DroneD/droned
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
###############################################################################

import os, re
from types import FunctionType
from droned.logging import log, err
from droned.errors import ServiceNotAvailable
import config
import services

try: #handle abstaction to service config
    jabber_service = services.getService('jabber')
    jabber_config = jabber_service.SERVICECONFIG
except ServiceNotAvailable:
    jabber_service = None
    jabber_config = None

#holds the responders
responders = {}

def loadAll():
    """loads all of the responders"""
    responders.clear()
    my_dir = os.path.dirname(__file__)
    for filename in os.listdir(my_dir):
        if not filename.endswith('.py'): continue
        if filename == '__init__.py': continue
コード例 #3
0
def running():
    return bool(service) and getService(dependant_service).running
コード例 #4
0
def get_resource():
    """get the webserver resource from the droned service"""
    #thanks to twisted interface definitions we know whic argument is
    #the site object in which the original resource is attached.
    return getService(dependant_service).service.args[1].resource
コード例 #5
0
ファイル: jabber.py プロジェクト: DroneD/droned
#   See the License for the specific language governing permissions and
#   limitations under the License.
###############################################################################

from twisted.internet import task
from droned.models.conversation import Conversation, ChatRoom
from droned.models.environment import env
from droned.models.event import Event
from droned.models.team import Team
from droned.models.server import Server
from droned.errors import ServiceNotAvailable
import services
import config

try:
   jabber = services.getService('jabber')
   jconfig = jabber.SERVICECONFIG
except ServiceNotAvailable:
   jabber = None
   jconfig = None

def notify_online(event):
    ready = env.ready
    for agent in Team('support').agents:
        agent.tell("%s droned reporting for duty." % config.ROMEO_ENV_NAME)
        if not ready:
            agent.tell("The environment is still being scanned, please wait...")

    def check():
        if env.ready:
            for agent in Team('support').agents:
コード例 #6
0
ファイル: team.py プロジェクト: c0ns0le/droned
class Team(Entity):
    jabber_service = property(lambda s: services.getService('jabber'))
    jabber_config = property(lambda s: s.jabber_service.SERVICECONFIG)
    availableAgents = property(
        lambda s: (agent for agent in s.agents if agent.available))
    available = property(lambda self: any(self.availableAgents))
    busy = property(lambda s: not s.available)
    rosterPath = property(lambda s: '%s/%s' %
                          (s.jabber_config.JABBER_TEAM_ROSTER, s.name))
    pendingIssues = property(lambda s: \
          (i for i in Issue.objects if not i.resolved and i.assignedTo == s))

    def __init__(self, name):
        self.name = name
        self.agents = set()
        self.worker = LoopingCall(self.workNextIssue)
        self.worker.start(5)
        self.loadRoster()

    def __getstate__(self):
        return {
            'name': self.name,
            'members': set(agent.jid for agent in self.agents),
        }

    @staticmethod
    def construct(state):
        team = Team(state['name'])
        team.agents = set(SupportAgent(jid) for jid in state['members'])
        return team

    def loadRoster(self):
        if not os.path.exists(self.rosterPath):
            log('no roster exists for the %s team, so it has no members!' %
                self.name,
                warning=True)
            return
        for line in open(self.rosterPath):
            line = line.strip()
            if not line or line.startswith('#'): continue
            jid = line
            agent = SupportAgent(jid)
            self.agents.add(agent)

    def saveRoster(self):
        jids = [agent.jid for agent in self.agents]
        content = '\n'.join(jids) + '\n'

        def blockingWrite():
            roster = open(self.rosterPath, 'w')
            roster.write(content)
            roster.close()

        config.reactor.callInThread(blockingWrite)

    def addMember(self, jid):
        self.agents.add(SupportAgent(jid))
        self.saveRoster()

    def removeMember(self, jid):
        self.agents.discard(SupportAgent(jid))
        self.saveRoster()

    def workNextIssue(self):
        while any(self.availableAgents) and any(self.pendingIssues):
            issue = self.pendingIssues.next()
            agent = self.availableAgents.next()
            agent.engage(issue)
            issue.whenResolved(lambda result: self.workNextIssue() or result)

    def notify(self, message):
        for agent in self.agents:
            agent.tell("<b>%s team notification:</b> %s" %
                       (self.name, message))
コード例 #7
0
ファイル: jabber.py プロジェクト: c0ns0le/droned
#   See the License for the specific language governing permissions and
#   limitations under the License.
###############################################################################

from twisted.internet import task
from droned.models.conversation import Conversation, ChatRoom
from droned.models.environment import env
from droned.models.event import Event
from droned.models.team import Team
from droned.models.server import Server
from droned.errors import ServiceNotAvailable
import services
import config

try:
    jabber = services.getService('jabber')
    jconfig = jabber.SERVICECONFIG
except ServiceNotAvailable:
    jabber = None
    jconfig = None


def notify_online(event):
    ready = env.ready
    for agent in Team('support').agents:
        agent.tell("%s droned reporting for duty." % config.ROMEO_ENV_NAME)
        if not ready:
            agent.tell(
                "The environment is still being scanned, please wait...")

    def check():
コード例 #8
0
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
###############################################################################

import os, re
from types import FunctionType
from droned.logging import log, err
from droned.errors import ServiceNotAvailable
import config
import services

try:  #handle abstaction to service config
    jabber_service = services.getService('jabber')
    jabber_config = jabber_service.SERVICECONFIG
except ServiceNotAvailable:
    jabber_service = None
    jabber_config = None

#holds the responders
responders = {}


def loadAll():
    """loads all of the responders"""
    responders.clear()
    my_dir = os.path.dirname(__file__)
    for filename in os.listdir(my_dir):
        if not filename.endswith('.py'): continue
コード例 #9
0
ファイル: conversation.py プロジェクト: c0ns0le/droned
class Conversation(Entity):
    """model of a conversation"""
    implements(IDroneModelConversation)
    jabber = property(lambda s: services.getService('jabber'))
    jabber_config = property(lambda s: s.jabber.SERVICECONFIG)
    deferredAnswer = None
    expectedAnswers = ()
    askingQuestion = property(lambda s: s.deferredAnswer is not None)
    groupChat = False
    authorized = property(lambda s: \
            s._authorized or s.buddy == s.jabber_config.DEPUTY)
    _authorized = False
    idleTime = property(lambda s: time.time() - s.lastMessageReceived)
    responsive = property(lambda s: \
            s.idleTime < s.jabber_config.CONVERSATION_RESPONSE_PERIOD)
    online = True  #TODO: need to safely track this state in Jabber service
    buddy = property(lambda s: s._buddy)
    buddyName = property(lambda s: s._buddyName)
    serializable = True

    def __init__(self, buddy):
        self._buddy = buddy
        self._buddyName = buddy.split('@')[0]
        self.notificationQueue = []
        self.lastMessageReceived = 0.0
        self.context = ConversationContext(self)

    def __getstate__(self):
        return {
            'buddy': self.buddy,
            'authorized': self.authorized,
            'subscriptions': list(self.context.get('subscriptions', []))
        }

    @staticmethod
    def construct(state):
        conversation = Conversation(state['buddy'])
        conversation.context['subscriptions'] = set(state['subscriptions'])
        if state.get('authorized'):
            conversation.grantAuthorization(notify=False)
        for name in state['subscriptions']:
            Event(name).subscribe(conversation.notify)
        return conversation

    @staticmethod
    def byName(name):
        """Convenience method for looking up Conversation objects 
           by short or long names
        """
        for conversation in Conversation.objects:
            if conversation.buddy == name:  #full jid
                return conversation
            elif conversation.buddyName == name:  #short username
                return conversation

    def say(self, message, **options):
        "Send a message to the remote party"
        options['groupChat'] = self.groupChat
        self.jabber.sendMessage(self.buddy, message, **options)

    def hear(self, message):
        "Receive a message from the remote party"
        self.lastMessageReceived = time.time()

        for answer in self.expectedAnswers:
            if message == answer:
                d = self.deferredAnswer
                del self.expectedAnswers
                #Clear this before the callback in case it asks another question
                del self.deferredAnswer
                d.callback(answer)
                return
        try:
            dispatch(self, message)
        except NoMatch:
            self.say(
                "Sorry I don't know what you mean by that. Say <b>?</b> for help."
            )
        except:
            self.say(Failure().getTraceback(), useHTML=False)

    def ask(self, question, answers):
        """Sends a message and returns a Deferred that fires whenever one 
           of the given answers is received
        """
        if self.askingQuestion:
            raise AlreadyAskingQuestion(self.context['question'],
                                        self.expectedAnswers)
        self.say(question)
        self.context['question'] = question
        self.context['expectedAnswers'] = answers
        self.deferredAnswer = Deferred()
        self.expectedAnswers = answers
        return self.deferredAnswer

    def nevermind(self):
        """forget the context of the conversation"""
        if self.askingQuestion:
            if 'question' in self.context:
                del self.context['question']
            if 'expectedAnswers' in self.context:
                del self.context['expectedAnswers']
            if hasattr(self, 'deferredAnswer'):
                # Probably best to just leave the deferred hanging
                #if not self.deferredAnswer.called:
                #  self.deferredAnswer.callback(None)
                del self.deferredAnswer
            if hasattr(self, 'expectedAnswers'):
                del self.expectedAnswers

    def grantAuthorization(self, notify=True):
        """method to allow this conversation extra priviledges"""
        self._authorized = True
        self.context['authorized'] = True
        if not notify: return
        self.say(
            "You have been granted authorization by the environment administrator."
        )

    def revokeAuthorization(self, notify=True):
        """method to deny this conversation extra priviledges"""
        self._authorized = False
        self.context['authorized'] = False
        self.nevermind()
        if not notify: return
        self.say(
            "Your authorization has been revoked by the environment administrator."
        )

    def notify(self, event):
        """Tells the remote party that an event occurred"""
        self.notificationQueue.append(event)
        if len(self.notificationQueue) == 1:
            config.reactor.callLater(1, self.sendNotifications)

    def sendNotifications(self):
        """Formats and sends notification to the remote party"""
        message = ""
        for event in self.notificationQueue:
            params = ', '.join("%s=%s" % item for item in event.params.items())
            params = escapeToXml(params)
            message += "[<b>%s</b> occurred (%s)]<br/>" % (event.name, params)
        self.notificationQueue = []
        preStyle = '<font color="gray"><i>'
        postStyle = '</i></font>'
        self.say(preStyle + message + postStyle)