murlsh 0.11.0 → 1.0.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.
Files changed (56) hide show
  1. data/.htaccess +2 -0
  2. data/README.textile +3 -33
  3. data/Rakefile +12 -5
  4. data/VERSION +1 -1
  5. data/config.ru +10 -4
  6. data/config.yaml +6 -12
  7. data/lib/murlsh/dispatch.rb +0 -6
  8. data/lib/murlsh/img_store.rb +36 -0
  9. data/lib/murlsh/markup.rb +0 -1
  10. data/lib/murlsh/plugin.rb +2 -6
  11. data/lib/murlsh/uri_ask.rb +66 -22
  12. data/lib/murlsh/url.rb +0 -18
  13. data/lib/murlsh/url_body.rb +15 -23
  14. data/lib/murlsh/url_server.rb +5 -5
  15. data/murlsh.gemspec +44 -19
  16. data/plugins/add_post_50_update_feed.rb +17 -3
  17. data/plugins/add_post_50_update_podcast.rb +46 -0
  18. data/plugins/add_post_50_update_rss.rb +18 -2
  19. data/plugins/add_post_60_notify_hubs.rb +3 -1
  20. data/plugins/add_pre_40_convert_mobile.rb +30 -0
  21. data/plugins/add_pre_50_lookup_content_type_title.rb +11 -4
  22. data/plugins/add_pre_60_flickr.rb +38 -0
  23. data/plugins/add_pre_60_github_title.rb +5 -1
  24. data/plugins/add_pre_60_google_code_title.rb +5 -2
  25. data/plugins/add_pre_60_imageshack.rb +31 -0
  26. data/plugins/add_pre_60_imgur.rb +32 -0
  27. data/plugins/add_pre_60_s3_image.rb +34 -0
  28. data/plugins/add_pre_60_twitter.rb +35 -0
  29. data/plugins/add_pre_60_vimeo.rb +35 -0
  30. data/plugins/add_pre_60_youtube.rb +31 -0
  31. data/plugins/html_parse_50_hpricot.rb +2 -0
  32. data/plugins/url_display_add_45_mp3.rb +30 -0
  33. data/plugins/url_display_add_50_hostrec.rb +38 -0
  34. data/plugins/url_display_add_55_content_type.rb +27 -0
  35. data/plugins/url_display_add_60_via.rb +52 -0
  36. data/plugins/url_display_add_65_time.rb +22 -0
  37. data/public/css/jquery.jgrowl.css +0 -3
  38. data/public/css/screen.css +0 -18
  39. data/public/img/thumb/README +0 -0
  40. data/public/js/jquery-1.4.3.min.js +166 -0
  41. data/public/js/js.js +62 -234
  42. data/public/js/twitter-text-1.0.3.js +538 -0
  43. data/spec/img_store_spec.rb +53 -0
  44. data/spec/uri_ask_spec.rb +14 -4
  45. metadata +139 -37
  46. data/lib/murlsh/flickr_server.rb +0 -55
  47. data/lib/murlsh/twitter_server.rb +0 -45
  48. data/lib/murlsh/unwrap_jsonp.rb +0 -15
  49. data/lib/murlsh/xhtml_response.rb +0 -20
  50. data/plugins/hostrec_50_redundant.rb +0 -14
  51. data/plugins/hostrec_60_skip.rb +0 -24
  52. data/plugins/time_50_ago.rb +0 -16
  53. data/plugins/via_50_domain.rb +0 -36
  54. data/public/js/jquery-1.4.2.min.js +0 -154
  55. data/spec/unwrap_json_spec.rb +0 -21
  56. data/spec/xhtml_response_spec.rb +0 -112
data/murlsh.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{murlsh}
8
- s.version = "0.11.0"
8
+ s.version = "1.0.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Matthew M. Boedicker"]
12
- s.date = %q{2010-09-21}
12
+ s.date = %q{2010-11-03}
13
13
  s.default_executable = %q{murlsh}
