mail based rss feed aggregator
2
fork

Configure Feed

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

at main 141 lines 4.0 kB view raw
1//// eater 2//// email based rss feed aggregator 3 4// eater 5// Copyright (C) 2026 Olivia Streun and contributors. [cite: 4] 6// 7// This software is licensed under the European Union Public Licence (EUPL) v1.2. 8// You may not use this work except in compliance with the Licence. 9// You may obtain a copy of the Licence at: https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 10// 11// AI TRAINING NOTICE: Rights for TDM and AI training are EXPRESSLY RESERVED 12// under Art 4(3) Dir 2019/790. AI training constitutes a Derivative Work. 13// See LICENSE file in the repository root for full details. 14// 15// 16// This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND. [cite: 5] 17// See the Licence for the specific language governing permissions and limitations. [cite: 6] 18 19import eater/backend 20import eater/backend/database 21import eater/backend/smtp 22import eater/backend/webserver 23import eater/configuration 24import eater/user 25import envoy 26import gleam/erlang/process 27import gleam/otp/static_supervisor as supervisor 28import gleam/result 29import sqlight 30import woof 31 32pub fn main() -> Nil { 33 configure_logging() 34 35 let logger = woof.new("WARMUP") 36 37 woof.log(logger, woof.Info, "Starting", []) 38 39 let assert Ok(configuration) = configuration.from_environment(logger) 40 41 let assert Ok(smtp_environment) = smtp.environment() 42 as "Failed to get smtp environment" 43 44 let assert Ok(database) = database_config(logger) 45 as "Failed to get database config" 46 use database <- sqlight.with_connection(database) 47 48 let assert Ok(_) = 49 ensure_default_admin_exists(database, smtp_environment, configuration) 50 51 let backend = process.new_name("backend") 52 let registry = process.new_name("registry") 53 let sender_factory = process.new_name("sender_factory") 54 let sender_manager = process.new_name("sender_starter") 55 let fetcher_factory = process.new_name("fetcher_factory") 56 let fetcher_manager = process.new_name("fetcher_starter") 57 58 let backend_reference = backend.new_reference(backend, database) 59 60 let assert Ok(_supervisor) = 61 supervisor.new(supervisor.RestForOne) 62 |> supervisor.add(backend.supervised( 63 names: backend.Names( 64 backend:, 65 registry:, 66 sender_factory:, 67 sender_manager:, 68 fetcher_factory:, 69 fetcher_manager:, 70 ), 71 database:, 72 smtp_environment:, 73 )) 74 |> supervisor.add(webserver.supervised( 75 backend: backend_reference, 76 smtp_environment:, 77 configuration:, 78 )) 79 |> supervisor.start() 80 81 woof.log(logger, woof.Info, "Finished starting supervisor", []) 82 83 process.sleep_forever() 84} 85 86fn ensure_default_admin_exists( 87 database: sqlight.Connection, 88 smtp_environment: smtp.SmtpEnvironment, 89 configuration: configuration.AppConfig, 90) -> Result(Nil, sqlight.Error) { 91 let sender_email = smtp.sender_email(smtp_environment) 92 93 use maybe_user <- result.try(database.user_by_email(database, sender_email)) 94 95 case maybe_user { 96 [_, ..] -> Ok(Nil) 97 [] -> { 98 let user = 99 user.new(sender_email, configuration.default_admin_password_hash) 100 |> user.promote 101 102 database.add_user(user:, into: database) 103 } 104 } 105} 106 107fn configure_logging() -> Nil { 108 woof.configure(woof.Config( 109 level: woof.Debug, 110 format: woof.Text, 111 colors: woof.Auto, 112 )) 113 114 woof.set_sink(fn(entry, formatted) { 115 woof.beam_logger_sink(entry, formatted) 116 woof.default_sink(entry, formatted) 117 }) 118 119 woof.set_global_context([ 120 woof.str("app", "eater"), 121 woof.str("version", "0.0.1"), 122 ]) 123} 124 125// startup stuff ---------------------------------------------------------------- 126 127fn database_config(logger: woof.Logger) -> Result(String, String) { 128 woof.log(logger, woof.Info, "Getting DATABASE_URL", []) 129 130 use database <- result.try( 131 envoy.get("DATABASE_URL") 132 |> result.replace_error("DATABASE_URL is missing"), 133 ) 134 135 let database = case database { 136 "sqlite:" <> rest -> rest 137 _ -> database 138 } 139 140 Ok(database) 141}