xmpp中取好友状态

magicgod 2008-03-16
为了把状态变更发为博客文章,需要知道好友状态。

监视了一下来往的xml,选中了presence回调方法。

监视很简单:
    j.add_xml_callback do |x|
      debug_log("xml: #{x}")
      false
    end


注意最后要返回false,这样就表示允许后面的回调处理,比如message, presence之类的。

加入presence的回调
    j.add_presence_callback do |presence|  
      begin
       #Robot.debug_log("presence: #{presence}")
       if presence!=nil && presence.from!=nil && presence.status!=nil && !presence.status.empty?
          email=Robot.split_email(presence.from)
          process_status(presence.status,email)
        end
      rescue => detail
        Robot.exception_log("process status error:",detail)
      end
    end


回调的参数非常简单就是一个对象presence, 是这个类:Jabber::Presence。具体参见:http://home.gna.org/xmpp4r/rdoc/classes/Jabber/Presence.html

里面的status属性就是好友发来的状态文本。

当然要处理的过程中要比较一下是否与原来的状态不同,另外忽略掉空状态,有些客户端是不发送状态的。

使用xmpp4r,已经在gtalk和openfire里试过了,可以正常使用。
greateWei 2009-07-03
confluence gtalk用户状态插件代码

package com.atlassian.confluence.extra.config;

import com.atlassian.confluence.core.ConfluenceActionSupport;
import com.atlassian.confluence.core.Administrative;
import com.atlassian.confluence.setup.bandana.ConfluenceBandanaContext;
import com.atlassian.confluence.extra.GtalkConnection;
import com.atlassian.bandana.BandanaManager;
import com.opensymphony.util.TextUtils;

/**
 * Action to configure the API key for your Google Maps api.
 */
public class ConfigureGtalkAction extends ConfluenceActionSupport implements Administrative
{
    BandanaManager bandanaManager;
    String gtalkAccount;
    String gtalkPassword;

    public void setBandanaManager(BandanaManager bandanaManager)
    {
        this.bandanaManager = bandanaManager;
    }

    public String execute() throws Exception
    {
        ConfluenceBandanaContext context = new ConfluenceBandanaContext();
        if (TextUtils.stringSet(gtalkAccount)) {
            bandanaManager.setValue(context, GtalkConnection.GTALK_ACCOUNT, gtalkAccount);
        }
        gtalkAccount = (String) bandanaManager.getValue(context, GtalkConnection.GTALK_ACCOUNT);

        if (TextUtils.stringSet(gtalkPassword)) {
            bandanaManager.setValue(context, GtalkConnection.GTALK_PASSWORD, gtalkPassword);
        }
        gtalkPassword = (String) bandanaManager.getValue(context, GtalkConnection.GTALK_PASSWORD);

        return SUCCESS;
    }

    public String getGtalkAccount()
    {
        return gtalkAccount;
    }

    public String getGtalkPassword()
    {
        return gtalkPassword;
    }

    public void setGtalkAccount(String gtalk_account)
    {
        this.gtalkAccount = gtalk_account;
    }

    public void setGtalkPassword(String gtalk_password)
    {
        this.gtalkPassword = gtalk_password;
    }

    public String getActionName(String fullClassName)
    {
        return "Configure GTalk Presence Macro";
    }
}


package com.atlassian.confluence.extra;

import org.jivesoftware.smack.GoogleTalkConnection;
import org.jivesoftware.smack.XMPPException;
import org.apache.log4j.Category;
import org.apache.commons.lang.StringUtils;
import com.atlassian.confluence.setup.bandana.ConfluenceBandanaContext;
import com.atlassian.bandana.BandanaManager;
import bucket.container.ContainerManager;

/**
 * Created by IntelliJ IDEA.
 * User: nolen
 * Date: Mar 1, 2006
 * Time: 3:41:20 PM
 * To change this template use File | Settings | File Templates.
 */
public class GtalkConnection extends GoogleTalkConnection {

    public static final Category log = Category.getInstance(GtalkConnection.class);

    private static GtalkConnection con = null;
    public static final String GTALK_ACCOUNT = "extra.gtalk.account.key";
    public static final String GTALK_PASSWORD = "extra.gtalk.password.key";


    private GtalkConnection() throws XMPPException { }

