diff --git a/cmd/mangaGetter/develop.go b/cmd/mangaGetter/develop.go new file mode 100644 index 0000000..eed9a77 --- /dev/null +++ b/cmd/mangaGetter/develop.go @@ -0,0 +1,7 @@ +//go:build Develop + +package main + +func getDbPath() string { + return "db.sqlite" +} diff --git a/cmd/mangaGetter/main.go b/cmd/mangaGetter/main.go index 73a39f3..a4efa3e 100644 --- a/cmd/mangaGetter/main.go +++ b/cmd/mangaGetter/main.go @@ -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 diff --git a/cmd/mangaGetter/release.go b/cmd/mangaGetter/release.go new file mode 100644 index 0000000..265beae --- /dev/null +++ b/cmd/mangaGetter/release.go @@ -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 +} diff --git a/internal/database/database.go b/internal/database/database.go index f145369..fd40f53 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -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 } diff --git a/internal/provider/bato.go b/internal/provider/bato.go index 4574e98..7fc5db0 100644 --- a/internal/provider/bato.go +++ b/internal/provider/bato.go @@ -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(`
.*?Chapter (\d*)`) + 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) diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 7ff98c2..994cebd 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -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) } diff --git a/internal/server/handler.go b/internal/server/handler.go index a79a090..d32b36c 100644 --- a/internal/server/handler.go +++ b/internal/server/handler.go @@ -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 = "" diff --git a/internal/view/Views/menu.gohtml b/internal/view/Views/menu.gohtml index 8537db9..f93d9e2 100644 --- a/internal/view/Views/menu.gohtml +++ b/internal/view/Views/menu.gohtml @@ -138,7 +138,7 @@ {{.Title}} - {{.Number}} + {{.Number}} / {{.LastNumber}} {{.LastTime}} diff --git a/internal/view/viewmodels.go b/internal/view/viewmodels.go index 06b224d..254fd55 100644 --- a/internal/view/viewmodels.go +++ b/internal/view/viewmodels.go @@ -14,6 +14,7 @@ type MangaViewModel struct { ID int Title string Number int + LastNumber int LastTime string Url string ThumbnailUrl string