Example #1
0
    def __init__(self):
        my_jid = JID(USER + '/Bot')
        self.my_jid = my_jid
        settings = XMPPSettings({
            "software_name": "qxbot",
            "software_version": __version__,
            "software_os": "Linux",
            "tls_verify_peer": False,
            "starttls": True,
            "ipv6": False,
            "poll_interval": 10,
        })

        settings["password"] = PASSWORD
        version_provider = VersionProvider(settings)
        event_queue = settings["event_queue"]
        self.webqq = WebQQ(QQ, event_queue)
        self.connected = False
        #self.mainloop = TornadoMainLoop(settings)
        self.mainloop = EpollMainLoop(settings)
        self.client = Client(my_jid, [self, version_provider], settings,
                             self.mainloop)
        self.logger = get_logger()
        self.msg_dispatch = MessageDispatch(self, self.webqq, BRIDGES)
        self.xmpp_msg_queue = Queue.Queue()
Example #2
0
 def newclient(self):
     version_provider = VersionProvider(self.settings)
     self.client = Client(
         self.jid,
         [self, version_provider],
         self.settings,
         main_loop=self.main_loop,
     )
Example #3
0
 def __init__(self, my_jid, settings):
     version_provider = VersionProvider(settings)
     self.main_loop = SelectMainLoop(settings)
     #self.main_loop = ThreadPool(settings)
     #self.main_loop.start(daemon=True)
     self.client = Client(my_jid, [self, version_provider],
                          settings,
                          main_loop=self.main_loop)
Example #4
0
 def start(self):
     """
     服务开始
     :return:
     """
     logger.warn("XMPPClient::start listen on %s:%s:%s" % (self.protocol, self.JID, self.password))
     self.xmpp_client = Client(self.JID, [self], self.settings)
     self.xmpp_client.connect()
     self.xmpp_client.run()
     self.is_auth = False
 def __init__(self):
     self.droid = android.Android()
     settings = XMPPSettings({"software_name": "Say Chat"})
     settings["jid"] = self.droid.dialogGetInput("Google Talk Username").result
     settings["password"] = self.droid.dialogGetInput("Google Talk Password").result
     settings["server"] = "talk.google.com"
     settings["starttls"] = True
     self.client = Client(
       JID(settings["jid"]),
       [self, VersionProvider(settings)],
       settings)
Example #6
0
    def __init__(self, your_jid, your_pass, target_jid, messages):
        self.target_jid = target_jid
        self.messages = messages

        self.connected = False
        self.established = False

        settings = XMPPSettings({
            u"password": your_pass,
            u"starttls": True,
            u"tls_verify_peer": False,
        })
        self.client = Client(JID(your_jid), [self], settings)
        self.client.connect()
Example #7
0
    def __init__(self):
        my_jid = JID(USER+'/Bot')
        self.my_jid = my_jid
        settings = XMPPSettings({
                            "software_name": "qxbot",
                            "software_version": __version__,
                            "software_os": "Linux",
                            "tls_verify_peer": False,
                            "starttls": True,
                            "ipv6":False,
                            "poll_interval": 10,
                            })

        settings["password"] = PASSWORD
        version_provider = VersionProvider(settings)
        event_queue = settings["event_queue"]
        self.webqq = WebQQ(QQ, event_queue)
        self.connected = False
        #self.mainloop = TornadoMainLoop(settings)
        self.mainloop = EpollMainLoop(settings)
        self.client = Client(my_jid, [self, version_provider],
                             settings, self.mainloop)
        self.logger = get_logger()
        self.msg_dispatch = MessageDispatch(self, self.webqq, BRIDGES)
        self.xmpp_msg_queue = Queue.Queue()
 def __init__(self):
     self.droid = android.Android()
     settings = XMPPSettings({"software_name": "Say Chat"})
     settings["jid"] = self.droid.dialogGetInput("Google Talk Username").result
     settings["password"] = self.droid.dialogGetInput("Google Talk Password").result
     settings["server"] = "talk.google.com"
     settings["starttls"] = True
     self.client = Client(JID(settings["jid"]), [self, VersionProvider(settings)], settings)
Example #9
0
 def __init__(self, my_jid, settings, myname, events, text):
     version_provider = VersionProvider(settings)
     self.client = Client(my_jid, [self, version_provider], settings)
     self.myname = myname  # first and last name of user
     self.logs = {}
     self.parser = ttp.Parser()  # twitter text processing lib handler
     self.events = events
     self.do_text = text
     self.last_msg = ""
Example #10
0
    def submit(self):
        for admin in settings_file.users['administrators']:
            self.target_jid = settings_file.users['administrators'][admin]
            if sys.version_info.major < 3:
                self.your_jid = self.your_jid.decode("utf-8")
                self.your_password = self.your_password.decode("utf-8")
                self.target_jid = self.target_jid.decode("utf-8")
                self.message = self.message.decode("utf-8")

                handler = MyHandler(JID(self.target_jid), self.message)
                settings = XMPPSettings({
                    u"password": self.your_password,
                    u"starttls": True,
                    u"tls_verify_peer": False,
                })

                client = Client(JID(self.your_jid), [handler], settings)
                client.connect()
                client.run()
Example #11
0
 def __init__(self, jid, settings):
   if 'software_name' not in settings:
     settings['software_name'] = self.__class__.__name__
   if 'software_version' not in settings:
     settings['software_version'] = __version__
   version_provider = VersionProvider(settings)
   self.client = Client(jid, [self, version_provider], settings)
   self.presence = defaultdict(dict)
   self.subscribes = ExpiringDictionary(default_timeout=5)
   self.invited = {}
Example #12
0
 def start(self):
     """
     服务开始
     :return:
     """
     logger.warn("XMPPClient::start listen on %s:%s:%s" % (self.protocol, self.JID, self.password))
     self.xmpp_client = Client(self.JID, [self], self.settings)
     self.xmpp_client.connect()
     self.xmpp_client.run()
     self.is_auth = False
Example #13
0
    def __init__(self, jid, settings, botsettings=None):
        if 'software_name' not in settings:
            settings['software_name'] = self.__class__.__name__
        if 'software_version' not in settings:
            settings['software_version'] = __version__
        version_provider = VersionProvider(settings)

        handlers = []
        if ReceiptSender:
            self.receipt_sender = rs = ReceiptSender()
            handlers.append(rs)

        handlers.extend([self, version_provider])
        self.client = Client(jid, handlers, settings)

        self.presence = defaultdict(dict)
        self.subscribes = ExpiringDictionary(default_timeout=5)
        self.invited = {}
        self.avatar_hash = None
        self.settings = botsettings
Example #14
0
    def __init__(self, your_jid, your_pass, target_jid, messages):
        self.target_jid = target_jid
        self.messages = messages

        self.connected = False
        self.established = False

        settings = XMPPSettings({
            u"password": your_pass,
            u"starttls": True,
            u"tls_verify_peer": False,
        })
        self.client = Client(JID(your_jid), [self], settings)
        self.client.connect()
Example #15
0
    def send(self, req_id, stanzas):
        self.req_id = req_id
        self.stanzas = stanzas
        logging.debug(u"XmppClient start sending messages for request #%s",
                      self.req_id)
        try:
            settings = XMPPSettings({
                u"password": self.password,
                u"starttls": self.use_tls,
                u"tls_verify_peer": self.tls_verify_peer,
                u"server": self.host,
                u"port": self.port,
                u"default_stanza_timeout": self.timeout,
            })

            self.client = Client(self.from_jid, [self], settings)
            self.client.connect()
            self.client.run(timeout=self.timeout)
        except Exception, e:
            logging.error(
                "Error sending XMPP notification for request #%s: %s",
                req_id,
                e,
                exc_info=1)
Example #16
0
    def __init__(self):
        my_jid = JID(USER + '/Bot')
        self.my_jid = my_jid
        settings = XMPPSettings({
            "software_name": "Clubot",
            "software_version": __version__,
            "software_os": "Linux",
            "tls_verify_peer": False,
            "starttls": True,
            "ipv6": False,
            "poll_interval": 10,
        })

        settings["password"] = PASSWORD
        version_provider = VersionProvider(settings)
        self.connected = False
        mainloop = TornadoMainLoop(settings)
        self.client = Client(my_jid, [self, version_provider], settings,
                             mainloop)
        #self.client = Client(my_jid, [self, version_provider], settings)
        self.logger = get_logger()
        self.trytimes = 0
        self.sended = []
        Logics.empty_status()
class SayChat(EventHandler, XMPPFeatureHandler):
  def __init__(self):
      self.droid = android.Android()
      settings = XMPPSettings({"software_name": "Say Chat"})
      settings["jid"] = self.droid.dialogGetInput("Google Talk Username").result
      settings["password"] = self.droid.dialogGetInput("Google Talk Password").result
      settings["server"] = "talk.google.com"
      settings["starttls"] = True
      self.client = Client(
        JID(settings["jid"]),
        [self, VersionProvider(settings)],
        settings)
      
  def connect(self):
    self.client.connect()
    self.client.run()

  def disconnect(self):
    self.client.disconnect()
    self.client.run(timeout = 2)

  @message_stanza_handler()
  def handle_message(self, stanza):
    self.droid.ttsSpeak(
      "{!s} says {!s}".format(stanza.from_jid.as_unicode(),
      stanza.body))
    return ""
    
  @event_handler(DisconnectedEvent)
  def handle_disconnected(self, event):
    return QUIT
    
  @event_handler()
  def handle_all(self, event):
    """If it's not logged, it didn't happen."""
    logging.info("-- {}".format(event))

  def run(self):
    try:
      self.connect()
    except KeyboardInterrupt:
      self.disconnect()
Example #18
0
class SayChat(EventHandler, XMPPFeatureHandler):
  def __init__(self):
      self.droid = sl4a.Android()
      settings = XMPPSettings({"software_name": "Say Chat"})
      settings["jid"] = self.droid.dialogGetInput("Google Talk Username").result
      settings["password"] = self.droid.dialogGetInput("Google Talk Password").result
      settings["server"] = "talk.google.com"
      settings["starttls"] = True
      self.client = Client(
        JID(settings["jid"]),
        [self, VersionProvider(settings)],
        settings)
      
  def connect(self):
    self.client.connect()
    self.client.run()

  def disconnect(self):
    self.client.disconnect()
    self.client.run(timeout = 2)

  @message_stanza_handler()
  def handle_message(self, stanza):
    self.droid.ttsSpeak(
      "{!s} says {!s}".format(stanza.from_jid.as_unicode(),
      stanza.body))
    return ""
    
  @event_handler(DisconnectedEvent)
  def handle_disconnected(self, event):
    return QUIT
    
  @event_handler()
  def handle_all(self, event):
    """If it's not logged, it didn't happen."""
    logging.info("-- {}".format(event))

  def run(self):
    try:
      self.connect()
    except KeyboardInterrupt:
      self.disconnect()
Example #19
0
 def push(self):
     settings = XMPPSettings({
         u"password": self.from_pwd,
         u"starttls": True,
         u"tls_verify_peer": False,
         u'server': self.xmpp_server,
         u'c2s_port': int(self.xmpp_port),
     })
     xml = self.msg
     client = Client(JID(self.from_jid), [MyHandler(xml.encode('utf-8'))],
                     settings)
     client.connect()
     client.run()
Example #20
0
    def __init__(self):
        my_jid = JID(USER+'/Bot')
        self.my_jid = my_jid
        settings = XMPPSettings({
                            "software_name": "Clubot",
                            "software_version": __version__,
                            "software_os": "Linux",
                            "tls_verify_peer": False,
                            "starttls": True,
                            "ipv6":False,
                            })

        settings["password"] = PASSWORD
        version_provider = VersionProvider(settings)
        self.connected = False
        self.client = Client(my_jid, [self, version_provider], settings)
        self.logger = get_logger()
        self.trytimes = 0
        empty_status()
Example #21
0
  def __init__(self, jid, settings, botsettings=None):
    if 'software_name' not in settings:
      settings['software_name'] = self.__class__.__name__
    if 'software_version' not in settings:
      settings['software_version'] = __version__
    version_provider = VersionProvider(settings)

    handlers = []
    if ReceiptSender:
      self.receipt_sender = rs = ReceiptSender()
      handlers.append(rs)

    handlers.extend([self, version_provider])
    self.client = Client(jid, handlers, settings)

    self.presence = defaultdict(dict)
    self.subscribes = ExpiringDictionary(default_timeout=5)
    self.invited = {}
    self.avatar_hash = None
    self.settings = botsettings
Example #22
0
class SmsRobotClient(EventHandler, XMPPFeatureHandler):
    def __init__(self, your_jid, your_pass, target_jid, messages):
        self.target_jid = target_jid
        self.messages = messages

        self.connected = False
        self.established = False

        settings = XMPPSettings({
            u"password": your_pass,
            u"starttls": True,
            u"tls_verify_peer": False,
        })
        self.client = Client(JID(your_jid), [self], settings)
        self.client.connect()

    def run(self):
        while self.messages:
            if self.connected and not self.established:
                print("Connecting...")
                self.client.stream.send(
                    Message(to_jid=self.target_jid,
                            body="?",
                            stanza_type='chat'))
            self.client.run(timeout=2)

    @event_handler(AuthorizedEvent)
    def handle_authorized(self, event):
        self.connected = True

    @message_stanza_handler()
    def handle_message(self, stanza):
        if not self.established:
            if '"help"' not in stanza.body:
                return
            self.established = True

        if not self.messages:
            self.client.disconnect()
            return None

        body = 'sms:%s:%s' % self.messages.pop()
        print(body)
        return Message(to_jid=self.target_jid, body=body, stanza_type='chat')

    @event_handler(DisconnectedEvent)
    def handle_disconnected(self, event):
        return QUIT
