Skip to content

Commit

Permalink
feat: notifications manager (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
nobe4 authored Jun 11, 2024
1 parent 005b274 commit b5a59cb
Show file tree
Hide file tree
Showing 14 changed files with 254 additions and 209 deletions.
3 changes: 2 additions & 1 deletion internal/actors/done/done.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ type Actor struct {
func (a *Actor) Run(n *notifications.Notification) (string, error) {
slog.Debug("marking notification as done", "notification", n.ToString())

n.Meta.ToDelete = true

err := a.Client.API.Do(http.MethodDelete, n.URL, nil, nil)
if err != nil {
return "", err
}

out := colors.Red("DONE ") + n.ToString()
n = nil

return out, nil
}
1 change: 0 additions & 1 deletion internal/cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ func init() {
}

func runConfig(cmd *cobra.Command, args []string) error {

marshalled, err := yaml.Marshal(config)
if err != nil {
slog.Error("Failed to marshall config", "err", err)
Expand Down
6 changes: 1 addition & 5 deletions internal/cmd/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,7 @@ func init() {
}

func runList(cmd *cobra.Command, args []string) error {
notifications, err := client.Notifications()
if err != nil {
slog.Error("Failed to list notifications", "err", err)
return err
}
notifications := manager.Notifications

if filterFlag != "" {
notificationsList, err := jq.Filter(filterFlag, notifications)
Expand Down
10 changes: 2 additions & 8 deletions internal/cmd/repl.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package cmd

import (
"log/slog"

tea "github.com/charmbracelet/bubbletea"
"github.com/nobe4/gh-not/internal/views/normal"
"github.com/spf13/cobra"
Expand All @@ -22,18 +20,14 @@ func init() {
}

func runRepl(cmd *cobra.Command, args []string) error {
notifications, err := client.Notifications()
if err != nil {
slog.Error("Failed to list notifications", "err", err)
return err
}
notifications := manager.Notifications

renderCache, err := notifications.ToTable()
if err != nil {
return err
}

model := normal.New(client, notifications, renderCache)
model := normal.New(manager.Actors, notifications, renderCache)

p := tea.NewProgram(model)
if _, err := p.Run(); err != nil {
Expand Down
41 changes: 25 additions & 16 deletions internal/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ import (

"github.com/nobe4/gh-not/internal/api"
"github.com/nobe4/gh-not/internal/api/file"
cachePkg "github.com/nobe4/gh-not/internal/cache"
configPkg "github.com/nobe4/gh-not/internal/config"
"github.com/nobe4/gh-not/internal/gh"
managerPkg "github.com/nobe4/gh-not/internal/manager"
"github.com/spf13/cobra"
)

Expand All @@ -25,9 +24,8 @@ var (
refreshFlag bool
noRefreshFlag bool

config *configPkg.Config
cache *cachePkg.FileCache
client *gh.Client
config *configPkg.Config
manager *managerPkg.Manager

rootCmd = &cobra.Command{
Use: "gh-not",
Expand All @@ -39,8 +37,9 @@ var (
gh-not --from-file notifications.json list
gh-not sync --refresh --verbosity 4
`,
PersistentPreRunE: setupGlobals,
SilenceErrors: true,
PersistentPreRunE: setupGlobals,
PersistentPostRunE: postRunE,
SilenceErrors: true,
}
)

Expand All @@ -62,6 +61,11 @@ func init() {
}

func setupGlobals(cmd *cobra.Command, args []string) error {
if err := initLogger(); err != nil {
slog.Error("Failed to init the logger", "err", err)
return err
}

var err error

config, err = configPkg.New(configPathFlag)
Expand All @@ -70,24 +74,29 @@ func setupGlobals(cmd *cobra.Command, args []string) error {
return err
}

cache = cachePkg.NewFileCache(config.Cache.TTLInHours, config.Cache.Path)

var apiCaller api.Caller

var caller api.Caller
if notificationDumpPath != "" {
apiCaller = file.New(notificationDumpPath)
caller = file.New(notificationDumpPath)
} else {
apiCaller, err = api.NewGH()
caller, err = api.NewGH()
if err != nil {
slog.Error("Failed to create an API REST client", "err", err)
return err
}
}

client = gh.NewClient(apiCaller, cache, refreshFlag, noRefreshFlag)
manager = managerPkg.New(config, caller)
if err := manager.Load(refreshFlag, noRefreshFlag); err != nil {
slog.Error("Failed to init the manager", "err", err)
return err
}

if err := initLogger(); err != nil {
slog.Error("Failed to init the logger", "err", err)
return nil
}

func postRunE(_ *cobra.Command, _ []string) error {
if err := manager.Save(); err != nil {
slog.Error("Failed to save the notifications", "err", err)
return err
}

Expand Down
15 changes: 1 addition & 14 deletions internal/cmd/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package cmd
import (
"log/slog"

"github.com/nobe4/gh-not/internal/actors"
"github.com/spf13/cobra"
)

Expand All @@ -30,22 +29,10 @@ func init() {
}

func runSync(cmd *cobra.Command, args []string) error {
notifications, err := client.Notifications()
if err != nil {
slog.Error("Failed to list notifications", "err", err)
return err
}

notifications, err = config.Apply(notifications, actors.Map(client), noop)
if err != nil {
if err := manager.Apply(noop); err != nil {
slog.Error("Failed to applying rules", "err", err)
return err
}

if err := cache.Write(notifications); err != nil {
slog.Error("Failed to write the cache", "err", err)
return err
}

return nil
}
47 changes: 0 additions & 47 deletions internal/config/config.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
package config

import (
"fmt"
"log/slog"
"os"
"path"

"github.com/nobe4/gh-not/internal/actors"
"github.com/nobe4/gh-not/internal/notifications"
"gopkg.in/yaml.v3"
)

Expand Down Expand Up @@ -42,46 +38,3 @@ func New(path string) (*Config, error) {

return config, nil
}

func (c *Config) Apply(n notifications.Notifications, actors map[string]actors.Actor, noop bool) (notifications.Notifications, error) {
indexIDMap := map[string]int{}
for i, n := range n {
indexIDMap[n.Id] = i
}

for _, rule := range c.Rules {
slog.Debug("apply rule", "name", rule.Name)

selectedIds, err := rule.filterIds(n)
if err != nil {
return nil, err
}

var out string
for _, id := range selectedIds {
i := indexIDMap[id]
notification := n[i]

if actor, ok := actors[rule.Action]; ok {
if noop {
fmt.Printf("NOOP'ing action %s on notification %s\n", rule.Action, notification.ToString())
} else {
out, err = actor.Run(notification)
if err != nil {
slog.Error("action failed", "action", rule.Action, "err", err)
}
if out != "" {
fmt.Println(out)
}
}
} else {
slog.Error("unknown action", "action", rule.Action)
}

// FIXME: is this still needed?
n[i] = notification
}
}

return n.Compact(), nil
}
2 changes: 1 addition & 1 deletion internal/config/rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ type Rule struct {
Action string `yaml:"action"`
}

func (r Rule) filterIds(n notifications.Notifications) ([]string, error) {
func (r Rule) FilterIds(n notifications.Notifications) ([]string, error) {
var err error

for _, filter := range r.Filters {
Expand Down
43 changes: 10 additions & 33 deletions internal/gh/gh.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,14 @@ const (
)

type Client struct {
API api.Caller
cache cache.ExpiringReadWriter
refresh bool
noRefresh bool
API api.Caller
cache cache.ExpiringReadWriter
}

func NewClient(api api.Caller, cache cache.ExpiringReadWriter, refresh, noRefresh bool) *Client {
func NewClient(api api.Caller, cache cache.ExpiringReadWriter) *Client {
return &Client{
API: api,
cache: cache,
refresh: refresh,
noRefresh: noRefresh,
API: api,
cache: cache,
}
}

Expand Down Expand Up @@ -144,34 +140,15 @@ func (c *Client) pullNotificationFromApi() (notifications.Notifications, error)
func (c *Client) Notifications() (notifications.Notifications, error) {
allNotifications := notifications.Notifications{}

cachedNotifications, refresh, err := c.loadCache()
pulledNotifications, err := c.pullNotificationFromApi()
if err != nil {
slog.Warn("Error while reading the cache: %#v\n", err)
} else if cachedNotifications != nil {
allNotifications = cachedNotifications
return nil, err
}

if !refresh && c.refresh {
slog.Info("forcing a refresh")
refresh = true
}
if refresh && c.noRefresh {
slog.Info("preventing a refresh")
refresh = false
}
allNotifications = append(allNotifications, pulledNotifications...)

if refresh {
fmt.Printf("Refreshing the cache...\n")
pulledNotifications, err := c.pullNotificationFromApi()
if err != nil {
return nil, err
}

allNotifications = append(allNotifications, pulledNotifications...)

if err := c.cache.Write(allNotifications); err != nil {
slog.Error("Error while writing the cache: %#v", err)
}
if err := c.cache.Write(allNotifications); err != nil {
slog.Error("Error while writing the cache: %#v", err)
}

return allNotifications.Uniq(), nil
Expand Down
Loading

0 comments on commit b5a59cb

Please sign in to comment.