Package vc.fq.fantalker

Source Code of vc.fq.fantalker.FantalkerServlet

/*
* Copyright 2012, Unicorn-Feng
* All rights reserved.
*
* This file is part of Fantalker.
* Fantalker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* Fantalker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Fantalker.  If not, see <http://www.gnu.org/licenses/>.
*/

/**
*饭否GTalk机器人 Fantalker
*Fanfou Chat Robot for Google Talk
*Author: 烽麒 Unicorn-Feng
*Website: http://fq.vc
*/

package vc.fq.fantalker;

import java.io.IOException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Collections;
import javax.cache.CacheManager;
import javax.servlet.http.*;
import com.google.appengine.api.memcache.stdimpl.GCache;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.memcache.stdimpl.GCacheFactory;
import com.google.appengine.api.urlfetch.HTTPHeader;
import com.google.appengine.api.urlfetch.HTTPRequest;
import com.google.appengine.api.urlfetch.HTTPMethod;
import com.google.appengine.api.urlfetch.HTTPResponse;
import com.google.appengine.api.urlfetch.URLFetchService;
import com.google.appengine.api.urlfetch.URLFetchServiceFactory;
import com.google.appengine.api.xmpp.JID;
import com.google.appengine.api.xmpp.Message;
import com.google.appengine.api.xmpp.XMPPService;
import com.google.appengine.api.xmpp.XMPPServiceFactory;
import com.google.appengine.labs.repackaged.org.json.JSONException;
import com.google.appengine.labs.repackaged.org.json.JSONObject;


/**
* 此类用于处理xmpp消息
* 接收来自 /_ah/xmpp/message/chat/ 的消息
* @author 烽麒 Unicorn-Feng
* @link http://fq.vc
*/
@SuppressWarnings("serial")
public class FantalkerServlet extends HttpServlet
{

