ZReviewTender 1.3.7 → 1.3.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 77c4a5c74b6076acbf3ec3ea98046ab703f1df3485c4590c9f1de62bda77fad9
4
- data.tar.gz: 1b8bc52b07eac4add166d360b648fa5991264d501b72a39c1dc7a412da51413c
3
+ metadata.gz: '016962d0d7c4215f6c60a77d20fb83290d5cd5b65e6883de27d7fb5116cfccdb'
4
+ data.tar.gz: 84810201df2669c00b955a8d7da1382112dd4041e963b8cbd3730dc05e988f8c
5
5
  SHA512:
6
- metadata.gz: 8bba8ffe64bb4342689ade1b868a4a369e7879641c927466792cfef62f1860b3508efb1d289c5fea8c0bb6741780e2ce491c063814b327e4b85c2b699851dff7
7
- data.tar.gz: 5cea45b9203f52e95ff67169fec881981e501e68b8e7cbc2298798e483963a44684d17e0337a7536b99ed2ba6f08f99bf531b762cf0848d8326c4864ba5bdc99
6
+ metadata.gz: a2cbe8d510432fb5a353faa7357ea5b9b194d58d8ef4f3e8dfec69792ab3f8b4512c1b43efb26d525be4ccb62c42ad61ebe3f6c9c37ebecd43da4fc6b71d4d4d
7
+ data.tar.gz: 520a4d667e91b28dba82c1b5f7829fd6566c7b0976ca7c90f7620b9d857e6efa463dd854d2eb3f5b9629e106557349b7f2dab031dfd8a20e457912c87dbd9d03
data/.version CHANGED
@@ -1 +1 @@
1
- 1.3.7
1
+ 1.3.8
@@ -112,7 +112,7 @@ class AndroidFetcher < ReviewFetcher
112
112
  if !config.accountID.nil? && !config.appID.nil?
113
113
  url = "https://play.google.com/console/developers/#{config.accountID}/app/#{config.appID}/user-feedback/review-details?reviewId=#{customerReviewID}"
114
114
  end
115
- reviews.append(Review.new(customerReviewPlatform, customerReviewID, customerReviewReviewerNickname, customerReviewRating, customerReviewTitle, customerReviewBody, customerReviewCreatedDateTimestamp, url, customerReviewVersionString, customerReviewTerritory))
115
+ reviews.append(Review.new(customerReviewPlatform, customerReviewID, customerReviewReviewerNickname, customerReviewRating, customerReviewTitle, customerReviewBody, customerReviewCreatedDateTimestamp, url, customerReviewVersionString, customerReviewTerritory, {}))
116
116
 
117
117
  # init first time, need first review to set as latestCheckTimestamp
118
118
  if latestCheckTimestamp == 0
data/lib/AppleFetcher.rb CHANGED
@@ -80,7 +80,7 @@ class AppleFetcher < ReviewFetcher
80
80
  break
81
81
  else
82
82
  url = "https://appstoreconnect.apple.com/WebObjects/iTunesConnect.woa/ra/ng/app/#{config.appID}/ios/ratingsResponses"
83
- reviews.append(Review.new(nil, customerReviewID, customerReviewReviewerNickname, customerReviewRating, customerReviewTitle, customerReviewBody, customerReviewCreatedDateTimestamp, url, nil, customerReviewTerritory))
83
+ reviews.append(Review.new(nil, customerReviewID, customerReviewReviewerNickname, customerReviewRating, customerReviewTitle, customerReviewBody, customerReviewCreatedDateTimestamp, url, nil, customerReviewTerritory, {}))
84
84
 
85
85
  # init first time, need first review to set as latestCheckTimestamp
86
86
  if latestCheckTimestamp == 0
data/lib/Models/Review.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  $lib = File.expand_path('../', File.dirname(__FILE__))
2
2
 
3
3
  class Review
4
- attr_accessor :platform, :id, :userName, :rating, :title, :body, :createdDateTimestamp, :url, :appVersion, :territory
5
- def initialize(platform, id, userName, rating, title, body, createdDateTimestamp, url, appVersion, territory)
4
+ attr_accessor :platform, :id, :userName, :rating, :title, :body, :createdDateTimestamp, :url, :appVersion, :territory, :tempData
5
+ def initialize(platform, id, userName, rating, title, body, createdDateTimestamp, url, appVersion, territory, tempData)
6
6
  @platform = platform # 來源平台 android or apple
7
7
  @id = id # review id
8
8
  @userName = userName # reviewer
@@ -13,5 +13,6 @@ class Review
13
13
  @url = url # 前往 review 的連結 (apple 不提供後台指定到某個 review 的連結)
14
14
  @appVersion = appVersion # app 版本號
15
15
  @territory = territory # apple: 地區(TWN/JPN...), android: 語系(zh-tw/en...)
