From 4b490dd07da28d79e935695e0e5f907fd2058d1c Mon Sep 17 00:00:00 2001 From: Jon Allured Date: Sun, 3 Nov 2024 16:21:23 -0600 Subject: [PATCH] Add Feedbin stats section to daily packet --- app/clients/feedbin_api.rb | 35 +++++++++++++++++++ app/models/daily_packet.rb | 10 ++++++ app/models/daily_packet/builder.rb | 3 ++ app/models/daily_packet/pdf_view.rb | 12 ++++--- app/models/feedbin_stats.rb | 10 ++++++ config/credentials.yml.enc | 2 +- ...4523_add_feedbin_stats_to_daily_packets.rb | 6 ++++ spec/factories/daily_packet.rb | 2 ++ spec/models/daily_packet/builder_spec.rb | 1 + spec/models/daily_packet/pdf_view_spec.rb | 5 ++- spec/models/daily_packet/producer_spec.rb | 4 +++ 11 files changed, 84 insertions(+), 6 deletions(-) create mode 100644 app/clients/feedbin_api.rb create mode 100644 app/models/feedbin_stats.rb create mode 100644 db/migrate/20241103214523_add_feedbin_stats_to_daily_packets.rb diff --git a/app/clients/feedbin_api.rb b/app/clients/feedbin_api.rb new file mode 100644 index 0000000..55cdc18 --- /dev/null +++ b/app/clients/feedbin_api.rb @@ -0,0 +1,35 @@ +class FeedbinApi + def self.generate_client + endpoint_url = Monolithium.config.feedbin_endpoint_url + password = Monolithium.config.feedbin_password + username = Monolithium.config.feedbin_username + return unless endpoint_url && password && username + + Faraday.new(url: endpoint_url) do |f| + f.adapter Faraday.default_adapter + f.request :authorization, :basic, username, password + f.request :json + f.response :json + end + end + + def self.client + @client ||= generate_client + end + + def self.get_unread_entries + return unless client + + url = "/v2/unread_entries.json" + response = client.get(url) + response.body + end + + def self.get_entry(entry_id) + return unless client + + url = "/v2/entries/#{entry_id}.json" + response = client.get(url) + response.body + end +end diff --git a/app/models/daily_packet.rb b/app/models/daily_packet.rb index fbff02c..e36f993 100644 --- a/app/models/daily_packet.rb +++ b/app/models/daily_packet.rb @@ -7,12 +7,22 @@ class DailyPacket < ApplicationRecord delegate :save_to_disk, :save_to_s3, to: :producer validates :built_on, presence: true + validates :feedbin_oldest_ago, presence: true + validates :feedbin_unread_count, presence: true validates :reading_list_pace, presence: true def built_on_phrase "#{built_on.to_fs}, week #{built_on.cweek}" end + def feedbin_oldest_phrase + "oldest: #{feedbin_oldest_ago} days ago" + end + + def feedbin_unread_phrase + "unread: #{feedbin_unread_count}" + end + def reading_list_phrase "#{reading_list_pace} pages/day" end diff --git a/app/models/daily_packet/builder.rb b/app/models/daily_packet/builder.rb index 70f16de..30e1cb7 100644 --- a/app/models/daily_packet/builder.rb +++ b/app/models/daily_packet/builder.rb @@ -3,10 +3,13 @@ def self.find_or_build_for(built_on) daily_packet = DailyPacket.find_or_initialize_by(built_on: built_on) return daily_packet if daily_packet.persisted? + feedbin_unread_count, feedbin_oldest_ago = FeedbinStats.compute reading_list = ReadingList.new warm_fuzzy = WarmFuzzy.random attributes = { + feedbin_oldest_ago: feedbin_oldest_ago, + feedbin_unread_count: feedbin_unread_count, reading_list_pace: reading_list.pace, warm_fuzzy: warm_fuzzy } diff --git a/app/models/daily_packet/pdf_view.rb b/app/models/daily_packet/pdf_view.rb index 88d5b34..aa90d17 100644 --- a/app/models/daily_packet/pdf_view.rb +++ b/app/models/daily_packet/pdf_view.rb @@ -44,10 +44,14 @@ def draw_front_page move_down 20 - font_size(20) do - text "Reading Pace", style: :bold - text daily_packet.reading_list_phrase - end + text "Reading Pace", style: :bold, size: 20 + text daily_packet.reading_list_phrase, size: 16 + + move_down 20 + + text "Feedbin Stats", style: :bold, size: 20 + text daily_packet.feedbin_unread_phrase, size: 16 + text daily_packet.feedbin_oldest_phrase, size: 16 end end diff --git a/app/models/feedbin_stats.rb b/app/models/feedbin_stats.rb new file mode 100644 index 0000000..caaffc7 --- /dev/null +++ b/app/models/feedbin_stats.rb @@ -0,0 +1,10 @@ +class FeedbinStats + def self.compute + unread_entry_ids = FeedbinApi.get_unread_entries + first_entry_id = unread_entry_ids.min + oldest_entry = FeedbinApi.get_entry(first_entry_id) + oldest_published_on = Date.parse(oldest_entry["published"]) + oldest_ago = (Date.today - oldest_published_on).to_i + [unread_entry_ids.count, oldest_ago] + end +end diff --git a/config/credentials.yml.enc b/config/credentials.yml.enc index 1bf42f7..1d1d66c 100644 --- a/config/credentials.yml.enc +++ b/config/credentials.yml.enc @@ -1 +1 @@ -pHjuU/ByM1jPqsmRZwCRgBfT5j7qznqc4t2j3zY+BzyKmQvWW+X09UNnlQXE0eJJ30g7KmMeTJ6pV7JibA7e2+CzYs+0ip3qnTyOkGNcdIom+V//vf5PoKk1KZ7UoxfV7sslSCOXnlDbjNfYhWYxT8OgHOQhQc/Z2jxeMasogzyxGi8kV4IcQpAH+QXmlqi3QjIsO4K1li2wCClaEQnZBHWSoy2Vz+1AZYo+Ug3LiGia4QRlpXUlJCNdit1rmoAIMfTZmVjsmu86N8PKMlu6zkhy/xOzyLDFglUW2Fy/ydL27JpwR9pAPN+ArkG+EF112m0NShhc9rQof1bvb8HlclxOFmwB0puAJJS/x6YfS9DORhE8h1jRu2ytP4C/gjTpYyPVFnaDp72UUnwkXD9ymIRTSok9pYGfvhqiRYURkMaRCWAcMDiaLfXpbaGMrJRAGL+5ZpSPmPCk1PQsD2PFSJHTOjzshrt3Zb0r/PYJrZ93BQczuMKv/9qU20KpdCQKOT/sGzOvUTD529uK/kiG472at4mFyE7YnwBOe3Xu3XPxf/DjxASiyWFRf+X6swsPX154KuueCVLssPaXS+ZCWB4WITWC9tP/VFwiQiycW/ma/Kds94urbg2z8EHmJ8nimhbvcXAQoxPsqCvWcRIUuQ6cMnRh/KJX8f79d5rHzmmqHCzQRUJOi+1rys2jVATOhwHNgdULc1j+nC101In1mzwH90HApLGiIfJr9+SqAWT/6QlQMhMPM5ahNS+E+k30LfxQan5moe6reMWbrBvcEm5EmOJaaoKsr6TT6loDKZlf2uJIjAsr0qv8s63RGUayoTjKqjO+EzwGp08gMr5ToKeDGF6j9ZngulsQwlQkeqlhcl1Z2941zf8+F1paNIU+grPpUUn+wIWMs5Dlec18pTJQYYmsHZNz0VDoGdPTnOVvS3u37D3ZtBoIqVol4ygp1mM79RJLKTQ2t9ikr6gEFK8abYNDZlcH8JRD7I4QBrddLA2m+zgVedmGN58RI68Ib4LbOKI+QKf8Zx3GHW6oIBlVTP5R8A5nd7AgnLqv+7DBaTwEn2z6GjeGjxS+7lG4w3CO+mrYnJz+7A3WRFLpOReBm1jeBQV4Idfn3isV9NPYJ2lztGtUusqKJ7M2yV3vPFTCAZehgna0IaunZNiitzPLNEMwWDL/1AIBIuPe1Sc6lEQomWXAjYnTaoJr5sFiMBsaEyzmG5402dA35+hdAJFx74rGTEJZ634iTTOL+okDUXuAQbfT+CyYCQO3SGDOb45un3LjQlo7l98aagyBAZlEEfBh75sdj6z7wazdYAS5Lvycq/ZpywaaTiFbD99oqofzvu5xUr/+XRH1EnjPGz7MZUU+bwFLz/+bSPySCfFrdo3Kbg28sOt+ZQXKteV3NZUUnw12Q7W7sZmVkA27QVXq+j6ssE6Q8avZxixtIXmzbV0+ZL0Hc5dhUEM+OoUG467Nr+zOCYlXuJpSW5ZLPYM852iq4gFyOzvmb8AiIbhH7manUK8wZRIjeryHodyxI8303xNoDqMhijau2ih6yDKQ2Vm+iVsnZXFsfYabIW8w/lLQaJsffpw8fJmRN+HOFMGZta2IAlqDpZtz9thvPnwdyhih1zF6e3uV+wQzNt4cQ3ajNIX8qN/0zExu7523psTO0lmOHhgybK+Qw72mEKRV4xB37OwKFEnkgDLLGsYdvRtSTDTY+xLQ+AezXYQ6a7mIjydhOHubfCgpPpciHdkNY73xDKLlSITYBouCjnZC5FymLEdLpbPjHNQCfywXzW+Sn2gIi6brx7sTVljz+JoIdlaAuINvw366GS8fADCzmLEWHmmSuXvJk7lEXThrETtjaikvCC9VnejsaexevSwywIv5wRPsB4tqUQ==--oeeW2+dsjrOVfq5H--zD562qzntgI0DMqq7Ey6SA== \ No newline at end of file +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--D5xacH6f7UnVOulj--5Z5Jka+gZTCWSlUZS1g3ig== \ No newline at end of file diff --git a/db/migrate/20241103214523_add_feedbin_stats_to_daily_packets.rb b/db/migrate/20241103214523_add_feedbin_stats_to_daily_packets.rb new file mode 100644 index 0000000..7b072de --- /dev/null +++ b/db/migrate/20241103214523_add_feedbin_stats_to_daily_packets.rb @@ -0,0 +1,6 @@ +class AddFeedbinStatsToDailyPackets < ActiveRecord::Migration[7.2] + def change + add_column :daily_packets, :feedbin_unread_count, :integer, null: false, default: 0 + add_column :daily_packets, :feedbin_oldest_ago, :integer, null: false, default: 0 + end +end diff --git a/spec/factories/daily_packet.rb b/spec/factories/daily_packet.rb index a15c170..5fb8628 100644 --- a/spec/factories/daily_packet.rb +++ b/spec/factories/daily_packet.rb @@ -1,6 +1,8 @@ FactoryBot.define do factory :daily_packet do built_on { Date.parse("2007-07-07") } + feedbin_oldest_ago { 14 } + feedbin_unread_count { 9 } reading_list_pace { 7.7 } warm_fuzzy end diff --git a/spec/models/daily_packet/builder_spec.rb b/spec/models/daily_packet/builder_spec.rb index b610b28..68581ed 100644 --- a/spec/models/daily_packet/builder_spec.rb +++ b/spec/models/daily_packet/builder_spec.rb @@ -15,6 +15,7 @@ context "without an existing DailyPacket record" do it "creates and returns a new record" do + expect(FeedbinStats).to receive(:compute).and_return([0, 0]) FactoryBot.create(:warm_fuzzy) expect do diff --git a/spec/models/daily_packet/pdf_view_spec.rb b/spec/models/daily_packet/pdf_view_spec.rb index ac2ecb0..01a94f1 100644 --- a/spec/models/daily_packet/pdf_view_spec.rb +++ b/spec/models/daily_packet/pdf_view_spec.rb @@ -19,7 +19,10 @@ "Your haircut is adequate.", "- Wife, 01/01/1970 12:00:00am", "Reading Pace", - "7.7 pages/day" + "7.7 pages/day", + "Feedbin Stats", + "unread: 9", + "oldest: 14 days ago" ]) expect(page_two_strings).to eq([ diff --git a/spec/models/daily_packet/producer_spec.rb b/spec/models/daily_packet/producer_spec.rb index f7e40b7..b10760c 100644 --- a/spec/models/daily_packet/producer_spec.rb +++ b/spec/models/daily_packet/producer_spec.rb @@ -2,6 +2,10 @@ describe DailyPacket::Producer do describe ".save_to" do + before do + allow(FeedbinStats).to receive(:compute).and_return([0, 0]) + end + context "with an invalid target" do it "raises an ArgumentError" do expect do