有了上一篇的基础,在学习下skype的api, 就可以实现skype字典机器人功能了:-)
1. 下载skype java 开发包
http://cvs.sourceforge.jp/cgi-bin/viewcvs.cgi/skype.tar.gz?view=tar
2. 将tar包里release文件夹下的jar加入到build path
3. 将上一篇(读取StarDict里的字典文件)用到的jar也加到build path, 同时注意配置好config.properties
4. 使用。
用了3个类来实现,
StarDict 根据输入的单词返回翻译结果
WitRobot 与skype交互的类,监听输入消息,返回结果
Start 开启一个后台线程监听skype消息
package com.msino.dict;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.msino.dict.StarDictReader;
import com.msino.dict.manager.DictsManager;
import com.msino.dict.service.IDictsManager;
import com.msino.dict.service.core.Word;
/**
* Get word info by word name
*
* @author XuDong.Su
* @version 0.1, Apr 10, 2009
* @see com.msino.dict.StarDictReader
*/
public class StarDict {
public static final Logger LOGGER = Logger.getLogger(StarDict.class.getName());
private StarDictReader instance;
private IDictsManager dictsManager = new DictsManager();
private String dictsProp = dictsManager.getDictProps();
private String dictFileDir = "";
private String dictName = "";
private HashMap wordMap = new HashMap();
/**
* Default constructor.
*/
public StarDict() {
// Get dictionary file directory and name
dictFileDir = dictsProp.substring(0, dictsProp.indexOf("||"));
dictName = dictsProp.substring(dictsProp.indexOf("||") + 2, dictsProp.length());
try {
instance = new StarDictReader(dictFileDir, dictName);
} catch (FileNotFoundException ex) {
LOGGER.log(Level.SEVERE, null, ex);
}
}
/**
* Lookup method, of class DictEngine.
* @throws java.lang.InterruptedException Thread.sleep(long)
*/
public String lookup(String wordName) throws InterruptedException {
String result = dictMap(wordName);
// if the word exists in map, no need to research
if (!"".equals(result) && result != null) {
return result;
}
try {
Word word = null;
long start = System.currentTimeMillis();
word = instance.lookup(wordName);
result = word.self + ": " + word.definition;
// Add word info into map
wordMap.put(wordName, result);
// For reduce memory
if (wordMap.size() >= 5000) {
wordMap.clear();
}
long end = System.currentTimeMillis();
LOGGER.log(Level.INFO, word.self + ": " + word.definition);
LOGGER.log(Level.INFO, "Space Time: " + (end - start) + "ms");
LOGGER.log(Level.INFO, "word map size : " + wordMap.size());
} catch (Exception ex) {
result = ex.getMessage();
LOGGER.log(Level.INFO, ex.getMessage());
}
return result;
}
/**
* A cache of store has searched word
* @param key
* @return value
*/
private String dictMap(String key) {
String value = (String) wordMap.get(key);
return value;
}
}
package com.msino.skype;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.skype.ChatMessage;
import com.skype.ChatMessageAdapter;
import com.skype.Skype;
import com.skype.SkypeException;
import com.msino.dict.StarDict;
/**
* Skype robot, start chat
*
* @author XuDong.Su
* @version 0.1, Apr 10, 2009
*/
public class WitRobot {
public static final String FY = "/fy ";
public static final String ERROR = "Sorry, you input command is not support yet, please use \"help\" or ? for more information!";
public static final String HELP = "You can use blow command : \r\n1. Translate a word \r\n /fy wordName \r\n2. Get help \r\n ? or help";
public static final String HELPCMD1 = "?";
public static final String HELPCMD2 = "help";
public static final String NOTFOUND = "Sorry, Not found the word.";
public static final Logger LOGGER = Logger.getLogger(WitRobot.class.getName());
private StarDict dict = null;
public WitRobot() {
// Initial class stardict
dict = new StarDict();
}
public void startChat() throws Exception {
Skype.addChatMessageListener(new ChatMessageAdapter() {
@Override
public void chatMessageReceived(ChatMessage receivedChatMessage) throws SkypeException {
String content = "";
String replyMsg = "";
// Get input content
content = receivedChatMessage.getContent().trim();
if (!"".equals(content) && receivedChatMessage.getType().equals(ChatMessage.Type.SAID)) {
// Get the word mean
if(content.length() > 3 && FY.equals(content.substring(0, 4))) {
content = content.substring(4, content.length());
replyMsg = autoReplyMsg(content);
} else if(HELPCMD1.equals(content) || HELPCMD2.equals(content)) {
replyMsg = HELP;
} else {
replyMsg = ERROR;
}
if("".equals(replyMsg)) {
replyMsg = NOTFOUND;
}
// reply the word's translate result
receivedChatMessage.getSender().send(replyMsg);
}
}
});
}
private String autoReplyMsg(String wordName) {
String replyMsg = "";
try {
// Lookup word info by word name
replyMsg = dict.lookup(wordName);
} catch (InterruptedException e) {
replyMsg = e.getMessage();
LOGGER.log(Level.INFO, e.getMessage());
}
return replyMsg;
}
}
package com.msino.test;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.msino.skype.WitRobot;
/**
* Test class, start a thread to listen message
*
* @author XuDong.Su
* @version 0.1, Apr 10, 2009
*/
public class Start extends Thread {
public static final Logger LOGGER = Logger.getLogger(Start.class.getName());
public Start() {
setDaemon(true);
super.start();
}
public void run() {
// do nothing
}
public void noStop() {
try {
Thread t = new Thread();
synchronized (t) {
t.wait();
}
} catch (InterruptedException e) {
LOGGER.log(Level.SEVERE, null, "Wait thread error!" + e);
}
}
public static void main(String[] args) throws Exception {
long freeMemory = Runtime.getRuntime().freeMemory() / 1024;
LOGGER.log(Level.INFO, "Before Free memory : " + freeMemory);
Start s = new Start();
WitRobot chat = new WitRobot();
// Start chat
chat.startChat();
freeMemory = Runtime.getRuntime().freeMemory() / 1024;
LOGGER.log(Level.INFO, "After Free memory : " + freeMemory);
s.noStop();
}
}
5. 运行Start类, 然后尝试向本机的skype发送消息. 如果你启动中碰到下面的错误,请将release文件夹下的swt-win32-3232.dll放到你的jave/jre/bin目录下
java.lang.UnsatisfiedLinkError: no swt-win32-3232 in java.library.path
.....
6. 演示效果:
7. 疑问:
以前用openfire可以整个google talk server, 因为gtalk基于japper协议. 但skype不基于这个协议,我现在实现的方式是在本地开启一个后台线程监听skype消息, 但不知如何部署在server上,哪位大虾知道的,还请指导下,非常感谢 :-)
If you have any query, please feel free to contact me -- m.msino##gmail.com