14
14
  s.description = %q{url sharing site framework with easy adding, title lookup, atom feed, thumbnails and embedding}
15
15
  s.email = %q{matthewm@boedicker.org}
@@ -35,51 +35,59 @@ Gem::Specification.new do |s|
35
35
  "lib/murlsh/etag_add_encoding.rb",
36
36
  "lib/murlsh/failproof.rb",
37
37
  "lib/murlsh/far_future_expires.rb",
38
- "lib/murlsh/flickr_server.rb",
39
38
  "lib/murlsh/head_from_get.rb",
39
+ "lib/murlsh/img_store.rb",
40
40
  "lib/murlsh/markup.rb",
41
41
  "lib/murlsh/must_revalidate.rb",
42
42
  "lib/murlsh/openlock.rb",
43
43
  "lib/murlsh/plugin.rb",
44
44
  "lib/murlsh/sqlite3_adapter.rb",
45
45
  "lib/murlsh/time_ago.rb",
46
- "lib/murlsh/twitter_server.rb",
47
- "lib/murlsh/unwrap_jsonp.rb",
48
46
  "lib/murlsh/uri.rb",
49
47
  "lib/murlsh/uri_ask.rb",
50
48
  "lib/murlsh/url.rb",
51
49
  "lib/murlsh/url_body.rb",
52
50
  "lib/murlsh/url_server.rb",
53
- "lib/murlsh/xhtml_response.rb",
54
51
  "lib/murlsh/yaml_ordered_hash.rb",
55
52
  "murlsh.gemspec",
56
53
  "plugins/add_post_50_update_feed.rb",
54
+ "plugins/add_post_50_update_podcast.rb",
57
55
  "plugins/add_post_50_update_rss.rb",
58
56
  "plugins/add_post_60_notify_hubs.rb",
57
+ "plugins/add_pre_40_convert_mobile.rb",
59
58
  "plugins/add_pre_50_lookup_content_type_title.rb",
59
+ "plugins/add_pre_60_flickr.rb",
60
60
  "plugins/add_pre_60_github_title.rb",
61
61
  "plugins/add_pre_60_google_code_title.rb",
62
- "plugins/hostrec_50_redundant.rb",
63
- "plugins/hostrec_60_skip.rb",
62
+ "plugins/add_pre_60_imageshack.rb",
63
+ "plugins/add_pre_60_imgur.rb",
64
+ "plugins/add_pre_60_s3_image.rb",
65
+ "plugins/add_pre_60_twitter.rb",
66
+ "plugins/add_pre_60_vimeo.rb",
67
+ "plugins/add_pre_60_youtube.rb",
64
68
  "plugins/html_parse_50_hpricot.rb",
65
- "plugins/time_50_ago.rb",
66
- "plugins/via_50_domain.rb",
69
+ "plugins/url_display_add_45_mp3.rb",
70
+ "plugins/url_display_add_50_hostrec.rb",
71
+ "plugins/url_display_add_55_content_type.rb",
72
+ "plugins/url_display_add_60_via.rb",
73
+ "plugins/url_display_add_65_time.rb",
67
74
  "public/css/jquery.jgrowl.css",
68
75
  "public/css/screen.css",
76
+ "public/img/thumb/README",
69
77
  "public/js/comments.json",
70
- "public/js/jquery-1.4.2.min.js",
78
+ "public/js/jquery-1.4.3.min.js",
71
79
  "public/js/jquery.jgrowl_compressed.js",
72
80
  "public/js/js.js",
81
+ "public/js/twitter-text-1.0.3.js",
73
82
  "public/swf/player_mp3_mini.swf",
74
83
  "spec/auth_spec.rb",
75
84
  "spec/dispatch_spec.rb",
76
85
  "spec/doc_spec.rb",
86
+ "spec/img_store_spec.rb",
77
87
  "spec/markup_spec.rb",
78
- "spec/unwrap_json_spec.rb",
79
88
  "spec/uri_ask_spec.rb",
80
89
  "spec/uri_spec.rb",
