murlsh 1.4.1 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/.gitignore +4 -0
  2. data/.htaccess +0 -3
  3. data/Gemfile +41 -0
  4. data/README.textile +68 -6
  5. data/Rakefile +65 -152
  6. data/config.ru +13 -2
  7. data/config.yaml +9 -4
  8. data/db/migrate/20110213023123_init.rb +20 -0
  9. data/lib/murlsh/atom_body.rb +78 -0
  10. data/lib/murlsh/atom_server.rb +38 -0
  11. data/lib/murlsh/auth.rb +12 -0
  12. data/lib/murlsh/build_query.rb +1 -1
  13. data/lib/murlsh/cat_files.rb +17 -0
  14. data/lib/murlsh/delicious_parse.rb +1 -0
  15. data/lib/murlsh/dispatch.rb +25 -11
  16. data/lib/murlsh/etag_add_encoding.rb +1 -1
  17. data/lib/murlsh/feed_body.rb +36 -0
  18. data/lib/murlsh/img_store.rb +27 -28
  19. data/lib/murlsh/install.rb +1 -0
  20. data/lib/murlsh/json_body.rb +5 -2
  21. data/lib/murlsh/json_server.rb +9 -13
  22. data/lib/murlsh/m3u_body.rb +28 -0
  23. data/lib/murlsh/m3u_server.rb +50 -0
  24. data/lib/murlsh/markup.rb +1 -1
  25. data/lib/murlsh/plugin.rb +5 -0
  26. data/lib/murlsh/podcast_server.rb +44 -0
  27. data/lib/murlsh/pop_server.rb +78 -0
  28. data/lib/murlsh/random_server.rb +41 -0
  29. data/lib/murlsh/rss_body.rb +46 -0
  30. data/lib/murlsh/rss_server.rb +38 -0
  31. data/lib/murlsh/search_conditions.rb +2 -2
  32. data/lib/murlsh/uri_ask.rb +2 -2
  33. data/lib/murlsh/url_body.rb +21 -6
  34. data/lib/murlsh/url_result_set.rb +2 -2
  35. data/lib/murlsh/url_server.rb +19 -16
  36. data/lib/murlsh/write_ordered_hash.rb +17 -0
  37. data/lib/murlsh.rb +13 -2
  38. data/murlsh.gemspec +41 -194
  39. data/plugins/add_post_60_notify_hubs.rb +3 -2
  40. data/plugins/add_pre_30_unajax_twitter.rb +1 -1
  41. data/plugins/add_pre_40_thumbnail_shortcuts.rb +23 -0
  42. data/plugins/add_pre_45_supplied_thumbnail.rb +4 -9
  43. data/plugins/add_pre_50_media_thumbnail.rb +4 -9
  44. data/plugins/add_pre_50_open_graph_image.rb +4 -8
  45. data/plugins/add_pre_60_github_title.rb +1 -1
  46. data/plugins/add_pre_65_html_thumb.rb +3 -8
  47. data/plugins/add_pre_65_img_thumb.rb +4 -9
  48. data/plugins/avatar_50_gravatar.rb +2 -1
  49. data/plugins/store_asset_40_s3.rb +40 -0
  50. data/plugins/store_asset_50_local.rb +22 -0
  51. data/public/js/js.js +0 -7
  52. data/spec/auth_spec.rb +7 -0
  53. data/spec/cat_files_spec.rb +49 -0
  54. data/spec/img_store_spec.rb +24 -8
  55. metadata +119 -76
  56. data/VERSION +0 -1
  57. data/lib/murlsh/build_md5.rb +0 -12
  58. data/lib/murlsh/head_from_get.rb +0 -15
  59. data/plugins/add_post_50_update_feed.rb +0 -84
  60. data/plugins/add_post_50_update_m3u.rb +0 -35
  61. data/plugins/add_post_50_update_podcast.rb +0 -44
  62. data/plugins/add_post_50_update_rss.rb +0 -51
  63. data/plugins/add_pre_60_s3_image.rb +0 -35
