ZReviewTender 1.3.6 → 1.3.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.version +1 -1
- data/config/android.example.yml +24 -0
- data/config/apple.example.yml +24 -0
- data/lib/Models/Processor.rb +15 -0
- data/lib/Models/ReviewFetcher.rb +9 -1
- data/lib/Processors/AsanaProcessor.rb +131 -0
- data/lib/Processors/GoogleSheetProcessor.rb +1 -11
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 77c4a5c74b6076acbf3ec3ea98046ab703f1df3485c4590c9f1de62bda77fad9
|
4
|
+
data.tar.gz: 1b8bc52b07eac4add166d360b648fa5991264d501b72a39c1dc7a412da51413c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8bba8ffe64bb4342689ade1b868a4a369e7879641c927466792cfef62f1860b3508efb1d289c5fea8c0bb6741780e2ce491c063814b327e4b85c2b699851dff7
|
7
|
+
data.tar.gz: 5cea45b9203f52e95ff67169fec881981e501e68b8e7cbc2298798e483963a44684d17e0337a7536b99ed2ba6f08f99bf531b762cf0848d8326c4864ba5bdc99
|
data/.version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.3.
|
1
|
+
1.3.7
|
data/config/android.example.yml
CHANGED
@@ -46,6 +46,30 @@ processors:
|
|
46
46
|
# %APPVERSION% for review's reviewer app version
|
47
47
|
# %CREATEDDATE% for review's created date
|
48
48
|
|
49
|
+
keywordsInclude: [] # keywords you want to filter out
|
50
|
+
ratingsInclude: [] # ratings you want to filter out
|
51
|
+
territoriesInclude: [] # territories you want to filter out(language for android e.g. zh-Hant, en)
|
52
|
+
- AsanaProcessor:
|
53
|
+
class: "AsanaProcessor"
|
54
|
+
enable: false # enable
|
55
|
+
asanaTimeZoneOffset: "+08:00"
|
56
|
+
asanaToken: "" # Asana Personal Access Token, get it here -> https://app.asana.com/0/my-apps
|
57
|
+
asanaProjectID: "" # Asana Project ID, get it in project url -> https://app.asana.com/0/asanaProjectID/list
|
58
|
+
asanaSectionName: "" # Task Target Project - Section Name, optional
|
59
|
+
asanaTaskTitleTemplate: "%PLATFORM% - %RATING% ⭐️ - %TITLE%" # Asana Task Title Template
|
60
|
+
asanaTaskBodyTemplate: "Title: %TITLE%\n---\nBody:\n%BODY%\n---\n- UserName: %USERNAME%\n- App Version: %APPVERSION%\n- Date:%CREATEDDATE%" # Asana Task Body Template
|
61
|
+
# you can uses magic variable below to compose string.
|
62
|
+
# %TITLE% for review's title
|
63
|
+
# %BODY% for review's content
|
64
|
+
# %RATING% for review's rating 1~5
|
65
|
+
# %PLATFORM% for review's platform Apple or Android
|
66
|
+
# %ID% for review's ID
|
67
|
+
# %USERNAME% for review's reviewer username
|
68
|
+
# %URL% for link to review
|
69
|
+
# %TERRITORY% for review's territory (territory for Apple e.g. TWN)
|
70
|
+
# %APPVERSION% for review's reviewer app version
|
71
|
+
# %CREATEDDATE% for review's created date
|
72
|
+
|
49
73
|
keywordsInclude: [] # keywords you want to filter out
|
50
74
|
ratingsInclude: [] # ratings you want to filter out
|
51
75
|
territoriesInclude: [] # territories you want to filter out(language for android e.g. zh-Hant, en)
|
data/config/apple.example.yml
CHANGED
@@ -47,6 +47,30 @@ processors:
|
|
47
47
|
# %APPVERSION% for review's reviewer app version
|
48
48
|
# %CREATEDDATE% for review's created date
|
49
49
|
|
50
|
+
keywordsInclude: [] # keywords you want to filter out
|
51
|
+
ratingsInclude: [] # ratings you want to filter out
|
52
|
+
territoriesInclude: [] # territories you want to filter out (territory for Apple e.g. TWN)
|
53
|
+
- AsanaProcessor:
|
54
|
+
class: "AsanaProcessor"
|
55
|
+
enable: false # enable
|
56
|
+
asanaTimeZoneOffset: "+08:00"
|
57
|
+
asanaToken: "" # Asana Personal Access Token, get it here -> https://app.asana.com/0/my-apps
|
58
|
+
asanaProjectID: "" # Asana Project ID, get it in project url -> https://app.asana.com/0/asanaProjectID/list
|
59
|
+
asanaSectionName: "" # Task Target Project - Section Name, optional
|
60
|
+
asanaTaskTitleTemplate: "%PLATFORM% - %RATING% ⭐️ - %TITLE%" # Asana Task Title Template
|
61
|
+
asanaTaskBodyTemplate: "Title: %TITLE%\n---\nBody:\n%BODY%\n---\n- UserName: %USERNAME%\n- App Version: %APPVERSION%\n- Date:%CREATEDDATE%" # Asana Task Body Template
|
62
|
+
# you can uses magic variable below to compose string.
|
63
|
+
# %TITLE% for review's title
|
64
|
+
# %BODY% for review's content
|
65
|
+
# %RATING% for review's rating 1~5
|
66
|
+
# %PLATFORM% for review's platform Apple or Android
|
67
|
+
# %ID% for review's ID
|
68
|
+
# %USERNAME% for review's reviewer username
|
69
|
+
# %URL% for link to review
|
70
|
+
# %TERRITORY% for review's territory (territory for Apple e.g. TWN)
|
71
|
+
# %APPVERSION% for review's reviewer app version
|
72
|
+
# %CREATEDDATE% for review's created date
|
73
|
+
|
50
74
|
keywordsInclude: [] # keywords you want to filter out
|
51
75
|
ratingsInclude: [] # ratings you want to filter out
|
52
76
|
territoriesInclude: [] # territories you want to filter out (territory for Apple e.g. TWN)
|
data/lib/Models/Processor.rb
CHANGED
@@ -13,4 +13,19 @@ class Processor
|
|
13
13
|
def processReviews(reviews, platform)
|
14
14
|
|
15
15
|
end
|
16
|
+
|
17
|
+
def renderReview(templateText, review, timeZoneOffset)
|
18
|
+
templateText = templateText.gsub("%TITLE%", review.title || "")
|
19
|
+
templateText = templateText.gsub("%BODY%", review.body || "")
|
20
|
+
templateText = templateText.gsub("%RATING%", review.rating.nil? ? "" :review.rating.to_s)
|
21
|
+
templateText = templateText.gsub("%PLATFORM%", review.platform || "")
|
22
|
+
templateText = templateText.gsub("%ID%", review.id || "")
|
23
|
+
templateText = templateText.gsub("%USERNAME%", review.userName || "")
|
24
|
+
templateText = templateText.gsub("%URL%", review.url || "")
|
25
|
+
templateText = templateText.gsub("%TERRITORY%", review.territory || "")
|
26
|
+
templateText = templateText.gsub("%APPVERSION%", review.appVersion || "")
|
27
|
+
templateText = templateText.gsub("%CREATEDDATE%", review.createdDateTimestamp.nil? ? "" : Time.at(review.createdDateTimestamp).getlocal(timeZoneOffset).to_s)
|
28
|
+
|
29
|
+
return templateText
|
30
|
+
end
|
16
31
|
end
|
data/lib/Models/ReviewFetcher.rb
CHANGED
@@ -20,7 +20,15 @@ class ReviewFetcher
|
|
20
20
|
|
21
21
|
def processReviews(reviews, platform)
|
22
22
|
processors.each do |processor|
|
23
|
-
|
23
|
+
begin
|
24
|
+
reviews = processor.processReviews(reviews, platform)
|
25
|
+
rescue => e
|
26
|
+
errorMessage = "# Processor Error"
|
27
|
+
errorMessage += "#Error Message: #{e.message}\n"
|
28
|
+
errorMessage += "#Error Class: #{e.class}\n"
|
29
|
+
errorMessage += "#Backtrace Start#\n#{e.backtrace.join("\n")}\n#Backtrace End#\n"
|
30
|
+
logger.logError(errorMessage)
|
31
|
+
end
|
24
32
|
end
|
25
33
|
end
|
26
34
|
|
@@ -0,0 +1,131 @@
|
|
1
|
+
$lib = File.expand_path('../lib', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
require "Models/Review"
|
4
|
+
require "Models/Processor"
|
5
|
+
require "Helper"
|
6
|
+
require "pathname"
|
7
|
+
require "GoogleAPI"
|
8
|
+
|
9
|
+
class AsanaProcessor < Processor
|
10
|
+
|
11
|
+
attr_accessor :keywordsInclude, :ratingsInclude, :territoriesInclude, :logger, :timeZoneOffset, :token, :projectID, :sectionName, :taskTitleTemplate, :taskBodyTemplate, :asanaAPIURL
|
12
|
+
|
13
|
+
def initialize(config, configFilePath, baseExecutePath)
|
14
|
+
@config = config
|
15
|
+
@configFilePath = configFilePath
|
16
|
+
@baseExecutePath = baseExecutePath
|
17
|
+
@logger = ZLogger.new(baseExecutePath)
|
18
|
+
|
19
|
+
@asanaAPIURL = "https://app.asana.com/api/1.0"
|
20
|
+
@token = Helper.unwrapRequiredParameter(config, "asanaToken")
|
21
|
+
@projectID = Helper.unwrapRequiredParameter(config, "asanaProjectID")
|
22
|
+
@taskTitleTemplate = Helper.unwrapRequiredParameter(config, "asanaTaskTitleTemplate")
|
23
|
+
@taskBodyTemplate = Helper.unwrapRequiredParameter(config, "asanaTaskBodyTemplate")
|
24
|
+
@timeZoneOffset = Helper.unwrapRequiredParameter(config, "asanaTimeZoneOffset")
|
25
|
+
@sectionName = nil
|
26
|
+
if !config["asanaSectionName"].nil? && config["asanaSectionName"] != ""
|
27
|
+
@sectionName = config["asanaSectionName"].strip
|
28
|
+
end
|
29
|
+
|
30
|
+
@keywordsInclude = []
|
31
|
+
if !config["keywordsInclude"].nil?
|
32
|
+
@keywordsInclude = config["keywordsInclude"]
|
33
|
+
end
|
34
|
+
|
35
|
+
@ratingsInclude = []
|
36
|
+
if !config["ratingsInclude"].nil?
|
37
|
+
@ratingsInclude = config["ratingsInclude"]
|
38
|
+
end
|
39
|
+
|
40
|
+
@territoriesInclude = []
|
41
|
+
if !config["territoriesInclude"].nil?
|
42
|
+
@territoriesInclude = config["territoriesInclude"]
|
43
|
+
end
|
44
|
+
|
45
|
+
puts "[AsanaProcessor] Init Success."
|
46
|
+
end
|
47
|
+
|
48
|
+
def processReviews(reviews, platform)
|
49
|
+
if reviews.length < 1
|
50
|
+
return reviews
|
51
|
+
end
|
52
|
+
|
53
|
+
sectionID = findSectionIDFromSectionName(sectionName)
|
54
|
+
|
55
|
+
filterReviews = reviews
|
56
|
+
|
57
|
+
if ratingsInclude.length > 0
|
58
|
+
filterReviews = filterReviews.select{ |review| ratingsInclude.map{ |rating| rating.to_i }.include? review.rating }
|
59
|
+
end
|
60
|
+
|
61
|
+
if territoriesInclude.length > 0
|
62
|
+
filterReviews = filterReviews.select{ |review| territoriesInclude.map{ |territory| territory.upcase }.include? review.territory.upcase }
|
63
|
+
end
|
64
|
+
|
65
|
+
if keywordsInclude.length > 0
|
66
|
+
keywordsInclude.select{ |keywordsInclude| keywordsInclude != "" }.each do |keywordInclude|
|
67
|
+
filterReviews = filterReviews.select{ |review| review.body.include? keywordInclude }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
filterReviews.each do |review|
|
72
|
+
title = renderReview(taskTitleTemplate, review, timeZoneOffset)
|
73
|
+
body = renderReview(taskBodyTemplate, review, timeZoneOffset)
|
74
|
+
|
75
|
+
requestTaskData = {
|
76
|
+
"name": title,
|
77
|
+
"notes": body,
|
78
|
+
"projects": [projectID.to_s]
|
79
|
+
}
|
80
|
+
|
81
|
+
if !review.createdDateTimestamp.nil?
|
82
|
+
requestTaskData['due_at'] = Time.at(review.createdDateTimestamp).iso8601
|
83
|
+
end
|
84
|
+
|
85
|
+
taskData = asanaAPI("/tasks", "POST", requestTaskData)
|
86
|
+
taskData = taskData["data"]
|
87
|
+
|
88
|
+
if !sectionID.nil? && !taskData.nil?
|
89
|
+
asanaAPI("/sections/#{sectionID}/addTask", "POST", {"task": taskData["gid"]})
|
90
|
+
end
|
91
|
+
|
92
|
+
puts "[AsanaProcessor] Insert Review #{title} as a task to asana project."
|
93
|
+
end
|
94
|
+
|
95
|
+
return reviews
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
def findSectionIDFromSectionName(sectionName)
|
100
|
+
if !sectionName.nil?
|
101
|
+
sections = asanaAPI("/projects/#{projectID}/sections")["data"]
|
102
|
+
section = sections.find{ |section| section["name"].strip == sectionName }
|
103
|
+
if !section.nil?
|
104
|
+
return section["gid"]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
return nil
|
109
|
+
end
|
110
|
+
|
111
|
+
private
|
112
|
+
def asanaAPI(path, method = "GET", data = nil)
|
113
|
+
uri = URI(asanaAPIURL+path)
|
114
|
+
https = Net::HTTP.new(uri.host, uri.port)
|
115
|
+
https.use_ssl = true
|
116
|
+
|
117
|
+
request = Net::HTTP::Get.new(uri)
|
118
|
+
if method.upcase == "POST"
|
119
|
+
request = Net::HTTP::Post.new(uri)
|
120
|
+
if !data.nil?
|
121
|
+
request['Content-Type'] = 'application/json'
|
122
|
+
request.body = JSON.dump({"data": data})
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
request['Authorization'] = "Bearer #{token}";
|
127
|
+
|
128
|
+
response = https.request(request).read_body
|
129
|
+
result = JSON.parse(response)
|
130
|
+
end
|
131
|
+
end
|
@@ -105,17 +105,7 @@ class GoogleSheetProcessor < Processor
|
|
105
105
|
sortedFilterReviews.each do |review|
|
106
106
|
cols = []
|
107
107
|
formatValues.each do |formatValue|
|
108
|
-
formatValue = formatValue
|
109
|
-
formatValue = formatValue.gsub("%BODY%", review.body || "")
|
110
|
-
formatValue = formatValue.gsub("%RATING%", review.rating.nil? ? "" :review.rating.to_s)
|
111
|
-
formatValue = formatValue.gsub("%PLATFORM%", review.platform || "")
|
112
|
-
formatValue = formatValue.gsub("%ID%", review.id || "")
|
113
|
-
formatValue = formatValue.gsub("%USERNAME%", review.userName || "")
|
114
|
-
formatValue = formatValue.gsub("%URL%", review.url || "")
|
115
|
-
formatValue = formatValue.gsub("%TERRITORY%", review.territory || "")
|
116
|
-
formatValue = formatValue.gsub("%APPVERSION%", review.appVersion || "")
|
117
|
-
formatValue = formatValue.gsub("%CREATEDDATE%", review.createdDateTimestamp.nil? ? "" : Time.at(review.createdDateTimestamp).getlocal(timeZoneOffset).to_s)
|
118
|
-
|
108
|
+
formatValue = renderReview(formatValue, review, timeZoneOffset)
|
119
109
|
cols.append(formatValue)
|
120
110
|
end
|
121
111
|
values.append(cols)
|
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.3.
|
4
|
+
version: 1.3.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ZhgChgLi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-12-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: net-http
|
@@ -59,6 +59,7 @@ files:
|
|
59
59
|
- lib/Models/Review.rb
|
60
60
|
- lib/Models/ReviewFetcher.rb
|
61
61
|
- lib/Models/Version.rb
|
62
|
+
- lib/Processors/AsanaProcessor.rb
|
62
63
|
- lib/Processors/FilterProcessor.rb
|
63
64
|
- lib/Processors/GoogleSheetProcessor.rb
|
64
65
|
- lib/Processors/GoogleTranslateProcessor.rb
|