81
90
  "spec/url_spec.rb",
82
- "spec/xhtml_response_spec.rb",
83
91
  "spec/yaml_ordered_hash_spec.rb"
84
92
  ]
85
93
  s.homepage = %q{http://github.com/mmb/murlsh}
@@ -88,11 +96,10 @@ Gem::Specification.new do |s|
88
96
  s.rubygems_version = %q{1.3.7}
89
97
  s.summary = %q{url sharing site framework}
90
98
  s.test_files = [
91
- "spec/xhtml_response_spec.rb",
92
- "spec/auth_spec.rb",
99
+ "spec/auth_spec.rb",
93
100
  "spec/yaml_ordered_hash_spec.rb",
94
- "spec/unwrap_json_spec.rb",
95
101
  "spec/uri_ask_spec.rb",
102
+ "spec/img_store_spec.rb",
96
103
  "spec/dispatch_spec.rb",
97
104
  "spec/markup_spec.rb",
98
105
  "spec/url_spec.rb",
@@ -108,42 +115,60 @@ Gem::Specification.new do |s|
108
115
  s.add_runtime_dependency(%q<activerecord>, [">= 2.3.4"])
109
116
  s.add_runtime_dependency(%q<bcrypt-ruby>, [">= 2.1.2"])
110
117
  s.add_runtime_dependency(%q<builder>, [">= 2.1.2"])
118
+ s.add_runtime_dependency(%q<flickraw>, [">= 0.8.3"])
119
+ s.add_runtime_dependency(%q<flog>, [">= 2.5.0"])
111
120
  s.add_runtime_dependency(%q<hpricot>, [">= 0.8.1"])
112
121
  s.add_runtime_dependency(%q<htmlentities>, [">= 4.2.0"])
113
122
  s.add_runtime_dependency(%q<json>, [">= 1.2.3"])
114
123
  s.add_runtime_dependency(%q<push-notify>, [">= 0.1.0"])
115
124
  s.add_runtime_dependency(%q<rack>, [">= 1.0.0"])
116
125
  s.add_runtime_dependency(%q<rack-cache>, [">= 0.5.2"])
126
+ s.add_runtime_dependency(%q<rack-rewrite>, [">= 1.0.2"])
117
127
  s.add_runtime_dependency(%q<rack-throttle>, [">= 0.3.0"])
118
128
  s.add_runtime_dependency(%q<sqlite3-ruby>, [">= 1.2.1"])
119
- s.add_runtime_dependency(%q<tinyatom>, [">= 0.1.1"])
129
+ s.add_runtime_dependency(%q<tinyatom>, [">= 0.2.0"])
130
+ s.add_runtime_dependency(%q<twitter>, [">= 0.9.12"])
131
+ s.add_runtime_dependency(%q<vimeo>, [">= 1.2.2"])
132
+ s.add_runtime_dependency(%q<rspec>, ["~> 1.3"])
120
133
  else
121
134
  s.add_dependency(%q<activerecord>, [">= 2.3.4"])
122
135
  s.add_dependency(%q<bcrypt-ruby>, [">= 2.1.2"])
123
136
  s.add_dependency(%q<builder>, [">= 2.1.2"])
137
+ s.add_dependency(%q<flickraw>, [">= 0.8.3"])
138
+ s.add_dependency(%q<flog>, [">= 2.5.0"])
124
139
  s.add_dependency(%q<hpricot>, [">= 0.8.1"])
125
140
  s.add_dependency(%q<htmlentities>, [">= 4.2.0"])
126
141
  s.add_dependency(%q<json>, [">= 1.2.3"])
127
142
  s.add_dependency(%q<push-notify>, [">= 0.1.0"])
128
143
  s.add_dependency(%q<rack>, [">= 1.0.0"])
129
144
  s.add_dependency(%q<rack-cache>, [">= 0.5.2"])
145
+ s.add_dependency(%q<rack-rewrite>, [">= 1.0.2"])
130
146
  s.add_dependency(%q<rack-throttle>, [">= 0.3.0"])
131
147
  s.add_dependency(%q<sqlite3-ruby>, [">= 1.2.1"])
132
- s.add_dependency(%q<tinyatom>, [">= 0.1.1"])
148
+ s.add_dependency(%q<tinyatom>, [">= 0.2.0"])
149
+ s.add_dependency(%q<twitter>, [">= 0.9.12"])
150
+ s.add_dependency(%q<vimeo>, [">= 1.2.2"])
151
+ s.add_dependency(%q<rspec>, ["~> 1.3"])
133
152
  end
134
153
  else
135
154
  s.add_dependency(%q<activerecord>, [">= 2.3.4"])
136
155
  s.add_dependency(%q<bcrypt-ruby>, [">= 2.1.2"])
137
156
  s.add_dependency(%q<builder>, [">= 2.1.2"])
157
+ s.add_dependency(%q<flickraw>, [">= 0.8.3"])
158
+ s.add_dependency(%q<flog>, [">= 2.5.0"])
138
159
  s.add_dependency(%q<hpricot>, [">= 0.8.1"])
139
160
  s.add_dependency(%q<htmlentities>, [">= 4.2.0"])
140
161
  s.add_dependency(%q<json>, [">= 1.2.3"])
141
162
  s.add_dependency(%q<push-notify>, [">= 0.1.0"])
142
163
  s.add_dependency(%q<rack>, [">= 1.0.0"])
143
164
  s.add_dependency(%q<rack-cache>, [">= 0.5.2"])
165
+ s.add_dependency(%q<rack-rewrite>, [">= 1.0.2"])
144
166
  s.add_dependency(%q<rack-throttle>, [">= 0.3.0"])
145
167
  s.add_dependency(%q<sqlite3-ruby>, [">= 1.2.1"])
146
- s.add_dependency(%q<tinyatom>, [">= 0.1.1"])
168
+ s.add_dependency(%q<tinyatom>, [">= 0.2.0"])
169
+ s.add_dependency(%q<twitter>, [">= 0.9.12"])
170
+ s.add_dependency(%q<vimeo>, [">= 1.2.2"])
171
+ s.add_dependency(%q<rspec>, ["~> 1.3"])
147
172
  end
148
173
  end
149
174
 
@@ -1,4 +1,6 @@
1
1
  %w{
2
+ uri
3
+
2
4
  tinyatom
3
5
 
4
6
  murlsh
@@ -11,7 +13,16 @@ module Murlsh
11
13
 
12
14
  @hook = 'add_post'
13
15
 
14
- def self.run(config)
16
+ # content types to add an enclosure for
17
+ EnclosureContentTypes = %w{
18
+ application/pdf
19
+ audio/mpeg
20
+ image/gif
21
+ image/jpeg
22
+ image/png
23
+ }
24
+
25
+ def self.run(url, config)
15
26
  feed = TinyAtom::Feed.new(config['root_url'], config.fetch('page_title'),
16
27
  URI.join(config['root_url'], config['feed_file']),
17
28
  :hubs => config.fetch('pubsubhubbub_hubs', []).
@@ -26,12 +37,15 @@ module Murlsh
26
37
  :summary => mu.title_stripped
27
38
  }
28
39
 
29
- if mu.is_image?
40
+ if EnclosureContentTypes.include?(mu.content_type)
30
41
  options.merge!(
31
42
  :enclosure_type => mu.content_type,
32
43
  :enclosure_href => mu.url,
33
- :enclosure_title => 'Full-size'
44
+ :enclosure_title => mu.title
34
45
  )
46
+ if mu.content_length
47
+ options.merge!(:enclosure_length => mu.content_length)
48
+ end
35
49
  end
36
50
 
37
51
  Murlsh::failproof do
@@ -0,0 +1,46 @@
1
+ %w{
2
+ rss/maker
3
+ uri
4
+
5
+ murlsh
6
+ }.each { |m| require m }
7
+
8
+ module Murlsh
9
+
10
+ # Regenerate podcast RSS feed after a new audio/mpeg url has been added.
11
+ class AddPost50UpdatePodcast < Plugin
12
+
13
+ @hook = 'add_post'
14
+
15
+ def self.run(url, config)
16
+ if url.content_type == 'audio/mpeg'
17
+ output_file = 'podcast.rss'
18
+
19
+ feed = RSS::Maker.make('2.0') do |f|
20
+ f.channel.title = f.channel.description = config.fetch(
21
+ 'page_title', '')
22
+ f.channel.link = URI.join(config.fetch('root_url'), output_file)
23
+ f.items.do_sort = true
24
+
25
+ Murlsh::Url.all(:conditions => { :content_type => 'audio/mpeg' },
26
+ :order => 'id DESC',
27
+ :limit => config.fetch('num_posts_feed', 25)).each do |mu|
28
+ i = f.items.new_item
29
+ i.title = mu.title_stripped
30
+ i.link = mu.url
31
+ i.date = mu.time
32
+
33
+ i.enclosure.url = mu.url
34
+ i.enclosure.type = mu.content_type
35
+ i.enclosure.length = mu.content_length
36
+ end
37
+
38
+ end
39
+
40
+ Murlsh::openlock(output_file, 'w') { |f| f.write(feed) }
41
+ end
42
+ end
43
+
44
+ end
45
+
46
+ end
@@ -1,5 +1,6 @@
1
1
  %w{
2
2
  rss/maker
3
+ uri
3
4
 
4
5
  murlsh
5
6
  }.each { |m| require m }
@@ -11,8 +12,17 @@ module Murlsh
11
12
 
12
13
  @hook = 'add_post'
13
14
 
14
- def self.run(config)
15
- output_file = 'rss.xml'
15
+ # content types to add an enclosure for
16
+ EnclosureContentTypes = %w{
17
+ application/pdf
18
+ audio/mpeg
19
+ image/gif
20
+ image/jpeg
21
+ image/png
22
+ }
23
+
24
+ def self.run(url, config)
25
+ output_file = 'rss.rss'
16
26
 
17
27
  feed = RSS::Maker.make('2.0') do |f|
18
28
  f.channel.title = f.channel.description = config.fetch('page_title', '')
@@ -25,6 +35,12 @@ module Murlsh
25
35
  i.title = mu.title_stripped
26
36
  i.link = mu.url
27
37
  i.date = mu.time
38
+
39
+ if EnclosureContentTypes.include?(mu.content_type)
40
+ i.enclosure.url = mu.url
41
+ i.enclosure.type = mu.content_type
42
+ i.enclosure.length = mu.content_length
43
+ end
28
44
  end
29
45
 
30
46
  end
@@ -1,4 +1,6 @@
1
1
  %w{
2
+ uri
3
+
2
4
  murlsh
3
5
  }.each { |m| require m }
4
6
 
@@ -9,7 +11,7 @@ module Murlsh
9
11
 
10
12
  @hook = 'add_post'
11
13
 
12
- def self.run(config)
14
+ def self.run(url, config)
13
15
  hubs = config.fetch('pubsubhubbub_hubs', [])
14
16
 
15
17
  unless hubs.empty?
@@ -0,0 +1,30 @@
1
+ %w{
2
+ murlsh
3
+ }.each { |m| require m }
4
+
5
+ module Murlsh
6
+
7
+
8
+ # Convert urls specifically for use on mobile devices into their non-mobile
9
+ # equivalents.
10
+ class AddPre40ConvertMobile < Plugin
11
+
12
+ @hook = 'add_pre'
13
+
14
+ TwitterRe = %r{^(http://)mobile\.(twitter\.com/.*)$}i
15
+ WikipediaRe = %r{^(http://[a-z]+\.)m\.(wikipedia\.org/.*)$}i
16
+
17
+ def self.run(url, config)
18
+ url.url = case
19
+ when match = TwitterRe.match(url.url)
20
+ "#{match[1]}#{match[2]}"
21
+ when match = WikipediaRe.match(url.url)
22
+ "#{match[1]}#{match[2]}"
23
+ else
24
+ url.url
25
+ end
26
+ end
27
+
28
+ end
29
+
30
+ end
@@ -1,19 +1,26 @@
1
1
  %w{
2
+ uri
3
+
2
4
  murlsh
3
5
  }.each { |m| require m }
4
6
 
5
7
  module Murlsh
6
8
 
7
- # try to fetch the content type and title of a url
9
+ # try to fetch the content length, content type and title of a url
8
10
  class AddPre50LookupContentTypeTitle < Plugin
9
11
 
10
12
  @hook = 'add_pre'
11
13
 
12
14
  def self.run(url, config)
13
15
  ask = URI(url.url).extend(Murlsh::UriAsk)
14
- headers = {
15
- 'User-Agent' => 'murlsh (http://github.com/mmb/murlsh)'
16
- }
16
+ headers = {}
17
+ headers['User-Agent'] = config['user_agent'] if config['user_agent']
18
+
19
+ content_length = ask.content_length(:headers => headers)
20
+ if content_length and not content_length.empty?
21
+ url.content_length = content_length
22
+ end
23
+
17
24
  url.content_type = ask.content_type(:headers => headers)
18
25
  url.title = ask.title(:headers => headers)
19
26
  end
@@ -0,0 +1,38 @@
1
+ %w{
2
+ cgi
3
+
4
+ flickraw
5
+
6
+ murlsh
7
+ }.each { |m| require m }
8
+
9
+ module Murlsh
10
+
11
+ # Set the title and thumbnail url of Flickr photos.
12
+ class AddPre60Flickr < Plugin
13
+
14
+ @hook = 'add_pre'
15
+
16
+ FlickrRe = %r{^http://(?:www\.)?flickr\.com/photos/[@\w\-]+?/([\d]+)}i
17
+ StorageDir = File.join(File.dirname(__FILE__), '..', 'public', 'img',
18
+ 'thumb')
19
+
20
+ def self.run(url, config)
21
+ if config['flickr_api_key'] and not config['flickr_api_key'].empty?
22
+ if photo_id = url.url[FlickrRe, 1]
23
+ FlickRaw.api_key = config['flickr_api_key']
24
+ info = flickr.photos.getInfo(:photo_id => photo_id)
25
+
26
+ url.title = "#{info.title} by #{info.owner.username}"
27
+
28
+ thumb_storage = Murlsh::ImgStore.new(StorageDir,
29
+ :user_agent => config['user_agent'])
30
+ stored_filename = thumb_storage.store(FlickRaw.url_s(info))
31
+ url.thumbnail_url = "img/thumb/#{CGI.escape(stored_filename)}"
32
+ end
33
+ end
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -1,4 +1,6 @@
1
1
  %w{
2
+ uri
3
+
2
4
  murlsh
3
5
  }.each { |m| require m }
4
6
 
@@ -10,8 +12,10 @@ module Murlsh
10
12
 
11
13
  @hook = 'add_pre'
12
14
 
15
+ GithubRe = %r{^http://github\.com/\w+/[\w.-]+$}i
16
+
13
17
  def self.run(url, config)
14
- if url.url[%r{^http://github\.com/\w+/[\w.-]+$}]
18
+ if url.url[GithubRe]
15
19
  ask = URI(url.url).extend(Murlsh::UriAsk)
16
20
  url.title << " - #{ask.description}" unless ask.description.empty?
17
21
  end
@@ -1,4 +1,6 @@
1
1
  %w{
2
+ uri
3
+
2
4
  murlsh
3
5
  }.each { |m| require m }
4
6
 
@@ -10,9 +12,10 @@ module Murlsh
10
12
 
11
13
  @hook = 'add_pre'
12
14
 
15
+ GoogleCodeRe = %r{^http://code\.google\.com/p/[\w-]+/$}i
16
+
13
17
  def self.run(url, config)
14
- if url.url[%r{^http://code\.google\.com/p/[\w-]+/$}]
15
- puts 'xxx'
18
+ if url.url[GoogleCodeRe]
16
19
  ask = URI(url.url).extend(Murlsh::UriAsk)
17
20
  ask.doc.xpath_search("//a[@id='project_summary_link']") do |node|
18
21
  summary = node ? node.inner_html : nil
@@ -0,0 +1,31 @@
1
+ %w{
2
+ cgi
3
+
4
+ murlsh
5
+ }.each { |m| require m }
6
+
7
+ module Murlsh
8
+
9
+ # Set the thumbnail of imageshack images.
10
+ class AddPre60Imageshack < Plugin
11
+
12
+ @hook = 'add_pre'
13
+
14
+ ImageshackRe =
15
+ %r{^(http://img\d+\.imageshack\.us/img\d+/\d+/)(\w+)\.(jpe?g|gif|png)$}i
16
+ StorageDir = File.join(File.dirname(__FILE__), '..', 'public', 'img',
17
+ 'thumb')
18
+
19
+ def self.run(url, config)
20
+ if match = ImageshackRe.match(url.url)
21
+ thumb_storage = Murlsh::ImgStore.new(StorageDir,
22
+ :user_agent => config['user_agent'])
23
+ stored_filename = thumb_storage.store(
24
+ "#{match[1]}#{match[2]}.th.#{match[3]}")
25
+ url.thumbnail_url = "img/thumb/#{CGI.escape(stored_filename)}"
26
+ end
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -0,0 +1,32 @@
1
+ %w{
2
+ cgi
3
+
4
+ murlsh
5
+ }.each { |m| require m }
6
+
7
+ module Murlsh
8
+
9
+ # Add YouTube thumbnail.
10
+ class AddPre60Imgur < Plugin
11
+
12
+ @hook = 'add_pre'
13
+
14
+ ImgurRe = %r{^(http://(?:i\.)?imgur\.com/)([a-z\d]+)(\.(?:jpe?g|gif|png))$}i
15
+ StorageDir = File.join(File.dirname(__FILE__), '..', 'public', 'img',
16
+ 'thumb')
17
+
18
+ def self.run(url, config)
19
+ if match = ImgurRe.match(url.url)
20
+ url.title = "imgur/#{match[2]}s#{match[3]}"
21
+
22
+ thumb_storage = Murlsh::ImgStore.new(StorageDir,
23
+ :user_agent => config['user_agent'])
24
+ stored_filename = thumb_storage.store(
25
+ "#{match[1]}#{match[2]}s#{match[3]}")
26
+ url.thumbnail_url = "img/thumb/#{CGI.escape(stored_filename)}"
27
+ end
28
+ end
29
+
30
+ end
31
+
32
+ end
@@ -0,0 +1,34 @@
1
+ %w{
2
+ cgi
3
+
4
+ murlsh
5
+ }.each { |m| require m }
6
+
7
+ module Murlsh
8
+
9
+ # Set the thumbnail of s3 hosted images.
10
+ class AddPre60S3Image < Plugin
11
+
12
+ @hook = 'add_pre'
13
+
14
+ S3ImageRe = %r{^(http://static\.mmb\.s3\.amazonaws\.com/)([\w\-]+)\.(jpe?g|gif|pdf|png)$}i
15
+ StorageDir = File.join(File.dirname(__FILE__), '..', 'public', 'img',
16
+ 'thumb')
17
+
18
+ def self.run(url, config)
19
+ if match = S3ImageRe.match(url.url)
20
+ extension = match[3].downcase == 'pdf' ? 'png' : match[3]
21
+
22
+ thumb_storage = Murlsh::ImgStore.new(StorageDir,
23
+ :user_agent => config['user_agent'])
24
+ stored_filename = thumb_storage.store(
25
+ "#{match[1]}#{match[2]}.th.#{extension}")
26
+
27
+ url.thumbnail_url = "img/thumb/#{CGI.escape(stored_filename)}"
28
+ url.title = match[2]
29
+ end
30
+ end
31
+
32
+ end
33
+
34
+ end
@@ -0,0 +1,35 @@
1
+ %w{
2
+ cgi
3
+
4
+ twitter
5
+
6
+ murlsh
7
+ }.each { |m| require m }
8
+
9
+ module Murlsh
10
+
11
+ # Set title to entire tweet and set thumbnail url.
12
+ class AddPre60Twitter < Plugin
13
+
14
+ @hook = 'add_pre'
15
+
16
+ TwitterRe = %r{^https?://twitter\.com/\w+/status(?:es)?/(\d+)$}i
17
+ StorageDir = File.join(File.dirname(__FILE__), '..', 'public', 'img',
18
+ 'thumb')
19
+
20
+ def self.run(url, config)
21
+ if tweet_id = url.url[TwitterRe, 1]
22
+ tweet = Twitter.status(tweet_id)
23
+
24
+ url.title = "@#{tweet.user.screen_name}: #{tweet.text}"
25
+
26
+ thumb_storage = Murlsh::ImgStore.new(StorageDir,
27
+ :user_agent => config['user_agent'])
28
+ stored_filename = thumb_storage.store(tweet.user.profile_image_url)
29
+ url.thumbnail_url = "img/thumb/#{CGI.escape(stored_filename)}"
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,35 @@
1
+ %w{
2
+ cgi
3
+
4
+ vimeo
5
+
6
+ murlsh
7
+ }.each { |m| require m }
8
+
9
+ module Murlsh
10
+
11
+ # Set title and thumbnail url for Vimeo urls.
12
+ class AddPre60Vimeo < Plugin
13
+
14
+ @hook = 'add_pre'
15
+
16
+ VimeoRe = %r{^http://(?:www\.)?vimeo\.com/(\d+)$}i
17
+ StorageDir = File.join(File.dirname(__FILE__), '..', 'public', 'img',
18
+ 'thumb')
19
+
20
+ def self.run(url, config)
21
+ if id = url.url[VimeoRe, 1]
22
+ info = Vimeo::Simple::Video.info(id)[0]
23
+
24
+ url.title = "#{info['title']} by #{info['user_name']}"
25
+
26
+ thumb_storage = Murlsh::ImgStore.new(StorageDir,
27
+ :user_agent => config['user_agent'])
28
+ stored_filename = thumb_storage.store(info['thumbnail_small'])
29
+ url.thumbnail_url = "img/thumb/#{CGI.escape(stored_filename)}"
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,31 @@
1
+ %w{
2
+ cgi
3
+
4
+ murlsh
5
+ }.each { |m| require m }
6
+
7
+ module Murlsh
8
+
9
+ # Add YouTube thumbnail.
10
+ class AddPre60Youtube < Plugin
11
+
12
+ @hook = 'add_pre'
13
+
14
+ YoutubeRe =
15
+ %r{^http://(?:(?:www|uk)\.)?youtube\.com/watch\?v=([\w\-]+)(?:&|$)}i
16
+ StorageDir = File.join(File.dirname(__FILE__), '..', 'public', 'img',
17
+ 'thumb')
18
+
19
+ def self.run(url, config)
20
+ if youtube_id = url.url[YoutubeRe, 1]
21
+ thumb_storage = Murlsh::ImgStore.new(StorageDir,
22
+ :user_agent => config['user_agent'])
23
+ stored_filename = thumb_storage.store(
24
+ "http://img.youtube.com/vi/#{youtube_id}/default.jpg")
25
+ url.thumbnail_url = "img/thumb/#{CGI.escape(stored_filename)}"
26
+ end
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -1,5 +1,7 @@
1
1
  %w{
2
2
  hpricot
3
+
4
+ murlsh
3
5
  }.each { |m| require m }
4
6
 
5
7
  module Murlsh