16
+ @tempData = tempData # 程式內部傳遞使用
16
17
  end
17
18
  end
@@ -84,6 +84,8 @@ class AsanaProcessor < Processor
84
84
 
85
85
  taskData = asanaAPI("/tasks", "POST", requestTaskData)
86
86
  taskData = taskData["data"]
87
+
88
+ review.tempData["asanaTaskGID"] = taskData["gid"]
87
89
 
88
90
  if !sectionID.nil? && !taskData.nil?
89
91
  asanaAPI("/sections/#{sectionID}/addTask", "POST", {"task": taskData["gid"]})
@@ -0,0 +1,159 @@
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 SlackAndAsanaConnector < Processor
10
+
11
+ attr_accessor :logger, :slackBotToken, :asanaToken, :projectID, :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
+ @asanaToken = Helper.unwrapRequiredParameter(config, "asanaToken")
21
+ @slackBotToken = Helper.unwrapRequiredParameter(config, "slackBotToken")
22
+
23
+ puts "[SlackAndAsanaConnector] Init Success."
24
+ end
25
+
26
+ def processReviews(reviews, platform)
27
+ if reviews.length < 1
28
+ return reviews
29
+ end
30
+
31
+ pendingReviews = reviews.dup
32
+
33
+ loop do
34
+ review = pendingReviews.shift
35
+
36
+ result = retrieveSlackMessage(review)
37
+ if !result["ok"]
38
+ if result["error"] == "ratelimited"
39
+ puts "[SlackAndAsanaConnector] Reached Rate Limited, sleep 1 sec..."
40
+ sleep(1)
41
+ pendingReviews.insert(0, review)
42
+ end
43
+ else
44
+ sendAsanaCommentMessage(review, "ref: #{result["permalink"]}")
45
+ end
46
+
47
+ puts "[SlackAndAsanaConnector] Connect Slack Message to Asana Task, rest: #{pendingReviews.length}"
48
+ break if pendingReviews.length < 1
49
+ end
50
+
51
+ pendingReviews = reviews.dup
52
+
53
+ loop do
54
+ review = pendingReviews.shift
55
+ asanaTaskURL = retrieveAsanaTaskURL(review)
56
+ if !asanaTaskURL.nil?
57
+ result = sendSlackCommnetMessage(review, "<#{asanaTaskURL}| Go To *Asana Task*>")
58
+ if !result["ok"]
59
+ if result["error"] == "ratelimited"
60
+ puts "[SlackAndAsanaConnector] Reached Rate Limited, sleep 1 sec..."
61
+ sleep(1)
62
+ pendingReviews.insert(0, review)
63
+ end
64
+ end
65
+ end
66
+
67
+ puts "[SlackAndAsanaConnector] Connect Asana Task to Slack Message, rest: #{pendingReviews.length}"
68
+ break if pendingReviews.length < 1
69
+ end
70
+
71
+ return reviews
72
+ end
73
+
74
+ private
75
+ def retrieveSlackMessage(review)
76
+ uri = URI("https://slack.com/api/chat.getPermalink?channel=#{review.tempData["slackChannelID"]}&message_ts=#{review.tempData["slackTS"]}")
77
+ headers = {'Content-Type': 'application/json; charset=utf-8', 'Authorization': "Bearer #{slackBotToken}"}
78
+
79
+ http = Net::HTTP.new(uri.host, uri.port)
80
+ http.use_ssl = true
81
+ req = Net::HTTP::Get.new(uri.request_uri, headers)
82
+ res = http.request(req)
83
+
84
+ result = JSON.parse(res.body)
85
+ return result
86
+ end
87
+
88
+ private
89
+ def sendSlackCommnetMessage(review, message)
90
+ payload = Payload.new()
91
+ payload.text = message
92
+ payload.channel = review.tempData["slackChannelID"]
93
+ payload.thread_ts = review.tempData["slackTS"]
94
+ payload.unfurl_links = true
95
+ payload.unfurl_media = true
96
+ uri = URI("https://slack.com/api/chat.postMessage")
97
+ headers = {'Content-Type': 'application/json; charset=utf-8', 'Authorization': "Bearer #{slackBotToken}"}
98
+
99
+ http = Net::HTTP.new(uri.host, uri.port)
100
+ http.use_ssl = true
101
+ req = Net::HTTP::Post.new(uri.request_uri, headers)
102
+ req.body = payload.to_json
103
+ res = http.request(req)
104
+
105
+ result = JSON.parse(res.body)
106
+ return result
107
+ end
108
+
109
+
110
+ private
111
+ def retrieveAsanaTaskURL(review)
112
+ if review.tempData["asanaTaskGID"].nil? || review.tempData["asanaTaskGID"] == ""
113
+ return nil
114
+ end
115
+
116
+ return "https://app.asana.com/0/0/#{review.tempData["asanaTaskGID"]}/f"
117
+ end
118
+
119
+ private
120
+ def sendAsanaCommentMessage(review, message)
121
+ if review.tempData["asanaTaskGID"].nil? || review.tempData["asanaTaskGID"] == ""
122
+ return nil
123
+ end
124
+
125
+ path = "/tasks/#{review.tempData["asanaTaskGID"]}/stories"
126
+ uri = URI(asanaAPIURL+path)
127
+ https = Net::HTTP.new(uri.host, uri.port)
128
+ https.use_ssl = true
129
+
130
+ request = Net::HTTP::Post.new(uri)
131
+ request['Content-Type'] = 'application/json'
132
+ request.body = JSON.dump({"data": {"text": message}})
133
+
134
+ request['Authorization'] = "Bearer #{asanaToken}"
135
+
136
+ response = https.request(request).read_body
137
+
138
+ return result = JSON.parse(response)
139
+ end
140
+
141
+ private
142
+ class Payload
143
+ attr_accessor :channel, :thread_ts, :text, :unfurl_links, :unfurl_media
144
+
145
+ def as_json(options={})
146
+ {
147
+ channel: @channel,
148
+ thread_ts: @thread_ts,
149
+ text: @text,
150
+ unfurl_links: @unfurl_links,
151
+ unfurl_media: @unfurl_media
152
+ }
153
+ end
154
+
155
+ def to_json(*options)
156
+ as_json(*options).to_json(*options)
157
+ end
158
+ end
159
+ end
@@ -42,7 +42,7 @@ class SlackProcessor < Processor
42
42
  return reviews
