wordstream_client 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,199 @@
1
+ # Wordstream API Gem
2
+
3
+ A wrapper around the Wordstream API calls.
4
+
5
+ * [Github](http://github.com/mtchavez/wordstream-client "Github Repo")
6
+ * [Rubygems](https://rubygems.org/gems/wordstream-client "Rubygems Page")
7
+
8
+ ## Disclaimer
9
+
10
+ The Wordstream API is constructed very poorly in my personal opinion. In addition to this I have had issues with it's
11
+ reliability and usability. I take no responsibility for you using their service and I advise you use them
12
+ **at your own risk**. This library was written due to the lack of libraries for Ruby and due to the only one out there does
13
+ not look maintained nor does it implement all the current endpoints available.
14
+
15
+ ## Description
16
+
17
+ Wordstream API gem to wrap the API calls available. Allows you to login/logout, get your api credits, get keyword volumes,
18
+ get keyword suggestions, get keyword niches, get question keywords and get related keywords. Currently the callback parameter
19
+ is not implemented on any of the endpoints. This may change in the future if it becomes a needed feature.
20
+
21
+ ## Install
22
+
23
+ gem install wordstream_client
24
+
25
+ ## Setup
26
+
27
+ To set up the gem you need to set your Wordstream username and password before making any API requests.
28
+
29
+ require 'wordstream_client'
30
+
31
+ WordstreamClient::Config.username = 'user@example.com'
32
+ WordstreamClient::Config.password = 'password'
33
+
34
+ ## Authentication Endpoints
35
+
36
+ ---
37
+
38
+ ### Login
39
+
40
+ After configuring your username and password you need to login to Wordstream to get a session_id
41
+ in order to make API requests. This will be configured for you automatically after login.
42
+
43
+ WordstreamClient::Auth.login
44
+
45
+ ### Logout
46
+
47
+ If you want to destroy your Wordstream session you can use the logout endpoint to do so.
48
+
49
+ WordstreamClient::Auth.logout
50
+
51
+ ### Get API Credits
52
+
53
+ Wordstream allows you to get your monthly API credits and your monthly credits used. Use this endpoint to
54
+ see your API credit usage.
55
+
56
+ data = WordstreamClient::Auth.get_api_credits
57
+
58
+ # Returns hash of credits
59
+ # { "remaining_monthly_credits" => 19, "credits_per_month" => 20 }
60
+
61
+ remaining = data['remaining_monthly_credits']
62
+ total = data['credits_per_month']
63
+
64
+ ## Keyword Tool Endpoints
65
+
66
+ ---
67
+
68
+ ### Volumes
69
+
70
+ To get keyword volumes you can pass in an array of keywords to get their volumes *relative* to each other.
71
+
72
+ keywords = %w[running apple ipod ipad race triathlon]
73
+ data = WordstreamClient::KeywordTool.get_volumes(keywords)
74
+
75
+ # Returns array of arrays with keywords and their volume
76
+ # [ ['running', 123], ['apple', 77], ['ipod', 34] ]
77
+
78
+ keyword_volumes = Hash[data]
79
+ keywords_with_volumes = keyword_volumes.keys
80
+
81
+ ### Niches
82
+
83
+ Make sure to pass in a smaller max then the default as it will most likely timeout from Wordstream.
84
+
85
+ keywords = %w[running apple ipod ipad race triathlon]
86
+ data = WordstreamClient::KeywordTool.get_niches(keywords)
87
+
88
+ # Example data response
89
+ # keyword_index refers to the array position in the 'keywords' dict element.
90
+ {
91
+ 'total': number_of_suggestions,
92
+ 'groupings': [
93
+ {
94
+ 'title': display_label,
95
+ 'score': score,
96
+ 'wordlist': [query_word, ... , query_word],
97
+ 'matches': [keyword_index, ... , keyword_index]
98
+ }
99
+ ],
100
+ 'keywords': [ [keyword, relative_volume], ... , [keyword, relative_volume] ]
101
+ }
102
+
103
+
104
+ ### Suggestions
105
+
106
+ Make sure to pass in a smaller max then the default as it will most likely timeout from Wordstream.
107
+
108
+ keywords = %w[running apple ipod ipad race triathlon]
109
+ data = WordstreamClient::KeywordTool.get_suggestions(keywords)
110
+
111
+ # Example data response
112
+ [["apple", 196], ["ipad 2 cases", 95], ["apple
113
+ stock", 75], ["apple cider vinegar", 72], ["apple store", 69], ["apple computers",
114
+ 69], ["apple juice", 68], ["apple vacations", 60], ["apple ipod", 60], ["apple
115
+ crisp recipe", 53], ["apple earnings", 52], ["case for ipad 2", 51], ["cases
116
+ for the ipad 2", 48], ["valley apple", 46], ["apple laptops", 42], ["apple
117
+ iphone", 42], ["vinegar apple", 39], ["silver apple", 39], ["jeans apple bottom",
118
+ 39], ["apple bottom", 39], ["what is in apple juice", 38], ["stock of apple",
119
+ 38], ["stock in apple", 38], ["stock for apple", 38], ["stock apple com",
120
+ 38], ["apple apple juice", 38], ["tree apple", 36], ["cider apple", 36], ["apple
121
+ stock shares", 34], ["ipad best buy", 33], ["apple pie", 33], ["apple jeans",
122
+ 33], ["recipes for apple crisp", 31], ["recipe apple", 31], ["ipad charger",
123
+ 31], ["apple osx tiger icons", 31], ["apple airport express", 31], ["wikipedia
124
+ apple", 29], ["green apple", 28], ["apple charger", 28], ["ipad 2 best buy",
125
+ 26], ["fiona apple", 26], ["big apple", 26], ["wikipedia ipad", 25], ["keyboard
126
+ case for ipad 2", 25], ["ipad 2 keyboard case", 25], ["ipad 2 case with keyboard",
127
+ 25], ["ipad 2 case and keyboard", 25], ["ipad 2 best cases", 25], ["best cases
128
+ for ipad 2", 25], ["pie recipe apple", 24], ["stocks on apple", 23], ["leather
129
+ ipad 2 case", 23], ["leather case for ipad 2", 23], ["cider from apple juice",
130
+ 23], ["cider apple juice", 23], ["apple talk", 23], ["apple juice apple cider",
131
+ 23], ["apple juice and apple cider", 23], ["apple cider or apple juice", 23],
132
+ ["apple cider from apple juice", 23], ["walmart ipad", 22], ["target ipad",
133
+ 22], ["stock price of apple", 22], ["stock price for apple", 22], ["stock
134
+ price apple", 22], ["red apple", 22], ["price of stock for apple", 22], ["ipad
135
+ at target", 22], ["ipad 2 cover case", 22], ["apple lyrics", 22], ["apple
136
+ stocks and shares", 21], ["apple itunes", 21], ["apple federal credit union",
137
+ 21], ["apple crisp", 21], ["value of apple stock", 20], ["stock quote for
138
+ apple", 20], ["stock quote apple", 20], ["pie crust for apple pie", 20], ["ipad
139
+ 2 case review", 20], ["how to can apple juice", 20], ["crystal apple", 20],
140
+ ["can apple juice", 20], ["apple trailers", 20], ["apple stock value", 20],
141
+ ["apple stock share price", 20], ["apple stock price quote", 20], ["apple
142
+ pie crust", 20], ["apple picking", 20], ["apple ipad 2 case", 20], ["apple
143
+ cinnamon", 20], ["stock market for apple", 19], ["stock market apple", 19],
144
+ ["orchard apple", 19], ["ipad", 19], ["beatles apple", 19], ["apple in the
145
+ stock market", 19], ["apple caramel", 19], ["apple cake", 19], ["make apple
146
+ juice", 18]]
147
+
148
+ ### Question Keywords
149
+
150
+ keywords = %w[running apple ipod ipad race triathlon]
151
+ data = WordstreamClient::KeywordTool.get_questions(keywords)
152
+
153
+ # Example data response
154
+ [["what is in apple juice", 38], ["how to can apple juice", 20], ["can apple juice", 20],
155
+ ["why buy apple stock", 13], ["where to buy apple stock", 13], ["what s in apple juice", 13],
156
+ ["what is apple juice concentrate", 13], ["how do i buy apple stock", 13],
157
+ ["what is apple stock today", 12], ["what is apple juice made of", 12], ["how is apple juice made", 12],
158
+ ["how much is apple juice", 11], ["does apple juice go bad", 10], ["kindle vs ipad", 9],
159
+ ["is apple juice good for you", 9], ["how much is stock in apple", 9], ["how much is apple stock", 9],
160
+ ["cider vs apple juice", 9], ["apple juice vs apple cider", 9], ["who owns apple", 8],
161
+ ["what is apple stock worth", 8], ["will apple stock split", 7], ...]
162
+
163
+ ### Related Keywords
164
+
165
+ keywords = %w[running apple ipod ipad race triathlon]
166
+ data = WordstreamClient::KeywordTool.get_related(keywords)
167
+
168
+ # Example data response
169
+ ["mac os x", "learn and earn", "all around
170
+ my", "store for education", "the crazy ones", "mac os rumors", "rip mix burn",
171
+ "ipaq pocket pc", "will ferrell", "steve jobs", "will farrell", "os x", "developer
172
+ connection", "think different", "power book", "learning interchange", "mac
173
+ rumors", "steven jobs", "knowledge navigator", "digital hub", "think secret",
174
+ "jonathan ive", "i mac", "data quest", "crazy ones", "rescue raiders", "mac
175
+ rumor", "next byte", "megahertz myth", "real losers", "pocket pc", "hard reset",
176
+ "concurso publico", "com br", "ipaq 2210", "ipaq 4150", "ipaq 1940", "detran
177
+ pernambuco", "detran pe", "iphone", "macintosh", "titanium", "laptops", "applescript",
178
+ "mac", "applesauce", "apples", "rumors", "mackintosh", "orchards", "appleseed",
179
+ "versiontracker", "resellers", "parody", "keynote", "imovie", "superdrive",
180
+ "crabapple", "wallstreet", "macworld", "iphoto", "appleworks", "applewood",
181
+ "cider", "parodies", "crumble", "laserwriter", "schnapps", "powerpc", "martinis",
182
+ "applecare", "performa", "crisp", "spoof", "rumor", "manzana", "stylewriter",
183
+ "gravis", "appletalk", "wozniak", "clarisworks", "pismo", "strudel", "macs",
184
+ "appel", "garamond", "pectin", "altair", "applejacks", "applestore", "macally",
185
+ "macrumors", "hypercard", "appleshare", "powerlogix", "macos", "applemac",
186
+ "isync", "thinkdifferent", "carbonlib"]
187
+
188
+ ## Todo
189
+
190
+ 1. Make RDoc for gem.
191
+ 2. Handle potential errors better when making requests to Wordstream.
192
+ 3. Refactor HTTP requests.
193
+ 4. Make a Response class to be returned from API calls instead of parsed JSON.
194
+
195
+ ## License
196
+
197
+ Written by Chavez
198
+
199
+ Released under the MIT License: http://www.opensource.org/licenses/mit-license.php
@@ -0,0 +1,81 @@
1
+ module WordstreamClient
2
+
3
+ class Auth
4
+
5
+ def initialize(config)
6
+ @config = config
7
+ end
8
+
9
+ def self.clear_session
10
+ Config.session_id = nil
11
+ end
12
+
13
+ def clear_session
14
+ self.class.clear_session
15
+ @config.session_id = nil if @config
16
+ end
17
+
18
+ def self.login
19
+ Config.client.auth.login
20
+ end
21
+
22
+ def login
23
+ path = '/authentication/login'
24
+ query = "?username=#{@config.username}&password=#{@config.password}"
25
+ resp = RestClient.get(@config.default_host + path + query)
26
+ data = JSON.parse resp.body
27
+
28
+ raise AuthError.new('login', data['error']) if data.has_key?('error')
29
+
30
+ session_id = data['data']['session_id'] if data.has_key?('data')
31
+ Config.session_id = session_id
32
+ @config.session_id = session_id
33
+
34
+ raise AuthError.new('login', 'Failed to get a session id from Wordstream.') if @config.session_id.nil?
35
+
36
+ return data
37
+ rescue JSON::ParserError => e
38
+ raise AuthError.new('login', 'Bad response from Wordstream when trying to login.')
39
+ end
40
+
41
+ def self.logout
42
+ Config.client.auth.logout
43
+ end
44
+
45
+ def logout
46
+ path = '/authentication/logout'
47
+ query = "?session_id=#{@config.session_id}"
48
+ resp = RestClient.get(@config.default_host + path + query)
49
+ data = JSON.parse resp.body
50
+
51
+ raise AuthError.new('logout', data['error']) if data.has_key?('error')
52
+
53
+ clear_session
54
+
55
+ return data
56
+ rescue JSON::ParserError => e
57
+ raise AuthError.new('logout', 'Bad response from Wordstream when trying to logout.')
58
+ ensure
59
+ clear_session
60
+ end
61
+
62
+ def self.get_api_credits
63
+ Config.client.auth.get_api_credits
64
+ end
65
+
66
+ def get_api_credits
67
+ path = '/authentication/get_api_credits'
68
+ query = "?session_id=#{@config.session_id}"
69
+ resp = RestClient.get(@config.default_host + path + query)
70
+ data = JSON.parse resp.body
71
+
72
+ raise AuthError.new('get_api_credits', data['detail']) if data['code'].match(/error/i)
73
+
74
+ return data
75
+ rescue JSON::ParserError => e
76
+ raise AuthError.new('get_api_credits', 'Bad response from Wordstream when trying to get api credits.')
77
+ end
78
+
79
+ end
80
+
81
+ end
@@ -0,0 +1,27 @@
1
+ module WordstreamClient
2
+
3
+ class Client
4
+
5
+ attr_reader :config
6
+
7
+ def initialize(config)
8
+ @config = if config.is_a?(Hash)
9
+ Config.new(config)
10
+ elsif config.is_a?(WordstreamClient::Config)
11
+ config
12
+ else
13
+ raise ArgumentError, 'invalid configuration for client.'
14
+ end
15
+ end
16
+
17
+ def auth
18
+ Auth.new @config
19
+ end
20
+
21
+ def keyword_tool(keywords)
22
+ KeywordTool.new @config, keywords
23
+ end
24
+
25
+ end
26
+
27
+ end
@@ -0,0 +1,47 @@
1
+ module WordstreamClient
2
+
3
+ class Config
4
+
5
+ class << self
6
+ attr_accessor :username, :password, :session_id
7
+ end
8
+
9
+ def self.instantiate # :nodoc:
10
+ new( username: username, password: password, session_id: session_id )
11
+ end
12
+
13
+ def self.client
14
+ Client.new instantiate
15
+ end
16
+
17
+ def initialize(options = {})
18
+ [:username, :password, :session_id].each do |var|
19
+ instance_variable_set "@#{var}", options[var]
20
+ end
21
+ end
22
+
23
+ def username
24
+ @username
25
+ end
26
+
27
+ def password
28
+ @password
29
+ end
30
+
31
+ def session_id
32
+ @session_id
33
+ end
34
+
35
+ def session_id=(new_session)
36
+ # return false if new_session.to_s.empty?
37
+ instance_variable_set "@session_id", new_session
38
+ self.class.session_id = new_session
39
+ end
40
+
41
+ def default_host
42
+ 'http://api.wordstream.com'
43
+ end
44
+
45
+ end
46
+
47
+ end
@@ -0,0 +1,22 @@
1
+ module WordstreamClient
2
+
3
+ class WordstreamClientError < ::StandardError; end
4
+
5
+ class AuthError < WordstreamClientError
6
+
7
+ def initialize(method, message) # :nodoc:
8
+ super "WordstreamClient::Auth.#{method} - #{message}"
9
+ end
10
+
11
+ end
12
+
13
+ class KeywordToolError < WordstreamClientError
14
+
15
+ def initialize(method, message) # :nodoc:
16
+ super "WordstreamClient::KeywordTool.#{method} - #{message}"
17
+ end
18
+
19
+ end
20
+
21
+
22
+ end
@@ -0,0 +1,114 @@
1
+ module WordstreamClient
2
+
3
+ class KeywordTool
4
+
5
+ attr_accessor :keywords
6
+
7
+ def initialize(config, keywords = [])
8
+ @config = config
9
+ @keywords = keywords.is_a?(Array) ? keywords.join("\n") : keywords.to_s
10
+ # Apache Web Server URL limit is 4000 characters
11
+ # The API is horrible and passes ALL the keywords
12
+ # In the URL string
13
+ @keywords = @keywords[0..3949]
14
+ end
15
+
16
+ def self.get_volumes(keywords, block_adult = 'false')
17
+ Config.client.keyword_tool(keywords).get_volumes(block_adult)
18
+ end
19
+
20
+ def get_volumes(block_adult = 'false')
21
+ path = '/keywordtool/get_keyword_volumes'
22
+ url_keywords = URI.encode( @keywords, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]") )
23
+ query = "?session_id=#{@config.session_id}&keywords=#{url_keywords}&block_adult=#{block_adult}"
24
+ resp = RestClient.get( @config.default_host + path + query )
25
+ data = JSON.parse resp.body
26
+
27
+ raise KeywordToolError.new('get_volumes', data['detail']) if data['code'].match(/error/i)
28
+
29
+ return data['data']
30
+ rescue JSON::ParserError => e
31
+ raise KeywordToolError.new('get_volumes', 'Bad response from Wordstream when trying to get keyword volumes.')
32
+ end
33
+
34
+ def self.get_niches(keywords, max = 2500, block_adult = 'false')
35
+ Config.client.keyword_tool(keywords).get_niches(max, block_adult)
36
+ end
37
+
38
+ def get_niches(max = 2500, block_adult = 'false')
39
+ max = max.abs > 2500 ? 2500 : max.abs
40
+ path = '/keywordtool/get_keyword_niches'
41
+ url_keywords = URI.encode( @keywords, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]") )
42
+ query = "?session_id=#{@config.session_id}&seeds=#{url_keywords}&block_adult=#{block_adult}&max_niches=#{max}"
43
+ resp = RestClient.get( @config.default_host + path + query )
44
+ data = JSON.parse resp.body
45
+
46
+ # TODO: Handle Error Code
47
+ # "{\"code\": \"ERROR\", \"detail\": \"No keywords provided!!!\"}"
48
+ raise KeywordToolError.new('get_niches', data['detail']) if data['code'].match(/error/i)
49
+
50
+ return data['data']
51
+ rescue JSON::ParserError => e
52
+ raise KeywordToolError.new('get_niches', 'Bad response from Wordstream when trying to get keyword niches.')
53
+ end
54
+
55
+ def self.get_suggestions(keywords, max = 100000, block_adult = 'false')
56
+ Config.client.keyword_tool(keywords).get_suggestions(max, block_adult)
57
+ end
58
+
59
+ def get_suggestions(max = 100000, block_adult = 'false')
60
+ max = max.abs > 100000 ? 100000 : max.abs
61
+ path = '/keywordtool/get_keywords'
62
+ url_keywords = URI.encode( @keywords[0..19], Regexp.new("[^#{URI::PATTERN::UNRESERVED}]") )
63
+ query = "?session_id=#{@config.session_id}&seeds=#{url_keywords}&block_adult=#{block_adult}&max_niches=#{max}"
64
+ resp = RestClient.get( @config.default_host + path + query )
65
+ data = JSON.parse resp.body
66
+
67
+ raise KeywordToolError.new('get_suggestions', data['detail']) if data['code'].match(/error/i)
68
+
69
+ return data['data']
70
+ rescue JSON::ParserError => e
71
+ raise KeywordToolError.new('get_suggestions', 'Bad response from Wordstream when trying to get keyword suggestions.')
72
+ end
73
+
74
+ def self.get_questions(keywords, max = 100000, block_adult = 'false')
75
+ Config.client.keyword_tool(keywords).get_questions(max, block_adult)
76
+ end
77
+
78
+ def get_questions(max = 100000, block_adult = 'false')
79
+ max = max.abs > 100000 ? 100000 : max.abs
80
+ path = '/keywordtool/get_question_keywords'
81
+ url_keywords = URI.encode( @keywords[0..19], Regexp.new("[^#{URI::PATTERN::UNRESERVED}]") )
82
+ query = "?session_id=#{@config.session_id}&seeds=#{url_keywords}&block_adult=#{block_adult}&max_niches=#{max}"
83
+ resp = RestClient.get( @config.default_host + path + query )
84
+ data = JSON.parse resp.body
85
+
86
+ raise KeywordToolError.new('get_questions', data['detail']) if data['code'].match(/error/i)
87
+
88
+ return data['data']
89
+ rescue JSON::ParserError => e
90
+ raise KeywordToolError.new('get_questions', 'Bad response from Wordstream when trying to get keyword questions.')
91
+ end
92
+
93
+ def self.get_related(keywords, max = 100, block_adult = 'false')
94
+ Config.client.keyword_tool(keywords).get_related(max, block_adult)
95
+ end
96
+
97
+ def get_related(max = 100, block_adult = 'false')
98
+ max = max.abs > 100 ? 100 : max.abs
99
+ path = '/keywordtool/get_related_keywords'
100
+ url_keywords = URI.encode( @keywords[0..19], Regexp.new("[^#{URI::PATTERN::UNRESERVED}]") )
101
+ query = "?session_id=#{@config.session_id}&seeds=#{url_keywords}&block_adult=#{block_adult}&max_niches=#{max}"
102
+ resp = RestClient.get( @config.default_host + path + query )
103
+ data = JSON.parse resp.body
104
+
105
+ raise KeywordToolError.new('get_related', data['detail']) if data['code'].match(/error/i)
106
+
107
+ return data['data']
108
+ rescue JSON::ParserError => e
109
+ raise KeywordToolError.new('get_related', 'Bad response from Wordstream when trying to get related keyword.')
110
+ end
111
+
112
+ end
113
+
114
+ end
@@ -0,0 +1,14 @@
1
+ require 'json'
2
+ require 'rest-client'
3
+ require 'net/http'
4
+ require 'pry'
5
+
6
+ module WordstreamClient
7
+
8
+ end
9
+
10
+ require File.dirname(__FILE__) + '/wordstream_client/auth'
11
+ require File.dirname(__FILE__) + '/wordstream_client/client'
12
+ require File.dirname(__FILE__) + '/wordstream_client/config'
13
+ require File.dirname(__FILE__) + '/wordstream_client/exceptions'
14
+ require File.dirname(__FILE__) + '/wordstream_client/keyword_tool'
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wordstream_client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Chavez
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-28 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rest-client
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 1.6.7
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.6.7
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '2.0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '2.0'
46
+ description: Wraps Wordstream API calls in a gem.
47
+ email: ''
48
+ executables: []
49
+ extensions: []
50
+ extra_rdoc_files:
51
+ - README.md
52
+ files:
53
+ - lib/wordstream_client/auth.rb
54
+ - lib/wordstream_client/client.rb
55
+ - lib/wordstream_client/config.rb
56
+ - lib/wordstream_client/exceptions.rb
57
+ - lib/wordstream_client/keyword_tool.rb
58
+ - lib/wordstream_client.rb
59
+ - README.md
60
+ homepage: http://github.com/mtchavez/wordstream-client
61
+ licenses: []
62
+ post_install_message:
63
+ rdoc_options:
64
+ - --charset=UTF-8 --main=README.md
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ! '>='
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ requirements: []
80
+ rubyforge_project: wordstream-client
81
+ rubygems_version: 1.8.24
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: Wordstream API Wrapper
85
+ test_files: []
86
+ has_rdoc: