diff --git a/fete/fete.go b/fete/fete.go index 5918cb7..1e586ae 100644 --- a/fete/fete.go +++ b/fete/fete.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" "github.com/carlmjohnson/requests" - "io" "log" "net/http" "os" @@ -83,16 +82,6 @@ func (c *Client) GetFete(ctx context.Context, date time.Time) (res *Fete, err er err = requests.URL("https://fetedujour.fr"). Pathf("/api/v2/%v/json-normal-%d-%d", c.config.APIKey, date.Day(), date.Month()). UserAgent("e-paper-display"). - AddValidator(func(resp *http.Response) error { - if resp.StatusCode >= 400 { - body, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - return fmt.Errorf("Fete API error: %s, %s", resp.Header, string(body)) - } - return nil - }). Client(c.client). ToJSON(&res). Fetch(ctx) diff --git a/img.go b/img.go index 8fc4e2b..b966ec5 100644 --- a/img.go +++ b/img.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/Crocmagnon/display-epaper/epd" "github.com/Crocmagnon/display-epaper/fete" + "github.com/Crocmagnon/display-epaper/quotes" "github.com/Crocmagnon/display-epaper/transports" "github.com/Crocmagnon/display-epaper/weather" "github.com/llgcode/draw2d" @@ -29,7 +30,14 @@ const ( rightX = 530 ) -func getBlack(ctx context.Context, nowFunc func() time.Time, transportsClient *transports.Client, feteClient *fete.Client, weatherClient *weather.Client) (*image.RGBA, error) { +func getBlack( + ctx context.Context, + nowFunc func() time.Time, + transportsClient *transports.Client, + feteClient *fete.Client, + weatherClient *weather.Client, + quotesClient *quotes.Client, +) (*image.RGBA, error) { bus, err := transportsClient.GetTCLPassages(ctx, 290) if err != nil { log.Println("error getting bus:", err) @@ -50,6 +58,10 @@ func getBlack(ctx context.Context, nowFunc func() time.Time, transportsClient *t if err != nil { log.Println("error getting weather:", err) } + quote, err := quotesClient.GetQuote(ctx) + if err != nil { + log.Println("error getting quotes:", err) + } img := newWhite() @@ -65,10 +77,20 @@ func getBlack(ctx context.Context, nowFunc func() time.Time, transportsClient *t drawDate(gc, nowFunc()) drawFete(gc, fetes) drawWeather(gc, wthr) + drawQuote(gc, quote) return img, nil } +func drawQuote(gc *draw2dimg.GraphicContext, quote *quotes.Quote) { + if quote == nil { + return + } + + text(gc, quote.Citation.Citation, 15, leftX, 450) + +} + func drawWeather(gc *draw2dimg.GraphicContext, wthr *weather.Prevision) { if wthr == nil { return diff --git a/main.go b/main.go index 0eada30..c02444e 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,7 @@ package main import ( "context" "github.com/Crocmagnon/display-epaper/fete" + "github.com/Crocmagnon/display-epaper/quotes" "github.com/Crocmagnon/display-epaper/transports" "github.com/Crocmagnon/display-epaper/weather" "github.com/golang/freetype/truetype" @@ -39,7 +40,11 @@ func main() { APIKey: os.Getenv("WEATHER_API_KEY"), }) - if err := run(ctx, transportsClient, feteClient, weatherClient); err != nil { + quotesClient := quotes.New(nil, quotes.Config{ + CacheLocation: os.Getenv("QUOTES_CACHE_LOCATION"), + }) + + if err := run(ctx, transportsClient, feteClient, weatherClient, quotesClient); err != nil { log.Fatal("error: ", err) } diff --git a/quotes/quotes.go b/quotes/quotes.go new file mode 100644 index 0000000..2351785 --- /dev/null +++ b/quotes/quotes.go @@ -0,0 +1,105 @@ +package quotes + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "github.com/carlmjohnson/requests" + "log" + "net/http" + "os" + "time" +) + +type Config struct { + CacheLocation string +} + +type Client struct { + client *http.Client + config Config +} + +func New(client *http.Client, config Config) *Client { + return &Client{client: client, config: config} +} + +type Quote struct { + Status int `json:"status"` + Code int `json:"code"` + Error string `json:"error"` + Citation struct { + Citation string `json:"citation"` + Infos struct { + Auteur string `json:"auteur"` + Acteur string `json:"acteur"` + Personnage string `json:"personnage"` + Saison string `json:"saison"` + Episode string `json:"episode"` + } `json:"infos"` + } `json:"citation"` +} + +var errTooOld = errors.New("quote is too old") + +func loadFromDisk(location string) (Quote, error) { + stat, err := os.Stat(location) + if err != nil { + return Quote{}, fmt.Errorf("getting file info: %w", err) + } + + if stat.ModTime().Add(24 * time.Hour).Before(time.Now()) { + return Quote{}, errTooOld + } + + file, err := os.Open(location) + if err != nil { + return Quote{}, fmt.Errorf("opening quote: %w", err) + } + + defer file.Close() + + var res Quote + if err = json.NewDecoder(file).Decode(&res); err != nil { + return Quote{}, fmt.Errorf("decoding quote: %w", err) + } + + return res, nil +} + +func (q Quote) dumpToDisk(location string) error { + file, err := os.Create(location) + if err != nil { + return fmt.Errorf("creating quote: %w", err) + } + + defer file.Close() + + if err = json.NewEncoder(file).Encode(q); err != nil { + return fmt.Errorf("dumping quote: %w", err) + } + return nil +} + +func (c *Client) GetQuote(ctx context.Context) (res *Quote, err error) { + if val, err := loadFromDisk(c.config.CacheLocation); nil == err { + log.Println("found quote in cache") + return &val, nil + } + + log.Println("querying quotes") + err = requests.URL("https://kaamelott.chaudie.re/api/random"). + Client(c.client). + ToJSON(&res). + Fetch(ctx) + if err != nil { + return nil, fmt.Errorf("fetching quotes: %w", err) + } + + if err := res.dumpToDisk(c.config.CacheLocation); err != nil { + log.Printf("error dumping files to disk: %v\n", err) + } + + return res, nil +} diff --git a/run_darwin_arm64.go b/run_darwin_arm64.go index 249a9d0..b69aa37 100644 --- a/run_darwin_arm64.go +++ b/run_darwin_arm64.go @@ -3,6 +3,7 @@ package main import ( "context" "github.com/Crocmagnon/display-epaper/fete" + "github.com/Crocmagnon/display-epaper/quotes" "github.com/Crocmagnon/display-epaper/transports" "github.com/Crocmagnon/display-epaper/weather" "github.com/llgcode/draw2d/draw2dimg" @@ -15,14 +16,22 @@ func run( transportsClient *transports.Client, feteClient *fete.Client, weatherClient *weather.Client, + quotesClient *quotes.Client, ) error { - img, err := getBlack(ctx, func() time.Time { - t, err := time.Parse(time.DateOnly, "2024-08-01zzz") - if err != nil { - return time.Now() - } - return t - }, transportsClient, feteClient, weatherClient) + img, err := getBlack( + ctx, + func() time.Time { + t, err := time.Parse(time.DateOnly, "2024-08-01zzz") + if err != nil { + return time.Now() + } + return t + }, + transportsClient, + feteClient, + weatherClient, + quotesClient, + ) if err != nil { log.Fatal(err) } diff --git a/run_linux_arm64.go b/run_linux_arm64.go index 658aea5..b674a52 100644 --- a/run_linux_arm64.go +++ b/run_linux_arm64.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/Crocmagnon/display-epaper/epd" "github.com/Crocmagnon/display-epaper/fete" + "github.com/Crocmagnon/display-epaper/quotes" "github.com/Crocmagnon/display-epaper/transports" "github.com/Crocmagnon/display-epaper/weather" "log" @@ -17,6 +18,7 @@ func run( transportsClient *transports.Client, feteClient *fete.Client, weatherClient *weather.Client, + quotesClient *quotes.Client, ) error { _, err := host.Init() if err != nil { @@ -36,7 +38,14 @@ func run( default: } - err = loop(ctx, display, transportsClient, feteClient, weatherClient) + err = loop( + ctx, + display, + transportsClient, + feteClient, + weatherClient, + quotesClient, + ) if err != nil { log.Printf("error looping: %v\n", err) } @@ -52,6 +61,7 @@ func loop( transportsClient *transports.Client, feteClient *fete.Client, weatherClient *weather.Client, + quotesClient *quotes.Client, ) error { defer func() { if err := display.Sleep(); err != nil { @@ -66,7 +76,14 @@ func loop( display.Clear() - black, err := getBlack(ctx, time.Now, transportsClient, feteClient, weatherClient) + black, err := getBlack( + ctx, + time.Now, + transportsClient, + feteClient, + weatherClient, + quotesClient, + ) if err != nil { return fmt.Errorf("getting black: %w", err) }