#!/usr/bin/env ruby
require 'rubygems'
Gem.path.push("/home/danbri/.gems")
require 'json'
# Ruby script to make KML for a Flickr group specified by its ID code
# Uses XSLT transforms by Danny Ayers
# Assumes some unix environment currently, including xsltproc commandline
# by Dan Brickley
# $Id$
# Ruby script to make KML for a Flickr group specified by its ID code
# Uses XSLT transforms by Danny Ayers
# Assumes some unix environment currently, including xsltproc commandline
# by Dan Brickley
# $Id$
# Notes:
#
# We use JSON that has been transformed from XML
# rather than Flickr's native JSON output. This is to explore
# possibility of a compatibility layer with SPARQL-accessed RDF data
# eg. such as that archived by the Net::Flickr::Backup CPAN module.
# Our JSON is in a tabular structure specified by W3C as a representation
# of the results we might get back from an RDF query. Basically, a bit like SQL.
#
# To achieve this we create some scratch files (_*.xml etc) and run
# XSLT on the commandline. Bit of a mess. But you'll live.
#
# Other mess:
# JSON library is a Ruby gem installation. How do we do that on Dreamhost?
#
# see http://norman.walsh.name/2006/10/20/examples/login
# Escape a string for printing to XML
#
def esc(str)
str = str.to_s.gsub("&", "&")
str = str.gsub("\"", "'")
str = str.gsub("\"", """)
str = str.gsub("<", "<")
str.gsub(">", ">")
end
# return a Flickr username, given a Flickr ID
# todo: failure conditions? - bad ID? no name set?
#
def nameFromID(user_id, cache)
return cache[user_id] if cache[user_id]
require 'net/http'
require 'uri'
api_key=ENV["FLICKR_API_KEY"] if ENV["FLICKR_API_KEY"]
uri="http://api.flickr.com/services/rest/?method=flickr.people.getInfo&api_key=#{api_key}&user_id=#{user_id}"
who = Net::HTTP.get(URI.parse(uri))
STDERR.puts("REST API user lookup: #{uri}")
who =~ /(.*)<\/username>/ # dumbass. use an api. any api!
name = ""
name = $1 if $1
cache[user_id] = name
STDERR.puts("Cached user lookup: #{user_id} as '#{name}' ")
return name
end
# Assuming our data is in file, return it KMLized
#
def json2kml(js, name="")
res = JSON.parse js
kml = ""
kml += ''
kml += "\n"
kml += ''
kml += "\n"
kml += "foaftown tester #{name}\n"
name_cache = {}
res["results"]["bindings"].each do |pic|
id = esc pic['id']['value']
owner = esc pic['owner']['value']
secret = esc pic['secret']['value']
server = esc pic['server']['value']
title = esc pic['title']['value']
lat = esc pic['latitude']['value'] if pic['latitude']
lon = pic['longitude']['value'] if pic['longitude']
acc = pic['accuracy']['value'] if pic['accuracy']
# See http://www.flickr.com/services/api/misc.urls.html
s_url = "http://static.flickr.com/" + server + "/" + id + "_" + secret + "_s.jpg"
m_url = "http://static.flickr.com/" + server + "/" + id + "_" + secret + "_m.jpg"
image_url = "http://static.flickr.com/" + server + "/" + id + "_" + secret + ".jpg"
img_page = "http://www.flickr.com/photos/" + owner +"/" + id
# puts "#{title} #{id} #{lat} #{lon} #{s_url} #{img_page}"
STDERR.puts("Making KML for: #{title} #{id} #{lat} #{lon} #{s_url} #{img_page}")
kml += "
#{title}
1
by #{nameFromID(owner,name_cache)}
at lat:#{lat} lon:#{lon} map level: #{acc}
]]>
#{title}
#{lon}
#{lat}
0
30
0
1
root://styleMaps#default?iconId=0x307
#{lon},#{lat},0
\n"
end
kml += "\n";
kml += "\n\n";
return kml
end
def getGroupMapXML(group_id)
require 'net/http'
require 'uri'
api_key=ENV["FLICKR_API_KEY"]
# min_taken_date=1970-01-01%2000:00:00&bbox=-180,-90,180,90&
# even if we set per_page=500, we get paged results here
#
# It might be time to use a proper API
uri="http://api.flickr.com/services/rest/?bbox=-180,-90,180,90&method=flickr.photos.search&api_key=#{api_key}&group_id=#{group_id}&extras=license,date_upload,date_taken,owner_name,icon_server,original_format,last_update,geo&per_page=500&accuracy=6"
xdata = Net::HTTP.get(URI.parse(uri))
xdata.gsub!(""","'") # so we can XSLT into JSON
# See http://www.flickr.com/services/api/flickr.photos.search.html
#per_page (Optional)
# Number of photos to return per page. If this argument is omitted, it defaults to 100. The #maximum allowed value is 500.
#page (Optional)
# The page of results to return. If this argument is omitted, it defaults to 1.
return xdata
end
def storeGroupMapJSON(group_id)
mymapdata = getGroupMapXML(group_id)
fdata = File.new("_fdata.xml","w")
fdata.puts(mymapdata)
fdata.close
bin="/home/danbri/working/bin/"
`#{bin}xsltproc flickr-sparqlxml.xsl _fdata.xml > _tmp.xml`
`#{bin}xsltproc pretty-xml.xsl _tmp.xml > _fdata_sparql.xml`
`#{bin}xsltproc flickr-sparqljson.xsl _fdata.xml > _fdata_json.js`
end
def getGroupKML(group_id)
storeGroupMapJSON(group_id)
file = File.new("_fdata_json.js", "r")
js=""
while (line = file.gets) # todo: get string from file must be easier
js = js + line
end
file.close
return json2kml(js, "group "+group_id)
end
def storeGroupKML(pool, dir="")
mykml = getGroupKML(pool)
fn= "_pool_#{pool}.kml"
kfile = File.new(dir+fn,"w+")
kfile.puts(mykml)
STDERR.puts("Stored KML for pool #{pool} in #{dir} file: #{fn} ")
kfile.close
end
group = "43935391225@N01" # B.A.
dir = "./examples/"
#storeGroupKML(group, dir)
#storeGroupKML("52240190192@N01",dir)# http://www.flickr.com/groups/iranian/pool/map
#storeGroupKML("43935391225@N01",dir) # http://www.flickr.com/groups/bsas/pool/map
#storeGroupKML("46594087@N00",dir) # http://www.flickr.com/groups/bristol/pool/map