  /**
   * 用于处理GET请求
   */
  public void doGet(HttpServletRequest req, HttpServletResponse resp)
    throws IOException
  {
    resp.setContentType("text/html; charset=UTF-8");
    resp.getWriter().println("你不该来这里的,快回去!<br>");
    resp.getWriter().println("<a href='http://fantalker.appspot.com'>回主页</a>");
  }
 
 
  /**
   * 用于处理POST请求,即接收到的xmpp消息
   * 机器人主函数
   */
  public void doPost(HttpServletRequest req, HttpServletResponse resp)
    throws IOException
  {
    req.setCharacterEncoding("UTF-8");
    resp.setCharacterEncoding("UTF-8");
    resp.setContentType("text/html; charset=utf-8");
    XMPPService xmpp = XMPPServiceFactory.getXMPPService();
    Message message = xmpp.parseMessage(req);
    JID fromJID = message.getFromJid();                    //发送者JID
    String msgbody = message.getBody();                    //接收到的消息
    msgbody = msgbody.trim();
    if(msgbody.isEmpty())
    {
      return;
    }
    char ch;
    ch = msgbody.charAt(0)
    if(ch != '-')                              //非命令
    {
      doSend(fromJID,msgbody);
    }
    else                                  //命令
    {
      String[] msgarr = msgbody.split("\\s+");
      msgarr[0] = msgarr[0].toLowerCase();
      int intCmdID = getCmdID(msgarr[0]);
      switch (intCmdID)
      {
      case 1:                                //-oauth
        doOauth(fromJID,msgarr);
        break;
      case 2:                                //-bind
        doBind(fromJID,msgarr);
        break;
      case 3:                                //-remove
        doRemove(fromJID);
        break;
      case 4:                                //-help
        doHelp(fromJID,msgarr);
        break;
      case 5:                                //-reply/-@
        doReply(fromJID,msgarr,msgbody);
        break;
      case 6:                                //-home
        doHome(fromJID,msgarr);
        break;
      case 7:                                //-msg
        doMsg(fromJID,msgarr);
        break;
      case 8:                                //-rt
        doRt(fromJID,msgarr,msgbody);
        break;
      case 9:                                //-u
        doUser(fromJID,msgarr,msgbody);
        break;
      case 10:                              //-del
        doDel(fromJID,msgarr);
        break;
      case 11:                              //-fo
        doFollow(fromJID,msgarr,true);
        break;
      case 12:                              //-unfo
        doFollow(fromJID,msgarr,false);
        break;
      case 13:                              //-on
        doOn(fromJID);
        break;
      case 14:                              //-off
        doOff(fromJID);
        break;
      case 15:                              //-time
        doTime(fromJID,msgarr);
        break;
      case 16:                              //-public
        doPublic(fromJID);
        break;
      case 17:                              //-timeline
        doTimeLine(fromJID,msgarr);
        break;
      case 18:                              //-fav
        doFavorite(fromJID,msgarr,true);
        break;
      //case 19:                              //-unfav
        //doFavorite(fromJID,msgarr,false);
        //break;
      case 20:                              //-search
        doSearch(fromJID,msgarr);
        break;
      case -1:                              //未知命令
      default:
        Common.sendMessage(fromJID,"无效命令");
        break;
      }
    }
  }
 
 
  /**
   * 执行-bind命令绑定账号
   * @param fromJID 来源JID
   * @param msgarr 输入字符串数组
   * @throws IOException
   */
  public void doBind(JID fromJID, String[] msgarr) throws IOException
  {
    if(isOauth(fromJID))                          //判断是否已绑定
    {
      return;
    }
   
    if(msgarr.length != 2)
    {
      doHelp(fromJID,"bind");
      return;
    }
    if(msgarr[1].isEmpty())
    {
      doHelp(fromJID,"bind");
      return;
    }
    String strPIN = msgarr[1];
    long timestamp = System.currentTimeMillis() / 1000;
    long nonce = System.nanoTime();
    URL url = new URL("http://fanfou.com/oauth/access_token");

    String oauth_token = Common.getData(fromJID,"request_token");
    try {
      if(oauth_token == null | oauth_token.isEmpty())
      {
        Common.sendMessage(fromJID,"未找到有效的Request Token\n请先使用-oauth命令获取PIN码。");
        return;
      }
    } catch (NullPointerException e) {
      Common.sendMessage(fromJID,"未找到有效的Request Token\n请先使用-oauth命令获取PIN码。");
      return;
    }
   
    String params = null;
    params = "oauth_consumer_key=" + API.consumer_key
          + "&oauth_nonce=" + String.valueOf(nonce)
          + "&oauth_signature_method=HMAC-SHA1"
          + "&oauth_timestamp=" + String.valueOf(timestamp)
          + "&oauth_token=" + oauth_token
          + "&oauth_verifier=" + strPIN;
   
    params = "GET&" + URLEncoder.encode(url.toString(),"UTF-8")
          + "&" + URLEncoder.encode(params,"UTF-8");
    String sig = API.generateSignature(params);
   
    String authorization = null;
   
    authorization = "OAuth realm=\"Fantalker\",oauth_consumer_key=\"" + API.consumer_key
          + "\",oauth_signature_method=\"HMAC-SHA1\""
          + ",oauth_timestamp=\"" + String.valueOf(timestamp) + "\""
          + ",oauth_nonce=\"" + String.valueOf(nonce) + "\""
          + ",oauth_signature=\"" + sig + "\""
          + ",oauth_token=\"" + oauth_token + "\""
          + ",oauth_verifier=\"" + strPIN + "\"";

    HTTPRequest request = new HTTPRequest(url,HTTPMethod.GET);
    request.addHeader(new HTTPHeader("Authorization",authorization));
    URLFetchService service = URLFetchServiceFactory.getURLFetchService();
    HTTPResponse response = service.fetch(request);
   
    if(response.getResponseCode() == 200)
    {
      //继续执行
    }
    else if(response.getResponseCode() == 401)
    {
      Common.sendMessage(fromJID, "PIN码无效,请使用-oauth命令重新获取PIN码");
      Common.log.info(Common.getStrJID(fromJID) + " bind:" + new String(response.getContent()));
      return;
    }
    else
    {
      Common.sendMessage(fromJID,"未知错误,请重试");
      Common.log.info(Common.getStrJID(fromJID) + " bind:" + new String(response.getContent()));
      return;
    }
   
    /* 提取接收到的未经授权的Request Token */
    String tokenstring = new String(response.getContent());
    String[] tokenarr = tokenstring.split("&");
    String[] tokenarr2 = tokenarr[0].split("=");
    oauth_token = tokenarr2[1];
    tokenarr2 = tokenarr[1].split("=");
    String oauth_token_secret = tokenarr2[1];

    Common.setToken(fromJID, oauth_token, oauth_token_secret);
  }
 
 
  /**
   * 执行-del删除指定消息
   * @param fromJID
   * @param strarr
   * @throws IOException
   */
  public void doDel(JID fromJID, String[] msgarr) throws IOException
  {
    API api = Common.getAPI(fromJID);
    if(api == null)
    {
      Common.sendMessage(fromJID,"您尚未绑定账号,请使用-oauth命令绑定");
      return;
    }
    if(msgarr.length != 2)
    {
      doHelp(fromJID,"del");
      return;
    }
    if(msgarr[1].isEmpty())
    {
      doHelp(fromJID,"del");
      return;
    }
    String id = msgarr[1];
    if(id.length()<=2)
    {
      id = Common.shortID2ID(fromJID, id);
      if(id == null)
      {
        Common.sendMessage(fromJID,"找不到该短ID对应的长ID,请重新输入或使用长ID");
        return;
      }
    }
    HTTPResponse response;
    response = api.statuses_destroy(fromJID, id);
    String strmessage;
    if(response.getResponseCode() == 200)
    {
      StatusJSON jsonstatus = new StatusJSON(new String(response.getContent()));
      strmessage = "成功删除消息: " + jsonstatus.getText();
    }
    else if(response.getResponseCode() == 404)
    {
      strmessage = "没有这条消息";
    }
    else if(response.getResponseCode() == 403)
    {
      strmessage = "这不是你的消息,不能删除";
    }
    else
    {
      strmessage = Common.getError(new String(response.getContent()));
      Common.log.info(Common.getStrJID(fromJID) + "del: " + new String(response.getContent()));
    }
    Common.sendMessage(fromJID,strmessage);
  }

 
  /**
   * 执行-fav/-unfav 收藏消息或查看已收藏消息
   * @param fromJID
   * @param msgarr
   * @throws IOException
   */
  public void doFavorite(JID fromJID, String[] msgarr, boolean fav)
  {
    API api = Common.getAPI(fromJID);
    if(api == null)
    {
      Common.sendMessage(fromJID,"您尚未绑定账号,请使用-oauth命令绑定");
      return;
    }
    HTTPResponse response;
    if(msgarr.length == 1)
    {
      if(fav == true)                            //-fav
      {
        try {
          response = api.favorites(fromJID);
          Common.StatusShowResp(fromJID, response,7);
        } catch (SocketTimeoutException e) {
          Common.sendMessage(fromJID, "连接饭否API超时,请重试");
          return;
        } catch (IOException e) {
          Common.sendMessage(fromJID, "连接饭否API时出错,请重试");
          return;
        }
      }
      else                                //-unfav
      {
        doHelp(fromJID,"unfav");
        return;
      }
    }
    else if(msgarr.length == 2)
    {
      if(fav == true)
      {
        if(msgarr[1].charAt(0) == 'p' || msgarr[1].charAt(0) == 'P')
        {
          if(Common.isNumeric(msgarr[1].substring(1)))        //-fav p2
          {
            try {
              msgarr[1] = msgarr[1].substring(1);
              response = api.favorites(fromJID, msgarr[1]);
              Common.StatusShowResp(fromJID, response, 7, msgarr[1]);
              return;
            } catch (SocketTimeoutException e) {
              Common.sendMessage(fromJID, "连接饭否API超时,请重试");
              return;
            } catch (IOException e) {
              Common.sendMessage(fromJID, "连接饭否API时出错,请重试");
              return;
            }
          }
        }
      }
     
      doHelp(fromJID,"fav");
      return;
     
      /* -fav 消息ID 或 -unfav 消息ID */
      /*
      String id = msgarr[1];
      if(id.length()<=2)
      {
        id = Common.shortID2ID(fromJID, id);
        if(id == null)
        {
          Common.sendMessage(fromJID,"找不到该短ID对应的长ID,请重新输入或使用长ID");
          return;
        }
      }
      try {
        response = api.favorites_create_destroy(fromJID, id, fav);
        String strMessage;
        if(response.getResponseCode() == 200)
        {
          StatusJSON jsonstatus = new StatusJSON(new String(response.getContent()));
          if(fav == true)
          {
            strMessage = "成功收藏 : " + jsonstatus.getText();
          }
          else
          {
            strMessage = "成功取消收藏: " + jsonstatus.getText();
          }
        }
        else if(response.getResponseCode() == 403)
        {
          strMessage = "你没有通过这个用户的验证,无法收藏TA的消息";
        }
        else if(response.getResponseCode() == 404)
        {
          strMessage = "找不到该消息";
        }
        else
        {
          strMessage = Common.getError(new String(response.getContent()));
          System.out.println(new String(response.getContent()));
          System.out.println(response.getResponseCode());
        }
        Common.sendMessage(fromJID, strMessage);
      } catch (SocketTimeoutException e) {
        Common.sendMessage(fromJID, "连接饭否API时超时,请重试");
        return;
      } catch (IOException e) {
        Common.sendMessage(fromJID, "连接饭否API时出错,请重试");
        return;
      }
      */
    }
    else
    {
      if(fav == true)
      {
        doHelp(fromJID,"fav");
      }
      else
      {
        doHelp(fromJID,"unfav");
      }
    }
  }

 
  /**
   * 执行-fo/-unfo关注好友
   * @param fromJID
   * @param msgarr
   * @throws IOException
   */
  public void doFollow(JID fromJID, String[] msgarr, boolean fo) throws IOException
  {
    API api = Common.getAPI(fromJID);
    if(api == null)
    {
      Common.sendMessage(fromJID,"您尚未绑定账号,请使用-oauth命令绑定");
      return;
    }
    if(msgarr.length != 2)
    {
      doHelp(fromJID,"fo");
      return;
    }
    if(msgarr[1].isEmpty())
    {
      doHelp(fromJID,"fo");
      return;
    }
    HTTPResponse response;
    response = api.friendships_create_destroy(fromJID, msgarr[1],fo);
    String strmessage;
    if(response.getResponseCode() == 200)
    {
      if(fo)
      {
        strmessage = "成功关注 " + msgarr[1];
      }
      else
      {
        strmessage = "成功取消关注 " + msgarr[1];
      }
    }
    else if(response.getResponseCode() == 404)
    {
      strmessage = "找不到该用户";
    }
    else
    {
      strmessage = Common.getError(new String(response.getContent()));
    }
    Common.sendMessage(fromJID,strmessage);
  }


