muri 0.0.13 → 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.
data/README.textile CHANGED
@@ -8,7 +8,7 @@ MURI Currently supports:
8
8
  * Vimeo (single videos and albums)
9
9
  ** "API documentation":http://vimeo.com/api/docs/simple-api
10
10
  * Flickr (single images and sets)
11
- ** "API documentation":http://www.flickr.com/services/api/
11
+ ** "API documentation":http://www.flickr.com/services/api/ or "[2]":http://developer.yahoo.com/flickr/
12
12
  * Imageshack
13
13
  * Photobucket
14
14
  ** "API documentation":http://photobucket.com/developer/documentation
@@ -41,10 +41,10 @@ Assuming the URI was successfully parsed (thus @a.valid? == true@), all media ty
41
41
 
42
42
  <pre>
43
43
  <code>
44
- a.service # 'Youtube'
45
- a.media_id # 'blahblahblah'
46
- a.original_url # 'http://www.youtube.com/watch?v=blahblahblah&feature=rec-LGOUT-exp_fresh+div-1r-1-HM'
47
- a.uri # URI object for 'http://www.youtube.com/watch?v=blahblahblah&feature=rec-LGOUT-exp_fresh+div-1r-1-HM'
44
+ a.media_service # 'Youtube'
45
+ a.media_id # 'blahblahblah'
46
+ a.media_original_url # 'http://www.youtube.com/watch?v=blahblahblah&feature=rec-LGOUT-exp_fresh+div-1r-1-HM'
47
+ a.media_uri # URI object for 'http://www.youtube.com/watch?v=blahblahblah&feature=rec-LGOUT-exp_fresh+div-1r-1-HM'
48
48
  </code>
49
49
  </pre>
50
50
 
@@ -53,7 +53,7 @@ Assuming the URI was successfully parsed (thus @a.valid? == true@), all media ty
53
53
  * All but Imageshack have a @media_api_id@, which is the ID which can be used in API calls to the related services. Typically the same as @media_id@.
54
54
 
55
55
  <pre>
56
- <code>
56
+ <code>
57
57
  a.media_api_id # 'blahblahblah'
58
58
  </code>
59
59
  </pre>
@@ -76,7 +76,7 @@ d
76
76
 
77
77
  <pre>
78
78
  <code>
79
- a.website # 'http://www.youtube.com/watch?v=blahblahblah'
79
+ a.media_website # 'http://www.youtube.com/watch?v=blahblahblah'
80
80
  </code>
81
81
  </pre>
82
82
 
@@ -84,7 +84,7 @@ d
84
84
 
85
85
  <pre>
86
86
  <code>
87
- a.content_type # 'jpg' (Content Type also for Imageshack and Photobucket)
87
+ a.media_content_type # 'jpg' (Content Type also for Imageshack and Photobucket)
88
88
  </code>
89
89
  </pre>
90
90
 
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
- :major: 0
2
+ :major: 1
3
3
  :minor: 0
4
- :patch: 13
4
+ :patch: 0
data/lib/muri/base.rb CHANGED
@@ -1,112 +1,92 @@
1
- require 'uri'
2
1
  class Muri
3
2
 
3
+ attr_reader :uri, :errors
4
+
4
5
  # NoParser raised if no parser is found for URI
5
6
  class NoParser < StandardError; end
6
-
7
- # UnsupportedURI raised if parser is found, but URI path does not
7
+
8
+ # UnsupportedURI raised if parser is found, but URI path does not
8
9
  # match accepted formats
9
10
  class UnsupportedURI < ArgumentError; end
10
-
11
- PARSERS = {}
12
-
13
- include Filter::Youtube
14
- include Filter::Flickr
15
- include Filter::Vimeo
16
- include Filter::Imageshack
17
- include Filter::Photobucket
18
- include Filter::Facebook
19
- include Filter::Twitpic
11
+
12
+ PARSERS = { }
13
+
14
+ # Defines is_#{service}? and is_#{service type constant}? methods, and sets service name constnat
15
+ ['Youtube', 'Flickr', 'Vimeo', 'Imageshack', 'Photobucket', 'Facebook', 'Twitpic'].each do |filter|
16
+ eval "include Filter::#{filter}"
17
+ is_service = "is_#{filter.downcase}?"
18
+ define_method(is_service) { self.media_service == filter }
19
+ self.constants.reject { |c| c !~ /^#{filter.upcase}/ }.each do |exp|
20
+ define_method("is_#{exp.downcase}?") { self.media_api_type == eval(exp) && eval("self.#{is_service}") }
21
+ end
22
+ const_set "#{filter.upcase}_SERVICE_NAME", "#{filter}"
23
+ end
20
24
 
21
25
  def self.parse(url)
22
26
  self.new(url)
23
27
  end
24
-
25
- def initialize(url)
26
- @info = { }
27
- _parse(url)
28
- end
29
28
 
30
- def to_yaml
31
- @info.to_yaml
29
+ # Show a list of the available parsers
30
+ def self.parsers
31
+ PARSERS.keys
32
32
  end
33
33
 
34
- def to_s
35
- @info.to_s
34
+ def initialize(url)
35
+ @info = { }
36
+ _parse(url)
36
37
  end
37
38
 
39
+ # Determine if Muri object is valid (errors mean not valid)
38
40
  def valid?
39
- @info[:media_id].nil? ? false : true
41
+ self.errors.nil?
40
42
  end
41
43
 
42
- # Taken from uri/generic.rb
43
- @@to_s = Kernel.instance_method(:to_s)
44
- def inspect
45
- @@to_s.bind(self).call.sub!(/>\z/) {" URL:#{self.original_url}>"}
44
+ def to_s
45
+ @info.to_s
46
46
  end
47
-
48
- def parsers
49
- PARSERS.keys
47
+
48
+ # 'Borrowed' from uri/generic.rb
49
+ def inspect
50
+ Kernel.instance_method(:to_s).bind(self).call.sub!(/>\z/) {" URL:#{self.uri.to_s}>"}
50
51
  end
51
-
52
+
52
53
  private
54
+ attr_writer :uri, :errors
55
+
56
+ def self.determine_feed_parser(uri)
57
+ PARSERS.keys.detect {|klass| klass.parsable?(uri)}
58
+ end
53
59
 
54
60
  def _parse(raw_url)
55
61
  begin
56
- @url = URI.parse(raw_url)
57
- if @url.scheme.nil?
62
+ self.uri = URI.parse(raw_url)
63
+ if self.uri.scheme.nil?
58
64
  raw_url = "http://#{raw_url}"
59
- @url = URI.parse(raw_url)
65
+ self.uri = URI.parse(raw_url)
60
66
  end
61
- if parser = determine_feed_parser
62
- @info[:uri] = @url
63
- @info[:original_url] = raw_url
67
+ if parser = Muri.determine_feed_parser(self.uri)
64
68
  send(PARSERS[parser])
65
69
  else
66
70
  raise NoParser
67
71
  end
68
72
  rescue NoParser, UnsupportedURI, URI::BadURIError, URI::InvalidURIError => e
69
- @info[:errors] = "#{e.class}"
73
+ self.errors = "#{e.class}"
70
74
  end
71
75
  end
72
-
73
- def determine_feed_parser
74
- PARSERS.keys.detect {|klass| klass.parsable?(@url)}
75
- end
76
-
77
- def method_missing(func, args = nil)
78
- @info[func.to_sym].nil? ? nil : @info[func.to_sym]
79
- end
80
-
81
- protected
82
-
83
- #used by flickr. Ported from PHP.
84
- def self.decode58(str)
85
- decoded = 0
86
- multi = 1
87
- alphabet = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"
88
- while str.length > 0
89
- digit = str[(str.length - 1),1]
90
- decoded += multi * alphabet.index(digit)
91
- multi = multi * alphabet.length
92
- str.chop!
76
+
77
+ def method_missing(method, *arguments, &block)
78
+ if method.to_s =~ /^media_(.+)/
79
+ process_option_method(method, *arguments)
80
+ else
81
+ super
93
82
  end
94
-
95
- decoded
96
83
  end
97
-
98
- #used by flickr. Ported from PHP.
99
- def self.encode58(str)
100
- alphabet = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"
101
- base_count = alphabet.length
102
- encoded = ''
103
- while str >= base_count
104
- div = str / base_count
105
- mod = (str-(base_count * div))
106
- encoded = alphabet[mod,1] + encoded
107
- str = div
84
+
85
+ def process_option_method(method, *arguments)
86
+ if method.to_s =~ /^media_(.+)=/
87
+ @info[$1.to_sym] = arguments.first
88
+ elsif method.to_s =~ /^media_(.+)/
89
+ @info[$1.to_sym]
108
90
  end
109
- encoded = (alphabet[str,1] + encoded) if str
110
- encoded
111
91
  end
112
92
  end
data/lib/muri/filter.rb CHANGED
@@ -0,0 +1,13 @@
1
+ class Muri
2
+
3
+ protected
4
+
5
+ def self.param_parse(query)
6
+ return { } if query.nil?
7
+ params_flat = { }
8
+ params = CGI::parse(query)
9
+ params.each {|k,v| params_flat[k] = v.first}
10
+ params_flat
11
+ end
12
+
13
+ end
@@ -1,68 +1,66 @@
1
- require 'cgi'
2
1
  class Muri
3
2
  module Filter
4
3
  module Facebook
5
-
4
+
5
+ private
6
6
  FACEBOOK_PHOTO = "photo"
7
7
  #FACEBOOK_VIDEO = "video"
8
8
  FACEBOOK_ALBUM = "album"
9
-
9
+ REGEX_FACEBOOK_PHOTO = /^\/photo\.php$/i
10
+ REGEX_FACEBOOK_ALBUM = /^\/album\.php$/i
11
+
10
12
  def self.included(base)
11
13
  base.class_eval do
12
14
  self::PARSERS[Muri::Filter::Facebook] = "facebook_parse"
13
15
  end
14
16
  end
15
-
17
+
18
+ def self.parsable?(uri)
19
+ uri.host =~ /^(www\.)?facebook\.com$/i
20
+ end
21
+
16
22
  def facebook_parse
17
- @info[:service] = 'Facebook'
18
- params = @url.query.nil? ? {} : CGI::parse(@url.query)#.each {|k,v| b[k] = v.first}
23
+ self.media_service = FACEBOOK_SERVICE_NAME #'Facebook'
24
+ params = Muri.param_parse(self.uri.query)
25
+
19
26
  url_common = "http://www.facebook.com"
20
-
21
- # if @url.path =~ /^\/v\/([0-9]+)/
27
+
28
+ # if self.uri.path =~ /^\/v\/([0-9]+)/
22
29
  # @info[:media_id] = $1
23
30
  # @info[:media_url] = "#{url_common}/v/#{@info[:media_id]}"
24
- #
31
+ #
25
32
  # # Currently no API for video, but media_id is best guess value for such content
26
33
  # @info[:media_api_id] = @info[:media_id]
27
34
  # @info[:media_api_type] = FACEBOOK_VIDEO
28
- if ((@url.path =~ /^\/photo\.php$/i) &&
29
- params.include?("pid") && params["pid"].first =~ /^([0-9]+)$/ &&
30
- params.include?("id") && params["id"].first =~ /^([0-9]+)$/ &&
31
- params.include?("l") && params["l"].first =~ /^([0-9a-z]+)$/i)
32
-
33
- @info[:media_api_type] = FACEBOOK_PHOTO
34
- @info[:media_id] = params["pid"].first
35
- media_creator = params["id"].first
36
- share_key = params["l"].first
37
-
38
- @info[:website] = "#{url_common}/photo.php?pid=#{@info[:media_id]}&l=#{share_key}&id=#{media_creator}"
39
- elsif ((@url.path =~ /^\/album\.php$/i) &&
40
- params.include?("aid") && params["aid"].first =~ /^([0-9]+)$/ &&
41
- params.include?("id") && params["id"].first =~ /^([0-9]+)$/ &&
42
- params.include?("l") && params["l"].first =~ /^([0-9a-z]+)$/i)
43
-
44
- @info[:media_api_type] = FACEBOOK_ALBUM
45
- @info[:media_id] = params["aid"].first
46
- media_creator = params["id"].first
47
- share_key = params["l"].first
48
-
49
- @info[:website] = "#{url_common}/album.php?aid=#{@info[:media_id]}&l=#{share_key}&id=#{media_creator}"
50
- end
51
-
52
- if self.valid?
53
- # The media_api_id is the PID which can be searched for in the facebook photos/albums table
54
- @info[:media_api_id] = (media_creator.to_i << 32) + @info[:media_id].to_i
35
+ if ((self.uri.path =~ REGEX_FACEBOOK_PHOTO) &&
36
+ params["pid"] =~ /^([0-9]+)$/ &&
37
+ params["id"] =~ /^([0-9]+)$/ &&
38
+ params["l"] =~ /^([0-9a-z]+)$/i)
39
+
40
+ self.media_api_type = FACEBOOK_PHOTO
41
+ self.media_id = params["pid"]
42
+ media_creator = params["id"]
43
+ share_key = params["l"]
44
+
45
+ self.media_website = "#{url_common}/photo.php?pid=#{self.media_id}&l=#{share_key}&id=#{media_creator}"
46
+ elsif ((self.uri.path =~ REGEX_FACEBOOK_ALBUM) &&
47
+ params["aid"] =~ /^([0-9]+)$/ &&
48
+ params["id"] =~ /^([0-9]+)$/ &&
49
+ params["l"] =~ /^([0-9a-z]+)$/i)
50
+
51
+ self.media_api_type = FACEBOOK_ALBUM
52
+ self.media_id = params["aid"]
53
+ media_creator = params["id"]
54
+ share_key = params["l"]
55
+
56
+ self.media_website = "#{url_common}/album.php?aid=#{self.media_id}&l=#{share_key}&id=#{media_creator}"
55
57
  else
56
58
  raise UnsupportedURI
57
59
  end
58
-
59
- self
60
- end
61
-
62
- def self.parsable?(uri)
63
- uri.host =~ /^(www\.)?facebook\.com$/i
60
+
61
+ # The media_api_id is the PID which can be searched for in the facebook photos/albums table
62
+ self.media_api_id = (media_creator.to_i << 32) +self.media_id.to_i
64
63
  end
65
-
66
64
  end
67
65
  end
68
66
  end
@@ -73,4 +71,4 @@ end
73
71
  # id = user id
74
72
  # l = photo share key
75
73
  # http://www.facebook.com/v/614695029223 (full) - deprecated
76
- # http://www.facebook.com/album.php?aid=2149275&id=15201063&l=99900807c3
74
+ # http://www.facebook.com/album.php?aid=2149275&id=15201063&l=99900807c3
@@ -1,56 +1,84 @@
1
1
  class Muri
2
2
  module Filter
3
3
  module Flickr
4
-
4
+
5
+ private
5
6
  FLICKR_PHOTO = "photo"
6
7
  FLICKR_SET = "set"
7
-
8
+
9
+ REGEX_FLICKR_PHOTO_OR_SET = /^\/photos\/([a-z0-9\-\_\@]+?)\/(sets\/)?([0-9]+)/i
10
+ REGEX_FLICKR_STATIC_PHOTO = /^farm([1-3])\.static.flickr.com\/([0-9]+?)\/([0-9]+?)\_([a-z0-9]+?)((?:\_[a-z]){1,2}){0,1}\.([a-z]+)/i
11
+ REGEX_FLICKR_SHORTURL = /^flic\.kr\/p\/([a-z0-9]+)/i
12
+
8
13
  def self.included(base)
9
14
  base.class_eval do
10
15
  self::PARSERS[Muri::Filter::Flickr] = "flickr_parse"
11
16
  end
12
17
  end
13
-
18
+
19
+ def self.parsable?(uri)
20
+ uri.host =~ /^(www\.)?(flic\.kr|(farm[0-9]\.static\.|)(flickr)\.com)/i
21
+ end
22
+
14
23
  def flickr_parse
15
- @info[:service] = 'Flickr'
16
-
17
- if @url.path =~ /^\/photos\/([a-z0-9\-\_\@]+?)\/(sets\/)?([0-9]+)/i
24
+ self.media_service = FLICKR_SERVICE_NAME #'Flickr'
25
+
26
+ if self.uri.path =~ REGEX_FLICKR_PHOTO_OR_SET
18
27
  media_creator = $1
19
- @info[:media_id] = $3
20
- @info[:media_api_type] = $2.nil? ? FLICKR_PHOTO : FLICKR_SET
21
- elsif (@url.host + @url.path) =~ /^farm([1-3])\.static.flickr.com\/([0-9]+?)\/([0-9]+?)\_([a-z0-9]+?)(\_[a-z]){0,1}\.([a-z]+)/i
28
+ self.media_id = $3
29
+ self.media_api_type = $2.nil? ? FLICKR_PHOTO : FLICKR_SET
30
+ elsif (self.uri.host + self.uri.path) =~ REGEX_FLICKR_STATIC_PHOTO
22
31
  farm = $1
23
32
  server_id = $2
24
- @info[:media_id] = $3
25
- @info[:media_api_type] = FLICKR_PHOTO
33
+ self.media_id = $3
34
+ self.media_api_type = FLICKR_PHOTO
26
35
  media_secret = $4
27
- url_prefix = "http://farm#{farm}.static.flickr.com/#{server_id}/#{@info[:media_id]}_#{media_secret}"
28
- @info[:media_url] = "#{url_prefix}.jpg"
29
- @info[:media_thumbnail] = "#{url_prefix}_t.jpg"
30
- elsif (@url.host + @url.path) =~ /^flic\.kr\/p\/([a-z0-9]+)/i
31
- @info[:media_id] = self.class.decode58($1)
32
- @info[:media_api_type] = FLICKR_PHOTO
33
- end
34
-
35
- if self.valid?
36
- @info[:media_api_id] = @info[:media_id]
37
- if @info[:media_api_type] == FLICKR_PHOTO
38
- @info[:website] = "http://flic.kr/p/" + self.class.encode58(@info[:media_id].to_i)
39
- elsif @info[:media_api_type] == FLICKR_SET
40
- @info[:website] = "http://www.flickr.com/photos/#{media_creator}/sets/#{@info[:media_id]}"#/show takes direct
41
- end
36
+ url_prefix = "http://farm#{farm}.static.flickr.com/#{server_id}/#{self.media_id}_#{media_secret}"
37
+ self.media_url = "#{url_prefix}.jpg"
38
+ self.media_thumbnail = "#{url_prefix}_t.jpg"
39
+ elsif (self.uri.host + self.uri.path) =~ REGEX_FLICKR_SHORTURL
40
+ self.media_id = Filter::Flickr.decode58($1)
41
+ self.media_api_type = FLICKR_PHOTO
42
42
  else
43
43
  raise UnsupportedURI
44
44
  end
45
-
46
- self
45
+
46
+ self.media_api_id = self.media_id
47
+ if self.is_flickr_photo?
48
+ self.media_website = "http://flic.kr/p/" + Filter::Flickr.encode58(self.media_id.to_i)
49
+ elsif self.is_flickr_set?
50
+ self.media_website = "http://www.flickr.com/photos/#{media_creator}/sets/#{self.media_id}" # appending /show takes direct to image through redirect
51
+ end
47
52
  end
48
53
 
49
- def self.parsable?(uri)
50
- uri.host =~ /^(www\.)?(flic\.kr|(farm[0-9]\.static\.|)(flickr)\.com)/i
51
- end
52
-
53
-
54
+ # Ported from PHP.
55
+ def self.decode58(str)
56
+ decoded = 0
57
+ multi = 1
58
+ alphabet = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"
59
+ while str.length > 0
60
+ digit = str[(str.length - 1),1]
61
+ decoded += multi * alphabet.index(digit)
62
+ multi = multi * alphabet.length
63
+ str.chop!
64
+ end
65
+ decoded
66
+ end
67
+
68
+ # Ported from PHP.
69
+ def self.encode58(str)
70
+ alphabet = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"
71
+ base_count = alphabet.length
72
+ encoded = ''
73
+ while str >= base_count
74
+ div = str / base_count
75
+ mod = (str-(base_count * div))
76
+ encoded = alphabet[mod,1] + encoded
77
+ str = div
78
+ end
79
+ encoded = (alphabet[str,1] + encoded) if str
80
+ encoded
81
+ end
54
82
  end
55
83
  end
56
84
  end
@@ -61,7 +89,7 @@ end
61
89
  # when '_m' then 'small'
62
90
  # when '_b' then 'large'
63
91
  # when '_o' then 'original'
64
- # else nil
92
+ # else 'medium'
65
93
  # end
66
94
  # end
67
95
  # @info[:content_type] = $6
@@ -2,43 +2,40 @@ class Muri
2
2
  module Filter
3
3
  module Imageshack
4
4
 
5
+ private
6
+
5
7
  def self.included(base)
6
8
  base.class_eval do
7
9
  self::PARSERS[Muri::Filter::Imageshack] = "imageshack_parse"
8
10
  end
9
11
  end
10
-
12
+
13
+ def self.parsable?(uri)
14
+ uri.host =~ /^img([0-9]*?)\.imageshack\.us$/i #/^(img([0-9]*?)\.imageshack\.us)|(yfrog\.com)/i
15
+ end
16
+
11
17
  def imageshack_parse
12
- @info[:service] = 'Imageshack'
13
-
14
- @url.host =~ /^img([0-9]*?)\.imageshack\.us/i
18
+ self.media_service = IMAGESHACK_SERVICE_NAME #'Imageshack'
19
+
20
+ self.uri.host =~ /^img([0-9]*?)\.imageshack\.us/i
15
21
  server_id = $1
16
22
  url_common = "http://img#{server_id}.imageshack.us"
17
-
18
- if @url.path =~ /^\/i\/([a-z0-9]+?)\.([a-z0-9]+)(\/)?/i
19
- @info[:media_id] = $1
20
- @info[:content_type] = $2
21
- elsif @url.path =~ /^\/img([0-9]*?)\/([0-9]+?)\/([a-z0-9]+?)\.([a-z0-9]+)/i
23
+
24
+ if self.uri.path =~ /^\/i\/([a-z0-9]+?)\.([a-z0-9]+)(\/)?/i
25
+ self.media_id = $1
26
+ self.media_content_type = $2
27
+ elsif self.uri.path =~ /^\/img([0-9]*?)\/([0-9]+?)\/([a-z0-9]+?)\.([a-z0-9]+)/i
22
28
  content_server_id = $2
23
- @info[:media_id] = $3
24
- @info[:content_type] = $4
25
- @info[:media_url] = "#{url_common}/img#{server_id}/#{content_server_id}/#{@info[:media_id]}.#{@info[:content_type]}"
26
- end
27
-
28
- # imageshack does not currently have API for retrieving individual video information
29
- if self.valid?
30
- @info[:website] = "#{url_common}/i/#{@info[:media_id]}.#{@info[:content_type]}/"
29
+ self.media_id = $3
30
+ self.media_content_type = $4
31
+ self.media_url = "#{url_common}/img#{server_id}/#{content_server_id}/#{self.media_id}.#{self.media_content_type}"
31
32
  else
32
- raise UnsupportedURI
33
+ raise UnsupportedURI
33
34
  end
34
-
35
- self
36
- end
37
-
38
- def self.parsable?(uri)
39
- uri.host =~ /^img([0-9]*?)\.imageshack\.us$/i #/^(img([0-9]*?)\.imageshack\.us)|(yfrog\.com)/i
40
- end
41
-
35
+
36
+ # imageshack does not currently have API for retrieving individual video information
37
+ self.media_website = "#{url_common}/i/#{self.media_id}.#{self.media_content_type}/"
38
+ end
42
39
  end
43
40
  end
44
41
  end