勉強したことのメモ

Webエンジニア / プログラマが勉強したことのメモ。

GASで「小説家になろう」サイトの更新通知をLINEに送る方法

   2024/02/27  Google Apps Script Google

Google Apps Scriptの勉強として「小説家になろう」サイトの特定小説が更新された場合、LINEに通知を送るというプログラムを作ってみたくなった。以下に作成方法をメモ。

 

やりたい事

スプレッドシートにNコードを入力しておくと定期的に「小説家になろう」のAPIにリクエストし話数に変更があった場合、LINEにその旨通知させたい。尚、Nコードは「https://ncode.syosetu.com/xxxxx/」の「xxxxx」部分にあたる。

 

API

「小説家になろう」のAPIについては以下リファレンスを参照。

https://dev.syosetu.com/man/api/

 

LINE Notify側の作業

トークンの発行等については以下過去記事を参照。

GASとLINEを連携させて通知メッセージを送る方法のメモ

GAS側の作業

GAS側ではスプレッドシートの設定、スクリプトの作成、トリガーの設定が必要になる。

スプレッドシートの設定

後で見たときにわかりやすいようA1~D1セルにカラム名を入力しておく。以下のような形。

「小説の更新日時」「チェックした日時」は本機能に必要は無いが、GASでの時間の比較及び現在日時の取得を勉強しておきたかったので追加した。

また、運用方法としてはA行にNコードを追記していく想定。

スクリプトの作成

function getNovel() {

    //スプレッドシートの読み込み
    const sheet = SpreadsheetApp.getActiveSheet();

    //読み込んだシートの最終行を取得する
    const last = sheet.getLastRow();

    //Nコードをループで取得。Nコードは2行目からなので注意
    for( let i = 2; i <= last; i++ ){

        //通知用フラグ
        let notifyFlg = false;

        //セルからデータ取得
        const ncode = sheet.getRange('A'+i).getValue();
        const cnt = sheet.getRange('B'+i).getValue();
        const novelUpdate = sheet.getRange('C'+i).getValue();
        const sheetUpdate = sheet.getRange('D'+i).getValue();

        //APIのURL。パラメータは「JSON形式での出力」「全掲載部分数と更新日時を出力」「Nコードを指定」
        const novelUrl = 'https://api.syosetu.com/novelapi/api/?out=json&of=ga-nu&ncode=' + ncode;

        //APIをリクエストして応答を受信する
        const result = UrlFetchApp.fetch(novelUrl);

        //JSON化
        const json = JSON.parse(result);

        //小説の更新日時が変更されている場合はセルに書き込み
        if( !novelUpdate || novelUpdate < json[1].novelupdated_at ){
            sheet.getRange('C'+i).setValue( json[1].novelupdated_at );
        }

        //全掲載部分数が変更されている場合はセルに書き込み
        if( !cnt || cnt < json[1].general_all_no ){
            sheet.getRange('B'+i).setValue( json[1].general_all_no );
            notifyFlg = true;
        }

        //チェック日時をセルに書き込み
        const now = new Date();
        const date = Utilities.formatDate(now, 'Asia/Tokyo', 'yyyy-MM-dd HH:mm:ss');
        sheet.getRange('D'+i).setValue( date );

        //全掲載部分数が変更されている場合のみLINE通知
        if( notifyFlg ){

            //メッセージ内容
            const messageText = "なろう更新通知\n\nhttps://ncode.syosetu.com/" + ncode;

            //LINEから取得したトークン
            const token = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxx';

            //fetch用の詳細パラメータ
            const options = {
                'method' : 'post',
                'headers' : {
                    'Authorization' : 'Bearer '+ token
                },
                'payload' : {
                    'message' : messageText
                }
            };

            //LINE APIのURL
            const lineUrl = 'https://notify-api.line.me/api/notify';

            //APIをリクエストして応答を受信する
            UrlFetchApp.fetch(lineUrl, options);
        }

    }

}

 

LINEのトークン部分は適宜変更する。

改良版(2021/03/21追記)

スプレッドシートの読み込み及び書き込みはまとめて行った方が処理時間が早いとの記事を見かけたので改良した。

