Skip to content

Premshree Pillai's Site

Sections
Personal tools
You are here: Home » Code » Ruby » Ruby API for Flickr

Ruby API for Flickr

Document Actions
IMPORTANT: This is an older version of the Ruby API for Flickr. The stuff has moved here: http://rubyforge.org/projects/libyws You can grab the latest copy from CVS: http://rubyforge.org/cgi-bin/viewvc.cgi/flickr/?root=libyws
#!/usr/local/bin/ruby

##
# Ruby API for Flickr (See http://www.flickr.com/services/api/)
# (C) 2005 Premshree Pillai
# http://www.livejournal.com/~premshree
#
# EXAMPLES:
#
#	user = User.new('18645779@N00')
# 	user.getPhotosets
#
# 	photoset = Photoset.new('4784077', '', '4784077')
#
#	photoset.create(Photo.new('4784077'), 'Test set')
#
# 	group = Photo.new('6714892')
#  	group.tags_getListPhoto
#
#  	user = Search.new('18645779@N00')
#  	user.photosSearch(['bombay', 'bangalore'])
#
#  	people = Search.new
#  	people.people_getPublicPhotos('44124329962@N01')
#
#  	people = Search.new
#  	people.favorites_getList('44124329962@N01')
#
# HISTORY:
#
#	0.2 [2005-03-27]: Added Upload class
#	0.1 [2005-03-21]: Initial release
#
# see code to understand stuff
##

__AUTHOR__ = "Premshree Pillai"
__VERSION__ = "0.1"
__DATE__ = "2005-03-27 04:13"

require 'cgi'
require 'md5'
require 'net/http'
require 'rexml/document'
include REXML

$HOST = 'http://flickr.com'
$API = '/services/rest'

$API_KEY = 'YOUR-API-KEY'
$email = 'YOUR-EMAIL'
$password = 'YOUR-PASSWORD'

##
# Represents a Flickr Photo
##
class Photo
	def initialize(id, owner=nil, dateuploaded=nil, \
                 title=nil, description=nil, ispublic=nil, \
                 isfriend=nil, isfamily=nil, cancomment=nil, \
                 canaddmeta=nil, comments=nil, tags=nil)
		@__id = id
		@__owner = owner
		@__dateuploaded = dateuploaded
		@__title = title
		@__description = description
		@__ispublic = ispublic
		@__isfriend = isfriend
		@__isfamily = isfamily
		@__cancomment = cancomment
		@__canaddmeta = canaddmeta
		@__comments = comments
		@__tags = tags
	end

	def _get_attr_id
		@__id
	end

	##
	# Loads the properties from Flickr
	##
	def _load_properties
		method = 'flickr.photos.getInfo'
		data = _doget(method, false, {'photo_id' => @__id})
		doc = Document.new(data)
		p = []
		doc.elements.each('rsp/photo') { |photo|
			@__dateuploaded = photo.attributes['dateuploaded']
			owner = photo.elements['owner']
			@__owner = User.new(owner.attributes['nsid'],\
			 username=owner.attributes['username'],\
			 realname=owner.attributes['realname'],\
			 location=owner.attributes['location'])
			@__title = photo.elements['title'].text
			@__description = photo.elements['description'].text
			@__ispublic = photo.elements['visibility'].attributes['ispublic']
			@__isfriend = photo.elements['visibility'].attributes['isfriend']
			@__isfamily = photo.elements['visibility'].attributes['isfamily']
			@__ispublic = photo.elements['editability'].attributes['cancomment']
			@__canaddmeta = photo.elements['editability'].attributes['canaddmeta']
			@__comments = photo.elements['comments'].text
			@__permcomment = photo.elements['permissions'].attributes['permcomment']
			@__permaddmeta = photo.elements['permissions'].attributes['permaddmeta']
			@__tags = []
			photo.elements.each('tags/tag') { |tag|
				@__tags << tag.text
			}
		}
	end

	##
	# Set the tags for current photo to list tags
	# (will delete any existing tags)
	##
	def setTags(tags)
		method = 'flickr.photos.setTags'
		tags = tags.uniq
		_doget(method, auth=true, {'photo_id'=>@__id, 'tags'=>tags})
		@__tags = tags
	end

	##
	# Add more tags to photo
	##
	def addTags(tags)
        	method = 'flickr.photos.addTags'
		tags = tags.uniq
		_doget(method, auth=true, {'photo_id'=>@__id, 'tags'=>tags})

		_load_properties
		tags.each { |tag| @__tags << tag }
	end

	##
	# Set metadata to photo
	##
	def setMeta(title=nil, description=nil)
        	method = 'flickr.photos.setMeta'

		if title == nil
            		title = self.title
		end
		if description == nil
            		description = self.description
		end

		_doget(method, auth=true, {'title'=>title, \
                'description'=>description, 'photo_id'=>@__id})

		@__title = title
		@__description = description
	end

	##
	# Retrieves a url for the photo
	# urlType - 'url' or 'source'
	#  'url' - flickr page of photo
	#  'source' - image file
	##
	def getURL(size='Medium', urlType='url')
		method = 'flickr.photos.getSizes'
		data = _doget(method, false, {'photo_id'=>@__id})
		doc = Document.new(data)
		p = []
		doc.elements.each('rsp/sizes/size') { |x|
			if x.attributes['label'] == size
				return x.attributes['url']
			end
		}
	end

	##
	# Returns a list of tags for a photo
	##
	def tags_getListPhoto
		method = 'flickr.tags.getListPhoto'
		data = _doget(method, false, {'photo_id'=>@__id})
		doc = Document.new(data)
		tags = []
		doc.elements.each('rsp/photo/tags/tag') { |tag|
			 tags << tag.text
		}
		tags
	end
