[WIP] Post Roulette feed where it sends you random posts by users you follow, unbiased by post age.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

initial commit

ansxor 1bb44d0a

+775
+29
.github/workflows/main.yml
··· 1 + name: Ruby 2 + 3 + on: 4 + push: 5 + branches: 6 + - master 7 + 8 + pull_request: 9 + 10 + jobs: 11 + build: 12 + runs-on: ubuntu-latest 13 + name: Ruby ${{ matrix.ruby }} 14 + strategy: 15 + matrix: 16 + ruby: 17 + - '4.0.1' 18 + 19 + steps: 20 + - uses: actions/checkout@v4 21 + with: 22 + persist-credentials: false 23 + - name: Set up Ruby 24 + uses: ruby/setup-ruby@v1 25 + with: 26 + ruby-version: ${{ matrix.ruby }} 27 + bundler-cache: true 28 + - name: Run the default task 29 + run: bundle exec rake
+11
.gitignore
··· 1 + /.bundle/ 2 + /.yardoc 3 + /_yardoc/ 4 + /coverage/ 5 + /doc/ 6 + /pkg/ 7 + /spec/reports/ 8 + /tmp/ 9 + .env 10 + .valkey_data 11 + .postgres_data
+3
.standard.yml
··· 1 + # For available configuration options, see: 2 + # https://github.com/standardrb/standard 3 + ruby_version: 4.1
+150
AGENTS.md
··· 1 + # AGENTS.md 2 + 3 + ## Repository summary 4 + - Ruby gem that provides a BlueFactory feed implementation. 5 + - Main entrypoint: `lib/bskypostroulettefeed.rb`. 6 + - Feed definition and server configuration live in `lib/bskypostroulettefeed/feed/`. 7 + - Tests use Minitest in `test/`. 8 + - Linting/formatting uses StandardRB via `standard` gem. 9 + - Build/release tasks come from `bundler/gem_tasks`. 10 + 11 + ## Setup 12 + - Install dependencies: `bin/setup` (runs `bundle install`). 13 + - Use `bundle exec` for all Ruby tooling. 14 + - Ruby version must satisfy the gemspec requirement (`>= 3.2.0`). 15 + 16 + ## Common commands 17 + - Default checks: `bundle exec rake` (runs tests + StandardRB). 18 + - Tests (all): `bundle exec rake test`. 19 + - Tests (single file): `bundle exec rake test TEST=test/test_bskypostroulettefeed.rb`. 20 + - Tests (single test name): `bundle exec ruby -Itest test/test_bskypostroulettefeed.rb -n test_name`. 21 + - Lint/format: `bundle exec standardrb`. 22 + - Lint via rake: `bundle exec rake standard`. 23 + - Build gem: `bundle exec rake build`. 24 + - Install gem locally: `bundle exec rake install`. 25 + - Interactive console: `bin/console`. 26 + - Run feed server (local dev): `bin/dev-feed` (requires env vars). 27 + 28 + ## Environment variables 29 + - `PUBLISHER_DID`: DID used by BlueFactory publisher. 30 + - `HOSTNAME`: hostname for feed endpoints. 31 + - Configure via shell env before running `bin/dev-feed`. 32 + 33 + ## Code layout 34 + - `lib/bskypostroulettefeed.rb` defines the gem module. 35 + - `lib/bskypostroulettefeed/version.rb` stores `VERSION`. 36 + - `lib/bskypostroulettefeed/feed/` contains feed config and implementation. 37 + - `sig/` stores RBS type signatures. 38 + - `test/` contains Minitest suites and `test_helper`. 39 + 40 + ## Formatting and linting (StandardRB) 41 + - Use StandardRB conventions; do not manually fight the formatter. 42 + - Run `bundle exec standardrb` after edits that touch Ruby files. 43 + - Prefer StandardRB defaults (2-space indent, no semicolons). 44 + - Let StandardRB manage trailing commas and hash formatting. 45 + 46 + ## Requires and file loading 47 + - Use `# frozen_string_literal: true` at top of Ruby files. 48 + - Order requires as: stdlib, gem dependencies, then `require_relative`. 49 + - Prefer `require_relative` for internal library files. 50 + - Keep require blocks minimal and scoped to file needs. 51 + 52 + ## Naming conventions 53 + - Modules/classes: CamelCase (`PostRouletteFeed`, `Bskypostroulettefeed`). 54 + - Methods/variables: snake_case. 55 + - Constants: SCREAMING_SNAKE_CASE. 56 + - Files: snake_case, mirroring module paths. 57 + - Test classes: `Test*` subclasses of `Minitest::Test`. 58 + - Test methods: `test_*` names. 59 + 60 + ## Types and signatures 61 + - Public API changes should be reflected in `sig/*.rbs`. 62 + - Keep RBS modules/classes aligned with Ruby implementation. 63 + - Use `String`, `Integer`, `Array[String]` style RBS types. 64 + - If adding new public classes, add matching RBS stubs. 65 + 66 + ## Error handling 67 + - Define custom errors under `Bskypostroulettefeed::Error` when needed. 68 + - Raise specific errors rather than generic `StandardError`. 69 + - Avoid rescuing broad exceptions unless you re-raise with context. 70 + - Include actionable messages for runtime errors. 71 + 72 + ## Configuration and environment 73 + - Use `ENV.fetch` when a variable is required. 74 + - Use `ENV["NAME"]` when optional. 75 + - Keep configuration centralized in `lib/bskypostroulettefeed/feed/config.rb`. 76 + 77 + ## Feed implementation guidance 78 + - `Feed#get_posts` should return a hash with `posts:` array. 79 + - `display_name` and `description` should return plain strings. 80 + - Keep network calls isolated; prefer small helper methods. 81 + 82 + ## Testing style 83 + - Require `test_helper` at the top of test files. 84 + - Use `refute_nil`, `assert`, `assert_equal`, etc. from Minitest. 85 + - Prefer small, focused tests over large integration cases. 86 + - Use fixture helpers in `test/` if new ones are introduced. 87 + 88 + ## Dependencies 89 + - Add runtime dependencies in `bskypostroulettefeed.gemspec`. 90 + - Add dev/test dependencies in `Gemfile`. 91 + - Prefer adding only what is needed to keep the gem slim. 92 + 93 + ## Documentation updates 94 + - Update `README.md` when public usage or CLI behavior changes. 95 + - Update `CHANGELOG.md` for noteworthy changes. 96 + 97 + ## Git and release notes 98 + - Use `bundle exec rake build` to verify packaging. 99 + - Avoid running `bundle exec rake release` unless instructed. 100 + - Do not update gemspec metadata unless asked. 101 + 102 + ## Editor and agent rules 103 + - No `.cursor/rules/`, `.cursorrules`, or Copilot instructions found. 104 + - If such files are added later, follow them for their scope. 105 + 106 + ## Writing new files 107 + - Match existing folder structure (`lib/`, `test/`, `sig/`). 108 + - Keep file names aligned with module names. 109 + 110 + ## Performance and clarity 111 + - Favor clear, readable Ruby over micro-optimizations. 112 + - Keep methods short and single-purpose. 113 + - Extract helpers when logic grows beyond a few lines. 114 + 115 + ## Security and secrets 116 + - Never commit API keys or tokens. 117 + - Use environment variables or local config files for secrets. 118 + 119 + ## Optional tooling (if needed) 120 + - Use `bundle exec rake -T` to list available rake tasks. 121 + - Use `bundle exec irb -r ./lib/bskypostroulettefeed` for quick REPL. 122 + 123 + ## Quick troubleshooting 124 + - Run `bundle exec rake` if unsure which checks to run. 125 + - If StandardRB fails, fix offenses then re-run. 126 + - If tests fail, run single tests with `-n` for isolation. 127 + 128 + ## Conventions to keep 129 + - Maintain `# frozen_string_literal: true` in Ruby source. 130 + - Keep `require_relative` paths consistent and minimal. 131 + - Keep module nesting aligned with folder structure. 132 + - Avoid monkey-patching global classes unless requested. 133 + 134 + ## Versioning 135 + - Update `lib/bskypostroulettefeed/version.rb` for releases. 136 + - Keep version as a semantic version string. 137 + 138 + ## BlueFactory specifics 139 + - `BlueFactory.add_feed` is configured in `feed/config.rb`. 140 + - `BlueFactory::Server.run!` is used in `bin/dev-feed`. 141 + - Keep feed registration centralized in config. 142 + 143 + ## New tests checklist 144 + - Add tests under `test/` and name files `test_*.rb`. 145 + - Ensure new tests run under `bundle exec rake test`. 146 + 147 + ## Summary for agents 148 + - Use StandardRB and Minitest. 149 + - Use `bundle exec` and update RBS with API changes. 150 + - Ask before running release-related commands.
+5
CHANGELOG.md
··· 1 + ## [Unreleased] 2 + 3 + ## [0.1.0] - 2026-01-17 4 + 5 + - Initial release
+10
CODE_OF_CONDUCT.md
··· 1 + # Code of Conduct 2 + 3 + "bskypostroulettefeed" follows [The Ruby Community Conduct Guideline](https://www.ruby-lang.org/en/conduct) in all "collaborative space", which is defined as community communications channels (such as mailing lists, submitted patches, commit comments, etc.): 4 + 5 + * Participants will be tolerant of opposing views. 6 + * Participants must ensure that their language and actions are free of personal attacks and disparaging personal remarks. 7 + * When interpreting the words and actions of others, participants should always assume good intentions. 8 + * Behaviour which can be reasonably considered harassment will not be tolerated. 9 + 10 + If you have any concerns about behaviour within this project, please contact us at ["me@ansxor.ca"](mailto:"me@ansxor.ca").
+34
Gemfile
··· 1 + # frozen_string_literal: true 2 + 3 + source "https://rubygems.org" 4 + 5 + # Specify your gem's dependencies in bskypostroulettefeed.gemspec 6 + gemspec 7 + 8 + gem "irb" 9 + gem "rake", "~> 13.0" 10 + 11 + gem "minitest", "~> 5.16" 12 + 13 + gem "standard", "~> 1.3" 14 + 15 + gem "dotenv", "~> 3.2.0" 16 + 17 + gem "blue_factory", "~> 0.2.1" 18 + 19 + gem "rackup", "~> 2.3" 20 + gem "puma", "~> 7.1" 21 + 22 + gem "sequel", "~> 5.100" 23 + 24 + gem "pg", "~> 1.6" 25 + 26 + gem "skyfall", "~> 0.6.1" 27 + 28 + gem "redis", "~> 5.4" 29 + 30 + gem "sidekiq", "~> 8.1" 31 + 32 + gem "minisky", "~> 0.5.0" 33 + 34 + gem "byebug", "~> 13.0"
+233
Gemfile.lock
··· 1 + PATH 2 + remote: . 3 + specs: 4 + bskypostroulettefeed (0.1.0) 5 + 6 + GEM 7 + remote: https://rubygems.org/ 8 + specs: 9 + ast (2.4.3) 10 + base32 (0.3.4) 11 + base64 (0.3.0) 12 + bigdecimal (4.0.1) 13 + blue_factory (0.2.1) 14 + sinatra (>= 3.0, < 5.0) 15 + byebug (13.0.0) 16 + reline (>= 0.6.0) 17 + cbor (0.5.10.1) 18 + connection_pool (3.0.2) 19 + date (3.5.1) 20 + dotenv (3.2.0) 21 + erb (6.0.1) 22 + eventmachine (1.2.7) 23 + faye-websocket (0.12.0) 24 + eventmachine (>= 0.12.0) 25 + websocket-driver (>= 0.8.0) 26 + io-console (0.8.2) 27 + irb (1.16.0) 28 + pp (>= 0.6.0) 29 + rdoc (>= 4.0.0) 30 + reline (>= 0.4.2) 31 + json (2.18.0) 32 + language_server-protocol (3.17.0.5) 33 + lint_roller (1.1.0) 34 + logger (1.7.0) 35 + minisky (0.5.0) 36 + base64 (~> 0.1) 37 + minitest (5.27.0) 38 + mustermann (3.0.4) 39 + ruby2_keywords (~> 0.0.1) 40 + nio4r (2.7.5) 41 + parallel (1.27.0) 42 + parser (3.3.10.1) 43 + ast (~> 2.4.1) 44 + racc 45 + pg (1.6.3) 46 + pg (1.6.3-x86_64-linux) 47 + pp (0.6.3) 48 + prettyprint 49 + prettyprint (0.2.0) 50 + prism (1.8.0) 51 + psych (5.3.1) 52 + date 53 + stringio 54 + puma (7.1.0) 55 + nio4r (~> 2.0) 56 + racc (1.8.1) 57 + rack (3.2.4) 58 + rack-protection (4.2.1) 59 + base64 (>= 0.1.0) 60 + logger (>= 1.6.0) 61 + rack (>= 3.0.0, < 4) 62 + rack-session (2.1.1) 63 + base64 (>= 0.1.0) 64 + rack (>= 3.0.0) 65 + rackup (2.3.1) 66 + rack (>= 3) 67 + rainbow (3.1.1) 68 + rake (13.3.1) 69 + rdoc (7.1.0) 70 + erb 71 + psych (>= 4.0.0) 72 + tsort 73 + redis (5.4.1) 74 + redis-client (>= 0.22.0) 75 + redis-client (0.26.3) 76 + connection_pool 77 + regexp_parser (2.11.3) 78 + reline (0.6.3) 79 + io-console (~> 0.5) 80 + rubocop (1.82.1) 81 + json (~> 2.3) 82 + language_server-protocol (~> 3.17.0.2) 83 + lint_roller (~> 1.1.0) 84 + parallel (~> 1.10) 85 + parser (>= 3.3.0.2) 86 + rainbow (>= 2.2.2, < 4.0) 87 + regexp_parser (>= 2.9.3, < 3.0) 88 + rubocop-ast (>= 1.48.0, < 2.0) 89 + ruby-progressbar (~> 1.7) 90 + unicode-display_width (>= 2.4.0, < 4.0) 91 + rubocop-ast (1.49.0) 92 + parser (>= 3.3.7.2) 93 + prism (~> 1.7) 94 + rubocop-performance (1.26.1) 95 + lint_roller (~> 1.1) 96 + rubocop (>= 1.75.0, < 2.0) 97 + rubocop-ast (>= 1.47.1, < 2.0) 98 + ruby-progressbar (1.13.0) 99 + ruby2_keywords (0.0.5) 100 + sequel (5.100.0) 101 + bigdecimal 102 + sidekiq (8.1.0) 103 + connection_pool (>= 3.0.0) 104 + json (>= 2.16.0) 105 + logger (>= 1.7.0) 106 + rack (>= 3.2.0) 107 + redis-client (>= 0.26.0) 108 + sinatra (4.2.1) 109 + logger (>= 1.6.0) 110 + mustermann (~> 3.0) 111 + rack (>= 3.0.0, < 4) 112 + rack-protection (= 4.2.1) 113 + rack-session (>= 2.0.0, < 3) 114 + tilt (~> 2.0) 115 + skyfall (0.6.1) 116 + base32 (~> 0.3, >= 0.3.4) 117 + base64 (~> 0.1) 118 + cbor (~> 0.5, >= 0.5.9.6) 119 + eventmachine (~> 1.2, >= 1.2.7) 120 + faye-websocket (~> 0.12) 121 + standard (1.53.0) 122 + language_server-protocol (~> 3.17.0.2) 123 + lint_roller (~> 1.0) 124 + rubocop (~> 1.82.0) 125 + standard-custom (~> 1.0.0) 126 + standard-performance (~> 1.8) 127 + standard-custom (1.0.2) 128 + lint_roller (~> 1.0) 129 + rubocop (~> 1.50) 130 + standard-performance (1.9.0) 131 + lint_roller (~> 1.1) 132 + rubocop-performance (~> 1.26.0) 133 + stringio (3.2.0) 134 + tilt (2.7.0) 135 + tsort (0.2.0) 136 + unicode-display_width (3.2.0) 137 + unicode-emoji (~> 4.1) 138 + unicode-emoji (4.2.0) 139 + websocket-driver (0.8.0) 140 + base64 141 + websocket-extensions (>= 0.1.0) 142 + websocket-extensions (0.1.5) 143 + 144 + PLATFORMS 145 + ruby 146 + x86_64-linux 147 + 148 + DEPENDENCIES 149 + blue_factory (~> 0.2.1) 150 + bskypostroulettefeed! 151 + byebug (~> 13.0) 152 + dotenv (~> 3.2.0) 153 + irb 154 + minisky (~> 0.5.0) 155 + minitest (~> 5.16) 156 + pg (~> 1.6) 157 + puma (~> 7.1) 158 + rackup (~> 2.3) 159 + rake (~> 13.0) 160 + redis (~> 5.4) 161 + sequel (~> 5.100) 162 + sidekiq (~> 8.1) 163 + skyfall (~> 0.6.1) 164 + standard (~> 1.3) 165 + 166 + CHECKSUMS 167 + ast (2.4.3) sha256=954615157c1d6a382bc27d690d973195e79db7f55e9765ac7c481c60bdb4d383 168 + base32 (0.3.4) sha256=cb9810ab7c79862ed6ead254b3a44fa2535d088396cd412eef38bdc206055aba 169 + base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b 170 + bigdecimal (4.0.1) sha256=8b07d3d065a9f921c80ceaea7c9d4ae596697295b584c296fe599dd0ad01c4a7 171 + blue_factory (0.2.1) sha256=a286aa673fad45b7b5b83fdc145c78341f5fb672aeb0d4c1506f6b3d84acb947 172 + bskypostroulettefeed (0.1.0) 173 + byebug (13.0.0) sha256=d2263efe751941ca520fa29744b71972d39cbc41839496706f5d9b22e92ae05d 174 + cbor (0.5.10.1) sha256=79cdf79f18dcd9ee97e0b849c6d573e5a2e3ddc1954d180f384d6ed2612b6df0 175 + connection_pool (3.0.2) sha256=33fff5ba71a12d2aa26cb72b1db8bba2a1a01823559fb01d29eb74c286e62e0a 176 + date (3.5.1) sha256=750d06384d7b9c15d562c76291407d89e368dda4d4fff957eb94962d325a0dc0 177 + dotenv (3.2.0) sha256=e375b83121ea7ca4ce20f214740076129ab8514cd81378161f11c03853fe619d 178 + erb (6.0.1) sha256=28ecdd99c5472aebd5674d6061e3c6b0a45c049578b071e5a52c2a7f13c197e5 179 + eventmachine (1.2.7) sha256=994016e42aa041477ba9cff45cbe50de2047f25dd418eba003e84f0d16560972 180 + faye-websocket (0.12.0) sha256=ad9f7dfcd0306d0a13baeee450729657661129af15bb5f38716c242484ab42e1 181 + io-console (0.8.2) sha256=d6e3ae7a7cc7574f4b8893b4fca2162e57a825b223a177b7afa236c5ef9814cc 182 + irb (1.16.0) sha256=2abe56c9ac947cdcb2f150572904ba798c1e93c890c256f8429981a7675b0806 183 + json (2.18.0) sha256=b10506aee4183f5cf49e0efc48073d7b75843ce3782c68dbeb763351c08fd505 184 + language_server-protocol (3.17.0.5) sha256=fd1e39a51a28bf3eec959379985a72e296e9f9acfce46f6a79d31ca8760803cc 185 + lint_roller (1.1.0) sha256=2c0c845b632a7d172cb849cc90c1bce937a28c5c8ccccb50dfd46a485003cc87 186 + logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203 187 + minisky (0.5.0) sha256=65859f1279e130346c95bbbb00b8ea669d3eaeac6c94e036a734a9a253e6a225 188 + minitest (5.27.0) sha256=2d3b17f8a36fe7801c1adcffdbc38233b938eb0b4966e97a6739055a45fa77d5 189 + mustermann (3.0.4) sha256=85fadcb6b3c6493a8b511b42426f904b7f27b282835502233dd154daab13aa22 190 + nio4r (2.7.5) sha256=6c90168e48fb5f8e768419c93abb94ba2b892a1d0602cb06eef16d8b7df1dca1 191 + parallel (1.27.0) sha256=4ac151e1806b755fb4e2dc2332cbf0e54f2e24ba821ff2d3dcf86bf6dc4ae130 192 + parser (3.3.10.1) sha256=06f6a725d2cd91e5e7f2b7c32ba143631e1f7c8ae2fb918fc4cebec187e6a688 193 + pg (1.6.3) sha256=1388d0563e13d2758c1089e35e973a3249e955c659592d10e5b77c468f628a99 194 + pg (1.6.3-x86_64-linux) sha256=5d9e188c8f7a0295d162b7b88a768d8452a899977d44f3274d1946d67920ae8d 195 + pp (0.6.3) sha256=2951d514450b93ccfeb1df7d021cae0da16e0a7f95ee1e2273719669d0ab9df6 196 + prettyprint (0.2.0) sha256=2bc9e15581a94742064a3cc8b0fb9d45aae3d03a1baa6ef80922627a0766f193 197 + prism (1.8.0) sha256=84453a16ef5530ea62c5f03ec16b52a459575ad4e7b9c2b360fd8ce2c39c1254 198 + psych (5.3.1) sha256=eb7a57cef10c9d70173ff74e739d843ac3b2c019a003de48447b2963d81b1974 199 + puma (7.1.0) sha256=e45c10cb124f224d448c98db653a75499794edbecadc440ad616cf50f2fd49dd 200 + racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f 201 + rack (3.2.4) sha256=5d74b6f75082a643f43c1e76b419c40f0e5527fcfee1e669ac1e6b73c0ccb6f6 202 + rack-protection (4.2.1) sha256=cf6e2842df8c55f5e4d1a4be015e603e19e9bc3a7178bae58949ccbb58558bac 203 + rack-session (2.1.1) sha256=0b6dc07dea7e4b583f58a48e8b806d4c9f1c6c9214ebc202ec94562cbea2e4e9 204 + rackup (2.3.1) sha256=6c79c26753778e90983761d677a48937ee3192b3ffef6bc963c0950f94688868 205 + rainbow (3.1.1) sha256=039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a 206 + rake (13.3.1) sha256=8c9e89d09f66a26a01264e7e3480ec0607f0c497a861ef16063604b1b08eb19c 207 + rdoc (7.1.0) sha256=494899df0706c178596ca6e1d50f1b7eb285a9b2aae715be5abd742734f17363 208 + redis (5.4.1) sha256=b5e675b57ad22b15c9bcc765d5ac26f60b675408af916d31527af9bd5a81faae 209 + redis-client (0.26.3) sha256=37a95ca193b7a79f350c09fe5e696dc15d1701195d559d031a107ab725effc49 210 + regexp_parser (2.11.3) sha256=ca13f381a173b7a93450e53459075c9b76a10433caadcb2f1180f2c741fc55a4 211 + reline (0.6.3) sha256=1198b04973565b36ec0f11542ab3f5cfeeec34823f4e54cebde90968092b1835 212 + rubocop (1.82.1) sha256=09f1a6a654a960eda767aebea33e47603080f8e9c9a3f019bf9b94c9cab5e273 213 + rubocop-ast (1.49.0) sha256=49c3676d3123a0923d333e20c6c2dbaaae2d2287b475273fddee0c61da9f71fd 214 + rubocop-performance (1.26.1) sha256=cd19b936ff196df85829d264b522fd4f98b6c89ad271fa52744a8c11b8f71834 215 + ruby-progressbar (1.13.0) sha256=80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33 216 + ruby2_keywords (0.0.5) sha256=ffd13740c573b7301cf7a2e61fc857b2a8e3d3aff32545d6f8300d8bae10e3ef 217 + sequel (5.100.0) sha256=cb0329b62287a01db68eead46759c14497a3fae01b174e2c41da108a9e9b4a12 218 + sidekiq (8.1.0) sha256=6bde5eaee9e4d7b1121e97ebd585273627fb32b1f870a47893723572479ad1e4 219 + sinatra (4.2.1) sha256=b7aeb9b11d046b552972ade834f1f9be98b185fa8444480688e3627625377080 220 + skyfall (0.6.1) sha256=6628ce57cb2b3300eadc14dfe138650b920af37c7221ab8e1c852e2809a4dc5f 221 + standard (1.53.0) sha256=f3c9493385db7079d0abce6f7582f553122156997b81258cd361d3480eeacf9c 222 + standard-custom (1.0.2) sha256=424adc84179a074f1a2a309bb9cf7cd6bfdb2b6541f20c6bf9436c0ba22a652b 223 + standard-performance (1.9.0) sha256=49483d31be448292951d80e5e67cdcb576c2502103c7b40aec6f1b6e9c88e3f2 224 + stringio (3.2.0) sha256=c37cb2e58b4ffbd33fe5cd948c05934af997b36e0b6ca6fdf43afa234cf222e1 225 + tilt (2.7.0) sha256=0d5b9ba69f6a36490c64b0eee9f6e9aad517e20dcc848800a06eb116f08c6ab3 226 + tsort (0.2.0) sha256=9650a793f6859a43b6641671278f79cfead60ac714148aabe4e3f0060480089f 227 + unicode-display_width (3.2.0) sha256=0cdd96b5681a5949cdbc2c55e7b420facae74c4aaf9a9815eee1087cb1853c42 228 + unicode-emoji (4.2.0) sha256=519e69150f75652e40bf736106cfbc8f0f73aa3fb6a65afe62fefa7f80b0f80f 229 + websocket-driver (0.8.0) sha256=ed0dba4b943c22f17f9a734817e808bc84cdce6a7e22045f5315aa57676d4962 230 + websocket-extensions (0.1.5) sha256=1c6ba63092cda343eb53fc657110c71c754c56484aad42578495227d717a8241 231 + 232 + BUNDLED WITH 233 + 4.0.3
+43
README.md
··· 1 + # Bskypostroulettefeed 2 + 3 + TODO: Delete this and the text below, and describe your gem 4 + 5 + Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/bskypostroulettefeed`. To experiment with that code, run `bin/console` for an interactive prompt. 6 + 7 + ## Installation 8 + 9 + TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org. 10 + 11 + Install the gem and add to the application's Gemfile by executing: 12 + 13 + ```bash 14 + bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG 15 + ``` 16 + 17 + If bundler is not being used to manage dependencies, install the gem by executing: 18 + 19 + ```bash 20 + gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG 21 + ``` 22 + 23 + ## Usage 24 + 25 + TODO: Write usage instructions here 26 + 27 + ## Development 28 + 29 + After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. 30 + 31 + To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org). 32 + 33 + ## Contributing 34 + 35 + Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/bskypostroulettefeed. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/bskypostroulettefeed/blob/master/CODE_OF_CONDUCT.md). 36 + 37 + ## Code of Conduct 38 + 39 + Everyone interacting in the Bskypostroulettefeed project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/bskypostroulettefeed/blob/master/CODE_OF_CONDUCT.md). 40 + 41 + ## Relevant Libraries 42 + - https://ruby.sdk.blue/blue_factory/ 43 + - https://ruby.sdk.blue/skyfall/
+38
Rakefile
··· 1 + # frozen_string_literal: true 2 + 3 + require "bundler/gem_tasks" 4 + require "dotenv/load" 5 + require "minitest/test_task" 6 + require "sequel" 7 + 8 + Minitest::TestTask.create 9 + 10 + require "blue_factory/rake" 11 + require "standard/rake" 12 + require_relative "lib/feed/config" 13 + require_relative "lib/firehose/firehose" 14 + 15 + namespace :db do 16 + desc "Run Sequel migrations" 17 + task :migrate do 18 + db = nil 19 + database_url = ENV.fetch("DATABASE_URL") 20 + db = Sequel.connect(database_url) 21 + Sequel.extension :migration 22 + Sequel::Migrator.run(db, "db/migrate") 23 + ensure 24 + db&.disconnect 25 + end 26 + end 27 + 28 + namespace :dev do 29 + task :feed do 30 + BlueFactory::Server.run! 31 + end 32 + task :firehose do 33 + firehose = PostRouletteFeed::Firehose.new ENV.fetch("REDIS_URL") 34 + firehose.run 35 + end 36 + end 37 + 38 + task default: %i[test standard]
+11
bin/console
··· 1 + #!/usr/bin/env ruby 2 + # frozen_string_literal: true 3 + 4 + require "bundler/setup" 5 + require "bskypostroulettefeed" 6 + 7 + # You can add fixtures and/or initialization code here to make experimenting 8 + # with your gem easier. You can also use a different console, if you like. 9 + 10 + require "irb" 11 + IRB.start(__FILE__)
+8
bin/setup
··· 1 + #!/usr/bin/env bash 2 + set -euo pipefail 3 + IFS=$'\n\t' 4 + set -vx 5 + 6 + bundle install 7 + 8 + # Do any other automated setup that you need to do here
+39
bskypostroulettefeed.gemspec
··· 1 + # frozen_string_literal: true 2 + 3 + require_relative "lib/bskypostroulettefeed/version" 4 + 5 + Gem::Specification.new do |spec| 6 + spec.name = "bskypostroulettefeed" 7 + spec.version = Bskypostroulettefeed::VERSION 8 + spec.authors = ["ansxor"] 9 + spec.email = ["me@ansxor.ca"] 10 + 11 + spec.summary = "TODO: Write a short summary, because RubyGems requires one." 12 + spec.description = "TODO: Write a longer description or delete this line." 13 + spec.homepage = "TODO: Put your gem's website or public repo URL here." 14 + spec.required_ruby_version = ">= 3.2.0" 15 + 16 + spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'" 17 + spec.metadata["homepage_uri"] = spec.homepage 18 + spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here." 19 + spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here." 20 + 21 + # Specify which files should be added to the gem when it is released. 22 + # The `git ls-files -z` loads the files in the RubyGem that have been added into git. 23 + gemspec = File.basename(__FILE__) 24 + spec.files = IO.popen(%w[git ls-files -z], chdir: __dir__, err: IO::NULL) do |ls| 25 + ls.readlines("\x0", chomp: true).reject do |f| 26 + (f == gemspec) || 27 + f.start_with?(*%w[bin/ Gemfile .gitignore test/ .github/ .standard.yml]) 28 + end 29 + end 30 + spec.bindir = "exe" 31 + spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) } 32 + spec.require_paths = ["lib"] 33 + 34 + # Uncomment to register a new dependency of your gem 35 + # spec.add_dependency "example-gem", "~> 1.0" 36 + 37 + # For more information and examples about making a new gem, check out our 38 + # guide at: https://bundler.io/guides/creating_gem.html 39 + end
+34
db/migrate/001_create_sample_records.rb
··· 1 + # frozen_string_literal: true 2 + 3 + Sequel.migration do 4 + change do 5 + extension :pg_enum 6 + 7 + create_enum(:backfill_status_enum, %w[unwatched queued backfilling active failed]) 8 + 9 + create_table(:users) do 10 + primary_key :id 11 + String :did, null: false 12 + backfill_status_enum :backfill_status, null: false, default: 'unwatched' 13 + Boolean :is_feed_subscriber, null: false, default: false 14 + 15 + index :backfill_status 16 + index :is_feed_subscriber 17 + end 18 + 19 + create_join_table({follower_id: :users, followed_id: :users}, options: { name: 'user_relationships' }) do 20 + index %i[follower_id followed_id], unique: true 21 + index :followed_id 22 + end 23 + 24 + create_table(:posts) do 25 + primary_key :id 26 + String :url, null: false 27 + foreign_key :user_id, :users, null: false 28 + Float :random_key, null: false 29 + 30 + index :user_id 31 + index :random_key 32 + end 33 + end 34 + end
+21
docker-compose.yml
··· 1 + version: "3.9" 2 + 3 + services: 4 + postgres: 5 + image: postgres:18.1 6 + environment: 7 + POSTGRES_USER: bsky 8 + POSTGRES_PASSWORD: bsky 9 + POSTGRES_DB: bskypostroulettefeed_dev 10 + ports: 11 + - "5432:5432" 12 + volumes: 13 + - .postgres_data:/var/lib/postgresql 14 + 15 + valkey: 16 + image: valkey/valkey:9.0 17 + ports: 18 + - "6379:6379" 19 + volumes: 20 + - .valkey_data:/data 21 +
+8
lib/bskypostroulettefeed.rb
··· 1 + # frozen_string_literal: true 2 + 3 + require_relative "bskypostroulettefeed/version" 4 + 5 + module Bskypostroulettefeed 6 + class Error < StandardError; end 7 + # Your code goes here... 8 + end
+5
lib/bskypostroulettefeed/version.rb
··· 1 + # frozen_string_literal: true 2 + 3 + module Bskypostroulettefeed 4 + VERSION = "0.1.0" 5 + end
+7
lib/feed/config.rb
··· 1 + require 'blue_factory' 2 + require_relative "feed" 3 + 4 + BlueFactory.set :publisher_did, ENV.fetch("FEED_PUBLISHER_DID") 5 + BlueFactory.set :hostname, ENV.fetch("FEED_HOSTNAME") 6 + 7 + BlueFactory.add_feed "postroulette", PostRouletteFeed::Feed.new
+16
lib/feed/feed.rb
··· 1 + module PostRouletteFeed 2 + class Feed 3 + def get_posts(params, context) 4 + p context.user 5 + { posts: ["at://did:plc:brka7yc4gssxdquiwpii22pr/app.bsky.feed.post/3mckyk6xwhc2y"] } 6 + end 7 + 8 + def display_name 9 + "Post Roulette" 10 + end 11 + 12 + def description 13 + "This is my testing feed for now" 14 + end 15 + end 16 + end
+23
lib/firehose/firehose.rb
··· 1 + require 'skyfall' 2 + require 'redis' 3 + 4 + module PostRouletteFeed 5 + class Firehose 6 + def initialize redis_url 7 + @sky = Skyfall::Firehose.new("bsky.network", :subscribe_repos) 8 + @redis_url = redis_url 9 + end 10 + 11 + def run 12 + redis = Redis.new(url: @redis_url) 13 + 14 + @sky.on_message do |msg| 15 + if redis.exists? "watching:#{msg.did}" 16 + p "watching", msg 17 + end 18 + end 19 + @sky.connect 20 + end 21 + end 22 + end 23 +
+26
lib/workers/followgraphseeder.rb
··· 1 + require 'sidekiq' 2 + require 'minisky' 3 + 4 + module PostRouletteFeed 5 + class FollowGraphSeeder 6 + include Sidekiq::Worker 7 + 8 + def perform(did) 9 + atproto = Minisky.new('public.api.bsky.app', nil) 10 + 11 + dids = [] 12 + cursor = nil 13 + 14 + while true do 15 + json = atproto.get_request('app.bsky.graph.getFollows', { 16 + actor: did, 17 + limit: 100, 18 + cursor: cursor 19 + }) 20 + cursor = json["cursor"] 21 + break if cursor.nil? 22 + end 23 + p "done" 24 + end 25 + end 26 + end
+4
sig/bskypostroulettefeed.rbs
··· 1 + module Bskypostroulettefeed 2 + VERSION: String 3 + # See the writing guide of rbs: https://github.com/ruby/rbs#guides 4 + end
+6
test/test_helper.rb
··· 1 + # frozen_string_literal: true 2 + 3 + $LOAD_PATH.unshift File.expand_path("../lib", __dir__) 4 + require "bskypostroulettefeed" 5 + 6 + require "minitest/autorun"
+11
test/test_workers_followgraphseeder.rb
··· 1 + # frozen_string_literal: true 2 + 3 + require "test_helper" 4 + require_relative "../lib/workers/followgraphseeder" 5 + 6 + class TestWorkersFollowGraphSeeder < Minitest::Test 7 + def test_that_it_has_a_version_number 8 + worker = PostRouletteFeed::FollowGraphSeeder.new 9 + worker.perform("did:plc:brka7yc4gssxdquiwpii22pr") 10 + end 11 + end