function getNarou() {

    //スプレッドシートの読み込み
    const sheet = SpreadsheetApp.getActiveSpreadsheet();

    //なろう用シートを指定
    const narouSheet = sheet.getSheetByName('narou');

    //なろう用シートのデータ取得
    const narouSheetVal = narouSheet.getDataRange().getValues();

    //結果用配列
    let resultVal = narouSheetVal;

    //ループ処理
    for( let i = 1; i < narouSheetVal.length; i++ ){

        //通知用フラグ
        let notifyFlg = false;

        //行からデータ取得
        const row = narouSheetVal[i];
        const ncode = row[0];
        const cnt = row[1];
        const novelUpdate = row[2];
        const sheetUpdate = row[3];

        //APIのURL。パラメータは「JSON形式での出力」「全掲載部分数と更新日時を出力」「Nコードを指定」
        const novelUrl = 'https://api.syosetu.com/novelapi/api/?out=json&of=ga-nu&ncode=' + ncode;

        //APIをリクエストして応答を受信する
        const response = UrlFetchApp.fetch(novelUrl);

        //JSON化
        const json = JSON.parse(response);

        //小説の更新日時が変更されている場合
        if( !novelUpdate || novelUpdate < json[1].novelupdated_at ){
            resultVal[i][2] = json[1].novelupdated_at;
        }

        //全掲載部分数が変更されている場合
        if( !cnt || cnt < json[1].general_all_no ){
            resultVal[i][1] = json[1].general_all_no;
            notifyFlg = true;
        }

        //チェック日時
        const now = new Date();
        const date = Utilities.formatDate(now, 'Asia/Tokyo', 'yyyy-MM-dd HH:mm:ss');
        resultVal[i][3] = date;

        //全掲載部分数が変更されている場合のみLINE通知
        if( notifyFlg ){

            //メッセージ内容
            const messageText = "なろう更新通知\n\nhttps://ncode.syosetu.com/" + ncode;

            //LINEから取得したトークン
            const token = 'xxxxxxxxxxxxxxx';

            //fetch用の詳細パラメータ
            const options = {
                'method' : 'post',
                'headers' : {
                    'Authorization' : 'Bearer '+ token
                },
                'payload' : {
                    'message' : messageText
                }
            };

            //LINE APIのURL
            const lineUrl = 'https://notify-api.line.me/api/notify';

            //APIをリクエストして応答を受信する
            UrlFetchApp.fetch(lineUrl, options);
        }

    }

    //シートにまとめて書き込み
    narouSheet.getRange(1, 1, narouSheetVal.length, narouSheetVal[0].length).setValues(resultVal);

}

シート名をデフォルトの「シート1」から「narou」に変更しておく。

トリガーの設定

トリガーとはCronのようにプログラムを自動実行してくれる機能のこと。スクリプトを記述するページの左側に時計のようなアイコンがあり、そちらをクリックするとトリガー設定ページに遷移する。

ページ右下の「トリガーを追加」ボタンをクリックし、「イベントのソースを選択」は「時間手動型」に変更、「時間ベースのトリガーのタイプの選択」は「時間ベース or 分ベースのタイマー」を選択、「時間の間隔を選択」は適宜選択する。

 

その他

GASとは関係ないが私がiPhoneを使用しており、普段使っているブラウザはSleipnir Mobileになる。

ただLINE通知からURLを開こうとするとLINEに搭載されているブラウザで開き、この点が不満なので改善したい。以下で対応可能。

LINE側の設定

「ホーム→歯車マーク→LINE Labs」に進み「リンクをデフォルトのブラウザで開く」をOnにする。この設定を行うとLINEのメッセージ内にあるURLをクリックした際、iPhone側で設定しているデフォルトブラウザでページを開くことができる。

iPhone側の設定

「設定→Sleipnir」に進み「デフォルトのブラウザApp」を「Sleipnir」に変更する。

 

所感

今回はAPIが用意されていたのでそこまで難易度は高くなかった。類似サイトで「カクヨム」があるが、こちらはAPIは用意されておらず、同様の機能を実装したい場合はスクレイピング作業が必要になりそう。GASでのスクレイピングも勉強しておきたいので「カクヨム」にも挑戦したいところ。

 

参考サイト

https://tonari-it.com/gas-spreadsheet-speedup/

https://memodays.jp/584/

 - Google Apps Script Google

  関連記事

GASとLINEを連携させて通知メッセージを送る方法のメモ

Google Apps ScriptとLINEを連携させ、LINEに何らかの通知 ...