[add] opds catalog, [add] migrate to non-cgo sqlite driver
This commit is contained in:
parent
4e1ee0022a
commit
eb7d711022
@ -19,11 +19,7 @@ ARG TARGETARCH
|
|||||||
RUN --mount=target=. \
|
RUN --mount=target=. \
|
||||||
--mount=type=cache,target=/root/.cache/go-build \
|
--mount=type=cache,target=/root/.cache/go-build \
|
||||||
--mount=type=cache,target=/go/pkg \
|
--mount=type=cache,target=/go/pkg \
|
||||||
if [ "$TARGETARCH" = "amd64" ]; then \
|
GOOS=$TARGETOS GOARCH=$TARGETARCH go build -o /opt/bookmanager/server; \
|
||||||
GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=1 CGO_CFLAGS="-D_LARGEFILE64_SOURCE" CC=x86_64-linux-gnu-gcc go build -o /opt/bookmanager/server; \
|
|
||||||
else \
|
|
||||||
GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=1 CGO_CFLAGS="-D_LARGEFILE64_SOURCE" go build -o /opt/bookmanager/server; \
|
|
||||||
fi; \
|
|
||||||
cp -a ./templates /opt/bookmanager/templates; \
|
cp -a ./templates /opt/bookmanager/templates; \
|
||||||
cp -a ./assets /opt/bookmanager/assets;
|
cp -a ./assets /opt/bookmanager/assets;
|
||||||
|
|
||||||
|
6
Makefile
6
Makefile
@ -5,8 +5,10 @@ build_local:
|
|||||||
cp -a ./templates ./build/templates
|
cp -a ./templates ./build/templates
|
||||||
cp -a ./assets ./build/assets
|
cp -a ./assets ./build/assets
|
||||||
|
|
||||||
env GOOS=linux GOARCH=amd64 CGO_ENABLED=1 CC="zig cc -target x86_64-linux" CXX="zig c++ -target x86_64-linux" go build -o ./build/server_linux_x86_64
|
env GOOS=linux GOARCH=amd64 go build -o ./build/server_linux_amd64
|
||||||
env GOOS=darwin GOARCH=arm64 CGO_ENABLED=1 CGO_CFLAGS="-D_LARGEFILE64_SOURCE" go build -o ./build/server_darwin_arm64
|
env GOOS=linux GOARCH=arm64 go build -o ./build/server_linux_arm64
|
||||||
|
env GOOS=darwin GOARCH=arm64 go build -o ./build/server_darwin_arm64
|
||||||
|
env GOOS=darwin GOARCH=amd64 go build -o ./build/server_darwin_amd64
|
||||||
|
|
||||||
docker_build_local:
|
docker_build_local:
|
||||||
docker build -t bookmanager:latest .
|
docker build -t bookmanager:latest .
|
||||||
|
45
README.md
45
README.md
@ -31,16 +31,17 @@
|
|||||||
|
|
||||||
This is BookManager! Will probably be renamed at some point. This repository contains:
|
This is BookManager! Will probably be renamed at some point. This repository contains:
|
||||||
|
|
||||||
- [KOReader KOSync](https://github.com/koreader/koreader-sync-server) Compatible API
|
- Web App / Progressive Web App (PWA)
|
||||||
- KOReader Plugin (See `client` subfolder)
|
- [KOReader](https://github.com/koreader/koreader) Plugin (See `client` subfolder)
|
||||||
- WebApp
|
- [KOReader KOSync](https://github.com/koreader/koreader-sync-server) compatible API
|
||||||
|
- OPDS API endpoint that provides access to the uploaded documents
|
||||||
|
|
||||||
In additional to the compatible KOSync API's, we add:
|
In additional to the compatible KOSync API's, we add:
|
||||||
|
|
||||||
- Additional APIs to automatically upload reading statistics
|
- Additional APIs to automatically upload reading statistics
|
||||||
- Automatically upload documents to the server (can download in the "Documents" view)
|
- Upload documents to the server (can download in the "Documents" view or via OPDS)
|
||||||
- Book metadata scraping (Thanks [OpenLibrary](https://openlibrary.org/) & [Google Books API](https://developers.google.com/books/docs/v1/getting_started))
|
- Book metadata scraping (Thanks [OpenLibrary](https://openlibrary.org/) & [Google Books API](https://developers.google.com/books/docs/v1/getting_started))
|
||||||
- No JavaScript! All information is generated server side.
|
- No JavaScript! All information is generated server side with go templates
|
||||||
|
|
||||||
# Server
|
# Server
|
||||||
|
|
||||||
@ -50,6 +51,10 @@ Docker Image: `docker pull gitea.va.reichard.io/evan/bookmanager:latest`
|
|||||||
|
|
||||||
The KOSync compatible API endpoint is located at: `http(s)://<SERVER>/api/ko`
|
The KOSync compatible API endpoint is located at: `http(s)://<SERVER>/api/ko`
|
||||||
|
|
||||||
|
## OPDS API
|
||||||
|
|
||||||
|
The OPDS API endpoint is located at: `http(s)://<SERVER>/api/opds`
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@ -80,6 +85,20 @@ The service is now accessible at: `http://localhost:8585`. I recommend registeri
|
|||||||
| REGISTRATION_ENABLED | false | Whether to allow registration (applies to both WebApp & KOSync API) |
|
| REGISTRATION_ENABLED | false | Whether to allow registration (applies to both WebApp & KOSync API) |
|
||||||
| COOKIE_SESSION_KEY | <EMPTY> | Optional secret cookie session key (auto generated if not provided) |
|
| COOKIE_SESSION_KEY | <EMPTY> | Optional secret cookie session key (auto generated if not provided) |
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
### Authentication
|
||||||
|
|
||||||
|
- _Web App / PWA_ - Session based token (7 day expiry, refresh after 6 days)
|
||||||
|
- _KOSync & SyncNinja API_ - Header based (KOSync compatibility)
|
||||||
|
- _OPDS API_ - Basic authentication (KOReader OPDS compatibility)
|
||||||
|
|
||||||
|
### Notes
|
||||||
|
|
||||||
|
- Credentials are the same amongst all endpoints
|
||||||
|
- The native KOSync plugin sends an MD5 hash of the password. Due to that:
|
||||||
|
- We store an Argon2 hash _and_ per-password salt of the MD5 hashed original password
|
||||||
|
|
||||||
# Client (KOReader Plugin)
|
# Client (KOReader Plugin)
|
||||||
|
|
||||||
See documentation in the `client` subfolder: [SyncNinja](https://gitea.va.reichard.io/evan/BookManager/src/branch/master/client/)
|
See documentation in the `client` subfolder: [SyncNinja](https://gitea.va.reichard.io/evan/BookManager/src/branch/master/client/)
|
||||||
@ -104,21 +123,15 @@ CONFIG_PATH=./data DATA_PATH=./data go run main.go serve
|
|||||||
The `Dockerfile` and `Makefile` contain the build information:
|
The `Dockerfile` and `Makefile` contain the build information:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# Build Local (Linux & Darwin - arm64 & amd64)
|
||||||
|
make build_local
|
||||||
|
|
||||||
# Build Local Docker Image
|
# Build Local Docker Image
|
||||||
make docker_build_local
|
make docker_build_local
|
||||||
|
|
||||||
# Push Latest
|
# Build Docker & Push Latest or Dev (Linux - arm64 & amd64)
|
||||||
make docker_build_release_latest
|
make docker_build_release_latest
|
||||||
```
|
make docker_build_release_dev
|
||||||
|
|
||||||
If manually building, you must enable CGO:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Download Dependencies
|
|
||||||
go mod download
|
|
||||||
|
|
||||||
# Compile (Binary `./bookmanager`)
|
|
||||||
CGO_ENABLED=1 CGO_CFLAGS="-D_LARGEFILE64_SOURCE" go build -o /bookmanager
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
28
api/api.go
28
api/api.go
@ -66,6 +66,7 @@ func NewApi(db *database.DBManager, c *config.Config) *API {
|
|||||||
// Register API Routes
|
// Register API Routes
|
||||||
apiGroup := api.Router.Group("/api")
|
apiGroup := api.Router.Group("/api")
|
||||||
api.registerKOAPIRoutes(apiGroup)
|
api.registerKOAPIRoutes(apiGroup)
|
||||||
|
api.registerOPDSRoutes(apiGroup)
|
||||||
|
|
||||||
return api
|
return api
|
||||||
}
|
}
|
||||||
@ -112,18 +113,27 @@ func (api *API) registerKOAPIRoutes(apiGroup *gin.RouterGroup) {
|
|||||||
koGroup := apiGroup.Group("/ko")
|
koGroup := apiGroup.Group("/ko")
|
||||||
|
|
||||||
koGroup.POST("/users/create", api.createUser)
|
koGroup.POST("/users/create", api.createUser)
|
||||||
koGroup.GET("/users/auth", api.authAPIMiddleware, api.authorizeUser)
|
koGroup.GET("/users/auth", api.authKOMiddleware, api.authorizeUser)
|
||||||
|
|
||||||
koGroup.PUT("/syncs/progress", api.authAPIMiddleware, api.setProgress)
|
koGroup.PUT("/syncs/progress", api.authKOMiddleware, api.setProgress)
|
||||||
koGroup.GET("/syncs/progress/:document", api.authAPIMiddleware, api.getProgress)
|
koGroup.GET("/syncs/progress/:document", api.authKOMiddleware, api.getProgress)
|
||||||
|
|
||||||
koGroup.POST("/documents", api.authAPIMiddleware, api.addDocuments)
|
koGroup.POST("/documents", api.authKOMiddleware, api.addDocuments)
|
||||||
koGroup.POST("/syncs/documents", api.authAPIMiddleware, api.checkDocumentsSync)
|
koGroup.POST("/syncs/documents", api.authKOMiddleware, api.checkDocumentsSync)
|
||||||
koGroup.PUT("/documents/:document/file", api.authAPIMiddleware, api.uploadDocumentFile)
|
koGroup.PUT("/documents/:document/file", api.authKOMiddleware, api.uploadDocumentFile)
|
||||||
koGroup.GET("/documents/:document/file", api.authAPIMiddleware, api.downloadDocumentFile)
|
koGroup.GET("/documents/:document/file", api.authKOMiddleware, api.downloadDocumentFile)
|
||||||
|
|
||||||
koGroup.POST("/activity", api.authAPIMiddleware, api.addActivities)
|
koGroup.POST("/activity", api.authKOMiddleware, api.addActivities)
|
||||||
koGroup.POST("/syncs/activity", api.authAPIMiddleware, api.checkActivitySync)
|
koGroup.POST("/syncs/activity", api.authKOMiddleware, api.checkActivitySync)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) registerOPDSRoutes(apiGroup *gin.RouterGroup) {
|
||||||
|
opdsGroup := apiGroup.Group("/opds")
|
||||||
|
|
||||||
|
opdsGroup.GET("/", api.authOPDSMiddleware, api.opdsDocuments)
|
||||||
|
opdsGroup.GET("/search.xml", api.authOPDSMiddleware, api.opdsSearchDescription)
|
||||||
|
opdsGroup.GET("/documents/:document/file", api.authOPDSMiddleware, api.downloadDocumentFile)
|
||||||
|
opdsGroup.GET("/documents/:document/cover", api.authOPDSMiddleware, api.getDocumentCover)
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateToken(n int) ([]byte, error) {
|
func generateToken(n int) ([]byte, error) {
|
||||||
|
34
api/auth.go
34
api/auth.go
@ -15,11 +15,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// KOSync API Auth Headers
|
// KOSync API Auth Headers
|
||||||
type authHeader struct {
|
type authKOHeader struct {
|
||||||
AuthUser string `header:"x-auth-user"`
|
AuthUser string `header:"x-auth-user"`
|
||||||
AuthKey string `header:"x-auth-key"`
|
AuthKey string `header:"x-auth-key"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OPDS Auth Headers
|
||||||
|
type authOPDSHeader struct {
|
||||||
|
Authorization string `header:"authorization"`
|
||||||
|
}
|
||||||
|
|
||||||
func (api *API) authorizeCredentials(username string, password string) (authorized bool) {
|
func (api *API) authorizeCredentials(username string, password string) (authorized bool) {
|
||||||
user, err := api.DB.Queries.GetUser(api.DB.Ctx, username)
|
user, err := api.DB.Queries.GetUser(api.DB.Ctx, username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -33,7 +38,7 @@ func (api *API) authorizeCredentials(username string, password string) (authoriz
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) authAPIMiddleware(c *gin.Context) {
|
func (api *API) authKOMiddleware(c *gin.Context) {
|
||||||
session := sessions.Default(c)
|
session := sessions.Default(c)
|
||||||
|
|
||||||
// Check Session First
|
// Check Session First
|
||||||
@ -46,7 +51,7 @@ func (api *API) authAPIMiddleware(c *gin.Context) {
|
|||||||
|
|
||||||
// Session Failed -> Check Headers (Allowed on API for KOSync Compatibility)
|
// Session Failed -> Check Headers (Allowed on API for KOSync Compatibility)
|
||||||
|
|
||||||
var rHeader authHeader
|
var rHeader authKOHeader
|
||||||
if err := c.ShouldBindHeader(&rHeader); err != nil {
|
if err := c.ShouldBindHeader(&rHeader); err != nil {
|
||||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Incorrect Headers"})
|
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Incorrect Headers"})
|
||||||
return
|
return
|
||||||
@ -71,6 +76,29 @@ func (api *API) authAPIMiddleware(c *gin.Context) {
|
|||||||
c.Next()
|
c.Next()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (api *API) authOPDSMiddleware(c *gin.Context) {
|
||||||
|
c.Header("WWW-Authenticate", `Basic realm="restricted", charset="UTF-8"`)
|
||||||
|
|
||||||
|
user, rawPassword, hasAuth := c.Request.BasicAuth()
|
||||||
|
|
||||||
|
// Validate Auth Fields
|
||||||
|
if hasAuth != true || user == "" || rawPassword == "" {
|
||||||
|
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid Authorization Headers"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate Auth
|
||||||
|
password := fmt.Sprintf("%x", md5.Sum([]byte(rawPassword)))
|
||||||
|
if authorized := api.authorizeCredentials(user, password); authorized != true {
|
||||||
|
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Set("AuthorizedUser", user)
|
||||||
|
c.Header("Cache-Control", "private")
|
||||||
|
c.Next()
|
||||||
|
}
|
||||||
|
|
||||||
func (api *API) authWebAppMiddleware(c *gin.Context) {
|
func (api *API) authWebAppMiddleware(c *gin.Context) {
|
||||||
session := sessions.Default(c)
|
session := sessions.Default(c)
|
||||||
|
|
||||||
|
113
api/opds-routes.go
Normal file
113
api/opds-routes.go
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"reichard.io/bbank/database"
|
||||||
|
"reichard.io/bbank/opds"
|
||||||
|
)
|
||||||
|
|
||||||
|
var mimeMapping map[string]string = map[string]string{
|
||||||
|
"epub": "application/epub+zip",
|
||||||
|
"azw": "application/vnd.amazon.mobi8-ebook",
|
||||||
|
"mobi": "application/x-mobipocket-ebook",
|
||||||
|
"pdf": "application/pdf",
|
||||||
|
"zip": "application/zip",
|
||||||
|
"txt": "text/plain",
|
||||||
|
"rtf": "application/rtf",
|
||||||
|
"htm": "text/html",
|
||||||
|
"html": "text/html",
|
||||||
|
"doc": "application/msword",
|
||||||
|
"lit": "application/x-ms-reader",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) opdsDocuments(c *gin.Context) {
|
||||||
|
var userID string
|
||||||
|
if rUser, _ := c.Get("AuthorizedUser"); rUser != nil {
|
||||||
|
userID = rUser.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Potential URL Parameters
|
||||||
|
qParams := bindQueryParams(c)
|
||||||
|
|
||||||
|
// Get Documents
|
||||||
|
documents, err := api.DB.Queries.GetDocumentsWithStats(api.DB.Ctx, database.GetDocumentsWithStatsParams{
|
||||||
|
UserID: userID,
|
||||||
|
Offset: (*qParams.Page - 1) * *qParams.Limit,
|
||||||
|
Limit: *qParams.Limit,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Error("[opdsDocuments] GetDocumentsWithStats DB Error:", err)
|
||||||
|
c.AbortWithStatus(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build OPDS Entries
|
||||||
|
var allEntries []opds.Entry
|
||||||
|
for _, doc := range documents {
|
||||||
|
// Require File
|
||||||
|
if doc.Filepath != nil {
|
||||||
|
splitFilepath := strings.Split(*doc.Filepath, ".")
|
||||||
|
fileType := splitFilepath[len(splitFilepath)-1]
|
||||||
|
|
||||||
|
item := opds.Entry{
|
||||||
|
Title: fmt.Sprintf("[%3d%%] %s", int(doc.Percentage.(float64)), *doc.Title),
|
||||||
|
Author: []opds.Author{
|
||||||
|
{
|
||||||
|
Name: *doc.Author,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Content: &opds.Content{
|
||||||
|
Content: *doc.Description,
|
||||||
|
ContentType: "text",
|
||||||
|
},
|
||||||
|
Links: []opds.Link{
|
||||||
|
{
|
||||||
|
Rel: "http://opds-spec.org/acquisition",
|
||||||
|
Href: fmt.Sprintf("./documents/%s/file", doc.ID),
|
||||||
|
TypeLink: mimeMapping[fileType],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Rel: "http://opds-spec.org/image",
|
||||||
|
Href: fmt.Sprintf("./documents/%s/cover", doc.ID),
|
||||||
|
TypeLink: "image/jpeg",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
allEntries = append(allEntries, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build & Return XML
|
||||||
|
searchFeed := &opds.Feed{
|
||||||
|
Title: "All Documents",
|
||||||
|
Updated: time.Now().UTC(),
|
||||||
|
// TODO
|
||||||
|
// Links: []opds.Link{
|
||||||
|
// {
|
||||||
|
// Title: "Search Book Manager",
|
||||||
|
// Rel: "search",
|
||||||
|
// TypeLink: "application/opensearchdescription+xml",
|
||||||
|
// Href: "search.xml",
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
Entries: allEntries,
|
||||||
|
}
|
||||||
|
|
||||||
|
c.XML(http.StatusOK, searchFeed)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) opdsSearchDescription(c *gin.Context) {
|
||||||
|
rawXML := `<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
|
||||||
|
<ShortName>Search Book Manager</ShortName>
|
||||||
|
<Description>Search Book Manager</Description>
|
||||||
|
<Url type="application/atom+xml;profile=opds-catalog;kind=acquisition" template="./search?query={searchTerms}"/>
|
||||||
|
</OpenSearchDescription>`
|
||||||
|
c.Data(http.StatusOK, "application/xml", []byte(rawXML))
|
||||||
|
}
|
@ -5,11 +5,15 @@ import (
|
|||||||
"database/sql"
|
"database/sql"
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
"path"
|
|
||||||
|
|
||||||
sqlite "github.com/mattn/go-sqlite3"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
"path"
|
||||||
"reichard.io/bbank/config"
|
"reichard.io/bbank/config"
|
||||||
|
|
||||||
|
// CGO SQLite
|
||||||
|
// sqlite "github.com/mattn/go-sqlite3"
|
||||||
|
|
||||||
|
// GO SQLite
|
||||||
|
_ "modernc.org/sqlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DBManager struct {
|
type DBManager struct {
|
||||||
@ -32,17 +36,32 @@ func NewMgr(c *config.Config) *DBManager {
|
|||||||
|
|
||||||
// Create Database
|
// Create Database
|
||||||
if c.DBType == "sqlite" {
|
if c.DBType == "sqlite" {
|
||||||
sql.Register("sqlite3_custom", &sqlite.SQLiteDriver{
|
// GO SQLite
|
||||||
ConnectHook: connectHookSQLite,
|
|
||||||
})
|
|
||||||
|
|
||||||
dbLocation := path.Join(c.ConfigPath, fmt.Sprintf("%s.db", c.DBName))
|
dbLocation := path.Join(c.ConfigPath, fmt.Sprintf("%s.db", c.DBName))
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
dbm.DB, err = sql.Open("sqlite3_custom", dbLocation)
|
dbm.DB, err = sql.Open("sqlite", dbLocation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Single Open Connection
|
||||||
|
dbm.DB.SetMaxOpenConns(1)
|
||||||
|
if _, err := dbm.DB.Exec(ddl, nil); err != nil {
|
||||||
|
log.Info("Exec Error:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CGO SQLite
|
||||||
|
// sql.Register("sqlite3_custom", &sqlite.SQLiteDriver{
|
||||||
|
// ConnectHook: connectHookSQLite,
|
||||||
|
// })
|
||||||
|
|
||||||
|
// dbLocation := path.Join(c.ConfigPath, fmt.Sprintf("%s.db", c.DBName))
|
||||||
|
|
||||||
|
// var err error
|
||||||
|
// dbm.DB, err = sql.Open("sqlite3_custom", dbLocation)
|
||||||
|
// if err != nil {
|
||||||
|
// log.Fatal(err)
|
||||||
|
// }
|
||||||
} else {
|
} else {
|
||||||
log.Fatal("Unsupported Database")
|
log.Fatal("Unsupported Database")
|
||||||
}
|
}
|
||||||
@ -59,6 +78,8 @@ func (dbm *DBManager) CacheTempTables() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// CGO SQLite
|
||||||
func connectHookSQLite(conn *sqlite.SQLiteConn) error {
|
func connectHookSQLite(conn *sqlite.SQLiteConn) error {
|
||||||
// Create Tables
|
// Create Tables
|
||||||
log.Debug("Creating Schema")
|
log.Debug("Creating Schema")
|
||||||
@ -67,3 +88,4 @@ func connectHookSQLite(conn *sqlite.SQLiteConn) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
24
go.mod
24
go.mod
@ -8,12 +8,12 @@ require (
|
|||||||
github.com/gin-contrib/multitemplate v0.0.0-20230212012517-45920c92c271
|
github.com/gin-contrib/multitemplate v0.0.0-20230212012517-45920c92c271
|
||||||
github.com/gin-contrib/sessions v0.0.4
|
github.com/gin-contrib/sessions v0.0.4
|
||||||
github.com/gin-gonic/gin v1.9.1
|
github.com/gin-gonic/gin v1.9.1
|
||||||
github.com/mattn/go-sqlite3 v1.14.17
|
|
||||||
github.com/microcosm-cc/bluemonday v1.0.25
|
github.com/microcosm-cc/bluemonday v1.0.25
|
||||||
github.com/sirupsen/logrus v1.9.3
|
github.com/sirupsen/logrus v1.9.3
|
||||||
github.com/urfave/cli/v2 v2.25.7
|
github.com/urfave/cli/v2 v2.25.7
|
||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9
|
golang.org/x/exp v0.0.0-20230905200255-921286631fa9
|
||||||
golang.org/x/net v0.14.0
|
golang.org/x/net v0.15.0
|
||||||
|
modernc.org/sqlite v1.26.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@ -22,30 +22,46 @@ require (
|
|||||||
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
|
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
|
||||||
github.com/chenzhuoyu/iasm v0.9.0 // indirect
|
github.com/chenzhuoyu/iasm v0.9.0 // indirect
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||||
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.15.3 // indirect
|
github.com/go-playground/validator/v10 v10.15.3 // indirect
|
||||||
github.com/goccy/go-json v0.10.2 // indirect
|
github.com/goccy/go-json v0.10.2 // indirect
|
||||||
|
github.com/google/uuid v1.3.0 // indirect
|
||||||
github.com/gorilla/context v1.1.1 // indirect
|
github.com/gorilla/context v1.1.1 // indirect
|
||||||
github.com/gorilla/css v1.0.0 // indirect
|
github.com/gorilla/css v1.0.0 // indirect
|
||||||
github.com/gorilla/securecookie v1.1.1 // indirect
|
github.com/gorilla/securecookie v1.1.1 // indirect
|
||||||
github.com/gorilla/sessions v1.2.1 // indirect
|
github.com/gorilla/sessions v1.2.1 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
|
||||||
github.com/leodido/go-urn v1.2.4 // indirect
|
github.com/leodido/go-urn v1.2.4 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.17 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
github.com/ugorji/go/codec v1.2.11 // indirect
|
github.com/ugorji/go/codec v1.2.11 // indirect
|
||||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||||
golang.org/x/arch v0.4.0 // indirect
|
golang.org/x/arch v0.4.0 // indirect
|
||||||
golang.org/x/crypto v0.12.0 // indirect
|
golang.org/x/crypto v0.13.0 // indirect
|
||||||
|
golang.org/x/mod v0.12.0 // indirect
|
||||||
golang.org/x/sys v0.12.0 // indirect
|
golang.org/x/sys v0.12.0 // indirect
|
||||||
golang.org/x/text v0.12.0 // indirect
|
golang.org/x/text v0.13.0 // indirect
|
||||||
|
golang.org/x/tools v0.13.0 // indirect
|
||||||
google.golang.org/protobuf v1.31.0 // indirect
|
google.golang.org/protobuf v1.31.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
lukechampine.com/uint128 v1.2.0 // indirect
|
||||||
|
modernc.org/cc/v3 v3.40.0 // indirect
|
||||||
|
modernc.org/ccgo/v3 v3.16.13 // indirect
|
||||||
|
modernc.org/libc v1.24.1 // indirect
|
||||||
|
modernc.org/mathutil v1.5.0 // indirect
|
||||||
|
modernc.org/memory v1.6.0 // indirect
|
||||||
|
modernc.org/opt v0.1.3 // indirect
|
||||||
|
modernc.org/strutil v1.1.3 // indirect
|
||||||
|
modernc.org/token v1.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
53
go.sum
53
go.sum
@ -22,6 +22,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
|
|||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
||||||
github.com/gin-contrib/multitemplate v0.0.0-20230212012517-45920c92c271 h1:s+boMV47gwTyff2PL+k6V33edJpp+K5y3QPzZlRhno8=
|
github.com/gin-contrib/multitemplate v0.0.0-20230212012517-45920c92c271 h1:s+boMV47gwTyff2PL+k6V33edJpp+K5y3QPzZlRhno8=
|
||||||
@ -56,8 +58,11 @@ github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaW
|
|||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
|
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
|
||||||
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
|
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
|
||||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||||
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
|
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
|
||||||
@ -71,6 +76,8 @@ github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/z
|
|||||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||||
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||||
github.com/kidstuff/mongostore v0.0.0-20181113001930-e650cd85ee4b/go.mod h1:g2nVr8KZVXJSS97Jo8pJ0jgq29P6H7dG0oplUA86MQw=
|
github.com/kidstuff/mongostore v0.0.0-20181113001930-e650cd85ee4b/go.mod h1:g2nVr8KZVXJSS97Jo8pJ0jgq29P6H7dG0oplUA86MQw=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
|
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
|
||||||
@ -112,6 +119,9 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
|||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b/go.mod h1:wTPjTepVu7uJBYgZ0SdWHQlIas582j6cn2jgk4DDdlg=
|
github.com/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b/go.mod h1:wTPjTepVu7uJBYgZ0SdWHQlIas582j6cn2jgk4DDdlg=
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||||
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
||||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||||
@ -153,23 +163,26 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
|||||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||||
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
|
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
|
||||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
|
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
|
||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
|
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
|
||||||
|
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||||
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
|
golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
|
||||||
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@ -195,12 +208,14 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
|
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
|
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
|
||||||
|
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
@ -219,5 +234,29 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
|||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
|
||||||
|
lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||||
|
modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw=
|
||||||
|
modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0=
|
||||||
|
modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw=
|
||||||
|
modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY=
|
||||||
|
modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk=
|
||||||
|
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
|
||||||
|
modernc.org/libc v1.24.1 h1:uvJSeCKL/AgzBo2yYIPPTy82v21KgGnizcGYfBHaNuM=
|
||||||
|
modernc.org/libc v1.24.1/go.mod h1:FmfO1RLrU3MHJfyi9eYYmZBfi/R+tqZ6+hQ3yQQUkak=
|
||||||
|
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
|
||||||
|
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||||
|
modernc.org/memory v1.6.0 h1:i6mzavxrE9a30whzMfwf7XWVODx2r5OYXvU46cirX7o=
|
||||||
|
modernc.org/memory v1.6.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
|
||||||
|
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
|
||||||
|
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||||
|
modernc.org/sqlite v1.26.0 h1:SocQdLRSYlA8W99V8YH0NES75thx19d9sB/aFc4R8Lw=
|
||||||
|
modernc.org/sqlite v1.26.0/go.mod h1:FL3pVXie73rg3Rii6V/u5BoHlSoyeZeIgKZEgHARyCU=
|
||||||
|
modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY=
|
||||||
|
modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw=
|
||||||
|
modernc.org/tcl v1.15.2 h1:C4ybAYCGJw968e+Me18oW55kD/FexcHbqH2xak1ROSY=
|
||||||
|
modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg=
|
||||||
|
modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||||
|
modernc.org/z v1.7.3 h1:zDJf6iHjrnB+WRD88stbXokugjyc0/pB91ri1gO6LZY=
|
||||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||||
|
90
opds/opds.go
Normal file
90
opds/opds.go
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
// https://github.com/opds-community/libopds2-go/blob/master/opds1/opds1.go
|
||||||
|
package opds
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/xml"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Feed root element for acquisition or navigation feed
|
||||||
|
type Feed struct {
|
||||||
|
XMLName xml.Name `xml:"feed"`
|
||||||
|
ID string `xml:"id,omitempty",`
|
||||||
|
Title string `xml:"title,omitempty"`
|
||||||
|
Updated time.Time `xml:"updated,omitempty"`
|
||||||
|
Entries []Entry `xml:"entry,omitempty"`
|
||||||
|
Links []Link `xml:"link,omitempty"`
|
||||||
|
TotalResults int `xml:"totalResults,omitempty"`
|
||||||
|
ItemsPerPage int `xml:"itemsPerPage,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Link link to different resources
|
||||||
|
type Link struct {
|
||||||
|
Rel string `xml:"rel,attr"`
|
||||||
|
Href string `xml:"href,attr,omitempty"`
|
||||||
|
TypeLink string `xml:"type,attr"`
|
||||||
|
Title string `xml:"title,attr,omitempty"`
|
||||||
|
FacetGroup string `xml:"facetGroup,attr,omitempty"`
|
||||||
|
Count int `xml:"count,attr,omitempty"`
|
||||||
|
Price *Price `xml:"price,omitempty"`
|
||||||
|
IndirectAcquisition []IndirectAcquisition `xml:"indirectAcquisition"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Author represent the feed author or the entry author
|
||||||
|
type Author struct {
|
||||||
|
Name string `xml:"name"`
|
||||||
|
URI string `xml:"uri,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Entry an atom entry in the feed
|
||||||
|
type Entry struct {
|
||||||
|
Title string `xml:"title,omitempty"`
|
||||||
|
ID string `xml:"id,omitempty"`
|
||||||
|
Identifier string `xml:"identifier,omitempty"`
|
||||||
|
Updated *time.Time `xml:"updated,omitempty"`
|
||||||
|
Rights string `xml:"rights,omitempty"`
|
||||||
|
Publisher string `xml:"publisher,omitempty"`
|
||||||
|
Author []Author `xml:"author,omitempty"`
|
||||||
|
Language string `xml:"language,omitempty"`
|
||||||
|
Issued string `xml:"issued,omitempty"`
|
||||||
|
Published *time.Time `xml:"published,omitempty"`
|
||||||
|
Category []Category `xml:"category,omitempty"`
|
||||||
|
Links []Link `xml:"link,omitempty"`
|
||||||
|
Summary *Content `xml:"summary,omitempty"`
|
||||||
|
Content *Content `xml:"content,omitempty"`
|
||||||
|
Series []Serie `xml:"series,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Content content tag in an entry, the type will be html or text
|
||||||
|
type Content struct {
|
||||||
|
Content string `xml:",cdata"`
|
||||||
|
ContentType string `xml:"type,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Category represent the book category with scheme and term to machine
|
||||||
|
// handling
|
||||||
|
type Category struct {
|
||||||
|
Scheme string `xml:"scheme,attr"`
|
||||||
|
Term string `xml:"term,attr"`
|
||||||
|
Label string `xml:"label,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Price represent the book price
|
||||||
|
type Price struct {
|
||||||
|
CurrencyCode string `xml:"currencycode,attr,omitempty"`
|
||||||
|
Value float64 `xml:",cdata"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// IndirectAcquisition represent the link mostly for buying or borrowing
|
||||||
|
// a book
|
||||||
|
type IndirectAcquisition struct {
|
||||||
|
TypeAcquisition string `xml:"type,attr"`
|
||||||
|
IndirectAcquisition []IndirectAcquisition `xml:"indirectAcquisition"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serie store serie information from schema.org
|
||||||
|
type Serie struct {
|
||||||
|
Name string `xml:"name,attr,omitempty"`
|
||||||
|
URL string `xml:"url,attr,omitempty"`
|
||||||
|
Position float32 `xml:"position,attr,omitempty"`
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user