Example #23
0
class SmsRobotClient(EventHandler, XMPPFeatureHandler):
    def __init__(self, your_jid, your_pass, target_jid, messages):
        self.target_jid = target_jid
        self.messages = messages

        self.connected = False
        self.established = False

        settings = XMPPSettings({
            u"password": your_pass,
            u"starttls": True,
            u"tls_verify_peer": False,
        })
        self.client = Client(JID(your_jid), [self], settings)
        self.client.connect()

    def run(self):
        while self.messages:
            if self.connected and not self.established:
                print("Connecting...")
                self.client.stream.send(Message(to_jid = self.target_jid,
                    body = "?", stanza_type = 'chat'))
            self.client.run(timeout = 2)

    @event_handler(AuthorizedEvent)
    def handle_authorized(self, event):
        self.connected = True

    @message_stanza_handler()
    def handle_message(self, stanza):
        if not self.established:
            if '"help"' not in stanza.body:
                return
            self.established = True

        if not self.messages:
            self.client.disconnect()
            return None

        body = 'sms:%s:%s' % self.messages.pop()
        print(body)
        return Message(to_jid = self.target_jid,
            body = body, stanza_type = 'chat')

    @event_handler(DisconnectedEvent)
    def handle_disconnected(self, event):
        return QUIT
    def send(self, req_id, stanzas):
        self.req_id = req_id
        self.stanzas = stanzas
        logging.debug(u"XmppClient start sending messages for request #%s", self.req_id)
        try:
            settings = XMPPSettings({
                            u"password": self.password,
                            u"starttls": self.use_tls,
                            u"tls_verify_peer": self.tls_verify_peer,
                            u"server" : self.host,
                            u"port": self.port,
                            u"default_stanza_timeout": self.timeout,
                        })

            self.client = Client(self.from_jid, [self], settings)
            self.client.connect()
            self.client.run( timeout = self.timeout )
        except Exception, e:
            logging.error("Error sending XMPP notification for request #%s: %s",
                      req_id,
                      e,
                      exc_info=1)
Example #25
0
    def __init__(self):
        my_jid = JID(USER+'/Bot')
        self.my_jid = my_jid
        settings = XMPPSettings({
                            "software_name": "Clubot",
                            "software_version": __version__,
                            "software_os": "Linux",
                            "tls_verify_peer": False,
                            "starttls": True,
                            "ipv6":False,
                            "poll_interval": 10,
                            })

        settings["password"] = PASSWORD
        version_provider = VersionProvider(settings)
        self.connected = False
        mainloop = TornadoMainLoop(settings)
        self.client = Client(my_jid, [self, version_provider], settings, mainloop)
        #self.client = Client(my_jid, [self, version_provider], settings)
        self.logger = get_logger()
        self.trytimes = 0
        self.sended = []
        Logics.empty_status()
Example #26
0
    def __init__(self, QQ, QQ_PWD, xmpp_account, xmpp_pwd, control_account,
                 debug=True, command=None):
        self.input_queue = InputQueue(self.send_control_msg)
        self.qq = QQClient(QQ, QQ_PWD, debug)
        self.qq.set_control_msg(self.send_control_msg, self)
        self.command = command or Command(self, self.qq)
        self.jid = JID(xmpp_account + '/Bridge')
        self.control_account = control_account

        settings = XMPPSettings(
            {"software_name": "Magpie",
             "software_version": ".".join(str(x) for x in __version__),
             "software_os": "Linux",
             "tls_verify_peer": False,
             "starttls": True,
             "ipv6": False,
             "password": xmpp_pwd,
             "poll_interval": 10})

        version_provider = VersionProvider(settings)
        mainloop = TornadoMainLoop(settings)
        self.client = Client(self.jid, [self, version_provider],
                             settings, mainloop)
class XmppClient(EventHandler):
    """
    A client to manage the XMPP connection and dispatch messages.
    """
    NAME = "Review Board XMPP Notification Client"
    VERSION = 0.1

    def __init__(self, host, port, timeout, from_jid, password, use_tls, tls_verify_peer):
        self.host = host
        self.port = port
        self.timeout = timeout or 5
        self.from_jid = from_jid
        self.password = password
        self.use_tls = use_tls
        self.tls_verify_peer = tls_verify_peer

        self.req_id = None
        self.client = None
        self.stanzas = None

    @event_handler(AuthorizedEvent)
    def handle_authorized(self, event):
        logging.debug(u"XmppClient event handler for request #%s authorized: %s", self.req_id, event)
        if self.client.stream != event.stream:
            logging.debug(u"XmppClient event handler ignore event")
            return
        for stanza in self.stanzas:
            logging.debug("XmppHandler for request #%s send message to %s", self.req_id, stanza.as_xml())
            event.stream.send(stanza)
        logging.debug(u"XmppHandler disconnecting stream for request #%s", self.req_id)
        self.client.disconnect()

    @event_handler(DisconnectedEvent)
    def handle_disconnected(self, event):
        logging.debug("XmppClient event handler for request #%s disconnected: %s", self.req_id, event)
        if self.client.stream != event.stream:
            logging.debug(u"XmppClient event handler ignore event")
            return
        logging.debug(u"XmppClient event handler closing stream for request #%s", self.req_id)
        self.client.close_stream()
        self.client = None
        return QUIT

    @event_handler()
    def handle_all(self, event):
        logging.debug(u"XmppClient event handler for request #%s: %s", self.req_id, event)

    def send(self, req_id, stanzas):
        self.req_id = req_id
        self.stanzas = stanzas
        logging.debug(u"XmppClient start sending messages for request #%s", self.req_id)
        try:
            settings = XMPPSettings({
                            u"password": self.password,
                            u"starttls": self.use_tls,
                            u"tls_verify_peer": self.tls_verify_peer,
                            u"server" : self.host,
                            u"port": self.port,
                            u"default_stanza_timeout": self.timeout,
                        })

            self.client = Client(self.from_jid, [self], settings)
            self.client.connect()
            self.client.run( timeout = self.timeout )
        except Exception, e:
            logging.error("Error sending XMPP notification for request #%s: %s",
                      req_id,
                      e,
                      exc_info=1)
Example #28
0
class Bot(EventHandler, XMPPFeatureHandler):
    def __init__(self, my_jid, settings):
        version_provider = VersionProvider(settings)
        self.main_loop = SelectMainLoop(settings)
        #self.main_loop = ThreadPool(settings)
        #self.main_loop.start(daemon=True)
        self.client = Client(my_jid, [self, version_provider],
                             settings,
                             main_loop=self.main_loop)
        #self.client = Client(my_jid, [self, version_provider], settings)

    def run(self):
        """Request client connection and start the main loop."""
        self.client.connect()
        self.client.run()

    def disconnect(self):
        """Request disconnection and let the main loop run for a 2 more
        seconds for graceful disconnection."""
        self.client.disconnect()
        self.client.run(timeout=2)

    @presence_stanza_handler("subscribe")
    def handle_presence_subscribe(self, stanza):
        logging.info(u"{0} requested presence subscription".format(
            stanza.from_jid))
        presence = Presence(to_jid=stanza.from_jid.bare(),
                            stanza_type="subscribe")
        return [stanza.make_accept_response(), presence]

    @presence_stanza_handler("subscribed")
    def handle_presence_subscribed(self, stanza):
        logging.info(u"{0!r} accepted our subscription request".format(
            stanza.from_jid))
        return True

    @presence_stanza_handler("unsubscribe")
    def handle_presence_unsubscribe(self, stanza):
        logging.info(u"{0} canceled presence subscription".format(
            stanza.from_jid))
        presence = Presence(to_jid=stanza.from_jid.bare(),
                            stanza_type="unsubscribe")
        return [stanza.make_accept_response(), presence]

    @presence_stanza_handler("unsubscribed")
    def handle_presence_unsubscribed(self, stanza):
        logging.info(u"{0!r} acknowledged our subscrption cancelation".format(
            stanza.from_jid))
        return True

    # @message_stanza_handler()
    # def handle_message(self, stanza):
    #     """Echo every non-error ``<message/>`` stanza.

    #     Add "Re: " to subject, if any.
    #     """
    #     if stanza.subject:
    #         subject = u"Re: " + stanza.subject
    #     else:
    #         subject = None
    #     if stanza.body is None:
    #         txt = None
    #     else:
    #         txt = stanza.body+'!'
    #     msg = Message(stanza_type = stanza.stanza_type,
    #                   from_jid = stanza.to_jid, to_jid = stanza.from_jid,
    #                   subject = subject, body = txt,
    #                   thread = stanza.thread)
    #     return msg
    @message_stanza_handler()
    def handle_message(self, stanza):
        if stanza.stanza_type == 'chat' and not hasattr(stanza, 'processed'):
            #print stanza
            stanza.processed = True

            to_jid = stanza.to_jid.as_unicode()
            from_jid = stanza.from_jid.as_unicode()

            im_tcp_tunneler.handle_message(from_jid, to_jid, stanza.body)

        return True

    @event_handler(DisconnectedEvent)
    def handle_disconnected(self, event):
        """Quit the main loop upon disconnection."""
        return QUIT

    @event_handler()
    def handle_all(self, event):
        """Log all events."""
        logging.info(u"-- {0}".format(event))
Example #29
0
 def __init__(self, my_jid, settings):
     version_provider = VersionProvider(settings)
     self.main_loop = SelectMainLoop(settings)
     #self.main_loop = ThreadPool(settings)
     #self.main_loop.start(daemon=True)
     self.client = Client(my_jid, [self, version_provider], settings, main_loop=self.main_loop)
Example #30
0
class Bot(EventHandler, XMPPFeatureHandler):
    def __init__(self, my_jid, settings):
        version_provider = VersionProvider(settings)
        self.main_loop = SelectMainLoop(settings)
        #self.main_loop = ThreadPool(settings)
        #self.main_loop.start(daemon=True)
        self.client = Client(my_jid, [self, version_provider], settings, main_loop=self.main_loop)
        #self.client = Client(my_jid, [self, version_provider], settings)

    def run(self):
        """Request client connection and start the main loop."""
        self.client.connect()
        self.client.run()

    def disconnect(self):
        """Request disconnection and let the main loop run for a 2 more
        seconds for graceful disconnection."""
        self.client.disconnect()
        self.client.run(timeout = 2)

    @presence_stanza_handler("subscribe")
    def handle_presence_subscribe(self, stanza):
        logging.info(u"{0} requested presence subscription".format(stanza.from_jid))
        presence = Presence(to_jid = stanza.from_jid.bare(), stanza_type = "subscribe")
        return [stanza.make_accept_response(), presence]

    @presence_stanza_handler("subscribed")
    def handle_presence_subscribed(self, stanza):
        logging.info(u"{0!r} accepted our subscription request".format(stanza.from_jid))
        return True

    @presence_stanza_handler("unsubscribe")
    def handle_presence_unsubscribe(self, stanza):
        logging.info(u"{0} canceled presence subscription".format(stanza.from_jid))
        presence = Presence(to_jid = stanza.from_jid.bare(), stanza_type = "unsubscribe")
        return [stanza.make_accept_response(), presence]

    @presence_stanza_handler("unsubscribed")
    def handle_presence_unsubscribed(self, stanza):
        logging.info(u"{0!r} acknowledged our subscrption cancelation".format(stanza.from_jid))
        return True

    # @message_stanza_handler()
    # def handle_message(self, stanza):
    #     """Echo every non-error ``<message/>`` stanza.
        
    #     Add "Re: " to subject, if any.
    #     """
    #     if stanza.subject:
    #         subject = u"Re: " + stanza.subject
    #     else:
    #         subject = None
    #     if stanza.body is None:
    #         txt = None
    #     else:
    #         txt = stanza.body+'!'
    #     msg = Message(stanza_type = stanza.stanza_type,
    #                   from_jid = stanza.to_jid, to_jid = stanza.from_jid,
    #                   subject = subject, body = txt,
    #                   thread = stanza.thread)
    #     return msg
    @message_stanza_handler()
    def handle_message(self, stanza):
        if stanza.stanza_type == 'chat' and not hasattr(stanza, 'processed'):
            #print stanza
            stanza.processed = True

            to_jid = stanza.to_jid.as_unicode()
            from_jid = stanza.from_jid.as_unicode()
            
            im_tcp_tunneler.handle_message(from_jid, to_jid, stanza.body)
            
        return True
        
    @event_handler(DisconnectedEvent)
    def handle_disconnected(self, event):
        """Quit the main loop upon disconnection."""
        return QUIT
    
    @event_handler()
    def handle_all(self, event):
        """Log all events."""
        logging.info(u"-- {0}".format(event))
