acts_as_unvlogable 1.0.0 → 1.0.2
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.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +2 -0
- data/.travis.yml +19 -0
- data/Gemfile +4 -9
- data/README.markdown +5 -29
- data/Rakefile +1 -1
- data/acts_as_unvlogable.gemspec +10 -8
- data/lib/acts_as_unvlogable.rb +63 -37
- data/lib/acts_as_unvlogable/flickr.rb +3 -487
- data/lib/acts_as_unvlogable/string_extend.rb +0 -1
- data/lib/acts_as_unvlogable/version.rb +1 -1
- data/lib/acts_as_unvlogable/vg_11870.rb +7 -18
- data/lib/acts_as_unvlogable/vg_blip.rb +4 -9
- data/lib/acts_as_unvlogable/vg_collegehumor.rb +8 -20
- data/lib/acts_as_unvlogable/vg_dailymotion.rb +3 -7
- data/lib/acts_as_unvlogable/vg_dalealplay.rb +7 -10
- data/lib/acts_as_unvlogable/vg_flickr.rb +2 -16
- data/lib/acts_as_unvlogable/vg_metacafe.rb +2 -21
- data/lib/acts_as_unvlogable/vg_myspace.rb +6 -12
- data/lib/acts_as_unvlogable/vg_pleer.rb +38 -0
- data/lib/acts_as_unvlogable/vg_rutube.rb +7 -51
- data/lib/acts_as_unvlogable/vg_ted.rb +8 -16
- data/lib/acts_as_unvlogable/vg_vimeo.rb +14 -22
- data/lib/acts_as_unvlogable/vg_wistia.rb +49 -0
- data/lib/acts_as_unvlogable/vg_youtu.rb +11 -0
- data/lib/acts_as_unvlogable/vg_youtube.rb +11 -22
- data/spec/acts_as_unvlogable_spec.rb +363 -0
- data/spec/spec_helper.rb +4 -0
- metadata +106 -108
- data/lib/acts_as_unvlogable/vg_marca.rb +0 -48
- data/lib/acts_as_unvlogable/vg_mtvmusic.rb +0 -65
- data/lib/acts_as_unvlogable/vg_qik.rb +0 -66
- data/test/acts_as_unvlogable_test.rb +0 -392
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 884f8db9f2bab7470f0e4e5f08d7e79c6648e225
|
4
|
+
data.tar.gz: d240151cccc6f0e9c62a647ebb1bb8fd38a23f23
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: dcfd4c8effb6d374031d9e26c5ab7af15cf8645c352077369983295f330b1fbd3f44288ec2a093b4c6398fa3c5fb6822db24bc3f12be67e1cdd44c8c697e47f7
|
7
|
+
data.tar.gz: 14237cb88f50ea0bdd9478df84269752f62d35f623de14666016cb14c9111e689776b0a0d3549a3d1db8429db33e9e8b1db10159bc81d0d7631f6f86dee60561
|
data/.coveralls.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
service_name: travis-ci
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
language: ruby
|
2
|
+
cache: bundler
|
3
|
+
|
4
|
+
rvm:
|
5
|
+
- 2.1.0
|
6
|
+
|
7
|
+
branches:
|
8
|
+
only:
|
9
|
+
- master
|
10
|
+
- refactor
|
11
|
+
|
12
|
+
script: "bundle exec rspec"
|
13
|
+
|
14
|
+
notifications:
|
15
|
+
email:
|
16
|
+
recipients:
|
17
|
+
- mamuso@mamuso.net
|
18
|
+
on_failure: change
|
19
|
+
on_success: never
|
data/Gemfile
CHANGED
@@ -1,15 +1,10 @@
|
|
1
1
|
source "http://rubygems.org"
|
2
|
-
|
3
|
-
# Specify your gem's dependencies in acts_as_unvlogable.gemspec
|
4
2
|
gemspec
|
5
3
|
|
6
4
|
group :development do
|
7
|
-
gem "bundler", "
|
8
|
-
gem 'ruby-debug', :platforms => :mri_18
|
9
|
-
gem 'ruby-debug19', :require => 'ruby-debug', :platforms => :mri_19
|
10
|
-
end
|
11
|
-
|
12
|
-
group :development, :test do
|
13
|
-
gem "shoulda"
|
5
|
+
gem "bundler", "> 1.3"
|
14
6
|
end
|
15
7
|
|
8
|
+
group :test do
|
9
|
+
gem 'coveralls', require: false
|
10
|
+
end
|
data/README.markdown
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
Acts as unvlogable
|
2
|
-
|
1
|
+
# Acts as unvlogable [](https://travis-ci.org/mamuso/acts_as_unvlogable) [](https://coveralls.io/r/mamuso/acts_as_unvlogable?branch=master)
|
2
|
+
|
3
3
|
|
4
4
|
What the hell is this!
|
5
5
|
----------------------
|
@@ -15,14 +15,12 @@ To include [this video](http://www.youtube.com/watch?v=GPQnbtldFyo) in [this pos
|
|
15
15
|
@aha.thumbnail => "http://i4.ytimg.com/vi/GPQnbtldFyo/default.jpg"
|
16
16
|
@aha.embed_url => "http://www.youtube.com/v/GPQnbtldFyo"
|
17
17
|
@aha.embed_html(width, height) => "<object [...]</object>"
|
18
|
-
@aha.flv => "http://...flv"
|
19
18
|
# all together :)
|
20
19
|
@aha.video_details(width, height) => {
|
21
20
|
:title => ...,
|
22
21
|
:thumbnail => ...,
|
23
22
|
:embed_url => ...,
|
24
23
|
:embed_html => ...,
|
25
|
-
:flv => ...
|
26
24
|
}
|
27
25
|
|
28
26
|
With this plugin we have an unique way to manage multiple services :)
|
@@ -37,15 +35,6 @@ Install it!
|
|
37
35
|
|
38
36
|
2. Optionally you can create the `config/unvlogable.yml` to store keys for the different services. You have in the plugin a [sample file](http://github.com/mamuso/acts_as_unvlogable/tree/master/unvlogable_sample.yml). At this moment you only need specify keys for flickr.
|
39
37
|
|
40
|
-
|
41
|
-
Dependencies
|
42
|
-
------------
|
43
|
-
|
44
|
-
The plugin depends on [youtube-it](https://github.com/kylejginavan/youtube_it), [xml-simple](http://xml-simple.rubyforge.org/) and [hpricot](https://code.whytheluckystiff.net/hpricot/).
|
45
|
-
|
46
|
-
We have included a modified version of the flickr gem to skip the gem dependency and manage video capabilities.
|
47
|
-
|
48
|
-
|
49
38
|
Use it!
|
50
39
|
-------
|
51
40
|
|
@@ -81,10 +70,7 @@ Then we have methods to know the 'basics' for use this video on your application
|
|
81
70
|
videotron.embed_html(400, 300)
|
82
71
|
=> "<object width='400' height='300'><param name='mo [...] 300'></embed></object>"
|
83
72
|
|
84
|
-
- __flv:__
|
85
|
-
|
86
|
-
videotron.flv
|
87
|
-
=> "http://www.vimeo.com/moogaloop/play/clip:1785993/ [...] 8ee400/video.flv"
|
73
|
+
- __flv:__ **DEPRECATED**
|
88
74
|
|
89
75
|
- __video\_details(width, height):__ All together :), returns all the previous elements in a hash. Width and height can be specified to build the embed\_html.
|
90
76
|
|
@@ -107,21 +93,11 @@ At this moment we support the following video services:
|
|
107
93
|
- [Myspace](http://vids.myspace.com/)
|
108
94
|
- [Ted Talks](http://www.ted.com/talks/)
|
109
95
|
- [11870.com](http://11870.com/)
|
110
|
-
- [Marca.tv](http://www.marca.tv/)
|
111
96
|
- [Dalealplay](http://www.dalealplay.com/)
|
112
97
|
- [RuTube](http://www.rutube.ru/)
|
98
|
+
- [Wistia](http://wistia.com/)
|
99
|
+
- [Pleer — Audio](http://pleer.com/)
|
113
100
|
|
114
|
-
Broken services
|
115
|
-
---------------
|
116
|
-
|
117
|
-
These services were implemented but due to changes in the website they don't work anymore. Any patch for fixing them would be great ;)
|
118
|
-
|
119
|
-
- [Qik](http://qik.com/)
|
120
|
-
- [MTV](http://www.mtvhive.com/)
|
121
|
-
|
122
|
-
You can detect new broken services when running the tests.
|
123
|
-
|
124
|
-
We are always open to incude new services.
|
125
101
|
|
126
102
|
And... what else?
|
127
103
|
-----------------
|
data/Rakefile
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
require 'bundler'
|
2
|
-
Bundler::GemHelper.install_tasks
|
2
|
+
Bundler::GemHelper.install_tasks
|
data/acts_as_unvlogable.gemspec
CHANGED
@@ -7,20 +7,22 @@ Gem::Specification.new do |s|
|
|
7
7
|
s.version = ActsAsUnvlogable::VERSION
|
8
8
|
s.platform = Gem::Platform::RUBY
|
9
9
|
s.authors = ["Manuel Muñoz", "Fernando Blat", "Alberto Romero"]
|
10
|
-
s.email = ["
|
11
|
-
s.homepage = ""
|
10
|
+
s.email = ["mamuso@mamuso.net", "ferblape@gmail.com", "denegro@gmail.com"]
|
11
|
+
s.homepage = "https://github.com/mamuso/acts_as_unvlogable"
|
12
12
|
s.summary = %q{An easy way to include external video services in a rails app}
|
13
13
|
s.description = %q{An easy way to include external video services in a rails app. This gem provides you wrappers for the most common video services, such as Youtube, Vimeo, Flickr, and so on...}
|
14
14
|
|
15
15
|
s.rubyforge_project = "acts_as_unvlogable"
|
16
16
|
|
17
17
|
s.files = `git ls-files`.split("\n")
|
18
|
-
s.test_files = `git ls-files -- {test}/*`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
19
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
20
|
s.require_paths = ["lib"]
|
21
|
-
|
22
|
-
s.add_development_dependency
|
23
|
-
s.
|
24
|
-
s.
|
25
|
-
s.
|
21
|
+
|
22
|
+
s.add_development_dependency 'bundler', '~> 1.3'
|
23
|
+
s.add_development_dependency 'rake'
|
24
|
+
s.add_development_dependency 'rspec'
|
25
|
+
s.add_runtime_dependency("nokogiri")
|
26
|
+
s.add_runtime_dependency("xml-simple")
|
27
|
+
s.add_runtime_dependency("youtube_it")
|
26
28
|
end
|
data/lib/acts_as_unvlogable.rb
CHANGED
@@ -1,36 +1,33 @@
|
|
1
|
-
require "rubygems"
|
2
1
|
require "bundler/setup"
|
3
|
-
|
4
|
-
require "
|
2
|
+
require "cgi"
|
3
|
+
require "json"
|
4
|
+
require "net/http"
|
5
|
+
require 'rexml/document'
|
5
6
|
require "youtube_it"
|
6
|
-
require "
|
7
|
-
require "iconv"
|
8
|
-
|
7
|
+
require "nokogiri"
|
9
8
|
require "acts_as_unvlogable/flickr"
|
10
|
-
|
9
|
+
|
10
|
+
|
11
11
|
if defined?(ActiveSupport).nil?
|
12
12
|
require "acts_as_unvlogable/string_base"
|
13
13
|
require "acts_as_unvlogable/object_base"
|
14
14
|
end
|
15
15
|
require "acts_as_unvlogable/string_extend"
|
16
16
|
|
17
|
-
|
17
|
+
|
18
|
+
# Video Services
|
18
19
|
videolibs = File.join(File.dirname(__FILE__), "acts_as_unvlogable", "vg_*.rb")
|
19
20
|
Dir.glob(videolibs).each {|file| require file}
|
20
21
|
|
22
|
+
|
21
23
|
class UnvlogIt
|
22
|
-
|
24
|
+
|
23
25
|
def initialize(url=nil, options={})
|
24
|
-
|
25
|
-
@object ||= "vg_#{get_domain(url).downcase}".camelize.constantize.new(url, options) rescue nil
|
26
|
-
raise ArgumentError.new("Unsuported url or service") and return if @object.nil?
|
27
|
-
unless @object.instance_variable_get("@details").nil? || !@object.instance_variable_get("@details").respond_to?("noembed")
|
28
|
-
raise ArgumentError.new("Embedding disabled by request") and return if @object.instance_variable_get("@details").noembed
|
29
|
-
end
|
26
|
+
@object = VideoFactory.new(url, options).load_service
|
30
27
|
end
|
31
28
|
|
32
29
|
def title
|
33
|
-
@object.title
|
30
|
+
@object.title rescue nil
|
34
31
|
end
|
35
32
|
|
36
33
|
def thumbnail
|
@@ -49,21 +46,21 @@ class UnvlogIt
|
|
49
46
|
@object.video_id rescue nil
|
50
47
|
end
|
51
48
|
|
52
|
-
def embed_html(width=425, height=344, options={})
|
53
|
-
@object.embed_html(width, height, options) rescue nil
|
54
|
-
end
|
55
|
-
|
56
|
-
def flv
|
57
|
-
@object.flv rescue nil
|
58
|
-
end
|
59
|
-
|
60
|
-
def download_url
|
61
|
-
@object.download_url rescue nil
|
49
|
+
def embed_html(width=425, height=344, options={}, params={})
|
50
|
+
@object.embed_html(width, height, options, params) rescue nil
|
62
51
|
end
|
63
52
|
|
64
53
|
def service
|
65
54
|
@object.service rescue nil
|
66
55
|
end
|
56
|
+
|
57
|
+
# Deprecated
|
58
|
+
def flv
|
59
|
+
end
|
60
|
+
|
61
|
+
# Deprecated
|
62
|
+
def download_url
|
63
|
+
end
|
67
64
|
|
68
65
|
def video_details(width=425, height=344)
|
69
66
|
{
|
@@ -71,21 +68,50 @@ class UnvlogIt
|
|
71
68
|
:thumbnail => @object.thumbnail,
|
72
69
|
:embed_url => @object.embed_url,
|
73
70
|
:embed_html => @object.embed_html(width, height),
|
74
|
-
:flv =>
|
75
|
-
:download_url =>
|
71
|
+
:flv => nil, # Deprecated
|
72
|
+
:download_url => nil, # Deprecated
|
76
73
|
:service => @object.service,
|
77
74
|
:duration => @object.duration
|
78
75
|
}
|
79
76
|
end
|
80
77
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
78
|
+
class VideoFactory
|
79
|
+
def initialize(url, options = {})
|
80
|
+
raise ArgumentError.new("We need a video url") if url.blank?
|
81
|
+
@url = url
|
82
|
+
@options = options
|
83
|
+
end
|
84
|
+
|
85
|
+
def load_service
|
86
|
+
@object = service_object
|
87
|
+
validate_embed(@object)
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def validate_embed(object)
|
93
|
+
unless object.instance_variable_get("@details").nil? || !object.instance_variable_get("@details").respond_to?("noembed")
|
94
|
+
if !object.instance_variable_get("@details").embeddable?
|
95
|
+
raise ArgumentError.new("Embedding disabled by request")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
object
|
99
|
+
end
|
100
|
+
|
101
|
+
def service_object
|
102
|
+
class_name = "vg_#{get_domain.downcase}".camelize
|
103
|
+
class_name.constantize.new(@url, @options)
|
104
|
+
rescue NameError
|
105
|
+
raise ArgumentError.new("Unsuported url or service")
|
106
|
+
end
|
107
|
+
|
108
|
+
def get_domain
|
109
|
+
host = URI::parse(@url).host.split(".")
|
110
|
+
unless host.size == 1
|
111
|
+
host[host.size-2]
|
112
|
+
else
|
113
|
+
host[0]
|
114
|
+
end
|
88
115
|
end
|
89
116
|
end
|
90
|
-
|
91
|
-
end
|
117
|
+
end
|
@@ -1,40 +1,6 @@
|
|
1
1
|
# included here to skip the gem dependency and modified to manage video capabilities.
|
2
2
|
# this is the updated version from http://github.com/ctagg/flickr/tree/master/lib/flickr.rb
|
3
|
-
|
4
|
-
# = Flickr
|
5
|
-
# An insanely easy interface to the Flickr photo-sharing service. By Scott Raymond.
|
6
|
-
#
|
7
|
-
# Author:: Scott Raymond <sco@redgreenblu.com>
|
8
|
-
# Copyright:: Copyright (c) 2005 Scott Raymond <sco@redgreenblu.com>. Additional content by Patrick Plattes and Chris Taggart (http://pushrod.wordpress.com)
|
9
|
-
# License:: MIT <http://www.opensource.org/licenses/mit-license.php>
|
10
|
-
#
|
11
|
-
# BASIC USAGE:
|
12
|
-
# require 'flickr'
|
13
|
-
# flickr = Flickr.new('some_flickr_api_key') # create a flickr client (get an API key from http://www.flickr.com/services/api/)
|
14
|
-
# user = flickr.users('sco@scottraymond.net') # lookup a user
|
15
|
-
# user.name # get the user's name
|
16
|
-
# user.location # and location
|
17
|
-
# user.photos # grab their collection of Photo objects...
|
18
|
-
# user.groups # ...the groups they're in...
|
19
|
-
# user.contacts # ...their contacts...
|
20
|
-
# user.favorites # ...favorite photos...
|
21
|
-
# user.photosets # ...their photo sets...
|
22
|
-
# user.tags # ...and their tags
|
23
|
-
# recentphotos = flickr.photos # get the 100 most recent public photos
|
24
|
-
# photo = recentphotos.first # or very most recent one
|
25
|
-
# photo.url # see its URL,
|
26
|
-
# photo.title # title,
|
27
|
-
# photo.description # and description,
|
28
|
-
# photo.owner # and its owner.
|
29
|
-
# File.open(photo.filename, 'w') do |file|
|
30
|
-
# file.puts p.file # save the photo to a local file
|
31
|
-
# end
|
32
|
-
# flickr.photos.each do |p| # get the last 100 public photos...
|
33
|
-
# File.open(p.filename, 'w') do |f|
|
34
|
-
# f.puts p.file('Square') # ...and save a local copy of their square thumbnail
|
35
|
-
# end
|
36
|
-
# end
|
37
|
-
|
3
|
+
# Modified and simplified to keep only the used methods
|
38
4
|
|
39
5
|
require 'cgi'
|
40
6
|
require 'net/http'
|
@@ -46,7 +12,7 @@ class Flickr
|
|
46
12
|
attr_reader :api_key, :auth_token
|
47
13
|
attr_accessor :user
|
48
14
|
|
49
|
-
HOST_URL = '
|
15
|
+
HOST_URL = 'https://flickr.com'
|
50
16
|
API_PATH = '/services/rest'
|
51
17
|
|
52
18
|
# Flickr, annoyingly, uses a number of representations to specify the size
|
@@ -92,87 +58,6 @@ class Flickr
|
|
92
58
|
end
|
93
59
|
end
|
94
60
|
|
95
|
-
# Gets authentication token given a Flickr frob, which is returned when user
|
96
|
-
# allows access to their account for the application with the api_key which
|
97
|
-
# made the request
|
98
|
-
def get_token_from(frob)
|
99
|
-
auth_response = request("auth.getToken", :frob => frob)['auth']
|
100
|
-
@auth_token = auth_response['token']
|
101
|
-
@user = User.new( 'id' => auth_response['user']['nsid'],
|
102
|
-
'username' => auth_response['user']['username'],
|
103
|
-
'name' => auth_response['user']['fullname'],
|
104
|
-
'client' => self)
|
105
|
-
@auth_token
|
106
|
-
end
|
107
|
-
|
108
|
-
# Stores authentication credentials to use on all subsequent calls.
|
109
|
-
# If authentication succeeds, returns a User object.
|
110
|
-
# NB This call is no longer in API and will result in an error if called
|
111
|
-
def login(email='', password='')
|
112
|
-
@email = email
|
113
|
-
@password = password
|
114
|
-
user = request('test.login')['user'] rescue fail
|
115
|
-
@user = User.new(user['id'], nil, nil, nil, @api_key)
|
116
|
-
end
|
117
|
-
|
118
|
-
# Implements flickr.urls.lookupGroup and flickr.urls.lookupUser
|
119
|
-
def find_by_url(url)
|
120
|
-
response = urls_lookupUser('url'=>url) rescue urls_lookupGroup('url'=>url) rescue nil
|
121
|
-
(response['user']) ? User.new(response['user']['id'], nil, nil, nil, @api_key) : Group.new(response['group']['id'], @api_key) unless response.nil?
|
122
|
-
end
|
123
|
-
|
124
|
-
# Implements flickr.photos.getRecent and flickr.photos.search
|
125
|
-
def photos(*criteria)
|
126
|
-
criteria ? photos_search(*criteria) : recent
|
127
|
-
end
|
128
|
-
|
129
|
-
# flickr.photos.getRecent
|
130
|
-
# 100 newest photos from everyone
|
131
|
-
def recent
|
132
|
-
photos_request('photos.getRecent')
|
133
|
-
end
|
134
|
-
|
135
|
-
def photos_search(params={})
|
136
|
-
photos_request('photos.search', params)
|
137
|
-
end
|
138
|
-
alias_method :search, :photos_search
|
139
|
-
|
140
|
-
# Gets public photos with a given tag
|
141
|
-
def tag(tag)
|
142
|
-
photos('tags'=>tag)
|
143
|
-
end
|
144
|
-
|
145
|
-
# Implements flickr.people.findByEmail and flickr.people.findByUsername.
|
146
|
-
def users(lookup=nil)
|
147
|
-
user = people_findByEmail('find_email'=>lookup)['user'] rescue people_findByUsername('username'=>lookup)['user']
|
148
|
-
return User.new("id" => user["nsid"], "username" => user["username"], "client" => self)
|
149
|
-
end
|
150
|
-
|
151
|
-
# Implements flickr.groups.search
|
152
|
-
def groups(group_name, options={})
|
153
|
-
collection = groups_search({"text" => group_name}.merge(options))['groups']['group']
|
154
|
-
collection = [collection] if collection.is_a? Hash
|
155
|
-
|
156
|
-
collection.collect { |group| Group.new( "id" => group['nsid'],
|
157
|
-
"name" => group['name'],
|
158
|
-
"eighteenplus" => group['eighteenplus'],
|
159
|
-
"client" => self) }
|
160
|
-
end
|
161
|
-
|
162
|
-
# Implements flickr.tags.getRelated
|
163
|
-
def related_tags(tag)
|
164
|
-
tags_getRelated('tag'=>tag)['tags']['tag']
|
165
|
-
end
|
166
|
-
|
167
|
-
# Implements flickr.photos.licenses.getInfo
|
168
|
-
def licenses
|
169
|
-
photos_licenses_getInfo['licenses']['license']
|
170
|
-
end
|
171
|
-
|
172
|
-
# Returns url for user to login in to Flickr to authenticate app for a user
|
173
|
-
def login_url(perms)
|
174
|
-
"http://flickr.com/services/auth/?api_key=#{@api_key}&perms=#{perms}&api_sig=#{signature_from('api_key'=>@api_key, 'perms' => perms)}"
|
175
|
-
end
|
176
61
|
|
177
62
|
# Implements everything else.
|
178
63
|
# Any method not defined explicitly will be passed on to the Flickr API,
|
@@ -182,11 +67,6 @@ class Flickr
|
|
182
67
|
request(method_id.id2name.gsub(/_/, '.'), params)
|
183
68
|
end
|
184
69
|
|
185
|
-
# Does an HTTP GET on a given URL and returns the response body
|
186
|
-
def http_get(url)
|
187
|
-
Net::HTTP.get_response(URI.parse(url)).body.to_s
|
188
|
-
end
|
189
|
-
|
190
70
|
# Takes a Flickr API method name and set of parameters; returns an XmlSimple object with the response
|
191
71
|
def request(method, params={})
|
192
72
|
url = request_url(method, params)
|
@@ -194,12 +74,6 @@ class Flickr
|
|
194
74
|
raise response['err']['msg'] if response['stat'] != 'ok'
|
195
75
|
response
|
196
76
|
end
|
197
|
-
|
198
|
-
# acts like request but returns a PhotoCollection (a list of Photo objects)
|
199
|
-
def photos_request(method, params={})
|
200
|
-
photos = request(method, params)
|
201
|
-
PhotoCollection.new(photos, @api_key)
|
202
|
-
end
|
203
77
|
|
204
78
|
# Builds url for Flickr API REST request from given the flickr method name
|
205
79
|
# (exclusing the 'flickr.' that begins each method call) and params (where
|
@@ -228,10 +102,6 @@ class Flickr
|
|
228
102
|
# builds a PhotoCollection from given params, such as those returned from
|
229
103
|
# photos.search API call
|
230
104
|
def initialize(photos_api_response={}, api_key=nil)
|
231
|
-
[ "page", "pages", "perpage", "total" ].each { |i| instance_variable_set("@#{i}", photos_api_response["photos"][i])}
|
232
|
-
collection = photos_api_response['photos']['photo'] || []
|
233
|
-
collection = [collection] if collection.is_a? Hash
|
234
|
-
collection.each { |photo| self << Photo.new(photo.delete('id'), api_key, photo) }
|
235
105
|
end
|
236
106
|
end
|
237
107
|
|
@@ -280,110 +150,6 @@ class Flickr
|
|
280
150
|
@client.login(@email, @password) if @email and @password # this is now irrelevant as Flickr API no longer supports authentication this way
|
281
151
|
end
|
282
152
|
|
283
|
-
def username
|
284
|
-
@username.nil? ? getInfo.username : @username
|
285
|
-
end
|
286
|
-
def name
|
287
|
-
@name.nil? ? getInfo.name : @name
|
288
|
-
end
|
289
|
-
def location
|
290
|
-
@location.nil? ? getInfo.location : @location
|
291
|
-
end
|
292
|
-
def count
|
293
|
-
@count.nil? ? getInfo.count : @count
|
294
|
-
end
|
295
|
-
def firstdate
|
296
|
-
@firstdate.nil? ? getInfo.firstdate : @firstdate
|
297
|
-
end
|
298
|
-
def firstdatetaken
|
299
|
-
@firstdatetaken.nil? ? getInfo.firstdatetaken : @firstdatetaken
|
300
|
-
end
|
301
|
-
|
302
|
-
# Builds url for user's photos page as per
|
303
|
-
# http://www.flickr.com/services/api/misc.urls.html
|
304
|
-
def photos_url
|
305
|
-
"http://www.flickr.com/photos/#{id}/"
|
306
|
-
end
|
307
|
-
|
308
|
-
# Builds url for user's profile page as per
|
309
|
-
# http://www.flickr.com/services/api/misc.urls.html
|
310
|
-
def url
|
311
|
-
"http://www.flickr.com/people/#{id}/"
|
312
|
-
end
|
313
|
-
|
314
|
-
def pretty_url
|
315
|
-
@pretty_url ||= @client.urls_getUserProfile('user_id'=>@id)['user']['url']
|
316
|
-
end
|
317
|
-
|
318
|
-
# Implements flickr.people.getPublicGroups
|
319
|
-
def groups
|
320
|
-
collection = @client.people_getPublicGroups('user_id'=>@id)['groups']['group']
|
321
|
-
collection = [collection] if collection.is_a? Hash
|
322
|
-
collection.collect { |group| Group.new( "id" => group['nsid'],
|
323
|
-
"name" => group['name'],
|
324
|
-
"eighteenplus" => group['eighteenplus'],
|
325
|
-
"client" => @client) }
|
326
|
-
end
|
327
|
-
|
328
|
-
# Implements flickr.people.getPublicPhotos. Options hash allows you to add
|
329
|
-
# extra restrictions as per flickr.people.getPublicPhotos docs, e.g.
|
330
|
-
# user.photos('per_page' => '25', 'extras' => 'date_taken')
|
331
|
-
def photos(options={})
|
332
|
-
@client.photos_request('people.getPublicPhotos', {'user_id' => @id}.merge(options))
|
333
|
-
# what about non-public photos?
|
334
|
-
end
|
335
|
-
|
336
|
-
# Gets photos with a given tag
|
337
|
-
def tag(tag)
|
338
|
-
@client.photos('user_id'=>@id, 'tags'=>tag)
|
339
|
-
end
|
340
|
-
|
341
|
-
# Implements flickr.contacts.getPublicList and flickr.contacts.getList
|
342
|
-
def contacts
|
343
|
-
@client.contacts_getPublicList('user_id'=>@id)['contacts']['contact'].collect { |contact| User.new(contact['nsid'], contact['username'], nil, nil, @api_key) }
|
344
|
-
#or
|
345
|
-
end
|
346
|
-
|
347
|
-
# Implements flickr.favorites.getPublicList
|
348
|
-
def favorites
|
349
|
-
@client.photos_request('favorites.getPublicList', 'user_id' => @id)
|
350
|
-
end
|
351
|
-
|
352
|
-
# Implements flickr.photosets.getList
|
353
|
-
def photosets
|
354
|
-
@client.photosets_getList('user_id'=>@id)['photosets']['photoset'].collect { |photoset| Photoset.new(photoset['id'], @api_key) }
|
355
|
-
end
|
356
|
-
|
357
|
-
# Implements flickr.tags.getListUser
|
358
|
-
def tags
|
359
|
-
@client.tags_getListUser('user_id'=>@id)['who']['tags']['tag'].collect { |tag| tag }
|
360
|
-
end
|
361
|
-
|
362
|
-
# Implements flickr.photos.getContactsPublicPhotos and flickr.photos.getContactsPhotos
|
363
|
-
def contactsPhotos
|
364
|
-
@client.photos_request('photos.getContactsPublicPhotos', 'user_id' => @id)
|
365
|
-
end
|
366
|
-
|
367
|
-
def to_s
|
368
|
-
@name
|
369
|
-
end
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
private
|
374
|
-
|
375
|
-
# Implements flickr.people.getInfo, flickr.urls.getUserPhotos, and flickr.urls.getUserProfile
|
376
|
-
def getInfo
|
377
|
-
info = @client.people_getInfo('user_id'=>@id)['person']
|
378
|
-
@username = info['username']
|
379
|
-
@name = info['realname']
|
380
|
-
@location = info['location']
|
381
|
-
@count = info['photos']['count']
|
382
|
-
@firstdate = info['photos']['firstdate']
|
383
|
-
@firstdatetaken = info['photos']['firstdatetaken']
|
384
|
-
self
|
385
|
-
end
|
386
|
-
|
387
153
|
end
|
388
154
|
|
389
155
|
class Photo
|
@@ -396,192 +162,20 @@ class Flickr
|
|
396
162
|
extra_params.each { |k,v| self.instance_variable_set("@#{k}", v) } # convert extra_params into instance variables
|
397
163
|
@client = Flickr.new @api_key
|
398
164
|
end
|
399
|
-
|
400
|
-
# Allows access to all photos instance variables through hash like
|
401
|
-
# interface, e.g. photo["datetaken"] returns @datetaken instance
|
402
|
-
# variable. Useful for accessing any weird and wonderful parameter
|
403
|
-
# that may have been returned by Flickr when finding the photo,
|
404
|
-
# e.g. those returned by the extras argument in
|
405
|
-
# flickr.people.getPublicPhotos
|
406
|
-
def [](param_name)
|
407
|
-
instance_variable_get("@#{param_name}")
|
408
|
-
end
|
409
|
-
|
165
|
+
|
410
166
|
def title
|
411
167
|
@title.nil? ? getInfo("title") : @title
|
412
168
|
end
|
413
169
|
|
414
|
-
# Returns the owner of the photo as a Flickr::User. If we have no info
|
415
|
-
# about the owner, we make an API call to get it. If we already have
|
416
|
-
# the owner's id, create a user based on that. Either way, we cache the
|
417
|
-
# result so we don't need to check again
|
418
|
-
def owner
|
419
|
-
case @owner
|
420
|
-
when Flickr::User
|
421
|
-
@owner
|
422
|
-
when String
|
423
|
-
@owner = Flickr::User.new(@owner, nil, nil, nil, @api_key)
|
424
|
-
else
|
425
|
-
getInfo("owner")
|
426
|
-
end
|
427
|
-
end
|
428
|
-
|
429
|
-
def server
|
430
|
-
@server.nil? ? getInfo("server") : @server
|
431
|
-
end
|
432
|
-
|
433
|
-
def isfavorite
|
434
|
-
@isfavorite.nil? ? getInfo("isfavorite") : @isfavorite
|
435
|
-
end
|
436
|
-
|
437
|
-
def license
|
438
|
-
@license.nil? ? getInfo("license") : @license
|
439
|
-
end
|
440
|
-
|
441
|
-
def rotation
|
442
|
-
@rotation.nil? ? getInfo("rotation") : @rotation
|
443
|
-
end
|
444
|
-
|
445
|
-
def description
|
446
|
-
@description || getInfo("description")
|
447
|
-
end
|
448
|
-
|
449
|
-
def notes
|
450
|
-
@notes.nil? ? getInfo("notes") : @notes
|
451
|
-
end
|
452
|
-
|
453
|
-
# Returns the URL for the photo size page
|
454
|
-
# defaults to 'Medium'
|
455
|
-
# other valid sizes are in the VALID_SIZES hash
|
456
|
-
def size_url(size='Medium')
|
457
|
-
uri_for_photo_from_self(size) || sizes(size)['url']
|
458
|
-
end
|
459
|
-
|
460
170
|
# converts string or symbol size to a capitalized string
|
461
171
|
def normalize_size(size)
|
462
172
|
size ? size.to_s.capitalize : size
|
463
173
|
end
|
464
174
|
|
465
|
-
# the URL for the main photo page
|
466
|
-
# if getInfo has already been called, this will return the pretty url
|
467
|
-
#
|
468
|
-
# for historical reasons, an optional size can be given
|
469
|
-
# 'Medium' returns the regular url; any other size returns a size page
|
470
|
-
# use size_url instead
|
471
|
-
def url(size = nil)
|
472
|
-
if normalize_size(size) != 'Medium'
|
473
|
-
size_url(size)
|
474
|
-
else
|
475
|
-
@url || uri_for_photo_from_self
|
476
|
-
end
|
477
|
-
end
|
478
|
-
|
479
|
-
# the 'pretty' url for a photo
|
480
|
-
# (if the user has set up a custom name)
|
481
|
-
# eg, http://flickr.com/photos/granth/2584402507/ instead of
|
482
|
-
# http://flickr.com/photos/23386158@N00/2584402507/
|
483
|
-
def pretty_url
|
484
|
-
@url || getInfo("pretty_url")
|
485
|
-
end
|
486
|
-
|
487
175
|
# Returns the URL for the image (default or any specified size)
|
488
176
|
def source(size='Medium')
|
489
177
|
image_source_uri_from_self(size) || sizes(size)['source']
|
490
178
|
end
|
491
|
-
|
492
|
-
# Returns the photo file data itself, in any specified size. Example: File.open(photo.title, 'w') { |f| f.puts photo.file }
|
493
|
-
def file(size='Medium')
|
494
|
-
Net::HTTP.get_response(URI.parse(source(size))).body
|
495
|
-
end
|
496
|
-
|
497
|
-
# Unique filename for the image, based on the Flickr NSID
|
498
|
-
def filename
|
499
|
-
"#{@id}.jpg"
|
500
|
-
end
|
501
|
-
|
502
|
-
# Implements flickr.photos.getContext
|
503
|
-
def context
|
504
|
-
context = @client.photos_getContext('photo_id'=>@id)
|
505
|
-
@previousPhoto = Photo.new(context['prevphoto'].delete('id'), @api_key, context['prevphoto']) if context['prevphoto']['id']!='0'
|
506
|
-
@nextPhoto = Photo.new(context['nextphoto'].delete('id'), @api_key, context['nextphoto']) if context['nextphoto']['id']!='0'
|
507
|
-
return [@previousPhoto, @nextPhoto]
|
508
|
-
end
|
509
|
-
|
510
|
-
# Implements flickr.photos.getExif
|
511
|
-
def exif
|
512
|
-
@client.photos_getExif('photo_id'=>@id)['photo']
|
513
|
-
end
|
514
|
-
|
515
|
-
# Implements flickr.photos.getPerms
|
516
|
-
def permissions
|
517
|
-
@client.photos_getPerms('photo_id'=>@id)['perms']
|
518
|
-
end
|
519
|
-
|
520
|
-
# Implements flickr.photos.getSizes
|
521
|
-
def sizes(size=nil)
|
522
|
-
size = normalize_size(size)
|
523
|
-
sizes = @client.photos_getSizes('photo_id'=>@id)['sizes']['size']
|
524
|
-
sizes = sizes.find{|asize| asize['label']==size} if size
|
525
|
-
return sizes
|
526
|
-
end
|
527
|
-
|
528
|
-
# flickr.tags.getListPhoto
|
529
|
-
def tags
|
530
|
-
@client.tags_getListPhoto('photo_id'=>@id)['photo']['tags']
|
531
|
-
end
|
532
|
-
|
533
|
-
# Implements flickr.photos.notes.add
|
534
|
-
def add_note(note)
|
535
|
-
end
|
536
|
-
|
537
|
-
# Implements flickr.photos.setDates
|
538
|
-
def dates=(dates)
|
539
|
-
end
|
540
|
-
|
541
|
-
# Implements flickr.photos.setPerms
|
542
|
-
def perms=(perms)
|
543
|
-
end
|
544
|
-
|
545
|
-
# Implements flickr.photos.setTags
|
546
|
-
def tags=(tags)
|
547
|
-
end
|
548
|
-
|
549
|
-
# Implements flickr.photos.setMeta
|
550
|
-
def title=(title)
|
551
|
-
end
|
552
|
-
def description=(title)
|
553
|
-
end
|
554
|
-
|
555
|
-
# Implements flickr.photos.addTags
|
556
|
-
def add_tag(tag)
|
557
|
-
end
|
558
|
-
|
559
|
-
# Implements flickr.photos.removeTag
|
560
|
-
def remove_tag(tag)
|
561
|
-
end
|
562
|
-
|
563
|
-
# Implements flickr.photos.transform.rotate
|
564
|
-
def rotate
|
565
|
-
end
|
566
|
-
|
567
|
-
# Implements flickr.blogs.postPhoto
|
568
|
-
def postToBlog(blog_id, title='', description='')
|
569
|
-
@client.blogs_postPhoto('photo_id'=>@id, 'title'=>title, 'description'=>description)
|
570
|
-
end
|
571
|
-
|
572
|
-
# Implements flickr.photos.notes.delete
|
573
|
-
def deleteNote(note_id)
|
574
|
-
end
|
575
|
-
|
576
|
-
# Implements flickr.photos.notes.edit
|
577
|
-
def editNote(note_id)
|
578
|
-
end
|
579
|
-
|
580
|
-
# Converts the Photo to a string by returning its title
|
581
|
-
def to_s
|
582
|
-
title
|
583
|
-
end
|
584
|
-
|
585
179
|
|
586
180
|
# unvlog
|
587
181
|
def media
|
@@ -630,84 +224,6 @@ class Flickr
|
|
630
224
|
end
|
631
225
|
end
|
632
226
|
|
633
|
-
# Builds uri of Flickr page for photo. By default returns the main
|
634
|
-
# page for the photo, but if passed a size will return the simplified
|
635
|
-
# flickr page featuring the given size of the photo
|
636
|
-
# TODO: Handle "Original" size
|
637
|
-
def uri_for_photo_from_self(size=nil)
|
638
|
-
return unless @owner&&@id
|
639
|
-
size = normalize_size(size)
|
640
|
-
s_size = VALID_SIZES[size] # get the short letters array corresponding to the size
|
641
|
-
s_size = s_size&&s_size[1] # the second element of this array is used to build the uri of the flickr page for this size
|
642
|
-
"http://www.flickr.com/photos/#{owner.id}/#{@id}" + (s_size ? "/sizes/#{s_size}/" : "")
|
643
|
-
end
|
644
|
-
end
|
645
|
-
|
646
|
-
# Todo:
|
647
|
-
# flickr.groups.pools.add
|
648
|
-
# flickr.groups.pools.getContext
|
649
|
-
# flickr.groups.pools.getGroups
|
650
|
-
# flickr.groups.pools.getPhotos
|
651
|
-
# flickr.groups.pools.remove
|
652
|
-
class Group
|
653
|
-
attr_reader :id, :client, :description, :name, :eighteenplus, :members, :online, :privacy, :url#, :chatid, :chatcount
|
654
|
-
|
655
|
-
def initialize(id_or_params_hash=nil, api_key=nil)
|
656
|
-
if id_or_params_hash.is_a?(Hash)
|
657
|
-
id_or_params_hash.each { |k,v| self.instance_variable_set("@#{k}", v) } # convert extra_params into instance variables
|
658
|
-
else
|
659
|
-
@id = id_or_params_hash
|
660
|
-
@api_key = api_key
|
661
|
-
@client = Flickr.new @api_key
|
662
|
-
end
|
663
|
-
end
|
664
|
-
|
665
|
-
# Implements flickr.groups.getInfo and flickr.urls.getGroup
|
666
|
-
# private, once we can call it as needed
|
667
|
-
def getInfo
|
668
|
-
info = @client.groups_getInfo('group_id'=>@id)['group']
|
669
|
-
@name = info['name']
|
670
|
-
@members = info['members']
|
671
|
-
@online = info['online']
|
672
|
-
@privacy = info['privacy']
|
673
|
-
# @chatid = info['chatid']
|
674
|
-
# @chatcount = info['chatcount']
|
675
|
-
@url = @client.urls_getGroup('group_id'=>@id)['group']['url']
|
676
|
-
self
|
677
|
-
end
|
678
|
-
|
679
|
-
end
|
680
|
-
|
681
|
-
# Todo:
|
682
|
-
# flickr.photosets.delete
|
683
|
-
# flickr.photosets.editMeta
|
684
|
-
# flickr.photosets.editPhotos
|
685
|
-
# flickr.photosets.getContext
|
686
|
-
# flickr.photosets.getInfo
|
687
|
-
# flickr.photosets.getPhotos
|
688
|
-
class Photoset
|
689
|
-
|
690
|
-
attr_reader :id, :client, :owner, :primary, :photos, :title, :description, :url
|
691
|
-
|
692
|
-
def initialize(id=nil, api_key=nil)
|
693
|
-
@id = id
|
694
|
-
@api_key = api_key
|
695
|
-
@client = Flickr.new @api_key
|
696
|
-
end
|
697
|
-
|
698
|
-
# Implements flickr.photosets.getInfo
|
699
|
-
# private, once we can call it as needed
|
700
|
-
def getInfo
|
701
|
-
info = @client.photosets_getInfo('photoset_id'=>@id)['photoset']
|
702
|
-
@owner = User.new(info['owner'], nil, nil, nil, @api_key)
|
703
|
-
@primary = info['primary']
|
704
|
-
@photos = info['photos']
|
705
|
-
@title = info['title']
|
706
|
-
@description = info['description']
|
707
|
-
@url = "http://www.flickr.com/photos/#{@owner.getInfo.username}/sets/#{@id}/"
|
708
|
-
self
|
709
|
-
end
|
710
|
-
|
711
227
|
end
|
712
228
|
|
713
229
|
end
|