読者です 読者をやめる 読者になる 読者になる

はてなブックマーク Web Hookで、はてなブックマークをパトロールしよう!

自作IRCライブラリを使ってみよう!ってことで、はてなブックマーク Web Hookを使って、ブックマークをIRCでヲチするアプリケーション「はてなパトロール」を作りました!

はてなWebHookの設定方法は、公式ページを参考にしてください!

このアプリケーションを実行するのに必要なライブラリは、IRCKitとJettyだけです。正常に起動できると、指定されたチャンネルに「Welcome to WebHook.」とメッセージを表示します。あとは、いつも通りはてなブックマークをすれば、ブックマークをIRCに表示します。簡単ですね。

/*
 *  Copyright (c) 2009 tarchan. All rights reserved.
 */
package com.mac.tarchan.webhook;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.mortbay.jetty.Connector;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.nio.SelectChannelConnector;
import org.mortbay.jetty.servlet.ServletHandler;
import org.mortbay.jetty.servlet.ServletHolder;

import com.mac.tarchan.net.irc.client.IRCClient;
import com.mac.tarchan.net.irc.client.IRCMessage;
import com.mac.tarchan.net.irc.client.Reply;

/**
 * はてなパトロールは、はてなWebHookを使用したサービスです。
 * 
 * @author tarchan
 */
public class HatetaPatrol extends HttpServlet
{
	/** WebHookのキー */
	String webhookKey = "WebHookのキー";

	/** WebHookのパス */
	String webhookPath = "WebHookのパス";

	/** WebHookのポート */
	int webhookPort = <WebHookのポート>;

	/** IRCクライアント */
	transient IRCClient irc;

	/** IRCサーバー */
	String ircHost = "IRCサーバー";

	/** IRCサーバーのポート */
	String ircPort = "IRCサーバーのポート";

	/** IRCチャンネル */
	String ircChannel = "IRCチャンネル";

	/** 文字エンコーディング */
	String ircEncoding = "文字エンコーディング";

	/** IRCニックネーム */
	String ircNick = "IRCニックネーム";

	/**
	 * はてなパトロールを開始します。
	 * 
	 * @param args なし
	 */
	public static void main(String[] args)
	{
		try
		{
			HatetaPatrol webhook = new HatetaPatrol();
			webhook.startIRC();
			webhook.startServlet();
		}
		catch (Exception x)
		{
			x.printStackTrace();
		}
	}

	/**
	 * IRCを開始します。
	 * 
	 * @throws IOException IRCサーバーに接続できない場合
	 */
	synchronized void startIRC() throws IOException
	{
		irc = new IRCClient()
			.setProperty("irc.host", ircHost)
			.setProperty("irc.port", ircPort)
			.setProperty("irc.channel", ircChannel)
			.setProperty("irc.encoding", ircEncoding)
			.setProperty("irc.nick.name", ircNick)
			.addAllHandlers(this);
		irc.open();
	}

	/**
	 * WebHookのリクエストを受けるサービスを開始します。
	 * 
	 * @throws Exception Webサーバーが開始できない場合
	 */
	void startServlet() throws Exception
	{
		ServletHolder servletHolder = new ServletHolder(this);
		ServletHandler servletHandler = new ServletHandler();
		servletHandler.addServletWithMapping(servletHolder, webhookPath);

		SelectChannelConnector connector = new SelectChannelConnector();
		connector.setPort(webhookPort);
		Server server = new Server();
		server.setConnectors(new Connector[]{connector});
		server.addHandler(servletHandler);
		server.start();
	}

	/**
	 * IRC接続のウェルカムメッセージを表示します。
	 * 
	 * @param msg IRCメッセージ
	 */
	@Reply("001")
	public void onWelcome(IRCMessage msg)
	{
		String welcome = "Welcome to WebHook.";
		log(welcome);
		doNotice(ircChannel, welcome);
	}

	/**
	 * IRCメッセージをロギングします。
	 * 
	 * @param msg IRCメッセージ
	 */
	@Reply("ALL")
	public void onMessage(IRCMessage msg)
	{
		// エラーでない場合は何もしない
		if (msg.isNumelicReply() && msg.getNumber() < 400) return;
		if (!msg.getCommand().equals("ERROR")) return;

		log(msg.toString());
	}

	/**
	 * IRCにメッセージを送信します。
	 * 
	 * @param channel チャンネル
	 * @param str メッセージ
	 */
	synchronized void doNotice(String channel, String str)
	{
		String msg = String.format("PRIVMSG %s :%s", channel, str);
		irc.postMessage(msg);
	}

	/**
	 * はてなWebHookを処理します。
	 */
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
	{
		req.setCharacterEncoding("UTF-8");
		String username = req.getParameter("username");
		String title = req.getParameter("title");
		String url = req.getParameter("url");
		String status = req.getParameter("status");
		String comment = req.getParameter("comment");
		String key = req.getParameter("key");

		// APIキーを確認
		if (!key.equals(webhookKey))
		{
			res.sendError(HttpServletResponse.SC_BAD_REQUEST);
			return;
		}

		// はてなブックマークを送信
		String bookmark = String.format("[%s] %s %s %s", username, title, url, comment);
		log(String.format("[%S] %s", status, bookmark));
		doNotice(ircChannel , bookmark);
	}

	/**
	 * ロギングします。
	 */
	@Override
	public void log(String msg)
	{
		System.out.println(msg);
	}
}