ZReviewTender 1.1.1 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.version +1 -0
- data/bin/ZReviewTender +76 -6
- data/config/android.example.yml +26 -0
- data/config/apple.example.yml +26 -0
- data/lib/AndroidFetcher.rb +10 -1
- data/lib/AppleFetcher.rb +26 -1
- data/lib/Models/Version.rb +39 -0
- data/lib/Processors/FilterProcessor.rb +8 -0
- data/lib/Processors/GoogleTranslateProcessor.rb +4 -0
- data/lib/Processors/SlackProcessor.rb +5 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3c3ed526dfeec33a979c0c3c5a31d269a68cabe3599ba14c2ad9df35a1667dff
|
4
|
+
data.tar.gz: cc919703c929aee31d1c0a7d59ca528734f66a776e5d530f14da27b28c97b73b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3be31356db49a927bc7e716649e3da90d7868497ed3e5257d86b7f3480fb6591fc3e5eae1a40219988aadd45f137dd58b50bf384b47985d9f8c881c80d6b0f0a
|
7
|
+
data.tar.gz: 1de0cf6339a46f271287e747bf4449905fa4eb1bbe1682294fe9d0f4f5ea8aad95711cd96c51274720a3455152fa5567db43a4011a121e9f85cbbce9ac4eb822
|
data/.version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.2.0
|
data/bin/ZReviewTender
CHANGED
@@ -7,17 +7,19 @@ $LOAD_PATH.unshift($lib)
|
|
7
7
|
require "Models/AppleConfig"
|
8
8
|
require "Models/AndroidConfig"
|
9
9
|
require "Models/Processor"
|
10
|
+
require "Models/Version"
|
10
11
|
require "Helper"
|
11
12
|
require "ZLogger"
|
12
13
|
require "AppleFetcher"
|
13
14
|
require "AndroidFetcher"
|
14
15
|
require "optparse"
|
15
16
|
require "yaml"
|
17
|
+
require "fileutils"
|
16
18
|
|
17
19
|
class Main
|
18
20
|
def initialize
|
19
21
|
|
20
|
-
ARGV << '-
|
22
|
+
ARGV << '-h' if ARGV.empty?
|
21
23
|
|
22
24
|
OptionParser.new do |opts|
|
23
25
|
opts.banner = "Usage: ZReviewTender [options]"
|
@@ -27,30 +29,41 @@ class Main
|
|
27
29
|
defaultAppleConfigFileName = "apple.yml"
|
28
30
|
defaultAndroidConfigFileName = "android.yml"
|
29
31
|
|
30
|
-
opts.on('-a', '--apple[=CONFIGYMLFILEPATH]', 'execute apple platform
|
32
|
+
opts.on('-a', '--apple[=CONFIGYMLFILEPATH]', 'execute apple platform, default config yml file path: /config/apple.yml, use --apple=CONFIG_YML_FILE_PATH specify config yml file path') do |configYMLFilePath|
|
31
33
|
if configYMLFilePath.nil?
|
32
34
|
configYMLFilePath = "#{basePath}/#{defaultConfigDirName}/#{defaultAppleConfigFileName}"
|
33
35
|
end
|
34
36
|
configFileCheck(configYMLFilePath, "--apple=CONFIG_YML_FILE_PATH")
|
35
37
|
|
38
|
+
puts "[ZReviewTender] run -a/-apple config yml file path: #{configYMLFilePath}"
|
39
|
+
|
36
40
|
fetcher = parseConfigYMLFile(configYMLFilePath)
|
37
41
|
fetcher.execute()
|
42
|
+
|
43
|
+
checkLatestVersionOfZReviewTender()
|
38
44
|
end
|
39
45
|
|
40
|
-
opts.on('-g', '--googleAndroid[=CONFIGYMLFILEPATH]', 'execute android platform
|
46
|
+
opts.on('-g', '--googleAndroid[=CONFIGYMLFILEPATH]', 'execute android platform, default config yml file path: /config/android.yml, use --googleAndroid=CONFIG_YML_FILE_PATH specify config yml file path') do |configYMLFilePath|
|
41
47
|
if configYMLFilePath.nil?
|
42
48
|
configYMLFilePath = "#{basePath}/#{defaultConfigDirName}/#{defaultAndroidConfigFileName}"
|
43
49
|
end
|
44
50
|
configFileCheck(configYMLFilePath, "--googleAndroid=CONFIG_YML_FILE_PATH")
|
45
51
|
|
52
|
+
puts "[ZReviewTender] run -g/-googleAndroid config yml file path: #{configYMLFilePath}"
|
53
|
+
|
46
54
|
fetcher = parseConfigYMLFile(configYMLFilePath)
|
47
55
|
fetcher.execute()
|
56
|
+
|
57
|
+
checkLatestVersionOfZReviewTender()
|
48
58
|
end
|
49
59
|
|
50
|
-
opts.on('-r', '--run=[=CONFIGFOLDERNAME]', 'execute both android and apple, specify
|
60
|
+
opts.on('-r', '--run=[=CONFIGFOLDERNAME]', 'execute both android and apple, specify a /config folder path') do |configFolderName|
|
51
61
|
if configFolderName.nil?
|
52
62
|
configFolderName = defaultConfigDirName
|
53
63
|
end
|
64
|
+
|
65
|
+
puts "[ZReviewTender] run -r/--run config folder path: #{configFolderName}"
|
66
|
+
|
54
67
|
androidConfigFilePath = "#{basePath}/#{configFolderName}/#{defaultAndroidConfigFileName}"
|
55
68
|
configFileCheck(androidConfigFilePath, "--googleAndroid=CONFIG_YML_FILE_PATH")
|
56
69
|
|
@@ -64,10 +77,61 @@ class Main
|
|
64
77
|
|
65
78
|
fetcher = parseConfigYMLFile(appleConfigFilePath)
|
66
79
|
fetcher.execute()
|
67
|
-
|
80
|
+
|
81
|
+
checkLatestVersionOfZReviewTender()
|
82
|
+
end
|
83
|
+
|
84
|
+
opts.on('-i', '--init', 'init config yml file from template.') do
|
85
|
+
configTemplateFolder = "#{File.expand_path("..", __dir__)}/config"
|
86
|
+
appleSourceExampleYML = "#{configTemplateFolder}/apple.example.yml"
|
87
|
+
androidSourceExampleYML = "#{configTemplateFolder}/android.example.yml"
|
88
|
+
appleDestExampleYML = "#{configTemplateFolder}/apple.yml"
|
89
|
+
androidDestExampleYML = "#{configTemplateFolder}/android.yml"
|
90
|
+
|
91
|
+
if File.exists?(appleSourceExampleYML)
|
92
|
+
if File.exists?(appleDestExampleYML)
|
93
|
+
puts "Failed! Config YML File Exists: #{appleDestExampleYML}"
|
94
|
+
else
|
95
|
+
FileUtils.cp(appleSourceExampleYML, appleDestExampleYML)
|
96
|
+
puts "Init Apple Config YML File at:#{appleDestExampleYML} Success!"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
#
|
100
|
+
if File.exists?(androidSourceExampleYML)
|
101
|
+
if File.exists?(androidDestExampleYML)
|
102
|
+
puts "Failed! Config YML File Exists: #{androidDestExampleYML}"
|
103
|
+
else
|
104
|
+
FileUtils.cp(androidSourceExampleYML, androidDestExampleYML)
|
105
|
+
puts "Init Android Config YML File at:#{androidDestExampleYML} Success!"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
checkLatestVersionOfZReviewTender()
|
110
|
+
end
|
111
|
+
|
112
|
+
opts.on('-n', '--new', 'update to latest version of ZReviewTender by RubyGem') do
|
113
|
+
version = Version.new
|
114
|
+
|
115
|
+
if version.getRemoteVersion() > version.getLocalVersion()
|
116
|
+
system('gem update ZReviewTender')
|
117
|
+
else
|
118
|
+
puts "You're using the latest version of ZReviewTender!"
|
119
|
+
end
|
120
|
+
end
|
68
121
|
end.parse!
|
69
122
|
end
|
70
123
|
|
124
|
+
private
|
125
|
+
def checkLatestVersionOfZReviewTender()
|
126
|
+
version = Version.new
|
127
|
+
if version.getRemoteVersion() > version.getLocalVersion()
|
128
|
+
puts "##########################################################"
|
129
|
+
puts "##### New Version Available!!! #####"
|
130
|
+
puts "##### Please type `ZReviewTender -n` to update!! #####"
|
131
|
+
puts "##########################################################"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
71
135
|
private
|
72
136
|
def configFileCheck(path, command)
|
73
137
|
if !File.exists? path
|
@@ -120,8 +184,14 @@ class Main
|
|
120
184
|
end
|
121
185
|
end
|
122
186
|
|
123
|
-
begin
|
187
|
+
begin
|
188
|
+
puts "#https://github.com/ZhgChgLi/ZReviewTender"
|
189
|
+
puts "You have read and agree with the Disclaimer."
|
124
190
|
Main.new()
|
191
|
+
puts "Execute Successfully!!!"
|
192
|
+
puts "#https://github.com/ZhgChgLi/ZReviewTender"
|
193
|
+
puts "#Thanks for using this tool."
|
194
|
+
puts "#If this is helpful, please help to star the repo or recommend it to your friends."
|
125
195
|
rescue => e
|
126
196
|
logger = ZLogger.new(ENV['PWD'] || ::Dir.pwd)
|
127
197
|
title = "#Error: #{e.class} #{e.message}"
|
@@ -0,0 +1,26 @@
|
|
1
|
+
platform: 'android'
|
2
|
+
packageName: '' # Android App Package Name
|
3
|
+
keyFilePath: '' # Google Android Publisher API Credential .json File Path
|
4
|
+
playConsoleDeveloperAccountID: '' # Google Console Developer Account ID
|
5
|
+
playConsoleAppID: '' # Google Console App ID
|
6
|
+
processors:
|
7
|
+
- FilterProcessor:
|
8
|
+
class: "FilterProcessor"
|
9
|
+
enable: true # enable
|
10
|
+
keywordsInclude: [] # keywords you want to filter out
|
11
|
+
ratingsInclude: [] # ratings you want to filter out
|
12
|
+
territoriesInclude: [] # territories you want to filter out(language for android e.g. zh-Hant, en)
|
13
|
+
- GoogleTranslateProcessor: # Google Translate Processor, will translate review text to your language, you can remove whole block if you don't needed it.
|
14
|
+
class: "GoogleTranslateProcessor"
|
15
|
+
enable: false # enable
|
16
|
+
googleTranslateAPIKeyFilePath: '' # Google Translate API Credential .json File Path
|
17
|
+
googleTranslateTargetLang: 'zh-TW' # Translate to what Language
|
18
|
+
googleTranslateTerritoriesExclude: ["zh-Hant","zh-Hans"] # Review origin Territory (language) that you don't want to translate. (language for android e.g. zh-Hant, en)
|
19
|
+
- SlackProcessor: # Slack Processor, resend App Review to Slack.
|
20
|
+
class: "SlackProcessor"
|
21
|
+
enable: true # enable
|
22
|
+
slackTimeZoneOffset: "+08:00" # Review Created Date TimeZone
|
23
|
+
slackAttachmentGroupByNumber: "1" # 1~100, how many review message in 1 slack message.
|
24
|
+
slackBotToken: "" # Slack Bot Token, send slack message throught Slack Bot.
|
25
|
+
slackBotTargetChannel: "" # Slack Bot Token, send slack message throught Slack Bot. (recommended, first priority)
|
26
|
+
slackInCommingWebHookURL: "" # Slack In-Comming WebHook URL, Send slack message throught In-Comming WebHook, not recommended, deprecated.
|
@@ -0,0 +1,26 @@
|
|
1
|
+
platform: 'apple'
|
2
|
+
appStoreConnectP8PrivateKeyFilePath: '' # APPLE STORE CONNECT API PRIVATE .p8 KEY File Path
|
3
|
+
appStoreConnectP8PrivateKeyID: '' # APPLE STORE CONNECT API PRIVATE KEY ID
|
4
|
+
appStoreConnectIssueID: '' # APPLE STORE CONNECT ISSUE ID
|
5
|
+
appID: '' # APP ID
|
6
|
+
processors:
|
7
|
+
- FilterProcessor:
|
8
|
+
class: "FilterProcessor"
|
9
|
+
enable: true # enable
|
10
|
+
keywordsInclude: [] # keywords you want to filter out
|
11
|
+
ratingsInclude: [] # ratings you want to filter out
|
12
|
+
territoriesInclude: [] # territories you want to filter out
|
13
|
+
- GoogleTranslateProcessor: # Google Translate Processor, will translate review text to your language, you can remove whole block if you don't needed it.
|
14
|
+
class: "GoogleTranslateProcessor"
|
15
|
+
enable: false # enable
|
16
|
+
googleTranslateAPIKeyFilePath: '' # Google Translate API Credential .json File Path
|
17
|
+
googleTranslateTargetLang: 'zh-TW' # Translate to what Language
|
18
|
+
googleTranslateTerritoriesExclude: ["TWN","CHN"] # Review origin Territory that you don't want to translate.
|
19
|
+
- SlackProcessor: # Slack Processor, resend App Review to Slack.
|
20
|
+
class: "SlackProcessor"
|
21
|
+
enable: true # enable
|
22
|
+
slackTimeZoneOffset: "+08:00" # Review Created Date TimeZone
|
23
|
+
slackAttachmentGroupByNumber: "1" # 1~100, how many review message in 1 slack message.
|
24
|
+
slackBotToken: "" # Slack Bot Token, send slack message throught Slack Bot.
|
25
|
+
slackBotTargetChannel: "" # Slack Bot Token, send slack message throught Slack Bot. (recommended, first priority)
|
26
|
+
slackInCommingWebHookURL: "" # Slack In-Comming WebHook URL, Send slack message throught In-Comming WebHook, not recommended, deprecated.
|
data/lib/AndroidFetcher.rb
CHANGED
@@ -17,16 +17,21 @@ class AndroidFetcher < ReviewFetcher
|
|
17
17
|
|
18
18
|
@client = Google::Apis::AndroidpublisherV3::AndroidPublisherService.new
|
19
19
|
@client.authorization = Google::Auth::ServiceAccountCredentials.make_creds(json_key_io: config.keyContent, scope: 'https://www.googleapis.com/auth/androidpublisher')
|
20
|
+
|
21
|
+
puts "[AndroidFetcher] Init Success."
|
20
22
|
end
|
21
23
|
|
22
24
|
def execute()
|
23
25
|
|
24
26
|
latestCheckTimestamp = getPlatformLatestCheckTimestamp()
|
25
27
|
|
28
|
+
puts "[AndroidFetcher] Start execute(), latestCheckTimestamp: #{latestCheckTimestamp}"
|
29
|
+
|
26
30
|
reviews = []
|
27
31
|
|
28
32
|
# Google API Bug, couldn't specify limit/offse/pagination, google only return a few recent reviews.
|
29
33
|
customerReviews = client.list_reviews(config.packageName).reviews
|
34
|
+
puts "[AndroidFetcher] Fetch reviews in #{config.packageName}, count: #{customerReviews.length}"
|
30
35
|
customerReviews.each do |customerReview|
|
31
36
|
|
32
37
|
customerReviewID = customerReview.review_id
|
@@ -53,9 +58,13 @@ class AndroidFetcher < ReviewFetcher
|
|
53
58
|
end
|
54
59
|
|
55
60
|
reviews = reviews.reject{ |review| latestCheckTimestamp >= review.createdDateTimestamp }.sort! { |a, b| a.createdDateTimestamp <=> b.createdDateTimestamp }
|
56
|
-
|
61
|
+
|
62
|
+
puts "[AndroidFetcher] latest reviews count: #{reviews.length}"
|
63
|
+
|
57
64
|
if reviews.length > 0
|
58
65
|
|
66
|
+
puts "[AndroidFetcher] latest review: #{reviews.last.body}, #{reviews.last.createdDateTimestamp}"
|
67
|
+
|
59
68
|
setPlatformLatestCheckTimestamp(reviews.last.createdDateTimestamp)
|
60
69
|
|
61
70
|
# init first time, send welcome message
|
data/lib/AppleFetcher.rb
CHANGED
@@ -18,16 +18,22 @@ class AppleFetcher < ReviewFetcher
|
|
18
18
|
@logger = ZLogger.new(config.baseExecutePath)
|
19
19
|
@platform = 'Apple'
|
20
20
|
@token = generateJWT()
|
21
|
+
|
22
|
+
puts "[AppleFetcher] Init Success."
|
21
23
|
end
|
22
24
|
|
23
25
|
def execute()
|
24
26
|
|
25
27
|
latestCheckTimestamp = getPlatformLatestCheckTimestamp()
|
26
28
|
|
29
|
+
puts "[AppleFetcher] Start execute(), latestCheckTimestamp: #{latestCheckTimestamp}"
|
30
|
+
|
27
31
|
reviews = fetchReviews(latestCheckTimestamp)
|
28
32
|
|
29
33
|
if reviews.length > 0
|
30
34
|
reviews.sort! { |a, b| a.createdDateTimestamp <=> b.createdDateTimestamp }
|
35
|
+
|
36
|
+
puts "[AppleFetcher] latest review: #{reviews.last.body}, #{reviews.last.createdDateTimestamp}"
|
31
37
|
setPlatformLatestCheckTimestamp(reviews.last.createdDateTimestamp)
|
32
38
|
|
33
39
|
# init first time, send welcome message
|
@@ -46,10 +52,14 @@ class AppleFetcher < ReviewFetcher
|
|
46
52
|
customerReviewsLink = "https://api.appstoreconnect.apple.com/v1/apps/#{config.appID}/customerReviews?sort=-createdDate"
|
47
53
|
reviews = []
|
48
54
|
|
55
|
+
puts "[AppleFetcher] Fetch reviews in #{config.appID}"
|
56
|
+
|
49
57
|
loop do
|
50
58
|
customerReviews = request(customerReviewsLink)
|
51
59
|
customerReviewsLink = customerReviews&.dig("links", "next")
|
52
60
|
|
61
|
+
puts "[AppleFetcher] Fetch reviews, page url: #{customerReviewsLink}"
|
62
|
+
puts "[AppleFetcher] Fetch reviews, page's reviews count: #{customerReviews&.dig("data").length}"
|
53
63
|
customerReviews&.dig("data").each do |customerReview|
|
54
64
|
|
55
65
|
customerReviewID = customerReview&.dig("id")
|
@@ -83,11 +93,18 @@ class AppleFetcher < ReviewFetcher
|
|
83
93
|
break if customerReviewsLink.nil?
|
84
94
|
end
|
85
95
|
|
96
|
+
puts "[AppleFetcher] Fetch reviews in #{config.appID}, total reviews count: #{reviews.length}"
|
97
|
+
|
86
98
|
return reviews
|
87
99
|
end
|
88
100
|
|
101
|
+
# because customerReviews, won't give us app version information
|
102
|
+
# so, we need to query it from appStoreVersions api and combine together
|
89
103
|
private
|
90
104
|
def fullfillAppInfo(reviews)
|
105
|
+
|
106
|
+
puts "[AppleFetcher] Full fill app version information."
|
107
|
+
|
91
108
|
customerReviewWhichAppVersionIsNil = reviews.select{ |review| review.appVersion.nil? }.map.with_index { |review, index| {"id":review.id, "index": index} }
|
92
109
|
|
93
110
|
appStoreVersionsLink = "https://api.appstoreconnect.apple.com/v1/apps/#{config.appID}/appStoreVersions"
|
@@ -96,6 +113,8 @@ class AppleFetcher < ReviewFetcher
|
|
96
113
|
appStoreVersions = request(appStoreVersionsLink)
|
97
114
|
appStoreVersionsLink = appStoreVersions&.dig("links", "next")
|
98
115
|
|
116
|
+
puts "[AppleFetcher] List app store version, page url: #{appStoreVersionsLink}"
|
117
|
+
puts "[AppleFetcher] List app store version, versions count: #{appStoreVersions&.dig("data").length}"
|
99
118
|
appStoreVersions&.dig("data").each do |appStoreVersion|
|
100
119
|
applePlatform = appStoreVersion&.dig("attributes","platform")
|
101
120
|
versionString = appStoreVersion&.dig("attributes","versionString")
|
@@ -108,6 +127,8 @@ class AppleFetcher < ReviewFetcher
|
|
108
127
|
customerReviews = request(customerReviewsLink)
|
109
128
|
customerReviewsLink = customerReviews&.dig("links", "next")
|
110
129
|
|
130
|
+
puts "[AppleFetcher] Fetch version reviews, page url: #{customerReviewsLink}"
|
131
|
+
puts "[AppleFetcher] Fetch version reviews, reviews count: #{customerReviews&.dig("data").length}"
|
111
132
|
customerReviews&.dig("data").each do |customerReview|
|
112
133
|
customerReviewID = customerReview&.dig("id")
|
113
134
|
if customerReviewID.nil?
|
@@ -121,6 +142,8 @@ class AppleFetcher < ReviewFetcher
|
|
121
142
|
|
122
143
|
customerReviewWhichAppVersionIsNil.delete_at(findIndex)
|
123
144
|
|
145
|
+
puts "[AppleFetcher] Count of reviews need full fill app version: #{customerReviewWhichAppVersionIsNil.length}"
|
146
|
+
|
124
147
|
if customerReviewWhichAppVersionIsNil.length < 1
|
125
148
|
customerReviewsLink = nil
|
126
149
|
break
|
@@ -172,7 +195,9 @@ class AppleFetcher < ReviewFetcher
|
|
172
195
|
raise "Could not connect to api.appstoreconnect.apple.com, error message: #{response}"
|
173
196
|
else
|
174
197
|
@token = generateJWT()
|
175
|
-
|
198
|
+
message = "JWT Expired, refresh a new one. (#{retryCount + 1})"
|
199
|
+
logger.logWarn(message)
|
200
|
+
puts "[AppleFetcher] #{message}"
|
176
201
|
return request(url, retryCount + 1)
|
177
202
|
end
|
178
203
|
else
|
@@ -0,0 +1,39 @@
|
|
1
|
+
$lib = File.expand_path('../lib', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
require "net/http"
|
4
|
+
|
5
|
+
class Version
|
6
|
+
def getLocalVersion()
|
7
|
+
versionFilePath = "#{File.expand_path("../..", __dir__)}/.version"
|
8
|
+
|
9
|
+
result = nil
|
10
|
+
if File.file?(versionFilePath)
|
11
|
+
result = File.read(versionFilePath).strip
|
12
|
+
else
|
13
|
+
result = Gem.loaded_specs["ZReviewTender"].version.version
|
14
|
+
end
|
15
|
+
|
16
|
+
if !result.nil?
|
17
|
+
Gem::Version.new(result)
|
18
|
+
else
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def getRemoteVersion()
|
24
|
+
apiPath = 'https://rubygems.org/api/v1/gems/ZReviewTender.json'
|
25
|
+
|
26
|
+
uri = URI(apiPath)
|
27
|
+
https = Net::HTTP.new(uri.host, uri.port)
|
28
|
+
https.use_ssl = true
|
29
|
+
request = Net::HTTP::Get.new(uri)
|
30
|
+
response = https.request(request).read_body
|
31
|
+
result = JSON.parse(response)
|
32
|
+
|
33
|
+
if !result['version'].nil?
|
34
|
+
Gem::Version.new(result['version'])
|
35
|
+
else
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -27,6 +27,8 @@ class FilterProcessor < Processor
|
|
27
27
|
if !config["territoriesInclude"].nil?
|
28
28
|
@territoriesInclude = config["territoriesInclude"]
|
29
29
|
end
|
30
|
+
|
31
|
+
puts "[FilterProcessor] Init Success."
|
30
32
|
end
|
31
33
|
|
32
34
|
def processReviews(reviews, platform)
|
@@ -35,17 +37,23 @@ class FilterProcessor < Processor
|
|
35
37
|
end
|
36
38
|
|
37
39
|
if ratingsInclude.length > 0
|
40
|
+
orgReviewsCount = reviews.length
|
38
41
|
reviews = reviews.select{ |review| ratingsInclude.map{ |rating| rating.to_i }.include? review.rating }
|
42
|
+
puts "[FilterProcessor] filter out ratings from #{orgReviewsCount} to #{reviews.length}"
|
39
43
|
end
|
40
44
|
|
41
45
|
if territoriesInclude.length > 0
|
46
|
+
orgReviewsCount = reviews.length
|
42
47
|
reviews = reviews.select{ |review| territoriesInclude.map{ |territory| territory.upcase }.include? review.territory.upcase }
|
48
|
+
puts "[FilterProcessor] filter out ratings from #{orgReviewsCount} to #{reviews.length}"
|
43
49
|
end
|
44
50
|
|
45
51
|
if keywordsInclude.length > 0
|
52
|
+
orgReviewsCount = reviews.length
|
46
53
|
keywordsInclude.select{ |keywordsInclude| keywordsInclude != "" }.each do |keywordInclude|
|
47
54
|
reviews = reviews.select{ |review| review.body.include? keywordInclude }
|
48
55
|
end
|
56
|
+
puts "[FilterProcessor] filter out ratings from #{orgReviewsCount} to #{reviews.length}"
|
49
57
|
end
|
50
58
|
|
51
59
|
return reviews
|
@@ -30,6 +30,8 @@ class GoogleTranslateProcessor < Processor
|
|
30
30
|
if !config['googleTranslateTerritoriesExclude'].nil? && config['googleTranslateTerritoriesExclude'].length > 0
|
31
31
|
@territoriesExclude = config['googleTranslateTerritoriesExclude']
|
32
32
|
end
|
33
|
+
|
34
|
+
puts "[GoogleTranslateProcessor] Init Success."
|
33
35
|
end
|
34
36
|
|
35
37
|
def processReviews(reviews, platform)
|
@@ -42,6 +44,8 @@ class GoogleTranslateProcessor < Processor
|
|
42
44
|
next
|
43
45
|
end
|
44
46
|
|
47
|
+
puts "[GoogleTranslateProcessor] translate #{reviews[index].body} from #{reviews[index].territory} to #{targetLang}"
|
48
|
+
|
45
49
|
if !reviews[index].title.nil?
|
46
50
|
reviews[index].title = "#{client.translate reviews[index].title, to: targetLang} (#{reviews[index].title})"
|
47
51
|
end
|
@@ -33,6 +33,8 @@ class SlackProcessor < Processor
|
|
33
33
|
elsif !botToken.nil? && botToken != "" && (targetChannel.nil? || targetChannel == "")
|
34
34
|
raise "must specify slackBotTargetChannel in SlackProcessor."
|
35
35
|
end
|
36
|
+
|
37
|
+
puts "[SlackProcessor] Init Success."
|
36
38
|
end
|
37
39
|
|
38
40
|
def processReviews(reviews, platform)
|
@@ -74,7 +76,7 @@ class SlackProcessor < Processor
|
|
74
76
|
|
75
77
|
loop do
|
76
78
|
payload = pendingPayloads.shift
|
77
|
-
|
79
|
+
|
78
80
|
result = request(payload)
|
79
81
|
if !result[:ok]
|
80
82
|
logger.logError(payload)
|
@@ -85,6 +87,7 @@ class SlackProcessor < Processor
|
|
85
87
|
end
|
86
88
|
end
|
87
89
|
|
90
|
+
puts "[SlackProcessor] Send new Review messages, rest: #{pendingPayloads.length}"
|
88
91
|
break if pendingPayloads.length < 1
|
89
92
|
end
|
90
93
|
|
@@ -109,6 +112,7 @@ class SlackProcessor < Processor
|
|
109
112
|
|
110
113
|
payload.attachments.append(attachment)
|
111
114
|
|
115
|
+
puts "[SlackProcessor] sendWelcomMessage(#{title})"
|
112
116
|
request(payload)
|
113
117
|
end
|
114
118
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ZReviewTender
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ZhgChgLi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-08-
|
11
|
+
date: 2022-08-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: net-http
|
@@ -73,7 +73,10 @@ executables:
|
|
73
73
|
extensions: []
|
74
74
|
extra_rdoc_files: []
|
75
75
|
files:
|
76
|
+
- ".version"
|
76
77
|
- bin/ZReviewTender
|
78
|
+
- config/android.example.yml
|
79
|
+
- config/apple.example.yml
|
77
80
|
- lib/AndroidFetcher.rb
|
78
81
|
- lib/AppleFetcher.rb
|
79
82
|
- lib/Helper.rb
|
@@ -82,6 +85,7 @@ files:
|
|
82
85
|
- lib/Models/Processor.rb
|
83
86
|
- lib/Models/Review.rb
|
84
87
|
- lib/Models/ReviewFetcher.rb
|
88
|
+
- lib/Models/Version.rb
|
85
89
|
- lib/Processors/FilterProcessor.rb
|
86
90
|
- lib/Processors/GoogleTranslateProcessor.rb
|
87
91
|
- lib/Processors/ProcessorTemplate.rb
|