Java初心者がVisual Studio Codeで年号のトリビアをLINEに通知する機能を作ってみた

#概要
JavaをUdemyでざっくり学習したくらいの状態。
取り敢えず何か作ってみようと思い、年号のトリビアをランダムで取得しLINEに通知する機能を作りました。
下記はcronに1分おきに定期実行するよう設定した際の結果です。

出力例

```
15:20 LINE Notify [年号雑学] 1564は、最初のねずみ王（フォークロア）発見が報告される年である。
15:21 LINE Notify [年号雑学] 886は、ブルガリア帝国で、グラゴール文字アルファベットが、シリルとメトディオスにより考案されて、コンスタンチノープルからの宣教師と採用される年である。
15:22 LINE Notify [年号雑学] 1086は、5月24日に1087年5月9日まで彼が選挙を受け入れないけれども、法王ビクターIIIが158番目の法王として法王グレゴリーVIIに続く年である。
15:23 LINE Notify [年号雑学] オランダ反乱をサポートするために、イギリスを委任し、1585は、ノンサッチの条約がサインされる年であり、従って、8月20日に80年の戦争に入る。
15:24 LINE Notify [年号雑学] 1164は、ベニスの共和国がジェノバ人例と安全であることを模倣する年である 下の利率を得る会計の収益に対するその貸付金 。
15:25 LINE Notify [年号雑学] 217は、シリアクスがコンスタンチノープルの家長としてバイカウツギに続く年である。
```

#環境
・java 17.0.1
・Visual Studio Code: 1.61.2

#使用したAPI
・LINE Notify

https://notify-api.line.me/api/notify

アクセストークンの取得や通知設定は下記のサイトを参考にしました。

https://www.smilevision.co.jp/blog/tsukatte01/

・Numbers API
数字に関するトリビアを教えてくれる。
今回は年号のトリビアをランダムで返してくれるAPIを使用。

http://numbersapi.com/random/year?json

#プロジェクトの作成
1)「Ctrl+Shift+P」でコマンドパレットを開き、「java:Create Java Project」を選択

2)No build toolsを選択

3)プロジェクトの保存先を選択
任意のディレクトリでプロジェクト名を入力します。
今回はLineNotifyというプロジェクトにしました。

#最終的なLineNotify配下のディレクトリ構成

```
├── README.md
├── bin
│   └── LineNotify.class
├── lib
│   ├── jackson-annotations-2.13.0.jar
│   ├── jackson-core-2.13.0.jar
│   └── jackson-databind-2.13.0.jar
└── src
    └── LineNotify.java
```

JSONを扱うため、こちらからjarファイルをダウンロードしlib配下に配置しました。

https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core

参考サイト

https://tech.pjin.jp/blog/2020/03/09/jackson_setup/

#ソース

```LineNotify.java
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.*;
import java.net.*;
import java.util.Objects;
import java.util.stream.Collectors;

public class LineNotify {
    private static final String ACCESS_TOKEN = "*****************"; // Line Notifyのアクセストークン
    private static final String NOTIFY_API = "https://notify-api.line.me/api/notify";

    public static void main(String[] args) {
        LineNotify lineNotify = new LineNotify();

        JsonNode numbersapi_result = getResult("http://numbersapi.com/random/year?json"); // 年号APIからJSONを取得
        String text = numbersapi_result.get("text").textValue();
        String ja_text = getTransText(text); // 日本語に翻訳
        lineNotify.notify(ja_text);
        System.out.println("lineへ通知成功");
    }

    public void notify(String message) {
        HttpURLConnection connection = null;
        try {
            URL url = new URL(NOTIFY_API);
            connection = (HttpURLConnection) url.openConnection();
            connection.setDoOutput(true);
            connection.setRequestMethod("POST");
            connection.addRequestProperty("Authorization", "Bearer " + ACCESS_TOKEN);
            try (OutputStream os = connection.getOutputStream(); PrintWriter writer = new PrintWriter(os)) {
                writer.append("message=").append(URLEncoder.encode(message, "UTF-8")).flush();
                try (InputStream is = connection.getInputStream();
                        BufferedReader r = new BufferedReader(new InputStreamReader(is))) {
                    String res = r.lines().collect(Collectors.joining());
                    if (!res.contains("\"message\":\"ok\"")) {
                        System.out.println(res);
                    }
                }
            }
        } catch (Exception ignore) {
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }

    public static JsonNode getResult(String urlString) {
        String result = "";
        JsonNode root = null;
        try {
            URL url = new URL(urlString);
            HttpURLConnection con = (HttpURLConnection) url.openConnection();
            con.connect(); // URL接続
            BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
            String tmp = "";

            while ((tmp = in.readLine()) != null) {
                result += tmp;
            }

            ObjectMapper mapper = new ObjectMapper();
            root = mapper.readTree(result);
            in.close();
            con.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return root;
    }

    public static String getTransText(String before) {
        String afterText = null; // 翻訳されたテキスト
        try {
            // URLクラスのインスタンスを生成
            URL exciteURL = new URL("https://www.excite.co.jp/world/english/");
            // 接続
            URLConnection con = exciteURL.openConnection();
            // 出力を行うように設定
            con.setDoOutput(true);
            // 出力ストリームを取得
            PrintWriter out = new PrintWriter(con.getOutputStream());
            // クエリー文の生成・送信
            out.print("before={" + before + "}&wb_lp=ENJA");
            out.close();
            // 入力ストリームを取得
            BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
            // 一行ずつ読み込む
            String aline;
            String matche = "<textarea id=\"after\" class=\"resizable\" cols=\"37\" rows=\"13\" name=\"after\">";
            while ((aline = in.readLine()) != null) {
                if (aline.contains(matche)) {
                    // 不要な文字を削除
                    afterText = aline.replace(matche + "{", "").replace("}</textarea>", "").trim();
                }
            }
            in.close(); // 入力ストリームを閉じる
        } catch (IOException e) {
            e.printStackTrace();
        }
        return afterText;
    }
}
```

#やっていること

getResultメソッドで年号のトリビアをAPIから取得
↓
getTransTextメソッドで取得したテキストを日本語に翻訳
↓
notifyメソッドでテキストをLINEに通知

#最後に
PHPに慣れてしまっているので、Javaだとやや冗長になってしまうという印象でした。
今回は「静的型付け言語も少しはかじっておかないとな」という危機感から、Javaを通して触れていきましたが、これを機にJVM系の言語にも手を出していけたら良いなと思います。