rss-connector 0.1.0
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 +7 -0
- data/.git-hooks/commit_msg/add_ticket_id.rb +54 -0
- data/.gitignore +9 -0
- data/.overcommit.yml +17 -0
- data/.rspec +2 -0
- data/.rubocop.yml +5 -0
- data/.travis.yml +14 -0
- data/Gemfile +4 -0
- data/README.md +27 -0
- data/Rakefile +6 -0
- data/lib/rss.rb +16 -0
- data/lib/rss/config.rb +19 -0
- data/lib/rss/connector.rb +315 -0
- data/lib/rss/rule.rb +130 -0
- data/lib/rss/version.rb +3 -0
- data/rss-connector.gemspec +35 -0
- metadata +185 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4f8d899ac890065f11c8d6697e5b1b2cf5b5ba61
|
4
|
+
data.tar.gz: 361b7655de149538e63c02b5e02749babbb34ce7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 89c51799dc31923adbd7944d5d9cda7dc9f74fb1844190e53311e7043fa5dbdbc6de83cabdf7170fd67e64dfd4cbb143bdcbf091fcd887396b64919135eb4a44
|
7
|
+
data.tar.gz: 56e11579fe69c99edf6e450f1946b4ffe8c7c718de779c7f6bc711cedd7863cdcc09d5984899625a7d0b8d168300aedd5586ed8e93194fffa18a65410a10bb90
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# Shore git prepare-commit-msg hook
|
2
|
+
#
|
3
|
+
# Autom. prepends git commit messages with ticket type and ticket id based on
|
4
|
+
# the current branch name (assuming naming convention has been followed).
|
5
|
+
#
|
6
|
+
# Naming convention for branches:
|
7
|
+
# {ticket type}/{ticket id}-{ticket title in param-case}
|
8
|
+
# Ex: feature/COR-42-the-meaning-of-life
|
9
|
+
# Ex: chore/BOK-23-refactor-everything
|
10
|
+
# Ex: bug/WAC-667-neighbor-of-the-beast
|
11
|
+
# Ex: task/COR-668-foo-bar-baz
|
12
|
+
#
|
13
|
+
# Only applies when using:
|
14
|
+
# $ git ci -m "message"
|
15
|
+
# $ git ci -F path/to/message.txt
|
16
|
+
# $ git ci
|
17
|
+
#
|
18
|
+
# Except it is a:
|
19
|
+
# - merge commit
|
20
|
+
# - squash commit
|
21
|
+
#
|
22
|
+
# Example:
|
23
|
+
# assuming current branch name is: feature/COR-1-some-ticket-title
|
24
|
+
# $ git commit -m "did some stuff"
|
25
|
+
# commit message is now: F [#COR-1] did some stuff
|
26
|
+
module Overcommit
|
27
|
+
module Hook
|
28
|
+
module CommitMsg
|
29
|
+
VALID_TICKET_TYPES = %w(feature chore bug task)
|
30
|
+
|
31
|
+
class AddTicketId < Base
|
32
|
+
def run
|
33
|
+
branch_name = `git symbolic-ref --short HEAD`
|
34
|
+
ticket_type, ticket_id = branch_name.scan(/(\w+)\/(\w+-\d+)/).flatten
|
35
|
+
may_apply_hook =
|
36
|
+
VALID_TICKET_TYPES.include?(ticket_type) &&
|
37
|
+
ticket_id &&
|
38
|
+
[nil, 'message'].include?(ARGV[1])
|
39
|
+
|
40
|
+
if may_apply_hook
|
41
|
+
prefix = "#{ticket_type[0].upcase} [##{ticket_id.upcase}] "
|
42
|
+
# Skip if commit Ticket ID is already present (this fixes a problem
|
43
|
+
# with `git commit --amend`).
|
44
|
+
unless commit_message.start_with?(prefix)
|
45
|
+
`sed -i.bak -e "1s/^/#{prefix}/" #{commit_message_file}`
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
:pass
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/.gitignore
ADDED
data/.overcommit.yml
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
CommitMsg:
|
2
|
+
ALL:
|
3
|
+
enabled: false
|
4
|
+
AddTicketId:
|
5
|
+
enabled: true
|
6
|
+
|
7
|
+
PreCommit:
|
8
|
+
RuboCop:
|
9
|
+
enabled: true
|
10
|
+
command: ['bundle', 'exec', 'rubocop']
|
11
|
+
on_warn: 'fail'
|
12
|
+
|
13
|
+
PrePush:
|
14
|
+
RSpec:
|
15
|
+
enabled: true
|
16
|
+
command: ['bundle', 'exec', 'rspec']
|
17
|
+
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# RSS::Connector
|
2
|
+
|
3
|
+
Talks to RSS.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'rss-connector', git
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install rss-connector
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
TODO: Write usage instructions here
|
24
|
+
|
25
|
+
## Contributing
|
26
|
+
|
27
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/shore-gmbh/rss-connector.
|
data/Rakefile
ADDED
data/lib/rss.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'active_support/all'
|
2
|
+
require_relative 'rss/config'
|
3
|
+
require_relative 'rss/rule'
|
4
|
+
|
5
|
+
module RSS #:nodoc:
|
6
|
+
# Authentication credentials are stored in constants, make sure
|
7
|
+
# configuration is set before requiring the connector.
|
8
|
+
def self.load!
|
9
|
+
if RSS.configuration.base_uri.empty?
|
10
|
+
puts 'Missing RSS base_uri config'
|
11
|
+
exit
|
12
|
+
end
|
13
|
+
|
14
|
+
require_relative 'rss/connector'
|
15
|
+
end
|
16
|
+
end
|
data/lib/rss/config.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module RSS #:nodoc:
|
2
|
+
class << self
|
3
|
+
attr_accessor :configuration
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.configure
|
7
|
+
self.configuration ||= Configuration.new
|
8
|
+
yield(configuration)
|
9
|
+
end
|
10
|
+
|
11
|
+
class Configuration #:nodoc:
|
12
|
+
attr_accessor :base_uri, :secret
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@base_uri = 'http://localhost:5000/'
|
16
|
+
@secret = ''
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,315 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'net/http'
|
3
|
+
|
4
|
+
module RSS
|
5
|
+
# Utility class encapsulating synchronous communication with RSS.
|
6
|
+
class Connector # rubocop:disable ClassLength
|
7
|
+
include HTTParty
|
8
|
+
|
9
|
+
base_uri RSS.configuration.base_uri
|
10
|
+
|
11
|
+
BASIC_AUTH_USERNAME = (RSS.configuration.secret || 'secret').freeze
|
12
|
+
BASIC_AUTH_PASSWORD = ''.freeze
|
13
|
+
BASIC_AUTH_CREDENTIALS = {
|
14
|
+
basic_auth: {
|
15
|
+
username: BASIC_AUTH_USERNAME,
|
16
|
+
password: BASIC_AUTH_PASSWORD
|
17
|
+
}
|
18
|
+
}.freeze
|
19
|
+
|
20
|
+
attr_reader :oid, :scope
|
21
|
+
|
22
|
+
# @param oid [String] Organziation ID
|
23
|
+
# @param scope [String]
|
24
|
+
def initialize(oid, scope)
|
25
|
+
@oid = oid
|
26
|
+
@scope = scope
|
27
|
+
end
|
28
|
+
|
29
|
+
# @param series_id [String]
|
30
|
+
# @raise [RuntimeError] RSS request failed
|
31
|
+
def get_series(series_id)
|
32
|
+
path = "#{base_path}/series/#{series_id}"
|
33
|
+
response = self.class.authenticated_get(path)
|
34
|
+
|
35
|
+
case response.code
|
36
|
+
when 200 then JSON.parse(response.body)['series']
|
37
|
+
when 404 then nil
|
38
|
+
else fail "RSS: 'GET #{path}' failed with status = #{response.code}."
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# @raise [RuntimeError] RSS request failed
|
43
|
+
def create_series(attributes = {})
|
44
|
+
path = "#{base_path}/series"
|
45
|
+
response = self.class.authenticated_post(
|
46
|
+
path, query: prepare_series_attributes(attributes)
|
47
|
+
)
|
48
|
+
|
49
|
+
case response.code
|
50
|
+
when 201 then JSON.parse(response.body)
|
51
|
+
else fail "RSS: 'POST #{path}' failed with status = #{response.code}."
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# @raise [RuntimeError] RSS request failed
|
56
|
+
def create_or_update_series(series_id, attributes = {})
|
57
|
+
path = "#{base_path}/series/#{series_id}"
|
58
|
+
response = self.class.authenticated_put(
|
59
|
+
path, query: prepare_series_attributes(attributes)
|
60
|
+
)
|
61
|
+
|
62
|
+
case response.code
|
63
|
+
when 200, 201 then JSON.parse(response.body)
|
64
|
+
else fail "RSS: 'PUT #{path}' failed with status = #{response.code}."
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# @raise [RuntimeError] RSS request failed
|
69
|
+
def update_series(series_id, attributes = {})
|
70
|
+
path = "#{base_path}/series/#{series_id}"
|
71
|
+
response = self.class.authenticated_patch(
|
72
|
+
path, query: prepare_series_attributes(attributes)
|
73
|
+
)
|
74
|
+
|
75
|
+
case response.code
|
76
|
+
when 200 then JSON.parse(response.body)
|
77
|
+
when 404 then nil
|
78
|
+
else fail "RSS: 'PATCH #{path}' failed with status = #{response.code}."
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# @raise [RuntimeError] RSS request failed
|
83
|
+
def delete_series(series_id)
|
84
|
+
path = "#{base_path}/series/#{series_id}"
|
85
|
+
response = self.class.authenticated_delete(path)
|
86
|
+
|
87
|
+
case response.code
|
88
|
+
when 200 then JSON.parse(response.body)
|
89
|
+
when 404 then nil
|
90
|
+
else fail "RSS: 'DELETE #{path}' failed with status = #{response.code}."
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# @raise [RuntimeError] RSS request failed
|
95
|
+
def get_rule(rule_id)
|
96
|
+
path = "#{base_path}/rules/#{rule_id}"
|
97
|
+
response = self.class.authenticated_get(path)
|
98
|
+
|
99
|
+
case response.code
|
100
|
+
when 200 then JSON.parse(response.body)
|
101
|
+
when 404 then nil
|
102
|
+
else fail "RSS: 'GET #{path}' failed with status = #{response.code}."
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# @raise [RuntimeError] RSS request failed
|
107
|
+
def get_rules(filters = {})
|
108
|
+
path = "#{base_path}/rules"
|
109
|
+
response = self.class.authenticated_get(
|
110
|
+
path, query: sanitize_filters(filters)
|
111
|
+
)
|
112
|
+
|
113
|
+
case response.code
|
114
|
+
when 200 then JSON.parse(response.body)['rules']
|
115
|
+
when 404 then nil
|
116
|
+
else fail "RSS: 'GET #{path}' failed with status = #{response.code}."
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# @raise [RuntimeError] RSS request failed
|
121
|
+
def create_rule(attributes = {})
|
122
|
+
path = "#{base_path}/rules"
|
123
|
+
response = self.class.authenticated_post(
|
124
|
+
path, query: prepare_rule_attributes(attributes)
|
125
|
+
)
|
126
|
+
|
127
|
+
case response.code
|
128
|
+
when 201 then JSON.parse(response.body)
|
129
|
+
else fail "RSS: 'POST #{path}' failed with status = #{response.code}."
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# @raise [RuntimeError] RSS request failed
|
134
|
+
def create_or_update_rule(rule_id, attributes = {})
|
135
|
+
path = "#{base_path}/rules/#{rule_id}"
|
136
|
+
response = self.class.authenticated_put(
|
137
|
+
path, query: prepare_rule_attributes(attributes)
|
138
|
+
)
|
139
|
+
|
140
|
+
case response.code
|
141
|
+
when 200, 201 then JSON.parse(response.body)
|
142
|
+
else fail "RSS: 'PUT #{path}' failed with status = #{response.code}."
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# @raise [RuntimeError] RSS request failed
|
147
|
+
def update_rule(rule_id, attributes = {})
|
148
|
+
path = "#{base_path}/rules/#{rule_id}"
|
149
|
+
response = self.class.authenticated_patch(
|
150
|
+
path, query: prepare_rule_attributes(attributes)
|
151
|
+
)
|
152
|
+
|
153
|
+
case response.code
|
154
|
+
when 200 then JSON.parse(response.body)
|
155
|
+
when 404 then nil
|
156
|
+
else fail "RSS: 'PATCH #{path}' failed with status = #{response.code}."
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# @raise [RuntimeError] RSS request failed
|
161
|
+
def delete_rule(rule_id)
|
162
|
+
path = "#{base_path}/rules/#{rule_id}"
|
163
|
+
response = self.class.authenticated_delete(path)
|
164
|
+
|
165
|
+
case response.code
|
166
|
+
when 200 then JSON.parse(response.body)
|
167
|
+
when 404 then nil
|
168
|
+
else fail "RSS: 'DELETE #{path}' failed with status = #{response.code}."
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
# @raise [RuntimeError] RSS request failed
|
173
|
+
def get_occurrences(filters = {}) # rubocop:disable MethodLength
|
174
|
+
path = "#{base_path}/occurrences"
|
175
|
+
response = self.class.authenticated_get(
|
176
|
+
path, query: sanitize_filters(filters)
|
177
|
+
)
|
178
|
+
|
179
|
+
case response.code
|
180
|
+
when 200
|
181
|
+
(JSON.parse(response.body)['occurrences'] || []).map do |h|
|
182
|
+
build_occurrence_payload(h)
|
183
|
+
end
|
184
|
+
else fail "RSS: 'GET #{path}' failed with status = #{response.code}."
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
# @param occurrence_id [String]
|
189
|
+
# @raise [RuntimeError] RSS request failed
|
190
|
+
def get_occurrence(occurrence_id)
|
191
|
+
path = "#{base_path}/occurrences/#{occurrence_id}"
|
192
|
+
response = self.class.authenticated_get(path)
|
193
|
+
|
194
|
+
case response.code
|
195
|
+
when 200
|
196
|
+
occurrence_hash = JSON.parse(response.body)['occurrence']
|
197
|
+
build_occurrence_payload(occurrence_hash)
|
198
|
+
when 404 then nil
|
199
|
+
else fail "RSS: 'GET #{path}' failed with status = #{response.code}."
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
# @param occurrence_id [String]
|
204
|
+
# @raise [RuntimeError] RSS request failed
|
205
|
+
# rubocop:disable MethodLength
|
206
|
+
def update_occurrence(occurrence_id, attributes = {})
|
207
|
+
path = "#{base_path}/occurrences/#{occurrence_id}"
|
208
|
+
response = self.class.authenticated_patch(
|
209
|
+
path, query: prepare_occurrence_attributes(attributes)
|
210
|
+
)
|
211
|
+
|
212
|
+
case response.code
|
213
|
+
when 200
|
214
|
+
occurrence_hash = JSON.parse(response.body)['occurrence']
|
215
|
+
build_occurrence_payload(occurrence_hash)
|
216
|
+
when 404 then nil
|
217
|
+
else fail "RSS: 'PATCH #{path}' failed with status = #{response.code}."
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
# @param occurrence_id [String]
|
222
|
+
# @raise [RuntimeError] RSS request failed
|
223
|
+
def delete_occurrence(occurrence_id)
|
224
|
+
path = "#{base_path}/occurrences/#{occurrence_id}"
|
225
|
+
response = self.class.authenticated_delete(path)
|
226
|
+
|
227
|
+
case response.code
|
228
|
+
when 200 then JSON.parse(response.body)
|
229
|
+
when 404 then nil
|
230
|
+
else fail "RSS: 'DELETE #{path}' failed with status = #{response.code}."
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
private
|
235
|
+
|
236
|
+
# Define variants of all HTTParty request methods with authentication
|
237
|
+
# support.
|
238
|
+
self::Request::SupportedHTTPMethods
|
239
|
+
.map { |x| x.name.demodulize.downcase }.each do |method|
|
240
|
+
define_singleton_method("authenticated_#{method}") do |path, options = {}|
|
241
|
+
send(method, path, options.merge(BASIC_AUTH_CREDENTIALS))
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
def base_path
|
246
|
+
"/v1/#{oid}/#{scope}"
|
247
|
+
end
|
248
|
+
|
249
|
+
# @param series_attributes [Hash]
|
250
|
+
# @return [Hash]
|
251
|
+
def prepare_series_attributes(series_attributes = {})
|
252
|
+
(series_attributes || {}).tap do |attributes|
|
253
|
+
attributes[:rules] ||= []
|
254
|
+
|
255
|
+
attributes[:rules].map! do |rule_attributes|
|
256
|
+
prepare_rule_attributes(rule_attributes, series_attributes)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
# @param rule_attributes [Hash]
|
262
|
+
# @return [Hash]
|
263
|
+
def prepare_rule_attributes(rule_attributes = {}, series_attributes = nil)
|
264
|
+
{}.tap do |attrs|
|
265
|
+
rule = Rule.new(rule_attributes)
|
266
|
+
|
267
|
+
attrs[:id] = rule.id # core is always creating the rule id now
|
268
|
+
attrs[:recurrence] = rule.recurrence
|
269
|
+
|
270
|
+
if series_attributes
|
271
|
+
attrs[:duration] = series_attributes[:duration] || rule.duration
|
272
|
+
attrs[:time_zone] = series_attributes[:time_zone]
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
# @param occurrence_attributes [Hash]
|
278
|
+
# @return [Hash]
|
279
|
+
def prepare_occurrence_attributes(occurrence_attributes = {})
|
280
|
+
{}.tap do |attrs|
|
281
|
+
if occurrence_attributes[:starts_at].present?
|
282
|
+
attrs[:starts_at] = iso8601_param(occurrence_attributes[:starts_at])
|
283
|
+
end
|
284
|
+
|
285
|
+
if occurrence_attributes[:ends_at].present?
|
286
|
+
attrs[:ends_at] = iso8601_param(occurrence_attributes[:ends_at])
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
def sanitize_filters(filters = {})
|
292
|
+
filters.tap do |f|
|
293
|
+
if f[:interval_starts_at].present?
|
294
|
+
f[:interval_starts_at] = iso8601_param(f[:interval_starts_at])
|
295
|
+
end
|
296
|
+
|
297
|
+
if f[:interval_ends_at].present?
|
298
|
+
f[:interval_ends_at] = iso8601_param(f[:interval_ends_at])
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
def iso8601_param(p)
|
304
|
+
p.respond_to?(:iso8601) ? p.iso8601 : p.to_s
|
305
|
+
end
|
306
|
+
|
307
|
+
# @param occurrence_hash [Hash]
|
308
|
+
def build_occurrence_payload(occurrence_hash)
|
309
|
+
occurrence_hash.tap do |p|
|
310
|
+
p['starts_at'] = Time.zone.parse(p['starts_at']) if p['starts_at']
|
311
|
+
p['ends_at'] = Time.zone.parse(p['ends_at']) if p['ends_at']
|
312
|
+
end if occurrence_hash
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
data/lib/rss/rule.rb
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
module RSS
|
2
|
+
# Class to build and compare RSS Rules.
|
3
|
+
class Rule
|
4
|
+
attr_reader :recurrence
|
5
|
+
|
6
|
+
def initialize(attributes = {})
|
7
|
+
@recurrence = {}
|
8
|
+
|
9
|
+
self.id = SecureRandom.uuid
|
10
|
+
self.attributes = attributes
|
11
|
+
end
|
12
|
+
|
13
|
+
# getters
|
14
|
+
attr_reader :id, :duration
|
15
|
+
|
16
|
+
def starts_at
|
17
|
+
@recurrence[:starts_at]
|
18
|
+
end
|
19
|
+
|
20
|
+
def ends_at
|
21
|
+
@recurrence[:ends_at]
|
22
|
+
end
|
23
|
+
|
24
|
+
def count
|
25
|
+
@recurrence[:count]
|
26
|
+
end
|
27
|
+
|
28
|
+
def frequency
|
29
|
+
@recurrence[:frequency] || 'daily'
|
30
|
+
end
|
31
|
+
|
32
|
+
def interval
|
33
|
+
@recurrence[:interval] || 1
|
34
|
+
end
|
35
|
+
|
36
|
+
def attributes
|
37
|
+
{}.tap do |a|
|
38
|
+
a[:id] = id
|
39
|
+
a[:recurrence] = @recurrence.stringify_keys
|
40
|
+
a[:duration] = @duration if @duration
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def convert_date(t)
|
45
|
+
t = t.is_a?(String) ? Time.zone.parse(t) : t
|
46
|
+
return if t.nil?
|
47
|
+
t.utc.iso8601
|
48
|
+
end
|
49
|
+
|
50
|
+
# setters
|
51
|
+
def id=(id)
|
52
|
+
@id = id.to_s
|
53
|
+
end
|
54
|
+
|
55
|
+
def count=(c)
|
56
|
+
@recurrence[:count] = c
|
57
|
+
end
|
58
|
+
|
59
|
+
def frequency=(f)
|
60
|
+
@recurrence[:frequency] = f.to_s
|
61
|
+
end
|
62
|
+
|
63
|
+
def interval=(i)
|
64
|
+
@recurrence[:interval] = i.to_i
|
65
|
+
end
|
66
|
+
|
67
|
+
def starts_at=(t)
|
68
|
+
@recurrence[:starts_at] = convert_date(t)
|
69
|
+
end
|
70
|
+
|
71
|
+
def ends_at=(t)
|
72
|
+
@recurrence[:ends_at] = convert_date(t)
|
73
|
+
end
|
74
|
+
|
75
|
+
def duration=(d)
|
76
|
+
@duration = d.to_i
|
77
|
+
end
|
78
|
+
|
79
|
+
def recurrence=(r)
|
80
|
+
if r.is_a?(Hash)
|
81
|
+
self.attributes = r
|
82
|
+
else
|
83
|
+
fail "recurrence= can only receive a Hash. Received #{r.class}"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def attributes=(attributes = {})
|
88
|
+
attributes.each_pair do |attr, value|
|
89
|
+
if respond_to?(assign = "#{attr}=")
|
90
|
+
send(assign, value)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# @return JSON string
|
96
|
+
def as_json(_options = nil)
|
97
|
+
# when on rails 4 use deep stringify keys
|
98
|
+
attributes.stringify_keys
|
99
|
+
end
|
100
|
+
|
101
|
+
# Tell wether +self+ is an one-off +Rule+ or not. +self+ is considered to be
|
102
|
+
# one-off if and only if it evaluates to a single occurrence.
|
103
|
+
#
|
104
|
+
# @return [true] if +self+ is a one-off +Rule+. This is 100% reliable.
|
105
|
+
# @return [false] if +self+ looks like it is not an one-off +Rule+. This is
|
106
|
+
# not 100% reliable. Unfortunately, there is no obvious way to tell for
|
107
|
+
# sure if +self+ evaluates to multple occurrences or not.
|
108
|
+
def one_off?
|
109
|
+
# TODO@cs: There are various problematic edge-cases in the system, because
|
110
|
+
# +#one_off?+ is not 100% reliable. We have to fix this ASAP.
|
111
|
+
count == 1 || starts_at == ends_at
|
112
|
+
end
|
113
|
+
|
114
|
+
# @return [Array of Rule Objects]
|
115
|
+
def self.load(value)
|
116
|
+
parsed = JSON.load(value)
|
117
|
+
parsed.is_a?(Array) ? parsed.map { |p| new(p) } : []
|
118
|
+
end
|
119
|
+
|
120
|
+
def ==(other)
|
121
|
+
as_json == other.as_json
|
122
|
+
end
|
123
|
+
|
124
|
+
# @return JSON string of rules
|
125
|
+
def self.dump(rules)
|
126
|
+
value = rules.is_a?(Array) ? rules.map(&:as_json) : []
|
127
|
+
JSON.dump(value)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
data/lib/rss/version.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rss/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'rss-connector'
|
8
|
+
spec.version = RSS::VERSION
|
9
|
+
spec.authors = ['Dylan Johnston']
|
10
|
+
spec.email = ['dylan.johnston@shore.com']
|
11
|
+
|
12
|
+
spec.summary = 'Connector for RSS'
|
13
|
+
spec.description = 'Easy access to RSS and its data.'
|
14
|
+
spec.homepage = 'http://shore.com'
|
15
|
+
spec.license = 'Proprietary'
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
18
|
+
f.match(%r{^(test|spec|features)/})
|
19
|
+
end
|
20
|
+
|
21
|
+
spec.bindir = 'exe'
|
22
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
|
+
spec.require_paths = ['lib']
|
24
|
+
|
25
|
+
spec.add_dependency 'httparty', '~> 0.10.2'
|
26
|
+
spec.add_dependency 'activesupport', '> 3.0'
|
27
|
+
|
28
|
+
spec.add_development_dependency 'bundler', '~> 1.10'
|
29
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
30
|
+
spec.add_development_dependency 'rspec'
|
31
|
+
spec.add_development_dependency 'simplecov', '>= 0.10'
|
32
|
+
spec.add_development_dependency 'rubocop', '>= 0.35.1'
|
33
|
+
spec.add_development_dependency 'overcommit', '>= 0.29.1'
|
34
|
+
spec.add_development_dependency 'pry-byebug'
|
35
|
+
end
|
metadata
ADDED
@@ -0,0 +1,185 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rss-connector
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dylan Johnston
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-01-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: httparty
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.10.2
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.10.2
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.10'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.10'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: simplecov
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.10'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.10'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rubocop
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.35.1
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.35.1
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: overcommit
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.29.1
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 0.29.1
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: pry-byebug
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
description: Easy access to RSS and its data.
|
140
|
+
email:
|
141
|
+
- dylan.johnston@shore.com
|
142
|
+
executables: []
|
143
|
+
extensions: []
|
144
|
+
extra_rdoc_files: []
|
145
|
+
files:
|
146
|
+
- ".git-hooks/commit_msg/add_ticket_id.rb"
|
147
|
+
- ".gitignore"
|
148
|
+
- ".overcommit.yml"
|
149
|
+
- ".rspec"
|
150
|
+
- ".rubocop.yml"
|
151
|
+
- ".travis.yml"
|
152
|
+
- Gemfile
|
153
|
+
- README.md
|
154
|
+
- Rakefile
|
155
|
+
- lib/rss.rb
|
156
|
+
- lib/rss/config.rb
|
157
|
+
- lib/rss/connector.rb
|
158
|
+
- lib/rss/rule.rb
|
159
|
+
- lib/rss/version.rb
|
160
|
+
- rss-connector.gemspec
|
161
|
+
homepage: http://shore.com
|
162
|
+
licenses:
|
163
|
+
- Proprietary
|
164
|
+
metadata: {}
|
165
|
+
post_install_message:
|
166
|
+
rdoc_options: []
|
167
|
+
require_paths:
|
168
|
+
- lib
|
169
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
175
|
+
requirements:
|
176
|
+
- - ">="
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
version: '0'
|
179
|
+
requirements: []
|
180
|
+
rubyforge_project:
|
181
|
+
rubygems_version: 2.4.5
|
182
|
+
signing_key:
|
183
|
+
specification_version: 4
|
184
|
+
summary: Connector for RSS
|
185
|
+
test_files: []
|