@@ -1,5 +1,3 @@
1
- require 'cgi'
2
-
3
1
  require 'murlsh'
4
2
 
5
3
  module Murlsh
@@ -9,20 +7,17 @@ module Murlsh
9
7
 
10
8
  @hook = 'add_pre'
11
9
 
12
- StorageDir = File.join(File.dirname(__FILE__), '..', 'public', 'img',
13
- 'thumb')
14
-
15
10
  def self.run(url, config)
16
11
  if url.thumbnail_url
17
12
  Murlsh::failproof do
18
- thumb_storage = Murlsh::ImgStore.new(StorageDir,
19
- :user_agent => config['user_agent'])
13
+ thumb_storage = Murlsh::ImgStore.new(config)
20
14
 
21
- stored_filename = thumb_storage.store_url(url.thumbnail_url) do |i|
15
+ stored_url = thumb_storage.store_url(url.thumbnail_url) do |i|
22
16
  max_side = config.fetch('thumbnail_max_side', 90)
23
17
  i.extend(Murlsh::ImageList).resize_down!(max_side)
24
18
  end
25
- url.thumbnail_url = "img/thumb/#{CGI.escape(stored_filename)}"
19
+
20
+ url.thumbnail_url = stored_url if stored_url
26
21
  end
27
22
  end
28
23
  end
@@ -1,5 +1,3 @@
1
- require 'cgi'
2
-
3
1
  require 'murlsh'
4
2
 
5
3
  module Murlsh
@@ -9,9 +7,6 @@ module Murlsh
9
7
 
10
8
  @hook = 'add_pre'
11
9
 
12
- StorageDir = File.join(File.dirname(__FILE__), '..', 'public', 'img',
13
- 'thumb')
14
-
15
10
  def self.run(url, config)
16
11
  if not url.thumbnail_url and url.ask.doc
17
12
  url.ask.doc.xpath_search(%w{
@@ -20,14 +15,14 @@ module Murlsh
20
15
  }) do |node|
21
16
  if node and not node['href'].to_s.empty?
22
17
  Murlsh::failproof do
23
- thumb_storage = Murlsh::ImgStore.new(StorageDir,
24
- :user_agent => config['user_agent'])
18
+ thumb_storage = Murlsh::ImgStore.new(config)
25
19
 
26
- stored_filename = thumb_storage.store_url(node['href']) do |i|
20
+ stored_url = thumb_storage.store_url(node['href']) do |i|
27
21
  max_side = config.fetch('thumbnail_max_side', 90)
28
22
  i.extend(Murlsh::ImageList).resize_down!(max_side)
29
23
  end
30
- url.thumbnail_url = "img/thumb/#{CGI.escape(stored_filename)}"
24
+
25
+ url.thumbnail_url = stored_url if stored_url
31
26
  end
32
27
  end
33
28
  end
@@ -1,4 +1,3 @@
1
- require 'cgi'
2
1
  require 'uri'
3
2
 
4
3
  require 'murlsh'
@@ -10,9 +9,6 @@ module Murlsh
10
9
 
11
10
  @hook = 'add_pre'
12
11
 
13
- StorageDir = File.join(File.dirname(__FILE__), '..', 'public', 'img',
14
- 'thumb')
15
-
16
12
  def self.run(url, config)
17
13
  if not url.thumbnail_url and url.ask.doc
18
14
  url.ask.doc.xpath_search("//meta[@property='og:image']") do |node|