43
43
  end
44
44
 
45
- pendingPayloads = []
45
+ pendingRequests = []
46
46
 
47
47
  # Slack Message Limit: posting one message per second per channel
48
48
  reviews.each_slice(attachmentGroupByNumber) do |reviewGroup|
@@ -71,12 +71,16 @@ class SlackProcessor < Processor
71
71
  payload.attachments.append(attachment)
72
72
  end
73
73
 
74
- pendingPayloads.append(payload)
74
+ pendingRequests.append({"payload" => payload, "reviewGroup" => reviewGroup})
75
75
  end
76
+
77
+ resultReviews = []
76
78
 
77
79
  loop do
78
- payload = pendingPayloads.shift
79
-
80
+ pendingRequest = pendingRequests.shift
81
+ payload = pendingRequest["payload"]
82
+ reviewGroup = pendingRequest["reviewGroup"]
83
+
80
84
  result = request(payload)
81
85
  if !result[:ok]
82
86
  logger.logError(payload)
@@ -84,12 +88,17 @@ class SlackProcessor < Processor
84
88
  if result[:message] == "ratelimited"
85
89
  puts "[SlackProcessor] Reached Rate Limited, sleep 1 sec..."
86
90
  sleep(1)
87
- pendingPayloads.insert(0, payload)
91
+ pendingRequests.insert(0, pendingRequest)
92
+ end
93
+ elsif !result[:ts].nil?
94
+ reviewGroup.each do |review|
95
+ review.tempData["slackTS"] = result[:ts]
96
+ review.tempData["slackChannelID"] = targetChannel
88
97
  end
89
98
  end
90
99
 
91
- puts "[SlackProcessor] Send new Review messages, rest: #{pendingPayloads.length}"
92
- break if pendingPayloads.length < 1
100
+ puts "[SlackProcessor] Send new Review messages, rest: #{pendingRequests.length}"
101
+ break if pendingRequests.length < 1
93
102
  end
94
103
 
95
104
  return reviews
@@ -140,10 +149,10 @@ class SlackProcessor < Processor
140
149
  res = http.request(req)
141
150
 
142
151
  if isInCommingWebHook
143
- return {"ok":res.body == "ok", "message":nil}
152
+ return {"ok":res.body == "ok", "message":nil, "ts": result['ts']}
144
153
  else
145
154
  result = JSON.parse(res.body)
146
- return {"ok":result["ok"] == true, "message":result['error']}
155
+ return {"ok":result["ok"] == true, "message":result['error'], "ts": result['ts']}
147
156
  end
148
157
 
149
158
  end
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.7
4
+ version: 1.3.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - ZhgChgLi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-28 00:00:00.000000000 Z
11
+ date: 2023-08-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: net-http
@@ -64,6 +64,7 @@ files:
64
64
  - lib/Processors/GoogleSheetProcessor.rb
65
65
  - lib/Processors/GoogleTranslateProcessor.rb
66
66
  - lib/Processors/ProcessorTemplate.rb
67
+ - lib/Processors/SlackAndAsanaConnector.rb
67
68
  - lib/Processors/SlackProcessor.rb
68
69
  - lib/ZLogger.rb
69
70
  homepage: https://github.com/ZhgChgLi/ZReviewTender