< Day Day Up > |
Hack 52 Use the Dictionary
Create a bot to look up the meaning of a word for you or to show the meaning of a word to other people in your channel. People very often use short acronyms or other jargon on IRC. Sometimes it can be helpful to have a clue what they are saying. One solution is to look these words up in the Jargon file (http://www.catb.org/~esr/jargon) or the Free On-Line Dictionary of Computing (FOLDOC—http://wombat.doc.ic.ac.uk/foldoc). Another way is to get an IRC bot to do the searches for you. A convenient way to access both the Jargon file and FOLDOC is via the Dictionary Server Protocol (ftp://ftp.isi.edu/in-notes/rfc2229.txt) through dict.org (http://www.dict.org/bin/Dict). 8.3.1 The CodeThe bot in this hack will respond to the commands !jargon and !foldoc and give the results of the search to the channel. The PircBot IRC framework will be used to connect to the IRC server and respond to simple IRC commands. The majority of the code will be used to connect to the dictionary server and parse the responses. Create a file called DictBot.java: import java.io.*; import java.net.*; import java.util.regex.*; import org.jibble.pircbot.*; public class DictBot extends PircBot { private static final String DICT_SERVER = "dict.org"; private static final int DICT_PORT = 2628; public DictBot( ) { this.setName("DictBot"); } public void onMessage(String channel, String sender, String login, String hostname, String message) { if(message.toLowerCase( ).startsWith("!jargon ")) { String searchString = message.substring(8).trim( ); sendMessage(channel, lookupWord(DICT_SERVER, DICT_PORT, "jargon", searchString)); } else if(message.toLowerCase( ).startsWith("!foldoc ")) { String searchString = message.substring(8).trim( ); sendMessage(channel, lookupWord(DICT_SERVER, DICT_PORT, "foldoc", searchString)); } } } When the bot receives a !jargon or !foldoc command, it will pass the parameters to the lookupWord method. This method will connect to the DICT server and try and return the definition of the word. You should now add this method to the DictBot class: public String lookupWord(String dictServer, int port, String book, String word) { try { Socket socket = new Socket(dictServer, port); BufferedReader reader = new BufferedReader( new InputStreamReader(socket.getInputStream( ))); BufferedWriter writer = new BufferedWriter( new OutputStreamWriter(socket.getOutputStream( ))); reader.readLine( ); // Set the book used for search (and double quote the search string). writer.write("DEFINE " + book + " \"" + word + "\"\r\n"); writer.flush( ); String definition = ""; String line = null; while((line = reader.readLine( )) != null) { // 552 No match. if(line.startsWith("552")) { // Switch to Levenshtein algorithm to try to get *some* result. writer.write("MATCH " + book + " lev \"" + word + "\"\r\n"); writer.flush( ); line = reader.readLine( ); // 552 No match if(line.startsWith("552")) { socket.close( ); // If it's still not found, stop. return "I can't find any words that look like that..."; // 152 n matches found - text follows. } else if(line.startsWith("152")) { String[] parts = line.split(" "); int numMatches = Integer.valueOf(parts[1]).intValue( ); // Some similar words were found ... String reply = ""; int count = 0; while((line = reader.readLine( )) != null) { if(count > numMatches || line.startsWith(".")) { break; } reply += " " + line.substring(line.indexOf("\""), line.lastIndexOf("\"") + 1); count++; } socket.close( ); return "The only similar words I could find were: " + reply; } else { // Something went wrong. Let the user know. return "Something unexpected happened: " + line; } } // 151 word database name - text follows. if(line.startsWith("151")) { if (book.equals("foldoc")) { // Skip first 2 lines returned (header and blank line). reader.readLine( ); reader.readLine( ); } definition = ""; while((line = reader.readLine( )) != null) { if(line.trim( ).equals("") || line.startsWith("2")) { break; } else { definition += line; } } break; } if(line.startsWith("2")) { break; } } socket.close( ); // Return the definition. Pattern pattern = Pattern.compile("[\\s\\r\\n\\t\\f]+"); Matcher m = pattern.matcher(definition); definition = m.replaceAll(" "); return definition; } catch (Exception e) { // Do nothing. } return "Something went wrong :oP"; } Now you just need a main method to construct the bot and tell it to connect to a server and join a channel. The bot will be happy to join more than one channel if you want. Create the following in DictBotMain.java: public class DictBotMain { public static void main(String[] args) throws Exception { DictBot fBot = new DictBot( ); fBot.setVerbose(true); fBot.connect("irc.freenode.net"); fBot.joinChannel("#irchacks"); } } 8.3.2 Running the HackCompile the bot with: C:\java\DictBot> javac -classpath pircbot.jar;. *.java Run the bot with: C:\java\DictBot> java -classpath pircbot.jar;. DictBotMain The bot will connect to the server and be ready to look up words as soon as it joins your channel. 8.3.3 The ResultsHere are some examples of the bot being used to look up words in the Free On-Line Dictionary of Computing (FOLDOC): <DeadEd> !foldoc irc <DictBot> {Internet Relay Chat} <DeadEd> !foldoc internet relay chat <DictBot> <chat, messaging> (IRC) /I-R-C/, occasionally /*rk/ A {client-server} {chat} system of large (often worldwide) networks. IRC is structured as networks of {Internet} {servers}, each accepting connections from {client} programs, one per user. <DeadEd> !foldoc html <DictBot> {Hypertext Markup Language} <DeadEd> !foldoc Hypertext Markup Language <DictBot> <hypertext, World-Wide Web, standard> (HTML) A {hypertext} document format used on the {World-Wide Web}. HTML is built on top of {SGML}. "Tags" are embedded in the text. A tag consists of a "<", a "directive" (case insensitive), zero or more parameters and a ">". Matched pairs of directives, like "<TITLE>" and "</TITLE>" are used to delimit text which is to appear in a special place or style. 8.3.4 Hacking the HackMany other dictionaries are available at dict.org. All of these can be accessed using the same Dictionary Server Protocol. The communication is basically the same, but some additional parsing may be needed to get a nicer output from some of the dictionaries. For example, you could easily add a new command !dict that would perform a lookup through all of the dictionaries available on dict.org by adding the following code to the end of the onMessage method: else if(message.toLowerCase( ).startsWith("!dict ")) { String searchString = message.substring(6).trim( ); sendMessage(channel, lookupWord(DICT_SERVER, DICT_PORT, "*", searchString)); } You could then ask the bot to look up a word in all of the available dictionaries by typing !dict word. —Alex North |
< Day Day Up > |