D言語でD言語くんbotを書くために調べたことまとめ

# はじめに

<blockquote class="twitter-tweet" lang="ja"><p lang="ja" dir="ltr">『プログラミング言語に関するbotを別の言語で実装するとか、どうして生き恥を晒すのか』と<a href="https://twitter.com/keithseahus">@keithseahus</a> 先生に激詰めされたので、<a href="https://twitter.com/d_man_bot">@d_man_bot</a> はD言語で作りました。これで僕もD言語er。</p>&mdash; しむD (@simd_nyan) <a href="https://twitter.com/simd_nyan/status/614987823616110592">2015, 6月 28</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

D言語で[D言語くんbot](https://twitter.com/d_man_bot)を書くために調べたことをまとめます。

## D言語くんbotでやること

* 設定ファイル(YAML)を読み込む
* Twitter API
  * 単語を指定して検索する
  * 対象のツイートをリツイートをする
  * 対象のユーザーをフォローをする
* 結果をDBに反映する

# 正規表現

```d
assert("123-abc-def".match(regex("([a-z]{3})")).captures[0] == "abc");
```

# データ形式

## HTML

http://code.dlang.org/packages/htmld

```html:test.html
<html>
  <body>
    <p>title</p>
    <ul>
      <li>0</li>
      <li>1</li>
    </ul>
  </body>
</html>
```

```d
import std.stdio,
       std.conv,
       html;

void main(){
  auto html = readText("test.html");
  auto doc = createDocument(html);

  doc.querySelector("body").text;

  assert(doc.querySelector("p").text == "title");

  int i = 0;
  foreach(li; doc.querySelectorAll("li")) {
    assert(li.text == to!string(i));
    i++;
  }
}

```

## JSON

```json:test.json
{
  "int":    123,
  "string": "abc",
  "bool":   true,
  "null":   null,
  "1st": {
    "2nd": "nested"
  },
  "array": [
    {"index": 0},
    {"index": 1}
  ]
}
```

```d
import std.stdio,
       std.json;

void main(){
  auto json_string = readText("test.json");

  JSONValue json = parseJSON(json_string);
  
  assert(json["int"].integer == 123);
  assert(json["string"].str == "abc");
  assert(json["bool"].type == JSON_TYPE.TRUE);
  assert(json["null"].isNull);
  assert(json["1st"]["2nd"].str == "nested");
  assert(json["array"].array.length == 2);
  foreach(int i, JSONValue v; json["array"].array){
    assert(v["index"].integer == i);
  }
  assert("2nd" in json["1st"].object);
  assert(("not_found" in json.object) == null);
}
```

## YAML

http://code.dlang.org/packages/dyaml

```yaml:test.yaml
int:    123
string: abc
bool:   true
null_value: null
1st:
  2nd: nested
array:
- index: 0
- index: 1
```

```d
import std.stdio,
       std.conv,
       dyaml.all;

void main(){
  auto yaml = Loader("test.yaml").load();

  assert(yaml["int"].as!int == 123);
  assert(yaml["string"].as!string == "abc");
  assert(yaml["bool"] == true);
  assert(yaml["null_value"].isNull);
  assert(yaml["1st"]["2nd"] == "nested");
  int i = 0;
  foreach(Node node; yaml["array"]){
    assert(node["index"].as!int == i);
    i++;
  }
}
```

# データベース

## MySQL

http://code.dlang.org/packages/mysql-d

## DDBC

MySQL, PostgreSQL, SQLiteに対応。
http://code.dlang.org/packages/ddbc

# その他

## Twitter

http://code.dlang.org/packages/twitter4d

# REPL

https://github.com/MartinNowak/drepl

CentOS 7で動作を確認しました。

```bash
sudo yum install linenoise-devel
git clone https://github.com/MartinNowak/drepl
git submodule init
git submodule update
dub
```

下記Warningが出たら`allocator.d`を修正して再度ビルドします。

```
libdparse/src/std/allocator.d(4229,15): Warning: instead of C-style syntax, use D-style syntax 'Allocator[(max - (min - 1)) / step] buckets'
```

writelnを打っても何も反応が無くて一瞬焦りますが、落ち着いて`import std.stdio;`して下さい。

```d:./drepl
Welcome to D REPL.
D> 1 + 1
2
D> "Hello, DREPL!"
Hello, DREPL!
D> import std.stdio;
std
D> writeln("Hello, DREPL!");
Hello, DREPL!

D> 
```

# さいごに

まだリツイートとフォローしかできないbotですが、生温かい目で見守って頂けると幸いです。
なお、ソースはGithubで公開しています。生き恥を晒したくない方は是非ご利用下さい。

* https://github.com/simdnyan/dmanbot