end



##
# A Flickr photoset
##
class Photoset
	def initialize(id, title, primary, photos=0, description='')
		@__id = id
		@__title = title
		@__primary = primary
		@__description = description
		@__n = photos
	end

	##
	# Returns a list of photos for a Photoset
	##
	def getPhotos
		method = 'flickr.photosets.getPhotos'
		data = _doget(method, false, {'photoset_id' => @__id})
		doc = Document.new(data)
		p = []
		doc.elements.each('rsp/photoset/photo') { |x|
			p << x.attributes['id']
		}
	end

	##
	# Edit the photos in a set
	#  photos - photos for set
	#  primary - primary photo (if None will used current)
	##
	def editPhotos(photos, primary=nil)
		method = 'flickr.photosets.editPhotos'
		if primary == nil
			primary = @__primary
		end
		ids = photos.join(',')
		if !ids.include? primary.id
			ids << primary.id
		end
		_doget(method, auth=true, {'photoset_id'=>@__id,\
                'primary_photo_id'=>'primary.id', 'photo_ids'=>ids})
		@__n = ids.length
	end

	##
	# Create a new photoset
	#  photo - primary photo
	##
	def create(photo, title, description='')
        	if photo.class != Photo
            		print "TypeError, Photo expected"
			exit
		end
		method = 'flickr.photosets.create'
		data = _doget(method, auth=true, {'title'=>title,\
                       'description'=>description,\
                       'primary_photo_id'=>photo._get_attr_id})
	end
end



##
# A Flickr User
##
class User
	def initialize(id, username=nil, isadmin=nil, ispro=nil, \
                 realname=nil, location=nil, firstdate=nil, count=nil)
		@__id = id
		@__username = username
		@__isadmin = isadmin
		@__ispro = ispro
		@__realname = realname
		@__location = location
		@__photos_firstdate = firstdate
		@__photos_count = count
	end

	def _load_properties
		method = 'flickr.people.getInfo'
		data = _doget(method, false, {'user_id' => @__id})
		doc = Document.new(data)
		person = doc.elements['rsp'].elements['person']

		@__isadmin = person.attributes['isadmin']
		@__ispro = person.attributes['ispro']

		@__username = person.elements['username'].text
		@__realname = person.elements['realname'].text
		@__location = person.elements['location'].text
		@__photos_firstdate = person.elements['photos'].elements['firstdate'].text
		@__photos_count = person.elements['photos'].elements['count'].text
	end

	##
	# Returns a list of Photosets
	##
	def getPhotosets
		method = 'flickr.photosets.getList'
		data = _doget(method, false, {'user_id' => @__id})
		sets = []
		doc = Document.new(data)
		doc.elements.each('rsp/photosets/photoset') { |photoset|
			id = photoset.attributes['id']
			title = photoset.elements['title'].text
			primary = photoset.attributes['primary']
			description = photoset.elements['description'].text
			photos = photoset.attributes['photos']
			sets << Photoset.new(id, title, Photo.new(primary), description,\
				      photos)
		}
		sets
	end

	##
	# Returns a list of tags for a userid
	##
	def tags_getListUser
		method = 'flickr.tags.getListUser'
		data = _doget(method, false, {'photo_id'=>@__id})
		doc = Document.new(data)
		tags = []
		doc.elements.each('rsp/who/tags/tag') { |tag|
			 tags << tag.text
		}
		tags
	end
end



