有了上一篇的基础,在学习下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<String, String> wordMap = new HashMap<String, String>(); /** * 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