Created
March 25, 2011 08:01
-
-
Save yuanying/886519 to your computer and use it in GitHub Desktop.
ガーミンコネクトのデータを Nike+ と同期するスクリプト。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby -wKU | |
require 'rubygems' | |
require 'rss/1.0' | |
require 'rss/2.0' | |
require 'rss/dublincore' | |
require 'open-uri' | |
require 'uri' | |
require 'cgi' | |
require 'optparse' | |
garmin_username = nil | |
nike_email = nil | |
nike_password = nil | |
proxy_host = nil | |
proxy_port = nil | |
opts = OptionParser.new | |
opts.on('-g', '--garmin-username GARMIN_USERNAME') { |v| garmin_username = v } | |
opts.on('-n', '--nike-email NIKE_PLUS_EMAIL') { |v| nike_email = v } | |
opts.on('-p', '--nike-password NIKE_PLUS_PASSWORD') { |v| nike_password = v } | |
opts.on('--proxy-host PROXY_HOST') { |v| proxy_host = v } | |
opts.on('--proxy-port PROXY_PORT', Integer) { |v| proxy_port = v } | |
opts.parse!(ARGV) | |
tmp = '/tmp/last-garmin-connect-url.txt' | |
url = nil | |
if File.exist?(tmp) | |
open(tmp) do |io| | |
url = io.read.chomp | |
end | |
end | |
rss = nil | |
rss_url = "http://connect.garmin.com/feed/rss/activities?feedname=Garmin#{Time.now.strftime('%Y%m%d%H')}&explore=true&activityType=running&eventType=all&activitySummarySumDistance-unit=kilometer&activitySummarySumDuration-unit=hour&activitySummaryGainElevation-unit=meter&owner=#{garmin_username}&sortField=beginTimestamp" | |
open(rss_url) do |io| | |
rss = RSS::Parser.parse(io.read) | |
end | |
module Multipart | |
class Post | |
# We have to pretend like we're a web browser... | |
USERAGENT = "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/523.10.6 (KHTML, like Gecko) Version/3.0.4 Safari/523.10.6" unless const_defined?(:USERAGENT) | |
BOUNDARY = "0123456789ABLEWASIEREISAWELBA9876543210" unless const_defined?(:BOUNDARY) | |
CONTENT_TYPE = "multipart/form-data; boundary=#{ BOUNDARY }" unless const_defined?(:CONTENT_TYPE) | |
HEADER = { "Content-Type" => CONTENT_TYPE, "User-Agent" => USERAGENT } unless const_defined?(:HEADER) | |
def self.prepare_query(params) | |
fp = [] | |
params.each do |k, v| | |
fp.push(StringParam.new(k, v)) | |
end | |
# Assemble the request body using the special multipart format | |
query = fp.collect {|p| "--" + BOUNDARY + "\r\n" + p.to_multipart }.join("") + "--" + BOUNDARY + "--" | |
return query, HEADER | |
end | |
end | |
private | |
# Formats a basic string key/value pair for inclusion with a multipart post | |
class StringParam | |
attr_accessor :k, :v | |
def initialize(k, v) | |
@k = k | |
@v = v | |
end | |
def to_multipart | |
return "Content-Disposition: form-data; name=\"#{CGI::escape(k)}\"\r\n\r\n#{v}\r\n" | |
end | |
end | |
end | |
class Tcx2NikePlus | |
require 'net/http' | |
Net::HTTP.version_1_2 | |
def post activity_id, email, password, proxy_addr=nil, proxy_port=nil | |
Net::HTTP::Proxy(proxy_addr, proxy_port).start('www.awsmithson.com', 80) {|http| | |
data, headers = ::Multipart::Post.prepare_query( | |
"garminActivityId" => activity_id, | |
"chkGps" => 'true', | |
"nikeEmail" => email, | |
"nikePassword" => password | |
) | |
response = http.post('/tcx2nikeplus/tcx2nikeplus/convert', data, headers) | |
raise "Error: #{response.body}" unless /"success":true/ =~ response.body | |
} | |
end | |
end | |
urls = [] | |
rss.items.each do |item| | |
if item.link == url | |
break | |
end | |
urls << item.link | |
end | |
urls.reverse.each do |url| | |
activity_id = url.split('/').last | |
Tcx2NikePlus.new.post(activity_id, nike_email, nike_password, proxy_host, proxy_port) | |
open(tmp, 'w') do |io| | |
io.write url | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment