Compare commits

...

4 Commits

@ -1,14 +0,0 @@
name: Do Things
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: actions/setup-ruby@v1
with:
ruby-version: '2.6.x'
- run: |
gem install bundler
bundle install --jobs 4 --retry 3
bundle exec rake

1
.gitignore vendored

@ -1,3 +1,4 @@
.*env
*.csv
.ruby-version
.envrc

@ -1,13 +0,0 @@
inherit_from: .rubocop_todo.yml
AllCops:
TargetRubyVersion: 2.6
Style/Documentation:
Enabled: false
Style/AccessModifierDeclarations:
EnforcedStyle: inline
Layout/MultilineMethodCallIndentation:
EnforcedStyle: indented

@ -1,7 +0,0 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2020-01-11 15:25:31 -0500 using RuboCop version 0.78.0.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.

@ -0,0 +1,42 @@
// vim:filetype=javascript
const defaultSeriesURL = "https://api.bls.gov/publicAPI/v2/timeseries/data/";
const defaultSeriesID = "CUUR0200SA0";
const defaultStartYear = "2014";
function CURRENTCPI(blsToken, options) {
var seriesURL = options?.seriesURL || defaultSeriesURL;
var seriesID = options?.seriesID || defaultSeriesID;
var startYear = options?.startYear || defaultStartYear;
var endYear = options?.endYear || new Date().getFullYear().toString();
var reqOptions = {
"method": "post",
"payload": JSON.stringify({
"seriesid": [seriesID],
"startyear": startYear,
"endyear": endYear
}),
"contentType": "application/json",
"headers": {
"Authorization": "token "+blsToken,
"Content-Type": "application/json"
}
};
var resp = UrlFetchApp.fetch(seriesURL, reqOptions);
var rawData = resp.getContentText().toString().trim();
var parsedData = JSON.parse(rawData);
var respData = parsedData.Results.series[0].data;
var rows = [["year", "period", "period_name", "value"]];
for (var i = 0; i < respData.length; i++) {
rows.push([
respData[i].year,
respData[i].period,
respData[i].periodName,
respData[i].value
]);
}
return rows;
}

@ -1,11 +0,0 @@
# frozen_string_literal: true
source 'https://rubygems.org'
ruby '2.7.2' if ENV.key?('DYNO')
gem 'aws-sdk', '~> 2'
gem 'pry', group: %i[development test]
gem 'rack'
gem 'rake'
gem 'rubocop', group: %i[development test]

@ -1,49 +0,0 @@
GEM
remote: https://rubygems.org/
specs:
ast (2.4.0)
aws-eventstream (1.0.3)
aws-sdk (2.11.421)
aws-sdk-resources (= 2.11.421)
aws-sdk-core (2.11.421)
aws-sigv4 (~> 1.0)
jmespath (~> 1.0)
aws-sdk-resources (2.11.421)
aws-sdk-core (= 2.11.421)
aws-sigv4 (1.1.0)
aws-eventstream (~> 1.0, >= 1.0.2)
coderay (1.1.2)
jaro_winkler (1.5.4)
jmespath (1.4.0)
method_source (0.9.2)
parallel (1.19.1)
parser (2.7.0.1)
ast (~> 2.4.0)
pry (0.12.2)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
rack (2.0.8)
rainbow (3.0.0)
rake (13.0.1)
rubocop (0.78.0)
jaro_winkler (~> 1.5.1)
parallel (~> 1.10)
parser (>= 2.6)
rainbow (>= 2.2.2, < 4.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 1.7)
ruby-progressbar (1.10.1)
unicode-display_width (1.6.0)
PLATFORMS
ruby
DEPENDENCIES
aws-sdk (~> 2)
pry
rack
rake
rubocop
BUNDLED WITH
2.1.2

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright © 2020 Dan Buch
Copyright © 2023 Dan Buch
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

@ -1 +0,0 @@
web: bundle exec rackup -p $PORT