  /**
   * 执行-help 显示帮助
   * @param fromJID
   * @param msgarr 命令字符串数组
   */
  public void doHelp(JID fromJID, String[] msgarr)
  {
    String helpMsg = null;
    if(msgarr.length == 1)
    {
      helpMsg = "Fantalker目前支持以下命令:\n"
          + "您可以通过-?/-h/-help COMMAND查询每条命令的详细用法(方括号代表参数可选):\n"
          + "-ho/-home: 查看首页时间线\n"
          + "-pub/-public: 显示20条随便看看的消息\n"
          + "-@/-r-/-reply:查看提到我的消息及 回复消息\n"
          + "-tl/-timeline: 查看指定用户已发送的消息\n"
          + "-rt:转发消息\n"
          + "-m/-msg: 查看指定消息的上下文\n"
          + "-del/-delete: 删除指定消息\n"
          + "-fav/-favorite: 查看已收藏消息\n"
          //+ "-unfav/-unfavorite: 取消收藏指定消息\n"
          + "-s/-search: 搜索指定消息\n"
          + "-u: 查看用户信息\n"
          + "-fo/-follow: 加指定用户为好友\n"
          + "-unfo/-unfollow: 删除指定好友\n"
          + "-on: 开启定时提醒\n"
          + "-off: 关闭定时提醒\n"
          //+ "-time: 设置定时提醒间隔\n"
          + "-oauth: 开始OAuth认证或进行XAuth认证\n"
          + "-bind: 绑定PIN码完成认证\n"
          + "-remove: 解除关联\n"
          + "-?/-h/-help: 显示本帮助\n"
          + "\n消息格式:\n"
          + "*作者*: 消息内容\n [ 消息长ID = 短ID ] 年-月-日 时:分:秒 <- 消息来源\n"
          + "\n如果在使用中发现有BUG,请及时联系我@烽麒 谢谢~";
    }
    else if(msgarr.length == 2)
    {
      msgarr[1] = "-" + msgarr[1];
     
      switch (getCmdID(msgarr[1]))
      {
      case 1:                                //-oauth
        helpMsg = "用法1: -oauth\n获取用于OAuth的链接\n"
            + "用法2: -oauth 用户名 密码\n"
            + "使用XAuth方式认证,免去登陆饭否网站认证的过程。\n"
            + "您的用户名密码用于提交至饭否完成认证,本程序不保存您的密码信息\n";
        break;
      case 2:                                //-bind
        helpMsg = "用法: -bind PIN码\n提供PIN码用以完成OAuth认证。PIN码可以通过访问用-oauth命令获取到的链接后获得\n";
        break;
      case 3:                                //-remove
        helpMsg = "用法: -remove\n解除现有账户绑定\n";
        break;
      case 4:                                //-help
        helpMsg = "用法: -help [COMMOND]\n显示帮助\n";
        break;
      case 5:                                //-reply/-@
        helpMsg = "用法1: -@/-r/-reply 消息ID 内容\n"
            + "回复消息ID所指定的消息,消息ID可为长ID也可为短ID\n"
            + "用法2: -@/-r/-reply [p页码]\n"
            + "显示@你的消息,页码可选\n命令如-@ p2\n";
        break;
      case 6:                                //-home
        helpMsg = "用法: -home [p页码]\n显示时间线,页码可选\n";
        break;
      case 7:                                //-msg
        helpMsg = "用法: -msg 消息ID\n显示消息ID所指定的消息及其上下文,消息ID可为长ID也可为短ID\n";
        break;
      case 8:                                //-rt
        helpMsg = "用法: -rt 消息ID [内容]\n转发指定消息ID的消息,内容可选,消息ID可为长ID也可为短ID\n";
        break;
      case 9:                                //-u
        helpMsg = "用法: -u [用户id]\n显示指定用户的详细信息,不加参数则显示已绑定用户的信息\n";
        break;
      case 10:                              //-del
        helpMsg = "用法: -del 消息ID\n删除指定消息,消息ID可为长ID也可为短ID\n";
        break;
      case 11:                              //-fo
        helpMsg = "用法: -fo 用户ID或loginname\n添加指定用户为好友\n";
        break;
      case 12:                              //-unfo
        helpMsg = "用法: -unfo 用户ID或loginname\n删除指定好友\n";
        break;
      case 13:                              //-on
        helpMsg = "用法: -on\n开启定时提醒新的@提到我的消息\n";
        break;
      case 14:                              //-off
        helpMsg = "用法: -off\n关闭定时提醒新的@提到我的消息\n";
        break;
      case 15:                              //-time
        helpMsg = "用法: -time 时间\n设置定时提醒时间间隔,现阶段仅可为5的倍数\n";
        break;
      case 16:                              //-public
        helpMsg = "用法: -public\n显示20条随便看看的消息\n";
        break;
      case 17:                              //-tl
        helpMsg = "用法1: -timeline/-tl [p页码]\n"
            + "显示当前用户已发送的消息,页码可选\n命令如-tl p2\n"
            + "用法2: -timeline/-tl 用户ID [p页码]\n"
            + "显示用户ID所指定的用户已发送的消息,页码可选\n";
        break;
      case 18:                              //-fav
        helpMsg = "用法: -favorite/-fav [p页码]\n"
            + "查看已收藏的消息,页码可选\n命令如-fav p2\n";
            //+ "用法2: -favorite/-fav 消息ID\n"
            //+ "收藏指定消息,消息ID可为长ID也可为短ID\n";
        break;
      //case 19:                              //-unfav
        //helpMsg = "用法: -unfavorite/-unfav 消息ID\n取消收藏指定消息,消息ID可为长ID也可为短ID\n";
        //break;
      case 20:                              //-search
        helpMsg = "用法: -s/-search 关键词\n"
            + "搜索含指定关键词的消息,多个关键词用|分隔\n";
        break;
      case -1:                              //未知命令
      default:
        helpMsg = "无此命令\n";
        break;
      }
    }
    else
    {
      doHelp(fromJID,"help");
      return;
    }
    Common.sendMessage(fromJID,helpMsg);
  }

 
  /**
   * 执行-help commond 显示指定命令的帮助信息
   * @param fromJID
   * @param commond 要显示帮助的命令
   */
  public void doHelp(JID fromJID, String commond)
  {
    String[] msgarr = new String[2];
    msgarr[0] = "-help";
    msgarr[1] = commond;
    doHelp(fromJID,msgarr);
  }

 
  /**
   * 执行-home命令
   * @param fromJID
   * @param msgarr
   * @throws IOException
   */
  public void doHome(JID fromJID, String[] msgarr) throws IOException
  {
    API api = Common.getAPI(fromJID);
    if(api == null)
    {
      Common.sendMessage(fromJID,"您尚未绑定账号,请使用-oauth命令绑定");
      return;
    }
    HTTPResponse response;
    int msgarr_len = msgarr.length;
    if(msgarr_len == 1)
    {
      response = api.statuses_home_timeline(fromJID);
      Common.StatusShowResp(fromJID, response,1);
    }
    else if(msgarr_len == 2)                        //-ho p2
    {
      char ch;
      ch = msgarr[1].charAt(0);
      if(ch != 'p' && ch != 'P')
      {
        doHelp(fromJID,"home");
        return;
      }
      msgarr[1] = msgarr[1].substring(1);
      if(!Common.isNumeric(msgarr[1]))
      {
        doHelp(fromJID,"home");
        return;
      }
      response = api.statuses_home_timeline(fromJID,msgarr[1]);
      Common.StatusShowResp(fromJID, response,1,msgarr[1]);
    }
    else
    {
      doHelp(fromJID,"home");
    }
  }


