murlsh 1.4.1 → 1.5.0
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.
- 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
|