ZReviewTender|無料オープンソースAppレビュー監視ロボットで評価を即時把握
Appの最新レビューをリアルタイム監視し、即座にフィードバックを提供。チームの連携強化とユーザー満足度向上を実現する無料ツールです。
本記事は AI による翻訳をもとに作成されています。表現が不自然な箇所がありましたら、ぜひコメントでお知らせください。
記事一覧
ZReviewTender — 無料オープンソースのAppレビュー監視ロボット
Appの最新レビューをリアルタイムで監視し、即座にフィードバックを提供して、協力効率と顧客満足度を向上させる
ZhgChgLi / ZReviewTender
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] アップデート
類似サービスとの比較
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のプライベートリポジトリは無料で無制限に作成可能です。
- ZReviewTender テンプレートリポジトリへ移動: ZReviewTender-deploy-with-github-action
右上の「Use this template」ボタンをクリックしてください。
- リポジトリの作成
Repository name: 入力したいリポジトリのプロジェクト名
アクセス: プライベート
⚠️⚠️ 必ず プライベートリポジトリ を作成してください ⚠️⚠️
なぜなら、設定ファイルと秘密鍵をプロジェクトにアップロードするため
最後に下の「Create repository from template」ボタンをクリックしてください。
- 作成したリポジトリがプライベートリポジトリであることを確認してください
右上のリポジトリ名に「🔒」と Private タグが表示されていることを確認してください。
もし設定していなければ、作成したリポジトリが Public Repo で非常に危険 です。上部タブの「Settings」-> 「General」-> 下部の「Danger Zone」-> 「Change repository visibility」->「Make private」から Private Repo に変更してください 。
- Projectの初期化が成功するまで待つ
RepoのトップページのReadme内で
バッジを確認し、passing であれば初期化が成功したことを示します。
または上部のタブ「Actions」-> 「Init ZReviewTender」ワークフローの実行完了を待ちます:
実行完了状態は3「✅ Init ZReviewTender」-> プロジェクト初期化成功に変わります。
- initファイルとディレクトリが正しく作成されているか確認する
上部の「Code」タブをクリックしてプロジェクトディレクトリに戻ります。Project init が成功すると、以下が表示されます:
目次:
config/ファイル:
config/android.ymlファイル:
config/apple.yml目次:
latestCheckTimestamp/ファイル:
latestCheckTimestamp/.keep
- Configurationの設定が完了し、
android.ymlとapple.ymlを準備する
config/ ディレクトリに移動し、android.yml と apple.yml ファイルの設定を完了してください。
編集するconfi YMLファイルをクリックし、右上の「✏️」をクリックしてファイルを編集します。
本文下部の「 設定 」セクションを参考にして、android.yml と apple.yml の設定を完了してください。
編集が完了したら、下の「Commit changes」ボタンをクリックして設定を保存できます。
対応するキー ファイルを config/ ディレクトリにアップロードしてください:
config/ ディレクトリで、右上の「Add file」->「Upload files」を選択してください
config yml に設定した該当のキーや外部ファイルのパスをまとめて config/ ディレクトリにアップロードし、ファイルを「上部ブロック」へドラッグ&ドロップ → アップロード完了を待つ → 下部の「Commit changes」をクリックして保存してください。
アップロード完了後、/config ディレクトリに戻り、ファイルが正しく保存およびアップロードされているか確認してください。
- ZReviewTenderの初期化(手動で一回実行)
上部のタブ「Actions」をクリック -> 左側で「ZReviewTender」を選択 -> 右側のボタンで「Run workflow」を選択 -> 「Run workflow」ボタンをクリックしてZReviewTenderを一度実行します。
クリックすると、ページがリロードされます が表示されます:
「ZReviewTender」をクリックすると、実行状況を確認できます。
「 Run ZreviewTender -r 」ブロックを展開すると実行ログを確認できます。
ここでエラーが表示されるのは、まだ config yml ファイルを設定していないためです。
android/apple の config yml を調整した後、6. の手順に戻り、最初から再度実行をトリガーしてください。
「 ZReviewTender -r 」ブロックのログを確認して、実行が成功したことを確認してください!
Slackで最新の評価メッセージを受信する指定チャンネルにも、init Successの成功メッセージが表示されます 🎉
- 完了! 🎉 🎉 🎉
設定完了!以降は6時間ごとに期間内の最新レビューを自動で取得し、あなたのSlackチャンネルに転送します!
RepoのホームページのReadmeの上部で最新の実行状況を確認できます:
エラーが発生した場合は、Actions -> ZReviewTender からログを確認してください。予期しないエラーがある場合は、Issueを作成し、ログ情報を添付してください。できるだけ早く修正します。
❌❌❌実行中にエラーが発生すると同時に、GitHubからもメール通知が届くため、エラーでロボットが停止しても誰も気づかないということがありません!
Github Action の調整
ご自身のニーズに合わせてGithub Actionの実行ルールを設定することも可能です。
上部のタブ「Actions」をクリック -> 左側の「ZReviewTender」を選択 -> 右上の「 ZReviewTender.yml 」をクリックしてください
右上の「✏️」をクリックしてファイルを編集してください。
調整可能なパラメータは2つあります:
cron : 新しいレビューをチェックする間隔を設定します。デフォルトは 15 */6 * * * で、6時間ごとに15分に実行されます。
参考に crontab.guru で自分のニーズに合わせて設定してください。
ご注意ください:
- Github Action は UTC タイムゾーンを使用しています
- 実行頻度が高いほど、GitHub Actionsの実行クレジットを多く消費します
run : 実行するコマンドを設定します。本文下部の「 実行 」セクションを参照してください。デフォルトは ZReviewTender -r です。
デフォルト実行 Androidアプリ & Apple(iOS/macOSアプリ):
ZReviewTender -rAndroidアプリのみ実行:
ZReviewTender -gApple(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 をステップバイステップでインストールしてください。
macOSにはRubyが標準搭載されていますが、新しいRubyのインストールやバージョン管理にはrbenv または rvm の使用をおすすめします(私は
2.6.5を使用しています)。rbenv または rvm を使って Ruby 2.6.5 をインストールし、rbenv/rvm の Ruby に切り替えます
which rubyを使って、現在使用している Ruby が /usr/bin/ruby のシステムRubyでないことを確認します。Ruby環境が整ったら、以下のコマンドで
ZReviewTenderをインストールしてください。
1
gem install ZReviewTender
デプロイ — 自分で機能を拡張したい場合
手動
git clone ZReviewTender ソースコード
環境を確認し、Rubyを準備する
ディレクトリに移動して、
bundle installを実行し、ZReviewTender の依存関係をインストールする
Processor の作成方法は、後述の記事内容を参照してください。
設定
ZReviewTender — yamlファイルで設定するApple/Googleレビュー監視ロボット。
[おすすめ] 記事下部の実行コマンド — 「設定ファイルを生成する」を直接使用してください:
1
ZReviewTender -i
空の apple.yml と android.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:
App Store Connect -> Keys -> App Store Connect API
発行者ID:
appStoreConnectIssueID
appStoreConnectP8PrivateKeyID & appStoreConnectP8PrivateKeyFilePath:
名前:
ZReviewTenderアクセス:
App Manager
appStoreConnectP8PrivateKeyID:
キーIDappStoreConnectP8PrivateKeyFilePath:
/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 API、Google 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.XXXXX は Google Play Console -> ダッシュボード -> アプリ から取得できます
playConsoleDeveloperAccountID & playConsoleAppID:
Google Play Console -> ダッシュボード -> アプリのページURLから取得可能:
チームがリンクをクリックしてすぐに管理画面のレビュー返信ページにアクセスできるように、レビューのメッセージリンクを生成します。
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.jsonGCPサービスアカウントの認証キー ファイルパス*.json。ファイルはconfig ymlと同じディレクトリに置いてください。内容の例は上記のGoogle Play Console JSONキーの例を参照してください。
(該当JSONキーのサービスアカウントにCloud Translation APIの使用権限があることを確認してください)googleTranslateTargetLang:
zh-TW、en…ターゲット翻訳言語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-xxxxSlack 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.jsonGCPサービスアカウントの認証キー ファイルパス*.json。ファイルはconfig ymlと同じディレクトリに配置してください。内容の例は上記のGoogle Play Console JSONキーの例を参照してください。
(該当JSONキーのサービスアカウントにGoogle Sheets APIとGoogle Drive APIの使用権限があることを確認してください)googleSheetTimeZoneOffset:
+08:00レビュー時間のタイムゾーン表示googleSheetID:
Google Sheet ID
Google SheetsのURLから取得可能:https://docs.google.com/spreadsheets/d/googleSheetID/googleSheetName: シート名、例:
Sheet1keywordsInclude: [“
キーワード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.ymlとandroid.ymlの設定を読み込みます
Apple と Android のレビュー取得&指定設定ファイルディレクトリの実行:
1
ZReviewTender --run=設定ファイルディレクトリ
- デフォルトで
/config/フォルダ内のapple.ymlとandroid.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/Apple と latestCheckTimestamp/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
Github Action デプロイ
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) ⚠️: 柔軟なフィルタリングができず、提供される情報も少なく、件数制限があり、時折データの不整合が発生するため非常に不安定です。公式は将来的に廃止する可能性があります。
Fastlane の — SpaceShip を使って、複雑なウェブ操作やセッション管理をラップし、App Store Connectの管理画面から評価データを取得します(ウェブブラウザのエミュレーターを使って管理画面をクロールするイメージです)。
昨年の方法に従うと、方法二のみで対応可能でしたが、効果はあまり良くありませんでした。セッションは期限切れになり、手動で定期的に更新する必要があり、IPが変わるとセッションがすぐに期限切れになるため、CI/CDサーバー上での運用はできません。
important-note-about-session-duration by Fastlane
今年、AppleがApp Store Connect APIを更新したという知らせを受けてすぐに、新しいレビュー監視ロボットの再設計に取り掛かりました。公式APIの採用に加え、以前のアーキテクチャ設計を改善し、Rubyの使い方にもより精通しました。
App Store Connect API 開発で直面した問題
- List All Customer Reviews for an App このエンドポイントはアプリのバージョン情報を返しません
とても奇妙ですが、まずこのエンドポイントを叩いて最新のレビューを絞り込み、その後に List All App Store Versions for an App と List 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 によって変換されました。
本記事は Medium にて初公開されました(こちらからオリジナル版を確認)。ZMediumToMarkdown による自動変換・同期技術を使用しています。










































{:target="_blank"}](/assets/e36e48bb9265/1*uDsJPUqtiltvCsNBFDTz-w.webp)
{:target="_blank"} by Fastlane](/assets/e36e48bb9265/1*N6B1H_PdtB4bNDrX4BIYRA.webp)