yatc 0.0.1

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.
Files changed (5) hide show
  1. checksums.yaml +7 -0
  2. data/lib/exceptions.rb +5 -0
  3. data/lib/settings.rb +7 -0
  4. data/lib/yatc.rb +171 -0
  5. metadata +46 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 431b6e6f0771b397399547281003d61fdc83722c
4
+ data.tar.gz: 59a0209401816eb3b4a8030f1d282cdfdbf7b4cf
5
+ SHA512:
6
+ metadata.gz: b57a7ce75fb36fd76093b575640350f5dc7907ee37367266575e670534292eba7100863727257808f4f6b6d9b51937844a38a865dd5097ac366faa6e22a300f0
7
+ data.tar.gz: 54a3c1d3975799b47aad8530337d9a45fa2c81de5c7351874e1cf311956f7b9e2659769fe4bad67bfd67bd1214bf0193d64772867c73ae68897a35a6d67dc080
@@ -0,0 +1,5 @@
1
+ class AuthenticationError < StandardError
2
+ end
3
+
4
+ class RateLimitExceeded < StandardError
5
+ end
@@ -0,0 +1,7 @@
1
+ # This module contains constants used by the Twitter client.
2
+ module Yatc
3
+ module Settings
4
+ MAX_FOLLOWER_IDS = 5000
5
+ MAX_TWEETS = 200
6
+ end
7
+ end
@@ -0,0 +1,171 @@
1
+ require 'rest_client'
2
+ require 'open-uri'
3
+ require 'base64'
4
+
5
+ require_relative 'settings'
6
+ require_relative 'exceptions'
7
+
8
+ BASE_URL = 'https://api.twitter.com/1.1'
9
+
10
+ # This is the Twitter client class that will allow you to query the Twitter API.
11
+ class TwitterClient
12
+ attr_accessor :consumer_key
13
+ attr_accessor :consumer_secret
14
+ attr_accessor :should_wait
15
+ attr_accessor :access_token
16
+
17
+ def test_access(ck, cs)
18
+ !request_access_token(ck, cs).empty?
19
+ end
20
+
21
+ def followers_ids(user, count = 5000)
22
+ params = {}
23
+ if user.class == Fixnum
24
+ params[:user_id] = user
25
+ else
26
+ params[:screen_name] = user
27
+ end
28
+ ids = []
29
+ cursor = nil
30
+ while count > 0
31
+ params[:count] = [Yatc::Settings::MAX_FOLLOWER_IDS, count].min
32
+ count -= params[:count]
33
+ unless cursor.nil?
34
+ params[:cursor] = cursor
35
+ end
36
+
37
+ encoded_params = encode_params(params)
38
+ url = "#{BASE_URL}/followers/ids.json?#{encoded_params}"
39
+ data = JSON.parse(execute(:get, url, access_token))
40
+ ids += data['ids']
41
+ cursor = data['next_cursor']
42
+ end
43
+ ids
44
+ end
45
+
46
+ def friends_ids(user, count = 5000)
47
+ params = {}
48
+ if user.class == Fixnum
49
+ params[:user_id] = user
50
+ else
51
+ params[:screen_name] = user
52
+ end
53
+ ids = []
54
+ cursor = nil
55
+ while count > 0
56
+ params[:count] = [Yatc::Settings::MAX_FOLLOWER_IDS, count].min
57
+ count -= params[:count]
58
+ unless cursor.nil?
59
+ params[:cursor] = cursor
60
+ end
61
+
62
+ encoded_params = encode_params(params)
63
+ url = "#{BASE_URL}/friends/ids.json?#{encoded_params}"
64
+ data = JSON.parse(execute(:get, url, access_token))
65
+ ids += data['ids']
66
+ cursor = data['next_cursor']
67
+ end
68
+ ids
69
+ end
70
+
71
+ def users_show(user)
72
+ params = {}
73
+ if user.class == Fixnum
74
+ params[:user_id] = user
75
+ else
76
+ params[:screen_name] = user
77
+ end
78
+ params = encode_params(params)
79
+ url = "#{BASE_URL}/users/show.json?#{params}"
80
+ JSON.parse(execute(:get, url, access_token))
81
+ end
82
+
83
+ def statuses_user_timeline(user, count = 200)
84
+ params = {}
85
+ if user.class == Fixnum
86
+ params[:user_id] = user
87
+ else
88
+ params[:screen_name] = user
89
+ end
90
+ tweets = []
91
+ max_id = nil
92
+ while count > 0
93
+ params[:count] = [Yatc::Settings::MAX_TWEETS, count].min
94
+ count -= params[:count]
95
+ unless max_id.nil?
96
+ params[:max_id] = max_id
97
+ end
98
+ encoded_params = encode_params(params)
99
+ url = "#{BASE_URL}/statuses/user_timeline.json?#{encoded_params}"
100
+ t = JSON.parse(execute(:get, url, access_token))
101
+ unless t.empty?
102
+ max_id = t.map{ |tweet| tweet['id'] }.min - 1
103
+ end
104
+ tweets += t
105
+ end
106
+ tweets
107
+ end
108
+
109
+ def initialize(ck, cs)
110
+ @consumer_key = ck
111
+ @consumer_secret = cs
112
+ @access_token = request_access_token(consumer_key, consumer_secret)
113
+ end
114
+
115
+ def bearer_token(ck, cs)
116
+ ck = URI.encode(ck)
117
+ cs = URI.encode(cs)
118
+ Base64.strict_encode64(ck + ':' + cs)
119
+ end
120
+
121
+ def request_access_token(ck, cs)
122
+ bearer_token = bearer_token(ck, cs)
123
+ begin
124
+ resp = RestClient::Request.execute(
125
+ method: :post,
126
+ url: 'https://api.twitter.com/oauth2/token',
127
+ headers: {
128
+ 'User-Agent' => 'My twitter App',
129
+ 'Authorization' => "Basic #{bearer_token}",
130
+ 'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8',
131
+ 'Content-Length' => 29,
132
+ 'Accept-Encoding' => 'gzip'
133
+ },
134
+ payload: 'grant_type=client_credentials'
135
+ )
136
+ JSON.parse(resp)['access_token']
137
+ rescue => e
138
+ raise e.http_code == 403 ? AuthenticationError : e
139
+ end
140
+ end
141
+
142
+ private
143
+ def encode_params(params)
144
+ params.map { |k, v| "#{k}=#{v}" }.join('&')
145
+ end
146
+
147
+ def execute(method, url, access_token)
148
+ tries = 0
149
+ begin
150
+ RestClient::Request.execute(
151
+ method: method,
152
+ url: url,
153
+ headers: {
154
+ 'User-Agent' => 'My Twitter App',
155
+ 'Authorization' => "Bearer #{access_token}",
156
+ 'Accept-Encoding' => 'gzip'
157
+ }
158
+ )
159
+ rescue RestClient::TooManyRequests => e
160
+ headers = e.response.headers
161
+ if should_wait && headers[:x_rate_limit_reset] && tries == 0
162
+ tries += 1
163
+ delta = (Time.at(headers[:x_rate_limit_reset].to_i) - Time.now).to_i
164
+ sleep(delta + 1)
165
+ retry
166
+ else
167
+ raise RateLimitExceeded.new(e.message)
168
+ end
169
+ end
170
+ end
171
+ end
metadata ADDED
@@ -0,0 +1,46 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yatc
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Rafael Rendón Pablo
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-09-28 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Twitter client.
14
+ email: rafaelrendonpablo@gmail.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/exceptions.rb
20
+ - lib/settings.rb
21
+ - lib/yatc.rb
22
+ homepage: https://github.com/rendon/yatc
23
+ licenses:
24
+ - GNU GPL v3.0
25
+ metadata: {}
26
+ post_install_message:
27
+ rdoc_options: []
28
+ require_paths:
29
+ - lib
30
+ required_ruby_version: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ required_rubygems_version: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ requirements: []
41
+ rubyforge_project:
42
+ rubygems_version: 2.4.8
43
+ signing_key:
44
+ specification_version: 4
45
+ summary: Yet Another Twitter Client
46
+ test_files: []