2009/10/16


まぁ手順通りだけど...
Ubuntu 9.04で作りました。以下手順。

必要なソフトウェアのインストール
# sudo apt-get install texlive-xetex latex-cjk-xcjk pandoc texlive-latex-recommended
ちなみにtexlive-latex-recommendedを入れないと"kvoptions.styが無いよ!"と怒られるので注意。

progitのリポジトリをcloneする
# git clone git://github.com/progit/progit.git
git入れてない人はプロジェクトページのdownloadボタンで...

フォントを設定する
latexというフォルダに移動し、config.xmlというファイルがあるのでfontを設定する。"Japan"なんて郷ひろみばりのフォント持ってないのでIPAGothicを指定した。
diff --git a/latex/config.yml b/latex/config.yml
index c8f0d61..305e262 100644
--- a/latex/config.yml
+++ b/latex/config.yml
@@ -9,7 +9,8 @@ zh:
   font: AR PL UMing CN
   fig: "图 "
 ja:
-  font: Japan
+  font: IPAGothic
+  mono: IPAGothic
   fig: "図"
   tab: "表"
 ru:

あとは実行
# ./makepdf ja
jaフォルダの中にmain.pdfというファイルが出来る。

progit-ja
ウマー! 印刷して持ち歩こう。
Posted at by



2009/10/14


Google Waveにinviteされた。人からじゃなくて前に申し込んでたのが来たらしい。
ブログで招待しようかと思ったけど、いつもお世話になっている人たちにIRCで「いりますか?」と尋ねたら40分くらいで完売。
って事でタイトルは「Google Waveに招待します」じゃなく「Google Waveに招待しました」になっちゃいました。

wave-invited
Posted at by



2009/10/09


tokuhiromさんがnanowwwという、C++から簡単にHTTPが扱えるクライアントライブラリを書いてくれたので、botを書いてみた。
tokuhirom's nanowww at master - GitHub

C++ lightweight, fast, portable HTTP client library

http://github.com/tokuhirom/nanowww
picojsonは以前ご紹介した通り、kazuhoさんが書いたC++からSTLと親和性の高いJSONパーサです。
今回はtokuhiromさんが、C++で、もちろんSTLと親和性の高いHTTPクライアントライブラリを書いてくれました。
これを使えば、例えばhttp://example.com/fooというURLにPOSTで"name=hasegawa"を送信するとした場合
  nanowww::Client client;
  nanowww::Request req("POST", "http://example.com/foo", "name=hasegawa");
  nanowww::Response res;
  req.set_header("Content-Type", "application/x-www-form-urlencoded");
  if (client.send_request(req, &res))
      std::cout << res.content() << std::endl;
  else
      std::cout << client.errstr() << std::endl;
これだけのコードでHTTP通信出来てしまいます。
C++らしくていいですね。CURLよりはインタフェースが優れていると思います。ただ現状はPROXYに対応していなかったり、Windowsで使えなかったりしますので、用途を絞られますが、今後に期待したいと思います。
さて今日はこれを使って、IRCに常駐し、指定のチャネルに入り、指定の単語が現れると「それXXX関係ないだろ!jk」と発言する、「関係ないbot」を書きました。実際にIRCプロトコルを喋っている訳でなく、webchat.freenode.netのAjax通信を、nanowwwとpicojsonによる擬似Ajax通信を行って実現しています。
以下、少々長いですが全ソースコード。
#include "picojson.h"
#include "nanowww.h"

using namespace std;
using namespace picojson;
using namespace nanowww;

#ifdef _WIN32
static char* utf8_to_str_alloc(const char* utf8) {
    size_t in_len = strlen(utf8);
    wchar_t* wcsdata;
    char* mbsdata;
    size_t mbssize, wcssize;

    wcssize = MultiByteToWideChar(CP_UTF8, 0, utf8, in_len,  NULL, 0);
    wcsdata = (wchar_t*) malloc((wcssize + 1) * sizeof(wchar_t));
    wcssize = MultiByteToWideChar(CP_UTF8, 0, utf8, in_len, wcsdata, wcssize + 1);
    wcsdata[wcssize] = 0;

    mbssize = WideCharToMultiByte(GetACP(), 0, (LPCWSTR) wcsdata, -1, NULL, 0, NULL, NULL);
    mbsdata = (char*) malloc((mbssize + 1));
    mbssize = WideCharToMultiByte(GetACP(), 0, (LPCWSTR) wcsdata, -1, mbsdata, mbssize, NULL, NULL);
    mbsdata[mbssize] = 0;
    free(wcsdata);
    return mbsdata;
}
#endif

