ZReviewTender 1.3.6 → 1.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|