fritzy / SleekXMPP

Python 2.6+/3.1+ XMPP Library
http://groups.google.com/group/sleekxmpp-discussion
Other
1.1k stars 301 forks source link

Can't quite figure out what I'm doing wrong here. #227

Open jayd3e opened 11 years ago

jayd3e commented 11 years ago

I am try to use the oneshot example in the documentation to send a single facebook message at a time. Using this class:

class SendMsgBot(ClientXMPP):

    """
    A basic SleekXMPP bot that will log in, send a message,
    and then log out.
    """

    def __init__(self, jid, recipient, message):
        ClientXMPP.__init__(self, jid, None)

        # The message we wish to send, and the JID that
        # will receive it.
        self.recipient = recipient
        self.msg = message

        # The session_start event will be triggered when
        # the bot establishes its connection with the server
        # and the XML streams are ready for use. We want to
        # listen for this event so that we we can initialize
        # our roster.
        self.add_event_handler("session_start", self.start)

    def start(self, event):
        """
        Process the session_start event.

        Typical actions for the session_start event are
        requesting the roster and broadcasting an initial
        presence stanza.

        Arguments:
            event -- An empty dictionary. The session_start
                     event does not provide any additional
                     data.
        """
        self.send_presence()
        self.get_roster()

        self.send_message(mto=self.recipient,
                          mbody=self.msg,
                          mtype='chat')

        # Using wait=True ensures that the send queue will be
        # emptied before ending the session.
        self.disconnect(wait=True)

The one important alteration in this class, is that I don't actually pass a password into ClientXMPP. Since I'm sending a message on behalf of another user, I won't have their password obviously, but I will have their access_token. I assumed that I wouldn't have to provide a password, seeing as I go on to see an access_token and api_key later on.

I run this code at the point where I actually want to send the message:

    message = 'This is an invite to Course<%s>.' % course.id
    xmpp = SendMsgBot('%s@chat.facebook.com' % request.user.facebook_auth_user.username,
                      'recipient@chat.facebook.com',
                      message)
    xmpp.credentials['api_key'] = request.registry.settings['clusterflunk.rauth.facebook.client_id']
    xmpp.credentials['access_token'] = get_app_access_token(request.registry.settings)

    server = ('chat.facebook.com', 5222)
    import pdb;pdb.set_trace()
    if xmpp.connect(server):
        xmpp.process(block=True)
    else:
        pass

This stack overflow post(http://stackoverflow.com/questions/10732616/connecting-to-facebook-chat-using-sleekxmpp) lead me to believe that I could simply provide sleekxmpp with the api_key and access_token credentials, and it would intelligently use X-FACEBOOK-PLATFORM as an auth method.

I am receiving the following error message:

2013-03-07 18:29:47,706 INFO  [sleekxmpp.xmlstream.xmlstream][Dummy-1] Negotiating TLS
2013-03-07 18:29:47,707 INFO  [sleekxmpp.xmlstream.xmlstream][Dummy-1] Using SSL version: 3
2013-03-07 18:29:47,900 WARNI [sleekxmpp.xmlstream.cert][Dummy-1] Could not find pyasn1 and pyasn1_modules. SSL certificate COULD NOT BE VERIFIED.
2013-03-07 18:29:48,251 INFO  [sleekxmpp.features.feature_mechanisms.mechanisms][Dummy-1] Authentication failed: not-authorized
2013-03-07 18:29:48,503 INFO  [sleekxmpp.features.feature_mechanisms.mechanisms][Dummy-1] Authentication failed: not-authorized
2013-03-07 18:29:48,505 ERROR [sleekxmpp.features.feature_mechanisms.mechanisms][Dummy-1] No appropriate login method.
2013-03-07 18:29:48,506 INFO  [sleekxmpp.xmlstream.xmlstream][Dummy-1] Waiting for </stream:stream> from server
2013-03-07 18:29:53,597 ERROR [sleekxmpp.xmlstream.xmlstream][Dummy-1] Error reading from XML stream.

Any ideas?

legastero commented 11 years ago

Did you include the xmpp_login scope when requesting the access token?

jayd3e commented 11 years ago

I did not. Is that error pretty characteristic of that?

legastero commented 11 years ago

I think so. That's the most immediate cause for the auth to fail, especially if you already know that the token hasn't expired and you've verified that the token was actually issued for your app.

jayd3e commented 11 years ago

Is the access_token being provided the app access_token or the user access_token?

jayd3e commented 11 years ago

B/c I just changed it from the app access_token to the user access_token, and the error messages changed to:

2013-03-07 21:30:38,385 INFO  [sleekxmpp.xmlstream.xmlstream][Dummy-1] Negotiating TLS
2013-03-07 21:30:38,386 INFO  [sleekxmpp.xmlstream.xmlstream][Dummy-1] Using SSL version: 3
2013-03-07 21:30:38,576 WARNI [sleekxmpp.xmlstream.cert][Dummy-1] Could not find pyasn1 and pyasn1_modules. SSL certificate COULD NOT BE VERIFIED.
2013-03-07 21:30:38,934 INFO  [sleekxmpp.features.feature_mechanisms.mechanisms][Dummy-1] Authentication failed: not-authorized
2013-03-07 21:30:39,407 INFO  [sleekxmpp.features.feature_bind.bind][event_thread_0] Node set to: -{id}@chat.facebook.com/{id}
2013-03-07 21:30:40,237 WARNI [sleekxmpp.xmlstream.cert][event_thread_0] Could not find pyasn1 and pyasn1_modules. SSL certificate expiration COULD NOT BE VERIFIED.
2013-03-07 21:30:41,024 INFO  [sleekxmpp.xmlstream.xmlstream][event_thread_0] Waiting for </stream:stream> from server
legastero commented 11 years ago

Yes, access_token is a user access token. I haven't looked into how app access tokens integrate with their XMPP service.

jayd3e commented 11 years ago

Hmmm so I'm still stumped. I am now using my access token generated by the Graph API Tool, and I have the correct Api Key. Do I need the two modules specified:

Could not find pyasn1 and pyasn1_modules. SSL certificate COULD NOT BE VERIFIED.
legastero commented 11 years ago

It is a good idea to pip install those modules in order to do cert validation.

So, using the Graph API tool you mentioned, I did:

1) Click generate new token 2) Select xmpp_login from the extended permissions tab 3) Generate the new token 4) Click Debug to get the app ID for the graph api tool. 5) Set xmpp.credentials['api_key'] to the app ID 6) Set xmpp.credentials['access_token'] to the generated token 7) Run code, it logs in and works using platform auth

