Twitter上でIokeプログラミングをとりあえず的に
@IokeGround fib = method(n, if(n == 0, 0, if(n == 1, 1, fib(n-1) + fib(n-2)))). fib(10)
http://twitter.com/katzchang/status/2450789054
とすると、
@katzchang 55
http://twitter.com/IokeGround/status/2450791565
こう返す。
つまり、Twitterで@メッセージを送ると、Iokeメッセージとして解釈してごりごり処理してくれるわけだ。超楽しいww
ちなみに、フッタをつけてる場合は";"を最後に入れると良い感じ。thanks id:bleis-tift
@IokeGround fact = method(n, if(n == 0, 1, n * fact(n - 1))). fact(5); 文法わからないけどfibを参考に投げてみる [SQL Puzzlersやります! http://bit.ly/M3zRO]
http://twitter.com/bleis/status/2451082449
今後の課題として:
- 手動起動する必要があるのはあんまりなので、起動してると定時でreplyを取りにいって適当に処理してくれるとうれしいとか。
- エラーがあるとIoke自体が落ちちゃうけどそれってどうなのとか。
- 実行権限をuserでしぼってるけどそれって大丈夫なのとか。
- stax.netにのせられる?
- とすると、セキュリティ的な心配ってそんなに必要ない?
- でも、無限ループとかされたらどうすんだろか?
- とすると、セキュリティ的な心配ってそんなに必要ない?
以下、自分用めも。
package iokebot; import java.io.*; import java.util.*; import java.util.logging.Logger; import twitter4j.*; import ioke.lang.*; import ioke.lang.exceptions.*; public class IokeBot { final MyRuntime r; final TwitterHandler h; final Prop p; final Logger logger; public IokeBot() throws Exception, ControlFlow { this.p = new Prop(); this.r = new MyRuntime(); this.h = new TwitterHandler(); this.logger = Logger.getLogger(this.getClass().getName()); logger.info("user:"+p.name); logger.info("commando:"+p.commando); logger.info("last status id:"+p.lastStatusID); } public void check() throws Exception, ControlFlow { Status status = this.h.checkStatuses(); logger.info("status:" + status); if (status != null) { Object result = this.h.handleMessage(status); logger.info("result:" + result); long newStatusID = this.h.updateLastStatusID(status); logger.info("newStatusID:" + newStatusID); } } public void tearDown() throws ControlFlow.Exit { this.r.tearDown(); logger.info("Bye..."); } class Result { Status status; Object result; } class TwitterHandler { final MyTwitter t; final String commando; TwitterHandler() { this.t = new MyTwitter(p.name, p.password); this.commando = p.commando; } Object handleMessage(Status status) throws TwitterException, ControlFlow { if(validCommando(status)) { String message = status.getText().substring(status.getText().indexOf(" ")); Object res = r.eval(message); t.updateStatus("@" + status.getUser().getName() + " " + res.toString(), status.getId()); return res; } else { return "invalid commando."; } } long updateLastStatusID(Status status) throws IOException { p.updateLastStatusID(status.getId()); return status.getId(); } Status checkStatuses() throws TwitterException, ControlFlow, IOException { List<Status> statuses = t.getReplies(p.lastStatusID); logger.fine("statuses" + statuses.toString()); if(!statuses.isEmpty()) { return statuses.get(0); } return null; } boolean validCommando(Status status) { return this.commando.equals(status.getUser().getName()); } } static class Prop { final Properties p; static String filename = "src/iokebot/iokebot.properties.xml"; final String name; final String password; final String commando; long lastStatusID; Prop() throws IOException { this.p = new Properties(); InputStream is = new FileInputStream(filename); try { p.loadFromXML(is); this.name = p.getProperty("name"); this.password = p.getProperty("password"); this.commando = p.getProperty("commando"); this.lastStatusID = Long.valueOf(p.getProperty("last_status_id")); } finally { is.close(); } } void updateLastStatusID(long id) throws IOException { this.lastStatusID = id; OutputStream os = new FileOutputStream(filename); try { p.setProperty("last_status_id", String.valueOf(id)); p.storeToXML(os, "IokeBot Properties"); } finally { os.close(); } } } }
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <comment>IokeBot Properties</comment> <entry key="last_status_id">2450789054</entry> <entry key="name">IokeGround</entry> <entry key="password"></entry> <entry key="commando">katzchang</entry> </properties>
package ioke.lang; import ioke.lang.exceptions.ControlFlow; public class MyRuntime { final Runtime r; public MyRuntime() throws Exception, ControlFlow { this.r = new Runtime(); this.init(); } public void init() throws ControlFlow { this.r.init(); this.eval("Hi =\"Hi. see also: http://d.hatena.ne.jp/katzchang/20090703/p3\""); } public void tearDown() throws ControlFlow.Exit { this.r.tearDown(); } public Object eval(String message) throws ControlFlow { return this.r.evaluateString(message); } }
package twitter4j; import java.util.List; public class MyTwitter extends Twitter { private static final long serialVersionUID = -4218983212013279106L; public MyTwitter(String id, String password) { super(id, password); } public List<Status> getReplies() throws TwitterException { return Status.constructStatuses(get(getBaseURL() + "statuses/replies.xml" , null, true), this); } public List<Status> getReplies(long sinceID) throws TwitterException { return Status.constructStatuses(get(getBaseURL() + "statuses/replies.xml" , null, new Paging(sinceID), true), this); } }