AnthoLume/api/app-routes.go

170 lines
4.1 KiB
Go

package api
import (
"fmt"
"net/http"
"os"
"path/filepath"
"github.com/gin-gonic/gin"
log "github.com/sirupsen/logrus"
"reichard.io/bbank/database"
"reichard.io/bbank/metadata"
)
func baseResourceRoute(template string, args ...map[string]any) func(c *gin.Context) {
variables := gin.H{"RouteName": template}
if len(args) > 0 {
variables = args[0]
}
return func(c *gin.Context) {
rUser, _ := c.Get("AuthorizedUser")
variables["User"] = rUser
c.HTML(http.StatusOK, template, variables)
}
}
func (api *API) createAppResourcesRoute(routeName string, args ...map[string]any) func(*gin.Context) {
// Merge Optional Template Data
var templateVars = gin.H{}
if len(args) > 0 {
templateVars = args[0]
}
templateVars["RouteName"] = routeName
return func(c *gin.Context) {
rUser, _ := c.Get("AuthorizedUser")
qParams := bindQueryParams(c)
templateVars["User"] = rUser
if routeName == "documents" {
documents, err := api.DB.Queries.GetDocumentsWithStats(api.DB.Ctx, database.GetDocumentsWithStatsParams{
UserID: rUser.(string),
Offset: (*qParams.Page - 1) * *qParams.Limit,
Limit: *qParams.Limit,
})
if err != nil {
log.Info(err)
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Invalid Request"})
return
}
templateVars["Data"] = documents
} else if routeName == "home" {
weekly_streak, _ := api.DB.Queries.GetUserWindowStreaks(api.DB.Ctx, database.GetUserWindowStreaksParams{
UserID: rUser.(string),
Window: "WEEK",
})
daily_streak, _ := api.DB.Queries.GetUserWindowStreaks(api.DB.Ctx, database.GetUserWindowStreaksParams{
UserID: rUser.(string),
Window: "DAY",
})
database_info, _ := api.DB.Queries.GetDatabaseInfo(api.DB.Ctx, rUser.(string))
read_graph_data, err := api.DB.Queries.GetDailyReadStats(api.DB.Ctx, rUser.(string))
if err != nil {
log.Info("HMMMM:", err)
}
templateVars["Data"] = gin.H{
"DailyStreak": daily_streak,
"WeeklyStreak": weekly_streak,
"DatabaseInfo": database_info,
"GraphData": read_graph_data,
}
}
c.HTML(http.StatusOK, routeName, templateVars)
}
}
func (api *API) getDocumentCover(c *gin.Context) {
var rDoc requestDocumentID
if err := c.ShouldBindUri(&rDoc); err != nil {
c.AbortWithStatus(http.StatusBadRequest)
return
}
// Validate Document Exists in DB
document, err := api.DB.Queries.GetDocument(api.DB.Ctx, rDoc.DocumentID)
if err != nil {
c.AbortWithStatus(http.StatusBadRequest)
return
}
// Handle Identified Document
if document.Olid != nil {
if *document.Olid == "UNKNOWN" {
c.Redirect(http.StatusFound, "/assets/no-cover.jpg")
return
}
// Derive Path
fileName := "." + filepath.Clean(fmt.Sprintf("/%s.jpg", *document.Olid))
safePath := filepath.Join(api.Config.DataPath, "covers", fileName)
// Validate File Exists
_, err = os.Stat(safePath)
if err != nil {
c.Redirect(http.StatusFound, "/assets/no-cover.jpg")
return
}
c.File(safePath)
return
}
/*
This is a bit convoluted because we want to ensure we set the OLID to
UNKNOWN if there are any errors. This will ideally prevent us from
hitting the OpenLibrary API multiple times in the future.
*/
var coverID string = "UNKNOWN"
var coverFilePath *string
// Identify Documents & Save Covers
coverIDs, err := metadata.GetCoverIDs(document.Title, document.Author)
if err == nil && len(coverIDs) > 0 {
coverFilePath, err = metadata.DownloadAndSaveCover(coverIDs[0], api.Config.DataPath)
if err == nil {
coverID = coverIDs[0]
}
}
// Upsert Document
if _, err = api.DB.Queries.UpsertDocument(api.DB.Ctx, database.UpsertDocumentParams{
ID: document.ID,
Olid: &coverID,
}); err != nil {
log.Error("Document Upsert Error")
}
// Return Unknown Cover
if coverID == "UNKNOWN" {
c.Redirect(http.StatusFound, "/assets/no-cover.jpg")
return
}
c.File(*coverFilePath)
}
/*
METADATA:
- Metadata Match
- Update Metadata
*/
/*
GRAPHS:
- Streaks (Daily, Weekly, Monthly)
- Last Week Activity (Daily - Pages & Time)
- Pages Read (Daily, Weekly, Monthly)
- Reading Progress
- Average Reading Time (Daily, Weekly, Monthly)
*/