value get_json(string url, map<string, string>& postdata) {
  value v;
  char error[256];
  string data;
  map<string, string>::iterator it;

  for (it = postdata.begin(); it != postdata.end(); it++) {
      if (data.size()) data += "&";
      data += it->first + "=";
      data += it->second;
  }

  Client client;
  Request req("POST", url.c_str(), data.c_str());
  Response res;
  req.set_header("Content-Type", "application/x-www-form-urlencoded");
  if (client.send_request(req, &res)) {
    const char* ptr = res.content().c_str();
    string err = parse(v, ptr, ptr + strlen(ptr));
    if (!err.empty()) cerr << err << endl;
  }
  return v;
}

int
main(int argc, char* argv[]) {
  map<string, string> postdata;
  value v;
  bool loop;

  if (argc != 4) {
      std::cerr << "usage: kankeinaibot [nick] [channel] [word]" << std::endl;
      return -1;
  }
  string nick = argv[1];
  string channel = argv[2];
  string word = argv[3];

  postdata.clear();
  postdata["nick"] = nick;
  v = get_json("http://webchat.freenode.net/e/n", postdata);
  string sid = v.get<array>()[1].get<string>();

  loop = true;
  postdata.clear();
  postdata["s"] = sid;
  while (loop) {
    v = get_json("http://webchat.freenode.net/e/s", postdata);
    array a = v.get<array>();
    for (array::iterator it = a.begin(); it != a.end(); it++) {
      if (!it->is<array>()) continue;
      array line = it->get<array>();
      if (line[0].to_str() == "c") {
        if (line[1].to_str() == "443") {
            postdata["nick"] += "_";
            v = get_json("http://webchat.freenode.net/e/n", postdata);
            sid = v.get<array>()[1].get<string>();
            break;
        }
        if (line[1].to_str() == "376") {
            loop = false;
            break;
        }
      }
    }
  }

  loop = true;
  postdata.clear();
  postdata["c"] = "JOIN #";
  postdata["c"] += channel;
  postdata["s"] = sid;
  v = get_json("http://webchat.freenode.net/e/p", postdata);
  while (loop) {
    v = get_json("http://webchat.freenode.net/e/s", postdata);
    array a = v.get<array>();
    for (array::iterator n = a.begin(); n != a.end(); n++) {
      array line = n->get<array>();
      if (line[0].to_str() == "c") {
        array aa = line[3].get<array>();
        if (aa.size() > 1 && aa[0].to_str() != nick) {
          cout << aa[0].serialize() << endl;
          cout << aa[1].serialize() << endl;
          if (!strncmp(aa[1].to_str().c_str(), word.c_str(), word.size())) {
              map<string, string> saydata;
              saydata["s"] = sid;
              std::stringstream s;
              s << "PRIVMSG #" << channel << " :" <<
                  "それ" << word << "関係ないだろ!jk";
              saydata["c"] = s.str();
              cout << saydata["c"] << endl;
              v = get_json("http://webchat.freenode.net/e/p", saydata);
          }
        }
        string s = line[3].serialize();
#ifdef _WIN32
        char* p = utf8_to_str_alloc(s.c_str());
        cout << p;
        cout << " ";
        free((void*)p);
        cout << endl;
#else
        cout << s << endl;
#endif
      }
    }
  }
  
  return 0;
}
CURLを使った場合のレスポンスwriterを書かなくてもいいので、かなりスッキリしましたね。

ソースはgithubにも置いてあるのでよろしければ試してみて下さい。
mattn's kankeinai-bot at master - GitHub

関係ないbot

http://github.com/mattn/kankeinai-bot

えっ?全然botじゃない?

bot関係ないだろ!jk

Posted at by