se-api 0.0.0.beta1 → 0.0.1

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: 39c9f55b4b8c90dec1f736ac5c07d1b0b45e0eebd9272eeb90d44077a5be139c
4
- data.tar.gz: be515d58d9963644cfd9905c7f6aefe6730a8b4f3afc674bff38ecd80dfdef89
3
+ metadata.gz: 3317150023e8aea78e2bd546faa25bd8508e0e9585a0f20e42b1423a8d15238c
4
+ data.tar.gz: bfc88930f0d54ef27443a2bbae29325a80e30c467611cadcc133aad03cfbf75b
5
5
  SHA512:
6
- metadata.gz: ecaa5d9b19d82802e1f1dcffb22787f434ec7fb11eefb3d2fb4536d7cc839955424e80b90b1d8b02b555493b79eafb14d6b84d9bcc675c630597ead9a377d960
7
- data.tar.gz: 60ff0cca0fb7e438abd116287119e9241b6443a07c57f9b6b82c1209a7831b8a9ae31c3bafb31adf108d0634564ac8fd84619a637a81cde1365e0f875b2af503
6
+ metadata.gz: 8c4419af179dd69d2ca48b327d921d10ad9ec7e451fbc34078b2df7cb08d0be7c58148445ee87cec090a89ec795a3e3c48ccdf1c258f425b32b2d5051ffb0b8f
7
+ data.tar.gz: 315e6a5b03dc76a94ebdff3cb87a4f6635b045b82394069f890d1f5d01ef5c7b6083c63b4ab43756bedadc257bcceac53e374d803889338355b32a7da220694c
data/README.md CHANGED
@@ -1,28 +1,46 @@
1
- # Se::Api
1
+ # SE API
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/se/api`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ SE API is a ruby gem for interacting with the Stack Exchange API. It was designed with the [SE Realtime Fee](https://stackexchange.com) in mind (specifically interactions through [se-realtime](https://github.com/izwick-schachter/se-realtime)), and therefore it will only work with four route subsets:
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
5
+ - `/users/{ids}`
6
+ - `/posts/{ids}`
7
+ - `/questions/{ids}`
8
+ - `/answers/{ids}`
6
9
 
7
10
  ## Installation
8
11
 
9
- Add this line to your application's Gemfile:
12
+ While a version of this gem does exist in rubygems, it's recommended to use it from git. The master branch should always work. You can add it to your Gemfile with:
10
13
 
11
14
  ```ruby