Example #31
0
class QXBot(EventHandler, XMPPFeatureHandler):
    def __init__(self):
        my_jid = JID(USER+'/Bot')
        self.my_jid = my_jid
        settings = XMPPSettings({
                            "software_name": "qxbot",
                            "software_version": __version__,
                            "software_os": "Linux",
                            "tls_verify_peer": False,
                            "starttls": True,
                            "ipv6":False,
                            "poll_interval": 10,
                            })

        settings["password"] = PASSWORD
        version_provider = VersionProvider(settings)
        event_queue = settings["event_queue"]
        self.webqq = WebQQ(QQ, event_queue)
        self.connected = False
        #self.mainloop = TornadoMainLoop(settings)
        self.mainloop = EpollMainLoop(settings)
        self.client = Client(my_jid, [self, version_provider],
                             settings, self.mainloop)
        self.logger = get_logger()
        self.msg_dispatch = MessageDispatch(self, self.webqq, BRIDGES)
        self.xmpp_msg_queue = Queue.Queue()

    def run(self, timeout = None):
        self.client.connect()
        self.client.run(timeout)

    def disconnect(self):
        self.client.disconnect()
        while True:
            try:
                self.run(2)
            except:
                pass
            else:
                break

    @presence_stanza_handler("subscribe")
    def handle_presence_subscribe(self, stanza):
        self.logger.info(u"{0} join us".format(stanza.from_jid))
        return stanza.make_accept_response()

    @presence_stanza_handler("subscribed")
    def handle_presence_subscribed(self, stanza):
        self.logger.info(u"{0!r} accepted our subscription request"
                                                    .format(stanza.from_jid))
        return stanza.make_accept_response()

    @presence_stanza_handler("unsubscribe")
    def handle_presence_unsubscribe(self, stanza):
        self.logger.info(u"{0} canceled presence subscription"
                                                    .format(stanza.from_jid))
        return stanza.make_accept_response()

    @presence_stanza_handler("unsubscribed")
    def handle_presence_unsubscribed(self, stanza):
        self.logger.info(u"{0!r} acknowledged our subscrption cancelation"
                                                    .format(stanza.from_jid))

    @presence_stanza_handler(None)
    def handle_presence_available(self, stanza):
        self.logger.info(r"{0} has been online".format(stanza.from_jid))

    @presence_stanza_handler("unavailable")
    def handle_presence_unavailable(self, stanza):
        self.logger.info(r"{0} has been offline".format(stanza.from_jid))

    @message_stanza_handler()
    def handle_message(self, stanza):
        if self.webqq.connected:
            self.msg_dispatch.dispatch_xmpp(stanza)
        else:
            self.xmpp_msg_queue.put(stanza)

    @event_handler(DisconnectedEvent)
    def handle_disconnected(self, event):
        return QUIT

    @event_handler(ConnectedEvent)
    def handle_connected(self, event):
        pass

    @event_handler(RosterReceivedEvent)
    def handle_roster_received(self, event):
        """ 此处代表xmpp已经连接
        开始连接QQ, 先将检查是否需要验证码的handler加入到mainloop
        """
        checkhandler = CheckHandler(self.webqq)
        self.mainloop.add_handler(checkhandler)
        self.connected = True

    @event_handler(CheckedEvent)
    def handle_webqq_checked(self, event):
        """ 第一步已经完毕, 删除掉检查的handler, 将登录前handler加入mainloop"""
        bloginhandler = BeforeLoginHandler(self.webqq, password = QQ_PWD)
        self.mainloop.remove_handler(event.handler)
        self.mainloop.add_handler(bloginhandler)

    @event_handler(BeforeLoginEvent)
    def handle_webqq_blogin(self, event):
        """ 登录前完毕开始真正的登录 """
        loginhandler = LoginHandler(self.webqq)
        self.mainloop.remove_handler(event.handler)
        self.mainloop.add_handler(loginhandler)

    @event_handler(WebQQLoginedEvent)
    def handle_webqq_logined(self, event):
        """ 登录后将获取群列表的handler放入mainloop """
        self.mainloop.remove_handler(event.handler)
        self.mainloop.add_handler(GroupListHandler(self.webqq))

    @event_handler(GroupListEvent)
    def handle_webqq_group_list(self, event):
        """ 获取群列表后"""
        self.mainloop.remove_handler(event.handler)
        data = event.data
        group_map = {}
        if data.get("retcode") == 0:
            group_list = data.get("result", {}).get("gnamelist", [])
            for group in group_list:
                gcode = group.get("code")
                group_map[gcode] = group

        self.webqq.group_map = group_map
        self.webqq.group_lst_updated = False   # 开放添加GroupListHandler
        i = 1
        for gcode in group_map:
            if i == len(group_map):
                self.mainloop.add_handler(
                    GroupMembersHandler(self.webqq, gcode = gcode, done = True))
            else:
                self.mainloop.add_handler(
                    GroupMembersHandler(self.webqq, gcode = gcode, done = False))

            i += 1

    @event_handler(GroupMembersEvent)
    def handle_group_members(self, event):
        """ 获取所有群成员 """
        self.mainloop.remove_handler(event.handler)
        members = event.data.get("result", {}).get("minfo", [])
        self.webqq.group_m_map[event.gcode] = {}
        for m in members:
            uin = m.get("uin")
            self.webqq.group_m_map[event.gcode][uin] = m
        cards = event.data.get("result", {}).get("cards", [])
        for card in cards:
            uin = card.get("muin")
            group_name = card.get("card")
            self.webqq.group_m_map[event.gcode][uin]["nick"] = group_name

        # 防止重复添加GroupListHandler
        if not self.webqq.group_lst_updated:
            self.webqq.group_lst_updated = True
            self.mainloop.add_handler(GroupListHandler(self.webqq, delay = 300))

    @event_handler(WebQQRosterUpdatedEvent)
    def handle_webqq_roster(self, event):
        """ 群成员都获取完毕后开启,Poll获取消息和心跳 """
        self.mainloop.remove_handler(event.handler)
        self.msg_dispatch.get_map()
        if not self.webqq.polled:
            self.webqq.polled = True
            self.mainloop.add_handler(PollHandler(self.webqq))
        if not self.webqq.heartbeated:
            self.webqq.heartbeated = True
            hb = HeartbeatHandler(self.webqq)
            self.mainloop.add_handler(hb)
        while True:
            try:
                stanza = self.xmpp_msg_queue.get_nowait()
                self.msg_dispatch.dispatch_xmpp(stanza)
            except Queue.Empty:
                break
        self.webqq.connected = True

    @event_handler(WebQQHeartbeatEvent)
    def handle_webqq_hb(self, event):
        """ 心跳完毕后, 延迟60秒在此触发此事件 重复心跳 """
        self.mainloop.remove_handler(event.handler)
        self.mainloop.add_handler(HeartbeatHandler(self.webqq, delay = 60))

    @event_handler(WebQQPollEvent)
    def handle_webqq_poll(self, event):
        """ 延迟1秒重复触发此事件, 轮询获取消息 """
        self.mainloop.remove_handler(event.handler)
        self.mainloop.add_handler(PollHandler(self.webqq))

    @event_handler(WebQQMessageEvent)
    def handle_webqq_msg(self, event):
        """ 有消息到达, 处理消息 """
        self.msg_dispatch.dispatch_qq(event.message)

    @event_handler(RetryEvent)
    def handle_retry(self, event):
        """ 有handler触发异常, 需重试 """
        self.mainloop.remove_handler(event.handler)
        handler = event.cls(self.webqq, event.req, *event.args, **event.kwargs)
        self.mainloop.add_handler(handler)

    @event_handler(RemoveEvent)
    def handle_remove(self, event):
        """ 触发此事件, 移除handler """
        self.mainloop.remove_handler(event.handler)

    def send_qq_group_msg(self, group_uin, content):
        """ 发送qq群消息 """
        handler = GroupMsgHandler(self.webqq, group_uin = group_uin,
                                  content = content)
        self.mainloop.add_handler(handler)

    @property
    def roster(self):
        return self.client.roster

    @property
    def stream(self):
        return self.client.stream

    @event_handler()
    def handle_all(self, event):
        self.logger.info(u"-- {0}".format(event))

    def make_message(self, to, typ, body):
        """ 构造消息
            `to` - 接收人 JID
            `typ` - 消息类型
            `body` - 消息主体
        """
        if typ not in ['normal', 'chat', 'groupchat', 'headline']:
            typ = 'chat'
        m = Message(from_jid = self.my_jid, to_jid = to, stanza_type = typ,
                    body = body)
        return m

    def send_msg(self, to, body):
        if not isinstance(to, JID):
            to = JID(to)
        msg = self.make_message(to, 'chat', body)
        self.stream.send(msg)
Example #32
0
class Rodney(EventHandler, XMPPFeatureHandler):
    """Personal Secretary for facebook chat."""

    def __init__(self, my_jid, settings, myname, events, text):
        version_provider = VersionProvider(settings)
        self.client = Client(my_jid, [self, version_provider], settings)
        self.myname = myname  # first and last name of user
        self.logs = {}
        self.parser = ttp.Parser()  # twitter text processing lib handler
        self.events = events
        self.do_text = text
        self.last_msg = ""

    def run(self):
        """Request client connection and start the main loop."""
        self.client.connect()
        self.client.run()

    def disconnect(self):
        """Request disconnection and let the main loop run for a 2 more
        seconds for graceful disconnection."""
        self.client.disconnect()
        self.client.run(timeout=2)

    @presence_stanza_handler("subscribe")
    def handle_presence_subscribe(self, stanza):
        logging.info(u"{0} requested presence subscription".format(stanza.from_jid))
        presence = Presence(to_jid=stanza.from_jid.bare(), stanza_type="subscribe")
        return [stanza.make_accept_response(), presence]

    @presence_stanza_handler("subscribed")
    def handle_presence_subscribed(self, stanza):
        logging.info(u"{0!r} accepted our subscription request".format(stanza.from_jid))
        return True

    @presence_stanza_handler("unsubscribe")
    def handle_presence_unsubscribe(self, stanza):
        logging.info(u"{0} canceled presence subscription".format(stanza.from_jid))
        presence = Presence(to_jid=stanza.from_jid.bare(), stanza_type="unsubscribe")
        return [stanza.make_accept_response(), presence]

    @presence_stanza_handler("unsubscribed")
    def handle_presence_unsubscribed(self, stanza):
        logging.info(u"{0!r} acknowledged our subscrption cancelation".format(stanza.from_jid))
        return True

    @event_handler(DisconnectedEvent)
    def handle_disconnected(self, event):
        endtime = int(time.time())
        filename = "rodney.{0}.log".format(endtime)
        f = open(filename, "w")
        from pprint import PrettyPrinter

        pp = PrettyPrinter(depth=10, stream=f)
        pp.pprint(self.logs)
        print "My transcript has been written to {0}".format(filename)
        """Quit the main loop upon disconnection."""
        return QUIT

    @event_handler()
    def handle_all(self, event):
        """Log all events."""
        logging.info(u"-- {0}".format(event))

    @event_handler(RosterReceivedEvent)
    def handle_roster_received(self, event):
        self.roster_items = self.client.roster.items()
        print type(self.roster_items)
        print "Roster received!"

    @message_stanza_handler()
    def handle_message(self, stanza):
        """ Does message dispatching:
        1) Checks when you're free on calendar
        2) Sends you a text
        3) Playful responses
        """
        if stanza.body is None:
            print stanza
        elif stanza.body == self.last_msg:
            print "bad"
            return
        else:
            self.last_msg = stanza.body
            parsed = self.parser.parse(stanza.body)

            sender = (i for i in self.roster_items if i.jid == stanza.from_jid).next()
            if sender.name not in self.logs.keys():
                self.logs[sender.name] = []

            if sender == None:
                print "no name found, making it fuzz"
                name = "fuzz"
            else:
                name = sender.name
            print "{0} sent the message: {1}".format(name, stanza.body)

            inmsg = stanza.body.lower()
            if len(self.logs[name]) == 0 or "help" in parsed.tags:
                res = " ".join(
                    [
                        "Hi there! I'm Rodney, the personal fbchat secretary. {0}'s not around right now, can I help you with anything?".format(
                            self.myname
                        ),
                        "\n 1) When is he free? (the question or '#free')",
                        "\n 2) Text him. ('#text message')",
                        "\n 3) #random",
                        "#help",
                    ]
                )
            else:
                if "free" in parsed.tags or ("when" in inmsg and "free" in inmsg):
                    res = " ".join([word for word in stanza.body.split() if not word == "#free"])
                    res += "?\n"
                    res += check_gcal(self.events).format(self.myname.split()[0])
                elif "text" in parsed.tags:
                    if not self.do_text:
                        res = "Sorry, texting is disabled for now ({0} is really cheap!)".format(self.myname.split()[0])
                    elif inmsg.strip() == "#text":
                        res = "Don't send an empty message! The texting costs come out of my salary :("
                    else:
                        out = " ".join([w for w in stanza.body.split() if not w == "#text"])
                        outmsg = send_text(out, name)
                        res = "Ok! I sent the message: {0} to {1}".format(outmsg, self.myname.split()[0])
                elif "random" in parsed.tags:
                    # corpus from nltk
                    res = "coming soon...."
                else:
                    res = lolz(stanza.body)

            msg = Message(
                stanza_type=stanza.stanza_type,
                from_jid=stanza.to_jid,
                to_jid=stanza.from_jid,
                body=res,
                thread=stanza.thread,
            )

            self.logs[name].append(time.asctime() + " {0}: ".format(name) + stanza.body)
            self.logs[name].append(time.asctime() + " {0}: ".format(self.myname) + res)

            return msg
Example #33
0
 def __init__(self, my_jid, args, settings):
     self.args = args
     self.client = Client(my_jid, [self], settings)
     self.presence = defaultdict(dict)
Example #34
0
class Talkbot(DB_oper, EventHandler, XMPPFeatureHandler, Messages, Command):
    def __init__(self, jid, settings):
        self.client = Client(JID(jid), [self], settings)

    def run_bot(self):
        self.client.connect()
        self.client.run()

    def stop_bot(self):
        self.client.disconnect()

    @event_handler(DisconnectedEvent)
    def handle_disconnect(self, event):
        return QUIT

    @event_handler()
    def handle_all(self, event):
        logging.info(u"--{0}".format(event))

    @message_stanza_handler()
    def handle_message(self, stanza):
        if stanza.stanza_type != 'chat':
            return True
        current_jid = stanza.from_jid
        body = stanza.body
        if body[0] == '-':
            logging.info(u"handle command which is {0}".format(body))
            command = body.split(' ')[0]
            print 'in main command is %s' % (command)
            self.dispatch_command(command, stanza)
            logging.info(u"handle command which is {0} done".format(body))
        else:
            logging.info(u"handle common message which is {0}".format(body))
            self.dispatch_message(stanza.body, current_jid.bare())
            logging.info(
                u"handle common message whcih is {0} done".format(body))
        return True

    @presence_stanza_handler("subscribe")
    def handle_subscribe(self, stanza):
        logging.info(u"{0} request presence subscripiton ".format(
            stanza.from_jid))

        sender = stanza.from_jid
        bare_jid = sender.bare().as_string()
        self.add_user(bare_jid)

        presence = Presence(to_jid=stanza.from_jid.bare(),
                            stanza_type="subscribe")
        return [stanza.make_accept_response(), presence]

    def get_online_users(self):
        users = [x.jid for x in self.client.roster if x.subscription == 'both']
        print self.client.roster
        return users

    def send_message(self, receiver, msg):
        if isinstance(receiver, str):
            receiver = JID(receiver)
        message = Message(
            stanza_type='chat',
            from_jid=self.client.jid,
            to_jid=receiver,
            body=msg,
        )
        self.send(message)

    def send(self, stanza):
        self.client.stream.send(stanza)

    def do_unsubscribe(self, jid, type='unsubscribe'):
        jid = JID(jid)
        presence = Presence(to_jid=jid, stanza_type=type)
        self.send(presence)

    def delete_from_roster(self, jid):
        self.client.roster.delItem(jid)
Example #35
0
class BotChat(EventHandler, XMPPFeatureHandler):
    trytimes = 0

    def __init__(self):
        my_jid = JID(USER + '/Bot')
        self.my_jid = my_jid
        settings = XMPPSettings({
            "software_name": "Clubot",
            "software_version": __version__,
            "software_os": "Linux",
            "tls_verify_peer": False,
            "starttls": True,
            "ipv6": False,
            "poll_interval": 10,
        })

        settings["password"] = PASSWORD
        version_provider = VersionProvider(settings)
        self.connected = False
        mainloop = TornadoMainLoop(settings)
        self.client = Client(my_jid, [self, version_provider], settings,
                             mainloop)
        #self.client = Client(my_jid, [self, version_provider], settings)
        self.logger = get_logger()
        self.trytimes = 0
        self.sended = []
        Logics.empty_status()

    def run(self, timeout=None):
        self.client.connect()
        self.client.run(timeout)

    def disconnect(self):
        self.client.disconnect()

    @presence_stanza_handler("subscribe")
    def handle_presence_subscribe(self, stanza):
        self.logger.info(u"{0} join us".format(stanza.from_jid))
        frm = stanza.from_jid
        presence = Presence(to_jid=frm, stanza_type="subscribe")
        Logics.add(frm, None, stanza.show)
        r = [stanza.make_accept_response(), presence]
        if frm not in self.sended:
            self.message_bus.send_sys_msg(stanza, new_member(frm))
            self.message_bus.send_back_msg(stanza, welcome(frm))
            self.sended.append(frm)
        return r

    @presence_stanza_handler("subscribed")
    def handle_presence_subscribed(self, stanza):
        self.logger.info(u"{0!r} accepted our subscription request".format(
            stanza.from_jid))
        frm = stanza.from_jid
        presence = Presence(to_jid=frm, stanza_type="subscribe")
        Logics.add(frm, None, stanza.show)
        r = [presence]
        r = [stanza.make_accept_response(), presence]
        if frm not in self.sended:
            self.message_bus.send_sys_msg(stanza, new_member(frm))
            self.message_bus.send_back_msg(stanza, welcome(frm))
            self.sended.append(frm)
        return r

    @presence_stanza_handler("unsubscribe")
    def handle_presence_unsubscribe(self, stanza):
        self.logger.info(u"{0} canceled presence subscription".format(
            stanza.from_jid))
        presence = Presence(to_jid=stanza.from_jid.bare(),
                            stanza_type="unsubscribe")
        nick = Logics.get_one(stanza.from_jid).nick
        self.message_bus.send_sys_msg(stanza, u'{0} 离开群'.format(nick))
        Logics.drop(stanza.from_jid.bare())
        r = [stanza.make_accept_response(), presence]
        return r

    @presence_stanza_handler("unsubscribed")
    def handle_presence_unsubscribed(self, stanza):
        self.logger.info(
            u"{0!r} acknowledged our subscrption cancelation".format(
                stanza.from_jid))
        Logics.drop(stanza.from_jid.bare())
        return True

    @presence_stanza_handler(None)
    def handle_presence_available(self, stanza):
        self.logger.info(r"{0} has been online".format(stanza.from_jid))
        if stanza.from_jid.bare().as_string() != USER:
            Logics.set_online(stanza.from_jid, stanza.show)
        self.message_bus.send_offline_message(stanza)

    @presence_stanza_handler("unavailable")
    def handle_presence_unavailable(self, stanza):
        self.logger.info(r"{0} has been offline".format(stanza.from_jid))
        frm = stanza.from_jid
        if frm.bare().as_string() == USER:
            self.logger.info('bot go to offline')
            self.disconnect()
        Logics.set_offline(frm)

    @message_stanza_handler()
    def handle_message(self, stanza):
        body = stanza.body
        frm = stanza.from_jid.bare().as_string()
        if not body: return True
        self.logger.info("receive message '{0}' from {1}".format(
            body, stanza.from_jid))
        if body.startswith('$') or body.startswith('-'):
            self.message_bus.send_command(stanza, body)
        #elif body.startswith('<') and frm == BRIDGE:
        #    self.message_bus.send_qq_msg(stanza, body)
        else:
            self.message_bus.send_all_msg(stanza, body)
        return True

    @event_handler(DisconnectedEvent)
    def handle_disconnected(self, event):
        return QUIT

    @event_handler(ConnectedEvent)
    def handle_connected(self, event):
        self.message_bus = MessageBus(self.my_jid, self.stream)
        self.connected = True
        BotChat.trytimes = 0

    @property
    def roster(self):
        return self.client.roster

    @property
    def stream(self):
        return self.client.stream

    def invite_member(self, jid):
        logging.info('invite {0}'.format(jid))
        p1 = Presence(from_jid=self.my_jid,
                      to_jid=jid,
                      stanza_type='subscribe')
        p = Presence(from_jid=self.my_jid,
                     to_jid=jid,
                     stanza_type='subscribed')
        self.stream.send(p)
        self.stream.send(p1)

    @event_handler(RosterUpdatedEvent)
    def handle_roster_update(self, event):
        item = event.item

    @event_handler(RosterReceivedEvent)
    def handle_roster_received(self, event):
        dbstatus = Logics.get_global_info('status').value
        if not dbstatus:
            status = STATUS
        else:
            status = dbstatus
        p = Presence(status=status)
        self.client.stream.send(p)
        ret = [x.jid.bare() for x in self.roster if x.subscription == 'both']
        self.logger.info(' -- roster:{0}'.format(ret))
        members = Logics.get_members()
        members = [m.email for m in members]
        [Logics.add(frm) for frm in ret if not Logics.get_one(frm)]
        if IMPORT:
            [self.invite_member(JID(m)) for m in members if JID(m) not in ret]
        #else:
        #[del_member(JID(m)) for m in members if JID(m) not in ret]

    @event_handler()
    def handle_all(self, event):
        self.logger.info(u"-- {0}".format(event))
class transmissionRobot(EventHandler, XMPPFeatureHandler, TimeoutHandler):
    userlist={};
    lastcycle={};
    def __init__(self, my_jid, settings):
        version_provider = VersionProvider(settings)
        self.client = Client(my_jid, [self, version_provider], settings)
        self.rpc=transmissionrpc.Client(TRANSURL,TRANSPORT,TRANSUSER,TRANSPASS)
        for user in SUBSCRIBERS:
            self.userlist[JID(user).local]=JID(user)
        
    def run(self):
        """Request client connection and start the main loop."""
        self.client.connect()
        self.client.run()

    def disconnect(self):
        """Request disconnection and let the main loop run for a 2 more
        seconds for graceful disconnection."""
        self.client.disconnect()
        self.client.run(timeout = 2)

    @presence_stanza_handler("subscribe")
    def handle_presence_subscribe(self, stanza):
        logging.info(u"{0} requested presence subscription"
                                                    .format(stanza.from_jid))
        presence = Presence(to_jid = stanza.from_jid.bare(),
                                                    stanza_type = "subscribe")
        return [stanza.make_accept_response(), presence]

    @presence_stanza_handler("subscribed")
    def handle_presence_subscribed(self, stanza):
        logging.info(u"{0!r} accepted our subscription request"
                                                    .format(stanza.from_jid))
        return True

    @presence_stanza_handler("unsubscribe")
    def handle_presence_unsubscribe(self, stanza):
        logging.info(u"{0} canceled presence subscription"
                                                    .format(stanza.from_jid))
        presence = Presence(to_jid = stanza.from_jid.bare(),
                                                    stanza_type = "unsubscribe")
        return [stanza.make_accept_response(), presence]

    @presence_stanza_handler("unsubscribed")
    def handle_presence_unsubscribed(self, stanza):
        logging.info(u"{0!r} acknowledged our subscrption cancelation"
                                                    .format(stanza.from_jid))
        return True

    @message_stanza_handler()
    def handle_message(self, stanza):
        messagebody='Robot connected.'
        if stanza.body=="connect":
            if not stanza.from_jid.local in self.userlist:
                self.userlist[stanza.from_jid.local]=stanza.from_jid;
            else:
                messagebody="Already connected."
            msg = Message(stanza_type = stanza.stanza_type,
                        from_jid = self.client.jid, to_jid = stanza.from_jid,
                        subject = None, body = messagebody,
                        thread = stanza.thread)
            return msg
        elif stanza.body=="disconnect":
            messagebody="Robot disconnected."
            try:
                del self.userlist[stanza.from_jid.local];
            except:
                messagebody="Already disconnected"
            msg = Message(stanza_type = stanza.stanza_type,
                        from_jid = self.client.jid, to_jid = stanza.from_jid,
                        subject = None, body = messagebody,
                        thread = stanza.thread)
            return msg
        
        if stanza.from_jid.local+'@'+stanza.from_jid.domain in SUBSCRIBERS:
            try:
                #print stanza.body
                torrent=self.rpc.add_torrent(stanza.body,timeout=10)
            except:
                return True
            messagebody="Torrent added: "+str(torrent)
            msg = Message(stanza_type = stanza.stanza_type,
                        from_jid = self.client.jid, to_jid = stanza.from_jid,
                        subject = None, body = messagebody,
                        thread = stanza.thread)
            return msg
        return True

    @event_handler(DisconnectedEvent)
    def handle_disconnected(self, event):
        """Quit the main loop upon disconnection."""
        return QUIT
        
    
    @event_handler()
    def handle_all(self, event):
        """Log all events."""
        logging.info(u"-- {0}".format(event))
        
    @timeout_handler(3,True)
    def handle_transmission_query(self):
        print "Checking transmission daemon."
        torrentlist=self.rpc.get_torrents()
        for torrent in torrentlist:
            if torrent.doneDate>0 and torrent.hashString in self.lastcycle:
                del self.lastcycle[torrent.hashString]
                messagebody="Torrent finished: "+ torrent.name + ". https://cloud.xiw.im/index.php/apps/files?dir=/Transmission"
                print messagebody
                for i in self.userlist:
                    msg = Message(stanza_type = "normal",
                        from_jid = self.client.jid, to_jid = self.userlist[i],
                        subject = None, body = messagebody,
                        thread = None)
                    self.client.send(msg)
            elif torrent.doneDate<=0 and not torrent.hashString in self.lastcycle:
                self.lastcycle[torrent.hashString]=1
        return 3
Example #37
0
    # (4) XMPPのメッセージを受信したときの処理を記述
    @message_stanza_handler()
    def handle_message(self, stanza):
        # (4-1)メッセージのタイトルを設定
        if stanza.subject:
            subject = "Re: " + stanza.subject
        else:
            subject = None

        if stanza.body:
            # (4-2)メッセージの本文の作成
            body = 'You said "' + stanza.body + '".'
            # (5) メッセージオブジェクトの作成
            msg = Message(stanza_type=stanza.stanza_type,
                          from_jid=stanza.to_jid,
                          to_jid=stanza.from_jid,
                          subject=subject,
                          body=body,
                          thread=stanza.thread)
            return msg


# (6) XMPPの初期化とイベントループ
jid = sys.argv[1]
password = sys.argv[2]
settings = XMPPSettings({"password": password})
client = Client(JID(jid), [EchoBotHandler()], settings)
client.connect()

client.run()
Example #38
0
class VersionChecker(EventHandler):
    """Version checker implementation."""
    def __init__(self, my_jid, target_jid, settings):
        self.client = Client(my_jid, [self], settings)
        self.target_jid = target_jid

    def run(self):
        """Request client connection and start the main loop."""
        self.client.connect()
        self.client.run()

    def disconnect(self):
        """Request disconnection and let the main loop run for a 2 more
        seconds for graceful disconnection."""
        self.client.disconnect()
        self.client.run(timeout=2)

    @event_handler(AuthorizedEvent)
    def handle_authorized(self, event):
        """Send the initial presence after log-in."""
        request_software_version(self.client, self.target_jid, self.success,
                                 self.failure)

    def success(self, version):
        print("Name: {0}".format(version.name))
        print("Version: {0}".format(version.version))
        if version.os_name is not None:
            print("Operating System: {0}".format(version.os_name))
        else:
            print("Operating System name not available")
        self.client.disconnect()

    def failure(self, stanza):
        print("Version query failed")
        if stanza and stanza.stanza_type == "error":
            cond_name = stanza.error.condition_name
            text = stanza.error.text
            if text:
                print("Error: {0} ({1})".format(cond_name, text))
            else:
                print("Error: {0}".format(cond_name))
        self.client.disconnect()

    @event_handler(DisconnectedEvent)
    def handle_disconnected(self, event):
        """Quit the main loop upon disconnection."""
        return QUIT
Example #39
0
 def __init__(self, my_jid, target_jid, settings):
     self.client = Client(my_jid, [self], settings)
     self.target_jid = target_jid
Example #40
0
class Talkbot(DB_oper,EventHandler,XMPPFeatureHandler,Messages,Command):

    def __init__(self,jid,settings):
        self.client = Client(JID(jid),[self],settings)
        
    def run_bot(self):
        self.client.connect()
        self.client.run()

    def stop_bot(self):
        self.client.disconnect()

    @event_handler(DisconnectedEvent)
    def handle_disconnect(self,event):
        return QUIT

    @event_handler()
    def handle_all(self,event):
        logging.info(u"--{0}".format(event))

    @message_stanza_handler()
    def handle_message(self,stanza):
        if stanza.stanza_type!='chat':
            return True
        current_jid = stanza.from_jid
        body = stanza.body
        if body[0]=='-':
            logging.info(u"handle command which is {0}".format(body))
            command = body.split(' ')[0]
            print 'in main command is %s' % (command)
            self.dispatch_command(command,stanza)
            logging.info(u"handle command which is {0} done".format(body))
        else:
            logging.info(u"handle common message which is {0}".format(body))
            self.dispatch_message(stanza.body,current_jid.bare())
            logging.info(u"handle common message whcih is {0} done".format(body))
        return True

    @presence_stanza_handler("subscribe")
    def handle_subscribe(self,stanza):
        logging.info(u"{0} request presence subscripiton ".format(stanza.from_jid))
        
        sender = stanza.from_jid
        bare_jid = sender.bare().as_string()
        self.add_user(bare_jid)

        presence = Presence(to_jid=stanza.from_jid.bare(),stanza_type="subscribe")
        return [stanza.make_accept_response(),presence]

    def get_online_users(self):
        users = [x.jid for x in self.client.roster if x.subscription=='both']
        print self.client.roster
        return users

    def send_message(self,receiver,msg):
        if isinstance(receiver,str):
            receiver=JID(receiver)
        message = Message(
                        stanza_type='chat',
                        from_jid = self.client.jid,
                        to_jid = receiver,
                        body = msg,)
        self.send(message)

    def send(self,stanza):
        self.client.stream.send(stanza)

    def do_unsubscribe(self,jid,type = 'unsubscribe'):
        jid = JID(jid)
        presence = Presence(to_jid=jid,stanza_type=type)
        self.send(presence)

    def delete_from_roster(self,jid):
        self.client.roster.delItem(jid)
Example #41
0
 def __init__(self, jid, settings):
     self.client = Client(JID(jid), [self], settings)