@@ -23,14 +19,14 @@ module Murlsh
23
19
  if og_image_url[%r{^//}]
24
20
  og_image_url = "#{URI(url.url).scheme}:#{og_image_url}"
25
21
  end
26
- thumb_storage = Murlsh::ImgStore.new(StorageDir,
27
- :user_agent => config['user_agent'])
22
+ thumb_storage = Murlsh::ImgStore.new(config)
28
23
 
29
- stored_filename = thumb_storage.store_url(og_image_url) do |i|
24
+ stored_url = thumb_storage.store_url(og_image_url) do |i|
30
25
  max_side = config.fetch('thumbnail_max_side', 90)
31
26
  i.extend(Murlsh::ImageList).resize_down!(max_side)
32
27
  end
33
- url.thumbnail_url = "img/thumb/#{CGI.escape(stored_filename)}"
28
+
29
+ url.thumbnail_url = stored_url if stored_url
34
30
  end
35
31
  end
36
32
  end
@@ -10,7 +10,7 @@ module Murlsh
10
10
 
11
11
  @hook = 'add_pre'
12
12
 
13
- GithubRe = %r{^https?://github\.com/\w+/[\w.-]+$}i
13
+ GithubRe = %r{^https?://github\.com/\w+/[\w.-]+/?$}i
14
14
 
15
15
  def self.run(url, config)
16
16
  if not url.user_supplied_title? and url.url.to_s[GithubRe]
@@ -1,5 +1,3 @@
1
- require 'cgi'
2
-
3
1
  require 'plumnailer'
4
2
 
5
3
  require 'murlsh'
@@ -11,9 +9,6 @@ module Murlsh
11
9
 
12
10
  @hook = 'add_pre'
13
11
 
14
- StorageDir = File.join(File.dirname(__FILE__), '..', 'public', 'img',
15
- 'thumb')
16
-
17
12
  def self.run(url, config)
18
13
  if not url.thumbnail_url and url.content_type and
19
14
  url.content_type[Murlsh::UriAsk::HtmlContentTypeRe]
@@ -25,10 +20,10 @@ module Murlsh
25
20
  max_side = config.fetch('thumbnail_max_side', 90)
26
21
  choice.extend(Murlsh::ImageList).resize_down!(max_side)
27
22
 
28
- thumb_storage = Murlsh::ImgStore.new(StorageDir)
23
+ thumb_storage = Murlsh::ImgStore.new(config)
29
24
 
30
- stored_filename = thumb_storage.store_img(choice)
31
- url.thumbnail_url = "img/thumb/#{CGI.escape(stored_filename)}"
25
+ stored_url = thumb_storage.store_img(choice)
26
+ url.thumbnail_url = stored_url if stored_url
32
27
  end
33
28
  end
34
29
  end
@@ -1,5 +1,3 @@
1
- require 'cgi'
2
-
3
1
  require 'murlsh'
4
2
 
5
3
  module Murlsh
@@ -9,9 +7,6 @@ module Murlsh
9
7
 
10
8
  @hook = 'add_pre'
11
9
 
12
- StorageDir = File.join(File.dirname(__FILE__), '..', 'public', 'img',
13
- 'thumb')
14
-
15
10
  ImageContentType = %w{
16
11
  image/gif
17
12
  image/jpeg
@@ -22,14 +17,14 @@ module Murlsh
22
17
  if not url.thumbnail_url and url.content_type and
23
18
  ImageContentType.include?(url.content_type)
24
19
  Murlsh::failproof do
25
- thumb_storage = Murlsh::ImgStore.new(StorageDir,
26
- :user_agent => config['user_agent'])
20
+ thumb_storage = Murlsh::ImgStore.new(config)
27
21
 
28
- stored_filename = thumb_storage.store_url(url.url) do |i|
22
+ stored_url = thumb_storage.store_url(url.url) do |i|
29
23
  max_side = config.fetch('thumbnail_max_side', 90)
30
24
  i.extend(Murlsh::ImageList).resize_down!(max_side)
31
25
  end
32
- url.thumbnail_url = "img/thumb/#{CGI.escape(stored_filename)}"
26
+
27
+ url.thumbnail_url = stored_url if stored_url
33
28
  end
34
29
  end
35
30
  end
@@ -13,7 +13,8 @@ module Murlsh
13
13
  if url.email and not url.email.empty? and
14
14
  (gravatar_size = config.fetch('gravatar_size', 0)) > 0
15
15
  query = { :s => gravatar_size }
16
- URI.join('http://www.gravatar.com/avatar/', url.email, Murlsh::build_query(query))
16
+ URI.join('http://www.gravatar.com/avatar/', url.email,
17
+ Murlsh::build_query(query))
17
18
  end
18
19
  end
19
20
 
@@ -0,0 +1,40 @@
1
+ require 'time'
2
+
3
+ require 'aws/s3'
4
+
5
+ module Murlsh
6
+
7
+ # Store assets in Amazon S3.
8
+ #
9
+ # Depends on 's3_id', 's3_secret', and 's3_bucket' in config.
10
+ class StoreAsset40S3 < Plugin
11
+
12
+ @hook = 'store_asset'
13
+
14
+ def self.run(name, data, config)
15
+ if !config['s3_id'].to_s.empty? and
16
+ !config['s3_secret'].to_s.empty? and
17
+ !config['s3_bucket'].to_s.empty?
18
+ AWS::S3::Base.establish_connection!(
19
+ :access_key_id => config['s3_id'],
20
+ :secret_access_key => config['s3_secret']
21
+ )
22
+
23
+ bucket = begin
24
+ AWS::S3::Bucket.find config['s3_bucket']
25
+ rescue AWS::S3::NoSuchBucket
26
+ AWS::S3::Bucket.create config['s3_bucket'], :access => :public_read
27
+ end
28
+
29
+ AWS::S3::S3Object.store name, data, bucket.name,
30
+ :access => :public_read,
31
+ # 100 years
32
+ :expires => (Time.now + (31536000000)).httpdate
33
+
34
+ AWS::S3::S3Object.url_for(name, bucket.name, :authenticated => false)
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+ end
@@ -0,0 +1,22 @@
1
+ require 'murlsh'
2
+
3
+ module Murlsh
4
+
5
+ # Store assets on the local filesystem in the public directory.
6
+ class StoreAsset50Local < Plugin
7
+
8
+ @hook = 'store_asset'
9
+
10
+ def self.run(name, data, config)
11
+ # break apart and rejoin to use os path separator
12
+ name_parts = name.split('/')
13
+ local_path = File.join('public', name_parts)
14
+
15
+ Murlsh::openlock(local_path, 'w') { |fout| fout.write data }
16
+
17
+ name
18
+ end
19
+
20
+ end
21
+
22
+ end
data/public/js/js.js CHANGED
@@ -9,8 +9,6 @@ var Murlsh = function ($, navigator, window, twtter) {
9
9
  /^http:\/\/img\d+\.imageshack\.us\/img\d+\/\d+\/\w+\.(?:jpe?g|gif|png)$/i,
10
10
  imgur :
11
11
  /^http:\/\/(?:i\.)?imgur\.com\/[a-z\d]+\.(?:jpe?g|gif|png)$/i,
12
- s3 :
13
- /^http:\/\/static\.mmb\.s3\.amazonaws\.com\/[\w\-]+\.(jpe?g|gif|pdf|png)$/i,
14
12
  twitter :
15
13
  /^https?:\/\/twitter\.com\/\w+\/status(?:es)?\/\d+$/i,
16
14
  vimeo :
@@ -119,11 +117,6 @@ var Murlsh = function ($, navigator, window, twtter) {
119
117
 
120
118
  if (match.imageshack || match.imgur) {
121
119
  setupClickHandler(thisA.siblings('img'), 'href', href, imgClick);
122
- } else if (match.s3) {
123
- if (!(match.s3[1].match(/^pdf$/i))) {
124
- setupClickHandler(thisA.siblings('img'), 'href', href,
125
- imgClick);
126
- }
127
120
  } else if (match.twitter) {
128
121
  thisA.siblings('img').addClass('twitter');
129
122
  tweetMatch = /^(@[0-9a-z_]+?): (.+)$/i.exec(thisA.text());
data/spec/auth_spec.rb CHANGED
@@ -30,4 +30,11 @@ describe Murlsh::Auth do
30
30
  @a.auth('not there').should be_nil
31
31
  end
32
32
 
33
+ it 'should be able to find user by email address' do
34
+ @a.by_email('test1@test.com').should == {
35
+ :name => 'test1',
36
+ :email => Digest::MD5.hexdigest('test1@test.com')
37
+ }
38
+ end
39
+
33
40
  end
@@ -0,0 +1,49 @@
1
+ require 'tempfile'
2
+
3
+ require 'murlsh'
4
+
5
+ describe Murlsh do
6
+
7
+ describe :cat_files do
8
+
9
+ context 'when all files are there' do
10
+
11
+ before do
12
+ @f1 = Tempfile.new('f1')
13
+ (1..2).each { |i| @f1.write "#{i}\n" }
14
+ @f1.close
15
+
16
+ @f2 = Tempfile.new('f2')
17
+ (1..3).each { |i| @f2.write "#{i}\n" }
18
+ @f2.close
19
+ end
20
+
21
+ after do
22
+ @f1.unlink
23
+ @f2.unlink
24
+ end
25
+
26
+ it 'should cat the files together and return the result' do
27
+ Murlsh.cat_files([@f1.path, @f2.path]).should == <<eos
28
+ 1
29
+ 2
30
+ 1
31
+ 2
32
+ 3
33
+ eos
34
+ end
35
+
36
+ end
37
+
38
+ context 'when one or more files are missing' do
39
+
40
+ it 'should raise no such file or directory' do
41
+ lambda { Murlsh.cat_files(['does_not_exist']) }.should raise_error(
42
+ Errno::ENOENT)
43
+ end
44
+
45
+ end
46
+
47
+ end
48
+
49
+ end
@@ -7,12 +7,28 @@ require 'RMagick'
7
7
 
8
8
  require 'murlsh'
9
9
 
10
+ module Murlsh
11
+
12
+ class StoreAsset50Test < Plugin
13
+
14
+ @hook = 'store_asset'
15
+
16
+ def self.run(name, data, config)
17
+ local_path = File.join(Dir::tmpdir, 'img_store_test', name)
18
+ FileUtils.mkdir_p(File.dirname(local_path))
19
+ Murlsh::openlock(local_path, 'w') { |fout| fout.write data }
20
+ name
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+
10
27
  describe Murlsh::ImgStore do
11
28
 
12
29
  before(:all) do
13
30
  @thumb_dir = File.join(Dir::tmpdir, 'img_store_test')
14
- FileUtils.mkdir_p @thumb_dir
15
- @img_store = Murlsh::ImgStore.new(@thumb_dir)
31
+ @img_store = Murlsh::ImgStore.new({})
16
32
  end
17
33
 
18
34
  describe :store_url do
@@ -22,13 +38,13 @@ describe Murlsh::ImgStore do
22
38
  before(:all) do
23
39
  image_url =
24
40
  'http://static.mmb.s3.amazonaws.com/2010_10_8_bacon_pancakes.jpg'
25
- @local_file = @img_store.store_url(image_url)
26
- @local_path = File.join(@thumb_dir, @local_file)
41
+ @stored_url = @img_store.store_url(image_url)
42
+ @local_path = File.join(@thumb_dir, @stored_url)
27
43
  end
28
44
 
29
45
  it 'should be named with the md5 sum of its contents' do
30
46
  md5 = Digest::MD5.file(@local_path).hexdigest
31
- @local_file.should == "#{md5}.jpg"
47
+ @stored_url.should == "img/thumb/#{md5}.jpg"
32
48
  end
33
49
 
34
50
  end
@@ -54,13 +70,13 @@ describe Murlsh::ImgStore do
54
70
  'http://static.mmb.s3.amazonaws.com/2010_10_8_bacon_pancakes.jpg') do |f|
55
71
  f.read
56
72
  end
57
- @local_file = @img_store.store_img_data(img_data)
58
- @local_path = File.join(@thumb_dir, @local_file)
73
+ @stored_url = @img_store.store_img_data(img_data)
74
+ @local_path = File.join(@thumb_dir, @stored_url)
59
75
  end
60
76
 
61
77
  it 'should be named with the md5 sum of its contents' do
62
78
  md5 = Digest::MD5.file(@local_path).hexdigest
63
- @local_file.should == "#{md5}.jpg"
79
+ @stored_url.should == "img/thumb/#{md5}.jpg"
64
80
  end
65
81
 
66
82
  end