mail based rss feed aggregator
2
fork

Configure Feed

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

update to the current version of my gcourier fork (post consolidation & message builder rework)

ollie 48fa5bfc 2ca0ef0f

+43 -43
+1
gleam.toml
··· 16 16 gleam_stdlib = ">= 0.44.0 and < 2.0.0" 17 17 parsed_it = ">= 0.1.1 and < 1.0.0" 18 18 gcourier = { git = "git@github.com:nnuuvv/gcourier.git", ref="main" } 19 + # gcourier = { path = "../gcourier/" } 19 20 envoy = ">= 1.1.0 and < 2.0.0" 20 21 lustre = ">= 5.6.0 and < 6.0.0" 21 22 gleam_erlang = ">= 1.3.0 and < 2.0.0"
+1 -11
manifest.toml
··· 3 3 4 4 packages = [ 5 5 { name = "argv", version = "1.0.2", build_tools = ["gleam"], requirements = [], otp_app = "argv", source = "hex", outer_checksum = "BA1FF0929525DEBA1CE67256E5ADF77A7CDDFE729E3E3F57A5BDCAA031DED09D" }, 6 - { name = "certifi", version = "2.15.0", build_tools = ["rebar3"], requirements = [], otp_app = "certifi", source = "hex", outer_checksum = "B147ED22CE71D72EAFDAD94F055165C1C182F61A2FF49DF28BCC71D1D5B94A60" }, 7 6 { name = "compresso", version = "0.1.0", build_tools = ["gleam"], requirements = ["exception", "gleam_erlang", "gleam_stdlib", "gleam_yielder", "logging"], otp_app = "compresso", source = "hex", outer_checksum = "8BE29A1EDA42F70826ED148EAE40C46BB3FC18E78FE472663DB01DD4A38172D4" }, 8 7 { name = "envoy", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "envoy", source = "hex", outer_checksum = "850DA9D29D2E5987735872A2B5C81035146D7FE19EFC486129E44440D03FD832" }, 9 8 { name = "esqlite", version = "0.9.0", build_tools = ["rebar3"], requirements = [], otp_app = "esqlite", source = "hex", outer_checksum = "CCF72258A4EE152EC7AD92AA9A03552EB6CA1B06B65C93AD5B6E55C302E05855" }, ··· 11 10 { name = "exception", version = "2.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "exception", source = "hex", outer_checksum = "329D269D5C2A314F7364BD2711372B6F2C58FA6F39981572E5CA68624D291F8C" }, 12 11 { name = "filepath", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "B06A9AF0BF10E51401D64B98E4B627F1D2E48C154967DA7AF4D0914780A6D40A" }, 13 12 { name = "formal", version = "3.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib", "gleam_time"], otp_app = "formal", source = "hex", outer_checksum = "8FBEB42758F90ACAA82A8B6B8FE11B4A3B2A2B290E97B4DDD4B7DCE98DEB885C" }, 14 - { name = "gcourier", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_hackney", "gleam_http", "gleam_stdlib", "gleam_time", "shellout", "simplifile", "youid"], source = "git", repo = "git@github.com:nnuuvv/gcourier.git", commit = "0c9e91e30bb97beebef18dd344deb3457a6f4edd" }, 13 + { name = "gcourier", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib", "gleam_time", "youid"], source = "git", repo = "git@github.com:nnuuvv/gcourier.git", commit = "504d59f21553afbc63c3d4505ad70dac09aa25f2" }, 15 14 { name = "glaze_oat", version = "3.0.0", build_tools = ["gleam"], requirements = ["gleam_json", "gleam_stdlib", "lustre"], otp_app = "glaze_oat", source = "hex", outer_checksum = "B1373CA720EBB9D7FBDA4D2E28CAAD2B1928F6845313570AE72CA1D93B069706" }, 16 15 { name = "gleam_crypto", version = "1.5.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_crypto", source = "hex", outer_checksum = "50774BAFFF1144E7872814C566C5D653D83A3EBF23ACC3156B757A1B6819086E" }, 17 16 { name = "gleam_erlang", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "1124AD3AA21143E5AF0FC5CF3D9529F6DB8CA03E43A55711B60B6B7B3874375C" }, 18 - { name = "gleam_hackney", version = "1.3.3", build_tools = ["gleam"], requirements = ["gleam_http", "gleam_stdlib", "hackney"], otp_app = "gleam_hackney", source = "hex", outer_checksum = "03B4125E5E6DFD6BC20CC1FAD0D35B8474D9515DFDFFB69255EFE6D7B49BEB07" }, 19 17 { name = "gleam_http", version = "4.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "82EA6A717C842456188C190AFB372665EA56CE13D8559BF3B1DD9E40F619EE0C" }, 20 18 { name = "gleam_httpc", version = "5.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_http", "gleam_stdlib"], otp_app = "gleam_httpc", source = "hex", outer_checksum = "C545172618D07811494E97AAA4A0FB34DA6F6D0061FDC8041C2F8E3BE2B2E48F" }, 21 19 { name = "gleam_json", version = "3.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "44FDAA8847BE8FC48CA7A1C089706BD54BADCC4C45B237A992EDDF9F2CDB2836" }, ··· 27 25 { name = "gleeunit", version = "1.9.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "DA9553CE58B67924B3C631F96FE3370C49EB6D6DC6B384EC4862CC4AAA718F3C" }, 28 26 { name = "glisten", version = "9.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_otp", "gleam_stdlib", "logging"], otp_app = "glisten", source = "hex", outer_checksum = "D92808C66F7D3F22F2289CD04CBA8151757AAE9CB3D86992F0C6DE32A41205E1" }, 29 27 { name = "group_registry", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_otp", "gleam_stdlib"], otp_app = "group_registry", source = "hex", outer_checksum = "BC798A53D6F2406DB94E27CB45C57052CB56B32ACF7CC16EA20F6BAEC7E36B90" }, 30 - { name = "hackney", version = "1.25.0", build_tools = ["rebar3"], requirements = ["certifi", "idna", "metrics", "mimerl", "parse_trans", "ssl_verify_fun", "unicode_util_compat"], otp_app = "hackney", source = "hex", outer_checksum = "7209BFD75FD1F42467211FF8F59EA74D6F2A9E81CBCEE95A56711EE79FD6B1D4" }, 31 28 { name = "houdini", version = "1.2.0", build_tools = ["gleam"], requirements = [], otp_app = "houdini", source = "hex", outer_checksum = "5DB1053F1AF828049C2B206D4403C18970ABEF5C18671CA3C2D2ED0DD64F6385" }, 32 - { name = "idna", version = "6.1.1", build_tools = ["rebar3"], requirements = ["unicode_util_compat"], otp_app = "idna", source = "hex", outer_checksum = "92376EB7894412ED19AC475E4A86F7B413C1B9FBB5BD16DCCD57934157944CEA" }, 33 29 { name = "logging", version = "1.5.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "logging", source = "hex", outer_checksum = "BC5F18CE5DD9686100229FE5409BDC3DD5C46D5A7DF2F804AD2D8F0DD6C5060E" }, 34 30 { name = "lustre", version = "5.6.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_json", "gleam_otp", "gleam_stdlib", "houdini"], otp_app = "lustre", source = "hex", outer_checksum = "EE558CD4DB9F09FCC16417ADF0183A3C2DAC3E4B21ED3AC0CAE859792AB810CA" }, 35 31 { name = "lustre_portal", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib", "lustre"], otp_app = "lustre_portal", source = "hex", outer_checksum = "7531667B9321B644E139F5BE42077932829431BE74BC7239471CEFC68943A661" }, 36 - { name = "metrics", version = "1.0.1", build_tools = ["rebar3"], requirements = [], otp_app = "metrics", source = "hex", outer_checksum = "69B09ADDDC4F74A40716AE54D140F93BEB0FB8978D8636EADED0C31B6F099F16" }, 37 - { name = "mimerl", version = "1.5.0", build_tools = ["rebar3"], requirements = [], otp_app = "mimerl", source = "hex", outer_checksum = "DB648CE065BAE14EA84CA8B5DD123F42F49417CEF693541110BF6F9E9BE9ECC4" }, 38 32 { name = "parrot", version = "2.2.1", build_tools = ["gleam"], requirements = ["argv", "envoy", "filepath", "gleam_crypto", "gleam_httpc", "gleam_json", "gleam_stdlib", "gleam_time", "glearray", "repeatedly", "simplifile", "tom"], otp_app = "parrot", source = "hex", outer_checksum = "BD114893BFA9564D8F3109AB388EC4BA162E8429A4DE689AF7C5624FF010CBEF" }, 39 - { name = "parse_trans", version = "3.4.1", build_tools = ["rebar3"], requirements = [], otp_app = "parse_trans", source = "hex", outer_checksum = "620A406CE75DADA827B82E453C19CF06776BE266F5A67CFF34E1EF2CBB60E49A" }, 40 33 { name = "parsed_it", version = "0.1.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "parsed_it", source = "hex", outer_checksum = "9F8BA3C634FEA847AD195E3322FD1DA51980F57C4171B02DCF069C6FC807944A" }, 41 34 { name = "repeatedly", version = "2.1.2", build_tools = ["gleam"], requirements = [], otp_app = "repeatedly", source = "hex", outer_checksum = "93AE1938DDE0DC0F7034F32C1BF0D4E89ACEBA82198A1FE21F604E849DA5F589" }, 42 - { name = "shellout", version = "1.8.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "shellout", source = "hex", outer_checksum = "C416356D45151F298108C9DB9CD1EDE0313F620B5EDBB5766CD7237659D87841" }, 43 35 { name = "simplifile", version = "2.4.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "7C18AFA4FED0B4CE1FA5B0B4BAC1FA1744427054EA993565F6F3F82E5453170D" }, 44 36 { name = "sqlight", version = "1.0.3", build_tools = ["gleam"], requirements = ["esqlite", "gleam_stdlib"], otp_app = "sqlight", source = "hex", outer_checksum = "CADD79663C9B61D4BAC960A47CC2D42CA8F48EAF5804DBEB79977287750F4B16" }, 45 - { name = "ssl_verify_fun", version = "1.1.7", build_tools = ["mix", "rebar3", "make"], requirements = [], otp_app = "ssl_verify_fun", source = "hex", outer_checksum = "FE4C190E8F37401D30167C8C405EDA19469F34577987C76DDE613E838BBC67F8" }, 46 37 { name = "tom", version = "2.0.2", build_tools = ["gleam"], requirements = ["gleam_stdlib", "gleam_time"], otp_app = "tom", source = "hex", outer_checksum = "234A842F3D087D35737483F5DFB6DE9839E3366EF0CAF8726D2D094210227670" }, 47 - { name = "unicode_util_compat", version = "0.7.1", build_tools = ["rebar3"], requirements = [], otp_app = "unicode_util_compat", source = "hex", outer_checksum = "B3A917854CE3AE233619744AD1E0102E05673136776FB2FA76234F3E03B23642" }, 48 38 { name = "websocks", version = "3.0.1", build_tools = ["gleam"], requirements = ["gleam_crypto", "gleam_erlang", "gleam_stdlib"], otp_app = "websocks", source = "hex", outer_checksum = "C70340E5B6C3390383ADA17029DCA6F8903863A7AD8CD8E1520EDCC4FE70D6FD" }, 49 39 { name = "woof", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "woof", source = "hex", outer_checksum = "A5DC2FCB04F23B0F440978885A167A91450B88F7760B969127187C57E05D489C" }, 50 40 { name = "youid", version = "1.6.0", build_tools = ["gleam"], requirements = ["gleam_crypto", "gleam_stdlib", "gleam_time"], otp_app = "youid", source = "hex", outer_checksum = "7A3ABA44B1B38BC2BDCB5474C5317AA372BE58DFBC649815EE08B03526DDA18D" },
+7 -4
src/eater/sender.gleam
··· 21 21 import eater/pubsub 22 22 import eater/smtp 23 23 import eater/user 24 - import gcourier/smtp as gsmtp 24 + import gcourier 25 25 import gleam/bool 26 26 import gleam/dict 27 27 import gleam/erlang/process ··· 548 548 549 549 type FeedUpdateError { 550 550 FailedToCheckSentStatus(sqlight.Error) 551 - FailedToSendEmail(gsmtp.Error) 551 + FailedToSendEmail(gcourier.Error) 552 552 FailedToPersistSending(sqlight.Error) 553 553 AlreadySent 554 554 } ··· 593 593 Ok(Nil) 594 594 } 595 595 596 - fn send_email(state: State, update: rss.FeedUpdate) -> Result(Nil, gsmtp.Error) { 597 - smtp.feed_update_to_email(update, state.user) 596 + fn send_email( 597 + state: State, 598 + update: rss.FeedUpdate, 599 + ) -> Result(Nil, gcourier.Error) { 600 + smtp.feed_update_to_email(state.smtp_environment, update, state.user) 598 601 |> smtp.send_message(state.smtp_environment) 599 602 }
+27 -25
src/eater/smtp.gleam
··· 19 19 import eater/feed/rss 20 20 import eater/user 21 21 import envoy 22 - import gcourier/message 23 - import gcourier/smtp 22 + import gcourier 24 23 import gleam/int 25 24 import gleam/option.{type Option} 26 25 import gleam/result ··· 31 30 /// takes a `message` and sends it using the configured sender from the supplied `environment` 32 31 /// 33 32 pub fn send_message( 34 - message: message.Message, 33 + message: gcourier.Message, 35 34 environment: SmtpEnvironment, 36 - ) -> Result(Nil, smtp.Error) { 37 - smtp.send( 35 + ) -> Result(Nil, gcourier.Error) { 36 + gcourier.send( 38 37 environment.host, 39 38 environment.port, 40 39 option.Some(#(environment.username, environment.password)), 41 - message 42 - |> message.set_from( 43 - sender_email(environment), 44 - sender_name: environment.sender_name 45 - |> option.unwrap("ollies RSS aggregator") 46 - |> option.Some, 47 - ), 40 + message, 48 41 ) 49 42 } 50 43 51 44 /// turn a feed item into an email ready to be sent using `smtp.send_message` 52 45 /// 53 46 pub fn feed_update_to_email( 47 + environment: SmtpEnvironment, 54 48 update: rss.FeedUpdate, 55 49 user: user.User, 56 - ) -> message.Message { 57 - message.build() 58 - |> message.set_subject(update.channel.title <> ": " <> update.new.title) 59 - |> message.add_recipient(user.email, message.To) 60 - |> message.set_html( 50 + ) -> gcourier.Message { 51 + gcourier.new_message(sender(environment)) 52 + |> gcourier.set_subject(update.channel.title <> ": " <> update.new.title) 53 + |> gcourier.add_recipient(gcourier.To(user.email)) 54 + |> gcourier.set_content(gcourier.Html( 61 55 html.html([], [ 62 56 html.body([], [ 63 57 html.h1([], [html.text(update.new.title)]), ··· 70 64 ]), 71 65 ]) 72 66 |> element.to_readable_string, 73 - ) 67 + )) 74 68 } 75 69 76 70 /// generate the `one time password` email 77 71 /// 78 72 pub fn one_time_password( 73 + environment: SmtpEnvironment, 79 74 email email: String, 80 75 one_time_password one_time_password: String, 81 - ) -> message.Message { 82 - message.build() 83 - |> message.set_subject("Your one time password") 84 - |> message.add_recipient(email, message.To) 85 - |> message.set_html( 76 + ) -> gcourier.Message { 77 + gcourier.new_message(sender(environment)) 78 + |> gcourier.set_subject("Your one time password") 79 + |> gcourier.add_recipient(gcourier.To(email)) 80 + |> gcourier.set_content(gcourier.Html( 86 81 html.html([], [ 87 82 html.body([], [ 88 83 html.h1([], [html.text("Your one time password")]), ··· 90 85 ]), 91 86 ]) 92 87 |> element.to_readable_string, 93 - ) 88 + )) 94 89 } 95 90 96 91 // environment ------------------------------------------------------------------ ··· 108 103 109 104 /// get the sender email 110 105 /// 111 - pub fn sender_email(environment: SmtpEnvironment) { 106 + pub fn sender_email(environment: SmtpEnvironment) -> String { 112 107 environment.sender_email |> option.unwrap(environment.username) 108 + } 109 + 110 + fn sender(environment: SmtpEnvironment) -> gcourier.Sender { 111 + let address = sender_email(environment) 112 + let name = environment.sender_name 113 + 114 + gcourier.Sender(address:, name:) 113 115 } 114 116 115 117 /// get the smtp_environment from the environment variables
+7 -3
src/eater/ui/main_ui.gleam
··· 26 26 import eater/ui/toaster 27 27 import eater/user 28 28 import formal/form.{type Form} 29 - import gcourier/smtp as gsmtp 29 + import gcourier 30 30 import glaze/oat/button 31 31 import glaze/oat/card 32 32 import glaze/oat/form as gform ··· 214 214 UserSubmittedSignUpForm(Result(FormUser, Form(FormUser))) 215 215 ServerGeneratedPassword(password: String, user: FormUser) 216 216 ServerSentPassword( 217 - Result(Nil, gsmtp.Error), 217 + Result(Nil, gcourier.Error), 218 218 password_to_confirm: String, 219 219 user: FormUser, 220 220 ) ··· 1193 1193 ) -> Effect(Message) { 1194 1194 use dispatch <- effect.from() 1195 1195 1196 - smtp.one_time_password(email: user.email, one_time_password:) 1196 + smtp.one_time_password( 1197 + smtp_environment, 1198 + email: user.email, 1199 + one_time_password:, 1200 + ) 1197 1201 |> smtp.send_message(smtp_environment) 1198 1202 |> ServerSentPassword(one_time_password, user) 1199 1203 |> dispatch