Is that the same as what you did?

jayd3e commented 11 years ago

Went through those steps exactly, including pip installing the modules that were missing, and got this log output:

2013-03-07 22:17:53,291 INFO  [sleekxmpp.xmlstream.xmlstream][Dummy-1] Negotiating TLS
2013-03-07 22:17:53,292 INFO  [sleekxmpp.xmlstream.xmlstream][Dummy-1] Using SSL version: 3
2013-03-07 22:17:53,844 INFO  [sleekxmpp.features.feature_mechanisms.mechanisms][Dummy-1] Authentication failed: not-authorized
2013-03-07 22:17:54,316 INFO  [sleekxmpp.features.feature_bind.bind][event_thread_0] Node set to: -527547491@chat.facebook.com/e9ce62d3_4D75D13FEBA15
2013-03-07 22:17:55,016 INFO  [sleekxmpp.xmlstream.xmlstream][event_thread_0] CERT: Time until certificate expiration: 343 days, 1:42:03.983422
2013-03-07 22:17:55,752 INFO  [sleekxmpp.xmlstream.xmlstream][event_thread_0] Waiting for </stream:stream> from server
legastero commented 11 years ago

Is it still sending your message?

If you enable debug level logging, you should be able to see which SASL mech is being tried and failing. Which version of Sleek are you using?

jayd3e commented 11 years ago

It's not sending my message. Enabled debug level logging, and I'm not seeing any extra log output. I'm using version 1.1.11.

jayd3e commented 11 years ago

And early when you said "run code", did you actually test out my code and it worked? B/c if that's true, then it must be an environment issue or something.

legastero commented 11 years ago

By run code I meant using the send_client.py example, edited to include the credentials

jayd3e commented 11 years ago

Ok now I'm having a little success, I'm using send_client.py exactly now and added a few lines for the credentials:

    xmpp = SendMsgBot(opts.jid, opts.password, opts.to, opts.message)
    xmpp.credentials['api_key'] = ....key....
    xmpp.credentials['access_token'] = ...token...

It looks like it's establishing a connection as it outputs this line:

DEBUG    SEND (IMMED): <iq type="set" id="211892b0-e211-4058-9e07-58fa83441ed1-2"><session xmlns="urn:ietf:params:xml:ns:xmpp-session" /></iq>
DEBUG    RECV: <iq type="result" id="211892b0-e211-4058-9e07-58fa83441ed1-2"><session xmlns="urn:ietf:params:xml:ns:xmpp-session" /></iq>
DEBUG    Established Session

And here it's sending the message:

DEBUG    SEND: <message to="1131870061@chat.facebook.com" type="chat" xml:lang="en"><body>This is a message</body></message>
DEBUG    SEND (IMMED): </stream:stream>

But the message isn't showing up in my inbox.

legastero commented 11 years ago

Ok, so playing around some more:

Sending a message to first.last@chat.facebook.com wouldn't work for me. Sending a message to idnumber@chat.facebook.com did.

The second issue, which isn't really an issue since you're doing one-off messages is that Facebook uses a custom receipt stanza which Sleek doesn't automatically answer, which causes Facebook to kill the stream.

jayd3e commented 11 years ago

Ok I'm using ids, so I don't think the first thing is an issue. So the second comment you made isn't an issue? And all you had to do was add the two lines mentioned above? Thanks for sticking with me, I'm really confused as to why this isn't working. I seem to be getting authenticated now, but the message still isn't showing up.

legastero commented 11 years ago

Other things I remember from trying to get this working in the past:

Are the two users friends? Did you check the 'Other' inbox tab? Are you receiving any chats/online status from the XMPP user in the popup chat window?

jayd3e commented 11 years ago

The two users are indeed friends. Yup checked the 'Other' tab, nothing in there. And no, not receiving either chats or online status from the XMPP user.

legastero commented 11 years ago

There is an advanced settings pane if you click on the gear in the chat box. Make sure both users are configured to allow chats, but that probably is the default already.

The last thing I can think of is to try using one of the other examples, say echo_client.py, and sending a message from the web user to the XMPP user.

jayd3e commented 11 years ago

Echo client just worked for me. Thanks man. I think I can figure everything out now, I just needed an example of it working.

jayd3e commented 11 years ago

So the problem seemed to be that all fb ids require a dash in front of them? When specifying the address, any idea why this is? So an address like so "1234567@chat.facebook.com" won't work, but "-1234567@chat.facebook.com" will.

legastero commented 11 years ago

Huh, that's good to know. As for why, I have no clue why Facebook implemented their gateway like that. There's no XMPP level reason for it.

jayd3e commented 11 years ago

So cool, I now have what I need, thanks for the help.