bluebird 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,115 @@
1
+ module Bluebird
2
+ class Tweet
3
+
4
+ include Twitter::Extractor
5
+
6
+ attr_reader :partials, :original_status, :media
7
+
8
+ def initialize(status, opts = {})
9
+ @original_status = status
10
+ @partials = extract_partials(status)
11
+ @media = opts[:media] if opts.has_key?(:media)
12
+ end
13
+
14
+ def status
15
+ partials.map { |partial| partial.content }.join
16
+ end
17
+
18
+ def length
19
+ total_partial_length + media_length
20
+ end
21
+
22
+ def text_partials
23
+ partials.select { |partial| partial.text? }
24
+ end
25
+
26
+ def url_partials
27
+ partials.select { |partial| partial.url? }
28
+ end
29
+
30
+ def mention_partials
31
+ partials.select { |partial| partial.mention? }
32
+ end
33
+
34
+ def hashtag_partials
35
+ partials.select { |partial| partial.hashtag? }
36
+ end
37
+
38
+ def cashtag_partials
39
+ partials.select { |partial| partial.cashtag? }
40
+ end
41
+
42
+ private
43
+
44
+ def total_partial_length
45
+ total = 0
46
+
47
+ partials.each do |partial|
48
+ total += partial.length
49
+ end
50
+
51
+ total
52
+ end
53
+
54
+ def media_length
55
+ media ? Config.characters_reserved_per_media : 0
56
+ end
57
+
58
+ def extract_partials(status)
59
+ entities = extract_entities_with_indices(status, extract_url_without_protocol: true)
60
+ length = status.char_length
61
+ index = 0
62
+ partials = []
63
+
64
+ entities.each do |entity|
65
+ first = entity[:indices].first
66
+ last = entity[:indices].last
67
+
68
+ add_partial(partials, status[index, first - index], :text)
69
+ add_partial(partials, status[first, last - first], entity_type(entity))
70
+
71
+ index = last
72
+ end
73
+
74
+ if ending_partial?(index, length)
75
+ add_partial(partials, status[index, length - index], :text)
76
+ end
77
+
78
+ partials
79
+ end
80
+
81
+ def add_partial(partials, content, partial_type)
82
+ if eligible_content?(content)
83
+ partial = Partial.new(content, partial_type)
84
+
85
+ if (last = partials.last)
86
+ last.next_partial = partial
87
+ partial.prev_partial = last
88
+ end
89
+
90
+ partials << partial
91
+ end
92
+ end
93
+
94
+ def entity_type(entity)
95
+ if entity.has_key?(:screen_name)
96
+ entity[:list_slug].empty? ? :mention : :list
97
+ elsif entity.has_key?(:hashtag)
98
+ :hashtag
99
+ elsif entity.has_key?(:url)
100
+ :url
101
+ elsif entity.has_key?(:cashtag)
102
+ :cashtag
103
+ end
104
+ end
105
+
106
+ def ending_partial?(index, length)
107
+ index <= length
108
+ end
109
+
110
+ def eligible_content?(content)
111
+ content.char_length > 0
112
+ end
113
+
114
+ end
115
+ end
@@ -0,0 +1,3 @@
1
+ module Bluebird
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,8 @@
1
+ require 'bundler/setup'
2
+ Bundler.setup
3
+
4
+ require 'bluebird'
5
+
6
+ RSpec.configure do |config|
7
+ # some (optional) config here
8
+ end
@@ -0,0 +1,444 @@
1
+ require 'spec_helper'
2
+
3
+ describe Bluebird::Strategies::Squeeze::Strategy do
4
+
5
+ before(:all) do
6
+ Bluebird.configure do |config|
7
+ config.max_length = 20
8
+ config.characters_reserved_per_media = 5
9
+ end
10
+ end
11
+
12
+ let!(:strategy) { Bluebird::Strategies::Squeeze::Strategy }
13
+ let!(:config) { Bluebird::Config }
14
+
15
+ context 'When tweet is shorter than max' do
16
+ context 'and without leading whitespaces' do
17
+ context 'and without trailing whitespaces' do
18
+ context 'and without middle whitespaces' do
19
+ context 'and without media' do
20
+ it 'does not modify the tweet' do
21
+ tweet = Bluebird::Tweet.new('Lorem ipsum dolor')
22
+ strategy.run(tweet, config)
23
+ expect(tweet.status).to eq 'Lorem ipsum dolor'
24
+ end
25
+ end
26
+ context 'and with media' do
27
+ it 'does not modify the tweet' do
28
+ tweet = Bluebird::Tweet.new('Lorem ipsum', media: true)
29
+ strategy.run(tweet, config)
30
+ expect(tweet.status).to eq 'Lorem ipsum'
31
+ end
32
+ end
33
+ end
34
+ context 'and with middle whitespaces' do
35
+ context 'and without media' do
36
+ it 'does not modify the tweet' do
37
+ tweet = Bluebird::Tweet.new('Lorem ipsum dolor')
38
+ strategy.run(tweet, config)
39
+ expect(tweet.status).to eq 'Lorem ipsum dolor'
40
+ end
41
+ end
42
+ context 'and with media' do
43
+ it 'does not modify the tweet' do
44
+ tweet = Bluebird::Tweet.new('Lorem ipsum ', media: true)
45
+ strategy.run(tweet, config)
46
+ expect(tweet.status).to eq 'Lorem ipsum '
47
+ end
48
+ end
49
+ end
50
+ end
51
+ context 'and with trailing whitespaces' do
52
+ context 'and without middle whitespaces' do
53
+ context 'and without media' do
54
+ it 'does not modify the tweet' do
55
+ tweet = Bluebird::Tweet.new('Lorem ipsum dolor ')
56
+ strategy.run(tweet, config)
57
+ expect(tweet.status).to eq 'Lorem ipsum dolor '
58
+ end
59
+ end
60
+ context 'and with media' do
61
+ it 'does not modify the tweet' do
62
+ tweet = Bluebird::Tweet.new('Lorem ipsum ', media: true)
63
+ strategy.run(tweet, config)
64
+ expect(tweet.status).to eq 'Lorem ipsum '
65
+ end
66
+ end
67
+ end
68
+ context 'and with middle whitespaces' do
69
+ context 'and without media' do
70
+ it 'does not modify the tweet' do
71
+ tweet = Bluebird::Tweet.new('Lorem ipsum do ')
72
+ strategy.run(tweet, config)
73
+ expect(tweet.status).to eq 'Lorem ipsum do '
74
+ end
75
+ end
76
+ context 'and with media' do
77
+ it 'does not modify the tweet' do
78
+ tweet = Bluebird::Tweet.new('Lorem do ', media: true)
79
+ strategy.run(tweet, config)
80
+ expect(tweet.status).to eq 'Lorem do '
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ context 'and with leading whitespaces' do
87
+ context 'and without trailing whitespaces' do
88
+ context 'and without middle whitespaces' do
89
+ context 'and without media' do
90
+ it 'does not modify the tweet' do
91
+ tweet = Bluebird::Tweet.new(' Lorem ipsum do')
92
+ strategy.run(tweet, config)
93
+ expect(tweet.status).to eq ' Lorem ipsum do'
94
+ end
95
+ end
96
+ context 'and with media' do
97
+ it 'does not modify the tweet' do
98
+ tweet = Bluebird::Tweet.new(' Lorem do', media: true)
99
+ strategy.run(tweet, config)
100
+ expect(tweet.status).to eq ' Lorem do'
101
+ end
102
+ end
103
+ end
104
+ context 'and with middle whitespaces' do
105
+ context 'and without media' do
106
+ it 'does not modify the tweet' do
107
+ tweet = Bluebird::Tweet.new(' Lorem ipsum do')
108
+ strategy.run(tweet, config)
109
+ expect(tweet.status).to eq ' Lorem ipsum do'
110
+ end
111
+ end
112
+ context 'and with media' do
113
+ it 'does not modify the tweet' do
114
+ tweet = Bluebird::Tweet.new(' Lorem do', media: true)
115
+ strategy.run(tweet, config)
116
+ expect(tweet.status).to eq ' Lorem do'
117
+ end
118
+ end
119
+ end
120
+ end
121
+ context 'and with trailing whitespaces' do
122
+ context 'and without middle whitespaces' do
123
+ context 'and without media' do
124
+ it 'does not modify the tweet' do
125
+ tweet = Bluebird::Tweet.new(' Lorem ipsum do ')
126
+ strategy.run(tweet, config)
127
+ expect(tweet.status).to eq ' Lorem ipsum do '
128
+ end
129
+ end
130
+ context 'and with media' do
131
+ it 'does not modify the tweet' do
132
+ tweet = Bluebird::Tweet.new(' Lorem do ', media: true)
133
+ strategy.run(tweet, config)
134
+ expect(tweet.status).to eq ' Lorem do '
135
+ end
136
+ end
137
+ end
138
+ context 'and with middle whitespaces' do
139
+ context 'and without media' do
140
+ it 'does not modify the tweet' do
141
+ tweet = Bluebird::Tweet.new(' Lorem ipsum do ')
142
+ strategy.run(tweet, config)
143
+ expect(tweet.status).to eq ' Lorem ipsum do '
144
+ end
145
+ end
146
+ context 'and with media' do
147
+ it 'does not modify the tweet' do
148
+ tweet = Bluebird::Tweet.new(' Lorem do ', media: true)
149
+ strategy.run(tweet, config)
150
+ expect(tweet.status).to eq ' Lorem do '
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
156
+ end
157
+
158
+ context 'When tweet is longer than max' do
159
+ context 'and without leading whitespaces' do
160
+ context 'and without trailing whitespaces' do
161
+ context 'and without middle whitespaces' do
162
+ context 'and without media' do
163
+ it 'does not modify the tweet' do
164
+ tweet = Bluebird::Tweet.new('Lorem ipsum dolor sit amet')
165
+ strategy.run(tweet, config)
166
+ expect(tweet.status).to eq 'Lorem ipsum dolor sit amet'
167
+ end
168
+ end
169
+ context 'and with media' do
170
+ it 'does not modify the tweet' do
171
+ tweet = Bluebird::Tweet.new('Lorem ipsum dolor', media: true)
172
+ strategy.run(tweet, config)
173
+ expect(tweet.status).to eq 'Lorem ipsum dolor'
174
+ end
175
+ end
176
+ end
177
+ context 'and with middle whitespaces' do
178
+ context 'and without media' do
179
+ it 'squeezes the middle whitespaces' do
180
+ tweet = Bluebird::Tweet.new('Lorem ipsum dolor sit amet')
181
+ strategy.run(tweet, config)
182
+ expect(tweet.status).to eq 'Lorem ipsum dolor sit amet'
183
+ end
184
+ end
185
+ context 'and with media' do
186
+ it 'squeezes the middle whitespaces' do
187
+ tweet = Bluebird::Tweet.new('Lorem ipsum dolor sit amet', media: true)
188
+ strategy.run(tweet, config)
189
+ expect(tweet.status).to eq 'Lorem ipsum dolor sit amet'
190
+ end
191
+ end
192
+ end
193
+ end
194
+ context 'and with trailing whitespaces' do
195
+ context 'and without middle whitespaces' do
196
+ context 'and without media' do
197
+ it 'squeezes the trailing whitespaces' do
198
+ tweet = Bluebird::Tweet.new('Lorem ipsum dolor sit amet ')
199
+ strategy.run(tweet, config)
200
+ expect(tweet.status).to eq 'Lorem ipsum dolor sit amet '
201
+ end
202
+ end
203
+ context 'and with media' do
204
+ it 'squeezes the trailing whitespaces' do
205
+ tweet = Bluebird::Tweet.new('Lorem ipsum dolor sit amet ', media: true)
206
+ strategy.run(tweet, config)
207
+ expect(tweet.status).to eq 'Lorem ipsum dolor sit amet '
208
+ end
209
+ end
210
+ end
211
+ context 'and with middle whitespaces' do
212
+ context 'and without media' do
213
+ it 'squeezes the trailing & middle whitespaces' do
214
+ tweet = Bluebird::Tweet.new('Lorem ipsum dolor sit amet ')
215
+ strategy.run(tweet, config)
216
+ expect(tweet.status).to eq 'Lorem ipsum dolor sit amet '
217
+ end
218
+ end
219
+ context 'and with media' do
220
+ it 'squeezes the trailing & middle whitespaces' do
221
+ tweet = Bluebird::Tweet.new('Lorem ipsum dolor sit amet ', media: true)
222
+ strategy.run(tweet, config)
223
+ expect(tweet.status).to eq 'Lorem ipsum dolor sit amet '
224
+ end
225
+ end
226
+ end
227
+ end
228
+ end
229
+ context 'and with leading whitespaces' do
230
+ context 'and without trailing whitespaces' do
231
+ context 'and without middle whitespaces' do
232
+ context 'and without media' do
233
+ it 'squeezes the leading whitespaces' do
234
+ tweet = Bluebird::Tweet.new(' Lorem ipsum dolor sit amet')
235
+ strategy.run(tweet, config)
236
+ expect(tweet.status).to eq ' Lorem ipsum dolor sit amet'
237
+ end
238
+ end
239
+ context 'and with media' do
240
+ it 'squeezes the leading whitespaces' do
241
+ tweet = Bluebird::Tweet.new(' Lorem ipsum dolor sit amet', media: true)
242
+ strategy.run(tweet, config)
243
+ expect(tweet.status).to eq ' Lorem ipsum dolor sit amet'
244
+ end
245
+ end
246
+ end
247
+ context 'and with middle whitespaces' do
248
+ context 'and without media' do
249
+ it 'squeezes the leading & middle whitespaces' do
250
+ tweet = Bluebird::Tweet.new(' Lorem ipsum dolor sit amet')
251
+ strategy.run(tweet, config)
252
+ expect(tweet.status).to eq ' Lorem ipsum dolor sit amet'
253
+ end
254
+ end
255
+ context 'and with media' do
256
+ it 'squeezes the leading & middle whitespaces' do
257
+ tweet = Bluebird::Tweet.new(' Lorem ipsum dolor sit amet', media: true)
258
+ strategy.run(tweet, config)
259
+ expect(tweet.status).to eq ' Lorem ipsum dolor sit amet'
260
+ end
261
+ end
262
+ end
263
+ end
264
+ context 'and with trailing whitespaces' do
265
+ context 'and without middle whitespaces' do
266
+ context 'and without media' do
267
+ it 'squeezes the leading & trailing whitespaces' do
268
+ tweet = Bluebird::Tweet.new(' Lorem ipsum dolor sit amet ')
269
+ strategy.run(tweet, config)
270
+ expect(tweet.status).to eq ' Lorem ipsum dolor sit amet '
271
+ end
272
+ end
273
+ context 'and with media' do
274
+ it 'squeezes the leading & trailing whitespaces' do
275
+ tweet = Bluebird::Tweet.new(' Lorem ipsum dolor sit amet ', media: true)
276
+ strategy.run(tweet, config)
277
+ expect(tweet.status).to eq ' Lorem ipsum dolor sit amet '
278
+ end
279
+ end
280
+ end
281
+ context 'and with middle whitespaces' do
282
+ context 'and without media' do
283
+ it 'squeezes the leading & middle & trailing whitespaces' do
284
+ tweet = Bluebird::Tweet.new(' Lorem ipsum dolor sit amet ')
285
+ strategy.run(tweet, config)
286
+ expect(tweet.status).to eq ' Lorem ipsum dolor sit amet '
287
+ end
288
+ end
289
+ context 'and with media' do
290
+ it 'squeezes the leading & middle & trailing whitespaces' do
291
+ tweet = Bluebird::Tweet.new(' Lorem ipsum dolor sit amet ', media: true)
292
+ strategy.run(tweet, config)
293
+ expect(tweet.status).to eq ' Lorem ipsum dolor sit amet '
294
+ end
295
+ end
296
+ end
297
+ end
298
+ end
299
+ end
300
+
301
+ context "When tweet's length is equal to max" do
302
+ context 'and without leading whitespaces' do
303
+ context 'and without trailing whitespaces' do
304
+ context 'and without middle whitespaces' do
305
+ context 'and without media' do
306
+ it 'does not modify the tweet' do
307
+ tweet = Bluebird::Tweet.new('Lorem ipsum dolor si')
308
+ strategy.run(tweet, config)
309
+ expect(tweet.status).to eq 'Lorem ipsum dolor si'
310
+ end
311
+ end
312
+ context 'and with media' do
313
+ it 'does not modify the tweet' do
314
+ tweet = Bluebird::Tweet.new('Lorem ipsum dol', media: true)
315
+ strategy.run(tweet, config)
316
+ expect(tweet.status).to eq 'Lorem ipsum dol'
317
+ end
318
+ end
319
+ end
320
+ context 'and with middle whitespaces' do
321
+ context 'and without media' do
322
+ it 'does not modify the tweet' do
323
+ tweet = Bluebird::Tweet.new('Lorem ipsum dolor')
324
+ strategy.run(tweet, config)
325
+ expect(tweet.status).to eq 'Lorem ipsum dolor'
326
+ end
327
+ end
328
+ context 'and with media' do
329
+ it 'does not modify the tweet' do
330
+ tweet = Bluebird::Tweet.new('Lorem dolor', media: true)
331
+ strategy.run(tweet, config)
332
+ expect(tweet.status).to eq 'Lorem dolor'
333
+ end
334
+ end
335
+ end
336
+ end
337
+ context 'and with trailing whitespaces' do
338
+ context 'and without middle whitespaces' do
339
+ context 'and without media' do
340
+ it 'does not modify the tweet' do
341
+ tweet = Bluebird::Tweet.new('Lorem ipsum dolor ')
342
+ strategy.run(tweet, config)
343
+ expect(tweet.status).to eq 'Lorem ipsum dolor '
344
+ end
345
+ end
346
+ context 'and with media' do
347
+ it 'does not modify the tweet' do
348
+ tweet = Bluebird::Tweet.new('Loremx dolor ', media: true)
349
+ strategy.run(tweet, config)
350
+ expect(tweet.status).to eq 'Loremx dolor '
351
+ end
352
+ end
353
+ end
354
+ context 'and with middle whitespaces' do
355
+ context 'and without media' do
356
+ it 'does not modify the tweet' do
357
+ tweet = Bluebird::Tweet.new('Lorem ipsum dol ')
358
+ strategy.run(tweet, config)
359
+ expect(tweet.status).to eq 'Lorem ipsum dol '
360
+ end
361
+ end
362
+ context 'and with media' do
363
+ it 'does not modify the tweet' do
364
+ tweet = Bluebird::Tweet.new('Lorem dol ', media: true)
365
+ strategy.run(tweet, config)
366
+ expect(tweet.status).to eq 'Lorem dol '
367
+ end
368
+ end
369
+ end
370
+ end
371
+ end
372
+ context 'and with leading whitespaces' do
373
+ context 'and without trailing whitespaces' do
374
+ context 'and without middle whitespaces' do
375
+ context 'and without media' do
376
+ it 'does not modify the tweet' do
377
+ tweet = Bluebird::Tweet.new(' Lorem ipsum dolor')
378
+ strategy.run(tweet, config)
379
+ expect(tweet.status).to eq ' Lorem ipsum dolor'
380
+ end
381
+ end
382
+ context 'and with media' do
383
+ it 'does not modify the tweet' do
384
+ tweet = Bluebird::Tweet.new(' Lorem ipsumd', media: true)
385
+ strategy.run(tweet, config)
386
+ expect(tweet.status).to eq ' Lorem ipsumd'
387
+ end
388
+ end
389
+ end
390
+ context 'and with middle whitespaces' do
391
+ context 'and without media' do
392
+ it 'does not modify the tweet' do
393
+ tweet = Bluebird::Tweet.new(' Lorem ipsum dol')
394
+ strategy.run(tweet, config)
395
+ expect(tweet.status).to eq ' Lorem ipsum dol'
396
+ end
397
+ end
398
+ context 'and with media' do
399
+ it 'does not modify the tweet' do
400
+ tweet = Bluebird::Tweet.new(' Lorem dol', media: true)
401
+ strategy.run(tweet, config)
402
+ expect(tweet.status).to eq ' Lorem dol'
403
+ end
404
+ end
405
+ end
406
+ end
407
+ context 'and with trailing whitespaces' do
408
+ context 'and without middle whitespaces' do
409
+ context 'and without media' do
410
+ it 'does not modify the tweet' do
411
+ tweet = Bluebird::Tweet.new(' Lorem ipsum dol ')
412
+ strategy.run(tweet, config)
413
+ expect(tweet.status).to eq ' Lorem ipsum dol '
414
+ end
415
+ end
416
+ context 'and with media' do
417
+ it 'does not modify the tweet' do
418
+ tweet = Bluebird::Tweet.new(' Loremi dol ', media: true)
419
+ strategy.run(tweet, config)
420
+ expect(tweet.status).to eq ' Loremi dol '
421
+ end
422
+ end
423
+ end
424
+ context 'and with middle whitespaces' do
425
+ context 'and without media' do
426
+ it 'does not modify the tweet' do
427
+ tweet = Bluebird::Tweet.new(' Lorem ips dol ')
428
+ strategy.run(tweet, config)
429
+ expect(tweet.status).to eq ' Lorem ips dol '
430
+ end
431
+ end
432
+ context 'and with media' do
433
+ it 'does not modify the tweet' do
434
+ tweet = Bluebird::Tweet.new(' Lore dol ', media: true)
435
+ strategy.run(tweet, config)
436
+ expect(tweet.status).to eq ' Lore dol '
437
+ end
438
+ end
439
+ end
440
+ end
441
+ end
442
+ end
443
+
444
+ end