  /**
   * 执行-m命令显示某条消息
   * @param fromJID
   * @param msgarr
   * @throws IOException
   */
  public void doMsg(JID fromJID, String[] msgarr) throws IOException
  {
    API api = Common.getAPI(fromJID);
    if(api == null)
    {
      Common.sendMessage(fromJID,"您尚未绑定账号,请使用-oauth命令绑定");
      return;
    }
    if(msgarr.length == 2)                          //-m 7rXy196_C3k
    {
      String id = msgarr[1];
      if(id.length()<=2)
      {
        id = Common.shortID2ID(fromJID, id);
        if(id == null)
        {
          Common.sendMessage(fromJID,"找不到该短ID对应的长ID,请重新输入或使用长ID");
          return;
        }
      }
      HTTPResponse response;
      response = api.statuses_context_timeline(fromJID, id);
      if(response.getResponseCode() == 200)
      {
        Common.StatusShowResp(fromJID, response,4);
      }
      else if(response.getResponseCode() == 403)
      {
        Common.sendMessage(fromJID,"你没有通过这个用户的验证,无法查看TA的消息");
      }
      else if(response.getResponseCode() == 404)
      {
        Common.sendMessage(fromJID,"id所指定的消息不存在");
      }
      else
      {
        Common.sendMessage(fromJID,Common.getError(new String(response.getContent())));
        Common.log.info(Common.getStrJID(fromJID) + "-msg: " + new String(response.getContent()));
      }
    }
    else
    {
      doHelp(fromJID,"m");
    }
  }


