記事

ZReviewTender|無料オープンソースAppレビュー監視ロボットで評価を即時把握

Appの最新レビューをリアルタイム監視し、即座にフィードバックを提供。チームの連携強化とユーザー満足度向上を実現する無料ツールです。

ZReviewTender|無料オープンソースAppレビュー監視ロボットで評価を即時把握

本記事は AI による翻訳をもとに作成されています。表現が不自然な箇所がありましたら、ぜひコメントでお知らせください。

記事一覧


ZReviewTender — 無料オープンソースのAppレビュー監視ロボット

Appの最新レビューをリアルタイムで監視し、即座にフィードバックを提供して、協力効率と顧客満足度を向上させる

[ZhgChgLi](https://github.com/ZhgChgLi){:target="_blank"} [ZReviewTender](https://github.com/ZhgChgLi/ZReviewTender){:target="_blank"}

ZhgChgLi / ZReviewTender

ZhgChgLi / ZReviewTender

App Reviews to Slack Channel

AppレビューをSlackチャンネルへ

ZReviewTender iOS/macOSのApp StoreとGoogle PlayのAndroidアプリの最新ユーザーレビューを自動で監視し、継続的インテグレーションツールを提供してチームのワークフローに連携、協力効率と顧客満足度を向上させます。

特徴機能

  • App StoreのiOS/macOSアプリとGoogle PlayのAndroidアプリの評価リストを取得し、まだ取得していない最新の評価内容をフィルタリングする

  • [デフォルト機能] 取得した最新の評価をSlackに転送し、メッセージのタイムスタンプリンクをクリックすると管理画面で素早く返信できます

  • [デフォルト機能] Google Translate API を使用して、指定された言語・地域以外のレビュー内容を自動的にあなたの言語に翻訳することをサポートしています

  • [デフォルト機能] Google Sheetへのレビュー自動記録対応

  • 柔軟な拡張をサポートしており、標準機能に加えてチームのワークフローに応じて必要な機能を独自に開発し、ツールに統合できます
    例:評価をDiscord、Line、Telegramなどに転送する…

  • タイムスタンプを使用して取得位置を記録し、レビューの重複取得を防止する

  • フィルタ機能をサポートしており、指定した評価数、評価内容に含まれるキーワード、地域や言語のレビューのみを取得できます。

  • Apple は 新しい App Store Connect API を基に、安定で信頼できる App Store のアプリ評価データを提供しています。これにより、以前のような XML データの不安定さや Fastlane Spaceship セッションの期限切れによる定期的な手動メンテナンス は不要になりました。

  • Androidも公式のAndroidpublisherV3 APIを使用して評価データを取得します

  • GithubリポジトリとGithub Actionsを使ったデプロイをサポートし、無料で迅速にZReviewTenderアプリレビュー監視ロボットを構築できます。

  • 100% Ruby @ RubyGem

TL;DR [2024/09/27] アップデート

迅速なデプロイ手順の整理、最新記事をご参照ください:[Quick Start! ] Github Action x ZReviewTender 無料で素早くあなたのアプリストア評価監視ロボットをデプロイ。

類似サービスとの比較

App Reviews ワークフロー統合例 (Pinkoiで)

問題:

ショップのレビューは製品にとって非常に重要ですが、非常に手作業で繰り返しの転送やコミュニケーションが必要な作業です。

新しい評価を時々手動で確認し、カスタマーサポートの問題があればサポートに転送して対応する必要があり、とても繰り返しの多い手作業です。

ZReviewTender 評価ロボットを使って、評価を自動的にSlackチャンネルに転送することで、皆が最新の評価情報を迅速に受け取り、リアルタイムで追跡・議論できます。また、チーム全体が現在のユーザーからの製品に対する評価や提案を把握できます。

詳細は以下をご参照ください: 2021 Pinkoi Tech Career Talk — 高効率エンジニアチームの秘密

デプロイ — デフォルト機能のみ使用

もしZReviewTenderのデフォルト機能(Slack/Google Translate/フィルター)だけが必要な場合は、以下の簡単なデプロイ方法を利用できます。

ZReviewTender は RubyGems にパッケージとして公開されており、RubyGems を使って簡単にインストールして利用できます。

[おすすめ] Githubリポジトリテンプレートを使って直接デプロイする

  • サーバースペース不要 ✅

  • 環境要件は不要 ✅

  • エンジニアリングの原理を理解する必要はありません ✅

  • Configファイルの設定が完了すれば、デプロイは完了です ✅

  • 8つのステップでデプロイ完了 ✅

  • 完全無料 ✅
    Github Actionはアカウントごとに月2,000分以上の実行時間を提供しており、ZReviewTenderの評価取得は1回あたり約15〜30秒で完了します。
    デフォルトでは6時間ごとに1回実行され、1日に4回実行されます。1か月で約60分の使用量にしかなりません
    Githubのプライベートリポジトリは無料で無制限に作成可能です。

  1. ZReviewTender テンプレートリポジトリへ移動: ZReviewTender-deploy-with-github-action

右上の「Use this template」ボタンをクリックしてください。

  1. リポジトリの作成

  • Repository name: 入力したいリポジトリのプロジェクト名

  • アクセス: プライベート

⚠️⚠️ 必ず プライベートリポジトリ を作成してください ⚠️⚠️

なぜなら、設定ファイルと秘密鍵をプロジェクトにアップロードするため

最後に下の「Create repository from template」ボタンをクリックしてください。

  1. 作成したリポジトリがプライベートリポジトリであることを確認してください

右上のリポジトリ名に「🔒」と Private タグが表示されていることを確認してください。

もし設定していなければ、作成したリポジトリが Public Repo で非常に危険 です。上部タブの「Settings」-> 「General」-> 下部の「Danger Zone」-> 「Change repository visibility」->「Make private」から Private Repo に変更してください

  1. Projectの初期化が成功するまで待つ

RepoのトップページのReadme内で

バッジを確認し、passing であれば初期化が成功したことを示します。

または上部のタブ「Actions」-> 「Init ZReviewTender」ワークフローの実行完了を待ちます:

実行完了状態は3「✅ Init ZReviewTender」-> プロジェクト初期化成功に変わります。

  1. initファイルとディレクトリが正しく作成されているか確認する

上部の「Code」タブをクリックしてプロジェクトディレクトリに戻ります。Project init が成功すると、以下が表示されます:

  • 目次: config/

  • ファイル: config/android.yml

  • ファイル: config/apple.yml

  • 目次: latestCheckTimestamp/

  • ファイル: latestCheckTimestamp/.keep

  1. Configurationの設定が完了し、android.ymlapple.yml を準備する

config/ ディレクトリに移動し、android.ymlapple.yml ファイルの設定を完了してください。

編集するconfi YMLファイルをクリックし、右上の「✏️」をクリックしてファイルを編集します。

本文下部の「 設定 」セクションを参考にして、android.ymlapple.yml の設定を完了してください。

編集が完了したら、下の「Commit changes」ボタンをクリックして設定を保存できます。

対応するキー ファイルを config/ ディレクトリにアップロードしてください:

config/ ディレクトリで、右上の「Add file」->「Upload files」を選択してください

config yml に設定した該当のキーや外部ファイルのパスをまとめて config/ ディレクトリにアップロードし、ファイルを「上部ブロック」へドラッグ&ドロップ → アップロード完了を待つ → 下部の「Commit changes」をクリックして保存してください。

アップロード完了後、/config ディレクトリに戻り、ファイルが正しく保存およびアップロードされているか確認してください。

  1. ZReviewTenderの初期化(手動で一回実行)

上部のタブ「Actions」をクリック -> 左側で「ZReviewTender」を選択 -> 右側のボタンで「Run workflow」を選択 -> 「Run workflow」ボタンをクリックしてZReviewTenderを一度実行します。

クリックすると、ページがリロードされます が表示されます:

「ZReviewTender」をクリックすると、実行状況を確認できます。

Run ZreviewTender -r 」ブロックを展開すると実行ログを確認できます。

ここでエラーが表示されるのは、まだ config yml ファイルを設定していないためです。

android/apple の config yml を調整した後、6. の手順に戻り、最初から再度実行をトリガーしてください。

ZReviewTender -r 」ブロックのログを確認して、実行が成功したことを確認してください!

Slackで最新の評価メッセージを受信する指定チャンネルにも、init Successの成功メッセージが表示されます 🎉

  1. 完了! 🎉 🎉 🎉

設定完了!以降は6時間ごとに期間内の最新レビューを自動で取得し、あなたのSlackチャンネルに転送します!

RepoのホームページのReadmeの上部で最新の実行状況を確認できます:

エラーが発生した場合は、Actions -> ZReviewTender からログを確認してください。予期しないエラーがある場合は、Issueを作成し、ログ情報を添付してください。できるだけ早く修正します。

❌❌❌実行中にエラーが発生すると同時に、GitHubからもメール通知が届くため、エラーでロボットが停止しても誰も気づかないということがありません!

Github Action の調整

ご自身のニーズに合わせてGithub Actionの実行ルールを設定することも可能です。

上部のタブ「Actions」をクリック -> 左側の「ZReviewTender」を選択 -> 右上の「 ZReviewTender.yml 」をクリックしてください

右上の「✏️」をクリックしてファイルを編集してください。

調整可能なパラメータは2つあります:

cron : 新しいレビューをチェックする間隔を設定します。デフォルトは 15 */6 * * * で、6時間ごとに15分に実行されます。

参考に crontab.guru で自分のニーズに合わせて設定してください。

ご注意ください:

  1. Github Action は UTC タイムゾーンを使用しています
  1. 実行頻度が高いほど、GitHub Actionsの実行クレジットを多く消費します

run : 実行するコマンドを設定します。本文下部の「 実行 」セクションを参照してください。デフォルトは ZReviewTender -r です。

  • デフォルト実行 Androidアプリ & Apple(iOS/macOSアプリ): ZReviewTender -r

  • Androidアプリのみ実行:ZReviewTender -g

  • Apple(iOS/macOS App) アプリのみ実行: ZReviewTender -a

編集が完了したら、右上の「Start commit」をクリックし、「Commit changes」を選択して設定を保存します。

手動でZReviewTenderを実行する

参考前文「6. ZReviewTenderの初期化(手動で一度実行)」

Gem を使ったインストール

Gems に慣れている場合は、以下のコマンドで ZReviewTender を直接インストールできます。

1
gem install ZReviewTender

Gem を使ったインストール(Ruby/Gemsに不慣れな方)

RubyやGemsに不慣れな場合は、以下の手順に従って ZReviewTender をステップバイステップでインストールしてください。

  1. macOSにはRubyが標準搭載されていますが、新しいRubyのインストールやバージョン管理にはrbenv または rvm の使用をおすすめします(私は 2.6.5 を使用しています)。

  2. rbenv または rvm を使って Ruby 2.6.5 をインストールし、rbenv/rvm の Ruby に切り替えます

  3. which ruby を使って、現在使用している Ruby が /usr/bin/ruby のシステムRubyでないことを確認します。

  4. Ruby環境が整ったら、以下のコマンドで ZReviewTender をインストールしてください。

1
gem install ZReviewTender

デプロイ — 自分で機能を拡張したい場合

手動

  1. git clone ZReviewTender ソースコード

  2. 環境を確認し、Rubyを準備する

  3. ディレクトリに移動して、bundle install を実行し、ZReviewTender の依存関係をインストールする

Processor の作成方法は、後述の記事内容を参照してください。

設定

ZReviewTender — yamlファイルで設定するApple/Googleレビュー監視ロボット。

[おすすめ] 記事下部の実行コマンド — 「設定ファイルを生成する」を直接使用してください:

1
ZReviewTender -i

空の apple.ymlandroid.yml 設定ファイルを直接生成します。

Apple (iOS/macOS アプリ)

apple.example.yml ファイルを参照:

⚠️ ダウンロードした apple.example.yml は必ずファイル名を apple.yml に変更してください

apple.yml:

1
2
3
4
5
6
platform: 'apple'
appStoreConnectP8PrivateKeyFilePath: '' # APPLE STORE CONNECT API のプライベート .p8 キーファイルのパス
appStoreConnectP8PrivateKeyID: '' # APPLE STORE CONNECT API プライベートキーID
appStoreConnectIssueID: '' # APPLE STORE CONNECT 発行ID
appID: '' # アプリID
...

appStoreConnectIssueID:

appStoreConnectP8PrivateKeyID & appStoreConnectP8PrivateKeyFilePath:

  • 名前: ZReviewTender

  • アクセス: App Manager

  • appStoreConnectP8PrivateKeyID: キーID

  • appStoreConnectP8PrivateKeyFilePath: /AuthKey_XXXXXXXXXX.p8 、APIキーをダウンロードし、ファイルをconfig.ymlと同じディレクトリに置いてください。

appID:

appID: App Store Connect -> App Store -> 一般 -> アプリ情報 -> Apple ID

GCPサービスアカウント

ZReviewTender が使用する Google API サービス(ストアレビューの取得、Google 翻訳、Google Sheet)はすべて Service Account 認証方式を使用しています。

まずは公式手順でGCPとサービスアカウントを作成し、GCPサービスアカウントの認証キー(*.json)をダウンロードして保存してください。

  • 自動翻訳機能を使用する場合は、GCPで Cloud Translation API が有効になっていることと、使用するサービスアカウントに権限が付与されていることを確認してください。

  • Google Sheetに記録する機能を使用する場合は、GCPでGoogle Sheets APIGoogle Drive APIが有効になっていることと、使用するService Accountが追加されていることを確認してください。

Google Play Console (Androidアプリ)

android.example.yml ファイルの参照:

⚠️ ダウンロードした android.example.yml のファイル名を必ず android.yml に変更してください

android.yml:

1
2
3
4
5
6
platform: 'android'
packageName: '' # Androidアプリのパッケージ名
keyFilePath: '' # Google Android Publisher API認証情報の.jsonファイルパス
playConsoleDeveloperAccountID: '' # Googleコンソール開発者アカウントID
playConsoleAppID: '' # GoogleコンソールアプリID
......

packageName:

packageName: com.XXXXXGoogle Play Console -> ダッシュボード -> アプリ から取得できます

playConsoleDeveloperAccountID & playConsoleAppID:

Google Play Console -> ダッシュボード -> アプリのページURLから取得可能:

https://play.google.com/console/developers/ playConsoleDeveloperAccountID /app/ playConsoleAppID /app-dashboard

チームがリンクをクリックしてすぐに管理画面のレビュー返信ページにアクセスできるように、レビューのメッセージリンクを生成します。

keyFilePath:

最も重要な情報、GCPサービスアカウントの認証キー(*.json

公式ドキュメント の手順に従い、Google Cloud プロジェクトとサービスアカウントを作成し、Google Play Console の Setup → API Access で Google Play Android Developer API を有効化してプロジェクトをリンクし、GCP でサービスアカウントの JSON キーをダウンロードしてください。

JSON キーのサンプル内容は以下の通りです:

gcp_key.json:

1
2
3
4
5
6
7
8
9
10
11
12
{
    "type": "service_account",
    "project_id": "XXXX",
    "private_key_id": "XXXX",
    "private_key": "-----BEGIN PRIVATE KEY-----\nXXXX\n-----END PRIVATE KEY-----\n",
    "client_email": "[email protected]",
    "client_id": "XXXX",
    "auth_uri": "https://accounts.google.com/o/oauth2/auth",
    "token_uri": "https://oauth2.googleapis.com/token",
    "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
    "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/XXXX.iam.gserviceaccount.com"
}
  • keyFilePath: /gcp_key.json キーファイルのパス。ファイルをconfig ymlと同じディレクトリに置いてください。

プロセッサー

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
processors:
    - FilterProcessor:
        class: "FilterProcessor"
        enable: true # 有効化
        keywordsInclude: [] # フィルタリングしたいキーワード
        ratingsInclude: [] # フィルタリングしたい評価
        territoriesInclude: [] # フィルタリングしたい地域
    - GoogleTranslateProcessor: # Google翻訳プロセッサー、レビュー本文を指定言語に翻訳します。不要な場合はこのブロックを削除してください。
        class: "GoogleTranslateProcessor"
        enable: false # 有効化
        googleTranslateAPIKeyFilePath: '' # Google翻訳API認証情報.jsonファイルのパス
        googleTranslateTargetLang: 'zh-TW' # 翻訳先の言語
        googleTranslateTerritoriesExclude: ["TWN","CHN"] # 翻訳したくないレビューの発信地域(言語)
    - SlackProcessor: # Slackプロセッサー、AppレビューをSlackに転送します。
        class: "SlackProcessor"
        enable: true # 有効化
        slackTimeZoneOffset: "+08:00" # レビュー作成日時のタイムゾーン
        slackAttachmentGroupByNumber: "1" # 1〜100、1つのSlackメッセージに含めるレビュー数
        slackBotToken: "" # Slack Botトークン、Slack Bot経由でメッセージを送信
        slackBotTargetChannel: "" # Slack Botトークン、Slack Bot経由でメッセージを送信するチャンネル(推奨、優先度高)
        slackInCommingWebHookURL: "" # Slack Incoming WebHook URL、Incoming WebHook経由でメッセージ送信(推奨されず非推奨)
    ...More Processors...

ZReviewTender は4つの Processor を備えており、処理の順序がデータ処理の流れに影響します。FilterProcessor → GoogleTranslateProcessor → SlackProcessor → GoogleSheetProcessor の順番です。

FilterProcessor:

指定された条件でフィルタリングされたレビューのみを処理します。

  • class: FilterProcessor は調整不要で、lib/Processors/ FilterProcessor.rb を指します。

  • enable: true / false このProcessorを有効にするかどうか

  • keywordsInclude: [“ キーワード1 ”,“ キーワード2 ”…] これらのキーワードを含むレビューをフィルタリングする

  • ratingsInclude: [ 1 , 2 …] 1〜5の評価スコアのうち、これらを含む評価をフィルタリングする

  • territoriesInclude: [“ zh-hant ”,” TWN ”…] これらの地域(Apple)または言語(Android)を含むレビューをフィルタリングする

GoogleTranslateProcessor:

評価を指定した言語に翻訳する。

  • class: GoogleTranslateProcessor は調整不要で、lib/Processors/ の GoogleTranslateProcessor.rb を指します。

  • enable: true / false このProcessorを有効にするかどうか

  • googleTranslateAPIKeyFilePath: /gcp_key.json GCPサービスアカウントの認証キー ファイルパス *.json 。ファイルはconfig ymlと同じディレクトリに置いてください。内容の例は上記のGoogle Play Console JSONキーの例を参照してください。
    (該当JSONキーのサービスアカウントに Cloud Translation API の使用権限があることを確認してください)

  • googleTranslateTargetLang: zh-TWen …ターゲット翻訳言語

  • googleTranslateTerritoriesExclude: [“ zh-hant ”,” TWN ”…] 翻訳不要の地域(Apple)または言語(Android)

SlackProcessor:

評価をSlackに転送する。

  • class: SlackProcessor は調整不要で、lib/Processors/ の SlackProcessor.rb を指します。

  • enable: true / false このProcessorを有効にするかどうか

  • slackTimeZoneOffset: +08:00 レビュー時間のタイムゾーン表示

  • slackAttachmentGroupByNumber: 1 は、いくつのレビューを1つのメッセージにまとめて送信するかを設定します。デフォルトは1件のレビューにつき1つのSlackメッセージです。

  • slackBotToken: xoxb-xxxx-xxxx-xxxx Slack Bot Token 、Slackでは postMessages スコープを含むSlack Botを作成し、それを使ってSlackメッセージを送信することを推奨しています。

  • slackBotTargetChannel: CXXXXXX グループID(グループ名ではありません)、Slack Botがメッセージを送信するチャンネルグループです;また、Slack Botをそのグループに追加する必要があります

  • slackInCommingWebHookURL: https://hooks.slack.com/services/XXXXX 旧いInComming WebHookURLを使ってSlackにメッセージを送信します。注意!Slackはこの方法でのメッセージ送信を推奨していません。

ご注意ください。これはレガシーなカスタム統合であり、チームがSlackと連携するための古い方法です。これらの統合は新しい機能が不足しており、将来的に廃止または削除される可能性があります。使用は推奨しません。 代わりに、後継の Slack apps をご確認ください。

  • slackBotToken と slackInCommingWebHookURL は、SlackProcessor が slackBotToken を優先して使用します。

GoogleSheetProcessor

評価をGoogle Sheetに記録する。

  • class: GoogleSheetProcessor は調整不要で、lib/Processors/ の SlackProcessor.rb を指します。

  • enable: true / false このProcessorを有効にするかどうか

  • googleSheetAPIKeyFilePath: /gcp_key.json GCPサービスアカウントの認証キー ファイルパス *.json。ファイルはconfig ymlと同じディレクトリに配置してください。内容の例は上記のGoogle Play Console JSONキーの例を参照してください。
    (該当JSONキーのサービスアカウントに Google Sheets APIGoogle Drive API の使用権限があることを確認してください)

  • googleSheetTimeZoneOffset: +08:00 レビュー時間のタイムゾーン表示

  • googleSheetID: Google Sheet ID
    Google SheetsのURLから取得可能:https://docs.google.com/spreadsheets/d/ googleSheetID /

  • googleSheetName: シート名、例:Sheet1

  • keywordsInclude: [“ キーワード1 ”,“ キーワード2 ”…] これらのキーワードを含むレビューをフィルタリングする

  • ratingsInclude: [ 1 , 2 …] 1〜5の評価スコアを含むレビューをフィルタリングする

  • territoriesInclude: [“ zh-hant ”,” TWN ”…] これらの地域(Apple)または言語(Android)を含むレビューをフィルタリングする

  • values: [ ] 評価情報のフィールド組み合わせ

1
2
3
4
5
6
7
8
9
10
%TITLE% レビュータイトル
%BODY% レビュー内容
%RATING% 評価スコア 1〜5
%PLATFORM% レビュープラットフォーム Apple または Android
%ID% レビューID
%USERNAME% レビュアー名
%URL% レビューリンク
%TERRITORY% レビュー地域(Apple)またはレビュー言語(Android)
%APPVERSION% 評価されたアプリのバージョン
%CREATEDDATE% レビュー作成日

例えば私の Google Sheet の列は以下の通りです:

1
評価スコア,評価タイトル,評価内容,評価情報

則 values は次のように設定できます:

1
values: ["%TITLE%","%BODY%","%RATING%","%PLATFORM% - %APPVERSION%"]

カスタムProcessorで独自のワークフローを連携する

カスタムProcessorが必要な場合は、手動デプロイを使用してください。gem版のZReviewTenderはパッケージ化されており、動的な調整ができません。

以下のように拡張機能を作成する際は、lib/Processors/ProcessorTemplate.rb を参照してください:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
$lib = File.expand_path('../lib', File.dirname(__FILE__))

require "Models/Review"
require "Models/Processor"
require "Helper"
require "ZLogger"

# config.ymlに追加してください:
#
# processors:
#   - ProcessorTemplate:
#       class: "ProcessorTemplate"
#       parameter1: "value"
#       parameter2: "value"
#       parameter3: "value"
#       ...
#

class ProcessorTemplate < Processor

    def initialize(config, configFilePath, baseExecutePath)
        # Processorを初期化
        # configからパラメータを取得 例: config["parameter1"]
        # configFilePath: 設定ファイルのパス (apple.yml/android.yml)
        # baseExecutePath: ユーザーの実行パス
    end

    def processReviews(reviews, platform)
        if reviews.length < 1
            return reviews
        end

        ## reviewsに対して必要な処理を行う...
        
        ## 処理後のreviewsを返す
        return reviews
    end
end

initialize は以下を提供します:

  • config Object: config yml 内の設定値に対応しています

  • configFilePath: 使用するconfig ymlファイルのパス

  • baseExecutePath: ユーザーがZReviewTenderを実行するパス

processReviews(reviews, platform):

新しいレビューを取得した後、この function に入り、Processor が処理する機会を得ます。処理が終わったら、結果の Reviews を return してください。

Review データ構造は lib/Models/ Review.rb に定義されています。

注記

XXXterritorXXX パラメータ:

  • Apple 使用地域:TWM/JPN…

  • Android 使用言語:zh-hant/en/…

特定のProcessorが不要な場合:
enable: false を設定するか、該当のProcessorの設定ブロックを直接削除してください。

Processors の実行順序はご自身のニーズに合わせて自由に調整できます:
例:まず Filter を実行し、その後翻訳、Slack、最後に Google Sheet へのログ記録を実行…

実行

⚠️ Gemを使用する場合は直接 ZReviewTender を実行してください。手動でプロジェクトをデプロイする場合は、bundle exec ruby bin/ZReviewTender を使って実行してください。

設定ファイルの生成:

1
ZReviewTender -i

apple.example.yml と android.example.yml から、現在の実行ディレクトリの config/ フォルダに apple.yml と android.yml を生成します。

Apple と Android のレビュー取得を実行:

1
ZReviewTender -r
  • デフォルトで /config/ フォルダ内の apple.ymlandroid.yml の設定を読み込みます

Apple と Android のレビュー取得&指定設定ファイルディレクトリの実行:

1
ZReviewTender --run=設定ファイルディレクトリ
  • デフォルトで /config/ フォルダ内の apple.ymlandroid.yml を読み込みます

Appleのレビュー取得のみ実行:

1
ZReviewTender -a
  • デフォルトで /config/ 下の apple.yml 設定を読み込みます

Appleのレビュー取得のみ実行 & 指定設定ファイルの場所:

1
ZReviewTender --apple=apple.yml設定ファイルの場所

Androidのレビュー収集のみ実行:

1
ZReviewTender -g
  • デフォルトで /config/ 下の android.yml 設定を読み込みます

Androidのレビュー取得のみ実行 & 設定ファイルの場所指定:

1
ZReviewTender --googleAndroid=android.yml設定ファイルの場所

実行記録をクリアして初期設定に戻す

1
ZReviewTender -d

/latestCheckTimestamp 内のタイムスタンプ記録ファイルを削除し、初期状態に戻すと、再度実行した際に再び init success メッセージを受け取ります:

現在の ZReviewTender バージョン

1
ZReviewTender -v

現在の ZReviewTender の最新バージョン番号を RubyGem で表示します。

ZReviewTender を最新バージョンに更新する (rubygem のみ)

1
ZReviewTender -n

初回実行

初回実行成功時に、指定したSlackチャンネルへ初期化成功メッセージを送信し、実行ディレクトリ内に latestCheckTimestamp/ApplelatestCheckTimestamp/Android ファイルが作成され、最後に取得したレビューのタイムスタンプを記録します。

また、実行エラーを記録する execute.log が生成されます。

スケジュールの継続実行設定

スケジュールを設定し定期的に( crontab )新しいレビューの取得を継続的に実行します。ZReviewTender は latestCheckTimestamp から前回取得したレビューのタイムスタンプから今回の取得時間までの新しいレビューを取得し、タイムスタンプの記録ファイルを更新します。

例:crontab: 15 */6 * * * ZReviewTender -r

また、Android APIは直近7日間に追加または編集された評価のみを取得できるため、スケジュールの周期は7日を超えないようにしてください。評価の取りこぼしを防ぐためです。

<https://developers.google.com/android-publisher/reply-to-reviews#retrieving_a_set_of_reviews>{:target="_blank"}

https://developers.google.com/android-publisher/reply-to-reviews#retrieving_a_set_of_reviews

Github Action デプロイ

[ZReviewTender App Reviews Automatic Bot](https://github.com/marketplace/actions/zreviewtender-app-reviews-automatic-bot){:target="_blank"}

ZReviewTender アプリレビュー自動監視ボット

1
2
3
4
5
6
7
8
9
10
11
12
13
14
name: ZReviewTender
on:
  workflow_dispatch:
  schedule:
    - cron: "15 */6 * * *" #6時間ごとに実行、上記のcrontabを参考に設定を変更可能

jobs:
  ZReviewTender:
    runs-on: ubuntu-latest
    steps:
    - name: ZReviewTender Automatic Bot
      uses: ZhgChgLi/ZReviewTender@main
      with:
        command: '-r' #Apple & iOSアプリの評価チェックを実行、上記を参考に他のコマンドに変更可能

⚠️️️️️ 再度警告!

設定ファイルやキーが公開されないように必ず管理してください。これらの機密情報が漏洩すると、AppやSlackの権限が不正利用される恐れがあります。作者は不正利用に関して一切の責任を負いません。

もし予期しないエラーが発生した場合は、Issueを作成してください ログ情報を添付していただければ、できるだけ早く修正します!

完了

使用方法の説明は以上です。次に、開発の裏話を共有します。

=========================

Appレビューとの戦い

昨年まとめた AppStore APP’s Reviews Slack Bot について と関連技術で実現した ZReviewsBot — Slack App Review 通知ボット によって、アプリの最新レビューを社内ワークフローに統合する取り組みは一区切りついたと思っていました。しかし、Appleが今年 App Store Connect APIを更新 し、この取り組みがさらに進化することになりました。

昨年まとめたApple iOS/macOSアプリのレビュー取得ソリューション:

  • Public URL API (RSS) ⚠️: 柔軟なフィルタリングができず、提供される情報も少なく、件数制限があり、時折データの不整合が発生するため非常に不安定です。公式は将来的に廃止する可能性があります。

  • FastlaneSpaceShip を使って、複雑なウェブ操作やセッション管理をラップし、App Store Connectの管理画面から評価データを取得します(ウェブブラウザのエミュレーターを使って管理画面をクロールするイメージです)。

昨年の方法に従うと、方法二のみで対応可能でしたが、効果はあまり良くありませんでした。セッションは期限切れになり、手動で定期的に更新する必要があり、IPが変わるとセッションがすぐに期限切れになるため、CI/CDサーバー上での運用はできません。

[important-note-about-session-duration](https://docs.fastlane.tools/best-practices/continuous-integration/#important-note-about-session-duration){:target="_blank"} by Fastlane

important-note-about-session-duration by Fastlane

今年、AppleがApp Store Connect APIを更新したという知らせを受けてすぐに、新しいレビュー監視ロボットの再設計に取り掛かりました。公式APIの採用に加え、以前のアーキテクチャ設計を改善し、Rubyの使い方にもより精通しました。

App Store Connect API 開発で直面した問題

とても奇妙ですが、まずこのエンドポイントを叩いて最新のレビューを絞り込み、その後に List All App Store Versions for an AppList All Customer Reviews for an App Store Version を組み合わせてアプリのバージョン情報を取得しています。

AndroidpublisherV3 開発で直面した問題

  • APIはすべてのレビュー一覧を取得する方法を提供しておらず、直近7日間に追加または編集されたレビューのみ取得可能です。

  • 同様に JWT を使って Google API に接続する(関連ライブラリに依存しない例 e.g. google-apis-androidpublisher_v3)

  • Google API JWT の生成&使用例を添付:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
require "jwt"
require "time"

payload = {
  iss: "GCP API 認証キー (*.json) ファイル内の client_email フィールド",
  sub: "GCP API 認証キー (*.json) ファイル内の client_email フィールド",
  scope: ["https://www.googleapis.com/auth/androidpublisher"].join(' '),
  aud: "GCP API 認証キー (*.json) ファイル内の token_uri フィールド",
  iat: Time.now.to_i,
  exp: Time.now.to_i + 60*20
}

rsa_private = OpenSSL::PKey::RSA.new("GCP API 認証キー (*.json) ファイル内の private_key フィールド")
token = JWT.encode payload, rsa_private, 'RS256', header_fields = {kid:"GCP API 認証キー (*.json) ファイル内の private_key_id フィールド", typ:"JWT"}

uri = URI("API 認証キー (*.json) ファイル内の token_uri フィールド")
https = Net::HTTP.new(uri.host, uri.port)
https.use_ssl = true
request = Net::HTTP::Post.new(uri)
request.body = "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=#{token}"

response = https.request(request).read_body

bearer = result["access_token"]

### bearer トークンを使用

uri = URI("https://androidpublisher.googleapis.com/androidpublisher/v3/applications/APP_PACKAGE_NAME/reviews")
https = Net::HTTP.new(uri.host, uri.port)
https.use_ssl = true
        
request = Net::HTTP::Get.new(uri)
request['Authorization'] = "Bearer #{bearer}";
        
response = https.request(request).read_body
        
result = JSON.parse(response)

# 成功!

ご質問やご意見がありましたら、お問い合わせ ください。

*Post は Medium から ZMediumToMarkdown によって変換されました。


🍺 Buy me a beer on PayPal

👉👉👉 Follow Me On Medium! (1,053+ Followers) 👈👈👈

本記事は Medium にて初公開されました(こちらからオリジナル版を確認)。ZMediumToMarkdown による自動変換・同期技術を使用しています。

Improve this page on Github.

本記事は著者により CC BY 4.0 に基づき公開されています。