    public static GtalkConnection getCon()
    {

        if(con == null){

            BandanaManager bandanaManager = (BandanaManager) ContainerManager.getComponent("bandanaManager");
            String account = getGtalkAccount(bandanaManager);
            String password = getGtalkPassword(bandanaManager);

            if(StringUtils.isEmpty(account) || StringUtils.isEmpty(password)){
              // No account set up, so return null and let the macro handle it.
                log.error("No account set up, so return null and let the macro handle it.");
                return null;
            }

            try {
                log.debug("Getting Connection");
                con = new GtalkConnection();
                log.debug("Getting Login");
                con.login(account, password);

                // Wait half second to let GTalk update the roster info.
                // If this fails, nothing bad happens, except the first
                // request may get no data
                try {
                    log.debug("sleeping half sec.");
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } catch (XMPPException e) {
                e.printStackTrace();
            }
        }
        return con;
    }


    public static String getGtalkAccount(BandanaManager bandanaManager){
        return (String) bandanaManager.getValue(new ConfluenceBandanaContext(), GTALK_ACCOUNT);
    }

    public static String getGtalkPassword(BandanaManager bandanaManager){
        return (String) bandanaManager.getValue(new ConfluenceBandanaContext(), GTALK_PASSWORD);
    }

}


package com.atlassian.confluence.extra;

import com.atlassian.confluence.renderer.radeox.macros.MacroUtils;
import com.atlassian.confluence.user.AuthenticatedUserThreadLocal;
import com.atlassian.confluence.util.velocity.VelocityUtils;
import com.atlassian.confluence.setup.BootstrapManager;
import com.atlassian.renderer.RenderContext;
import com.atlassian.renderer.v2.RenderMode;
import com.atlassian.renderer.v2.RenderUtils;
import com.atlassian.renderer.v2.macro.BaseMacro;
import com.atlassian.renderer.v2.macro.ResourceAware;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Category;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Presence;

import java.util.Map;

/**
 * Created by IntelliJ IDEA.
 * User: nolen
 * Date: Feb 28, 2006
 * Time: 7:18:00 PM
 * To change this template use File | Settings | File Templates.
 */
public class GtalkPresenceMacro extends BaseMacro implements ResourceAware {

  public static final Category log = Category.getInstance(GtalkPresenceMacro.class);
  private String resourcePath;
  private BootstrapManager bootstrapManager;

  public boolean hasBody() {
    return false;
  }

  public RenderMode getBodyRenderMode() {
    return RenderMode.ALL.and(RenderMode.suppress(RenderMode.F_PARAGRAPHS));
  }

  public boolean isInline() {
    return true;
  }

  public String getResourcePath() {
    return resourcePath;
  }

  public void setResourcePath(String resourcePath) {
    this.resourcePath = resourcePath;

  }

  public void setBootstrapManager(BootstrapManager bootstrapManager) {
    this.bootstrapManager = bootstrapManager;
  }

  public String execute(Map params, String body, RenderContext context) {

    String id = (String) params.get("0");
    id = id.trim();

    if (StringUtils.isEmpty(id)) {
      return RenderUtils.error("There was a problem understanding the gtalk account your requested.");
    } else {
      return getGtalkPresence(id);
    }

  }

  private String getGtalkPresence(String user) {

    Map velocityContext = MacroUtils.defaultVelocityContext();
    try {
      GtalkConnection con = GtalkConnection.getCon();

      if (con == null) {
        log.error("Connection was null");
        velocityContext.put("remoteUser", AuthenticatedUserThreadLocal.getUser());
        return VelocityUtils.getRenderedTemplate("/templates/gtalk-not-configured.vm", velocityContext);
      }

      Roster roster = con.getRoster();

      if (roster == null) {
        log.error("Roster is null. " + roster);
        return RenderUtils.error("There was a problem logging into the Google Talk service.");
      }

      if (!roster.contains(user)) {
        // Add the member to the roster
        roster.createEntry(user, null, null);
        return RenderUtils.error("We've attempted to add " + user + " to our roster. " +  user + " will remain invisible until he gives us permission to see his presence.");
      } else {
        log.debug(user + " is in our roster.");
      }


      if (roster.getPresence(user) != null) {
        Presence presence = roster.getPresence(user);
        Presence.Mode mode = presence.getMode();
        String status = presence.getStatus();
        if(status == null) status = "";

        if (mode == Presence.Mode.AVAILABLE) {
          return getPresenceUrl(user, "im_available", status);
        } else if (mode == Presence.Mode.AWAY) {
          return getPresenceUrl(user, "im_away", status);
        } else if (mode == Presence.Mode.CHAT) {
          return getPresenceUrl(user, "im_free_chat", status);
        } else if (mode == Presence.Mode.DO_NOT_DISTURB) {
          return getPresenceUrl(user, "im_dnd", status);
        } else if (mode == Presence.Mode.EXTENDED_AWAY) {
          return getPresenceUrl(user, "im_away", status);
        } else if (mode == Presence.Mode.INVISIBLE) {
          return getPresenceUrl(user, "im_invisible", status);
        } else {
          return getPresenceUrl(user, "im_invisible", status);
        }
      } else {
        return getPresenceUrl(user, "im_invisible", "");
      }


    } catch (XMPPException e) {
      e.printStackTrace();
      return RenderUtils.error("There was a problem getting presence info for " + user);
    }
  }

  private String getPresenceUrl(String user, String icon, String status) {
    return "<A href='jabber:" + user + "' title='" + status + "'>" +
      "<img src='" + bootstrapManager.getBaseUrl() + getResourcePath() + "/" + icon + ".gif' " +
      "style='vertical-align:bottom;' " +
      "/>" + user + "</a>";
  }

}

Global site tag (gtag.js) - Google Analytics