  /**
   * 执行-oauth命令完成认证
   * @param fromJID 来源JID
   * @param msgarr
   * @throws IOException
   */
  public void doOauth(JID fromJID, String[] msgarr) throws IOException
  {
    if(isOauth(fromJID))                          //判断是否已绑定
    {
      return;
    }
   
    String strJID = Common.getStrJID(fromJID);
    long timestamp = System.currentTimeMillis() / 1000;
    long nonce = System.nanoTime();
    String params = null;
    String authorization;
   
    if(msgarr.length == 1)                          //OAuth
    {
      URL url = new URL("http://fanfou.com/oauth/request_token");
   
      params = "oauth_consumer_key=" + API.consumer_key
            + "&oauth_nonce=" + String.valueOf(nonce)
            + "&oauth_signature_method=HMAC-SHA1"
            + "&oauth_timestamp=" + String.valueOf(timestamp);
   
      params = "GET&" + URLEncoder.encode(url.toString(),"UTF-8")
            + "&" + URLEncoder.encode(params,"UTF-8");
      String sig = API.generateSignature(params);
         
      StringBuffer strBuf = new StringBuffer(250);
      strBuf.append("OAuth realm=\"Fantalker\",oauth_consumer_key=\"");
      strBuf.append(API.consumer_key);
      strBuf.append("\",oauth_signature_method=\"HMAC-SHA1\"");
      strBuf.append(",oauth_timestamp=\"").append(timestamp).append("\"");
      strBuf.append(",oauth_nonce=\"").append(nonce).append("\"");
      strBuf.append(",oauth_signature=\"").append(sig).append("\"");
      authorization = strBuf.toString();
     
      HTTPRequest request = new HTTPRequest(url,HTTPMethod.GET);
      request.addHeader(new HTTPHeader("Authorization",authorization));
      URLFetchService service = URLFetchServiceFactory.getURLFetchService();
      HTTPResponse response;
      try {
        response = service.fetch(request);
      } catch (SocketTimeoutException e) {
        Common.sendMessage(fromJID, "连接饭否超时,请重试");
        return;
      }
      if(response.getResponseCode() != 200)
      {
        String errMsg = "出现错误,请重试";
        Common.sendMessage(fromJID,errMsg);
        Common.log.warning(strJID + " :" + String.valueOf(response.getResponseCode()) + ": " + new String(response.getContent()));
        return;
      }
     
      /* 提取接收到的未经授权的Request Token */
      String tokenstring = new String(response.getContent());
      String[] tokenarr = tokenstring.split("&");
      String[] tokenarr2 = tokenarr[0].split("=");
      String oauth_token = tokenarr2[1];
      Common.setData(fromJID,"Account","request_token",oauth_token);
     
      /* 请求用户授权Request Token */
      String strMessage = "请访问以下网址获取PIN码: \n http://fanfou.com/oauth/authorize?oauth_token="
            + oauth_token + "&oauth_callback=oob"
            + " \n 手机用户请访问: \n http://m.fanfou.com/oauth/authorize?oauth_token="
            + oauth_token + "&oauth_callback=oob"
            + " \n 然后使用\"-bind PIN码\"命令绑定账号。";
      Common.sendMessage(fromJID,strMessage);
    }
    else if(msgarr.length == 3)                        //XAuth
    {
      URL url = new URL("http://fanfou.com/oauth/access_token");
      String username = msgarr[1];
      String password = msgarr[2];
      params = "oauth_consumer_key=" + API.consumer_key
          + "&oauth_nonce=" + String.valueOf(nonce)
          + "&oauth_signature_method=HMAC-SHA1"
          + "&oauth_timestamp=" + String.valueOf(timestamp)
          + "&x_auth_username=" + username
          + "&x_auth_password=" + password
          + "&x_auth_mode=client_auth";
   
      params = "GET&" + URLEncoder.encode(url.toString(),"UTF-8")
            + "&" + URLEncoder.encode(params,"UTF-8");
      String sig = API.generateSignature(params);
     
      authorization = "OAuth realm=\"Fantalker\",oauth_consumer_key=\"" + API.consumer_key
            + "\",oauth_signature_method=\"HMAC-SHA1\""
            + ",oauth_timestamp=\"" + String.valueOf(timestamp) + "\""
            + ",oauth_nonce=\"" + String.valueOf(nonce) + "\""
            + ",oauth_signature=\"" + sig + "\""
            + ",x_auth_username=\"" + username + "\""
            + ",x_auth_password=\"" + password + "\""
            + ",x_auth_mode=\"client_auth\"";
     
     
      HTTPRequest request = new HTTPRequest(url,HTTPMethod.GET);
      request.addHeader(new HTTPHeader("Authorization",authorization));
      URLFetchService service = URLFetchServiceFactory.getURLFetchService();
      HTTPResponse response;
      try {
        response = service.fetch(request);
      } catch (SocketTimeoutException e) {
        Common.sendMessage(fromJID, "连接饭否超时,请重试");
        return;
      }
     
      if(response.getResponseCode() == 200)
      {
        //继续执行
      }
      else if(response.getResponseCode() == 401)
      {
        Common.sendMessage(fromJID, "用户名或密码错误,请重试");
        return;
      }
      else
      {
        Common.sendMessage(fromJID,"未知错误,请重试");
        Common.log.info(Common.getStrJID(fromJID) + " xauth:" + new String(response.getContent()));
        return;
      }
      try {
        /* 提取接收到的未经授权的Request Token */
        String tokenstring = new String(response.getContent());
        String[] tokenarr = tokenstring.split("&");
        String[] tokenarr2 = tokenarr[0].split("=");
        String oauth_token = tokenarr2[1];
        tokenarr2 = tokenarr[1].split("=");
        String oauth_token_secret = tokenarr2[1];
        Common.setToken(fromJID, oauth_token, oauth_token_secret);
      } catch (ArrayIndexOutOfBoundsException e) {
        Common.sendMessage(fromJID, "未知错误,请重试");
        return;
      }

    }
    else
    {
      doHelp(fromJID,"oauth");
    }
  }


