January 2012 Archives

之前說到XMPP已經成為即時訊息的標準,那就利用Facebook手機即時通的便捷快速來送Facebook Chat訊息。
其實只要拿之前GTalk的程式碼,稍微修改一下,就可發送了。其中差異在於DIGEST-MD5的認證機制。在Smack討論區已經有人實作出XMPP DIGEST-MD5的物件。只要將login部份加上DIGEST-MD5認證。
※注意:facebook chat發送對象的帳號是-XXXXX@@chat.facebook.com,而XXXXX是一組數字,必須由c.displayBuddyList();列出才會知道。
完整程式碼如下:

package messenger;


import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.util.Collection;


import org.jivesoftware.smack.Chat;

import org.jivesoftware.smack.ConnectionConfiguration;

import org.jivesoftware.smack.MessageListener;

import org.jivesoftware.smack.Roster;

import org.jivesoftware.smack.RosterEntry;

import org.jivesoftware.smack.SASLAuthentication;

import org.jivesoftware.smack.XMPPConnection;

import org.jivesoftware.smack.XMPPException;

import org.jivesoftware.smack.packet.Message;


public class facebook implements MessageListener {

XMPPConnection connection;

private volatile static facebook fclient;

static String username = "xxxxxxxx";

static String password = "xxxxxxxx";

private facebook(){}

public static facebook getInstance(){

if (fclient == null) {

synchronized (facebook.class){

if (fclient == null) {

fclient = new facebook();

}

}

}

return fclient;

}


public void login(String userName, String password) throws XMPPException {

SASLAuthentication.registerSASLMechanism("DIGEST-MD5", MySASLDigestMD5Mechanism.class);

ConnectionConfiguration config = new ConnectionConfiguration(

"chat.facebook.com", 5222, "chat.facebook.com");

config.setCompressionEnabled(true);

config.setSASLAuthenticationEnabled(true);

connection = new XMPPConnection(config);


connection.connect();

connection.login(userName, password);

}

public void sendMessage(String message, String to) throws XMPPException {

Chat chat = connection.getChatManager().createChat(to, this);

chat.sendMessage(message);

}


public void displayBuddyList() {

Roster roster = connection.getRoster();

roster.setSubscriptionMode(Roster.SubscriptionMode.accept_all);

Collection<RosterEntry> entries = roster.getEntries();


System.out.println("\n\n" + entries.size() + " buddy(ies):");

for (RosterEntry r : entries) {

System.out.println(r.getUser());

}

}

public void addRoster(String bot, String email, String input){

facebook c = facebook.getInstance();

try {

addRoster(bot,input);

c.sendMessage(input, email);

} catch (XMPPException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

public void addRoster(String bot,String input){

facebook c = facebook.getInstance();

try {

c.login(username, password);

Roster roster = connection.getRoster();

roster.createEntry(input, null, null);

} catch (XMPPException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

c.disconnect();

}

public void disconnect() {

connection.disconnect();

}


public void processMessage(Chat chat, Message message) {

if (message.getType() == Message.Type.chat)

System.out.println(chat.getParticipant() + " says: "

+ message.getBody());

}


public static void main(String args[]) throws XMPPException, IOException {

// declare variables

facebook c = facebook.getInstance();

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

String msg;


// turn on the enhanced debugger

XMPPConnection.DEBUG_ENABLED = false;


// provide your login information here

c.login(username, password);


c.displayBuddyList();

System.out.println("-----");

System.out.println("Enter your message in the console.");

System.out.println("All messages will be sent to abhijeet.maharana");

System.out.println("-----\n");


while (!(msg = br.readLine()).equals("bye")) {

// your buddy's gmail address goes here

c.sendMessage(msg, "-xxxxxxxx@chat.facebook.com");

}


c.disconnect();

System.exit(0);

}


public void alert(String bot,String email, String msg) {

facebook c = facebook.getInstance();


// turn on the enhanced debugger

XMPPConnection.DEBUG_ENABLED = false;


// provide your login information here

try {

c.login(username, password);

c.sendMessage(msg, email);

} catch (XMPPException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

c.disconnect();

}

}

自由軟體鑄造場得知Microsoft 打開 Messenger 大門 開始支援 XMPP,因此目前主流即時訊息都支援XMPP,包括Facebook chat

既然如此,當然找看看熟悉的Smack套件是否也有MSN的sample code。果然Github上有MS放出的LiveSDK,便有JAVAAndroid的程式碼。有空再把拿token那程式改成用httpclient
JAVA程式碼如下:

package messenger;


import java.net.URL;

import java.net.URLDecoder;


import javax.swing.JOptionPane;


import org.jivesoftware.smack.ConnectionConfiguration;

import org.jivesoftware.smack.PacketListener;

import org.jivesoftware.smack.Roster;

import org.jivesoftware.smack.RosterEntry;

import org.jivesoftware.smack.SASLAuthentication;

import org.jivesoftware.smack.XMPPConnection;

import org.jivesoftware.smack.XMPPException;

import org.jivesoftware.smack.filter.MessageTypeFilter;

import org.jivesoftware.smack.filter.PacketFilter;

import org.jivesoftware.smack.filter.PacketTypeFilter;

import org.jivesoftware.smack.packet.Message;

import org.jivesoftware.smack.packet.Packet;

import org.jivesoftware.smack.packet.Presence;

import org.jivesoftware.smack.util.StringUtils;


/**

 * XmppClient class has all the XMPP specific logic. This class uses smack

 * library to connect to windows live messenger service. For Windows Live Xmpp

 * documentation see <link>

 */

public class msn {


public static final String Host = "xmpp.messenger.live.com";

public static final int Port = 5222;

public static final String Service = "messenger.live.com";


private String accessToken;

private XMPPConnection connection;


/**

* This block initializes smack with SASL mechanism used by Windows Live.

*/

static {

SASLAuthentication.registerSASLMechanism("X-MESSENGER-OAUTH2",

XMessengerOAuth2.class);

SASLAuthentication.supportSASLMechanism("X-MESSENGER-OAUTH2");

}


public static void main(String[] args) throws InterruptedException {

/**

* 1. Set up a string with the path to the website.

* 2. Create a desktop variable.  The desktop class uses the computer's default browser to open the URL.

* 3. Load the URL.

* 4. Browse to the URL.

*/


//TODO put your own clientId here.

//String clientId = "000000004807AE0A";

//String scopes = "wl.messenger";

//String signInUrl = "https://oauth.live.com/authorize?client_id=" + clientId + "&redirect_uri=https://oauth.live.com/desktop&response_type=token&scope=" + scopes;


try {

// launch a web browser to take the user through the OAuth 2.0 consent flow

//BareBonesBrowserLaunch.browse(signInUrl);


// pop a dialog that tells the developer to copy and paste the URL and put it into a text box in the dialog

//String returnUrlString = (String)JOptionPane.showInputDialog("After completing the OAuth consent flow in the browser, copy and paste the return URL into this dialog box");

String returnUrlString = "https://oauth.live.com/desktop#access_token=EwAoAq1DBAAUlbRWyAJjK5w968Ru3Cyt%2f6GvwXwAAcQc5qjgPRbE4InoTBM3bsPTd0eAZIcSZiRxdNSMn3K8jSLvqJjDBfhjf3fd71C%2fBlGBFqDAs%2fFZYb1WYDPUfbL239Y3sXKA8ZFZgMOKIWWb%2beib%2fyTpNIW6m4O4SUMhAu5GYe3DAiC7JsXAnLgu%2bUFeUpF%2fEMjmrdRGzVDUjNNuwfKgdqpgvBD5kWAU1A3NNGhwxJZZhwOpKcogIcWZ%2fR7eKdFsYjGN9riWjBh2gcmk%2bGiEMifAxI0PoqeECqq9otHAZ1fz9NxCUbFssIQuy5mxlzjPu%2fWl9wmwRvZnHkDY4EiuDrfUw6SHflWirQ74nQ2fjv7Ew7Dk4nl%2fvvTymxcDZgAACPsOZ%2fNUm4kh%2bABDsVcnU0eMbHeEikN9WrYIwYTrTQKy2WtThAVuuNwsJOiqgyP%2fInBCWZMudPy0qGOlFoJriKm16OiYrgf44t9aua6MO7Lq0hJchmmbBm9%2fEsSquOhKaLOrNgx%2fVPs%2bqycd6sBkqzPJMD69eIztb%2fPnllMbX%2f4qDz1cUU1ySkE%2f3%2bMlENfPDKiNARAvKxSpljsM6yjMgwPCTawChrUgExYjbeGxAR16vY1N7ibTmwcgIB9ewoyghGeNBI7GHBdpOMzBbp%2b6YZQYBDHwPc7SXYoxPq1s8TAlfdXrrpj2J2kEpxuwPGM6VnBJN1yOdFsolRENflmAkTCh4gAA&token_type=bearer&expires_in=3600&scope=wl.messenger";

// take the string URL from the dialog and programmatically cram it into the access token parameter

String accessToken = urlTokenizerHelper(returnUrlString);


// log in using the access token

msn client = new msn(accessToken);

client.logIn();

Roster r = client.getRoster();

System.out.println(r.toString());

// make sure the program hasn't already closed before the login has completed

// in a real XMPP client, this would be replaced with waiting on UI events and Xmpp events 

Thread.sleep(1000000);

} catch (Exception e) {

System.out.println(e);

}

}


/**

* This function helps to extract the access_token query string parameter from the return URL.

*/

public static String urlTokenizerHelper(String urlString) {

URL returnUrl = null;

try{

returnUrl = new URL(urlString);

}catch(Exception e){}

String queryParameters = returnUrl.getRef();

queryParameters = queryParameters.substring(queryParameters.indexOf("access_token"));

queryParameters = queryParameters.substring(queryParameters.indexOf("=")+1);


String encodedAccessToken = queryParameters.substring(0, queryParameters.indexOf("&"));


return URLDecoder.decode(encodedAccessToken);


}

/**

* Constructor

* @param accessToken

*            The OAuth2.0 access token to be used for login.

*/

public msn(String accessToken) {

this.accessToken = accessToken;

}


/**

* Get the Roster for this client instance.

* @return The full Roster for the client.

*/

public Roster getRoster() {

return this.connection.getRoster();

}


/**

* Get the Jid for this client instance.

*/

public String getLocalJid() {

return StringUtils.parseBareAddress(this.connection.getUser());

}


/**

* Log in the client to the messenger service.

*/

public void logIn() {


// Create a connection. We use service name in config and asmack will do

// SRV look up locate the xmpp server.

ConnectionConfiguration connConfig = new ConnectionConfiguration(

msn.Service);

connConfig.setRosterLoadedAtLogin(true);

this.connection = new XMPPConnection(connConfig);


try {

this.connection.connect();


// We do not need user name in this case.

this.connection.login("", this.accessToken);

} catch (XMPPException ex) {

this.connection = null;

return;

}


System.out.println(String.format("Logged in as %s",

this.connection.getUser()));

// set the message and presence handlers

this.setPacketFilters();


// Set the status to available

Presence presence = new Presence(Presence.Type.available);

this.connection.sendPacket(presence);

}


/**

* Send a text message to the buddy.

* @param to

*            The Buddy Jid.

* @param text

*            The text message to be sent.

*/

public void sendMessage(String to, String text) {

Message msg = new Message(to, Message.Type.chat);

msg.setBody(text);

this.connection.sendPacket(msg);

}


/**

* Set the packet filters for handling incoming stanzas.

*/

private void setPacketFilters() {

if (this.connection != null) {

PacketFilter presenceFilter = new PacketTypeFilter(Presence.class);

this.connection.addPacketListener(new PacketListener() {

public void processPacket(Packet packet) {

Presence presence = (Presence) packet;

handlePresenceReceived(presence);

}

}, presenceFilter);


PacketFilter messageFilter = new MessageTypeFilter(

Message.Type.chat);

this.connection.addPacketListener(new PacketListener() {

public void processPacket(Packet packet) {

Message message = (Message) packet;

if (message.getBody() != null) {

handleMessageReceived(message);

}

}

}, messageFilter);

}

}


/**

* Handle the presence stanza received.

* @param presence

*            The received presence stanza.

*/

private void handlePresenceReceived(Presence presence) {

String from = StringUtils.parseBareAddress(presence.getFrom());

System.out.println(String.format(

"Presence received from Jid: %s, Name: %s", from,

this.getContactName(from)));

}


/**

* Handle the message stanza received.

* @param message

*            The received message stanza.

*/

private void handleMessageReceived(Message message) {

String from = StringUtils.parseBareAddress(message.getFrom());

System.out.println(String.format(

"Message received from Jid: %s, Name: %s", from,

this.getContactName(from)));

}


/**

* Get friendly name of a contact given the jid.

* @param jid

*            Jid for the target contact.

* @return The friendly name by looking up roster.

*/

private String getContactName(String jid) {

Roster roster = this.connection.getRoster();

RosterEntry entry = roster.getEntry(jid);

return entry.getName();

}

}


April 2012

Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30          

Archives

Powered by Movable Type 4.34-en

About this Archive

This page is an archive of entries from January 2012 listed from newest to oldest.

July 2011 is the previous archive.

March 2012 is the next archive.

Find recent content on the main index or look in the archives to find all content.