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 +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +19 -0
- data/CHANGELOG.md +4 -0
- data/README.md +45 -0
- data/Rakefile +12 -0
- data/lib/scaretable/version.rb +5 -0
- data/lib/scaretable.rb +71 -0
- data/sig/scaretable.rbs +10 -0
- metadata +64 -0
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
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
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
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
|
data/sig/scaretable.rbs
ADDED
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: []
|