simple_twitter 1.0.0 → 2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2736729c95b2f5def88674bda64a6fecd397a5f422c829ab8b301ac4a36f216c
4
- data.tar.gz: 530c600f14041e91c7476b1179bf2069f8d35076175d10089b07db642b13c3fe
3
+ metadata.gz: 9efa656f4b989f1702d73b9fc4dcd1526edeb944fd9de450993cea3a359ac980
4
+ data.tar.gz: eb2027e3aaf434de6014f8ad60775af313c6a3bc88dfca3ac350dd5ad4798c91
5
5
  SHA512:
6
- metadata.gz: e216e514b9bcdfd91e600e07137c409b1bd3d84c4eb045a7988b30a29c4b4dea4bb05f39dddf309295c104a640420bd43a7cf5f7f2702b86ea05f13b2df0acda
7
- data.tar.gz: '036388ae7887f3af5b3b625f15dd6ab7e5241502e1af4257ae1b59ed92b3082e406f9246f623d711a9791af9de851d3f0b5870badde6a4e41e4673df75308a06'
6
+ metadata.gz: d7f681333e86714dbf3aba86319761118c002b914f0d45579b9c35bcb0d0937a4a276ee04137c7cc76cdf66ddd25ab057e431420bd3b95b0fa91e411a96925d0
7
+ data.tar.gz: 7c0159dbc2da88fed921c25887488b5c81406ebcb4793ff10bf76de8d447cb5d8d61f7954c0c44a0b766e3ee1828d68f6ef9c9fa2812eaf709ab5f705d678579
data/.env.example ADDED
@@ -0,0 +1,5 @@
1
+ # TWITTER_OAUTH2_BEARER_TOKEN=
2
+ # TWITTER_OAUTH1_API_KEY=
3
+ # TWITTER_OAUTH1_API_SECRET_KEY=
4
+ # TWITTER_OAUTH1_ACCESS_TOKEN=
5
+ # TWITTER_OAUTH1_ACCESS_TOKEN_SECRET=
@@ -0,0 +1,8 @@
1
+ # c.f. https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
2
+ version: 2
3
+
4
+ updates:
5
+ - package-ecosystem: github-actions
6
+ directory: /
7
+ schedule:
8
+ interval: weekly
@@ -0,0 +1,51 @@
1
+ # Simple workflow for deploying static content to GitHub Pages
2
+ name: Deploy static content to Pages
3
+
4
+ on:
5
+ # Runs on pushes targeting the default branch
6
+ push:
7
+ branches:
8
+ - main
9
+
10
+ # Allows you to run this workflow manually from the Actions tab
11
+ workflow_dispatch:
12
+
13
+ # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
14
+ permissions:
15
+ contents: read
16
+ pages: write
17
+ id-token: write
18
+
19
+ # Allow one concurrent deployment
20
+ concurrency:
21
+ group: "pages"
22
+ cancel-in-progress: true
23
+
24
+ jobs:
25
+ # Single deploy job since we're just deploying
26
+ deploy:
27
+ environment:
28
+ name: github-pages
29
+ url: ${{ steps.deployment.outputs.page_url }}
30
+ runs-on: ubuntu-latest
31
+ steps:
32
+ - name: Checkout
33
+ uses: actions/checkout@v3
34
+
35
+ - uses: ruby/setup-ruby@v1
36
+ with:
37
+ ruby-version: ruby
38
+ bundler-cache: true
39
+
40
+ - run: bundle exec yard
41
+
42
+ - name: Setup Pages
43
+ uses: actions/configure-pages@v3
44
+ - name: Upload artifact
45
+ uses: actions/upload-pages-artifact@v2
46
+ with:
47
+ # Upload entire repository
48
+ path: './doc'
49
+ - name: Deploy to GitHub Pages
50
+ id: deployment
51
+ uses: actions/deploy-pages@main
@@ -0,0 +1,48 @@
1
+ name: test
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request:
8
+ types:
9
+ - opened
10
+ - synchronize
11
+ - reopened
12
+ schedule:
13
+ - cron: "0 10 * * 5" # JST 19:00 (Fri)
14
+
15
+ jobs:
16
+ test:
17
+ runs-on: ubuntu-latest
18
+
19
+ strategy:
20
+ fail-fast: false
21
+
22
+ matrix:
23
+ ruby:
24
+ - "2.3"
25
+ - "2.4"
26
+ - "2.5"
27
+ - "2.6"
28
+ - "2.7"
29
+ - "3.0"
30
+ - "3.1"
31
+ - "3.2"
32
+
33
+ steps:
34
+ - uses: actions/checkout@v3
35
+
36
+ - uses: ruby/setup-ruby@v1
37
+ with:
38
+ ruby-version: ${{ matrix.ruby }}
39
+ bundler-cache: true
40
+
41
+ - name: bundle update
42
+ run: |
43
+ set -xe
44
+ bundle config path vendor/bundle
45
+ bundle update --jobs $(nproc) --retry 3
46
+
47
+ - run: bundle exec rspec
48
+ - run: bundle exec yard --fail-on-warning
data/.gitignore CHANGED
@@ -6,3 +6,5 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ Gemfile.lock
10
+ .env
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/.yardopts ADDED
@@ -0,0 +1,5 @@
1
+ --markup markdown
2
+ --hide-void-return
3
+ -
4
+ CHANGELOG.md
5
+ LICENSE.txt
data/CHANGELOG.md CHANGED
@@ -1,3 +1,125 @@
1
+ ## Unreleased
2
+ https://github.com/yhara/simple_twitter/compare/v2.1.0...main
3
+
4
+ ## v2.1.0 (2023-07-22)
5
+ https://github.com/yhara/simple_twitter/compare/v2.0.0...v2.1.0
6
+
7
+ * Support media uploading
8
+ * https://github.com/yhara/simple_twitter/pull/26
9
+ * Add User-Agent
10
+ * https://github.com/yhara/simple_twitter/pull/27
11
+
12
+ ## v2.0.0 (2023-07-17)
13
+ https://github.com/yhara/simple_twitter/compare/v1.0.0...v2.0.0
14
+
15
+ ### :bomb: [BREAKING CHANGE] positional args to keywords args
16
+ Since v2.0, the positional arguments of the following methods are now keyword arguments.
17
+
18
+ | v1.0 | v2.0+ |
19
+ | ---------------------------------------------------- | ------------------------------------------------------------- |
20
+ | `SimpleTwitter::Client#get(url, params = {})` | `SimpleTwitter::Client#get(url, params: {}, json: {})` |
21
+ | `SimpleTwitter::Client#get_raw(url, params = {})` | `SimpleTwitter::Client#get_raw(url, params: {}, json: {})` |
22
+ | `SimpleTwitter::Client#post(url, params = {})` | `SimpleTwitter::Client#post(url, params: {}, json: {})` |
23
+ | `SimpleTwitter::Client#post_raw(url, params = {})` | `SimpleTwitter::Client#post_raw(url, params: {}, json: {})` |
24
+ | `SimpleTwitter::Client#put(url, params = {})` | `SimpleTwitter::Client#put(url, params: {}, json: {})` |
25
+ | `SimpleTwitter::Client#put_raw(url, params = {})` | `SimpleTwitter::Client#put_raw(url, params: {}, json: {})` |
26
+ | `SimpleTwitter::Client#delete(url, params = {})` | `SimpleTwitter::Client#delete(url, params: {}, json: {})` |
27
+ | `SimpleTwitter::Client#delete_raw(url, params = {})` | `SimpleTwitter::Client#delete_raw(url, params: {}, json: {})` |
28
+
29
+ Please modify as follows when you upgrade from v1.0 :pray:
30
+
31
+ Before (v1.0)
32
+
33
+ ```ruby
34
+ client.get("https://api.twitter.com/2/tweets", ids: "1302127884039909376,1369885448319889409")
35
+ ```
36
+
37
+ After (v2.0+)
38
+
39
+ ```ruby
40
+ client.get("https://api.twitter.com/2/tweets", params: { ids: "1302127884039909376,1369885448319889409" })
41
+ ```
42
+
43
+ If only 1 argument was used (e.g. `client.get("https://api.twitter.com/2/users/me")`), no modification is required.
44
+
45
+ See more.
46
+
47
+ * https://github.com/yhara/simple_twitter/pull/3
48
+ * https://github.com/yhara/simple_twitter/pull/19
49
+
50
+ ### :bomb: [BREAKING CHANGE] raise Error when Twitter API returned error
51
+ Until v1.0, even if the Twitter API returns an error, Ruby does not throw an error, so it is considered a normal exit.
52
+
53
+ This is confusing, so when the API returns an error, Ruby also raises an error.
54
+
55
+ Before (v1.0)
56
+
57
+ ```ruby
58
+ client = SimpleTwitter::Client.new(bearer_token: "dummy")
59
+ client.get("https://api.twitter.com/2/users/me")
60
+ #=>
61
+ {:title=>"Unsupported Authentication",
62
+ :detail=>
63
+ "Authenticating with OAuth 2.0 Application-Only is forbidden for this endpoint. Supported authentication types are [OAuth 1.0a User Context, OAuth 2.0 User Context].",
64
+ :type=>"https://api.twitter.com/2/problems/unsupported-authentication",
65
+ :status=>403}
66
+ ```
67
+
68
+ After (v2.0+)
69
+
70
+ ```ruby
71
+ client = SimpleTwitter::Client.new(bearer_token: "dummy")
72
+ client.get("https://api.twitter.com/2/users/me")
73
+ /path/to/simple_twitter/lib/simple_twitter.rb:96:in `parse_response': Unsupported Authentication (status 403) (SimpleTwitter::ClientError)
74
+ from (eval):6:in `get'
75
+ from (irb):2:in `<main>'
76
+ from ./bin/console:15:in `<main>'
77
+ ```
78
+
79
+ Detailed error details can be obtained as follows
80
+
81
+ ```ruby
82
+ begin
83
+ client = SimpleTwitter::Client.new(bearer_token: "invalid_bearer_token")
84
+ client.get("https://api.twitter.com/2/users/me")
85
+ rescue SimpleTwitter::Error => error
86
+ error.raw_response.class
87
+ #=> HTTP::Response
88
+
89
+ error.raw_response.code
90
+ #=> 403
91
+
92
+ error.body[:title]
93
+ # => "Unsupported Authentication"
94
+ end
95
+ ```
96
+
97
+ See more.
98
+
99
+ * https://github.com/yhara/simple_twitter/pull/2
100
+ * https://github.com/yhara/simple_twitter/pull/15
101
+
102
+ ### Features
103
+ - Enabled rubygems_mfa_required
104
+ - https://github.com/yhara/simple_twitter/pull/9
105
+ - Add changelog_uri to gemspec
106
+ - https://github.com/yhara/simple_twitter/pull/10
107
+ - Write YARD comment and publish to Pages
108
+ - https://github.com/yhara/simple_twitter/pull/13
109
+ - Add documentation_uri to gemspec metadata
110
+ - https://github.com/yhara/simple_twitter/pull/16
111
+
112
+ ### Others
113
+ - Add @sue445 as an author
114
+ - https://github.com/yhara/simple_twitter/pull/6
115
+ - Add tests and CI
116
+ - https://github.com/yhara/simple_twitter/pull/7
117
+ - https://github.com/yhara/simple_twitter/pull/12
118
+ - Tweak doc
119
+ - https://github.com/yhara/simple_twitter/pull/17
120
+ - https://github.com/yhara/simple_twitter/pull/18
121
+ - https://github.com/yhara/simple_twitter/pull/20
122
+
1
123
  ## v1.0.0 (2021-03-28)
2
124
 
3
125
  - initial release
data/README.md CHANGED
@@ -2,6 +2,9 @@
2
2
 
3
3
  Dead simple Twitter API client. Supports both v1 and v2
4
4
 
5
+ [![Gem Version](https://badge.fury.io/rb/simple_twitter.svg)](https://badge.fury.io/rb/simple_twitter)
6
+ [![test](https://github.com/yhara/simple_twitter/actions/workflows/test.yml/badge.svg)](https://github.com/yhara/simple_twitter/actions/workflows/test.yml)
7
+
5
8
  ## Installation
6
9
 
7
10
  Add this line to your application's Gemfile:
@@ -25,7 +28,7 @@ require 'simple_twitter'
25
28
 
26
29
  client = SimpleTwitter::Client.new(bearer_token: "...")
27
30
  pp client.get("https://api.twitter.com/2/tweets",
28
- ids: "1302127884039909376,1369885448319889409")
31
+ params: { ids: "1302127884039909376,1369885448319889409" })
29
32
  ```
30
33
 
31
34
  Result:
@@ -55,11 +58,67 @@ client = SimpleTwitter::Client.new(
55
58
  access_token_secret: config[:access_token_secret],
56
59
  )
57
60
  pp client.post("https://api.twitter.com/1.1/statuses/update.json",
58
- status: "Test.")
61
+ params: { status: "Test." })
59
62
  ```
60
63
 
61
64
  You can get the access_token and access_token_secret for your own at the Twitter Developer Portal. For other users, you need to get them via OAuth (out of scope of this gem.)
62
65
 
66
+ ### Post with JSON body
67
+ Since Twitter API v2, POST must be sent as JSON body
68
+
69
+ e.g.https://developer.twitter.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/post-tweets
70
+
71
+ Send using the `json` argument.
72
+
73
+ e.g.
74
+
75
+ ```ruby
76
+ client = SimpleTwitter::Client.new(bearer_token: ENV["ACCESS_TOKEN"])
77
+ client.post("https://api.twitter.com/2/tweets", json: { text: "Hello twitter!" })
78
+ ```
79
+
80
+ ### Upload media
81
+ If you want to tweet with an image, you need to do the following steps
82
+
83
+ 1. Upload image as media
84
+ * c.f. https://developer.twitter.com/en/docs/twitter-api/v1/media/upload-media/api-reference/post-media-upload
85
+ 2. Tweet with media
86
+ * c.f. https://developer.twitter.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/post-tweets
87
+
88
+ e.g.
89
+
90
+ ```ruby
91
+ config = (load from yaml or something)
92
+ client = SimpleTwitter::Client.new(
93
+ api_key: config[:api_key],
94
+ api_secret_key: config[:api_secret_key],
95
+ access_token: config[:access_token],
96
+ access_token_secret: config[:access_token_secret],
97
+ )
98
+
99
+ # Upload image as media
100
+ media = client.post(
101
+ "https://upload.twitter.com/1.1/media/upload.json",
102
+ form: {
103
+ media: HTTP::FormData::File.new("/path/to/image.png")
104
+ }
105
+ )
106
+ # =>
107
+ # {:media_id=>12345678901234567890,
108
+ # :media_id_string=>"12345678901234567890",
109
+ # :size=>60628,
110
+ # :expires_after_secs=>86400,
111
+ # :image=>{:image_type=>"image/png", :w=>400, :h=>400}}
112
+
113
+ # Tweet with media
114
+ client.post("https://api.twitter.com/2/tweets",
115
+ json: {
116
+ text: "Test tweet with image",
117
+ media: { media_ids: [media[:media_id_string]] },
118
+ }
119
+ )
120
+ ```
121
+
63
122
  ### Advanced
64
123
 
65
124
  If you want the raw json string or use streaming API, use `get_raw`, `post_raw`, etc. which returns `HTTP::Response` of the [http gem](https://github.com/httprb/http).
@@ -77,16 +136,42 @@ end
77
136
  Some API parameters has `.` in its name (eg. `tweet.fields`.) Did you know that in Ruby you can include `.` in a hash key if quoted? :-)
78
137
 
79
138
  ```rb
80
- tweets = @client.get("https://api.twitter.com/2/users/#{id}/tweets", {
139
+ tweets = @client.get("https://api.twitter.com/2/users/#{id}/tweets", params: {
81
140
  expansions: "author_id",
82
141
  max_results: 100,
83
142
  "tweet.fields": "author_id,created_at,referenced_tweets,text",
84
143
  })
85
144
  ```
86
145
 
146
+ ### Detailed error details
147
+ If an error is returned from the API, you may need more information.
148
+
149
+ In such cases, you can retrieve it as follows.
150
+
151
+ ```ruby
152
+ begin
153
+ client = SimpleTwitter::Client.new(bearer_token: "invalid_bearer_token")
154
+ client.get("https://api.twitter.com/2/users/me")
155
+ rescue SimpleTwitter::Error => error
156
+ error.raw_response.class
157
+ #=> HTTP::Response
158
+
159
+ error.raw_response.code
160
+ #=> 403
161
+
162
+ error.body[:title]
163
+ # => "Unsupported Authentication"
164
+ end
165
+ ```
166
+
167
+ See more. [SimpleTwitter::Error](https://yhara.github.io/simple_twitter/SimpleTwitter/Error.html)
168
+
169
+ ## API Reference
170
+ See https://yhara.github.io/simple_twitter/
171
+
87
172
  ## Contributing
88
173
 
89
- Bug reports and pull requests are welcome on GitHub at https://github.com/naclyhara/simple_twitter.
174
+ Bug reports and pull requests are welcome on GitHub at https://github.com/yhara/simple_twitter.
90
175
 
91
176
  ## License
92
177
 
data/bin/console CHANGED
@@ -3,6 +3,7 @@
3
3
 
4
4
  require "bundler/setup"
5
5
  require "simple_twitter"
6
+ require "dotenv/load"
6
7
 
7
8
  # You can add fixtures and/or initialization code here to make experimenting
8
9
  # with your gem easier. You can also use a different console, if you like.
@@ -11,5 +12,13 @@ require "simple_twitter"
11
12
  # require "pry"
12
13
  # Pry.start
13
14
 
15
+ @client = SimpleTwitter::Client.new(
16
+ bearer_token: ENV["TWITTER_OAUTH2_BEARER_TOKEN"],
17
+ api_key: ENV["TWITTER_OAUTH1_API_KEY"],
18
+ api_secret_key: ENV["TWITTER_OAUTH1_API_SECRET_KEY"],
19
+ access_token: ENV["TWITTER_OAUTH1_ACCESS_TOKEN"],
20
+ access_token_secret: ENV["TWITTER_OAUTH1_ACCESS_TOKEN_SECRET"],
21
+ )
22
+
14
23
  require "irb"
15
24
  IRB.start(__FILE__)
@@ -0,0 +1,165 @@
1
+ module SimpleTwitter
2
+ # Twitter API Client
3
+ class Client
4
+ # @param bearer_token [String] This requires for OAuth 2
5
+ # @param api_key [String] This requires for OAuth 1.0a
6
+ # @param api_secret_key [String] This requires for OAuth 1.0a
7
+ # @param access_token [String] This requires for OAuth 1.0a
8
+ # @param access_token_secret [String] This requires for OAuth 1.0a
9
+ def initialize(bearer_token: nil,
10
+ api_key: nil,
11
+ api_secret_key: nil,
12
+ access_token: nil,
13
+ access_token_secret: nil)
14
+ if bearer_token
15
+ @bearer_token = bearer_token
16
+ else
17
+ @oauth_params = {
18
+ consumer_key: api_key,
19
+ consumer_secret: api_secret_key,
20
+ token: access_token,
21
+ token_secret: access_token_secret,
22
+ }
23
+ end
24
+ end
25
+
26
+ # @!method get(url, params: {}, json: {}, form: {})
27
+ # Call Twitter API with GET method
28
+ # @param url [String]
29
+ # @param params [Hash] Send this arg as a query string. (e.g. `?name1=value1&name2=value2`)
30
+ # @param json [Hash] Send this arg as JSON request body with `Content-Type: application/json` header
31
+ # @param form [Hash] Send this arg as form-data request body with `Content-Type: multipart/form-data` header
32
+ # @return [Hash] parsed json data
33
+ # @raise [SimpleTwitter::ClientError] Twitter API returned 4xx error
34
+ # @raise [SimpleTwitter::ServerError] Twitter API returned 5xx error
35
+
36
+ # @!method get_raw(url, params: {}, json: {}, form: {})
37
+ # Call Twitter API with GET method
38
+ # @param url [String]
39
+ # @param params [Hash] Send this arg as a query string. (e.g. `?name1=value1&name2=value2`)
40
+ # @param json [Hash] Send this arg as JSON request body with `Content-Type: application/json` header
41
+ # @param form [Hash] Send this arg as form-data request body with `Content-Type: multipart/form-data` header
42
+ # @return [HTTP::Response]
43
+
44
+ # @!method post(url, params: {}, json: {}, form: {})
45
+ # Call Twitter API with POST method
46
+ # @param url [String]
47
+ # @param params [Hash] Send this arg as a query string. (e.g. `?name1=value1&name2=value2`)
48
+ # @param json [Hash] Send this arg as JSON request body with `Content-Type: application/json` header
49
+ # @param form [Hash] Send this arg as form-data request body with `Content-Type: multipart/form-data` header
50
+ # @return [Hash] parsed json data
51
+ # @raise [SimpleTwitter::ClientError] Twitter API returned 4xx error
52
+ # @raise [SimpleTwitter::ServerError] Twitter API returned 5xx error
53
+
54
+ # @!method post_raw(url, params: {}, json: {}, form: {})
55
+ # Call Twitter API with POST method
56
+ # @param url [String]
57
+ # @param params [Hash] Send this arg as a query string. (e.g. `?name1=value1&name2=value2`)
58
+ # @param json [Hash] Send this arg as JSON request body with `Content-Type: application/json` header
59
+ # @param form [Hash] Send this arg as form-data request body with `Content-Type: multipart/form-data` header
60
+ # @return [HTTP::Response]
61
+
62
+ # @!method put(url, params: {}, json: {}, form: {})
63
+ # Call Twitter API with PUT method
64
+ # @param url [String]
65
+ # @param params [Hash] Send this arg as a query string. (e.g. `?name1=value1&name2=value2`)
66
+ # @param json [Hash] Send this arg as JSON request body with `Content-Type: application/json` header
67
+ # @param form [Hash] Send this arg as form-data request body with `Content-Type: multipart/form-data` header
68
+ # @return [Hash] parsed json data
69
+ # @raise [SimpleTwitter::ClientError] Twitter API returned 4xx error
70
+ # @raise [SimpleTwitter::ServerError] Twitter API returned 5xx error
71
+
72
+ # @!method put_raw(url, params: {}, json: {}, form: {})
73
+ # Call Twitter API with PUT method
74
+ # @param url [String]
75
+ # @param params [Hash] Send this arg as a query string. (e.g. `?name1=value1&name2=value2`)
76
+ # @param json [Hash] Send this arg as JSON request body with `Content-Type: application/json` header
77
+ # @param form [Hash] Send this arg as form-data request body with `Content-Type: multipart/form-data` header
78
+ # @return [HTTP::Response]
79
+
80
+ # @!method delete(url, params: {}, json: {}, form: {})
81
+ # Call Twitter API with DELETE method
82
+ # @param url [String]
83
+ # @param params [Hash] Send this arg as a query string. (e.g. `?name1=value1&name2=value2`)
84
+ # @param json [Hash] Send this arg as JSON request body with `Content-Type: application/json` header
85
+ # @param form [Hash] Send this arg as form-data request body with `Content-Type: multipart/form-data` header
86
+ # @return [Hash] parsed json data
87
+ # @raise [SimpleTwitter::ClientError] Twitter API returned 4xx error
88
+ # @raise [SimpleTwitter::ServerError] Twitter API returned 5xx error
89
+
90
+ # @!method delete_raw(url, params: {}, json: {}, form: {})
91
+ # Call Twitter API with DELETE method
92
+ # @param url [String]
93
+ # @param params [Hash] Send this arg as a query string. (e.g. `?name1=value1&name2=value2`)
94
+ # @param json [Hash] Send this arg as JSON request body with `Content-Type: application/json` header
95
+ # @param form [Hash] Send this arg as form-data request body with `Content-Type: multipart/form-data` header
96
+ # @return [HTTP::Response]
97
+
98
+ %i[get post put delete].each do |m|
99
+ class_eval <<~EOD
100
+ def #{m}(url, params: {}, json: {}, form: {})
101
+ res = #{m}_raw(url, params: params, json: json, form: form)
102
+ parse_response(res)
103
+ end
104
+
105
+ def #{m}_raw(url, params: {}, json: {}, form: {})
106
+ args = create_http_args(params: params, json: json, form: form)
107
+ http(:#{m}, url, params).#{m}(url, args)
108
+ end
109
+ EOD
110
+ end
111
+
112
+ private
113
+
114
+ # @param params [Hash] Send this arg as a query string. (e.g. `?name1=value1&name2=value2`)
115
+ # @param json [Hash] Send this arg as JSON request body with `Content-Type: application/json` header
116
+ # @param form [Hash] Send this arg as form-data request body with `Content-Type: multipart/form-data` header
117
+ # @return [Hash<Symbol, Object>]
118
+ def create_http_args(params:, json:, form:)
119
+ args = {
120
+ params: params,
121
+ headers: {
122
+ "User-Agent" => "simple_twitter v#{SimpleTwitter::VERSION} (https://github.com/yhara/simple_twitter)",
123
+ },
124
+ }
125
+ args[:json] = json unless json.empty?
126
+ args[:form] = form unless form.empty?
127
+ args
128
+ end
129
+
130
+ # @param method [Symbol]
131
+ # @param url [String]
132
+ # @param params [Hash<Symbol, String>]
133
+ # @return [HTTP::Client]
134
+ def http(method, url, params)
135
+ HTTP.auth(auth_header(method, url, params))
136
+ end
137
+
138
+ # @param method [Symbol]
139
+ # @param url [String]
140
+ # @param params [Hash<Symbol, String>]
141
+ # @return [String]
142
+ def auth_header(method, url, params)
143
+ if @bearer_token
144
+ "Bearer #{@bearer_token}"
145
+ else
146
+ SimpleOAuth::Header.new(method, url, params, @oauth_params).to_s
147
+ end
148
+ end
149
+
150
+ # @param res [HTTP::Response]
151
+ # @return [Hash] parsed json data
152
+ # @raise [SimpleTwitter::ClientError] Twitter API returned 4xx error
153
+ # @raise [SimpleTwitter::ServerError] Twitter API returned 5xx error
154
+ def parse_response(res)
155
+ case res.code.to_i / 100
156
+ when 4
157
+ raise ClientError, res
158
+ when 5
159
+ raise ServerError, res
160
+ end
161
+
162
+ JSON.parse(res.to_s, symbolize_names: true)
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,5 @@
1
+ module SimpleTwitter
2
+ # Twitter API 4xx error
3
+ class ClientError < Error
4
+ end
5
+ end
@@ -0,0 +1,29 @@
1
+ module SimpleTwitter
2
+ # Error base class
3
+ class Error < StandardError
4
+ # @!attribute [r] raw_response
5
+ # @return [HTTP::Response] raw error response
6
+ attr_reader :raw_response
7
+
8
+ # @!attribute [r] body
9
+ # @return [Hash<Symbol, String>] error response body
10
+ attr_reader :body
11
+
12
+ # @param raw_response [HTTP::Response] raw error response from Twitter API
13
+ def initialize(raw_response)
14
+ @raw_response = raw_response
15
+
16
+ begin
17
+ @body = JSON.parse(raw_response.to_s, symbolize_names: true)
18
+
19
+ title = @body[:title] || "Unknown error"
20
+ title << " (status #{raw_response.code})"
21
+
22
+ super(title)
23
+ rescue JSON::ParserError => e
24
+ # Twitter doesn't returns json
25
+ super("Unknown error (status #{raw_response.code})")
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,5 @@
1
+ module SimpleTwitter
2
+ # Twitter API 5xx error
3
+ class ServerError < Error
4
+ end
5
+ end
@@ -1,3 +1,3 @@
1
1
  module SimpleTwitter
2
- VERSION = "1.0.0"
2
+ VERSION = "2.1.0"
3
3
  end
@@ -1,59 +1,11 @@
1
1
  require 'http'
2
2
  require 'simple_oauth'
3
3
 
4
- module SimpleTwitter
5
- class Client
6
- def initialize(bearer_token: nil,
7
- api_key: nil,
8
- api_secret_key: nil,
9
- access_token: nil,
10
- access_token_secret: nil)
11
- if bearer_token
12
- @bearer_token = bearer_token
13
- else
14
- @oauth_params = {
15
- consumer_key: api_key,
16
- consumer_secret: api_secret_key,
17
- token: access_token,
18
- token_secret: access_token_secret,
19
- }
20
- end
21
- end
22
-
23
- %i[get post put delete].each do |m|
24
- class_eval <<~EOD
25
- # @return [Object] parsed json data
26
- def #{m}(url, params={})
27
- JSON.parse(#{m}_raw(url, params).to_s, symbolize_names: true)
28
- end
29
-
30
- # @return [HTTP::Response]
31
- def #{m}_raw(url, params={})
32
- http(:#{m}, url, params).#{m}(url, params: params)
33
- end
34
- EOD
35
- end
4
+ require_relative "simple_twitter/version"
36
5
 
37
- private
38
-
39
- # @param method [Symbol]
40
- # @param url [String]
41
- # @param params [Hash<Symbol, String>]
42
- # @return [HTTP::Request]
43
- def http(method, url, params)
44
- HTTP.auth(auth_header(method, url, params))
45
- end
46
-
47
- # @param method [Symbol]
48
- # @param url [String]
49
- # @param params [Hash<Symbol, String>]
50
- # @return [String]
51
- def auth_header(method, url, params)
52
- if @bearer_token
53
- "Bearer #{@bearer_token}"
54
- else
55
- SimpleOAuth::Header.new(method, url, params, @oauth_params).to_s
56
- end
57
- end
58
- end
6
+ module SimpleTwitter
7
+ autoload :Client, "simple_twitter/client"
8
+ autoload :ClientError, "simple_twitter/client_error"
9
+ autoload :Error, "simple_twitter/error"
10
+ autoload :ServerError, "simple_twitter/server_error"
59
11
  end
@@ -3,8 +3,8 @@ require_relative "lib/simple_twitter/version"
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "simple_twitter"
5
5
  spec.version = SimpleTwitter::VERSION
6
- spec.authors = ["Yutaka HARA"]
7
- spec.email = ["yutaka.hara+github@gmail.com"]
6
+ spec.authors = ["Yutaka HARA", "sue445"]
7
+ spec.email = ["yutaka.hara+github@gmail.com", "sue445fukuoka@gmail.com"]
8
8
 
9
9
  spec.summary = "Dead simple client for Twitter API v1/v2"
10
10
  spec.description = "Dead simple client for Twitter API (supports both v1 and v2)"
@@ -14,7 +14,9 @@ Gem::Specification.new do |spec|
14
14
 
15
15
  spec.metadata["homepage_uri"] = spec.homepage
16
16
  spec.metadata["source_code_uri"] = spec.homepage
17
- #spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
17
+ spec.metadata["changelog_uri"] = spec.homepage + "/blob/main/CHANGELOG.md"
18
+ spec.metadata["documentation_uri"] = "https://yhara.github.io/simple_twitter/"
19
+ spec.metadata["rubygems_mfa_required"] = "true"
18
20
 
19
21
  # Specify which files should be added to the gem when it is released.
20
22
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
@@ -25,6 +27,12 @@ Gem::Specification.new do |spec|
25
27
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
26
28
  spec.require_paths = ["lib"]
27
29
 
28
- spec.add_dependency "http", "~> 4"
29
- spec.add_dependency "simple_oauth", "~> 0.3.1"
30
+ spec.add_dependency "http", ">= 4"
31
+ spec.add_dependency "simple_oauth", ">= 0.3.1"
32
+
33
+ spec.add_development_dependency "dotenv"
34
+ spec.add_development_dependency "rspec"
35
+ spec.add_development_dependency "rspec-its"
36
+ spec.add_development_dependency "webmock"
37
+ spec.add_development_dependency "yard"
30
38
  end
metadata CHANGED
@@ -1,51 +1,129 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_twitter
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yutaka HARA
8
+ - sue445
8
9
  autorequire:
9
10
  bindir: exe
10
11
  cert_chain: []
11
- date: 2021-03-28 00:00:00.000000000 Z
12
+ date: 2023-07-21 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: http
15
16
  requirement: !ruby/object:Gem::Requirement
16
17
  requirements:
17
- - - "~>"
18
+ - - ">="
18
19
  - !ruby/object:Gem::Version
19
20
  version: '4'
20
21
  type: :runtime
21
22
  prerelease: false
22
23
  version_requirements: !ruby/object:Gem::Requirement
23
24
  requirements:
24
- - - "~>"
25
+ - - ">="
25
26
  - !ruby/object:Gem::Version
26
27
  version: '4'
27
28
  - !ruby/object:Gem::Dependency
28
29
  name: simple_oauth
29
30
  requirement: !ruby/object:Gem::Requirement
30
31
  requirements:
31
- - - "~>"
32
+ - - ">="
32
33
  - !ruby/object:Gem::Version
33
34
  version: 0.3.1
34
35
  type: :runtime
35
36
  prerelease: false
36
37
  version_requirements: !ruby/object:Gem::Requirement
37
38
  requirements:
38
- - - "~>"
39
+ - - ">="
39
40
  - !ruby/object:Gem::Version
40
41
  version: 0.3.1
42
+ - !ruby/object:Gem::Dependency
43
+ name: dotenv
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rspec
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: rspec-its
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: webmock
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ - !ruby/object:Gem::Dependency
99
+ name: yard
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
41
112
  description: Dead simple client for Twitter API (supports both v1 and v2)
42
113
  email:
43
114
  - yutaka.hara+github@gmail.com
115
+ - sue445fukuoka@gmail.com
44
116
  executables: []
45
117
  extensions: []
46
118
  extra_rdoc_files: []
47
119
  files:
120
+ - ".env.example"
121
+ - ".github/dependabot.yml"
122
+ - ".github/workflows/pages.yml"
123
+ - ".github/workflows/test.yml"
48
124
  - ".gitignore"
125
+ - ".rspec"
126
+ - ".yardopts"
49
127
  - CHANGELOG.md
50
128
  - Gemfile
51
129
  - LICENSE.txt
@@ -54,6 +132,10 @@ files:
54
132
  - bin/console
55
133
  - bin/setup
56
134
  - lib/simple_twitter.rb
135
+ - lib/simple_twitter/client.rb
136
+ - lib/simple_twitter/client_error.rb
137
+ - lib/simple_twitter/error.rb
138
+ - lib/simple_twitter/server_error.rb
57
139
  - lib/simple_twitter/version.rb
58
140
  - simple_twitter.gemspec
59
141
  homepage: https://github.com/yhara/simple_twitter
@@ -62,6 +144,9 @@ licenses:
62
144
  metadata:
63
145
  homepage_uri: https://github.com/yhara/simple_twitter
64
146
  source_code_uri: https://github.com/yhara/simple_twitter
147
+ changelog_uri: https://github.com/yhara/simple_twitter/blob/main/CHANGELOG.md
148
+ documentation_uri: https://yhara.github.io/simple_twitter/
149
+ rubygems_mfa_required: 'true'
65
150
  post_install_message:
66
151
  rdoc_options: []
67
152
  require_paths:
@@ -77,7 +162,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
77
162
  - !ruby/object:Gem::Version
78
163
  version: '0'
79
164
  requirements: []
80
- rubygems_version: 3.2.3
165
+ rubygems_version: 3.4.10
81
166
  signing_key:
82
167
  specification_version: 4
83
168
  summary: Dead simple client for Twitter API v1/v2