Added Last Chapter functionality to see how many more chapters you have, also kinda works as update Status bar
changed it to only load latest chapter instead of all chapters for manga Added develop and release db from different locations Added stopwatch for future performance improvement metrics
This commit is contained in:
7
cmd/mangaGetter/develop.go
Normal file
7
cmd/mangaGetter/develop.go
Normal file
@@ -0,0 +1,7 @@
|
||||
//go:build Develop
|
||||
|
||||
package main
|
||||
|
||||
func getDbPath() string {
|
||||
return "db.sqlite"
|
||||
}
|
||||
@@ -9,44 +9,15 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
dir, err := os.UserCacheDir()
|
||||
if err != nil {
|
||||
fmt.Println(nil)
|
||||
return
|
||||
}
|
||||
|
||||
dirPath := filepath.Join(dir, "MangaGetter")
|
||||
filePath := filepath.Join(dirPath, "db.sqlite")
|
||||
|
||||
if _, err := os.Stat(dirPath); os.IsNotExist(err) {
|
||||
err = os.Mkdir(dirPath, os.ModePerm)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
||||
f, err := os.Create(filePath)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
err = f.Close()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
filePath := getDbPath()
|
||||
|
||||
db := database.NewDatabase(filePath, true)
|
||||
err = db.Open()
|
||||
err := db.Open()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
|
||||
38
cmd/mangaGetter/release.go
Normal file
38
cmd/mangaGetter/release.go
Normal file
@@ -0,0 +1,38 @@
|
||||
//go:build !Develop
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func getDbPath() string {
|
||||
dir, err := os.UserCacheDir()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
dirPath := filepath.Join(dir, "MangaGetter")
|
||||
filePath := filepath.Join(dirPath, "db.sqlite")
|
||||
|
||||
if _, err := os.Stat(dirPath); os.IsNotExist(err) {
|
||||
err = os.Mkdir(dirPath, os.ModePerm)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
||||
f, err := os.Create(filePath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = f.Close()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
return filePath
|
||||
}
|
||||
@@ -195,28 +195,15 @@ func (dbMgr *Manager) load() error {
|
||||
return err
|
||||
}
|
||||
manga.Thumbnail = bytes.NewBuffer(thumbnail)
|
||||
dbMgr.Mangas[manga.Id] = &manga
|
||||
}
|
||||
|
||||
rows, err = db.Query("SELECT * FROM Chapter")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for rows.Next() {
|
||||
latestChapter := db.QueryRow("SELECT Id, Url, Name, Number, TimeStampUnixEpoch FROM Chapter where MangaID = ? ORDER BY TimeStampUnixEpoch desc LIMIT 1", manga.Id)
|
||||
chapter := Chapter{}
|
||||
var mangaID int
|
||||
if err = rows.Scan(&chapter.Id, &mangaID, &chapter.Url, &chapter.Name, &chapter.Number, &chapter.TimeStampUnix); err != nil {
|
||||
if err = latestChapter.Scan(&chapter.Id, &chapter.Url, &chapter.Name, &chapter.Number, &chapter.TimeStampUnix); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
chapter.Manga = dbMgr.Mangas[mangaID]
|
||||
if dbMgr.Mangas[mangaID].LatestChapter == nil || dbMgr.Mangas[mangaID].LatestChapter.TimeStampUnix < chapter.TimeStampUnix {
|
||||
dbMgr.Mangas[mangaID].LatestChapter = &chapter
|
||||
}
|
||||
|
||||
dbMgr.Chapters[chapter.Id] = &chapter
|
||||
manga.LatestChapter = &chapter
|
||||
dbMgr.Mangas[manga.Id] = &manga
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -109,9 +109,24 @@ func (b *Bato) GetTitleIdAndChapterId(url string) (titleId int, chapterId int, e
|
||||
return t, c, err
|
||||
}
|
||||
|
||||
//func (b *Bato) GetChapterList(url string) (chapterIds []int, err error) {
|
||||
//
|
||||
//}
|
||||
func (b *Bato) GetChapterList(subUrl string) (subUrls []string, err error) {
|
||||
reg, err := regexp.Compile(`<div class="space-x-1">.*?<a href="(.*?)" .*?>Chapter (\d*)</a>`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
html, err := b.GetHtml(subUrl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
subUrls = make([]string, 0)
|
||||
matches := reg.FindAllStringSubmatch(html, -1)
|
||||
for _, match := range matches {
|
||||
subUrls = append(subUrls, match[1])
|
||||
}
|
||||
return subUrls, nil
|
||||
}
|
||||
|
||||
func (b *Bato) GetThumbnail(subUrl string) (thumbnailUrl string, err error) {
|
||||
url := fmt.Sprintf("https://bato.to/title/%s", subUrl)
|
||||
|
||||
@@ -8,4 +8,5 @@ type Provider interface {
|
||||
GetTitleAndChapter(url string) (title string, chapter string, err error)
|
||||
GetTitleIdAndChapterId(url string) (titleId int, chapterId int, err error)
|
||||
GetThumbnail(mangaId string) (thumbnailUrl string, err error)
|
||||
GetChapterList(url string) (urls []string, err error)
|
||||
}
|
||||
|
||||
@@ -52,19 +52,56 @@ func (s *Server) HandleMenu(w http.ResponseWriter, _ *http.Request) {
|
||||
mangaViewModels := make([]view.MangaViewModel, l)
|
||||
counter := 0
|
||||
|
||||
n := time.Now().UnixNano()
|
||||
|
||||
var thumbNs int64 = 0
|
||||
var titNs int64 = 0
|
||||
|
||||
//TODO: Change all this to be more performant
|
||||
for _, manga := range all {
|
||||
title := cases.Title(language.English, cases.Compact).String(strings.Replace(manga.Title, "-", " ", -1))
|
||||
|
||||
t1 := time.Now().UnixNano()
|
||||
|
||||
thumbnail, err := s.LoadThumbnail(manga.Id)
|
||||
//TODO: Add default picture instead of not showing Manga at all
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
manga.Thumbnail = s.ImageBuffers[thumbnail]
|
||||
|
||||
t2 := time.Now().UnixNano()
|
||||
|
||||
thumbNs += t2 - t1
|
||||
|
||||
t1 = time.Now().UnixNano()
|
||||
// This is very slow
|
||||
l, err := s.Provider.GetChapterList("/title/" + strconv.Itoa(manga.Id))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
le := len(l)
|
||||
_, c, err := s.Provider.GetTitleAndChapter(l[le-1])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
chapterNumberStr := strings.Replace(c, "ch_", "", 1)
|
||||
|
||||
i, err := strconv.Atoi(chapterNumberStr)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
t2 = time.Now().UnixNano()
|
||||
|
||||
titNs += t2 - t1
|
||||
|
||||
mangaViewModels[counter] = view.MangaViewModel{
|
||||
ID: manga.Id,
|
||||
Title: title,
|
||||
Number: manga.LatestChapter.Number,
|
||||
ID: manga.Id,
|
||||
Title: title,
|
||||
Number: manga.LatestChapter.Number,
|
||||
LastNumber: i,
|
||||
// I Hate this time Format... 15 = hh, 04 = mm, 02 = DD, 01 = MM, 06 == YY
|
||||
LastTime: time.Unix(manga.TimeStampUnix, 0).Format("15:04 (02-01-06)"),
|
||||
Url: manga.LatestChapter.Url,
|
||||
@@ -73,10 +110,21 @@ func (s *Server) HandleMenu(w http.ResponseWriter, _ *http.Request) {
|
||||
counter++
|
||||
}
|
||||
|
||||
fmt.Printf("Loading Thumbnails took %d ms\n", (thumbNs)/1000000)
|
||||
fmt.Printf("Loading latest Chapter took %d ms\n", (titNs)/1000000)
|
||||
|
||||
nex := time.Now().UnixNano()
|
||||
fmt.Printf("Creating Viewmodels took %d ms\n", (nex-n)/1000000)
|
||||
|
||||
n = time.Now().UnixNano()
|
||||
|
||||
slices.SortStableFunc(mangaViewModels, func(a, b view.MangaViewModel) int {
|
||||
return cmp.Compare(a.Title, b.Title)
|
||||
})
|
||||
|
||||
nex = time.Now().UnixNano()
|
||||
fmt.Printf("Sorting took %d ms\n", (nex-n)/1000000)
|
||||
|
||||
menuViewModel := view.MenuViewModel{
|
||||
Mangas: mangaViewModels,
|
||||
}
|
||||
@@ -117,7 +165,31 @@ func (s *Server) HandleExit(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("Cleaned out of scope Last")
|
||||
|
||||
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
|
||||
|
||||
go func() {
|
||||
s.Mutex.Lock()
|
||||
if s.PrevViewModel != nil {
|
||||
for _, img := range s.PrevViewModel.Images {
|
||||
delete(s.ImageBuffers, img.Path)
|
||||
}
|
||||
}
|
||||
if s.CurrViewModel != nil {
|
||||
|
||||
for _, img := range s.CurrViewModel.Images {
|
||||
delete(s.ImageBuffers, img.Path)
|
||||
}
|
||||
}
|
||||
if s.NextViewModel != nil {
|
||||
|
||||
for _, img := range s.NextViewModel.Images {
|
||||
delete(s.ImageBuffers, img.Path)
|
||||
}
|
||||
}
|
||||
s.Mutex.Unlock()
|
||||
}()
|
||||
}
|
||||
|
||||
func (s *Server) HandleCurrent(w http.ResponseWriter, _ *http.Request) {
|
||||
@@ -279,9 +351,6 @@ func (s *Server) HandleNewQuery(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
url := fmt.Sprintf("/title/%s", sub)
|
||||
|
||||
s.Mutex.Lock()
|
||||
s.ImageBuffers = make(map[string]*bytes.Buffer)
|
||||
s.Mutex.Unlock()
|
||||
s.CurrSubUrl = url
|
||||
s.PrevSubUrl = ""
|
||||
s.NextSubUrl = ""
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
</a>
|
||||
</td>
|
||||
<td class="table-left">{{.Title}}</td>
|
||||
<td>{{.Number}}</td>
|
||||
<td>{{.Number}} / {{.LastNumber}}</td>
|
||||
<td>{{.LastTime}}</td>
|
||||
<td>
|
||||
<a href="/new/{{.Url}}}">
|
||||
|
||||
@@ -14,6 +14,7 @@ type MangaViewModel struct {
|
||||
ID int
|
||||
Title string
|
||||
Number int
|
||||
LastNumber int
|
||||
LastTime string
|
||||
Url string
|
||||
ThumbnailUrl string
|
||||
|
||||
Reference in New Issue
Block a user