  /**
   * 执行 -on 命令开启自动提醒
   * @param fromJID
   * @throws IOException
   */
  public void doOn(JID fromJID) throws IOException
  {
    if(Common.getData(fromJID,"access_token") == null)            //判断是否已绑定
    {
      Common.sendMessage(fromJID, "您尚未绑定账号,请使用-oauth命令绑定");
      return;
    }
    Setting set = Common.getSetting(fromJID);
    set.setMention(true);
    Common.setSetting(fromJID, set);
    Common.sendMessage(fromJID, "成功开启定时提醒新的@提到我的消息 功能");
  }
 
 
  /**
   * 执行-off 命令关闭自动提醒
   * @param fromJID
   * @throws IOException
   */
  public void doOff(JID fromJID) throws IOException
  {
    if(Common.getData(fromJID,"access_token") == null)            //判断是否已绑定
    {
      Common.sendMessage(fromJID, "您尚未绑定账号,请使用-oauth命令绑定");
      return;
    }
    Setting set = Common.getSetting(fromJID);
    set.setMention(false);
    Common.setSetting(fromJID, set);
    Common.sendMessage(fromJID, "成功关闭定时提醒新的@提到我的消息 功能");
  }
 
 
  /**
   * 执行-public 命令随便看看
   * @param fromJID
   * @throws IOException
   */
  public void doPublic(JID fromJID) throws IOException
  {
    API api = Common.getAPI(fromJID);
    if(api == null)
    {
      Common.sendMessage(fromJID,"您尚未绑定账号,请使用-oauth命令绑定");
      return;
    }
    HTTPResponse response;
    response = api.statuses_public_timeline(fromJID);
    Common.StatusShowResp(fromJID, response,5);
  }
 
 
  /**
   * 执行-@ 命令回复或获取回复
   * @param fromJID
   * @param msgarr 输入字符串数组
   * @param strMessage 完整输入字符串
   * @throws IOException
   */
  public void doReply(JID fromJID, String[] msgarr, String strMessage) throws IOException
  {
    API api = Common.getAPI(fromJID);
    if(api == null)
    {
      Common.sendMessage(fromJID,"您尚未绑定账号,请使用-oauth命令绑定");
      return;
    }
    HTTPResponse response;
    int msgarr_len = msgarr.length;
    if(msgarr_len == 1)
    {
      response = api.statuses_mentions(fromJID);
      Common.StatusShowResp(fromJID, response,2);
    }
    else if(msgarr_len == 2)                        //-@ p2
    {
      char ch;
      ch = msgarr[1].charAt(0);
      if(ch != 'p' && ch != 'P')
      {
        Common.sendMessage(fromJID,"无效命令");
        return;
      }
      msgarr[1] = msgarr[1].substring(1);
      if(!Common.isNumeric(msgarr[1]))
      {
        Common.sendMessage(fromJID,"无效命令");
        return;
      }
      response = api.statuses_mentions(fromJID, msgarr[1]);
      Common.StatusShowResp(fromJID, response,2,msgarr[1]);
    }
    else                                  //-@ -WNEO5ZQt28 test t
    {
      int intIndex = strMessage.lastIndexOf(msgarr[1]) + msgarr[1].length() + 1;
      String replyMsg = strMessage.substring(intIndex);
      String id = msgarr[1];
      if(id.length()<=2)
      {
        id = Common.shortID2ID(fromJID, id);
        if(id == null)
        {
          Common.sendMessage(fromJID,"找不到该短ID对应的长ID,请重新输入或使用长ID");
          return;
        }
      }
      response = api.statuses_reply(fromJID, replyMsg, id);
      if(response == null)
      {
        return;
      }
      if(response.getResponseCode() == 200)
      {
        StatusJSON jsonStatus = new StatusJSON(new String(response.getContent()));
        Common.sendMessage(fromJID,"成功回复\n  " + jsonStatus.getText());
      }
      else if(response.getResponseCode() == 400)
      {
        try {
          JSONObject json = new JSONObject(new String(response.getContent()));
          String error = json.getString("error");
          Common.sendMessage(fromJID,error);
         
        } catch (JSONException e) {
          //e.printStackTrace();
          Common.log.warning(Common.getStrJID(fromJID) + " @:" + new String(response.getContent()));
          Common.sendMessage(fromJID,"未知错误");
        }
      }
      else
      {
        Common.sendMessage(fromJID,"未知错误");
        Common.log.info(Common.getStrJID(fromJID) + " rt:" + new String(response.getContent()));
      }

    }
  }
 
 
  /**
   * 执行-remove命令解除账号绑定
   * @param fromJID
   */
  public void doRemove(JID fromJID)
  {
    if(Common.getData(fromJID,"access_token") == null)
    {
      Common.sendMessage(fromJID,"您尚未绑定账号,请使用-oauth命令绑定");
      return;
    }
    DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
    String strJID = Common.getStrJID(fromJID);
    Key k = KeyFactory.createKey("Account", strJID);
    datastore.delete(k);
    k = KeyFactory.createKey("mention",strJID);
    datastore.delete(k);
    k = KeyFactory.createKey("setting",strJID);
    datastore.delete(k);
   
    GCache cache;
    try{
      GCacheFactory cacheFactory = (GCacheFactory) CacheManager.getInstance().getCacheFactory();
      cache = (GCache) cacheFactory.createCache(Collections.emptyMap());
      cache.remove(strJID + ",access_token");
      cache.remove(strJID + ",access_token_secret");
      cache.remove(strJID + ",last_id");
    } catch (javax.cache.CacheException e){
      Common.log.info(strJID + ":JCache " + e.getMessage());
    }
   
    Common.sendMessage(fromJID,"您已成功解除账号绑定,请使用-oauth命令再次绑定账号");
  }