##
# Upload
##
class Upload
	def initialize
		@flickr_host = 'www.flickr.com'
		@upload_action = '/tools/uploader_go.gne'
		@boundary = ''
	end
	
	def _to_multipart(name, value)
		return "Content-Disposition: form-data; name=\"#{CGI::escape(name)}\"\r\n\r\n#{value}\r\n"
	end
	
	def _file_to_multipart(name, file, content)
		return "Content-Disposition: form-data; name=\"#{CGI::escape(name)}\"; filename=\"#{file}\"\r\n" +
			  "Content-Transfer-Encoding: binary\r\n" +
			  "Content-Type: image/jpeg\r\n\r\n" + content + "\r\n"
	end
	
	def _prepare_query(params)
		query = params.collect { |k, v|
			if v.respond_to?(:read)
				q = _file_to_multipart(k, v.path, v.read)
			else
				q = _to_multipart(k, v)
			end
			"--" + @boundary + "\r\n" + q 
		}.join("") + "--" + @boundary + "--"
		header = {"Content-type" => "multipart/form-data, boundary=" + @boundary + " "}
		return query, header
	end
	
	##
	# Upload a photo to Flickr
	#  returns a Photo object
	#  returns o on error
	##
	def upload(photo, title='', description='', tags=[], is_public=1,\
		   is_friend=0, is_family=0)
		@boundary = MD5.md5(photo).to_s
		file = File.new(photo, 'rb')
		params = {
			"email" 		=> $email,
			"password" 	=> $password,
			"photo"		=> file,
			"title"		=> title,
			"description" 	=> description,
			"tags"		=> tags.join(","),
			"is_public"	=> is_public,
			"is_friend"	=> is_friend,
			"is_family"	=> is_family
		}
		query, header = _prepare_query(params)
		file.close
		Net::HTTP.start(@flickr_host, 80) { |http|
			response = http.post(@upload_action, query, header)
			doc = Document.new(response.body)
			status = doc.elements['uploader/status'].text
			if status == "ok"
				photoid = doc.elements['uploader/photoid'].text
				Photo.new(photoid, nil, nil, title=title, description=description,\
				    ispublic=ispublic, isfriend=isfriend,\
				    isfamily=isfamily)
			else
				0
			end
		}
	end
end



##
# Flickr Group
##
class Group
	def initialize(id, name=nil, members=nil, online=nil, privacy=nil,\
	    chatid=nil, chatcount=nil)
        	@__id = id
        	@__name = name
        	@__members = members
        	@__online = online
        	@__privacy = privacy
        	@__chatid = chatid
        	@__chatcount = chatcount
	end

	def _load_properties()
        	# Loads the properties from Flickr
		method = 'flickr.groups.getInfo'
        	data = _doget(method, false, {'group_id'=>@__id})
		doc = Document.new(data)
		group = doc.elements['rsp'].elements['group']
		@__name = group.elements['name'].text
        	@__members = group.elements['members'].text
        	@__online = group.elements['online'].text
        	@__privacy = group.elements['privacy'].text
        	@__chatid = group.elements['chatid'].text
        	@__chatcount = group.elements['chatid'].text
		p @__chatid
	end

	##
	# Get a list of photo objects for this group
	##
	def getPhotos(tags=[], per_page='', page='')
		tags = tags.join(',')
		method = 'flickr.groups.pools.getPhotos'
		data = _doget(method, false, {'group_id'=>@__id, 'tags'=>tags,\
                       'per_page'=>per_page, 'page'=>page})
		p = []
		doc = Document.new(data)
		doc.elements.each('rsp/photos/photo') { |photo|
			id = photo.attributes['id']
			owner = photo.attributes['owner']
			title = photo.attributes['title']
			ispublic = photo.attributes['ispublic']
			isfriend = photo.attributes['isfriend']
			isfamily = photo.attributes['isfamily']
			photo_obj = Photo.new(id, owner=owner, title=title,\
				    ispublic=ispublic, isfriend=isfriend,\
				    isfamily=isfamily)
			p << photo_obj
		}
		p
	 end
end



