Changed Project structure, added Hot Reload of gohtml files for Develop and embedding of gohtml files for Release
This commit is contained in:
@@ -7,41 +7,24 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"mangaGetter/internal/database"
|
||||||
|
"mangaGetter/internal/provider"
|
||||||
|
"mangaGetter/internal/server"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Image struct {
|
|
||||||
Path string
|
|
||||||
Index int
|
|
||||||
}
|
|
||||||
|
|
||||||
type ImageViewModel struct {
|
|
||||||
Title string
|
|
||||||
Images []Image
|
|
||||||
}
|
|
||||||
|
|
||||||
type MangaViewModel struct {
|
|
||||||
Title string
|
|
||||||
Number int
|
|
||||||
LastTime string
|
|
||||||
Url string
|
|
||||||
}
|
|
||||||
|
|
||||||
type MenuViewModel struct {
|
|
||||||
Mangas []MangaViewModel
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
db := NewDatabase("db.sqlite", true)
|
db := database.NewDatabase("db.sqlite", true)
|
||||||
err := db.Open()
|
err := db.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
server := Server{
|
s := server.Server{
|
||||||
ImageBuffers: make(map[string]*bytes.Buffer),
|
ImageBuffers: make(map[string]*bytes.Buffer),
|
||||||
NextReady: make(chan bool),
|
NextReady: make(chan bool),
|
||||||
PrevReady: make(chan bool),
|
PrevReady: make(chan bool),
|
||||||
Provider: &Bato{},
|
Provider: &provider.Bato{},
|
||||||
DbMgr: &db,
|
DbMgr: &db,
|
||||||
Mutex: &sync.Mutex{},
|
Mutex: &sync.Mutex{},
|
||||||
}
|
}
|
||||||
@@ -55,13 +38,13 @@ func main() {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
http.HandleFunc("/", server.HandleMenu)
|
http.HandleFunc("/", s.HandleMenu)
|
||||||
http.HandleFunc("/new/title/{title}/{chapter}", server.HandleNew)
|
http.HandleFunc("/new/title/{title}/{chapter}", s.HandleNew)
|
||||||
http.HandleFunc("/current/", server.HandleCurrent)
|
http.HandleFunc("/current/", s.HandleCurrent)
|
||||||
http.HandleFunc("/img/{url}/", server.HandleImage)
|
http.HandleFunc("/img/{url}/", s.HandleImage)
|
||||||
http.HandleFunc("POST /next", server.HandleNext)
|
http.HandleFunc("POST /next", s.HandleNext)
|
||||||
http.HandleFunc("POST /prev", server.HandlePrev)
|
http.HandleFunc("POST /prev", s.HandlePrev)
|
||||||
http.HandleFunc("POST /exit", server.HandleExit)
|
http.HandleFunc("POST /exit", s.HandleExit)
|
||||||
|
|
||||||
fmt.Println("Server starting...")
|
fmt.Println("Server starting...")
|
||||||
err = http.ListenAndServe(":8000", nil)
|
err = http.ListenAndServe(":8000", nil)
|
||||||
@@ -71,7 +54,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Close(db *DatabaseManager) {
|
func Close(db *database.DatabaseManager) {
|
||||||
fmt.Println("Attempting to save and close DB")
|
fmt.Println("Attempting to save and close DB")
|
||||||
err := db.Save()
|
err := db.Save()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package main
|
package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
@@ -30,7 +30,7 @@ type DatabaseManager struct {
|
|||||||
ConnectionString string
|
ConnectionString string
|
||||||
db *sql.DB
|
db *sql.DB
|
||||||
|
|
||||||
rw *sync.Mutex
|
Rw *sync.Mutex
|
||||||
Mangas map[int]*Manga
|
Mangas map[int]*Manga
|
||||||
Chapters map[int]*Chapter
|
Chapters map[int]*Chapter
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ type DatabaseManager struct {
|
|||||||
func NewDatabase(connectionString string, createIfNotExists bool) DatabaseManager {
|
func NewDatabase(connectionString string, createIfNotExists bool) DatabaseManager {
|
||||||
return DatabaseManager{
|
return DatabaseManager{
|
||||||
ConnectionString: connectionString,
|
ConnectionString: connectionString,
|
||||||
rw: &sync.Mutex{},
|
Rw: &sync.Mutex{},
|
||||||
Mangas: make(map[int]*Manga),
|
Mangas: make(map[int]*Manga),
|
||||||
Chapters: make(map[int]*Chapter),
|
Chapters: make(map[int]*Chapter),
|
||||||
CreateIfNotExists: createIfNotExists,
|
CreateIfNotExists: createIfNotExists,
|
||||||
@@ -78,8 +78,8 @@ func (dbMgr *DatabaseManager) Close() error {
|
|||||||
func (dbMgr *DatabaseManager) Save() error {
|
func (dbMgr *DatabaseManager) Save() error {
|
||||||
db := dbMgr.db
|
db := dbMgr.db
|
||||||
|
|
||||||
dbMgr.rw.Lock()
|
dbMgr.Rw.Lock()
|
||||||
defer dbMgr.rw.Unlock()
|
defer dbMgr.Rw.Unlock()
|
||||||
for _, m := range dbMgr.Mangas {
|
for _, m := range dbMgr.Mangas {
|
||||||
count := 0
|
count := 0
|
||||||
err := db.QueryRow("SELECT COUNT(*) FROM Manga where ID = ?", m.Id).Scan(&count)
|
err := db.QueryRow("SELECT COUNT(*) FROM Manga where ID = ?", m.Id).Scan(&count)
|
||||||
@@ -134,8 +134,8 @@ func (dbMgr *DatabaseManager) createDatabaseIfNotExists() error {
|
|||||||
func (dbMgr *DatabaseManager) load() error {
|
func (dbMgr *DatabaseManager) load() error {
|
||||||
db := dbMgr.db
|
db := dbMgr.db
|
||||||
|
|
||||||
dbMgr.rw.Lock()
|
dbMgr.Rw.Lock()
|
||||||
defer dbMgr.rw.Unlock()
|
defer dbMgr.Rw.Unlock()
|
||||||
|
|
||||||
rows, err := db.Query("SELECT * FROM Manga")
|
rows, err := db.Query("SELECT * FROM Manga")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package main
|
package provider
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
@@ -6,15 +6,9 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Provider interface {
|
|
||||||
GetImageList(html string) (imageUrls []string, err error)
|
|
||||||
GetHtml(url string) (html string, err error)
|
|
||||||
GetNext(html string) (url string, err error)
|
|
||||||
GetPrev(html string) (url string, err error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Bato struct{}
|
type Bato struct{}
|
||||||
|
|
||||||
func (b *Bato) GetImageList(html string) ([]string, error) {
|
func (b *Bato) GetImageList(html string) ([]string, error) {
|
||||||
@@ -81,3 +75,36 @@ func (b *Bato) GetPrev(html string) (subUrl string, err error) {
|
|||||||
|
|
||||||
return match[1], err
|
return match[1], err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Bato) GetTitleAndChapter(url string) (title string, chapter string, err error) {
|
||||||
|
reg, err := regexp.Compile(`/title/\d*-(.*?)/\d*-(.*)`)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
matches := reg.FindAllStringSubmatch(url, -1)
|
||||||
|
if len(matches) <= 0 {
|
||||||
|
return "", "", errors.New("no title or chapter found")
|
||||||
|
}
|
||||||
|
|
||||||
|
return matches[0][1], matches[0][2], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bato) GetTitleIdAndChapterId(url string) (titleId int, chapterId int, err error) {
|
||||||
|
reg, err := regexp.Compile(`/title/(\d*)-.*?/(\d*)-.*`)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
matches := reg.FindAllStringSubmatch(url, -1)
|
||||||
|
if len(matches) <= 0 {
|
||||||
|
return 0, 0, errors.New("no title or chapter found")
|
||||||
|
}
|
||||||
|
t, err := strconv.Atoi(matches[0][1])
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
c, err := strconv.Atoi(matches[0][2])
|
||||||
|
|
||||||
|
return t, c, err
|
||||||
|
}
|
||||||
10
internal/provider/provider.go
Normal file
10
internal/provider/provider.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package provider
|
||||||
|
|
||||||
|
type Provider interface {
|
||||||
|
GetImageList(html string) (imageUrls []string, err error)
|
||||||
|
GetHtml(url string) (html string, err error)
|
||||||
|
GetNext(html string) (url string, err error)
|
||||||
|
GetPrev(html string) (url string, err error)
|
||||||
|
GetTitleAndChapter(url string) (title string, chapter string, err error)
|
||||||
|
GetTitleIdAndChapterId(url string) (titleId int, chapterId int, err error)
|
||||||
|
}
|
||||||
@@ -1,10 +1,14 @@
|
|||||||
package main
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"golang.org/x/text/language"
|
"golang.org/x/text/language"
|
||||||
"html/template"
|
"html/template"
|
||||||
|
"io"
|
||||||
|
"mangaGetter/internal/database"
|
||||||
|
"mangaGetter/internal/provider"
|
||||||
|
"mangaGetter/internal/view"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -16,9 +20,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
PrevViewModel *ImageViewModel
|
PrevViewModel *view.ImageViewModel
|
||||||
CurrViewModel *ImageViewModel
|
CurrViewModel *view.ImageViewModel
|
||||||
NextViewModel *ImageViewModel
|
NextViewModel *view.ImageViewModel
|
||||||
|
|
||||||
ImageBuffers map[string]*bytes.Buffer
|
ImageBuffers map[string]*bytes.Buffer
|
||||||
Mutex *sync.Mutex
|
Mutex *sync.Mutex
|
||||||
@@ -27,12 +31,12 @@ type Server struct {
|
|||||||
CurrSubUrl string
|
CurrSubUrl string
|
||||||
PrevSubUrl string
|
PrevSubUrl string
|
||||||
|
|
||||||
Provider Provider
|
Provider provider.Provider
|
||||||
|
|
||||||
IsFirst bool
|
IsFirst bool
|
||||||
IsLast bool
|
IsLast bool
|
||||||
|
|
||||||
DbMgr *DatabaseManager
|
DbMgr *database.DatabaseManager
|
||||||
|
|
||||||
// I'm not even sure if this helps.
|
// I'm not even sure if this helps.
|
||||||
// If you press next and then prev too fast you still lock yourself out
|
// If you press next and then prev too fast you still lock yourself out
|
||||||
@@ -62,7 +66,7 @@ func (s *Server) HandleNext(w http.ResponseWriter, r *http.Request) {
|
|||||||
fmt.Println("Received Next")
|
fmt.Println("Received Next")
|
||||||
|
|
||||||
if s.PrevViewModel != nil {
|
if s.PrevViewModel != nil {
|
||||||
go func(viewModel ImageViewModel, s *Server) {
|
go func(viewModel view.ImageViewModel, s *Server) {
|
||||||
s.Mutex.Lock()
|
s.Mutex.Lock()
|
||||||
for _, img := range viewModel.Images {
|
for _, img := range viewModel.Images {
|
||||||
delete(s.ImageBuffers, img.Path)
|
delete(s.ImageBuffers, img.Path)
|
||||||
@@ -109,7 +113,7 @@ func (s *Server) LoadNext() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
title, chapter, err := getTitleAndChapter(next)
|
title, chapter, err := s.Provider.GetTitleAndChapter(next)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
title = "Unknown"
|
title = "Unknown"
|
||||||
chapter = "ch_?"
|
chapter = "ch_?"
|
||||||
@@ -117,7 +121,7 @@ func (s *Server) LoadNext() {
|
|||||||
|
|
||||||
full := strings.Replace(title, "-", " ", -1) + " - " + strings.Replace(chapter, "_", " ", -1)
|
full := strings.Replace(title, "-", " ", -1) + " - " + strings.Replace(chapter, "_", " ", -1)
|
||||||
|
|
||||||
s.NextViewModel = &ImageViewModel{Images: imagesNext, Title: full}
|
s.NextViewModel = &view.ImageViewModel{Images: imagesNext, Title: full}
|
||||||
|
|
||||||
s.NextSubUrl = next
|
s.NextSubUrl = next
|
||||||
fmt.Println("Loaded next")
|
fmt.Println("Loaded next")
|
||||||
@@ -147,7 +151,7 @@ func (s *Server) LoadPrev() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
title, chapter, err := getTitleAndChapter(prev)
|
title, chapter, err := s.Provider.GetTitleAndChapter(prev)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
title = "Unknown"
|
title = "Unknown"
|
||||||
chapter = "ch_?"
|
chapter = "ch_?"
|
||||||
@@ -155,7 +159,7 @@ func (s *Server) LoadPrev() {
|
|||||||
|
|
||||||
full := strings.Replace(title, "-", " ", -1) + " - " + strings.Replace(chapter, "_", " ", -1)
|
full := strings.Replace(title, "-", " ", -1) + " - " + strings.Replace(chapter, "_", " ", -1)
|
||||||
|
|
||||||
s.PrevViewModel = &ImageViewModel{Images: imagesNext, Title: full}
|
s.PrevViewModel = &view.ImageViewModel{Images: imagesNext, Title: full}
|
||||||
|
|
||||||
s.PrevSubUrl = prev
|
s.PrevSubUrl = prev
|
||||||
fmt.Println("Loaded prev")
|
fmt.Println("Loaded prev")
|
||||||
@@ -165,7 +169,7 @@ func (s *Server) LoadPrev() {
|
|||||||
func (s *Server) HandlePrev(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) HandlePrev(w http.ResponseWriter, r *http.Request) {
|
||||||
fmt.Println("Received Prev")
|
fmt.Println("Received Prev")
|
||||||
if s.NextViewModel != nil {
|
if s.NextViewModel != nil {
|
||||||
go func(viewModel ImageViewModel, s *Server) {
|
go func(viewModel view.ImageViewModel, s *Server) {
|
||||||
s.Mutex.Lock()
|
s.Mutex.Lock()
|
||||||
for _, img := range viewModel.Images {
|
for _, img := range viewModel.Images {
|
||||||
delete(s.ImageBuffers, img.Path)
|
delete(s.ImageBuffers, img.Path)
|
||||||
@@ -188,22 +192,22 @@ func (s *Server) HandlePrev(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) HandleCurrent(w http.ResponseWriter, _ *http.Request) {
|
func (s *Server) HandleCurrent(w http.ResponseWriter, _ *http.Request) {
|
||||||
tmpl := template.Must(template.ParseFiles("viewer.gohtml"))
|
tmpl := template.Must(view.GetViewTemplate(view.Viewer))
|
||||||
|
|
||||||
s.DbMgr.rw.Lock()
|
s.DbMgr.Rw.Lock()
|
||||||
defer s.DbMgr.rw.Unlock()
|
defer s.DbMgr.Rw.Unlock()
|
||||||
|
|
||||||
mangaId, chapterId, err := getMangaIdAndChapterId(s.CurrSubUrl)
|
mangaId, chapterId, err := s.Provider.GetTitleIdAndChapterId(s.CurrSubUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
} else {
|
} else {
|
||||||
title, chapter, err := getTitleAndChapter(s.CurrSubUrl)
|
title, chapter, err := s.Provider.GetTitleAndChapter(s.CurrSubUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
} else {
|
} else {
|
||||||
var manga *Manga
|
var manga *database.Manga
|
||||||
if s.DbMgr.Mangas[mangaId] == nil {
|
if s.DbMgr.Mangas[mangaId] == nil {
|
||||||
manga = &Manga{
|
manga = &database.Manga{
|
||||||
Id: mangaId,
|
Id: mangaId,
|
||||||
Title: title,
|
Title: title,
|
||||||
TimeStampUnix: time.Now().Unix(),
|
TimeStampUnix: time.Now().Unix(),
|
||||||
@@ -222,7 +226,7 @@ func (s *Server) HandleCurrent(w http.ResponseWriter, _ *http.Request) {
|
|||||||
number = 0
|
number = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
s.DbMgr.Chapters[chapterId] = &Chapter{
|
s.DbMgr.Chapters[chapterId] = &database.Chapter{
|
||||||
Id: chapterId,
|
Id: chapterId,
|
||||||
Manga: manga,
|
Manga: manga,
|
||||||
Url: s.CurrSubUrl,
|
Url: s.CurrSubUrl,
|
||||||
@@ -270,7 +274,7 @@ func (s *Server) LoadCurr() {
|
|||||||
|
|
||||||
imagesCurr, err := s.AppendImagesToBuf(html)
|
imagesCurr, err := s.AppendImagesToBuf(html)
|
||||||
|
|
||||||
title, chapter, err := getTitleAndChapter(s.CurrSubUrl)
|
title, chapter, err := s.Provider.GetTitleAndChapter(s.CurrSubUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
title = "Unknown"
|
title = "Unknown"
|
||||||
chapter = "ch_?"
|
chapter = "ch_?"
|
||||||
@@ -278,17 +282,17 @@ func (s *Server) LoadCurr() {
|
|||||||
|
|
||||||
full := strings.Replace(title, "-", " ", -1) + " - " + strings.Replace(chapter, "_", " ", -1)
|
full := strings.Replace(title, "-", " ", -1) + " - " + strings.Replace(chapter, "_", " ", -1)
|
||||||
|
|
||||||
s.CurrViewModel = &ImageViewModel{Images: imagesCurr, Title: full}
|
s.CurrViewModel = &view.ImageViewModel{Images: imagesCurr, Title: full}
|
||||||
fmt.Println("Loaded current")
|
fmt.Println("Loaded current")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) AppendImagesToBuf(html string) ([]Image, error) {
|
func (s *Server) AppendImagesToBuf(html string) ([]view.Image, error) {
|
||||||
imgList, err := s.Provider.GetImageList(html)
|
imgList, err := s.Provider.GetImageList(html)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
images := make([]Image, len(imgList))
|
images := make([]view.Image, len(imgList))
|
||||||
|
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
for i, url := range imgList {
|
for i, url := range imgList {
|
||||||
@@ -302,7 +306,7 @@ func (s *Server) AppendImagesToBuf(html string) ([]Image, error) {
|
|||||||
s.Mutex.Lock()
|
s.Mutex.Lock()
|
||||||
s.ImageBuffers[name] = buf
|
s.ImageBuffers[name] = buf
|
||||||
s.Mutex.Unlock()
|
s.Mutex.Unlock()
|
||||||
images[i] = Image{Path: name, Index: i}
|
images[i] = view.Image{Path: name, Index: i}
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}(i, url, &wg)
|
}(i, url, &wg)
|
||||||
}
|
}
|
||||||
@@ -311,21 +315,21 @@ func (s *Server) AppendImagesToBuf(html string) ([]Image, error) {
|
|||||||
return images, nil
|
return images, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) HandleMenu(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) HandleMenu(w http.ResponseWriter, _ *http.Request) {
|
||||||
tmpl := template.Must(template.ParseFiles("menu.gohtml"))
|
tmpl := template.Must(view.GetViewTemplate(view.Menu))
|
||||||
|
|
||||||
s.DbMgr.rw.Lock()
|
s.DbMgr.Rw.Lock()
|
||||||
defer s.DbMgr.rw.Unlock()
|
defer s.DbMgr.Rw.Unlock()
|
||||||
|
|
||||||
all := s.DbMgr.Mangas
|
all := s.DbMgr.Mangas
|
||||||
l := len(all)
|
l := len(all)
|
||||||
mangaViewModels := make([]MangaViewModel, l)
|
mangaViewModels := make([]view.MangaViewModel, l)
|
||||||
counter := 0
|
counter := 0
|
||||||
|
|
||||||
for _, manga := range all {
|
for _, manga := range all {
|
||||||
title := cases.Title(language.English, cases.Compact).String(strings.Replace(manga.Title, "-", " ", -1))
|
title := cases.Title(language.English, cases.Compact).String(strings.Replace(manga.Title, "-", " ", -1))
|
||||||
|
|
||||||
mangaViewModels[counter] = MangaViewModel{
|
mangaViewModels[counter] = view.MangaViewModel{
|
||||||
Title: title,
|
Title: title,
|
||||||
Number: manga.LatestChapter.Number,
|
Number: manga.LatestChapter.Number,
|
||||||
// I Hate this time Format... 15 = hh, 04 = mm, 02 = DD, 01 = MM, 06 == YY
|
// I Hate this time Format... 15 = hh, 04 = mm, 02 = DD, 01 = MM, 06 == YY
|
||||||
@@ -335,7 +339,7 @@ func (s *Server) HandleMenu(w http.ResponseWriter, r *http.Request) {
|
|||||||
counter++
|
counter++
|
||||||
}
|
}
|
||||||
|
|
||||||
menuViewModel := MenuViewModel{
|
menuViewModel := view.MenuViewModel{
|
||||||
Mangas: mangaViewModels,
|
Mangas: mangaViewModels,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,3 +358,23 @@ func (s *Server) HandleExit(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
|
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addFileToRam(url string) (*bytes.Buffer, error) {
|
||||||
|
// Get the data
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer func(Body io.ReadCloser) {
|
||||||
|
err := Body.Close()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}(resp.Body)
|
||||||
|
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
|
||||||
|
// Write the body to file
|
||||||
|
_, err = io.Copy(buf, resp.Body)
|
||||||
|
return buf, err
|
||||||
|
}
|
||||||
25
internal/view/embedded.go
Normal file
25
internal/view/embedded.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
//go:build !Develop
|
||||||
|
|
||||||
|
package view
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "embed"
|
||||||
|
"errors"
|
||||||
|
"html/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed Views/menu.gohtml
|
||||||
|
var menu string
|
||||||
|
|
||||||
|
//go:embed Views/viewer.gohtml
|
||||||
|
var viewer string
|
||||||
|
|
||||||
|
func GetViewTemplate(view View) (*template.Template, error) {
|
||||||
|
switch view {
|
||||||
|
case Menu:
|
||||||
|
return template.New("menu").Parse(menu)
|
||||||
|
case Viewer:
|
||||||
|
return template.New("viewer").Parse(viewer)
|
||||||
|
}
|
||||||
|
return nil, errors.New("invalid view")
|
||||||
|
}
|
||||||
18
internal/view/hotreload.go
Normal file
18
internal/view/hotreload.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
//go:build Develop
|
||||||
|
|
||||||
|
package view
|
||||||
|
|
||||||
|
import (
|
||||||
|
"html/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetViewTemplate(view View) (*template.Template, error) {
|
||||||
|
var path string
|
||||||
|
switch view {
|
||||||
|
case Menu:
|
||||||
|
path = "internal/view/Views/menu.gohtml"
|
||||||
|
case Viewer:
|
||||||
|
path = "internal/view/Views/viewer.gohtml"
|
||||||
|
}
|
||||||
|
return template.ParseFiles(path)
|
||||||
|
}
|
||||||
22
internal/view/viewmodels.go
Normal file
22
internal/view/viewmodels.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package view
|
||||||
|
|
||||||
|
type Image struct {
|
||||||
|
Path string
|
||||||
|
Index int
|
||||||
|
}
|
||||||
|
|
||||||
|
type ImageViewModel struct {
|
||||||
|
Title string
|
||||||
|
Images []Image
|
||||||
|
}
|
||||||
|
|
||||||
|
type MangaViewModel struct {
|
||||||
|
Title string
|
||||||
|
Number int
|
||||||
|
LastTime string
|
||||||
|
Url string
|
||||||
|
}
|
||||||
|
|
||||||
|
type MenuViewModel struct {
|
||||||
|
Mangas []MangaViewModel
|
||||||
|
}
|
||||||
8
internal/view/views.go
Normal file
8
internal/view/views.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package view
|
||||||
|
|
||||||
|
type View int
|
||||||
|
|
||||||
|
const (
|
||||||
|
Menu View = iota
|
||||||
|
Viewer View = iota
|
||||||
|
)
|
||||||
64
util.go
64
util.go
@@ -1,64 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"regexp"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getTitleAndChapter(url string) (title string, chapter string, err error) {
|
|
||||||
reg, err := regexp.Compile(`/title/\d*-(.*?)/\d*-(.*)`)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
matches := reg.FindAllStringSubmatch(url, -1)
|
|
||||||
if len(matches) <= 0 {
|
|
||||||
return "", "", errors.New("no title or chapter found")
|
|
||||||
}
|
|
||||||
|
|
||||||
return matches[0][1], matches[0][2], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getMangaIdAndChapterId(url string) (titleId int, chapterId int, err error) {
|
|
||||||
reg, err := regexp.Compile(`/title/(\d*)-.*?/(\d*)-.*`)
|
|
||||||
if err != nil {
|
|
||||||
return 0, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
matches := reg.FindAllStringSubmatch(url, -1)
|
|
||||||
if len(matches) <= 0 {
|
|
||||||
return 0, 0, errors.New("no title or chapter found")
|
|
||||||
}
|
|
||||||
t, err := strconv.Atoi(matches[0][1])
|
|
||||||
if err != nil {
|
|
||||||
return 0, 0, err
|
|
||||||
}
|
|
||||||
c, err := strconv.Atoi(matches[0][2])
|
|
||||||
|
|
||||||
return t, c, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func addFileToRam(url string) (*bytes.Buffer, error) {
|
|
||||||
// Get the data
|
|
||||||
resp, err := http.Get(url)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer func(Body io.ReadCloser) {
|
|
||||||
err := Body.Close()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
}(resp.Body)
|
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
|
|
||||||
// Write the body to file
|
|
||||||
_, err = io.Copy(buf, resp.Body)
|
|
||||||
return buf, err
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user