  /**
   * 执行-rt 命令转发消息
   * @param fromJID
   * @param msgarr 输入字符串数组
   * @param strMessage 完整输入字符串
   * @throws IOException
   */
  public void doRt(JID fromJID, String[] msgarr, String strMessage) throws IOException
  {
    API api = Common.getAPI(fromJID);
    if(api == null)
    {
      Common.sendMessage(fromJID,"您尚未绑定账号,请使用-oauth命令绑定");
      return;
    }
    HTTPResponse response;
    int msgarr_len = msgarr.length;
    if(msgarr_len == 1)
    {
      doHelp(fromJID,"rt");
    }
    else                                  //-rt -WNEO5ZQt28 test t
    {
      int intIndex;
      String replyMsg;
      try{
        intIndex = strMessage.lastIndexOf(msgarr[1]) + msgarr[1].length() + 1;
        replyMsg = strMessage.substring(intIndex);
      } catch (StringIndexOutOfBoundsException e) {
        replyMsg = "";
      }
 
      String id = msgarr[1];
      if(id.length()<=2)
      {
        id = Common.shortID2ID(fromJID, id);
        if(id == null)
        {
          Common.sendMessage(fromJID,"找不到该短ID对应的长ID,请重新输入或使用长ID");
          return;
        }
      }
      response = api.statuses_repost(fromJID, replyMsg, id);
      if(response.getResponseCode() == 200)
      {
        StatusJSON jsonStatus = new StatusJSON(new String(response.getContent()));
        Common.sendMessage(fromJID,"成功转发\n  " + jsonStatus.getText());
      }
      else
      {
        Common.sendMessage(fromJID,Common.getError(new String(response.getContent())));
        Common.log.info(Common.getStrJID(fromJID) + " rt:" + new String(response.getContent()));
      }
    }
  }


  /**
   * 发布状态
   * @param fromJID
   * @param message 状态内容
   * @throws IOException
   */
  public void doSend(JID fromJID, String message) throws IOException
  {
    API api = Common.getAPI(fromJID);
    if(api == null)
    {
      Common.sendMessage(fromJID,"您尚未绑定账号,请使用-oauth命令绑定");
      return;
    }
    HTTPResponse response;
    response = api.statuses_send(fromJID,message);
    if(response.getResponseCode() == 200)
    {
      Common.sendMessage(fromJID,"成功发布状态");
    }
    else
    {
      Common.sendMessage(fromJID,Common.getError(new String(response.getContent())));
      Common.log.info(Common.getStrJID(fromJID) + "status.send: " + new String(response.getContent()));
    }
  }
 
 
  /**
   * 执行-search搜索指定消息
   * @param fromJID
   * @param msgarr
   */
  public void doSearch(JID fromJID, String[] msgarr)
  {
    API api = Common.getAPI(fromJID);
    if(api == null)
    {
      Common.sendMessage(fromJID,"您尚未绑定账号,请使用-oauth命令绑定");
      return;
    }
    if(msgarr.length < 2)
    {
      doHelp(fromJID,"search");
      return;
    }
   
    String keyword = "";
    for(int i=1;i<msgarr.length;i++)
    {
      keyword = keyword + msgarr[i] + " ";
    }
    keyword = keyword.substring(0,keyword.length()-1);
   
    HTTPResponse response;
    try {
      response = api.search_public_timeline(fromJID, keyword);
      Common.StatusShowResp(fromJID, response,8,null,keyword);
    } catch (SocketTimeoutException e) {
      Common.sendMessage(fromJID, "连接饭否API超时,请重试");
      return;
    } catch (IOException e) {
      Common.sendMessage(fromJID, "连接饭否API时出错,请重试");
      return;
    }
  }
 
 
  /**
   * 执行-time 命令设置定时提醒间隔
   * @param fromJID
   * @param msgarr
   * @throws IOException
   */
  public void doTime(JID fromJID, String[] msgarr) throws IOException
  {
    if(msgarr.length == 1)
    {
      doHelp(fromJID,"time");
      return;
    }
    if(!Common.isNumeric(msgarr[1]))
    {
      doHelp(fromJID,"time");
    }
    long time = Long.parseLong(msgarr[1]);
    time = time / 5;
    time = time * 5;                            //将time设置为5的倍数
    if(time == 0)
    {
      time = 5;
    }
    Setting set = Common.getSetting(fromJID);
    set.setTime(time);
    Common.setSetting(fromJID, set);
    Common.sendMessage(fromJID, "成功设置间隔时间" + String.valueOf(time) + "分钟");
  }
 
 
  /**
   * 执行-tl 显示指定用户已发送的消息
   * @param fromJID
   * @param msgarr
   * @throws IOException
   */
  public void doTimeLine(JID fromJID, String[] msgarr) throws IOException
  {
    API api = Common.getAPI(fromJID);
    if(api == null)
    {
      Common.sendMessage(fromJID,"您尚未绑定账号,请使用-oauth命令绑定");
      return;
    }
    HTTPResponse response;
    int msgarr_len = msgarr.length;
    if(msgarr_len == 1)
    {
      response = api.statuses_user_timeline(fromJID);
      Common.StatusShowResp(fromJID, response,6);
    }
    else if(msgarr_len == 2)                        //-tl p2或-tl 用户ID
    {
      char ch;
      ch = msgarr[1].charAt(0);
      if(ch == 'p' || ch == 'P')
      {
        if(Common.isNumeric(msgarr[1].substring(1)))          //-tl p2
        {
          msgarr[1] = msgarr[1].substring(1);
          response = api.statuses_user_timeline(fromJID, msgarr[1]);
          Common.StatusShowResp(fromJID, response, 6, msgarr[1]);
          return;
        }
      }
     
      response = api.statuses_user_timeline(fromJID, msgarr[1], null);
      Common.StatusShowResp(fromJID, response, 6);
    }
    else if(msgarr_len == 3)                        //-tl 用户ID p2
    {
      char ch;
      ch = msgarr[2].charAt(0);
      if(ch != 'p' && ch != 'P')
      {
        doHelp(fromJID,"timeline");
      }
      msgarr[2] = msgarr[2].substring(1);
      if(!Common.isNumeric(msgarr[2]))
      {
        doHelp(fromJID,"timeline");
      }
      response = api.statuses_user_timeline(fromJID, msgarr[1], msgarr[2]);
      Common.StatusShowResp(fromJID, response, 6, msgarr[2]);
    }
    else
    {
      doHelp(fromJID,"timeline");
    }
  }
 
 
  /**
   * 执行-u查看用户信息
   * @param fromJID
   * @param msgarr 输入字符串数组
   * @param strMessage 完整输入字符串
   * @throws IOException
   */
  public void doUser(JID fromJID, String[] msgarr, String strMessage) throws IOException
  {
    API api = Common.getAPI(fromJID);
    if(api == null)
    {
      Common.sendMessage(fromJID,"您尚未绑定账号,请使用-oauth命令绑定");
      return;
    }
    HTTPResponse response;
    if(msgarr.length == 1)                          //-u
    {
      response = api.account_verify_credentials(fromJID);
    }
    else if(msgarr.length == 2)                        //-u id
    {
      response = api.users_show(fromJID, msgarr[1]);
    }
    else
    {
      doHelp(fromJID,"u");
      return;
    }
   
    if(response.getResponseCode() == 200)
    {
      UserJSON jsonUser = new UserJSON(new String(response.getContent()));
      String message = null;
      message = jsonUser.getScreenName() + " (" + jsonUser.getId() + ") 的信息\n"
          + "头像地址: " + jsonUser.getProfileImageUrl()
          + "\n性别: " + jsonUser.getGender()
          + "\n自述: " + jsonUser.getDescription()
          + "\n地址: " + jsonUser.getLocation()
          + "\nTA关注的人数: " + String.valueOf(jsonUser.getFriendsCount())
          + "\n关注TA的人数: " + String.valueOf(jsonUser.getFollowersCount())
          + "\n收藏消息数: " + String.valueOf(jsonUser.getFavouritesCount())
          + "\n已发消息数: " + String.valueOf(jsonUser.getStatusesCount());
      if(jsonUser.getIsFollowing())
      {
        message = message + "\n\n您已经关注了" + jsonUser.getId();
      }
      else
      {
        message = message + "\n\n您没有关注" + jsonUser.getId();
      }
      Common.sendMessage(fromJID,message);
    }
    else if(response.getResponseCode() == 403)
    {
      Common.sendMessage(fromJID,"你没有通过这个用户的验证,无法查看TA的信息");
    }
    else if(response.getResponseCode() == 404)
    {
      Common.sendMessage(fromJID,"id所指定的用户不存在");
    }
    else
    {
      Common.sendMessage(fromJID,Common.getError(new String(response.getContent())));
      Common.log.info(Common.getStrJID(fromJID) + "-u: " + new String(response.getContent()));
    }
  }