##
# Methods to search
##
class Search
	def initialize(id='')
		@__id = id
	end

	def tags_getListUserPopular(id='', count='')
		method = 'flickr.tags.getListUserPopular'
		data = _doget(method, false, {'user_id'=>id, 'count'=>count})
		data = _doget(method, false, {'photo_id'=>@__id})
		doc = Document.new(data)
		tags = []
		doc.elements.each('rsp/who/tags/tag') { |tag|
			 tags << tag.text
		}
		tags
	end

	##
	# Returns a list of Photo objects.
	# If auth=true then will load private pics, etc.
	##
	def photosSearch(user_id='', auth=false,  tags=[], tag_mode='',\
			 text='',min_upload_date='', max_upload_date='',\
			 per_page='', page='')
		tags = tags.join(',')
		method = 'flickr.photos.search'
		data = _doget(method, auth=auth, {'user_id'=>user_id, 'tags'=>tags,\
		 	'text'=>text, 'min_upload_date'=>min_upload_date,\
                  	'max_upload_date'=>max_upload_date, 'per_page'=>per_page,\
                   	'page'=>page})
		p = []
		doc = Document.new(data)
		doc.elements.each('rsp/photos/photo') { |photo|
			id = photo.attributes['id']
			owner = photo.attributes['owner']
			title = photo.attributes['title']
			ispublic = photo.attributes['ispublic']
			isfriend = photo.attributes['isfriend']
			isfamily = photo.attributes['isfamily']
			photo_obj = Photo.new(id, owner=owner, title=title,\
				    ispublic=ispublic, isfriend=isfriend,\
				    isfamily=isfamily)
			p << photo_obj
		}
		p
	end

	##
	# Returns a User object for given email
	##
	def people_findByEmail(email)
		method = 'flickr.people.findByEmail'
		data = _doget(method, false, {'find_email'=>email})
		doc = Document.new(data)
		user = doc.elements['rsp/user']
		user = User.new(user.attributes['id'], username=user.elements['username'].text)
		user
	end

	##
	# Returns a User object for given username
	##
	def people_findByUsername(username)
		method = 'flickr.people.findByUsername'
		data = _doget(method, false, {'username'=>username})
		doc = Document.new(data)
		user = doc.elements['rsp/user']
		user = User.new(user.attributes['id'], username=user.elements['username'].text)
		user
	end

	##
	# Returns a list of public photos for userid, as Photo objects
	##
	def people_getPublicPhotos(user_id, per_page='', page='')
		method = 'flickr.people.getPublicPhotos'
		data = _doget(method, false, {'user_id'=>user_id,\
			'per_page'=>per_page, 'page'=>page})
		p = []
		doc = Document.new(data)
		doc.elements.each('rsp/photos/photo') { |photo|
			id = photo.attributes['id']
			owner = photo.attributes['owner']
			title = photo.attributes['title']
			ispublic = photo.attributes['ispublic']
			isfriend = photo.attributes['isfriend']
			isfamily = photo.attributes['isfamily']
			photo_obj = Photo.new(id, owner=owner, title=title,\
				    ispublic=ispublic, isfriend=isfriend,\
				    isfamily=isfamily)
			p << photo_obj
		}
		p
	end

	##
	# Returns a list of favorite photos for userid, as Photo objects
	##
	def favorites_getList(user_id='', per_page='', page='')
		# Returns list of Photo objects
		method = 'flickr.favorites.getList'
		data = _doget(method, auth=true, {'user_id'=>user_id,\
			'per_page'=>per_page, 'page'=>page})
		p = []
		doc = Document.new(data)
		doc.elements.each('rsp/photos/photo') { |photo|
			id = photo.attributes['id']
			owner = photo.attributes['owner']
			title = photo.attributes['title']
			ispublic = photo.attributes['ispublic']
			isfriend = photo.attributes['isfriend']
			isfamily = photo.attributes['isfamily']
			photo_obj = Photo.new(id, owner=owner, title=title,\
				    ispublic=ispublic, isfriend=isfriend,\
				    isfamily=isfamily)
			p << photo_obj
		}
		p
	end
end



##
# JLT
##
def login
	method = 'flickr.test.login'
	data = _doget(method, auth=true)
	doc = Document.new(data)
	user = doc.elements['rsp/user']
	user = User.new(user.attributes['id'],\
	       username=user.elements['username'].text)
	user
end

def test_echo
	method = 'flickr.test.echo'
	data = _doget(method, false)
	doc = Document.new(data)
	doc.elements['rsp'].attributes['stat']
end



##
# methods for use within the classes
##
def _doget(method, auth=false, *params)
	params.each { |x, y|
		if y.class == Array then params[x] = y.join(y) end
	}
	url = "#{$HOST}#{$API}/?api_key=#{$API_KEY}&method=#{method}#{_urlencode(params)}"
	if auth then url = url + "&email=#{$email}&password=#{$password}" end
	p url
	resp = Net::HTTP.get_response(URI.parse(url))
	doc = Document.new(resp.body.to_s)
	if doc.elements['rsp'].attributes['stat'] != 'ok'
		error_code = doc.elements['rsp'].elements['err'].attributes['code']
		error_msg = doc.elements['rsp'].elements['err'].attributes['msg']
		msg = "ERROR[#{error_code}]: #{error_msg}"
	end
	resp.body.to_s
end

def _urlencode(params)
	ret = ''
	params.each { |param|
		param.each { |x, y|
			ret += "&#{x}=#{y}"
		}
	}
	ret
end
Created by premshree
Last modified 2006-07-30 11:45 AM
« May 2008 »
Su Mo Tu We Th Fr Sa
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
 
 

Powered by Plone

This site conforms to the following standards: