scaretable 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e90c999f6824dc4082e33a69d0e5d8513e3e4e754f4fbbab291f8cfa8be3d87c
4
+ data.tar.gz: ddef578cab89dd4a7c2c0889e11705d98f9c8428e89eaab15461a44ff1e85c10
5
+ SHA512:
6
+ metadata.gz: 4dff30c97d03ff1c669d2ff613c185207eb334a3cc16f34f3d8d46d7b94dcab281a4b1e8c7f7048973ccc2349f77ac3f6148dbae1f9618dbed60085970c8891a
7
+ data.tar.gz: 5ad87791253ac1ea0b30fb140cf266702848f4d367e0795a971c62187a91b888bfaf7541ff7dcd87d073f3b20c91bd8828990957828d8870e301dc50d0f325b2
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,19 @@
1
+ AllCops:
2
+ TargetRubyVersion: 3.1
3
+
4
+ Style/StringLiterals:
5
+ EnforcedStyle: single_quotes
6
+
7
+ Style/StringLiteralsInInterpolation:
8
+ EnforcedStyle: single_quotes
9
+
10
+ Style/PercentLiteralDelimiters:
11
+ PreferredDelimiters:
12
+ default: '()'
13
+ '%i': '()'
14
+
15
+ Layout/LineLength:
16
+ Enabled: false
17
+
18
+ Metrics:
19
+ Enabled: false
data/CHANGELOG.md ADDED
@@ -0,0 +1,4 @@
1
+ # changelog:
2
+
3
+ ### 0.1.0 (2024-04-08)
4
+ it begins.
data/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # Scaretable
2
+
3
+ this gem is a place for me to stash my less-than-legitimate Airtable tricks.
4
+ as of now it's just CSV export, but surely more will follow given the limited nature of this blessed platform's publicly documented API surface.
5
+
6
+ you have the "i'll probably fix this when Airtable breaks it" guarantee (tbc only valid for as long as i'm working in codebases that need this functionality)
7
+
8
+ ## Installation
9
+
10
+ install the gem and add to the application's Gemfile by executing:
11
+
12
+ ```bash
13
+ bundle add scaretable
14
+ ```
15
+
16
+ if bundler is not being used to manage dependencies, install the gem by executing:
17
+
18
+ ```bash
19
+ gem install scaretable
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ i wouldn't....
25
+
26
+ anyway, call `Scaretable.get_csv("appfymsBOQvUDVDrn", "shrEcl5zKeqmzNKXG", "viw6pc5plZ0r1oZTS")` for a CSV.
27
+ if you don't specify a view ID, it'll figure it out.
28
+ `get_csv_url` is also available if you want to download it yourself.
29
+
30
+ ## Development
31
+ are you sure?
32
+
33
+
34
+ after checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. you can also run `bin/console` for an interactive prompt that will allow you to experiment.
35
+
36
+ to install this gem onto your local machine, run `bundle exec rake install`. to release a new version, bump version.rb and push to main, preferably without running the test suite first.
37
+
38
+ ## Contributing
39
+
40
+ PRs welcome! bug reports also welcome, but slightly less so.
41
+ this repo lives at https://github.com/24c02/scaretable.
42
+
43
+ ## License
44
+
45
+ lol as if
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require 'rubocop/rake_task'
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i(spec rubocop)
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Scaretable
4
+ VERSION = '0.1.0'
5
+ end
data/lib/scaretable.rb ADDED
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'scaretable/version'
4
+ require 'faraday'
5
+ require 'uri'
6
+ require 'json'
7
+
8
+ # unstable evil Airtable interface
9
+ module Scaretable
10
+ class Error < StandardError; end
11
+
12
+ class << self
13
+ attr_accessor :timezone
14
+ attr_writer :conn # in case i ever write tests
15
+
16
+ # given an appxxx, a shrxxx (and a viwxxx if you're feeling generous),
17
+ # get CSV content ready to feed into CSV.parse
18
+ def get_csv(base_id, share_id, view_id = nil)
19
+ url = get_csv_url(base_id, share_id, view_id)
20
+ conn.get(url).body.sub("\uFEFF", '') # U woTF m-8? BOMs away...
21
+ end
22
+
23
+ # you ship an appxxx, a shrxxx (and a viwxxx if you're feeling generous),
24
+ # we ship a URL at which airtable thinks you might find a CSV
25
+ def get_csv_url(base_id, share_id, view_id = nil)
26
+ params = grab_params(base_id, share_id)
27
+
28
+ access_policy = params['accessPolicy'] or raise Error, 'where accessPolicy? did you check between the couch cushions?'
29
+ actions = JSON.parse(access_policy, symbolize_names: true)[:allowedActions] or raise Error, 'no allowedActions? god forbid women do anything'
30
+ view_id ||= actions.find { |a| a[:modelClassName] == 'view' }
31
+ &.dig(:modelIdSelector) or raise Error, 'no view id? visionblind.'
32
+
33
+ resp = conn.get(
34
+ "https://airtable.com/v0.3/view/#{view_id}/downloadCsv",
35
+ {
36
+ 'x-time-zone' => effective_timezone,
37
+ 'x-user-locale' => 'en',
38
+ 'x-airtable-application-id' => base_id,
39
+ 'stringifiedObjectParams' => { origin: 'viewMenuPopover' } # me when i lie:
40
+ }.merge(
41
+ # i think these are the only ones we need?
42
+ params.slice('accessPolicy', 'requestId')
43
+ )
44
+ )
45
+
46
+ location = resp.headers['location'] or raise Error, "idk where i'm going with this"
47
+ location
48
+ end
49
+
50
+ def grab_params(base_id, share_id)
51
+ page = conn.get("https://airtable.com/#{base_id}/#{share_id}").body
52
+ /urlWithParams: "(.*?)"/ =~ page or raise Error, 'urlWithParams? never heard of her :-('
53
+ q = URI(::Regexp.last_match(1).gsub('\u002F', '/')).query or raise Error, 'congrats! you found the string with no query params!' # why is it Like That
54
+ URI.decode_www_form(q).to_h
55
+ end
56
+
57
+ def effective_timezone
58
+ timezone || 'America/New_York' # let's be real is it ever not gonna be EST
59
+ end
60
+
61
+ def conn
62
+ @conn ||= Faraday.new do |f|
63
+ f.request :url_encoded
64
+ f.adapter Faraday.default_adapter
65
+ f.response :raise_error
66
+ # "Hello Airtable, am Firefox. Please give me your secrets."
67
+ f.headers['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:137.0) Gecko/20100101 Firefox/137.0'
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,10 @@
1
+ module Scaretable
2
+ VERSION: String
3
+ attr_accessor self.timezone: String
4
+
5
+ def self.get_csv: -> String
6
+
7
+ def self.get_csv_url: -> String
8
+
9
+ def self.get_share_params: -> Hash[String, String]
10
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: scaretable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - 24c02
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 2025-04-09 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: faraday
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '2.13'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '2.13'
26
+ email:
27
+ - nora@hackclub.com
28
+ executables: []
29
+ extensions: []
30
+ extra_rdoc_files: []
31
+ files:
32
+ - ".rspec"
33
+ - ".rubocop.yml"
34
+ - CHANGELOG.md
35
+ - README.md
36
+ - Rakefile
37
+ - lib/scaretable.rb
38
+ - lib/scaretable/version.rb
39
+ - sig/scaretable.rbs
40
+ homepage: https://github.com/24c02/scaretable
41
+ licenses:
42
+ - MIT
43
+ metadata:
44
+ homepage_uri: https://github.com/24c02/scaretable
45
+ source_code_uri: https://github.com/24c02/scaretable
46
+ changelog_uri: https://github.com/24c02/scaretable/blob/main/CHANGELOG.md
47
+ rdoc_options: []
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 3.1.0
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ requirements: []
61
+ rubygems_version: 3.6.2
62
+ specification_version: 4
63
+ summary: less-than-legit Airtable interface
64
+ test_files: []