  /**
   * 获取命令 ID
   * 输入: 字符串,以-开头
   * 返回: 命令ID
   */
  public int getCmdID(String strCmd)
  {
    if(strCmd.equals("-oauth"))                        //绑定账号
      return 1;
    else if(strCmd.equals("-bind"))                      //接收PIN码
      return 2;
    else if(strCmd.equals("-remove"))                    //解除绑定
      return 3;
    else if(strCmd.equals("-?") || strCmd.equals("-h") || strCmd.equals("-help"))  //显示帮助
      return 4;
    else if(strCmd.equals("-@") || strCmd.equals("-r") || strCmd.equals("-reply") || strCmd.equals("-mention")) //回复,提及
      return 5;
    else if(strCmd.equals("-home") || strCmd.equals("-ho"))          //显示时间线
      return 6;
    else if(strCmd.equals("-m") || strCmd.equals("-msg"))          //查看某条消息
      return 7;
    else if(strCmd.equals("-rt"))                      //转发消息
      return 8;
    else if(strCmd.equals("-u") || strCmd.equals("-user"))          //显示用户信息
      return 9;
    else if(strCmd.equals("-del") || strCmd.equals("-delete"))        //删除消息
      return 10;
    else if(strCmd.equals("-fo") || strCmd.equals("-follow"))        //关注好友
      return 11;
    else if(strCmd.equals("-unfo") || strCmd.equals("-unfollow"))      //取消关注
      return 12;
    else if(strCmd.equals("-on"))                      //开启自动提醒
      return 13;
    else if(strCmd.equals("-off"))                      //关闭自动提醒
      return 14;
    else if(strCmd.equals("-time"))                      //设置自动更新间隔
      return 15;
    else if(strCmd.equals("-public") || strCmd.equals("-pub"))        //显示随便看看
      return 16;
    else if(strCmd.equals("-timeline") || strCmd.equals("-tl"))        //显示指定用户已发送消息
      return 17;
    else if(strCmd.equals("-favorite") || strCmd.equals("-fav"))      //收藏消息
      return 18;
    else if(strCmd.equals("-unfavorite") || strCmd.equals("-unfav"))    //取消收藏消息
      return 19;
    else if(strCmd.equals("-s") || strCmd.equals("-search"))        //搜索消息
      return 20;
    else                                  //未知命令
      return -1;
  }


  /**
   * 通过是否有access_token判断是否已绑定账号
   * @param fromJID 来源JID
   * @return 已绑定返回true,并发送提示
   */
  public boolean isOauth(JID fromJID)
  {
    if(Common.getData(fromJID,"access_token") == null)
    {
      return false;
    }
    else
    {
      String id;
      id = Common.getID(fromJID);
      if(id == null)
      {
        String strMessage = "您已经绑定饭否ID\n 若您希望绑定新的账号请先使用-remove命令取消现有绑定";
        Common.sendMessage(fromJID, strMessage);
      }
      else
      {
        String strMessage = "您已经绑定饭否ID:" + id +" \n 若您希望绑定新的账号请先使用-remove命令取消现有绑定";
        Common.sendMessage(fromJID, strMessage);
      }
      return true;
    }
  }
 
}
TOP

Related Classes of vc.fq.fantalker.FantalkerServlet

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.