Example #42
0
class XMPPBot(EventHandler, XMPPFeatureHandler):
  autoReconnect = False

  def __init__(self, my_jid, settings, autoReconnect=None, main_loop=None):
    self.jid = my_jid
    self.settings = settings
    if autoReconnect is not None:
      self.autoReconnect = autoReconnect
    self.do_quit = False
    self.main_loop = main_loop

  def newclient(self):
    version_provider = VersionProvider(self.settings)
    self.client = Client(
      self.jid, [self, version_provider], self.settings,
      main_loop=self.main_loop,
    )

  def start(self):
    while not self.do_quit:
      logging.info('XMPP connecting...')
      self.connect()
      self.run()
      if not self.autoReconnect:
        self.do_quit = True

  def connect(self):
    self.newclient()
    self.client.connect()

  def run(self):
    self.client.run()

  def disconnect(self):
    self.do_quit = True
    self.client.disconnect()
    try:
      self.client.run(timeout=2)
    except RuntimeError: # IOLoop is already running
      pass

  @property
  def roster(self):
    return self.client.roster

  @message_stanza_handler()
  def handle_message(self, stanza):
    if stanza.stanza_type and stanza.stanza_type.endswith('chat') and stanza.body:
      logging.info("%s said: %s", stanza.from_jid, stanza.body)
      self.last_chat_message = stanza
    else:
      logging.info("%s message: %s", stanza.from_jid, stanza.serialize())
    return True

  def send_message(self, receiver, msg):
    m = Message(
      stanza_type = 'chat',
      from_jid = self.client.jid,
      to_jid = receiver,
      body = msg,
    )
    self.send(m)

  def send(self, stanza):
    self.client.stream.send(stanza)

  def delayed_call(self, seconds, func, *args, **kwargs):
    self.client.main_loop.delayed_call(seconds, partial(func, *args, **kwargs))

  def get_vcard(self, jid, callback):
    '''callback is used as both result handler and error handler'''
    q = Iq(
      to_jid = jid.bare(),
      stanza_type = 'get'
    )
    vc = ET.Element("{vcard-temp}vCard")
    q.add_payload(vc)
    self.stanza_processor.set_response_handlers(q, callback, callback)
    self.send(q)

  def update_roster(self, jid, name=NO_CHANGE, groups=NO_CHANGE):
    self.client.roster_client.update_item(jid, name, groups)

  @presence_stanza_handler()
  def handle_presence_available(self, stanza):
    logging.info('%s[%s]', stanza.from_jid, stanza.show or 'available')
    return True

  @event_handler(DisconnectedEvent)
  def handle_disconnected(self, event):
    if self.do_quit:
      return QUIT
    else:
      logging.warn('XMPP disconnected. Reconnecting...')
      # We can't restart here because the stack will overflow
      return True

  @event_handler()
  def handle_all(self, event):
    """Log all events."""
    logging.info("-- {0}".format(event))
Example #43
0
class ChatBot(MessageMixin, UserMixin, EventHandler, XMPPFeatureHandler):
    got_roster = False
    message_queue = None
    receipt_sender = None
    ignore = set()

    def __init__(self, jid, settings, botsettings=None):
        if 'software_name' not in settings:
            settings['software_name'] = self.__class__.__name__
        if 'software_version' not in settings:
            settings['software_version'] = __version__
        version_provider = VersionProvider(settings)

        handlers = []
        if ReceiptSender:
            self.receipt_sender = rs = ReceiptSender()
            handlers.append(rs)

        handlers.extend([self, version_provider])
        self.client = Client(jid, handlers, settings)

        self.presence = defaultdict(dict)
        self.subscribes = ExpiringDictionary(default_timeout=5)
        self.invited = {}
        self.avatar_hash = None
        self.settings = botsettings

    def run(self):
        self.client.connect()
        self.jid = self.client.jid.bare()
        logger.info('self jid: %r', self.jid)
        self.update_on_setstatus = set()

        if self.receipt_sender:
            self.receipt_sender.stream = self.client.stream
        self.client.run()

    def disconnect(self):
        '''Request disconnection and let the main loop run for a 2 more
    seconds for graceful disconnection.'''
        self.client.disconnect()
        while True:
            try:
                self.client.run(timeout=2)
            except pyxmpp2.exceptions.StreamParseError:
                # we raise SystemExit to exit, expat says XML_ERROR_FINISHED
                pass
            else:
                break

    def handle_early_message(self):
        self.got_roster = True
        q = self.message_queue
        if q:
            self.now = datetime.datetime.utcnow()
            for sender, stanza in q:
                self.current_jid = sender
                self._cached_jid = None
                try:
                    timestamp = stanza.as_xml().find(
                        '{urn:xmpp:delay}delay').attrib['stamp']
                except AttributeError:
                    timestamp = None
                self.handle_message(stanza.body, timestamp)
            self.message_queue = self.__class__.message_queue = None

    @event_handler(RosterReceivedEvent)
    def roster_received(self, stanze):
        self.delayed_call(2, self.handle_early_message)
        self.delayed_call(getattr(config, 'reconnect_timeout', 24 * 3600),
                          self.signal_connect)
        nick, avatar_type, avatar_file = (getattr(config, x, None)
                                          for x in ('nick', 'avatar_type',
                                                    'avatar_file'))
        if nick or (avatar_type and avatar_file):
            self.set_vcard(nick, (avatar_type, avatar_file))
        return True

    def signal_connect(self):
        logging.info('Schedule to re-connecting...')
        self.client.disconnect()

    @message_stanza_handler()
    def message_received(self, stanza):
        if stanza.stanza_type != 'chat':
            return True
        if not stanza.body:
            logging.info("%s message: %s", stanza.from_jid, stanza.serialize())
            return True

        sender = stanza.from_jid
        body = stanza.body
        self.current_jid = sender
        self.now = datetime.datetime.utcnow()

        logging.info('[%s] %s', sender, stanza.body)
        if str(sender.bare()) in self.ignore:
            logging.info('(The above message is ignored on purpose)')
            return True

        if not self.got_roster:
            if not self.message_queue:
                self.message_queue = []
            self.message_queue.append((sender, stanza))
        else:
            self.handle_message(body)

        logging.info('done with new message')
        return True

    def send_message(self, receiver, msg):
        if isinstance(receiver, str):
            receiver = JID(receiver)

        m = Message(
            stanza_type='chat',
            from_jid=self.jid,
            to_jid=receiver,
            body=msg,
        )
        self.send(m)

    def reply(self, msg):
        self.send_message(self.current_jid, msg)

    def send(self, stanza):
        self.client.stream.send(stanza)

    def delayed_call(self, seconds, func, *args, **kwargs):
        self.client.main_loop.delayed_call(seconds,
                                           partial(func, *args, **kwargs))

    @event_handler(DisconnectedEvent)
    def handle_disconnected(self, event):
        return QUIT

    @property
    def roster(self):
        return self.client.roster

    def get_online_users(self):
        ret = [x.jid for x in self.roster if x.subscription == 'both' and \
               str(x.jid) in self.presence]
        logging.info('%d online buddies: %r', len(ret), ret)
        return ret

    def get_xmpp_status(self, jid):
        return sorted(self.presence[str(jid)].values(),
                      key=lambda x: x['priority'],
                      reverse=True)[0]

    def xmpp_setstatus(self, status, to_jid=None):
        if isinstance(to_jid, str):
            to_jid = JID(to_jid)

        presence = Presence(status=status, to_jid=to_jid)
        self.send(presence)

    def update_roster(self, jid, name=NO_CHANGE, groups=NO_CHANGE):
        self.client.roster_client.update_item(jid, name, groups)

    def removeInvitation(self):
        for ri in self.roster.values():
            if ri.ask is not None:
                self.client.roster_client.remove_item(ri.jid)
                logging.info('%s removed', ri.jid)

    def unsubscribe(self, jid, type='unsubscribe'):
        presence = Presence(to_jid=jid, stanza_type=type)
        self.send(presence)

    def subscribe(self, jid):
        self.invited[jid] = 2
        presence = Presence(to_jid=jid, stanza_type='subscribe')
        self.send(presence)

    @presence_stanza_handler('subscribe')
    def handle_presence_subscribe(self, stanza):
        logging.info('%s subscribe', stanza.from_jid)
        sender = stanza.from_jid
        bare = sender.bare()

        # avoid repeated request
        invited = False
        if bare not in self.subscribes:
            invited = self.invited.get(bare, False)
            if invited is not False:
                if invited == 2:
                    self.invited[bare] = 1
                else:
                    del self.invited[bare]
                    return stanza.make_accept_response()
                # We won't deny inivted members
                self.handle_userjoin_before()
            else:
                if config.private and str(bare) != config.root:
                    self.send_message(
                        sender,
                        _('Sorry, this is a private group, and you are not invited.'
                          ))
                    return stanza.make_deny_response()
                if not self.handle_userjoin_before():
                    return stanza.make_deny_response()

            self.current_jid = sender
            self.now = datetime.datetime.utcnow()
            try:
                self.handle_userjoin(action=stanza.stanza_type)
            except ValidationError:
                #The server is subscribing
                pass
            self.subscribes[bare] = True

        if stanza.stanza_type.endswith('ed'):
            return stanza.make_accept_response()

        if invited is False:
            presence = Presence(to_jid=stanza.from_jid.bare(),
                                stanza_type='subscribe')
            return [stanza.make_accept_response(), presence]

    @presence_stanza_handler('subscribed')
    def handle_presence_subscribed(self, stanza):
        # use the same function
        logging.info('%s subscribed', stanza.from_jid)
        return self.handle_presence_subscribe(stanza)

    @presence_stanza_handler('unsubscribe')
    def handle_presence_unsubscribe(self, stanza):
        logging.info('%s unsubscribe', stanza.from_jid)
        sender = stanza.from_jid
        self.current_jid = sender
        self.now = datetime.datetime.utcnow()
        self.handle_userleave(action=stanza.stanza_type)

        if stanza.stanza_type.endswith('ed'):
            return stanza.make_accept_response()

        presence = Presence(to_jid=stanza.from_jid.bare(),
                            stanza_type='unsubscribe')
        return [stanza.make_accept_response(), presence]

    @presence_stanza_handler('unsubscribed')
    def handle_presence_unsubscribed(self, stanza):
        # use the same function
        logging.info('%s unsubscribed', stanza.from_jid)
        return self.handle_presence_unsubscribe(stanza)

    @presence_stanza_handler()
    def handle_presence_available(self, stanza):
        if stanza.stanza_type not in ('available', None):
            return False

        jid = stanza.from_jid
        plainjid = str(jid.bare())
        if plainjid == str(self.jid):
            return

        self.now = datetime.datetime.utcnow()
        if plainjid not in self.presence:
            type = 'new'
            self.current_jid = jid
            self.user_update_presence(plainjid)
            if conn_lost_interval and self.current_user.last_seen and \
               self.now - self.current_user.last_seen < conn_lost_interval:
                type = 'reconnect'
                self.send_lost_message()
            logging.info('%s[%s] (%s)', jid, stanza.show or 'available', type)
        else:
            if jid.resource not in self.presence[plainjid]:
                self.user_update_presence(plainjid)
            logging.info('%s[%s]', jid, stanza.show or 'available')

        self.presence[plainjid][jid.resource] = {
            'show': stanza.show,
            'status': stanza.status,
            'priority': stanza.priority,
        }

        if self.get_user_by_jid(plainjid) is None:
            try:
                self.current_jid = jid
                self.handle_userjoin()
            except ValidationError:
                #The server is subscribing
                pass

        if config.warnv105 and jid.resource and \
           jid.resource.startswith('Talk.') and not jid.resource.startswith('Talk.v104'):
            # Got a Talk.v107...
            # No need to translate; GTalk only has a v105 for Chinese.
            self.send_message(
                jid,
                '警告:你正在使用的可能是不加密的 GTalk v105 版本。网络上的其它人可能会截获您的消息。这样不安全!请使用 GTalk v104 英文版或者其它 XMPP 客户端。\nGTalk 英文版: http://www.google.com/talk/index.html\nPidgin: http://www.pidgin.im/'
            )

        return True

    @presence_stanza_handler('unavailable')
    def handle_presence_unavailable(self, stanza):
        jid = stanza.from_jid
        plainjid = str(jid.bare())
        if plainjid in self.presence and plainjid != str(self.jid):
            try:
                del self.presence[plainjid][jid.resource]
            except KeyError:
                pass
            if self.presence[plainjid]:
                logging.info('%s[unavailable] (partly)', jid)
            else:
                del self.presence[plainjid]
                self.now = datetime.datetime.utcnow()
                self.user_disappeared(plainjid)
                logging.info('%s[unavailable] (totally)', jid)
        return True

    @event_handler()
    def handle_all(self, event):
        '''Log all events.'''
        logging.info('-- {0}'.format(event))

    def get_name(self, jid):
        if isinstance(jid, str):
            jid = JID(jid)
        else:
            jid = jid.bare()
        try:
            return self.roster[jid].name or hashjid(jid)
        except KeyError:
            return hashjid(jid)

    def get_vcard(self, jid=None, callback=None):
        '''callback is used as both result handler and error handler'''
        q = Iq(
            to_jid=jid and jid.bare(),
            stanza_type='get',
        )
        vc = ET.Element("{vcard-temp}vCard")
        q.add_payload(vc)
        if callback:
            self.stanza_processor.set_response_handlers(q, callback, callback)
        self.send(q)

    def set_vcard(self, nick=None, avatar=None):
        self.get_vcard(callback=partial(self._set_vcard, nick, avatar))

    def _set_vcard(self, nick=None, avatar=None, stanza=None):
        #FIXME: This doesn't seem to work with jabber.org
        q = Iq(
            from_jid=self.jid,
            stanza_type='set',
        )
        vc = ET.Element("{vcard-temp}vCard")
        if nick is not None:
            n = ET.SubElement(vc, '{vcard-temp}FN')
            n.text = nick
        if avatar is not None:
            type, picfile = avatar
            photo = ET.SubElement(vc, '{vcard-temp}PHOTO')
            t = ET.SubElement(photo, '{vcard-temp}TYPE')
            t.text = type
            d = ET.SubElement(photo, '{vcard-temp}BINVAL')
            data = open(picfile, 'rb').read()
            d.text = base64.b64encode(data).decode('ascii')
            self.avatar_hash = hashlib.new('sha1', data).hexdigest()

        q.add_payload(vc)
        self.stanza_processor.set_response_handlers(q,
                                                    self._set_vcard_callback,
                                                    self._set_vcard_callback)
        self.send(q)

    def _set_vcard_callback(self, stanza):
        if stanza.stanza_type == 'error':
            logging.error('failed to set my vCard.')
        else:
            logging.info('my vCard set.')
            self.update_presence()

    def update_presence(self):
        #TODO: update for individual users
        presence = self.settings['presence']
        x = ET.Element('{vcard-temp:x:update}x')
        if self.avatar_hash:
            photo = ET.SubElement(x, '{vcard-temp:x:update}photo')
            photo.text = self.avatar_hash
        presence.add_payload(x)
        self.send(presence)
Example #44
0
 def newclient(self):
   version_provider = VersionProvider(self.settings)
   self.client = Client(
     self.jid, [self, version_provider], self.settings,
     main_loop=self.main_loop,
   )
