snapcat 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 (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