170 lines
4.1 KiB
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)
|
||
|
*/
|