Example #45
0
class VersionChecker(EventHandler):
    """Version checker implementation."""
    def __init__(self, my_jid, target_jid, settings):
        self.client = Client(my_jid, [self], settings)
        self.target_jid = target_jid

    def run(self):
        """Request client connection and start the main loop."""
        self.client.connect()
        self.client.run()

    def disconnect(self):
        """Request disconnection and let the main loop run for a 2 more
        seconds for graceful disconnection."""
        self.client.disconnect()
        self.client.run(timeout = 2)

    @event_handler(AuthorizedEvent)
    def handle_authorized(self, event):
        """Send the initial presence after log-in."""
        request_software_version(self.client, self.target_jid,
                                        self.success, self.failure)

    def success(self, version):
        print("Name: {0}".format(version.name))
        print("Version: {0}".format(version.version))
        if version.os_name is not None:
            print("Operating System: {0}".format(version.os_name))
        else:
            print("Operating System name not available")
        self.client.disconnect()

    def failure(self, stanza):
        print("Version query failed")
        if stanza and stanza.stanza_type == "error":
            cond_name = stanza.error.condition_name
            text = stanza.error.text
            if text:
                print("Error: {0} ({1})".format(cond_name, text))
            else:
                print("Error: {0}".format(cond_name))
        self.client.disconnect()

    @event_handler(DisconnectedEvent)
    def handle_disconnected(self, event):
        """Quit the main loop upon disconnection."""
        return QUIT
Example #46
0
 def __init__(self, my_jid, settings):
     version_provider = VersionProvider(settings)
     self.client = Client(my_jid, [self, version_provider], settings)
Example #47
0
 def __init__(self,jid,settings):
     self.client = Client(JID(jid),[self],settings)
Example #48
0
 def __init__(self, my_jid, target_jid, settings):
     self.client = Client(my_jid, [self], settings)
     self.target_jid = target_jid
Example #49
0
class XmppClient(EventHandler):
    """
    A client to manage the XMPP connection and dispatch messages.
    """
    NAME = "Review Board XMPP Notification Client"
    VERSION = 0.1

    def __init__(self, host, port, timeout, from_jid, password, use_tls,
                 tls_verify_peer):
        self.host = host
        self.port = port
        self.timeout = timeout or 5
        self.from_jid = from_jid
        self.password = password
        self.use_tls = use_tls
        self.tls_verify_peer = tls_verify_peer

        self.req_id = None
        self.client = None
        self.stanzas = None

    @event_handler(AuthorizedEvent)
    def handle_authorized(self, event):
        logging.debug(
            u"XmppClient event handler for request #%s authorized: %s",
            self.req_id, event)
        if self.client.stream != event.stream:
            logging.debug(u"XmppClient event handler ignore event")
            return
        for stanza in self.stanzas:
            logging.debug("XmppHandler for request #%s send message to %s",
                          self.req_id, stanza.as_xml())
            event.stream.send(stanza)
        logging.debug(u"XmppHandler disconnecting stream for request #%s",
                      self.req_id)
        self.client.disconnect()

    @event_handler(DisconnectedEvent)
    def handle_disconnected(self, event):
        logging.debug(
            "XmppClient event handler for request #%s disconnected: %s",
            self.req_id, event)
        if self.client.stream != event.stream:
            logging.debug(u"XmppClient event handler ignore event")
            return
        logging.debug(
            u"XmppClient event handler closing stream for request #%s",
            self.req_id)
        self.client.close_stream()
        self.client = None
        return QUIT

    @event_handler()
    def handle_all(self, event):
        logging.debug(u"XmppClient event handler for request #%s: %s",
                      self.req_id, event)

    def send(self, req_id, stanzas):
        self.req_id = req_id
        self.stanzas = stanzas
        logging.debug(u"XmppClient start sending messages for request #%s",
                      self.req_id)
        try:
            settings = XMPPSettings({
                u"password": self.password,
                u"starttls": self.use_tls,
                u"tls_verify_peer": self.tls_verify_peer,
                u"server": self.host,
                u"port": self.port,
                u"default_stanza_timeout": self.timeout,
            })

            self.client = Client(self.from_jid, [self], settings)
            self.client.connect()
            self.client.run(timeout=self.timeout)
        except Exception, e:
            logging.error(
                "Error sending XMPP notification for request #%s: %s",
                req_id,
                e,
                exc_info=1)
Example #50
0
class XMPPClient(EventHandler, XMPPFeatureHandler):
    """
    xmpp 客户端
    """
    def __init__(self):
        self.subject_to_fun_dic = {}
        self.xmpp_client = None
        self.is_auth = False
        self.protocol = PT_XMPP
        self.jid_bare_str = None

    def init(self, jid, password, c2s_port=5222):
        """
        初始化
        :param jid: jid
        :param password: 密码
        :return:
        """
        self.JID = jid if isinstance(jid, JID) else JID(jid)
        self.jid_bare_str = self.JID.bare().as_string()
        self.password = password
        self.settings = XMPPSettings({
            u"password": password,
            u"starttls": True,
            u"tls_verify_peer": False,
            u"c2s_port": c2s_port
        })
        if c2s_port != 5222:
            logger.warn("XMPPClient::init c2s_port is :%s!!!!!" % c2s_port)

    @gevent_adaptor(use_join_result=False)
    def start(self):
        """
        服务开始
        :return:
        """
        logger.warn("XMPPClient::start listen on %s:%s:%s" %
                    (self.protocol, self.JID, self.password))
        self.xmpp_client = Client(self.JID, [self], self.settings)
        self.xmpp_client.connect()
        self.xmpp_client.run()
        self.is_auth = False

    def stop(self):
        """
        Request disconnection and let the main loop run for a 2 more
        seconds for graceful disconnection.
        """
        logger.warn("XMPPClient::stop listen on %s:%s:%s" %
                    (self.protocol, self.JID, self.password))
        assert self.xmpp_client
        self.xmpp_client.disconnect()
        self.xmpp_client.run(timeout=2)
        self.is_auth = False

    def restart(self):
        """
        服务重启
        :return:
        """
        logger.warn("XMPPClient::restart listen on %s:%s:%s" %
                    (self.protocol, self.JID, self.password))
        self.stop()
        self.start()

    @xmpp_send_adaptor()
    def _send(self, tgt_jid, subject, body):
        """
        发送消息
        :param tgt_jid:目的jid
        :param subject: 主题
        :param body:  文本
        :return:
        """
        if not self.xmpp_client.stream:
            self.restart()
        self.wait_for_auth()

        tgt_jid = tgt_jid if isinstance(tgt_jid, JID) else JID(tgt_jid)
        msg = Message(to_jid=tgt_jid,
                      body=body,
                      subject=subject,
                      stanza_type="normal")

        # _send与send的区别,send的锁有点奇怪,有时候会卡主,暂时不用锁
        # def send(self, stanza):
        # """Write stanza to the stream.
        #
        # :Parameters:
        #     - `stanza`: XMPP stanza to send.
        # :Types:
        #     - `stanza`: `pyxmpp2.stanza.Stanza`
        # """
        # with self.lock:
        #     return self._send(stanza)
        self.xmpp_client.stream._send(msg)
        logger.info("XMPPClient::_send, src_jid:%s ,src_pass:%s, des_jid:%s, subject:%s, body:%s" %\
                    (self.JID,self.password, tgt_jid, subject, body))

    @gevent_adaptor()
    def send_async(self, sto_jid, ssubject, sbody):
        """
        协程非阻塞发送
        :param sto_jid:
        :param ssubject:
        :param sbody:
        :return:
        """
        self._send(sto_jid, ssubject, sbody)

    def send_sync(self, sto_jid, ssubject, sbody):
        """
        阻塞发送
        :param sto_jid:
        :param ssubject:
        :param sbody:
        :return:
        """
        self._send(sto_jid, ssubject, sbody)

    @event_handler(ConnectingEvent)
    def handle_connected(self, event):
        """
        XMPP 连接成功
        :param event:
        :return:
        """
        pass

    @event_handler(DisconnectedEvent)
    def handle_disconnected(self, event):
        """
        XMPP 断开连接
        :param event:
        :return:
        """
        """Quit the main loop upon disconnection."""
        logger.error("XMPPClient::handle_disconnected: JID:%s!!! event:%s" %
                     (self.JID, event))
        return QUIT

    @event_handler(AuthorizedEvent)
    def handle_authorized(self, event):
        """
        OPENFIRE 授权成功
        :param event:
        :return:
        """
        logger.info("XMPPClient::handle_authorized: JID:%s!!!" % self.JID)
        self.is_auth = True

    @event_handler(RosterReceivedEvent)
    def handle_roster_received(self, event):
        """
        XMPP 接收到roster列表
        :param event:
        :return:
        """
        return True

    @event_handler(RosterUpdatedEvent)
    def handle_roster_update(self, event):
        """
        XMPP 接收到roster列表更新
        :param event:
        :return:
        """
        log_params = "jid:%s item:%s old_item:%s" % (
            self.jid_bare_str, roster_item_2_dic(
                event.item), roster_item_2_dic(event.old_item))
        logger.info("XMPPClient::handle_roster_update, %s" % log_params)

        added_ls = []
        removed_ls = []
        modified_ls = []

        item = event.item
        if item.subscription == "remove":
            self.on_roster_del_notify(item)
            removed_ls.append(item)
        elif item.subscription == "both":
            self.on_roster_add_notify(item)
            modified_ls.append(item) if event.old_item else added_ls.append(
                item)

        self.on_roster_update_notify(added_ls, removed_ls, modified_ls)

    def reg_message(self, subject, hander_fun):
        """
        注册主题接收回调
        :param subject: 主题
        :param hander_fun: 回调函数
        :return:
        """
        self.subject_to_fun_dic[subject] = hander_fun

    @message_stanza_handler("normal")
    @except_adaptor()
    @xmpp_recv_adaptor()
    def handle_message(self, from_jid, subject, body):
        """
        消息接收分发
        :param from_jid: 发送者jid
        :param subject: 发送主题
        :param body: 发送内容
        :return:
        """
        if subject not in self.subject_to_fun_dic:
            error_msg = "subject:%s not register, details:%s" % (
                subject, self.subject_to_fun_dic)
            logger.error(error_msg)
            return True

        self.subject_to_fun_dic[subject](self, from_jid, body)
        return True

    @presence_stanza_handler()
    @except_adaptor()
    def handle_presence_available(self, stanza):
        """
        XMPP 上线通知
        :param stanza:
        :return:
        """
        return True

    @presence_stanza_handler("unavailable")
    @except_adaptor()
    def handle_presence_unavailable(self, stanza):
        """
        XMPP 下线通知
        :param stanza:
        :return:
        """
        return True

    @presence_stanza_handler("subscribe")
    def handle_presence_subscribe(self, stanza):
        """
        上下线状态预定请求
        :param stanza:
        :return:
        """
        presence = Presence(to_jid=stanza.from_jid.bare(),
                            stanza_type="subscribe")
        return [stanza.make_accept_response(), presence]

    @presence_stanza_handler("subscribed")
    def handle_presence_subscribed(self, stanza):
        """
        上下线状态预定通知
        :param stanza:
        :return:
        """
        return True

    @presence_stanza_handler("unsubscribe")
    def handle_presence_unsubscribe(self, stanza):
        """
        上下线状态取消预定请求
        :param stanza:
        :return:
        """
        if not self.is_jid_in_roster(stanza.from_jid):
            return True
        presence = Presence(to_jid=stanza.from_jid.bare(),
                            stanza_type="unsubscribe")
        return [stanza.make_accept_response(), presence]

    @presence_stanza_handler("unsubscribed")
    def handle_presence_unsubscribed(self, stanza):
        """
        上下线状态取消预定通知
        :param stanza:
        :return:
        """
        return True

    def is_jid_in_roster(self, jid):
        """
        判断某个jid是否在roster中
        :param jid: jid
        :return:True/False
        """
        if not self.xmpp_client.roster_client.roster:
            return False

        for item in self.xmpp_client.roster_client.roster.items():
            if JidMgr().get_jid_str(item.jid) == JidMgr().get_jid_str(jid):
                return True
        return False

    @gevent_adaptor(use_join_result=False)
    def add_roster(self, Jid, name=None, groups=None):
        """
        添加好友
        :param Jid: 添加的jid
        :param name: 添加的用户名
        :param groups: 添加的用户组
        :return:
        """
        if self.is_jid_in_roster(Jid):
            return

        self.xmpp_client.roster_client.add_item(Jid, name, groups)
        self.xmpp_client.stream._send(
            Presence(to_jid=Jid, stanza_type='subscribe'))
        # 注意:以下方式也可以实现添加roster功能,但是用userservice 的add roster则没有handle_presence_available通知
        # UserService().add_roster(self.JID.local, Jid.local)
        # UserService().add_roster(Jid.local, self.JID.local)

    @gevent_adaptor(use_join_result=False)
    def del_roster(self, Jid):
        """
        删除好友
        :param Jid: 删除的jid
        :return:
        """
        if isinstance(Jid, str) or isinstance(Jid, unicode):
            Jid = JID(Jid)

        if not self.is_jid_in_roster(Jid):
            return
        UserService().del_roster(self.JID.local, Jid.bare().as_string())
        UserService().del_roster(Jid.local, self.JID.as_string())
        self.xmpp_client.stream._send(
            Presence(to_jid=Jid, stanza_type='unsubscribe'))

    def on_roster_del_notify(self, roster_item):
        """
        roster删除成功通知
        :param roster_item: RosterItem 对象
        :return:
        """
        pass

    def on_roster_add_notify(self, roster_item):
        """
        roster添加成功通知
        :param roster_item: RosterItem 对象
        :return:
        """
        pass

    def on_roster_update_notify(self, added_ls, removed_ls, modified_ls):
        """
        roster添加成功通知
        :param added_ls: added_ls RosterItem 列表
        :param removed_ls: removed RosterItem 列表
        :param modified_ls: modified RosterItem 列表
        :return:
        """
        pass

    def wait_for_auth(self):
        """
        等待xmpp登陆授权成功
        :return:
        """
        while not self.is_auth:
            logger.warn("XMPPClient::wait_for_auth, sleep 1s to wait for auth")
            gevent.sleep(5)
 def __init__(self, my_jid, settings):
     version_provider = VersionProvider(settings)
     self.client = Client(my_jid, [self, version_provider], settings)
     self.rpc=transmissionrpc.Client(TRANSURL,TRANSPORT,TRANSUSER,TRANSPASS)
     for user in SUBSCRIBERS:
         self.userlist[JID(user).local]=JID(user)
Example #52
0
    def handle_disconnected(self, event):
        return QUIT

    @event_handler()
    def handle_all(self, event):
        logging.info(u"-- {0}".format(event))


logging.basicConfig(level=logging.INFO)  # change to 'DEBUG' to see more

your_jid = raw_input("Your jid: ")
your_password = getpass("Your password: "******"Target jid: ")
message = raw_input("Message: ")

if sys.version_info.major < 3:
    your_jid = your_jid.decode("utf-8")
    your_password = your_password.decode("utf-8")
    target_jid = target_jid.decode("utf-8")
    message = message.decode("utf-8")

