diff options
Diffstat (limited to 'walrss/internal')
| -rw-r--r-- | walrss/internal/db/20250810191816_skipifempty.up.sql | 1 | ||||
| -rw-r--r-- | walrss/internal/db/db.go | 6 | ||||
| -rw-r--r-- | walrss/internal/http/edit.go | 37 | ||||
| -rw-r--r-- | walrss/internal/http/http.go | 8 | ||||
| -rw-r--r-- | walrss/internal/http/mainpage.go | 1 | ||||
| -rw-r--r-- | walrss/internal/http/views/main.qtpl.html | 22 | ||||
| -rw-r--r-- | walrss/internal/http/views/main.qtpl.html.go | 32 | ||||
| -rw-r--r-- | walrss/internal/rss/processor.go | 37 | ||||
| -rw-r--r-- | walrss/internal/urls/urls.go | 1 |
9 files changed, 128 insertions, 17 deletions
diff --git a/walrss/internal/db/20250810191816_skipifempty.up.sql b/walrss/internal/db/20250810191816_skipifempty.up.sql new file mode 100644 index 0000000..e008132 --- /dev/null +++ b/walrss/internal/db/20250810191816_skipifempty.up.sql @@ -0,0 +1 @@ +ALTER TABLE users ADD COLUMN skip_if_empty BOOLEAN DEFAULT FALSE NOT NULL diff --git a/walrss/internal/db/db.go b/walrss/internal/db/db.go index 37e093a..7fed362 100644 --- a/walrss/internal/db/db.go +++ b/walrss/internal/db/db.go @@ -3,12 +3,13 @@ package db import ( "database/sql" "fmt" + "strings" + "time" + _ "github.com/mattn/go-sqlite3" "github.com/rs/zerolog/log" "github.com/uptrace/bun" "github.com/uptrace/bun/dialect/sqlitedialect" - "strings" - "time" ) func New(filename string) (*bun.DB, error) { @@ -39,6 +40,7 @@ type User struct { Active bool `bun:"active,notnull"` ScheduleDay SendDay `bun:"schedule_day"` ScheduleHour int `bun:"schedule_hour"` + SkipIfEmpty bool `bun:"skip_if_empty"` } type Feed struct { diff --git a/walrss/internal/http/edit.go b/walrss/internal/http/edit.go index f126710..eb1b7d5 100644 --- a/walrss/internal/http/edit.go +++ b/walrss/internal/http/edit.go @@ -1,13 +1,14 @@ package http import ( + "strconv" + "strings" + "github.com/codemicro/walrss/walrss/internal/core" "github.com/codemicro/walrss/walrss/internal/db" "github.com/codemicro/walrss/walrss/internal/http/views" "github.com/codemicro/walrss/walrss/internal/urls" "github.com/gofiber/fiber/v2" - "strconv" - "strings" ) func (s *Server) editEnabledState(ctx *fiber.Ctx) error { @@ -34,6 +35,37 @@ func (s *Server) editEnabledState(ctx *fiber.Ctx) error { fragmentEmitSuccess(ctx) return ctx.SendString((&views.MainPage{ EnableDigests: user.Active, + SkipIfEmpty: user.SkipIfEmpty, + SelectedDay: user.ScheduleDay, + SelectedTime: user.ScheduleHour, + }).RenderScheduleCard()) +} + +func (s *Server) editSkipEmptyState(ctx *fiber.Ctx) error { + currentUserID := getCurrentUserID(ctx) + if currentUserID == "" { + return requestFragmentSignIn(ctx, urls.Index) + } + + user, err := core.GetUserByID(s.state, currentUserID) + if err != nil { + return err + } + + if strings.ToLower(ctx.FormValue("skipIfEmpty", "off")) == "on" { + user.SkipIfEmpty = true + } else { + user.SkipIfEmpty = false + } + + if err := core.UpdateUser(s.state, user); err != nil { + return err + } + + fragmentEmitSuccess(ctx) + return ctx.SendString((&views.MainPage{ + EnableDigests: user.Active, + SkipIfEmpty: user.SkipIfEmpty, SelectedDay: user.ScheduleDay, SelectedTime: user.ScheduleHour, }).RenderScheduleCard()) @@ -77,6 +109,7 @@ func (s *Server) editTimings(ctx *fiber.Ctx) error { fragmentEmitSuccess(ctx) return ctx.SendString((&views.MainPage{ EnableDigests: user.Active, + SkipIfEmpty: user.SkipIfEmpty, SelectedDay: user.ScheduleDay, SelectedTime: user.ScheduleHour, }).RenderScheduleCard()) diff --git a/walrss/internal/http/http.go b/walrss/internal/http/http.go index f76170c..12a5da9 100644 --- a/walrss/internal/http/http.go +++ b/walrss/internal/http/http.go @@ -3,6 +3,10 @@ package http import ( "context" "errors" + "net/url" + "strings" + "time" + "github.com/codemicro/walrss/walrss/internal/core" "github.com/codemicro/walrss/walrss/internal/http/views" "github.com/codemicro/walrss/walrss/internal/state" @@ -13,9 +17,6 @@ import ( "github.com/rs/zerolog/log" "github.com/stevelacy/daz" "golang.org/x/oauth2" - "net/url" - "strings" - "time" ) const ( @@ -112,6 +113,7 @@ func (s *Server) registerHandlers() { s.app.Get(urls.AuthOIDCCallback, s.authOIDCCallback) s.app.Put(urls.EditEnabledState, s.editEnabledState) + s.app.Put(urls.EditSkipEmptyState, s.editSkipEmptyState) s.app.Put(urls.EditTimings, s.editTimings) s.app.Get(urls.EditFeedItem, s.editFeedItem) diff --git a/walrss/internal/http/mainpage.go b/walrss/internal/http/mainpage.go index 99b26b8..b3530f1 100644 --- a/walrss/internal/http/mainpage.go +++ b/walrss/internal/http/mainpage.go @@ -24,6 +24,7 @@ func (s *Server) mainPage(ctx *fiber.Ctx) error { return views.SendPage(ctx, &views.MainPage{ EnableDigests: user.Active, + SkipIfEmpty: user.SkipIfEmpty, SelectedDay: user.ScheduleDay, SelectedTime: user.ScheduleHour, Feeds: feeds, diff --git a/walrss/internal/http/views/main.qtpl.html b/walrss/internal/http/views/main.qtpl.html index 4619ee6..2e593e0 100644 --- a/walrss/internal/http/views/main.qtpl.html +++ b/walrss/internal/http/views/main.qtpl.html @@ -9,6 +9,7 @@ EnableDigests bool SelectedDay db.SendDay SelectedTime int + SkipIfEmpty bool Feeds db.FeedSlice } %} @@ -268,6 +269,27 @@ </div> </div> + <div class="mb-2 row row-cols-lg-auto align-items-center"> + <div class="col-12"> + <input + type="checkbox" + id="skipIfEmptyCheckbox" + name="skipIfEmpty" + {% if !p.EnableDigests %}disabled{% endif %} + {% if p.SkipIfEmpty %}checked{% endif %} + hx-put="{%s= urls.EditSkipEmptyState %}" + hx-indicator="#skipIfEmptyCheckboxIndicator" + > + <label for="skipIfEmptyCheckbox">Skip digest if there are no updates</label> + </div> + + <div class="col-12"> + <div class="spinner-border spinner-border-sm request-indicator align-middle" style="width: 1rem; height: 1rem;" role="status" id="skipIfEmptyCheckboxIndicator"> + <span class="visually-hidden">Loading...</span> + </div> + </div> + </div> + <form class="row row-cols-lg-auto g-3 align-items-center" hx-put="{%s urls.EditTimings %}" diff --git a/walrss/internal/http/views/main.qtpl.html.go b/walrss/internal/http/views/main.qtpl.html.go index a85f33e..644e0f6 100644 --- a/walrss/internal/http/views/main.qtpl.html.go +++ b/walrss/internal/http/views/main.qtpl.html.go @@ -29,6 +29,7 @@ type MainPage struct { EnableDigests bool SelectedDay db.SendDay SelectedTime int + SkipIfEmpty bool Feeds db.FeedSlice } @@ -449,6 +450,37 @@ func (p *MainPage) StreamRenderScheduleCard(qw422016 *qt422016.Writer) { </div> </div> + <div class="mb-2 row row-cols-lg-auto align-items-center"> + <div class="col-12"> + <input + type="checkbox" + id="skipIfEmptyCheckbox" + name="skipIfEmpty" + `) + if !p.EnableDigests { + qw422016.N().S(`disabled`) + } + qw422016.N().S(` + `) + if p.SkipIfEmpty { + qw422016.N().S(`checked`) + } + qw422016.N().S(` + hx-put="`) + qw422016.N().S(urls.EditSkipEmptyState) + qw422016.N().S(`" + hx-indicator="#skipIfEmptyCheckboxIndicator" + > + <label for="skipIfEmptyCheckbox">Skip digest if there are no updates</label> + </div> + + <div class="col-12"> + <div class="spinner-border spinner-border-sm request-indicator align-middle" style="width: 1rem; height: 1rem;" role="status" id="skipIfEmptyCheckboxIndicator"> + <span class="visually-hidden">Loading...</span> + </div> + </div> + </div> + <form class="row row-cols-lg-auto g-3 align-items-center" hx-put="`) diff --git a/walrss/internal/rss/processor.go b/walrss/internal/rss/processor.go index 8a9885d..b989e3c 100644 --- a/walrss/internal/rss/processor.go +++ b/walrss/internal/rss/processor.go @@ -5,6 +5,14 @@ import ( "context" "crypto/tls" "fmt" + "net/http" + "net/smtp" + "net/textproto" + "sort" + "strings" + "sync" + "time" + "github.com/carlmjohnson/requests" "github.com/codemicro/walrss/walrss/internal/core" "github.com/codemicro/walrss/walrss/internal/db" @@ -14,13 +22,6 @@ import ( "github.com/matcornic/hermes" "github.com/mmcdole/gofeed" "github.com/rs/zerolog/log" - "net/http" - "net/smtp" - "net/textproto" - "sort" - "strings" - "sync" - "time" ) const ( @@ -105,6 +106,7 @@ func ProcessUserFeed(st *state.State, user *db.User, progressChannel chan string } var processedFeeds []*processedFeed + var newContent bool startTime := time.Now().UTC() @@ -131,6 +133,9 @@ func ProcessUserFeed(st *state.State, user *db.User, progressChannel chan string } pf.Items = ffcRes.filtered + if len(pf.Items) > 0 { + newContent = true + } // add new items to DB cache when we're not testing. if we're testing, adding known items to the cache will // stop them from appearing in any scheduled emails later on. @@ -150,7 +155,16 @@ func ProcessUserFeed(st *state.State, user *db.User, progressChannel chan string processedFeeds = append(processedFeeds, pf) } - reportProgress(progressChannel, "Finished fetching feed content\nGenerating email") + reportProgress(progressChannel, "Finished fetching feed content") + + if user.SkipIfEmpty && !newContent { + reportProgress(progressChannel, "There is no new content to send") + if !isTest { + return nil + } + } + + reportProgress(progressChannel, "Generating email") plainContent, htmlContent, err := generateEmail(st, processedFeeds, interval, time.Now().UTC().Sub(startTime)) if err != nil { @@ -166,8 +180,11 @@ func ProcessUserFeed(st *state.State, user *db.User, progressChannel chan string user.Email, "RSS digest for "+time.Now().UTC().Format(dateFormat), ) - - reportProgress(progressChannel, "Done!") + if err != nil { + reportProgress(progressChannel, "Failed to send email") + } else { + reportProgress(progressChannel, "Done!") + } return err } diff --git a/walrss/internal/urls/urls.go b/walrss/internal/urls/urls.go index b0b154d..99943f8 100644 --- a/walrss/internal/urls/urls.go +++ b/walrss/internal/urls/urls.go @@ -17,6 +17,7 @@ const ( Edit = "/edit" EditEnabledState = Edit + "/enabled" + EditSkipEmptyState = Edit + "/skipempty" EditTimings = Edit + "/timings" EditFeedItem = Edit + "/feed/:id" CancelEditFeedItem = Edit + "/feed/:id/cancel" |