12
- gem 'se-api'
15
+ gem 'se-api', git: 'https://github.com/izwick-schachter/se-api.git', branch: 'master'
13
16
  ```
14
17
 
15
18
  And then execute:
16
19
 
17
20
  $ bundle
18
21
 
19
- Or install it yourself as:
22
+ ## Usage
20
23
 
21
- $ gem install se-api
24
+ First, initialize your client. You can omit the api key, but it's strongly recommended that you use one because it increases your request limit drastically. Also, any paramters that you pass on initialization will be passed with any request (but can be overridden later). It is recommended that you set the `site` this way.
22
25
 
23
- ## Usage
26
+ ```ruby
27
+ require 'se/api'
28
+
29
+ cli = SE::API::Client.new(ENV['APIKey'], site: 'stackoverflow')
30
+ ```
31
+
32
+ Now that you've initialized the client, you can use the instance methods provided:
33
+
34
+ > Note: All the routes below pass `**params` directly to the API.
24
35
 
25
- TODO: Write usage instructions here
36
+ - `post(id, **params)`: Gets a post based on the ID passed.
37
+ - `posts(*ids, **params)`: Get posts based on either a semicolon delimited string of ids or an array of ids.
38
+ - `question(id, **params)`: Gets a question based on the ID passed.
39
+ - `questions(*ids, **params)`: Gets questions based on either a semicolon delimited string of ids or an array of ids.
40
+ - `answer(id, **params)`: Gets an answer based on the ID passed.
41
+ - `answers(*ids, **params)`: Gets answers based on either a semicolon delimited string of ids or an array of ids.
42
+ - `user(id, **params)`: Gets a user based on the ID passed.
43
+ - `users(*ids, **params)`: Gets users based on either a semicolon delimited string of ids or an array of ids.
26
44
 
27
45
  ## Development
28
46
 
@@ -32,7 +50,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
32
50
 
33
51
  ## Contributing
34
52
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/se-api. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
53
+ Bug reports and pull requests are welcome on GitHub at https://github.com/izwick-schachter/se-api. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
36
54
 
37
55
  ## License
38
56
 
@@ -40,4 +58,4 @@ The gem is available as open source under the terms of the [MIT License](http://
40
58
 
41
59
  ## Code of Conduct
42
60
 
43
- Everyone interacting in the Se::Api project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/se-api/blob/master/CODE_OF_CONDUCT.md).
61
+ Everyone interacting in the Se::Api project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/izwick-schachter/se-api/blob/master/CODE_OF_CONDUCT.md).
@@ -1,12 +1,15 @@
1
1
  require "se/api/version"
2
- require "se/api/types/post"
3
2
  require "se/api/types/answer"
4
3
  require "se/api/types/question"
4
+ require "se/api/types/comment"
5
+ require "se/api/types/user"
6
+ require "se/api/types/post"
5
7
 
6
8
  require "net/http"
7
9
  require "json"
8
10
  require "uri"
9
11
  require "time"
12
+ require "logger"
10
13
 
11
14
  module SE
12
15
  module API
@@ -16,7 +19,7 @@ module SE
16
19
  attr_reader :quota, :quota_used
17
20
  attr_accessor :params
18
21
 
19
- def initialize(key, **params)
22
+ def initialize(key = "", log_api_raw: false, log_api_json: false, log_meta: true, **params)
20
23
  @key = key
21
24
  @params = params.merge({filter: '!*1_).BnZb8pdvWlZpJYNyauMekouxK9-RzUNUrwiB'})
22
25
  @quota = nil
@@ -24,45 +27,78 @@ module SE
24
27
  @backoff = Time.now
25
28
  @logger_raw = Logger.new 'api_raw.log'
26
29
  @logger_json = Logger.new 'api_json.log'
30
+ @logger = Logger.new 'se-api.log'
31
+ @logger_raw.level = Logger::Severity::UNKNOWN unless log_api_raw
32
+ @logger_json.level = Logger::Severity::UNKNOWN unless log_api_json
33
+ @logger.level = Logger::Severity::UNKNOWN unless log_meta
27
34
  end
28
35
 
29
- def posts(ids = "", **params)
30
- return if ids == ""
31
- json("posts/#{Array(ids).join(';')}", **params).map do |i|
32
- Post.new(i)
33
- end
36
+ def posts(*ids, **params)
37
+ objectify Post, ids, **params
34
38
  end
35
39
 
36
- def questions(ids = "", **params)
37
- return if ids == ""
38
- json("questions/#{Array(ids).join(';')}", **params).map do |i|
39
- Question.new(i)
40
- end
40
+ def post(id, **params)
41
+ posts(id, **params).first
41
42
  end
42
43
 
43
- def answers(ids = "", **params)
44
- return if ids == ""
45
- json("answers/#{Array(ids).join(';')}", **params).map do |i|
46
- Answer.new(i)
47
- end
44
+ def questions(*ids, **params)
45
+ objectify Question, ids, **params
46
+ end
47
+
48
+ def question(id, **params)
49
+ questions(id, **params).first
50
+ end
51
+
52
+ def answers(*ids, **params)
53
+ objectify Answer, ids, **params
54
+ end
55
+
56
+ def answer(id, **params)
57
+ answers(id, **params).first
58
+ end
59
+
60
+ def comments(*ids, **params)
61
+ objectify Comment, ids, **params
62
+ end
63
+
64
+ def comment(id, **params)
65
+ comments(id, **params).first
66
+ end
67
+
68
+ def users(*ids, **params)
69
+ objectify User, ids, **params
70
+ end
71
+
72
+ def user(id, **params)
73
+ users(id, **params).first
48
74
  end
49
75
 
50
76
  private
51
77
 
78
+ def objectify(type, ids = "", uri: nil, **params)
79
+ return if ids == ""
80
+ uri = "#{type.to_s.split('::').last.downcase}s" if uri.nil?
81
+ json("#{uri}/#{Array(ids).join(';')}", **params).map do |i|
82
+ type.new(i)
83
+ end
84
+ end
85
+
52
86
  def json(uri, **params)
87
+ params = @params.merge(params)
53
88
  throw "No site specified" if params[:site].nil?
54
89
  backoff_for = @backoff-Time.now
55
90
  backoff_for = 0 if backoff_for <= 0
56
91
  if backoff_for > 0
57
- puts "Backing off for #{backoff_for}"
92
+ @logger.warn "Backing off for #{backoff_for}"
58
93
  sleep backoff_for+2
59
- puts "Finished backing off!"
94
+ @logger.warn "Finished backing off!"
60
95
  end
61
96
  params = @params.merge(params).merge({key: @key}).map { |k,v| "#{k}=#{v}" }.join('&')
62
- puts "Posting to https://api.stackexchange.com/#{API_VERSION}/#{uri}?#{params}"
97
+ @logger.info "Posting to https://api.stackexchange.com/#{API_VERSION}/#{uri}?#{params}"
63
98
  begin
64
99
  resp_raw = Net::HTTP.get_response(URI("https://api.stackexchange.com/#{API_VERSION}/#{uri}?#{params}")).body
65
100
  rescue Net::OpenTimeout, SocketError => e
101
+ @logger.warn "Got timeout on API request (#{e}). Retrying..."
66
102
  puts "Got timeout on API request (#{e}). Retrying..."
67
103
  sleep 0.3
68
104
  retry
@@ -73,7 +109,7 @@ module SE
73
109
  @logger_json.info "https://api.stackexchange.com/#{API_VERSION}/#{uri}?#{params} => #{resp}"
74
110
  @quota = resp["quota_remaining"]
75
111
  @quota_used += 1
76
- resp["items"]
112
+ Array(resp["items"])
77
113
  end
78
114
  end
79
115
  end
@@ -1,3 +1,5 @@
1
+ require "se/api/types/post"
2
+
1
3
  module SE
2
4
  module API
3
5
  class Answer < Post
@@ -0,0 +1,30 @@
1
+ require "se/api/types/user"
2
+
3
+ module SE
4
+ module API
5
+ class Comment
6
+ attr_reader :body, :link, :id, :post_id, :score, :type, :created_at, :author, :body_markdown, :edited, :post_type
7
+ attr_reader :json
8
+
9
+ def initialize(item_json)
10
+ @json = Hash(item_json)
11
+ @body = @json["body"]
12
+ @body_markdown = @json["body_markdown"]
13
+ @link = @json["link"]
14
+ @edited = (@json["edited"] == "true")
15
+ @post_id = @json["post_id"].to_i
16
+ @post_type = @json["post_type"]
17
+ @score = @json["score"].to_i
18
+ @type = @json["post_type"]
19
+ @id = @json["comment_id"].to_i
20
+ @created_at = @json["creation_date"]
21
+ @author = User.new(@json["owner"])
22
+ end
23
+
24
+ alias_method :user, :author
25
+ alias_method :owner, :author
26
+ alias_method :comment_id, :id
27
+ alias_method :creation_date, :created_at
28
+ end
29
+ end
30
+ end
@@ -1,20 +1,29 @@
1
+ require "se/api/types/user"
2
+
1
3
  module SE
2
4
  module API
3
5
  class Post
4
- attr_reader :body, :title, :link, :author, :score, :type, :id, :last_activity_date
6
+ attr_reader :body, :title, :link, :author, :score, :type, :id, :last_activity_date, :created_at, :updated_at, :last_editor, :comments
5
7
  attr_reader :json
6
8
 
7
9
  def initialize(item_json)
8
- @json = item_json
9
- @body = item_json["body"]
10
- @title = item_json["title"]
11
- @link = item_json["link"]
12
- @score = item_json["score"].to_i
13
- @type = item_json["post_type"]
14
- @id = item_json["id"].to_i
15
- @last_activity_date = item_json["last_activity_date"]
16
- # @author = User.new(item_json["author"])
10
+ @json = Hash(item_json)
11
+ @body = @json["body"]
12
+ @title = @json["title"]
13
+ @link = @json["link"]
14
+ @score = @json["score"].to_i
15
+ @type = @json["post_type"]
16
+ @last_editor = User.new(@json["last_editor"])
17
+ @comments = Array(@json["comments"]&.map { |c| Comment.new(c) })
18
+ @id = (@json["post_id"] || @json["answer_id"] || @json["question_id"]).to_i
19
+ @updated_at = @json["last_activity_date"]
20
+ @created_at = @json["creation_date"]
21
+ @author = User.new(@json["owner"])
17
22
  end
23
+
24
+ alias_method :last_activity_date, :updated_at
25
+ alias_method :user, :author
26
+ alias_method :owner, :author
18
27
  end
19
28
  end
20
29
  end
@@ -1,3 +1,5 @@
1
+ require "se/api/types/post"
2
+
1
3
  module SE
2
4
  module API
3
5
  class Question < Post
@@ -0,0 +1,19 @@
1
+ module SE
2
+ module API
3
+ class User
4
+ attr_reader :json, :accept_rate, :badge_counts, :name, :link, :image, :reputation, :id, :type
5
+
6
+ def initialize(item_json)
7
+ @json = Hash(item_json)
8
+ @accept_rate = @json["accept_rate"]
9
+ @badge_counts = @json["badge_counts"]
10
+ @name = @json["display_name"]
11
+ @link = @json["link"]
12
+ @image = @json["profile_image"]
13
+ @reputation = @json["reputation"]
14
+ @id = @json["user_id"]
15
+ @type = @json["user_type"]
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,5 +1,5 @@
1
1
  module SE
2
2
  module API
3
- VERSION = "0.0.0.beta1"
3
+ VERSION = "0.0.1"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: se-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0.beta1
4
+ version: 0.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - thesecretmaster
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-12-25 00:00:00.000000000 Z
11
+ date: 2018-05-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -70,8 +70,10 @@ files:
70
70
  - bin/setup
71
71
  - lib/se/api.rb
72
72
  - lib/se/api/types/answer.rb
73
+ - lib/se/api/types/comment.rb
73
74
  - lib/se/api/types/post.rb
74
75
  - lib/se/api/types/question.rb
76
+ - lib/se/api/types/user.rb
75
77
  - lib/se/api/version.rb
76
78
  - se-api.gemspec
77
79
  homepage: https://github.com/izwick-schachter/se-api
@@ -90,9 +92,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
90
92
  version: '0'
91
93
  required_rubygems_version: !ruby/object:Gem::Requirement
92
94
  requirements:
93
- - - ">"
95
+ - - ">="
94
96
  - !ruby/object:Gem::Version
95
- version: 1.3.1
97
+ version: '0'
96
98
  requirements: []
97
99
  rubyforge_project:
98
100
  rubygems_version: 2.7.3