handler = MyHandler(JID(target_jid), message)
settings = XMPPSettings({
    u"password": your_password,
    u"starttls": True,
    u"tls_verify_peer": False,
})
client = Client(JID(your_jid), [handler], settings)
client.connect()
client.run()
Example #53
0
class XMPPBot(EventHandler, XMPPFeatureHandler):
    autoReconnect = False

    def __init__(self, my_jid, settings, autoReconnect=None, main_loop=None):
        self.jid = my_jid
        self.settings = settings
        if autoReconnect is not None:
            self.autoReconnect = autoReconnect
        self.do_quit = False
        self.main_loop = main_loop

    def newclient(self):
        version_provider = VersionProvider(self.settings)
        self.client = Client(
            self.jid,
            [self, version_provider],
            self.settings,
            main_loop=self.main_loop,
        )

    def start(self):
        while not self.do_quit:
            logging.info('XMPP connecting...')
            self.connect()
            self.run()
            if not self.autoReconnect:
                self.do_quit = True

    def connect(self):
        self.newclient()
        self.client.connect()

    def run(self):
        self.client.run()

    def disconnect(self):
        self.do_quit = True
        self.client.disconnect()
        try:
            self.client.run(timeout=2)
        except RuntimeError:  # IOLoop is already running
            pass

    @property
    def roster(self):
        return self.client.roster

    @message_stanza_handler()
    def handle_message(self, stanza):
        if stanza.stanza_type and stanza.stanza_type.endswith(
                'chat') and stanza.body:
            logging.info("%s said: %s", stanza.from_jid, stanza.body)
            self.last_chat_message = stanza
        else:
            logging.info("%s message: %s", stanza.from_jid, stanza.serialize())
        return True

    def send_message(self, receiver, msg):
        m = Message(
            stanza_type='chat',
            from_jid=self.client.jid,
            to_jid=receiver,
            body=msg,
        )
        self.send(m)

    def send(self, stanza):
        self.client.stream.send(stanza)

    def delayed_call(self, seconds, func, *args, **kwargs):
        self.client.main_loop.delayed_call(seconds,
                                           partial(func, *args, **kwargs))

    def get_vcard(self, jid, callback):
        '''callback is used as both result handler and error handler'''
        q = Iq(to_jid=jid.bare(), stanza_type='get')
        vc = ET.Element("{vcard-temp}vCard")
        q.add_payload(vc)
        self.stanza_processor.set_response_handlers(q, callback, callback)
        self.send(q)

    def update_roster(self, jid, name=NO_CHANGE, groups=NO_CHANGE):
        self.client.roster_client.update_item(jid, name, groups)

    @presence_stanza_handler()
    def handle_presence_available(self, stanza):
        logging.info('%s[%s]', stanza.from_jid, stanza.show or 'available')
        return True

    @event_handler(DisconnectedEvent)
    def handle_disconnected(self, event):
        if self.do_quit:
            return QUIT
        else:
            logging.warn('XMPP disconnected. Reconnecting...')
            # We can't restart here because the stack will overflow
            return True

    @event_handler()
    def handle_all(self, event):
        """Log all events."""
        logging.info("-- {0}".format(event))
Example #54
0
class BotChat(EventHandler, XMPPFeatureHandler):
    trytimes = 0
    def __init__(self):
        my_jid = JID(USER+'/Bot')
        self.my_jid = my_jid
        settings = XMPPSettings({
                            "software_name": "Clubot",
                            "software_version": __version__,
                            "software_os": "Linux",
                            "tls_verify_peer": False,
                            "starttls": True,
                            "ipv6":False,
                            "poll_interval": 10,
                            })

        settings["password"] = PASSWORD
        version_provider = VersionProvider(settings)
        self.connected = False
        mainloop = TornadoMainLoop(settings)
        self.client = Client(my_jid, [self, version_provider], settings, mainloop)
        #self.client = Client(my_jid, [self, version_provider], settings)
        self.logger = get_logger()
        self.trytimes = 0
        self.sended = []
        Logics.empty_status()

    def run(self, timeout = None):
        self.client.connect()
        self.client.run(timeout)

    def disconnect(self):
        self.client.disconnect()

    @presence_stanza_handler("subscribe")
    def handle_presence_subscribe(self, stanza):
        self.logger.info(u"{0} join us".format(stanza.from_jid))
        frm = stanza.from_jid
        presence = Presence(to_jid = frm, stanza_type = "subscribe")
        Logics.add(frm, None, stanza.show)
        r =[stanza.make_accept_response(), presence]
        if frm not in self.sended:
            self.message_bus.send_sys_msg(stanza, new_member(frm))
            self.message_bus.send_back_msg(stanza, welcome(frm))
            self.sended.append(frm)
        return r

    @presence_stanza_handler("subscribed")
    def handle_presence_subscribed(self, stanza):
        self.logger.info(u"{0!r} accepted our subscription request"
                                                    .format(stanza.from_jid))
        frm = stanza.from_jid
        presence = Presence(to_jid = frm, stanza_type = "subscribe")
        Logics.add(frm, None, stanza.show)
        r =[presence]
        r =[stanza.make_accept_response(), presence]
        if frm not in self.sended:
            self.message_bus.send_sys_msg(stanza, new_member(frm))
            self.message_bus.send_back_msg(stanza, welcome(frm))
            self.sended.append(frm)
        return r

    @presence_stanza_handler("unsubscribe")
    def handle_presence_unsubscribe(self, stanza):
        self.logger.info(u"{0} canceled presence subscription"
                                                    .format(stanza.from_jid))
        presence = Presence(to_jid = stanza.from_jid.bare(),
                                                    stanza_type = "unsubscribe")
        nick = Logics.get_one(stanza.from_jid).nick
        self.message_bus.send_sys_msg(stanza, u'{0} 离开群'.format(nick))
        Logics.drop(stanza.from_jid.bare())
        r =[stanza.make_accept_response(), presence]
        return r

    @presence_stanza_handler("unsubscribed")
    def handle_presence_unsubscribed(self, stanza):
        self.logger.info(u"{0!r} acknowledged our subscrption cancelation"
                                                    .format(stanza.from_jid))
        Logics.drop(stanza.from_jid.bare())
        return True

    @presence_stanza_handler(None)
    def handle_presence_available(self, stanza):
        self.logger.info(r"{0} has been online".format(stanza.from_jid))
        if stanza.from_jid.bare().as_string() != USER:
            Logics.set_online(stanza.from_jid, stanza.show)
        self.message_bus.send_offline_message(stanza)

    @presence_stanza_handler("unavailable")
    def handle_presence_unavailable(self, stanza):
        self.logger.info(r"{0} has been offline".format(stanza.from_jid))
        frm = stanza.from_jid
        if frm.bare().as_string() == USER:
            self.logger.info('bot go to offline')
            self.disconnect()
        Logics.set_offline(frm)

    @message_stanza_handler()
    def handle_message(self, stanza):
        body = stanza.body
        frm = stanza.from_jid.bare().as_string()
        if not body: return True
        self.logger.info("receive message '{0}' from {1}"
                                        .format(body, stanza.from_jid))
        if body.startswith('$') or body.startswith('-'):
            self.message_bus.send_command(stanza, body)
        #elif body.startswith('<') and frm == BRIDGE:
        #    self.message_bus.send_qq_msg(stanza, body)
        else:
            self.message_bus.send_all_msg(stanza, body)
        return True

    @event_handler(DisconnectedEvent)
    def handle_disconnected(self, event):
        return QUIT

    @event_handler(ConnectedEvent)
    def handle_connected(self, event):
        self.message_bus = MessageBus(self.my_jid, self.stream)
        self.connected = True
        BotChat.trytimes = 0

    @property
    def roster(self):
        return self.client.roster

    @property
    def stream(self):
        return self.client.stream

    def invite_member(self, jid):
        logging.info('invite {0}'.format(jid))
        p1 = Presence(from_jid = self.my_jid, to_jid = jid,
                      stanza_type = 'subscribe')
        p = Presence(from_jid = self.my_jid, to_jid = jid,
                     stanza_type = 'subscribed')
        self.stream.send(p)
        self.stream.send(p1)

    @event_handler(RosterUpdatedEvent)
    def handle_roster_update(self, event):
        item = event.item

    @event_handler(RosterReceivedEvent)
    def handle_roster_received(self, event):
        dbstatus = Logics.get_global_info('status').value
        if not dbstatus:
            status = STATUS
        else:
            status = dbstatus
        p = Presence(status=status)
        self.client.stream.send(p)
        ret = [x.jid.bare() for x in self.roster if x.subscription == 'both']
        self.logger.info(' -- roster:{0}'.format(ret))
        members = Logics.get_members()
        members = [m.email for m in members]
        [Logics.add(frm) for frm in ret if not Logics.get_one(frm)]
        if IMPORT:
            [self.invite_member(JID(m)) for m in members if JID(m) not in ret]
        #else:
            #[del_member(JID(m)) for m in members if JID(m) not in ret]

    @event_handler()
    def handle_all(self, event):
        self.logger.info(u"-- {0}".format(event))
