lexervariables 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +38 -0
- data/Gemfile +4 -0
- data/README.md +25 -0
- data/Rakefile +9 -0
- data/lexervariables.gemspec +30 -0
- data/lib/lexervariables.rb +85 -0
- data/lib/lexervariables/api.rb +90 -0
- data/lib/lexervariables/attribute_generator.rb +15 -0
- data/lib/lexervariables/attribute_geo_region.rb +7 -0
- data/lib/lexervariables/attribute_page.rb +7 -0
- data/lib/lexervariables/attribute_user.rb +7 -0
- data/lib/lexervariables/dashboard_object.rb +34 -0
- data/lib/lexervariables/error.rb +7 -0
- data/lib/lexervariables/monitored_account.rb +85 -0
- data/lib/lexervariables/monitored_geo_region.rb +7 -0
- data/lib/lexervariables/monitored_object.rb +21 -0
- data/lib/lexervariables/monitored_page.rb +7 -0
- data/lib/lexervariables/monitored_term.rb +7 -0
- data/lib/lexervariables/monitored_url.rb +7 -0
- data/lib/lexervariables/monitored_user.rb +7 -0
- data/lib/lexervariables/oauth.rb +29 -0
- data/lib/lexervariables/version.rb +3 -0
- data/test/attribute_generator_test.rb +45 -0
- data/test/docker-launch-tests.sh +4 -0
- data/test/docker-run-tests.sh +9 -0
- data/test/factories/monitored_accounts.rb +21 -0
- data/test/factories/monitored_terms.rb +9 -0
- data/test/factories/oauths.rb +9 -0
- data/test/lexer_variables_test.rb +19 -0
- data/test/monitored_account_test.rb +106 -0
- data/test/monitored_object_test.rb +62 -0
- data/test/oauth_test.rb +22 -0
- data/test/test_helper.rb +38 -0
- metadata +204 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 866f1bc83bd911c1870c91da77d7acd725f2961f
|
4
|
+
data.tar.gz: 55286b7635617c451c6c535488330e57a1cacdc6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d66dc4d6676cc0f4c66596970599ab3c6d63954078e1c5c44862288fbf07a0ef7a2c6ad1763a7b43cc4a73ff1d37194a798210279bd0d2316d0b9ef5e6665f51
|
7
|
+
data.tar.gz: c5c21c4c76e322a513b5ff3fa6b145cb939841e9bba7166ede0b114f6619ba109275713fe4ee6a9ee7eac8c29c4adc3df72441e96c7cb20b0568163f17d77d23
|
data/.gitignore
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
*.swp
|
4
|
+
/.config
|
5
|
+
/coverage/
|
6
|
+
/InstalledFiles
|
7
|
+
/pkg/
|
8
|
+
/test/reports/
|
9
|
+
/test/tmp/
|
10
|
+
/test/version_tmp/
|
11
|
+
/tmp/
|
12
|
+
|
13
|
+
## Specific to RubyMotion:
|
14
|
+
.dat*
|
15
|
+
.repl_history
|
16
|
+
build/
|
17
|
+
|
18
|
+
## Documentation cache and generated files:
|
19
|
+
/.yardoc/
|
20
|
+
/_yardoc/
|
21
|
+
/doc/
|
22
|
+
/rdoc/
|
23
|
+
|
24
|
+
## Environment normalisation:
|
25
|
+
/.bundle/
|
26
|
+
/lib/bundler/man/
|
27
|
+
|
28
|
+
# for a library or gem, you might want to ignore these files since the code is
|
29
|
+
# intended to run in multiple environments; otherwise, check them in:
|
30
|
+
Gemfile.lock
|
31
|
+
.ruby-version
|
32
|
+
.ruby-gemset
|
33
|
+
|
34
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
35
|
+
.rvmrc
|
36
|
+
|
37
|
+
.swp
|
38
|
+
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# lexer-variables.gem
|
2
|
+
|
3
|
+
Gem for loading variables (terms, geographies, authors, pages, oauths) to monitor
|
4
|
+
|
5
|
+
Communicates with the [lexer-dashboard-app](http://github.com/lexerdev/lexer-dashboard-app) to lease:
|
6
|
+
* Monitored Terms
|
7
|
+
* Monitored Geo Regions
|
8
|
+
* Monitored Authors
|
9
|
+
* Monitored Pages
|
10
|
+
* OAuths (with associations to above)
|
11
|
+
|
12
|
+
This gem and the functionality held in the dashboard-app aims to retire the current implementation whereby variables and oauths are loaded from the Lexer-API thorugh the Lexer-API.gem.
|
13
|
+
|
14
|
+
# Tests
|
15
|
+
|
16
|
+
Run tests:
|
17
|
+
bundle exec rake test
|
18
|
+
|
19
|
+
# IRB
|
20
|
+
|
21
|
+
Need to have a tinker?
|
22
|
+
|
23
|
+
irb -rubygems -I lib -r $PWD/lib/lexervariables.rb
|
24
|
+
|
25
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "lexervariables/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "lexervariables"
|
7
|
+
s.version = LexerVariables::VERSION
|
8
|
+
s.authors = ["Aaron Wallis"]
|
9
|
+
s.email = ["aaron.wallis@lexer.com.au"]
|
10
|
+
s.homepage = "http://lexer.com.au"
|
11
|
+
s.summary = "Gem for loading variables (terms, geographies, authors, pages, oauths) to monitor"
|
12
|
+
s.description = "Gem for loading variables (terms, geographies, authors, pages, oauths) to monitor"
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
|
19
|
+
s.add_dependency 'faraday'
|
20
|
+
s.add_dependency 'multi_json'
|
21
|
+
s.add_dependency 'oj'
|
22
|
+
|
23
|
+
s.add_development_dependency 'minitest'
|
24
|
+
s.add_development_dependency 'minitest-reporters'
|
25
|
+
s.add_development_dependency 'factory_girl'
|
26
|
+
s.add_development_dependency 'faker'
|
27
|
+
s.add_development_dependency 'rake'
|
28
|
+
s.add_development_dependency 'webmock'
|
29
|
+
end
|
30
|
+
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'oj'
|
2
|
+
require 'multi_json'
|
3
|
+
require 'lexervariables/error'
|
4
|
+
require 'lexervariables/version'
|
5
|
+
|
6
|
+
module LexerVariables
|
7
|
+
module_function
|
8
|
+
|
9
|
+
DEFAULT_ENDPOINT = 'https://lexer-dashboard/api/system/'
|
10
|
+
USER_AGENT = 'Lexer Worker'
|
11
|
+
SECRET_TOKEN = 'MLXTblicbwEVqyWXXrtz2DccoEuoqx9h5VFKZfBsP48QCOQ2hEcWvPDYoWwY4sQj'
|
12
|
+
|
13
|
+
def validate_provider(provider)
|
14
|
+
fail LexerVariables::UnknownProvider, "Unknown provider: #{provider}" unless [:facebook, :twitter, :instagram, :spinn3r, :yammer].include?(provider)
|
15
|
+
true
|
16
|
+
end
|
17
|
+
|
18
|
+
class Configuration
|
19
|
+
class << self
|
20
|
+
attr_accessor :endpoint
|
21
|
+
attr_accessor :api_key
|
22
|
+
end
|
23
|
+
|
24
|
+
@endpoint = DEFAULT_ENDPOINT
|
25
|
+
@api_key = SECRET_TOKEN
|
26
|
+
|
27
|
+
def self.default_options
|
28
|
+
{'api_token' => self.api_key}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class LexerModel
|
33
|
+
attr_accessor :attrs
|
34
|
+
alias :to_hash :attrs
|
35
|
+
|
36
|
+
# Define methods that retrieve the value from an initialized instance variable Hash, using the attribute as a key
|
37
|
+
#
|
38
|
+
# @overload self.lazy_attr_reader(attr)
|
39
|
+
# @param attr [Symbol]
|
40
|
+
# @overload self.lazy_attr_reader(attrs)
|
41
|
+
# @param attrs [Array<Symbol>]
|
42
|
+
def self.lazy_attr_reader(*attrs)
|
43
|
+
attrs.each do |attribute|
|
44
|
+
class_eval do
|
45
|
+
define_method attribute do
|
46
|
+
@attrs[attribute.to_s]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Initializes a new Base object
|
53
|
+
#
|
54
|
+
# @param attrs [Hash]
|
55
|
+
# @return [LexerModel]
|
56
|
+
def initialize(attrs={})
|
57
|
+
@attrs = attrs.dup
|
58
|
+
end
|
59
|
+
|
60
|
+
# Initializes a new Base object
|
61
|
+
#
|
62
|
+
# @param method [String, Symbol] Message to send to the object
|
63
|
+
def [](method)
|
64
|
+
self.__send__(method.to_sym)
|
65
|
+
rescue NoMethodError
|
66
|
+
nil
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
require 'lexervariables/api'
|
73
|
+
require 'lexervariables/dashboard_object'
|
74
|
+
require 'lexervariables/attribute_generator'
|
75
|
+
require 'lexervariables/attribute_geo_region'
|
76
|
+
require 'lexervariables/attribute_page'
|
77
|
+
require 'lexervariables/attribute_user'
|
78
|
+
require 'lexervariables/monitored_account'
|
79
|
+
require 'lexervariables/monitored_object'
|
80
|
+
require 'lexervariables/monitored_geo_region'
|
81
|
+
require 'lexervariables/monitored_page'
|
82
|
+
require 'lexervariables/monitored_term'
|
83
|
+
require 'lexervariables/monitored_user'
|
84
|
+
require 'lexervariables/monitored_url'
|
85
|
+
require 'lexervariables/oauth'
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'oj'
|
3
|
+
require 'multi_json'
|
4
|
+
|
5
|
+
module LexerVariables
|
6
|
+
|
7
|
+
class ParseJson < ::Faraday::Response::Middleware
|
8
|
+
def parse(body)
|
9
|
+
case body
|
10
|
+
when '', 'null'
|
11
|
+
nil
|
12
|
+
when 'true'
|
13
|
+
true
|
14
|
+
when 'false'
|
15
|
+
false
|
16
|
+
else
|
17
|
+
MultiJson.decode(body)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def on_complete(env)
|
22
|
+
if env[:status] >= 300
|
23
|
+
fail ::LexerVariables::RequestError, "API Request error #{env[:status]} : #{env[:url]} : #{MultiJson.encode(env[:request_headers])} #{env[:body]}"
|
24
|
+
elsif env[:status] == 204
|
25
|
+
env[:body] = nil
|
26
|
+
else
|
27
|
+
env[:body] = parse(env[:body])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.api_connection(options={})
|
33
|
+
default_options = {
|
34
|
+
:headers => {
|
35
|
+
:accept => 'application/json'
|
36
|
+
},
|
37
|
+
:ssl => {
|
38
|
+
:verify => false
|
39
|
+
}
|
40
|
+
}
|
41
|
+
@__api_connection ||= Faraday.new(default_options.merge(options)) do |builder|
|
42
|
+
builder.use(Faraday::Request::UrlEncoded) # convert request params as "www-form-urlencoded"
|
43
|
+
builder.use(LexerVariables::ParseJson) # Decode the response as JSON
|
44
|
+
builder.use(Faraday::Adapter::NetHttp) # make http requests with Net::HTTP
|
45
|
+
|
46
|
+
# Enable if you want super noisy (but informative) logs
|
47
|
+
# builder.use Faraday::Response::Logger # log the request to STDOUT
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.reset_connection
|
52
|
+
@__api_connection = nil
|
53
|
+
end
|
54
|
+
|
55
|
+
module Request
|
56
|
+
module_function
|
57
|
+
|
58
|
+
# Perform an HTTP GET request
|
59
|
+
def get(path, params={}, options={})
|
60
|
+
request(:get, path, params, options)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Perform an HTTP POST request
|
64
|
+
def self.post(path, params={}, options={})
|
65
|
+
request(:post, path, params, options)
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
# Perform an HTTP request
|
70
|
+
def self.request(method, path, params, options)
|
71
|
+
params.merge!(LexerVariables::Configuration.default_options)
|
72
|
+
path = "#{LexerVariables::Configuration.endpoint}#{path}"
|
73
|
+
response = LexerVariables::api_connection(options).run_request(method, nil, nil, nil) do |request|
|
74
|
+
case method.to_sym
|
75
|
+
when :delete, :get
|
76
|
+
request.url(path, params)
|
77
|
+
when :post, :put
|
78
|
+
request.path = path
|
79
|
+
request.body = params unless params.empty?
|
80
|
+
request.options.timeout = 20
|
81
|
+
request.options.open_timeout = 30
|
82
|
+
else
|
83
|
+
fail LexerVariables::RequestError, "Request method '#{method}' is unsupported"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
response.body
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class LexerVariables::AttributeGenerator < LexerVariables::DashboardObject
|
2
|
+
ENDPOINT = "attribute_generators"
|
3
|
+
|
4
|
+
lazy_attr_reader :object, :attributes
|
5
|
+
|
6
|
+
def self.format_object(objects)
|
7
|
+
objects.collect do |object|
|
8
|
+
{
|
9
|
+
'object' => object.fetch('monitored_object', {})['object'],
|
10
|
+
'attributes' => object['attributes']
|
11
|
+
}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class LexerVariables::DashboardObject < LexerVariables::LexerModel
|
2
|
+
def self.all(provider:, shards: 0)
|
3
|
+
LexerVariables.validate_provider(provider)
|
4
|
+
|
5
|
+
objects = LexerVariables::Request.get("#{self::ENDPOINT}/#{provider}/#{self.object_type}")
|
6
|
+
formatted_objects = format_object(objects)
|
7
|
+
shard_objects(objects:formatted_objects, shards:shards)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.format_object(objects)
|
11
|
+
objects
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.shard_objects(objects:, shards:)
|
15
|
+
return objects if shards == 0
|
16
|
+
|
17
|
+
# If we don't have enough objects to shard, every shard gets all the objects
|
18
|
+
return shards.times.collect{objects} if objects.size.to_f <= (shards * 2)
|
19
|
+
|
20
|
+
slice_size = (objects.size.to_f / shards).ceil
|
21
|
+
object_distribution = objects.each_slice(slice_size).collect{|i| i}
|
22
|
+
number_of_objects_to_shift = slice_size - object_distribution.last.size - 1
|
23
|
+
number_of_objects_to_shift.times do |i|
|
24
|
+
object_distribution.last << object_distribution[i].pop
|
25
|
+
end
|
26
|
+
|
27
|
+
object_distribution
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
self.object
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
|
3
|
+
class LexerVariables::MonitoredAccount < LexerVariables::LexerModel
|
4
|
+
attr_reader :key
|
5
|
+
attr_reader :secret
|
6
|
+
attr_reader :username
|
7
|
+
attr_reader :email
|
8
|
+
attr_reader :client_id
|
9
|
+
attr_reader :id
|
10
|
+
attr_reader :monitored_object
|
11
|
+
|
12
|
+
def initialize(data)
|
13
|
+
|
14
|
+
unless data.key?('access_token_key') && data.key?('access_token_secret')
|
15
|
+
fail LexerVariables::InvalidObject, "JSON OAuth returned (#{data}) was not usable due to missing fields."
|
16
|
+
end
|
17
|
+
|
18
|
+
@key = data['access_token_key']
|
19
|
+
@secret = data['access_token_secret']
|
20
|
+
@username = data['username']
|
21
|
+
@email = data['email']
|
22
|
+
@client_id = data['client_id']
|
23
|
+
@monitored_object = data['monitored_object']
|
24
|
+
@id = data['id']
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.lease(provider)
|
28
|
+
self.lease_object(provider, nil)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.lease_object(provider, monitored_object)
|
32
|
+
LexerVariables.validate_provider(provider)
|
33
|
+
|
34
|
+
options = {}
|
35
|
+
if monitored_object
|
36
|
+
options['monitored_object'] = monitored_object
|
37
|
+
end
|
38
|
+
|
39
|
+
response = LexerVariables::Request.get("monitored_accounts/#{provider}/lease", options)
|
40
|
+
return nil if response == {}
|
41
|
+
LexerVariables::MonitoredAccount.new(response)
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.all(provider)
|
45
|
+
LexerVariables.validate_provider(provider)
|
46
|
+
|
47
|
+
monitored_accounts = LexerVariables::Request.get("monitored_accounts/#{provider}")
|
48
|
+
return nil if monitored_accounts == []
|
49
|
+
|
50
|
+
response = []
|
51
|
+
monitored_accounts.each do |monitored_account|
|
52
|
+
response << LexerVariables::MonitoredAccount.new(monitored_account)
|
53
|
+
end
|
54
|
+
#Sort as lowest MonitoredAccount.id going to worker 0
|
55
|
+
response = response.sort_by{|account| account.id }
|
56
|
+
|
57
|
+
return response
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.send_error(provider, error_message, id)
|
61
|
+
LexerVariables.validate_provider(provider)
|
62
|
+
|
63
|
+
options = {
|
64
|
+
"provider" => provider,
|
65
|
+
"id" => id,
|
66
|
+
"error_message" => error_message
|
67
|
+
}
|
68
|
+
|
69
|
+
response = LexerVariables::Request.post('monitored_accounts/error', options)
|
70
|
+
if response.nil?
|
71
|
+
response = "Successfully posted email"
|
72
|
+
end
|
73
|
+
return response
|
74
|
+
end
|
75
|
+
|
76
|
+
def <=>(account)
|
77
|
+
if self.id < account.id
|
78
|
+
-1
|
79
|
+
elsif self.id > account.id
|
80
|
+
1
|
81
|
+
else
|
82
|
+
0
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
|
3
|
+
class LexerVariables::MonitoredObject < LexerVariables::DashboardObject
|
4
|
+
ENDPOINT = "monitored_objects"
|
5
|
+
|
6
|
+
lazy_attr_reader :object
|
7
|
+
|
8
|
+
def self.pop(provider:)
|
9
|
+
LexerVariables.validate_provider(provider)
|
10
|
+
|
11
|
+
response = LexerVariables::Request.get("#{ENDPOINT}/#{provider}/#{self.object_type}/pop")
|
12
|
+
self.new(response)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.format_object(objects)
|
16
|
+
objects.collect do |object|
|
17
|
+
object['object']
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
|
3
|
+
class LexerVariables::OAuth < LexerVariables::MonitoredObject
|
4
|
+
attr_reader :key
|
5
|
+
attr_reader :secret
|
6
|
+
attr_reader :username
|
7
|
+
attr_reader :email
|
8
|
+
|
9
|
+
def initialize(attrs)
|
10
|
+
super(attrs)
|
11
|
+
data = MultiJson::decode(object)
|
12
|
+
|
13
|
+
unless data.key?('access_token') && data.key?('access_token_secret')
|
14
|
+
fail LexerVariables::InvalidObject, "JSON OAuth returned (#{object}) was not usable due to missing fields."
|
15
|
+
end
|
16
|
+
|
17
|
+
@key = data['access_token']
|
18
|
+
@secret = data['access_token_secret']
|
19
|
+
@username = data['username']
|
20
|
+
@email = data['email']
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def self.object_type
|
26
|
+
'oauths'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe LexerVariables::AttributeGenerator do
|
4
|
+
|
5
|
+
describe 'no objects to acquire' do
|
6
|
+
before do
|
7
|
+
stub_get("/api/system/attribute_generators/twitter/regions?api_token=#{LexerVariables::SECRET_TOKEN}").
|
8
|
+
to_return(body: MultiJson.dump('Not found'), status: 404) if $should_stub
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should fail for an unpopulated type' do
|
12
|
+
assert_raises LexerVariables::RequestError do
|
13
|
+
LexerVariables::AttributeGeoRegion.all(provider: :twitter)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#all' do
|
19
|
+
let(:attribute_users) {
|
20
|
+
(1..10).collect { |x| test_attribute_user }
|
21
|
+
}
|
22
|
+
|
23
|
+
before do
|
24
|
+
stub_get("/api/system/attribute_generators/twitter/users?api_token=#{LexerVariables::SECRET_TOKEN}").
|
25
|
+
to_return(body: MultiJson.dump(attribute_users), status: 200) if $should_stub
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should get all attribute generator users for single provider' do
|
29
|
+
users = LexerVariables::AttributeUser.all(provider: :twitter)
|
30
|
+
users.must_be_instance_of(Array)
|
31
|
+
users.size.must_equal(10)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should shard attribute generator users' do
|
35
|
+
users = LexerVariables::AttributeUser.all(provider: :twitter, shards: 4)
|
36
|
+
users.must_be_instance_of(Array)
|
37
|
+
users.size.must_equal(4)
|
38
|
+
users[0].must_be_instance_of(Array)
|
39
|
+
users[0].size.must_equal(2)
|
40
|
+
users[1].must_be_instance_of(Array)
|
41
|
+
users[1].size.must_equal(3)
|
42
|
+
users.flatten.size.must_equal(10)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
|
3
|
+
factory :monitored_account, class:Hash do
|
4
|
+
id { Faker::Number.number(4).to_i }
|
5
|
+
provider { "twitter" }
|
6
|
+
client_id { Faker::Number.digit }
|
7
|
+
username { Faker::Internet.user_name }
|
8
|
+
email { Faker::Internet.email }
|
9
|
+
access_token_key { Faker::Internet.password(8) }
|
10
|
+
access_token_secret { Faker::Internet.password(16) }
|
11
|
+
monitored_object { Faker::Lorem::words(1)[0] }
|
12
|
+
last_used { DateTime.now.iso8601 }
|
13
|
+
expires { DateTime.now.iso8601 }
|
14
|
+
created_time { DateTime.now.iso8601 }
|
15
|
+
updated_time { DateTime.now.iso8601 }
|
16
|
+
is_priority { false }
|
17
|
+
|
18
|
+
initialize_with { attributes }
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe LexerVariables do
|
4
|
+
describe '#validate_provider' do
|
5
|
+
it 'should reject invalid network' do
|
6
|
+
assert_raises LexerVariables::UnknownProvider do
|
7
|
+
LexerVariables.validate_provider(:lexer)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should accept valid networks' do
|
12
|
+
assert LexerVariables.validate_provider(:twitter)
|
13
|
+
assert LexerVariables.validate_provider(:spinn3r)
|
14
|
+
assert LexerVariables.validate_provider(:instagram)
|
15
|
+
assert LexerVariables.validate_provider(:facebook)
|
16
|
+
assert LexerVariables.validate_provider(:yammer)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe LexerVariables::MonitoredAccount do
|
4
|
+
|
5
|
+
describe 'no accounts to monitor' do
|
6
|
+
before do
|
7
|
+
stub_get("/api/system/monitored_accounts/twitter/lease?api_token=#{LexerVariables::SECRET_TOKEN}").
|
8
|
+
to_return(body: MultiJson.dump('Not found'), status: 404) if $should_stub
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'fails' do
|
12
|
+
assert_raises LexerVariables::RequestError do
|
13
|
+
LexerVariables::MonitoredAccount.lease(:twitter)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#all' do
|
19
|
+
let(:monitored_accounts) {[
|
20
|
+
FactoryGirl.build(:monitored_account),
|
21
|
+
FactoryGirl.build(:monitored_account),
|
22
|
+
FactoryGirl.build(:monitored_account),
|
23
|
+
FactoryGirl.build(:monitored_account),
|
24
|
+
FactoryGirl.build(:monitored_account)
|
25
|
+
]}
|
26
|
+
|
27
|
+
before do
|
28
|
+
stub_get("/api/system/monitored_accounts/twitter?api_token=#{LexerVariables::SECRET_TOKEN}").
|
29
|
+
to_return(body: MultiJson.dump(monitored_accounts)) if $should_stub
|
30
|
+
|
31
|
+
stub_get("/api/system/monitored_accounts/facebook?api_token=#{LexerVariables::SECRET_TOKEN}").
|
32
|
+
to_return(body: MultiJson.dump([])) if $should_stub
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should get all monitored accounts for single provider' do
|
36
|
+
accounts = LexerVariables::MonitoredAccount.all(:twitter)
|
37
|
+
accounts.must_be_instance_of(Array)
|
38
|
+
accounts.size.must_equal(5)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should return nil for provider with no accounts' do
|
42
|
+
accounts = LexerVariables::MonitoredAccount.all(:facebook)
|
43
|
+
accounts.must_be_instance_of(NilClass)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should return monitored accounts in sorted order' do
|
47
|
+
accounts = LexerVariables::MonitoredAccount.all(:twitter)
|
48
|
+
accounts.must_be_instance_of(Array)
|
49
|
+
accounts.size.must_equal(5)
|
50
|
+
last_id = -1
|
51
|
+
sorted = true
|
52
|
+
accounts.each do |account|
|
53
|
+
sorted &= account.id > last_id
|
54
|
+
last_id = account.id if sorted
|
55
|
+
end
|
56
|
+
assert(sorted, 'monitored_accounts are not sorted by .id')
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe 'twitter' do
|
61
|
+
let(:monitored_account) {
|
62
|
+
FactoryGirl.build(:monitored_account)
|
63
|
+
}
|
64
|
+
|
65
|
+
describe 'get accounts to monitor' do
|
66
|
+
before do
|
67
|
+
stub_get("/api/system/monitored_accounts/twitter/lease?api_token=#{LexerVariables::SECRET_TOKEN}").
|
68
|
+
to_return(body: MultiJson.dump(monitored_account)) if $should_stub
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'leases a single account' do
|
72
|
+
account = LexerVariables::MonitoredAccount.lease(:twitter)
|
73
|
+
account.must_be_instance_of(LexerVariables::MonitoredAccount)
|
74
|
+
account.monitored_object.must_equal(monitored_account[:monitored_object])
|
75
|
+
account.key.must_equal(monitored_account[:access_token_key])
|
76
|
+
account.secret.must_equal(monitored_account[:access_token_secret])
|
77
|
+
account.client_id.must_equal(monitored_account[:client_id])
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe 'facebook' do
|
83
|
+
let(:monitored_account) {
|
84
|
+
FactoryGirl.build(:monitored_account)
|
85
|
+
}
|
86
|
+
|
87
|
+
let(:facebook_page_id) {
|
88
|
+
Faker::Internet.password(8)
|
89
|
+
}
|
90
|
+
|
91
|
+
describe 'get accounts to monitor' do
|
92
|
+
before do
|
93
|
+
stub_get("/api/system/monitored_accounts/facebook/lease?api_token=#{LexerVariables::SECRET_TOKEN}&monitored_object=#{facebook_page_id}").
|
94
|
+
to_return(body: MultiJson.dump(monitored_account)) if $should_stub
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'leases a single account' do
|
98
|
+
account = LexerVariables::MonitoredAccount.lease_object(:facebook, facebook_page_id)
|
99
|
+
account.must_be_instance_of(LexerVariables::MonitoredAccount)
|
100
|
+
account.monitored_object.must_equal(monitored_account[:monitored_object])
|
101
|
+
account.key.must_equal(monitored_account[:access_token_key])
|
102
|
+
account.secret.must_equal(monitored_account[:access_token_secret])
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe LexerVariables::MonitoredObject do
|
4
|
+
|
5
|
+
describe 'no objects to acquire' do
|
6
|
+
before do
|
7
|
+
stub_get("/api/system/monitored_objects/twitter/regions/pop?api_token=#{LexerVariables::SECRET_TOKEN}").
|
8
|
+
to_return(body: MultiJson.dump('Not found'), status: 404) if $should_stub
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should fail for an unpopulated type' do
|
12
|
+
assert_raises LexerVariables::RequestError do
|
13
|
+
LexerVariables::MonitoredGeoRegion.pop(provider: :twitter)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#all' do
|
19
|
+
let(:monitored_terms) {
|
20
|
+
(1..10).collect { |x| FactoryGirl.build(:monitored_term, object: x.to_s) }
|
21
|
+
}
|
22
|
+
|
23
|
+
before do
|
24
|
+
stub_get("/api/system/monitored_objects/twitter/terms?api_token=#{LexerVariables::SECRET_TOKEN}").
|
25
|
+
to_return(body: MultiJson.dump(monitored_terms), status: 200) if $should_stub
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should get all monitored terms for single provider' do
|
29
|
+
terms = LexerVariables::MonitoredTerm.all(provider: :twitter)
|
30
|
+
terms.must_be_instance_of(Array)
|
31
|
+
terms.size.must_equal(10)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should shard monitored terms' do
|
35
|
+
terms = LexerVariables::MonitoredTerm.all(provider: :twitter, shards: 4)
|
36
|
+
terms.must_be_instance_of(Array)
|
37
|
+
terms.size.must_equal(4)
|
38
|
+
terms[0].must_be_instance_of(Array)
|
39
|
+
terms[0].size.must_equal(2)
|
40
|
+
terms[1].must_be_instance_of(Array)
|
41
|
+
terms[1].size.must_equal(3)
|
42
|
+
terms.flatten.size.must_equal(10)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#pop' do
|
48
|
+
let(:monitored_term) { |x| FactoryGirl.build(:monitored_term) }
|
49
|
+
|
50
|
+
before do
|
51
|
+
stub_get("/api/system/monitored_objects/twitter/terms/pop?api_token=#{LexerVariables::SECRET_TOKEN}").
|
52
|
+
to_return(body: MultiJson.dump(monitored_term), status: 200) if $should_stub
|
53
|
+
stub_get("/api/system/monitored_objects/twitter/regions/pop?api_token=#{LexerVariables::SECRET_TOKEN}").
|
54
|
+
to_return(body: '{"error":"404 Not Found"}', status: 404) if $should_stub
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should acquire a term' do
|
58
|
+
term1 = LexerVariables::MonitoredTerm.pop(provider: :twitter)
|
59
|
+
term1.to_s.must_equal(monitored_term[:object])
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/test/oauth_test.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe LexerVariables::OAuth do
|
4
|
+
|
5
|
+
describe '#pop' do
|
6
|
+
let(:oauth) { |x| FactoryGirl.build(:oauth) }
|
7
|
+
|
8
|
+
before do
|
9
|
+
stub_get("/api/system/monitored_objects/twitter/oauths/pop?api_token=#{LexerVariables::SECRET_TOKEN}").
|
10
|
+
to_return(body: MultiJson.dump(oauth), status: 200) if $should_stub
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should acquire an OAuth' do
|
14
|
+
oauth = LexerVariables::OAuth.pop(provider: :twitter)
|
15
|
+
oauth.key.must_equal('abcdef')
|
16
|
+
oauth.secret.must_equal('ghi')
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require 'minitest/reporters'
|
5
|
+
require 'minitest/spec'
|
6
|
+
require 'webmock/minitest'
|
7
|
+
require 'faker'
|
8
|
+
require 'factory_girl'
|
9
|
+
|
10
|
+
MiniTest::Reporters.use! [Minitest::Reporters::SpecReporter.new, MiniTest::Reporters::JUnitReporter.new]
|
11
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'lexervariables')
|
12
|
+
FactoryGirl.find_definitions
|
13
|
+
|
14
|
+
$should_stub = true
|
15
|
+
if $should_stub
|
16
|
+
WebMock.disable_net_connect!
|
17
|
+
else
|
18
|
+
WebMock.allow_net_connect!
|
19
|
+
end
|
20
|
+
|
21
|
+
def request_path(path)
|
22
|
+
"https://lexer-dashboard#{path}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def stub_get(path)
|
26
|
+
WebMock::API.stub_http_request(:get, request_path(path))
|
27
|
+
end
|
28
|
+
|
29
|
+
# As the hash requires a key called 'attributes', this breaks factory call as when you call
|
30
|
+
# ```initialise_with { attributes }``` in FactoryGirl, it becomes infinitely recursive.
|
31
|
+
def test_attribute_user
|
32
|
+
{
|
33
|
+
monitored_object: {
|
34
|
+
object: Faker::Number.number(10)
|
35
|
+
},
|
36
|
+
attributes: ['io.company.' + Faker::Lorem::words(1)[0]] * 3
|
37
|
+
}
|
38
|
+
end
|
metadata
ADDED
@@ -0,0 +1,204 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lexervariables
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Aaron Wallis
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-02-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: faraday
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: multi_json
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: oj
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: minitest-reporters
|
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: factory_girl
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: faker
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rake
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: webmock
|
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: Gem for loading variables (terms, geographies, authors, pages, oauths)
|
140
|
+
to monitor
|
141
|
+
email:
|
142
|
+
- aaron.wallis@lexer.com.au
|
143
|
+
executables: []
|
144
|
+
extensions: []
|
145
|
+
extra_rdoc_files: []
|
146
|
+
files:
|
147
|
+
- ".gitignore"
|
148
|
+
- Gemfile
|
149
|
+
- README.md
|
150
|
+
- Rakefile
|
151
|
+
- lexervariables.gemspec
|
152
|
+
- lib/lexervariables.rb
|
153
|
+
- lib/lexervariables/api.rb
|
154
|
+
- lib/lexervariables/attribute_generator.rb
|
155
|
+
- lib/lexervariables/attribute_geo_region.rb
|
156
|
+
- lib/lexervariables/attribute_page.rb
|
157
|
+
- lib/lexervariables/attribute_user.rb
|
158
|
+
- lib/lexervariables/dashboard_object.rb
|
159
|
+
- lib/lexervariables/error.rb
|
160
|
+
- lib/lexervariables/monitored_account.rb
|
161
|
+
- lib/lexervariables/monitored_geo_region.rb
|
162
|
+
- lib/lexervariables/monitored_object.rb
|
163
|
+
- lib/lexervariables/monitored_page.rb
|
164
|
+
- lib/lexervariables/monitored_term.rb
|
165
|
+
- lib/lexervariables/monitored_url.rb
|
166
|
+
- lib/lexervariables/monitored_user.rb
|
167
|
+
- lib/lexervariables/oauth.rb
|
168
|
+
- lib/lexervariables/version.rb
|
169
|
+
- test/attribute_generator_test.rb
|
170
|
+
- test/docker-launch-tests.sh
|
171
|
+
- test/docker-run-tests.sh
|
172
|
+
- test/factories/monitored_accounts.rb
|
173
|
+
- test/factories/monitored_terms.rb
|
174
|
+
- test/factories/oauths.rb
|
175
|
+
- test/lexer_variables_test.rb
|
176
|
+
- test/monitored_account_test.rb
|
177
|
+
- test/monitored_object_test.rb
|
178
|
+
- test/oauth_test.rb
|
179
|
+
- test/test_helper.rb
|
180
|
+
homepage: http://lexer.com.au
|
181
|
+
licenses: []
|
182
|
+
metadata: {}
|
183
|
+
post_install_message:
|
184
|
+
rdoc_options: []
|
185
|
+
require_paths:
|
186
|
+
- lib
|
187
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
188
|
+
requirements:
|
189
|
+
- - ">="
|
190
|
+
- !ruby/object:Gem::Version
|
191
|
+
version: '0'
|
192
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
193
|
+
requirements:
|
194
|
+
- - ">="
|
195
|
+
- !ruby/object:Gem::Version
|
196
|
+
version: '0'
|
197
|
+
requirements: []
|
198
|
+
rubyforge_project:
|
199
|
+
rubygems_version: 2.2.2
|
200
|
+
signing_key:
|
201
|
+
specification_version: 4
|
202
|
+
summary: Gem for loading variables (terms, geographies, authors, pages, oauths) to
|
203
|
+
monitor
|
204
|
+
test_files: []
|