パルが更新されたら通知するLINE BotをJavaでつくる。

パルの更新をチェックするのが不毛なので、パルが更新されたら通知するLINE botを作りました。Feedlyとかだと見逃す。

使用した環境・ライブラリ

Javaを採用した理由は、持ってるマシン(Windows 10 2台(内1台はほぼすっぴん)、Raspberry Pi 3(raspbian stretch)、CentOS7)全部で動くようにしたかったからです。DockerはWindowsマシンの片割れで正常に動作せず、Windows Subsystem for Linuxはすっぴんのほうでダウンロードに失敗して環境構築がめんどくさくなってしまい、全員JDKなら入ってるからこれでいいやと思いました。環境ごとにOracleJDKかOpenJDKかがバラバラなのですが、大したことはしないので問題ないと判断しました。

全環境でコマンド一発で動くようにしたいので、依存するクラスをすべて内包した実行可能jarを作ることにします。

実際のコード

java

package biz.retrorocket.hai;

import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.StandardCharsets;

import com.linecorp.bot.client.LineMessagingClient;
import com.linecorp.bot.model.PushMessage;
import com.linecorp.bot.model.message.TextMessage;

import com.rometools.rome.feed.synd.SyndEntry;
import com.rometools.rome.feed.synd.SyndFeed;
import com.rometools.rome.io.FeedException;
import com.rometools.rome.io.SyndFeedInput;

public class RSSReaderBot {

    private static final String CHANNEL_ACCCESS_TOKEN = "TOKEN";
    private static final LineMessagingClient CLIENT = LineMessagingClient.builder(CHANNEL_ACCCESS_TOKEN).build();
    private static final String URL = "http://negineesan.hatenablog.com/rss"; // パルのFeed
    private static final SyndFeedInput INPUT = new SyndFeedInput();
    private static final String CHANNEL_ID = "CHANNEL_ID"; // 通知を流したいチャンネルのID

    public static void main(String[] args) throws IllegalArgumentException, FeedException, IOException {

        long lastUpdateDate = 0;

        while (true) {
            SyndFeed feed = INPUT.build(new InputStreamReader(new URL(URL).openStream(), StandardCharsets.UTF_8));
            SyndEntry entry = feed.getEntries().get(0); // 最新のエントリだけ取得
            long publishedDate = entry.getPublishedDate().getTime();

            if (publishedDate > lastUpdateDate) { // 「最新の日付 > 現在時刻-更新間隔を引いた値」でも別に良い
                CLIENT.pushMessage(new PushMessage(CHANNEL_ID,
                        new TextMessage("パルが更新されました" + "\n" + entry.getTitle() + "\n" + entry.getLink())));
                lastUpdateDate = publishedDate;
            }
            try {
                Thread.sleep(10 * 60 * 1000); // 10分
            } catch (InterruptedException ignore) {
            }
        }
    }
}

今話題の無限ループで10分毎に更新をチェックします。alertじゃないから大丈夫なんじゃないですかね…。(震えながら)httpclientは不要です。

build.gradle

plugins {
    id 'java'
}

version = '0.1-SNAPSHOT'

dependencies {
    // LINE BOT SDK
    implementation 'com.linecorp.bot:line-bot-api-client:2.4.0'
    // ROME
    implementation 'com.rometools:rome:1.12.0'
    implementation 'org.slf4j:slf4j-simple:1.7.25'
    // test
    testImplementation 'junit:junit:4.12'
}

repositories {
    mavenCentral()
}

tasks.withType(JavaCompile) {
    options.encoding = 'UTF-8'
}

jar {
    manifest {
        attributes 'Main-Class':'biz.retrorocket.hai.RSSReaderBot'
    }
    from configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}

Gradle 3.4あたりからcompileじゃなくてimplementation使わないといけないらしいので以下を参考にimplementationで書きました。

LINE SDKとROMEがslf4j-apiに依存していて、実行時にSLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder"でWARNが出てくるので、slf4j-simpleも一緒に指定しています。

あと、ソースコードをUTF-8で書いている場合、build.gradleのオプションでエンコードを指定するのを忘れるとこうなります。

久々に力強い文字化けを見た。

コメントを残す

お手数ですが半角数字で計算結果を入力してください。 *