More database file info stuff

master
Noah Pederson 6 years ago
parent 8fae32d143
commit 4d985c5c7f
  1. 4
      .gitignore
  2. 2
      .idea/misc.xml
  3. 70
      database/database.go
  4. 11
      gocomics.go
  5. 24
      models/comics.go
  6. 31
      scanner/comicscanner.go

4
.gitignore vendored

@ -9,6 +9,7 @@
_obj
_test
comics
.images
# Architecture specific extensions/prefixes
*.[568vq]
@ -28,4 +29,5 @@ _testmain.go
*.mdb
*.key
*.pem
*.pem
*.txt

@ -17,7 +17,7 @@
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_3" default="false" assert-keyword="false" jdk-15="false" project-jdk-name="Go 1.6.2" project-jdk-type="Go SDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_3" default="false" assert-keyword="false" jdk-15="false" project-jdk-name="Go 1.6" project-jdk-type="Go SDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

@ -5,9 +5,15 @@ import (
"git.chiefnoah.tech/chiefnoah/gocomics/models"
_ "github.com/mattn/go-sqlite3"
"log"
"strings"
)
var db *sql.DB
//holds a reference to a database connection and a transaction used for large database processes
//like adding a shitton of comics ;P
type Dbhandler struct {
Transaction *sql.Tx
Db *sql.DB
}
func Init() {
@ -51,6 +57,7 @@ func Init() {
'ID' INTEGER PRIMARY KEY AUTOINCREMENT,
'RelativePath' TEXT NOT NULL,
'AbsolutePath' TEXT NOT NULL,
'FileName' TEXT NOT NULL,
'Hash' TEXT NOT NULL UNIQUE,
'Filesize' INTEGER DEFAULT 0
);`
@ -61,6 +68,7 @@ func Init() {
'IssueNumber' REAL DEFAULT 0.0,
'PageCount' INTEGER,
'ComicFileID' INTEGER,
'Hash' TEXT NOT NULL,
'Volume' TEXT,
'DateAdded' INTEGER DEFAULT 0,
'PublishDate' INTEGER,
@ -143,29 +151,59 @@ func Init() {
}
func AddComic(comic models.ComicInfo, file models.ComicFile) bool {
db, err := sql.Open("sqlite3", "./library.mdb")
if err != nil {
log.Fatal("Unable to open database: ", err)
}
INSERT_COMIC_FILE_INFO := `INSERT INTO ComicFile(RelativePath, AbsolutePath, Hash, Filesize) VALUES(?, ?, ?, ?)`
func(h *Dbhandler) AddComic(comic models.ComicInfo, file models.ComicFile) bool {
INSERT_COMIC_FILE_INFO := `INSERT INTO ComicFile(RelativePath, AbsolutePath, FileName, Hash, Filesize) VALUES(?, ?, ?, ?, ?)`
tx, err := db.Begin()
stmt, err := h.Transaction.Prepare(INSERT_COMIC_FILE_INFO)
defer stmt.Close()
if err != nil {
log.Fatal(err)
}
stmt, err := tx.Prepare(INSERT_COMIC_FILE_INFO)
res, _ := stmt.Exec(file.RelativePath, file.AbsolutePath, file.Hash, file.FileSize)
_, err = stmt.Exec(file.RelativePath, file.AbsolutePath, file.FileName, file.Hash, file.FileSize)
if err != nil {
log.Fatal(err)
//If the unique contraint on the HASH field fails, we just update the data
if strings.Contains(err.Error(), "UNIQUE") {
log.Print("File already in database, updating to latest info...")
sql := `UPDATE ComicFile SET RelativePath = ?, AbsolutePath = ?, FileName = ? WHERE Hash = ?`
st, err := h.Transaction.Prepare(sql)
defer st.Close()
if err != nil {
log.Fatal("Unable to prepare statement: ", err)
}
log.Printf("Updating with:%+v\n", file)
_, err = st.Exec(file.RelativePath, file.AbsolutePath, file.FileName, file.Hash)
if err != nil {
log.Fatal("error updating: ", err)
}
} else {
log.Fatal("Error inserting: ", err)
}
}
log.Printf("Results:%x", res)
defer stmt.Close()
//log.Printf("Results:%+v\n", res)
return false
}
//Creates a new dbhandler object for running a transaction
func BeginTransaction() *Dbhandler {
var handler Dbhandler
db, err := sql.Open("sqlite3", "./library.mdb")
if err != nil {
log.Fatal("Unable to open database: ", err)
}
handler.Db = db
tx, err := db.Begin()
handler.Transaction = tx
return &handler
}
func(h *Dbhandler) FinishTransaction() error {
err := h.Transaction.Commit()
defer h.Db.Close()
return err
}

@ -6,17 +6,24 @@ import (
"git.chiefnoah.tech/chiefnoah/gocomics/scanner"
"git.chiefnoah.tech/chiefnoah/gocomics/database"
"log"
"os"
)
//Let's get started!
func main() {
f, err := os.OpenFile("log.txt", os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666)
if err != nil {
log.Fatal("Can't write log file! D:")
}
defer f.Close()
log.SetOutput(f)
database.Init()
config := &config.ApiConfig{
false, false, ":3008", ":3000",
}
comicscanner.Scan("./comics")
go comicscanner.Scan(`F:\eBooks\eComics\Manga`)
web.Start(config)
}

@ -4,7 +4,8 @@ package models
MGA database structures used for internal stuff
*/
type ComicInfo struct {
ID int `json:"id"sql:"id"`
ID int `json:"id"`
Hash string `json:"hash"`
Title string `json:"title"`
Series string `json:"series"`
IssueNumber float32 `json:"issue_number"`
@ -12,8 +13,8 @@ type ComicInfo struct {
Credits credit `json:"credits"`
Volume string `json:"volume"`
Genres []string `json:"genres"`
DateAdded int64 `json:"date_added"`
PublishDate int64 `json:"publish_date"`
DateAdded int64 `json:"date_added"`
PublishDate int64 `json:"publish_date"`
Synopsis string `json:"synopsis"`
Characters []string `json:"characters"`
Rating float32 `json:"rating"`
@ -26,8 +27,9 @@ type ComicFile struct {
ID int `json:"id"`
RelativePath string `json:"relative_path"`
AbsolutePath string `json:"absolute_path"`
FileName string `json:"file_name"`
Hash string `json:"hash"` //MD5 hash
FileSize int64 `json:"filesize"`
FileSize int64 `json:"filesize"`
}
type credit struct {
@ -45,13 +47,13 @@ type User struct {
}
type UserProgress struct {
ID int `json:"id"`
ComicInfoID int `json:"comic_info_id"`
Read bool `json:"read"`
Completed bool `json:"completed"`
DateLastRead int64 `json:"date_last_read"`
DateCompleted int64 `json:"date_completed"`
LastReadPage int `json:"last_read_page"`
ID int `json:"id"`
ComicInfoID int `json:"comic_info_id"`
Read bool `json:"read"`
Completed bool `json:"completed"`
DateLastRead int64 `json:"date_last_read"`
DateCompleted int64 `json:"date_completed"`
LastReadPage int `json:"last_read_page"`
}
/*

@ -12,14 +12,22 @@ import (
"log"
"git.chiefnoah.tech/chiefnoah/gocomics/models"
"git.chiefnoah.tech/chiefnoah/gocomics/database"
"encoding/hex"
)
var root string
var dbhandler *database.Dbhandler
func Scan(f string) error {
root = f
dbhandler = database.BeginTransaction()
defer dbhandler.FinishTransaction()
err := filepath.Walk(f, visit)
if err != nil {
fmt.Printf("walk error: %v\n", err)
return err
}
log.Print("DONE WALKING!")
return nil
}
@ -27,7 +35,7 @@ func visit(p string, f os.FileInfo, e error) error {
fmt.Printf("Visited: %s\n", p)
if strings.EqualFold(path.Ext(f.Name()), ".cbz") || strings.EqualFold(path.Ext(f.Name()), ".cbr") {
fmt.Printf("Found cbz file!\n")
//fmt.Printf("Found cbz file!\n")
//TODO: parse comic info
file, err := ioutil.ReadFile(p)
@ -37,16 +45,25 @@ func visit(p string, f os.FileInfo, e error) error {
}
var comicfile models.ComicFile
//TODO: somehow get comic info based on filename/directory structure
//TODO: generate cover images using hash
checksum := md5.Sum(file)
n := len(checksum)
comicfile.Hash = string(checksum[:n])
comicfile.Hash = hex.EncodeToString(checksum[:n])
comicfile.FileSize = int64(f.Size())
comicfile.AbsolutePath = p
comicfile.RelativePath = ""
rel, _ := filepath.Rel(root, p)
comicfile.RelativePath = filepath.ToSlash(rel)
comicfile.FileName = f.Name()
if !path.IsAbs(root) {
ab, err := filepath.Abs(p)
if err != nil {
log.Print("Couldn't get relative path: ", err)
}
comicfile.AbsolutePath = filepath.ToSlash(ab)
}
fmt.Printf("MD5: %x\n", comicfile.Hash)
database.AddComic(models.ComicInfo{}, comicfile)
//fmt.Printf("MD5: %s\n", comicfile.Hash)
dbhandler.AddComic(models.ComicInfo{}, comicfile)
}
return nil

Loading…
Cancel
Save