@ -1,21 +1,20 @@
# cpi-feed
Transforms [this](https://api.bls.gov/publicAPI/v2/timeseries/data/CUUSA210SA0)
into [this](https://s3.amazonaws.com/meatballhat/cpi/current.csv) :tada:.
into CSV rows.
## usage
This is intended for use with Google Sheets via:
```
=IMPORTDATA("https://s3.amazonaws.com/meatballhat/cpi/current.csv")
=CURRENTCPI("{bls-token}")
```
## deployment
where `{bls-token}` is the value issued after registering with
[bls.gov](https://www.bls.gov/developers/home.htm).
A copy of this thing is deployed to Heroku with a Heroku Scheduler addon
configured to run the following once daily:
## deployment
``` bash
bundle exec ./sync
```
Just like [this
example](https://apipheny.io/import-json-google-sheets/).

@ -1,11 +0,0 @@
# frozen_string_literal: true
begin
require 'rubocop/rake_task'
rescue LoadError => e
warn e
end
RuboCop::RakeTask.new if defined?(RuboCop)
task default: %i[rubocop]

@ -1,3 +0,0 @@
# frozen_string_literal: true
run ->(*) { [301, { 'Location' => ENV['CPI_FEED_URL'] }, []] }

@ -1,94 +0,0 @@
# frozen_string_literal: true
require 'csv'
require 'json'
require 'net/http'
require 'net/https'
require 'uri'
class CPIFetcher
def cpi
resp = fetch_raw_response
return nil unless resp['Results']['series']
resp['Results']['series'].first['data']
end
def cpi_csv
CSV.generate do |csv|
csv << %w[year period period_name value]
cpi.each do |rec|
csv << %w[
year period periodName value
].map { |k| rec.fetch(k) }
end
end
end
private def url
@url ||= URI(ENV['CPI_SERIES_URL'] || File.join(
'https://api.bls.gov',
'publicAPI/v2/timeseries/data/'
))
end
private def series_id
@series_id ||= ENV.fetch(
'CPI_SERIES_ID', 'CUUR0200SA0'
).split(/[, ]/).map(&:strip).reject(&:empty?)
end
private def start_year
@start_year ||= ENV.fetch('CPI_SERIES_START_YEAR', '2014')
end
private def end_year
@end_year ||= ENV.fetch('CPI_SERIES_END_YEAR', Time.now.year.to_s)
end
private def bls_token
@bls_token ||= ENV.fetch('BLS_TOKEN')
end
private def start_cpi_value(data)
data = data.sort do |a, b|
record_key(a) <=> record_key(b)
end
data.first.fetch('value')
end
private def record_key(record)
"#{record['year']}.#{record['period']}"
end
private def latest_cpi_value(data)
data.find { |d| d['latest'] == 'true' }.fetch('value')
end
private def fetch_raw_response
Net::HTTP.new(url.hostname, url.port)
.tap { |h| h.use_ssl = true }
.tap { |h| h.verify_mode = OpenSSL::SSL::VERIFY_PEER }
.then { |h| JSON.parse(h.request(build_request).body) }
end
private def build_request
Net::HTTP::Post.new(url)
.tap { |r| r['Authorization'] = "token #{bls_token}" }
.tap { |r| r['Content-Type'] = 'application/json' }
.tap { |r| r.body = JSON.generate(build_request_body) }
end
private def build_request_body
{
'seriesid' => series_id,
'startyear' => start_year,
'endyear' => end_year
}
end
end
if $PROGRAM_NAME == __FILE__
puts CPIFetcher.new.cpi_csv
exit 0
end

@ -1,35 +0,0 @@
# frozen_string_literal: true
require 'aws-sdk'
class MiniS3put
def initialize(key: nil, instream: $stdin)
@bucket = ENV.fetch('CPI_FEED_AWS_BUCKET')
@key = key || ENV.fetch('CPI_FEED_AWS_KEY')
@instream = instream
end
attr_reader :bucket, :key, :instream
private :bucket, :key, :instream
def put
Aws::S3::Resource.new.bucket(bucket).object(key).put(
body: instream.read
).on_success(&method(:on_put_success))
end
private def on_put_success(response)
puts response.data
Aws::S3::Client.new.put_object_acl(
bucket: bucket, key: key, acl: 'public-read'
).on_success do |acl_response|
puts acl_response.data
end
end
end
if $PROGRAM_NAME == __FILE__
MiniS3put.new(key: ARGV.first).put
exit 0
end

@ -1,2 +0,0 @@
#!/usr/bin/env bash
ruby cpi_fetcher.rb | ruby mini_s3put.rb
Loading…
Cancel
Save