snapcat 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +6 -0
  3. data/.travis.yml +3 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +194 -0
  7. data/Rakefile +10 -0
  8. data/lib/snapcat.rb +19 -0
  9. data/lib/snapcat/client.rb +189 -0
  10. data/lib/snapcat/crypt.rb +35 -0
  11. data/lib/snapcat/friend.rb +57 -0
  12. data/lib/snapcat/media.rb +81 -0
  13. data/lib/snapcat/requestor.rb +106 -0
  14. data/lib/snapcat/response.rb +43 -0
  15. data/lib/snapcat/snap.rb +80 -0
  16. data/lib/snapcat/snapcat_error.rb +4 -0
  17. data/lib/snapcat/timestamp.rb +17 -0
  18. data/lib/snapcat/user.rb +46 -0
  19. data/snapcat.gemspec +28 -0
  20. data/spec/snapcat/client_spec.rb +217 -0
  21. data/spec/snapcat/crypt_spec.rb +27 -0
  22. data/spec/snapcat/friend_spec.rb +22 -0
  23. data/spec/snapcat/media_spec.rb +61 -0
  24. data/spec/snapcat/response_spec.rb +71 -0
  25. data/spec/snapcat/snap_spec.rb +72 -0
  26. data/spec/snapcat/timestamp_spec.rb +32 -0
  27. data/spec/snapcat/user_spec.rb +40 -0
  28. data/spec/snapcat_spec.rb +4 -0
  29. data/spec/spec_helper.rb +13 -0
  30. data/spec/support/data_helper.rb +20 -0
  31. data/spec/support/fixture.rb +70 -0
  32. data/spec/support/minitest_spec_context.rb +7 -0
  33. data/spec/support/request_stub.rb +322 -0
  34. data/spec/support/response_helper.rb +15 -0
  35. data/spec/support/responses/block_success.json +5 -0
  36. data/spec/support/responses/delete_success.json +5 -0
  37. data/spec/support/responses/login_success.json +91 -0
  38. data/spec/support/responses/logout_success.json +1 -0
  39. data/spec/support/responses/register_failure.json +4 -0
  40. data/spec/support/responses/register_success.json +6 -0
  41. data/spec/support/responses/registeru_failure.json +4 -0
  42. data/spec/support/responses/registeru_success.json +58 -0
  43. data/spec/support/responses/send_snap_success.json +1 -0
  44. data/spec/support/responses/set_display_name_failure.json +4 -0
  45. data/spec/support/responses/set_display_name_success.json +9 -0
  46. data/spec/support/responses/unblock_success.json +10 -0
  47. data/spec/support/responses/update_email_success.json +5 -0
  48. data/spec/support/responses/update_privacy_success.json +5 -0
  49. data/spec/support/responses/updates_success.json +97 -0
  50. data/spec/support/responses/upload_success.json +1 -0
  51. data/spec/support/snaps/image_decrypted.jpg +0 -0
  52. data/spec/support/snaps/image_encrypted.jpg +0 -0
  53. data/spec/support/snaps/video_decrypted.mp4 +0 -0
  54. data/spec/support/snaps/video_encrypted.mp4 +0 -0
  55. data/spec/support/user_experience.rb +20 -0
  56. metadata +218 -0
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe Snapcat::Timestamp do
4
+ before(:each) do
5
+ fake_time = Time.at(1384635477.196865)
6
+ Time.stubs(:now).returns(fake_time)
7
+ end
8
+
9
+ describe '.float' do
10
+ it 'returns timestamp with decimals' do
11
+ timestamp = Snapcat::Timestamp.float
12
+
13
+ timestamp.must_equal 1384635477.196865
14
+ end
15
+ end
16
+
17
+ describe '.macro' do
18
+ it 'returns timestamp with second precision' do
19
+ timestamp = Snapcat::Timestamp.macro
20
+
21
+ timestamp.must_equal 1384635477
22
+ end
23
+ end
24
+
25
+ describe '.micro' do
26
+ it 'returns timestamp with high precision' do
27
+ timestamp = Snapcat::Timestamp.micro
28
+
29
+ timestamp.must_equal 1384635477196
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe Snapcat::User do
4
+ describe '#data=' do
5
+ it 'sets friends' do
6
+ user = Snapcat::User.new
7
+
8
+ user.data = Fixture.user_data
9
+
10
+ user.friends.count.must_equal 1
11
+ user.friends.first.must_be_kind_of Snapcat::Friend
12
+ end
13
+
14
+ it 'sets snaps_received' do
15
+ user = Snapcat::User.new
16
+
17
+ user.data = Fixture.user_data
18
+
19
+ user.snaps_received.count.must_equal 1
20
+ user.snaps_received.first.must_be_kind_of Snapcat::Snap
21
+ end
22
+
23
+ it 'sets snaps_sent' do
24
+ user = Snapcat::User.new
25
+
26
+ user.data = Fixture.user_data
27
+
28
+ user.snaps_sent.count.must_equal 1
29
+ user.snaps_sent.first.must_be_kind_of Snapcat::Snap
30
+ end
31
+
32
+ it 'sets raw data' do
33
+ user = Snapcat::User.new
34
+
35
+ user.data = Fixture.user_data
36
+
37
+ user.data.must_equal Fixture.user_data
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe Snapcat do
4
+ end
@@ -0,0 +1,13 @@
1
+ $:.unshift File.expand_path("../lib", File.dirname(__FILE__))
2
+
3
+ require 'snapcat'
4
+ require 'minitest/autorun'
5
+ require 'minitest/mock'
6
+ require 'minitest/pride'
7
+ require 'minitest/spec'
8
+ require 'mocha/setup'
9
+ require 'webmock/minitest'
10
+
11
+ SPEC_ROOT = File.dirname(__FILE__)
12
+
13
+ Dir["#{SPEC_ROOT}/support/**.rb"].each{ |file| require file }
@@ -0,0 +1,20 @@
1
+ module DataHelper
2
+ extend self
3
+
4
+ def data_for(status, type = :image)
5
+ File.open(
6
+ "#{SPEC_ROOT}/support/snaps/#{type}_#{status}#{file_extension(type)}",
7
+ 'rb'
8
+ ).read
9
+ end
10
+
11
+ private
12
+
13
+ def file_extension(type)
14
+ if type == :image
15
+ '.jpg'
16
+ elsif type == :video
17
+ '.mp4'
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,70 @@
1
+ module Fixture
2
+ extend self
3
+
4
+ BIRTHDAY = '1990-01-30'
5
+ EMAIL = 'meow@meow.com'
6
+ FRIEND_DISPLAY_NAME = 'Henrie McKitten'
7
+ FRIEND_USERNAME = 'catsaregreat'
8
+ FRIEND_TYPE = Snapcat::Friend::Type::CONFIRMED
9
+ MEDIA_ID = 'ILUVKITTENS4~1384804683'
10
+ PASSWORD = 'topsecret'
11
+ RECIPIENT = 'ronnie99'
12
+ RECIPIENTS = %w(ronnie99 jimbo2000)
13
+ SNAP_ID = '519861384740350100r'
14
+ USERNAME = 'iluvkittens'
15
+ VIEW_DURATION = 6
16
+
17
+ def friend_data
18
+ {
19
+ can_see_custom_stories: true,
20
+ display: 'John Smith',
21
+ name: 'jsmith10',
22
+ type: FRIEND_TYPE
23
+ }
24
+ end
25
+
26
+ def snap_data(status = :sent)
27
+ {
28
+ broadcast: 'broadcast',
29
+ broadcast_action_text: 'broadcast_action_text',
30
+ broadcast_hide_timer: 'broadcast_hide_timer',
31
+ broadcast_url: 'broadcast_url',
32
+ c: 'c',
33
+ id: '519861384740350100r',
34
+ m: 0,
35
+ st: 1,
36
+ sts: 1384740350062,
37
+ t: 6,
38
+ ts: 1384740350062
39
+ }.merge(status_specific_snap_data(status))
40
+ end
41
+
42
+ def user_data
43
+ {
44
+ friends: [
45
+ friend_data
46
+ ],
47
+ snaps: [
48
+ snap_data(:sent),
49
+ snap_data(:received)
50
+ ]
51
+ }
52
+ end
53
+
54
+ private
55
+
56
+ def status_specific_snap_data(status)
57
+ if status == :sent
58
+ {
59
+ c_id: 'some_media_id',
60
+ rp: FRIEND_USERNAME,
61
+ sn: USERNAME
62
+ }
63
+ else
64
+ {
65
+ rp: FRIEND_USERNAME,
66
+ sn: USERNAME
67
+ }
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,7 @@
1
+ module MiniTest
2
+ class Spec
3
+ class << self
4
+ alias_method :context, :describe
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,322 @@
1
+ module RequestStub
2
+ extend WebMock::API
3
+ extend self
4
+
5
+ BASE_URI = Snapcat::Requestor.base_uri
6
+ NOW = 1384635477196
7
+ REQUEST_TOKEN = '9309075617c17ae86eefa3e6fca2e344f7e04d8419456a8299b4f814d7c5126b'
8
+
9
+ def stub_all
10
+ stub_basics
11
+ block
12
+ clear_feed
13
+ delete
14
+ fetch_updates
15
+ logout
16
+ media
17
+ register
18
+ registeru
19
+ send_snap_to_multiple
20
+ send_snap_to_single
21
+ set_display_name
22
+ unblock
23
+ update_email
24
+ update_privacy
25
+ upload
26
+ end
27
+
28
+ def upload
29
+ Snapcat::Requestor.any_instance.stubs(:generate_media_id).
30
+ returns(Fixture::MEDIA_ID)
31
+
32
+ request_body = requestify(
33
+ {
34
+ data: DataHelper.data_for(:decrypted)
35
+ },
36
+ username: true
37
+ )
38
+ stub_request(:post, "#{BASE_URI}/upload").with(
39
+ body: request_body
40
+ ).to_return(
41
+ status: 200,
42
+ body: '',
43
+ headers: json_headers
44
+ )
45
+ end
46
+
47
+ def send_snap_to_multiple
48
+ request_body = requestify(
49
+ {
50
+ media_id: Fixture::MEDIA_ID,
51
+ recipient: Fixture::RECIPIENTS.join(','),
52
+ time: Fixture::VIEW_DURATION
53
+ },
54
+ username: true
55
+ )
56
+ stub_request(:post, "#{BASE_URI}/send").with(
57
+ body: request_body
58
+ ).to_return(
59
+ status: 200,
60
+ body: '',
61
+ headers: json_headers
62
+ )
63
+ end
64
+
65
+ def send_snap_to_single
66
+ request_body = requestify(
67
+ {
68
+ media_id: Fixture::MEDIA_ID,
69
+ recipient: Fixture::RECIPIENT,
70
+ time: Fixture::VIEW_DURATION
71
+ },
72
+ username: true
73
+ )
74
+ stub_request(:post, "#{BASE_URI}/send").with(
75
+ body: request_body
76
+ ).to_return(
77
+ status: 200,
78
+ body: '',
79
+ headers: json_headers
80
+ )
81
+ end
82
+
83
+ def media
84
+ request_body = requestify({ id: Fixture::SNAP_ID }, username: true)
85
+ stub_request(:post, "#{BASE_URI}/blob").with(
86
+ body: request_body
87
+ ).to_return(
88
+ status: 200,
89
+ body: DataHelper.data_for(:encrypted),
90
+ headers: { 'Content-Type' => 'application/octet-stream' }
91
+ )
92
+ end
93
+
94
+ def block
95
+ request_body = requestify(
96
+ {
97
+ action: 'block',
98
+ friend: Fixture::FRIEND_USERNAME
99
+ },
100
+ username: true
101
+ )
102
+ stub_request(:post, "#{BASE_URI}/friend").with(
103
+ body: request_body
104
+ ).to_return(
105
+ status: 200,
106
+ body: ResponseHelper.json_for(:block),
107
+ headers: json_headers
108
+ )
109
+ end
110
+
111
+ def clear_feed
112
+ request_body = requestify({}, username: true)
113
+ stub_request(:post, "#{BASE_URI}/clear").with(
114
+ body: request_body
115
+ ).to_return(
116
+ status: 200,
117
+ body: '', #ResponseHelper.json_for(:clear_feed),
118
+ headers: json_headers
119
+ )
120
+ end
121
+
122
+ def login
123
+ request_body = requestify(
124
+ { password: Fixture::PASSWORD },
125
+ username: true
126
+ )
127
+ stub_request(:post, "#{BASE_URI}/login").with(
128
+ body: request_body
129
+ ).to_return(
130
+ status: 200,
131
+ body: ResponseHelper.json_for(:login),
132
+ headers: json_headers
133
+ )
134
+ end
135
+
136
+ def logout
137
+ request_body = requestify({}, username: true)
138
+ stub_request(:post, "#{BASE_URI}/logout").with(
139
+ body: request_body
140
+ ).to_return(
141
+ status: 200,
142
+ body: '',
143
+ headers: json_headers
144
+ )
145
+ end
146
+
147
+ def delete
148
+ request_body = requestify(
149
+ {
150
+ action: 'delete',
151
+ friend: Fixture::FRIEND_USERNAME
152
+ },
153
+ username: true
154
+ )
155
+ stub_request(:post, "#{BASE_URI}/friend").with(
156
+ body: request_body
157
+ ).to_return(
158
+ status: 200,
159
+ body: ResponseHelper.json_for(:delete),
160
+ headers: json_headers
161
+ )
162
+ end
163
+
164
+ def set_display_name
165
+ request_body = requestify(
166
+ {
167
+ action: 'display',
168
+ display: Fixture::FRIEND_DISPLAY_NAME,
169
+ friend: Fixture::FRIEND_USERNAME
170
+ },
171
+ username: true
172
+ )
173
+ stub_request(:post, "#{BASE_URI}/friend").with(
174
+ body: request_body
175
+ ).to_return(
176
+ status: 200,
177
+ body: ResponseHelper.json_for(:set_display_name),
178
+ headers: json_headers
179
+ )
180
+ end
181
+
182
+ def register
183
+ request_body = requestify(
184
+ {
185
+ birthday: Fixture::BIRTHDAY,
186
+ email: Fixture::EMAIL,
187
+ password: Fixture::PASSWORD
188
+ }
189
+ )
190
+ stub_request(:post, "#{BASE_URI}/register").with(
191
+ body: request_body
192
+ ).to_return(
193
+ status: 200,
194
+ body: ResponseHelper.json_for(:register),
195
+ headers: json_headers
196
+ )
197
+ end
198
+
199
+ def registeru
200
+ request_body = requestify(
201
+ {
202
+ email: Fixture::EMAIL
203
+ },
204
+ username: true
205
+ )
206
+ stub_request(:post, "#{BASE_URI}/registeru").with(
207
+ body: request_body
208
+ ).to_return(
209
+ status: 200,
210
+ body: ResponseHelper.json_for(:registeru),
211
+ headers: json_headers
212
+ )
213
+ end
214
+
215
+ def fetch_updates
216
+ request_body = requestify(
217
+ {
218
+ update_timestamp: 0
219
+ },
220
+ username: true
221
+ )
222
+ stub_request(:post, "#{BASE_URI}/updates").with(
223
+ body: request_body
224
+ ).to_return(
225
+ status: 200,
226
+ body: ResponseHelper.json_for(:updates),
227
+ headers: json_headers
228
+ )
229
+ end
230
+
231
+ def update_email
232
+ request_body = requestify(
233
+ {
234
+ action: 'updateEmail',
235
+ email: Fixture::EMAIL
236
+ },
237
+ username: true
238
+ )
239
+ stub_request(:post, "#{BASE_URI}/settings").with(
240
+ body: request_body
241
+ ).to_return(
242
+ status: 200,
243
+ body: ResponseHelper.json_for(:update_email),
244
+ headers: json_headers
245
+ )
246
+ end
247
+
248
+ def unblock
249
+ request_body = requestify(
250
+ {
251
+ action: 'unblock',
252
+ friend: Fixture::FRIEND_USERNAME
253
+ },
254
+ username: true
255
+ )
256
+ stub_request(:post, "#{BASE_URI}/friend").with(
257
+ body: request_body
258
+ ).to_return(
259
+ status: 200,
260
+ body: ResponseHelper.json_for(:unblock),
261
+ headers: json_headers
262
+ )
263
+ end
264
+
265
+ def update_privacy
266
+ request_body = requestify(
267
+ {
268
+ action: 'updatePrivacy',
269
+ privacySetting: Snapcat::User::Privacy::EVERYONE
270
+ },
271
+ username: true
272
+ )
273
+ stub_request(:post, "#{BASE_URI}/settings").with(
274
+ body: request_body
275
+ ).to_return(
276
+ status: 200,
277
+ body: ResponseHelper.json_for(:update_privacy),
278
+ headers: json_headers
279
+ )
280
+ end
281
+
282
+ private
283
+
284
+ def default_request_hash
285
+ {
286
+ req_token: REQUEST_TOKEN,
287
+ timestamp: NOW,
288
+ version: Snapcat::Requestor::APP_VERSION
289
+ }
290
+ end
291
+
292
+ def json_headers
293
+ { 'Content-Type' => 'application/json' }
294
+ end
295
+
296
+ def requestify(data, options = {})
297
+ if options[:username]
298
+ data.merge!({ username: Fixture::USERNAME })
299
+ end
300
+
301
+ data.merge!(default_request_hash)
302
+
303
+ data = data.map do |key, value|
304
+ escaped_value = URI::encode(value.to_s).gsub(/@/, '%40').gsub(/,/, '%2C')
305
+ [key, escaped_value].join('=')
306
+ end
307
+
308
+ data.join('&')
309
+ end
310
+
311
+ def stub_auth
312
+ Snapcat::Response.any_instance.stubs(:auth_token).returns(
313
+ Snapcat::Requestor::STATIC_TOKEN
314
+ )
315
+ Snapcat::Timestamp.stubs(:micro).returns(NOW)
316
+ end
317
+
318
+ def stub_basics
319
+ stub_auth
320
+ login
321
+ end
322
+ end