murlsh 1.4.1 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/.htaccess +0 -3
- data/Gemfile +41 -0
- data/README.textile +68 -6
- data/Rakefile +65 -152
- data/config.ru +13 -2
- data/config.yaml +9 -4
- data/db/migrate/20110213023123_init.rb +20 -0
- data/lib/murlsh/atom_body.rb +78 -0
- data/lib/murlsh/atom_server.rb +38 -0
- data/lib/murlsh/auth.rb +12 -0
- data/lib/murlsh/build_query.rb +1 -1
- data/lib/murlsh/cat_files.rb +17 -0
- data/lib/murlsh/delicious_parse.rb +1 -0
- data/lib/murlsh/dispatch.rb +25 -11
- data/lib/murlsh/etag_add_encoding.rb +1 -1
- data/lib/murlsh/feed_body.rb +36 -0
- data/lib/murlsh/img_store.rb +27 -28
- data/lib/murlsh/install.rb +1 -0
- data/lib/murlsh/json_body.rb +5 -2
- data/lib/murlsh/json_server.rb +9 -13
- data/lib/murlsh/m3u_body.rb +28 -0
- data/lib/murlsh/m3u_server.rb +50 -0
- data/lib/murlsh/markup.rb +1 -1
- data/lib/murlsh/plugin.rb +5 -0
- data/lib/murlsh/podcast_server.rb +44 -0
- data/lib/murlsh/pop_server.rb +78 -0
- data/lib/murlsh/random_server.rb +41 -0
- data/lib/murlsh/rss_body.rb +46 -0
- data/lib/murlsh/rss_server.rb +38 -0
- data/lib/murlsh/search_conditions.rb +2 -2
- data/lib/murlsh/uri_ask.rb +2 -2
- data/lib/murlsh/url_body.rb +21 -6
- data/lib/murlsh/url_result_set.rb +2 -2
- data/lib/murlsh/url_server.rb +19 -16
- data/lib/murlsh/write_ordered_hash.rb +17 -0
- data/lib/murlsh.rb +13 -2
- data/murlsh.gemspec +41 -194
- data/plugins/add_post_60_notify_hubs.rb +3 -2
- data/plugins/add_pre_30_unajax_twitter.rb +1 -1
- data/plugins/add_pre_40_thumbnail_shortcuts.rb +23 -0
- data/plugins/add_pre_45_supplied_thumbnail.rb +4 -9
- data/plugins/add_pre_50_media_thumbnail.rb +4 -9
- data/plugins/add_pre_50_open_graph_image.rb +4 -8
- data/plugins/add_pre_60_github_title.rb +1 -1
- data/plugins/add_pre_65_html_thumb.rb +3 -8
- data/plugins/add_pre_65_img_thumb.rb +4 -9
- data/plugins/avatar_50_gravatar.rb +2 -1
- data/plugins/store_asset_40_s3.rb +40 -0
- data/plugins/store_asset_50_local.rb +22 -0
- data/public/js/js.js +0 -7
- data/spec/auth_spec.rb +7 -0
- data/spec/cat_files_spec.rb +49 -0
- data/spec/img_store_spec.rb +24 -8
- metadata +119 -76
- data/VERSION +0 -1
- data/lib/murlsh/build_md5.rb +0 -12
- data/lib/murlsh/head_from_get.rb +0 -15
- data/plugins/add_post_50_update_feed.rb +0 -84
- data/plugins/add_post_50_update_m3u.rb +0 -35
- data/plugins/add_post_50_update_podcast.rb +0 -44
- data/plugins/add_post_50_update_rss.rb +0 -51
- 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(
|
19
|
-
:user_agent => config['user_agent'])
|
13
|
+
thumb_storage = Murlsh::ImgStore.new(config)
|
20
14
|
|
21
|
-
|
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
|
-
|
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(
|
24
|
-
:user_agent => config['user_agent'])
|
18
|
+
thumb_storage = Murlsh::ImgStore.new(config)
|
25
19
|
|
26
|
-
|
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
|
-
|
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(
|
27
|
-
:user_agent => config['user_agent'])
|
22
|
+
thumb_storage = Murlsh::ImgStore.new(config)
|
28
23
|
|
29
|
-
|
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
|
-
|
28
|
+
|
29
|
+
url.thumbnail_url = stored_url if stored_url
|
34
30
|
end
|
35
31
|
end
|
36
32
|
end
|
@@ -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(
|
23
|
+
thumb_storage = Murlsh::ImgStore.new(config)
|
29
24
|
|
30
|
-
|
31
|
-
url.thumbnail_url =
|
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(
|
26
|
-
:user_agent => config['user_agent'])
|
20
|
+
thumb_storage = Murlsh::ImgStore.new(config)
|
27
21
|
|
28
|
-
|
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
|
-
|
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,
|
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
|
data/spec/img_store_spec.rb
CHANGED
@@ -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
|
-
|
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
|
-
@
|
26
|
-
@local_path = File.join(@thumb_dir, @
|
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
|
-
@
|
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
|
-
@
|
58
|
-
@local_path = File.join(@thumb_dir, @
|
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
|
-
@
|
79
|
+
@stored_url.should == "img/thumb/#{md5}.jpg"
|
64
80
|
end
|
65
81
|
|
66
82
|
end
|