## Usage # gem install oauth2 # ruby checkins.rb # ## .env # https://foursquare.com/developers/apps # ENV["4SQ_CLIENT_ID"] = "" # ENV["4SQ_CLIENT_SECRET"] = "" # ENV["4SQ_REDIRECT_URI"] = "http://localhost" # ## Save access_token after running this script # ENV["4SQ_ACCESS_TOKEN"] = "" # ## Import CSV to Google Calendar # https://calendar.google.com/calendar/u/0/r/settings/export require "oauth2" require "csv" begin load ".env"; rescue LoadError; nil; end client_id = ENV["4SQ_CLIENT_ID"] client_secret = ENV["4SQ_CLIENT_SECRET"] redirect_uri = ENV["4SQ_REDIRECT_URI"] access_token = ENV["4SQ_ACCESS_TOKEN"] csv_path = "./#{Time.now.strftime("%Y%m%d%H%M")}.csv" accept_language = "ja", client = OAuth2::Client.new(client_id, client_secret, { site: "https://foursquare.com", authorize_url: "oauth2/authenticate", token_url: "oauth2/access_token" }) if access_token.nil? || access_token.empty? authorize_url = client.auth_code.authorize_url(redirect_uri: redirect_uri) puts "Open url below and copy a code from callback url:\n#{authorize_url}" puts "Paste the code:" code = gets.chomp token = client.auth_code.get_token(code, redirect_uri: redirect_uri) access_token = token.token puts "Save access_token if you want: #{access_token}" end offset = 0 limit = 250 items = [] loop do puts "Fetching: #{offset}..#{offset + limit}" response = client.request( :get, "https://api.foursquare.com/v2/users/self/checkins", params: { v: 20210514, limit: limit, offset: offset, oauth_token: access_token, headers: { "Accept-Language" => accept_language } } ) checkins = response.parsed.dig("response", "checkins") items += checkins["items"] offset += limit break if checkins["count"] < offset end rows = items.map do |item| created_at = Time.at(item["createdAt"] + item["timeZoneOffset"] * 60, in: "UTC") start_date = created_at.strftime("%-m/%-d/%Y") start_time = created_at.strftime("%H:%M %p") venue = item.dig("venue") location = venue["location"] formattedAddress = location["formattedAddress"] || [] if location["cc"] == "JP" case formattedAddress.size when 2 index = -1 when 3 index = -2 end if index address = formattedAddress[index].split(", ").reverse.join address += formattedAddress[0] end else address = formattedAddress.join(", ") end { "Subject" => venue["name"], "Start Date" => start_date, "Start Time" => start_time, "End Date" => start_date, "End Time" => start_time, "All Day Event" => "False", "Description" => item["shout"], "Location" => address, "Private" => "False" } end CSV.open(csv_path, "wb", converters: nil) do |csv| csv << rows.first.keys rows.each { |row| csv << row.values } end