JavaとXMPPでSlackのbotをつくる

# TL;DR

* XMPPを使うことで簡単にbot作ることが可能

# はじめに

[slack](https://slack.com/)に[HUBOT](https://hubot.github.com/)経由で投稿する奴はたくさんあるんだけど、js以外の言語でかけるといいなーとずっと思ってきた。
Rubyだと[Ruboty](https://github.com/r7kamura/ruboty)ってツールがあっていいなーと思ってた。
仕事ではJVM系の言語使うこと多いんで、調べてみた。

# やり方

## slackでxmppオプションをオンにする

## [Smack](https://www.igniterealtime.org/projects/smack/)

JavaのXMPPクライアントはいくつかあるけど、今回はSmackを使った。

# サンプルコード

```groovy:build.gradle
apply plugin: 'java'
sourceCompatibility = 1.8
targetCompatibility = 1.8
def defaultEncoding = 'UTF-8'
tasks.withType(AbstractCompile)*.options*.encoding = defaultEncoding
tasks.withType(GroovyCompile)*.groovyOptions*.encoding = defaultEncoding
repositories {
    mavenCentral()
}

dependencies {

    compile "org.igniterealtime.smack:smack-java7:4.1.3"
    compile "org.igniterealtime.smack:smack-tcp:4.1.3"
    compile "org.igniterealtime.smack:smack-im:4.1.3"

    compile "org.igniterealtime.smack:smack-extensions:4.1.3"
}
```


```java:SlackBot.java
package com.github.masahitojp;

import org.jivesoftware.smack.*;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
import org.jivesoftware.smackx.muc.MultiUserChat;
import org.jivesoftware.smackx.muc.MultiUserChatManager;

import java.io.IOException;

public class SlackBot {

  //  TODO 設定から読み込む
	static String SLACK_HOST_NAME = "SLACK_HOST_NAME";
	static String SLACK_HOST_USER = "SLACK_HOST_USER";
	static String SLACK_HOST_PASSWORD = "SLACK_HOST_PASSWORD";
	static String SLACK_ROOM_NAME = "general";

	static public void main(String[] Args) {

		final XMPPTCPConnectionConfiguration connConfig = XMPPTCPConnectionConfiguration
				.builder()
				.setServiceName(SLACK_HOST_NAME)
				.setCompressionEnabled(false)
				.build();


		final AbstractXMPPConnection connection = new XMPPTCPConnection(connConfig);
		try {
			connection.connect();
			connection.login(SLACK_HOST_USER, SLACK_HOST_PASSWORD);
			final MultiUserChatManager mucm = MultiUserChatManager.getInstanceFor(connection);
			final MultiUserChat muc = mucm.getMultiUserChat(SLACK_ROOM_NAME + "@conference." + SLACK_HOST_NAME);

			muc.addMessageListener(message -> {

				System.out.println("Received message: " + message);
				final String body = message.getBody();
				if (body != null) {
					try {
						if (message.getBody().equals("ping")) {
							muc.sendMessage("pong");
						}
					} catch (SmackException.NotConnectedException e) {
						System.out.println(e.getMessage());
					}
				}
			});

            final ChatManager cm = ChatManager.getInstanceFor(connection);


            // private message
            cm.addChatListener((chat1, message) -> {
                    chat1.addMessageListener(
                            (chat, message1) -> {
                                System.out.println(message1);
                                try {
                                    chat.sendMessage("Hello, World!");
                                } catch (SmackException.NotConnectedException e) {
                                    e.printStackTrace();
                                }
                            }
                    );

            });

			muc.join(SLACK_HOST_USER, SLACK_HOST_PASSWORD);

			muc.sendMessage("connected at " + System.currentTimeMillis());

			while(true) {
				Thread.sleep(1000);
			}
		} catch (XMPPException | SmackException | IOException | InterruptedException e) {
			e.printStackTrace();
		} finally {
			connection.disconnect();
		}
	}
}
```

# まとめ

JVM言語でもSlackbotが実装できることがわかりました。
JavaのPaas があればそのまま動かすことが可能だと思いますー

以上