Example #55
0
class ChatBot(MessageMixin, UserMixin, EventHandler, XMPPFeatureHandler):
  got_roster = False
  message_queue = None
  ignore = set()

  def __init__(self, jid, settings, botsettings=None):
    if 'software_name' not in settings:
      settings['software_name'] = self.__class__.__name__
    if 'software_version' not in settings:
      settings['software_version'] = __version__
    version_provider = VersionProvider(settings)
    self.client = Client(jid, [self, version_provider], settings)
    self.presence = defaultdict(dict)
    self.subscribes = ExpiringDictionary(default_timeout=5)
    self.invited = {}
    self.avatar_hash = None
    self.settings = botsettings

  def run(self):
    self.client.connect()
    self.jid = self.client.jid.bare()
    logger.info('self jid: %r', self.jid)
    self.update_on_setstatus = set()
    self.client.run()

  def disconnect(self):
    '''Request disconnection and let the main loop run for a 2 more
    seconds for graceful disconnection.'''
    self.client.disconnect()
    while True:
      try:
        self.client.run(timeout = 2)
      except pyxmpp2.exceptions.StreamParseError:
        # we raise SystemExit to exit, expat says XML_ERROR_FINISHED
        pass
      else:
        break

  def handle_early_message(self):
    self.got_roster = True
    q = self.message_queue
    if q:
      self.now = datetime.datetime.utcnow()
      for sender, stanza in q:
        self.current_jid = sender
        self._cached_jid = None
        try:
          timestamp = stanza.as_xml().find('{urn:xmpp:delay}delay').attrib['stamp']
        except AttributeError:
          timestamp = None
        self.handle_message(stanza.body, timestamp)
      self.message_queue = self.__class__.message_queue = None

  @event_handler(RosterReceivedEvent)
  def roster_received(self, stanze):
    self.delayed_call(2, self.handle_early_message)
    self.delayed_call(getattr(config, 'reconnect_timeout', 24 * 3600), self.signal_connect)
    nick, avatar_type, avatar_file = (getattr(config, x, None) for x in ('nick', 'avatar_type', 'avatar_file'))
    if nick or (avatar_type and avatar_file):
      self.set_vcard(nick, (avatar_type, avatar_file))
    return True

  def signal_connect(self):
    logging.info('Schedule to re-connecting...')
    self.client.disconnect()

  @message_stanza_handler()
  def message_received(self, stanza):
    if stanza.stanza_type != 'chat':
      return True
    if not stanza.body:
      logging.info("%s message: %s", stanza.from_jid, stanza.serialize())
      return True

    sender = stanza.from_jid
    body = stanza.body
    self.current_jid = sender
    self.now = datetime.datetime.utcnow()

    logging.info('[%s] %s', sender, stanza.body)
    if str(sender.bare()) in self.ignore:
      logging.info('(The above message is ignored on purpose)')
      return True

    if not self.got_roster:
      if not self.message_queue:
        self.message_queue = []
      self.message_queue.append((sender, stanza))
    else:
      self.handle_message(body)

    logging.info('done with new message')
    return True

  def send_message(self, receiver, msg):
    if isinstance(receiver, str):
      receiver = JID(receiver)

    m = Message(
      stanza_type = 'chat',
      from_jid = self.jid,
      to_jid = receiver,
      body = msg,
    )
    self.send(m)

  def reply(self, msg):
    self.send_message(self.current_jid, msg)

  def send(self, stanza):
    self.client.stream.send(stanza)

  def delayed_call(self, seconds, func, *args, **kwargs):
    self.client.main_loop.delayed_call(seconds, partial(func, *args, **kwargs))

  @event_handler(DisconnectedEvent)
  def handle_disconnected(self, event):
    return QUIT

  @property
  def roster(self):
    return self.client.roster

  def get_online_users(self):
    ret = [x.jid for x in self.roster if x.subscription == 'both' and \
           str(x.jid) in self.presence]
    logging.info('%d online buddies: %r', len(ret), ret)
    return ret

  def get_xmpp_status(self, jid):
    return sorted(self.presence[str(jid)].values(), key=lambda x: x['priority'], reverse=True)[0]

  def xmpp_add_user(self, jid):
    presence = Presence(to_jid=jid, stanza_type='subscribe')
    self.send(presence)

  def xmpp_setstatus(self, status, to_jid=None):
    if isinstance(to_jid, str):
      to_jid = JID(to_jid)

    presence = Presence(status=status, to_jid=to_jid)
    self.send(presence)

  def update_roster(self, jid, name=NO_CHANGE, groups=NO_CHANGE):
    self.client.roster_client.update_item(jid, name, groups)

  def removeInvitation(self):
    for ri in self.roster.values():
      if ri.ask is not None:
        self.client.roster_client.remove_item(ri.jid)
        logging.info('%s removed', ri.jid)

  def unsubscribe(self, jid, type='unsubscribe'):
    presence = Presence(to_jid=jid, stanza_type=type)
    self.send(presence)

  def subscribe(self, jid):
    self.invited[jid] = 2
    presence = Presence(to_jid=jid, stanza_type='subscribe')
    self.send(presence)

  @presence_stanza_handler('subscribe')
  def handle_presence_subscribe(self, stanza):
    logging.info('%s subscribe', stanza.from_jid)
    sender = stanza.from_jid
    bare = sender.bare()

    # avoid repeated request
    invited = False
    if bare not in self.subscribes:
      invited = self.invited.get(bare, False)
      if invited is not False:
        if invited == 2:
          self.invited[bare] = 1
        else:
          del self.invited[bare]
          return stanza.make_accept_response()
        # We won't deny inivted members
        self.handle_userjoin_before()
      else:
        if config.private and str(bare) != config.root:
          self.send_message(sender, _('Sorry, this is a private group, and you are not invited.'))
          return stanza.make_deny_response()
        if not self.handle_userjoin_before():
          return stanza.make_deny_response()

      self.current_jid = sender
      self.now = datetime.datetime.utcnow()
      try:
        self.handle_userjoin(action=stanza.stanza_type)
      except ValidationError:
        #The server is subscribing
        pass
      self.subscribes[bare] = True

    if stanza.stanza_type.endswith('ed'):
      return stanza.make_accept_response()

    if invited is False:
      presence = Presence(to_jid=stanza.from_jid.bare(),
                          stanza_type='subscribe')
      return [stanza.make_accept_response(), presence]

  @presence_stanza_handler('subscribed')
  def handle_presence_subscribed(self, stanza):
    # use the same function
    logging.info('%s subscribed', stanza.from_jid)
    return self.handle_presence_subscribe(stanza)

  @presence_stanza_handler('unsubscribe')
  def handle_presence_unsubscribe(self, stanza):
    logging.info('%s unsubscribe', stanza.from_jid)
    sender = stanza.from_jid
    self.current_jid = sender
    self.now = datetime.datetime.utcnow()
    self.handle_userleave(action=stanza.stanza_type)

    if stanza.stanza_type.endswith('ed'):
      return stanza.make_accept_response()

    presence = Presence(to_jid=stanza.from_jid.bare(),
                        stanza_type='unsubscribe')
    return [stanza.make_accept_response(), presence]

  presence_stanza_handler('unsubscribed')
  def handle_presence_unsubscribed(self, stanza):
    # use the same function
    logging.info('%s unsubscribed', stanza.from_jid)
    return self.handle_presence_unsubscribe(stanza)

  @presence_stanza_handler()
  def handle_presence_available(self, stanza):
    if stanza.stanza_type not in ('available', None):
      return False

    jid = stanza.from_jid
    plainjid = str(jid.bare())
    if plainjid == str(self.jid):
      return

    self.now = datetime.datetime.utcnow()
    if plainjid not in self.presence:
      type = 'new'
      self.current_jid = jid
      self.user_update_presence(plainjid)
      if conn_lost_interval and self.current_user.last_seen and \
         self.now - self.current_user.last_seen < conn_lost_interval:
        type = 'reconnect'
        self.send_lost_message()
      logging.info('%s[%s] (%s)', jid, stanza.show or 'available', type)
    else:
      if jid.resource not in self.presence[plainjid]:
        self.user_update_presence(plainjid)
      logging.info('%s[%s]', jid, stanza.show or 'available')

    self.presence[plainjid][jid.resource] = {
      'show': stanza.show,
      'status': stanza.status,
      'priority': stanza.priority,
    }

    if self.get_user_by_jid(plainjid) is None:
      try:
        self.current_jid = jid
        self.handle_userjoin()
      except ValidationError:
        #The server is subscribing
        pass

    if config.warnv105 and jid.resource and \
       jid.resource.startswith('Talk.') and not jid.resource.startswith('Talk.v104'):
      # Got a Talk.v107...
      # No need to translate; GTalk only has a v105 for Chinese.
      self.send_message(jid, '警告:你正在使用的可能是不加密的 GTalk v105 版本。网络上的其它人可能会截获您的消息。这样不安全!请使用 GTalk v104 英文版或者其它 XMPP 客户端。\nGTalk 英文版: http://www.google.com/talk/index.html\nPidgin: http://www.pidgin.im/')

    return True

  @presence_stanza_handler('unavailable')
  def handle_presence_unavailable(self, stanza):
    jid = stanza.from_jid
    plainjid = str(jid.bare())
    if plainjid in self.presence and plainjid != str(self.jid):
      try:
        del self.presence[plainjid][jid.resource]
      except KeyError:
        pass
      if self.presence[plainjid]:
        logging.info('%s[unavailable] (partly)', jid)
      else:
        del self.presence[plainjid]
        self.now = datetime.datetime.utcnow()
        self.user_disappeared(plainjid)
        logging.info('%s[unavailable] (totally)', jid)
    return True

  @event_handler()
  def handle_all(self, event):
    '''Log all events.'''
    logging.info('-- {0}'.format(event))

  def get_name(self, jid):
    if isinstance(jid, str):
      jid = JID(jid)
    else:
      jid = jid.bare()
    try:
      return self.roster[jid].name or hashjid(jid)
    except KeyError:
      return hashjid(jid)

  def get_vcard(self, jid=None, callback=None):
    '''callback is used as both result handler and error handler'''
    q = Iq(
      to_jid = jid and jid.bare(),
      stanza_type = 'get',
    )
    vc = ET.Element("{vcard-temp}vCard")
    q.add_payload(vc)
    if callback:
      self.stanza_processor.set_response_handlers(q, callback, callback)
    self.send(q)

  def set_vcard(self, nick=None, avatar=None):
    self.get_vcard(callback=partial(self._set_vcard, nick, avatar))

  def _set_vcard(self, nick=None, avatar=None, stanza=None):
    #FIXME: This doesn't seem to work with jabber.org
    q = Iq(
      from_jid = self.jid,
      stanza_type = 'set',
    )
    vc = ET.Element("{vcard-temp}vCard")
    if nick is not None:
      n = ET.SubElement(vc, '{vcard-temp}FN')
      n.text = nick
    if avatar is not None:
      type, picfile = avatar
      photo = ET.SubElement(vc, '{vcard-temp}PHOTO')
      t = ET.SubElement(photo, '{vcard-temp}TYPE')
      t.text = type
      d = ET.SubElement(photo, '{vcard-temp}BINVAL')
      data = open(picfile, 'rb').read()
      d.text = base64.b64encode(data).decode('ascii')
      self.avatar_hash = hashlib.new('sha1', data).hexdigest()

    q.add_payload(vc)
    self.stanza_processor.set_response_handlers(
      q, self._set_vcard_callback, self._set_vcard_callback)
    self.send(q)

  def _set_vcard_callback(self, stanza):
    if stanza.stanza_type == 'error':
      logging.error('failed to set my vCard.')
    else:
      logging.info('my vCard set.')
      self.update_presence()

  def update_presence(self):
    #TODO: update for individual users
    presence = self.settings['presence']
    x = ET.Element('{vcard-temp:x:update}x')
    if self.avatar_hash:
      photo = ET.SubElement(x, '{vcard-temp:x:update}photo')
      photo.text = self.avatar_hash
    presence.add_payload(x)
    self.send(presence)
Example #56
0
class QXBot(EventHandler, XMPPFeatureHandler):
    def __init__(self):
        my_jid = JID(USER + '/Bot')
        self.my_jid = my_jid
        settings = XMPPSettings({
            "software_name": "qxbot",
            "software_version": __version__,
            "software_os": "Linux",
            "tls_verify_peer": False,
            "starttls": True,
            "ipv6": False,
            "poll_interval": 10,
        })

        settings["password"] = PASSWORD
        version_provider = VersionProvider(settings)
        event_queue = settings["event_queue"]
        self.webqq = WebQQ(QQ, event_queue)
        self.connected = False
        #self.mainloop = TornadoMainLoop(settings)
        self.mainloop = EpollMainLoop(settings)
        self.client = Client(my_jid, [self, version_provider], settings,
                             self.mainloop)
        self.logger = get_logger()
        self.msg_dispatch = MessageDispatch(self, self.webqq, BRIDGES)
        self.xmpp_msg_queue = Queue.Queue()

    def run(self, timeout=None):
        self.client.connect()
        self.client.run(timeout)

    def disconnect(self):
        self.client.disconnect()
        while True:
            try:
                self.run(2)
            except:
                pass
            else:
                break

    @presence_stanza_handler("subscribe")
    def handle_presence_subscribe(self, stanza):
        self.logger.info(u"{0} join us".format(stanza.from_jid))
        return stanza.make_accept_response()

    @presence_stanza_handler("subscribed")
    def handle_presence_subscribed(self, stanza):
        self.logger.info(u"{0!r} accepted our subscription request".format(
            stanza.from_jid))
        return stanza.make_accept_response()

    @presence_stanza_handler("unsubscribe")
    def handle_presence_unsubscribe(self, stanza):
        self.logger.info(u"{0} canceled presence subscription".format(
            stanza.from_jid))
        return stanza.make_accept_response()

    @presence_stanza_handler("unsubscribed")
    def handle_presence_unsubscribed(self, stanza):
        self.logger.info(
            u"{0!r} acknowledged our subscrption cancelation".format(
                stanza.from_jid))

    @presence_stanza_handler(None)
    def handle_presence_available(self, stanza):
        self.logger.info(r"{0} has been online".format(stanza.from_jid))

    @presence_stanza_handler("unavailable")
    def handle_presence_unavailable(self, stanza):
        self.logger.info(r"{0} has been offline".format(stanza.from_jid))

    @message_stanza_handler()
    def handle_message(self, stanza):
        if self.webqq.connected:
            self.msg_dispatch.dispatch_xmpp(stanza)
        else:
            self.xmpp_msg_queue.put(stanza)

    @event_handler(DisconnectedEvent)
    def handle_disconnected(self, event):
        return QUIT

    @event_handler(ConnectedEvent)
    def handle_connected(self, event):
        pass

    @event_handler(RosterReceivedEvent)
    def handle_roster_received(self, event):
        """ 此处代表xmpp已经连接
        开始连接QQ, 先将检查是否需要验证码的handler加入到mainloop
        """
        checkhandler = CheckHandler(self.webqq)
        self.mainloop.add_handler(checkhandler)
        self.connected = True

    @event_handler(CheckedEvent)
    def handle_webqq_checked(self, event):
        """ 第一步已经完毕, 删除掉检查的handler, 将登录前handler加入mainloop"""
        bloginhandler = BeforeLoginHandler(self.webqq, password=QQ_PWD)
        self.mainloop.remove_handler(event.handler)
        self.mainloop.add_handler(bloginhandler)

    @event_handler(BeforeLoginEvent)
    def handle_webqq_blogin(self, event):
        """ 登录前完毕开始真正的登录 """
        loginhandler = LoginHandler(self.webqq)
        self.mainloop.remove_handler(event.handler)
        self.mainloop.add_handler(loginhandler)

    @event_handler(WebQQLoginedEvent)
    def handle_webqq_logined(self, event):
        """ 登录后将获取群列表的handler放入mainloop """
        self.mainloop.remove_handler(event.handler)
        self.mainloop.add_handler(GroupListHandler(self.webqq))

    @event_handler(GroupListEvent)
    def handle_webqq_group_list(self, event):
        """ 获取群列表后"""
        self.mainloop.remove_handler(event.handler)
        data = event.data
        group_map = {}
        if data.get("retcode") == 0:
            group_list = data.get("result", {}).get("gnamelist", [])
            for group in group_list:
                gcode = group.get("code")
                group_map[gcode] = group

        self.webqq.group_map = group_map
        self.webqq.group_lst_updated = False  # 开放添加GroupListHandler
        i = 1
        for gcode in group_map:
            if i == len(group_map):
                self.mainloop.add_handler(
                    GroupMembersHandler(self.webqq, gcode=gcode, done=True))
            else:
                self.mainloop.add_handler(
                    GroupMembersHandler(self.webqq, gcode=gcode, done=False))

            i += 1

    @event_handler(GroupMembersEvent)
    def handle_group_members(self, event):
        """ 获取所有群成员 """
        self.mainloop.remove_handler(event.handler)
        members = event.data.get("result", {}).get("minfo", [])
        self.webqq.group_m_map[event.gcode] = {}
        for m in members:
            uin = m.get("uin")
            self.webqq.group_m_map[event.gcode][uin] = m
        cards = event.data.get("result", {}).get("cards", [])
        for card in cards:
            uin = card.get("muin")
            group_name = card.get("card")
            self.webqq.group_m_map[event.gcode][uin]["nick"] = group_name

        # 防止重复添加GroupListHandler
        if not self.webqq.group_lst_updated:
            self.webqq.group_lst_updated = True
            self.mainloop.add_handler(GroupListHandler(self.webqq, delay=300))

    @event_handler(WebQQRosterUpdatedEvent)
    def handle_webqq_roster(self, event):
        """ 群成员都获取完毕后开启,Poll获取消息和心跳 """
        self.mainloop.remove_handler(event.handler)
        self.msg_dispatch.get_map()
        if not self.webqq.polled:
            self.webqq.polled = True
            self.mainloop.add_handler(PollHandler(self.webqq))
        if not self.webqq.heartbeated:
            self.webqq.heartbeated = True
            hb = HeartbeatHandler(self.webqq)
            self.mainloop.add_handler(hb)
        while True:
            try:
                stanza = self.xmpp_msg_queue.get_nowait()
                self.msg_dispatch.dispatch_xmpp(stanza)
            except Queue.Empty:
                break
        self.webqq.connected = True

    @event_handler(WebQQHeartbeatEvent)
    def handle_webqq_hb(self, event):
        """ 心跳完毕后, 延迟60秒在此触发此事件 重复心跳 """
        self.mainloop.remove_handler(event.handler)
        self.mainloop.add_handler(HeartbeatHandler(self.webqq, delay=60))

    @event_handler(WebQQPollEvent)
    def handle_webqq_poll(self, event):
        """ 延迟1秒重复触发此事件, 轮询获取消息 """
        self.mainloop.remove_handler(event.handler)
        self.mainloop.add_handler(PollHandler(self.webqq))

    @event_handler(WebQQMessageEvent)
    def handle_webqq_msg(self, event):
        """ 有消息到达, 处理消息 """
        self.msg_dispatch.dispatch_qq(event.message)

    @event_handler(RetryEvent)
    def handle_retry(self, event):
        """ 有handler触发异常, 需重试 """
        self.mainloop.remove_handler(event.handler)
        handler = event.cls(self.webqq, event.req, *event.args, **event.kwargs)
        self.mainloop.add_handler(handler)

    @event_handler(RemoveEvent)
    def handle_remove(self, event):
        """ 触发此事件, 移除handler """
        self.mainloop.remove_handler(event.handler)

    def send_qq_group_msg(self, group_uin, content):
        """ 发送qq群消息 """
        handler = GroupMsgHandler(self.webqq,
                                  group_uin=group_uin,
                                  content=content)
        self.mainloop.add_handler(handler)

    @property
    def roster(self):
        return self.client.roster

    @property
    def stream(self):
        return self.client.stream

    @event_handler()
    def handle_all(self, event):
        self.logger.info(u"-- {0}".format(event))

    def make_message(self, to, typ, body):
        """ 构造消息
            `to` - 接收人 JID
            `typ` - 消息类型
            `body` - 消息主体
        """
        if typ not in ['normal', 'chat', 'groupchat', 'headline']:
            typ = 'chat'
        m = Message(from_jid=self.my_jid,
                    to_jid=to,
                    stanza_type=typ,
                    body=body)
        return m

    def send_msg(self, to, body):
        if not isinstance(to, JID):
            to = JID(to)
        msg = self.make_message(to, 'chat', body)
        self.stream.send(msg)