import java.io.File; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; import java.util.logging.LogManager; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathFactory; import org.luaj.vm2.LuaTable; import org.luaj.vm2.LuaValue; import org.luaj.vm2.lib.OneArgFunction; import org.pircbotx.Channel; import org.pircbotx.Colors; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import pl.shockah.HTTPQuery; import pl.shockah.StringTools; import pl.shockah.shocky.Data; import pl.shockah.shocky.Module; import pl.shockah.shocky.Utils; import pl.shockah.shocky.cmds.Command; import pl.shockah.shocky.cmds.CommandCallback; import pl.shockah.shocky.cmds.Parameters; import pl.shockah.shocky.interfaces.ILua; public class ModuleWolframAlpha extends Module implements ILua { protected Command cmd; public Map<String,String> getResultMap(String apiKey, String query, String xquery) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); XPathFactory xpathFactory = XPathFactory.newInstance(); try { query = URLEncoder.encode(query,"UTF8"); DocumentBuilder builder = factory.newDocumentBuilder(); HTTPQuery q = HTTPQuery.create("http://api.wolframalpha.com/v2/query?appid="+apiKey+"&format=Plaintext&input="+query); Document doc; try { q.connect(true,false); doc = builder.parse(q.getConnection().getInputStream()); } finally { q.close(); } Element docElement = doc.getDocumentElement(); boolean error = Boolean.parseBoolean(docElement.getAttribute("error")); boolean success = Boolean.parseBoolean(docElement.getAttribute("success")); if (error || !success) return null; Map<String,String> parts = new LinkedHashMap<String,String>(); XPath xpath = xpathFactory.newXPath(); XPathExpression xptitle = xpath.compile("./@title"); NodeList xe = (NodeList) xpath.evaluate(xquery,doc,XPathConstants.NODESET); for (int i = 0; i < xe.getLength();++i) { String text = StringTools.deleteWhitespace(xe.item(i).getTextContent()).trim(); if (text.length() > 0) parts.put(xptitle.evaluate(xe.item(i)),text); } return parts; } catch (Exception e) {e.printStackTrace();} return null; } public String getResult(Channel channel, String query) { String apiKey = Data.forChannel(channel).getString("wolfram-apikey"); if (apiKey.isEmpty()) return ">>> WolframAlpha module can't be used without setting up an API key. Get one at http://products.wolframalpha.com/developers/ <<<"; Map<String,String> resultMap = getResultMap(apiKey,query,"//queryresult/pod[(@primary='true') or (@title='Alternate form')]"); ArrayList<String> parts = new ArrayList<String>(); if (resultMap == null) parts.add("No result"); try {query = URLEncoder.encode(query,"UTF8");} catch (UnsupportedEncodingException e) {} parts.add(Utils.shortenUrl("http://www.wolframalpha.com/input/?i="+query)); if (resultMap != null) { for (Entry<String, String> part : resultMap.entrySet()) { parts.add(Colors.BOLD+part.getKey()+Colors.NORMAL+": "+part.getValue()); } } StringBuilder sb = new StringBuilder(); for (String part : parts) { if (sb.length() != 0) sb.append(" | "); sb.append(part); } return StringTools.limitLength(sb); } public String name() {return "wolfram";} public void onEnable(File dir) { Command.addCommands(this, cmd = new CmdWolframAlpha()); Command.addCommand(this, "wa", cmd); Data.config.setNotExists("wolfram-apikey",""); Data.protectedKeys.add("wolfram-apikey"); } public void onDisable() { Command.removeCommands(cmd); } public class CmdWolframAlpha extends Command { public String command() {return "wolframalpha";} public String help(Parameters params) { StringBuilder sb = new StringBuilder(); sb.append("wolframalpha/wa"); sb.append("\nwolframalpha {query} - shows WolframAlpha's result"); return sb.toString(); } public void doCommand(Parameters params, CommandCallback callback) { String result = getResult(params.channel, params.input); if (result == null) return; result = Utils.mungeAllNicks(params.channel,0,result,params.sender); callback.append(result); } } public class Function extends OneArgFunction { @Override public LuaValue call(LuaValue arg) { String apiKey = Data.config.getString("wolfram-apikey"); if (apiKey.isEmpty()) return NIL; Map<String,String> result = getResultMap(apiKey,arg.checkjstring(),"//queryresult/pod"); LuaValue[] values = new LuaValue[result.size()<<1]; int i = 0; for (Entry<String,String> item : result.entrySet()) { values[i++] = valueOf(item.getKey()); values[i++] = valueOf(item.getValue()); } return tableOf(values); } } @Override public void setupLua(LuaTable env) { try { Class.forName("pl.shockah.HTTPQuery"); Class.forName("pl.shockah.HTTPQuery$Method"); LogManager.getLoggingMXBean(); } catch (Exception e) { e.printStackTrace(); } env.rawset("wa", new Function()); } }