From ad32acda9c28c0a0c1455b72fb402e77259a7783 Mon Sep 17 00:00:00 2001 From: Thomas Krzero Date: Fri, 17 Nov 2017 23:23:24 +0100 Subject: [PATCH 1/3] Init codeclimate issues --- handlers.go | 22 +++++++++++----------- internal/archiver/archiver.go | 19 ++++++++++--------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/handlers.go b/handlers.go index 9bcf6e6..35cd10d 100644 --- a/handlers.go +++ b/handlers.go @@ -19,7 +19,7 @@ import ( "github.com/rylio/ytdl" ) -type Response struct { +type response struct { Config Config Request *http.Request Params *httprouter.Params @@ -64,14 +64,14 @@ func stringInSlice(a string, list []string) bool { return false } -func NewResponse(r *http.Request, ps httprouter.Params) *Response { +func newResponse(r *http.Request, ps httprouter.Params) *response { diskInfo, err := NewDiskInfo(datadir) if err != nil { panic(err) } user, _, _ := r.BasicAuth() isAdmin := stringInSlice(user, httpAdminUsers) - return &Response{ + return &response{ Config: config.Get(), Request: r, Params: &ps, @@ -102,7 +102,7 @@ func home(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { Error(w, err) return } - res := NewResponse(r, ps) + res := newResponse(r, ps) res.Section = "home" res.Lists = lists HTML(w, "home.html", res) @@ -150,7 +150,7 @@ func importHandler(w http.ResponseWriter, r *http.Request, ps httprouter.Params) } youtubes = filtered - res := NewResponse(r, ps) + res := newResponse(r, ps) res.Section = "import" res.Youtubes = youtubes HTML(w, "import.html", res) @@ -221,7 +221,7 @@ func library(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { return } - res := NewResponse(r, ps) + res := newResponse(r, ps) res.Section = "library" res.Medias = medias[begin:end] res.Lists = lists @@ -269,7 +269,7 @@ func viewMedia(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { return } - res := NewResponse(r, ps) + res := newResponse(r, ps) res.Media = media res.Section = "library" res.Section = "view" @@ -309,7 +309,7 @@ func streamMedia(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { // func archiverJobs(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { - res := NewResponse(r, ps) + res := newResponse(r, ps) res.ActiveMedias = ActiveMedias() res.QueuedMedias = QueuedMedias() HTML(w, "jobs.html", res) @@ -429,7 +429,7 @@ func playList(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { return } - res := NewResponse(r, ps) + res := newResponse(r, ps) res.Section = "play" res.List = list HTML(w, "play.html", res) @@ -437,7 +437,7 @@ func playList(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { func createList(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { if r.Method == "GET" { - res := NewResponse(r, ps) + res := newResponse(r, ps) res.Section = "create" HTML(w, "create.html", res) return @@ -514,7 +514,7 @@ func editList(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { return } - res := NewResponse(r, ps) + res := newResponse(r, ps) res.Section = "edit" res.List = list HTML(w, "edit.html", res) diff --git a/internal/archiver/archiver.go b/internal/archiver/archiver.go index c283e02..8f98a77 100644 --- a/internal/archiver/archiver.go +++ b/internal/archiver/archiver.go @@ -21,10 +21,10 @@ import ( ) var ( - HTTPUserAgent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36" + httpUserAgent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36" ) -type Job struct { +type job struct { id string source string context *context.Context @@ -35,11 +35,12 @@ type Job struct { audiofile string } +// Return a new Archiver func NewArchiver(datadir string, concurrency int, logger *zap.SugaredLogger) *Archiver { a := &Archiver{ datadir: datadir, concurrency: concurrency, - active: make(map[string]*Job), + active: make(map[string]*job), failed: make(map[string]error), logger: logger, } @@ -51,8 +52,8 @@ type Archiver struct { mu sync.RWMutex datadir string concurrency int - queue []*Job - active map[string]*Job + queue []*job + active map[string]*job failed map[string]error logger *zap.SugaredLogger debug bool @@ -165,9 +166,9 @@ func (a *Archiver) runlock(loc string) { a.mu.RUnlock() } -func (a *Archiver) newJob(id, source string) *Job { +func (a *Archiver) newJob(id, source string) *job { ctx, cancel := context.WithCancel(context.Background()) - return &Job{ + return &job{ id: id, source: source, context: &ctx, @@ -210,7 +211,7 @@ func (a *Archiver) manager() { } } -func (a *Archiver) archive(job *Job) { +func (a *Archiver) archive(job *job) { var failed error // Clean up on completion. @@ -268,7 +269,7 @@ func (a *Archiver) download(ctx context.Context, rawurl, filename string) error if err != nil { return err } - req.Header.Set("User-Agent", HTTPUserAgent) + req.Header.Set("User-Agent", httpUserAgent) req = req.WithContext(ctx) res, err := http.DefaultClient.Do(req) From b8d06fcfe8ba616deca5ad561a2176eca78dcff8 Mon Sep 17 00:00:00 2001 From: Thomas Krzero Date: Sat, 18 Nov 2017 00:47:53 +0100 Subject: [PATCH 2/3] Review all --- handlers.go | 136 ++++++++++++++++---------------- internal/archiver/archiver.go | 22 ++++-- internal/logtailer/logtailer.go | 5 ++ internal/youtube/search.go | 2 + internal/youtube/stream.go | 1 + internal/youtube/video.go | 8 ++ main.go | 60 +++++++------- streamlist.go | 112 +++++++++++++------------- templates/view.html | 2 +- utils.go | 30 +++---- web.go | 20 ++--- 11 files changed, 213 insertions(+), 185 deletions(-) diff --git a/handlers.go b/handlers.go index 35cd10d..2cfffec 100644 --- a/handlers.go +++ b/handlers.go @@ -26,7 +26,7 @@ type response struct { HTTPHost string Version string Backlink string - DiskInfo *DiskInfo + DiskInfo *diskInfo Archiver *archiver.Archiver Error string @@ -65,7 +65,7 @@ func stringInSlice(a string, list []string) bool { } func newResponse(r *http.Request, ps httprouter.Params) *response { - diskInfo, err := NewDiskInfo(datadir) + diskInfo, err := newDiskInfo(datadir) if err != nil { panic(err) } @@ -93,19 +93,19 @@ func logs(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { } func index(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { - Redirect(w, r, "/") + redirect(w, r, "/") } func home(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { - lists, err := ListLists() + lists, err := listLists() if err != nil { - Error(w, err) + _error(w, err) return } res := newResponse(r, ps) res.Section = "home" res.Lists = lists - HTML(w, "home.html", res) + html(w, "home.html", res) } func configHandler(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { @@ -116,15 +116,15 @@ func configHandler(w http.ResponseWriter, r *http.Request, ps httprouter.Params) case "volume": n, err := strconv.ParseFloat(value, 32) if err != nil { - Error(w, err) + _error(w, err) return } if err := config.SetVolume(float32(n)); err != nil { - Error(w, err) + _error(w, err) return } } - JSON(w, "OK") + toJSON(w, "OK") } func importHandler(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { @@ -142,7 +142,7 @@ func importHandler(w http.ResponseWriter, r *http.Request, ps httprouter.Params) for _, v := range youtubes { // Already exists in library, so filter it out. if m, err := loadMedia(v.ID); err == nil { - if m.HasAudio() || archive.InProgress(m.ID) { + if m.hasAudio() || archive.InProgress(m.ID) { continue } } @@ -153,13 +153,13 @@ func importHandler(w http.ResponseWriter, r *http.Request, ps httprouter.Params) res := newResponse(r, ps) res.Section = "import" res.Youtubes = youtubes - HTML(w, "import.html", res) + html(w, "import.html", res) } func library(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { medias, err := ListMedias() if err != nil { - Error(w, err) + _error(w, err) return } @@ -200,7 +200,7 @@ func library(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { limit = 100 } pages := []int64{} - var lastpage int64 = (total / limit) + 1 + var lastpage = (total / limit) + 1 for i := int64(1); i <= lastpage; i++ { pages = append(pages, i) } @@ -209,15 +209,15 @@ func library(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { } // chunk - var begin int64 = (page - 1) * limit + var begin = (page - 1) * limit var end = begin + limit if end > total { end = total } - lists, err := ListLists() + lists, err := listLists() if err != nil { - Error(w, err) + _error(w, err) return } @@ -231,7 +231,7 @@ func library(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { res.Limit = limit res.Total = total res.GrandTotal = grandTotal - HTML(w, "library.html", res) + html(w, "library.html", res) } // @@ -241,13 +241,13 @@ func library(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { func thumbnailMedia(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { media, err := FindMedia(ps.ByName("media")) if err != nil { - Error(w, err) + _error(w, err) return } - img, err := imaging.Open(media.ImageFile()) + img, err := imaging.Open(media.imageFile()) if err != nil { - Error(w, err) + _error(w, err) return } @@ -257,7 +257,7 @@ func thumbnailMedia(w http.ResponseWriter, r *http.Request, ps httprouter.Params w.Header().Set("Vary", "Accept-Encoding") w.Header().Set("Cache-Control", fmt.Sprintf("public, max-age=%d", 7*86400)) if err := imaging.Encode(w, img, imaging.JPEG); err != nil { - Error(w, err) + _error(w, err) return } } @@ -265,7 +265,7 @@ func thumbnailMedia(w http.ResponseWriter, r *http.Request, ps httprouter.Params func viewMedia(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { media, err := FindMedia(ps.ByName("media")) if err != nil { - Error(w, err) + _error(w, err) return } @@ -273,15 +273,15 @@ func viewMedia(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { res.Media = media res.Section = "library" res.Section = "view" - HTML(w, "view.html", res) + html(w, "view.html", res) } func deleteMedia(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { if err := DeleteMedia(ps.ByName("media")); err != nil { - Error(w, err) + _error(w, err) return } - Redirect(w, r, "/library?p=%s&q=%s&message=mediadeleted", r.FormValue("p"), r.FormValue("q")) + redirect(w, r, "/library?p=%s&q=%s&message=mediadeleted", r.FormValue("p"), r.FormValue("q")) } func downloadMedia(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { @@ -293,8 +293,8 @@ func downloadMedia(w http.ResponseWriter, r *http.Request, ps httprouter.Params) func streamMedia(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { filename := filepath.Join(datadir, ps.ByName("filename")) if id := ps.ByName("list"); id != "" { - if _, err := FindList(id); err != nil { - Error(w, err) + if _, err := findList(id); err != nil { + _error(w, err) return } } @@ -312,7 +312,7 @@ func archiverJobs(w http.ResponseWriter, r *http.Request, ps httprouter.Params) res := newResponse(r, ps) res.ActiveMedias = ActiveMedias() res.QueuedMedias = QueuedMedias() - HTML(w, "jobs.html", res) + html(w, "jobs.html", res) } func archiverSave(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { @@ -321,41 +321,41 @@ func archiverSave(w http.ResponseWriter, r *http.Request, ps httprouter.Params) vinfo, err := ytdl.GetVideoInfoFromID(id) if err != nil { - Error(w, err) + _error(w, err) return } media, err := NewMedia(vinfo.ID, vinfo.Author, vinfo.Title, int64(vinfo.Duration.Seconds()), source) if err != nil { - Error(w, err) + _error(w, err) return } logger.Infof("created new media %q %q", media.ID, media.Title) archive.Add(id, source) - JSON(w, "OK") + toJSON(w, "OK") } func archiverCancel(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { archive.Remove(ps.ByName("id")) - Redirect(w, r, "/import?message=savecancelled") + redirect(w, r, "/import?message=savecancelled") } func deleteList(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { - list, err := FindList(ps.ByName("id")) + list, err := findList(ps.ByName("id")) if err != nil { - Error(w, err) + _error(w, err) return } if err := DeleteList(list.ID); err != nil { - Error(w, err) + _error(w, err) return } - Redirect(w, r, "/?message=playlistdeleted") + redirect(w, r, "/?message=playlistdeleted") } func podcastList(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { - list, err := FindList(ps.ByName("id")) + list, err := findList(ps.ByName("id")) if err != nil { http.NotFound(w, r) return @@ -374,7 +374,7 @@ func podcastList(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { for _, media := range list.Medias { typ := podcast.M4V ext := "m4a" - filename := media.AudioFile() + filename := media.audioFile() fileInfo, err := os.Stat(filename) if err != nil { @@ -391,18 +391,18 @@ func podcastList(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { } item.AddEnclosure(streamurl, typ, fileInfo.Size()) if _, err := p.AddItem(item); err != nil { - Error(w, err) + _error(w, err) return } } w.Header().Set("Content-Type", "application/rss+xml; charset=utf-8") if err := p.Encode(w); err != nil { - Error(w, err) + _error(w, err) } } func m3uList(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { - list, err := FindList(ps.ByName("id")) + list, err := findList(ps.ByName("id")) if err != nil { http.NotFound(w, r) return @@ -423,7 +423,7 @@ func m3uList(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { } func playList(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { - list, err := FindList(ps.ByName("id")) + list, err := findList(ps.ByName("id")) if err != nil { http.NotFound(w, r) return @@ -432,92 +432,92 @@ func playList(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { res := newResponse(r, ps) res.Section = "play" res.List = list - HTML(w, "play.html", res) + html(w, "play.html", res) } func createList(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { if r.Method == "GET" { res := newResponse(r, ps) res.Section = "create" - HTML(w, "create.html", res) + html(w, "create.html", res) return } title := strings.TrimSpace(r.FormValue("title")) if title == "" { - Redirect(w, r, "/create") + redirect(w, r, "/create") return } - _, err := NewList(title) + _, err := newList(title) if err != nil { - Error(w, err) + _error(w, err) return } - Redirect(w, r, "/library?message=playlistadded") + redirect(w, r, "/library?message=playlistadded") } func removeMediaList(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { media, err := FindMedia(ps.ByName("media")) if err != nil { - Error(w, err) + _error(w, err) return } - list, err := FindList(ps.ByName("list")) + list, err := findList(ps.ByName("list")) if err != nil { - Error(w, err) + _error(w, err) return } - if err := list.RemoveMedia(media); err != nil { - Error(w, err) + if err := list.removeMedia(media); err != nil { + _error(w, err) return } - Redirect(w, r, "/edit/%s", list.ID) + redirect(w, r, "/edit/%s", list.ID) } func addMediaList(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { media, err := FindMedia(ps.ByName("media")) if err != nil { - Error(w, err) + _error(w, err) return } - list, err := FindList(ps.ByName("list")) + list, err := findList(ps.ByName("list")) if err != nil { - Error(w, err) + _error(w, err) return } - list.AddMedia(media) - JSON(w, "OK") + list.addMedia(media) + toJSON(w, "OK") } func shuffleList(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { - list, err := FindList(ps.ByName("id")) + list, err := findList(ps.ByName("id")) if err != nil { - Error(w, err) + _error(w, err) return } - if err := list.ShuffleMedia(); err != nil { - Error(w, err) + if err := list.shuffleMedia(); err != nil { + _error(w, err) return } - Redirect(w, r, "/play/%s", list.ID) + redirect(w, r, "/play/%s", list.ID) } func editList(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { - list, err := FindList(ps.ByName("id")) + list, err := findList(ps.ByName("id")) if err != nil { - Error(w, err) + _error(w, err) return } res := newResponse(r, ps) res.Section = "edit" res.List = list - HTML(w, "edit.html", res) + html(w, "edit.html", res) } func staticAsset(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { @@ -538,7 +538,7 @@ func serveAsset(w http.ResponseWriter, r *http.Request, filename string) { } fi, err := AssetInfo(path) if err != nil { - Error(w, err) + _error(w, err) return } http.ServeContent(w, r, path, fi.ModTime(), bytes.NewReader(b)) diff --git a/internal/archiver/archiver.go b/internal/archiver/archiver.go index 8f98a77..c1f10dd 100644 --- a/internal/archiver/archiver.go +++ b/internal/archiver/archiver.go @@ -35,7 +35,7 @@ type job struct { audiofile string } -// Return a new Archiver +// NewArchiver returns a new Archiver func NewArchiver(datadir string, concurrency int, logger *zap.SugaredLogger) *Archiver { a := &Archiver{ datadir: datadir, @@ -48,6 +48,7 @@ func NewArchiver(datadir string, concurrency int, logger *zap.SugaredLogger) *Ar return a } +// Archiver object type Archiver struct { mu sync.RWMutex datadir string @@ -59,18 +60,19 @@ type Archiver struct { debug bool } -func (a *Archiver) SetConcurrency(n int) { - a.lock("Concurrency") - defer a.unlock("Concurrency") +func (a *Archiver) setConcurrency(n int) { + a.lock("concurrency") + defer a.unlock("concurrency") a.concurrency = n } -func (a *Archiver) Concurrency() int { - a.rlock("Concurrency") - defer a.runlock("Concurrency") +func (a *Archiver) getConcurrency() int { + a.rlock("concurrency") + defer a.runlock("concurrency") return a.concurrency } +// QueuedJobs return job queue list func (a *Archiver) QueuedJobs() []string { a.rlock("QueuedJobs") defer a.runlock("QueuedJobID") @@ -82,17 +84,19 @@ func (a *Archiver) QueuedJobs() []string { return ids } +// ActiveJobs return job active list func (a *Archiver) ActiveJobs() []string { a.rlock("ActiveJobs") defer a.runlock("ActiveJobs") var ids []string - for id, _ := range a.active { + for id := range a.active { ids = append(ids, id) } sort.Strings(ids) return ids } +// InProgress return true if job id is in progress func (a *Archiver) InProgress(id string) bool { for _, job := range a.QueuedJobs() { if job == id { @@ -107,6 +111,7 @@ func (a *Archiver) InProgress(id string) bool { return false } +// Remove removes a job func (a *Archiver) Remove(id string) { a.lock("Remove") defer a.unlock("Remove") @@ -124,6 +129,7 @@ func (a *Archiver) Remove(id string) { return } +// Add adds a job func (a *Archiver) Add(id string, source string) { a.lock("Add") defer a.unlock("Add") diff --git a/internal/logtailer/logtailer.go b/internal/logtailer/logtailer.go index f8f1b00..6086e1b 100644 --- a/internal/logtailer/logtailer.go +++ b/internal/logtailer/logtailer.go @@ -6,12 +6,14 @@ import ( "sync" ) +// Logtailer ... type Logtailer struct { sync.RWMutex tail *circbuf.Buffer } +// NewLogtailer ... func NewLogtailer(size int64) (*Logtailer, error) { buf, err := circbuf.NewBuffer(size) if err != nil { @@ -20,6 +22,7 @@ func NewLogtailer(size int64) (*Logtailer, error) { return &Logtailer{tail: buf}, nil } +// Lines ... func (l *Logtailer) Lines() []string { l.RLock() buf := l.tail.Bytes() @@ -33,6 +36,7 @@ func (l *Logtailer) Lines() []string { return strings.Split(s[start:], "\n") } +// Write ... func (l *Logtailer) Write(buf []byte) (int, error) { l.Lock() n, err := l.tail.Write(buf) @@ -40,6 +44,7 @@ func (l *Logtailer) Write(buf []byte) (int, error) { return n, err } +// Sync ... func (l *Logtailer) Sync() error { return nil } diff --git a/internal/youtube/search.go b/internal/youtube/search.go index 4f8a56d..4fb9a7e 100644 --- a/internal/youtube/search.go +++ b/internal/youtube/search.go @@ -14,10 +14,12 @@ import ( log "github.com/Sirupsen/logrus" ) +// SetDebug ... func SetDebug() { log.SetLevel(log.DebugLevel) } +// Search ... func Search(query string) ([]Video, error) { u, err := url.Parse("https://www.youtube.com/results") if err != nil { diff --git a/internal/youtube/stream.go b/internal/youtube/stream.go index b23f39b..828d9b5 100644 --- a/internal/youtube/stream.go +++ b/internal/youtube/stream.go @@ -4,6 +4,7 @@ import ( "fmt" ) +// Stream ... type Stream struct { URL string `json:"url"` Extension string `json:"extension"` diff --git a/internal/youtube/video.go b/internal/youtube/video.go index 05d1377..884c929 100644 --- a/internal/youtube/video.go +++ b/internal/youtube/video.go @@ -25,6 +25,7 @@ var ( fixurlRegexp = regexp.MustCompile(`\,[^=]+=.*$`) ) +// Video ... type Video struct { ID string `json:"id"` Title string `json:"title"` @@ -37,18 +38,22 @@ type Video struct { Streams []Stream } +// Filename ... func (v Video) Filename(dir string) string { return filepath.Join(dir, v.ID+".mp4") } +// ThumbnailFilename ... func (v Video) ThumbnailFilename(dir string) string { return filepath.Join(dir, v.ID+".jpg") } +// jsonFilename ... func (v Video) jsonFilename(dir string) string { return filepath.Join(dir, v.ID+".json") } +// Transcode ... func (v Video) Transcode(ctx context.Context, dir string) error { filename := v.Filename(dir) tmpname := filename + ".encoding" @@ -71,6 +76,7 @@ func (v Video) Transcode(ctx context.Context, dir string) error { return nil } +// Download ... func (v Video) Download(ctx context.Context, dir string) error { if len(v.Streams) == 0 { return fmt.Errorf("no streams") @@ -141,6 +147,7 @@ func download(ctx context.Context, rawurl, filename string) error { return err } +// GetVideo ... func GetVideo(rawid string) (Video, error) { id := rawid if strings.HasPrefix(rawid, "http") { @@ -293,6 +300,7 @@ func GetVideo(rawid string) (Video, error) { }, nil } +// GET ... func GET(ctx context.Context, rawurl string) (*http.Response, error) { client := &http.Client{ Timeout: 15 * time.Second, diff --git a/main.go b/main.go index d7b2e28..2192008 100644 --- a/main.go +++ b/main.go @@ -174,55 +174,55 @@ func main() { r.HandleMethodNotAllowed = false // Handlers - r.GET("/", Log(auth(index, "readonly"))) - r.GET(Prefix("/logs"), Log(auth(logs, "admin"))) - r.GET(Prefix("/"), Log(auth(home, "readonly"))) + r.GET("/", log(auth(index, "readonly"))) + r.GET(prefix("/logs"), log(auth(logs, "admin"))) + r.GET(prefix("/"), log(auth(home, "readonly"))) // Library - r.GET(Prefix("/library"), Log(auth(library, "readonly"))) + r.GET(prefix("/library"), log(auth(library, "readonly"))) // Media - r.GET(Prefix("/media/thumbnail/:media"), Log(auth(thumbnailMedia, "readonly"))) - r.GET(Prefix("/media/view/:media"), Log(auth(viewMedia, "readonly"))) - r.GET(Prefix("/media/delete/:media"), Log(auth(deleteMedia, "admin"))) - r.GET(Prefix("/media/access/:filename"), auth(streamMedia, "readonly")) - r.GET(Prefix("/media/download/:filename"), auth(downloadMedia, "readonly")) + r.GET(prefix("/media/thumbnail/:media"), log(auth(thumbnailMedia, "readonly"))) + r.GET(prefix("/media/view/:media"), log(auth(viewMedia, "readonly"))) + r.GET(prefix("/media/delete/:media"), log(auth(deleteMedia, "admin"))) + r.GET(prefix("/media/access/:filename"), auth(streamMedia, "readonly")) + r.GET(prefix("/media/download/:filename"), auth(downloadMedia, "readonly")) // Publicly accessible streaming (using playlist id as "auth") - r.GET(Prefix("/stream/:list/:filename"), auth(streamMedia, "none")) + r.GET(prefix("/stream/:list/:filename"), auth(streamMedia, "none")) // Import - r.GET(Prefix("/import"), Log(auth(importHandler, "admin"))) + r.GET(prefix("/import"), log(auth(importHandler, "admin"))) // Archiver - r.GET(Prefix("/archiver/jobs"), auth(archiverJobs, "admin")) - r.POST(Prefix("/archiver/save/:id"), Log(auth(archiverSave, "admin"))) - r.GET(Prefix("/archiver/cancel/:id"), Log(auth(archiverCancel, "admin"))) + r.GET(prefix("/archiver/jobs"), auth(archiverJobs, "admin")) + r.POST(prefix("/archiver/save/:id"), log(auth(archiverSave, "admin"))) + r.GET(prefix("/archiver/cancel/:id"), log(auth(archiverCancel, "admin"))) // List - r.GET(Prefix("/create"), Log(auth(createList, "admin"))) - r.POST(Prefix("/create"), Log(auth(createList, "admin"))) - r.POST(Prefix("/add/:list/:media"), Log(auth(addMediaList, "admin"))) - r.POST(Prefix("/remove/:list/:media"), Log(auth(removeMediaList, "admin"))) - r.GET(Prefix("/remove/:list/:media"), Log(auth(removeMediaList, "admin"))) + r.GET(prefix("/create"), log(auth(createList, "admin"))) + r.POST(prefix("/create"), log(auth(createList, "admin"))) + r.POST(prefix("/add/:list/:media"), log(auth(addMediaList, "admin"))) + r.POST(prefix("/remove/:list/:media"), log(auth(removeMediaList, "admin"))) + r.GET(prefix("/remove/:list/:media"), log(auth(removeMediaList, "admin"))) - r.GET(Prefix("/edit/:id"), Log(auth(editList, "admin"))) - r.POST(Prefix("/edit/:id"), Log(auth(editList, "admin"))) - r.GET(Prefix("/shuffle/:id"), Log(auth(shuffleList, "admin"))) - r.GET(Prefix("/play/:id"), Log(auth(playList, "none"))) - r.GET(Prefix("/m3u/:id"), Log(auth(m3uList, "none"))) - r.GET(Prefix("/podcast/:id"), Log(auth(podcastList, "none"))) + r.GET(prefix("/edit/:id"), log(auth(editList, "admin"))) + r.POST(prefix("/edit/:id"), log(auth(editList, "admin"))) + r.GET(prefix("/shuffle/:id"), log(auth(shuffleList, "admin"))) + r.GET(prefix("/play/:id"), log(auth(playList, "none"))) + r.GET(prefix("/m3u/:id"), log(auth(m3uList, "none"))) + r.GET(prefix("/podcast/:id"), log(auth(podcastList, "none"))) - r.POST(Prefix("/config"), Log(auth(configHandler, "admin"))) + r.POST(prefix("/config"), log(auth(configHandler, "admin"))) - r.GET(Prefix("/delete/:id"), Log(auth(deleteList, "admin"))) + r.GET(prefix("/delete/:id"), log(auth(deleteList, "admin"))) // API - r.GET(Prefix("/v1/status"), Log(auth(v1status, "none"))) + r.GET(prefix("/v1/status"), log(auth(v1status, "none"))) // Assets - r.GET(Prefix("/static/*path"), auth(staticAsset, "none")) - r.GET(Prefix("/logo.png"), Log(auth(logo, "none"))) + r.GET(prefix("/static/*path"), auth(staticAsset, "none")) + r.GET(prefix("/logo.png"), log(auth(logo, "none"))) // // Server diff --git a/streamlist.go b/streamlist.go index b70c457..1d4cc4d 100644 --- a/streamlist.go +++ b/streamlist.go @@ -14,11 +14,9 @@ import ( "time" ) -var ErrMediaNotFound = errors.New("media not found") +var errMediaNotFound = errors.New("media not found") -// -// Config -// +// Config is the global config type Config struct { sync.RWMutex filename string @@ -27,6 +25,7 @@ type Config struct { Volume float32 `json:"volume"` } +// NewConfig returns a new Config func NewConfig(filename string) (*Config, error) { filename = filepath.Join(datadir, filename) c := &Config{filename: filename} @@ -48,6 +47,7 @@ func NewConfig(filename string) (*Config, error) { return c, nil } +// Get return the current config func (c *Config) Get() Config { c.RLock() defer c.RUnlock() @@ -57,6 +57,7 @@ func (c *Config) Get() Config { } } +// SetVolume modify configured volume func (c *Config) SetVolume(n float32) error { c.Lock() c.Volume = n @@ -64,6 +65,7 @@ func (c *Config) SetVolume(n float32) error { return c.Save() } +// Save saves config to file func (c *Config) Save() error { c.RLock() defer c.RUnlock() @@ -72,12 +74,10 @@ func (c *Config) Save() error { if err != nil { return err } - return Overwrite(c.filename, b, 0644) + return overwrite(c.filename, b, 0644) } -// -// Media -// +// Media represent a media in the library type Media struct { ID string `json:"id"` Author string `json:"author"` @@ -96,6 +96,7 @@ func mediaFile(id string) string { return filepath.Join(datadir, id+".media") } +// NewMedia return a new Media func NewMedia(id, author, title string, length int64, source string) (*Media, error) { media := &Media{ ID: id, @@ -106,9 +107,10 @@ func NewMedia(id, author, title string, length int64, source string) (*Media, er Modified: time.Now(), Created: time.Now(), } - return media, media.Save() + return media, media.save() } +// QueuedMedias return queueud media list func QueuedMedias() []*Media { var medias []*Media for _, id := range archive.QueuedJobs() { @@ -122,6 +124,7 @@ func QueuedMedias() []*Media { return medias } +// ActiveMedias return active media list func ActiveMedias() []*Media { var medias []*Media for _, id := range archive.ActiveJobs() { @@ -135,6 +138,7 @@ func ActiveMedias() []*Media { return medias } +// DeleteMedia removes mediafrom library func DeleteMedia(id string) error { media, err := FindMedia(id) if err != nil { @@ -142,22 +146,22 @@ func DeleteMedia(id string) error { } // Remove all list references to this media. - lists, err := ListLists() + lists, err := listLists() if err != nil { return err } for _, l := range lists { - if err := l.RemoveMedia(media); err != nil { + if err := l.removeMedia(media); err != nil { return err } } // Remove all media files. files := []string{ - media.ImageFile(), - media.VideoFile(), - media.AudioFile(), - media.File(), + media.imageFile(), + media.videoFile(), + media.audioFile(), + media.file(), } for _, f := range files { if _, err := os.Stat(f); os.IsNotExist(err) { @@ -170,14 +174,16 @@ func DeleteMedia(id string) error { return nil } +// DeleteList removes a playlist func DeleteList(id string) error { - list, err := FindList(id) + list, err := findList(id) if err != nil { return err } - return os.Remove(list.File()) + return os.Remove(list.file()) } +// FindMedia search media in library func FindMedia(id string) (*Media, error) { medias, err := ListMedias() if err != nil { @@ -188,9 +194,10 @@ func FindMedia(id string) (*Media, error) { return m, nil } } - return nil, ErrMediaNotFound + return nil, errMediaNotFound } +// LoadMedia reads media file func loadMedia(id string) (*Media, error) { b, err := ioutil.ReadFile(mediaFile(id)) if err != nil { @@ -200,6 +207,7 @@ func loadMedia(id string) (*Media, error) { return &media, json.Unmarshal(b, &media) } +// ListMedias list medias in library func ListMedias() ([]*Media, error) { files, err := ioutil.ReadDir(datadir) if err != nil { @@ -220,11 +228,11 @@ func ListMedias() ([]*Media, error) { return nil, err } // must have an image file. - if !m.HasImage() { + if !m.hasImage() { continue } // must have an audio file (otherwise it's not finished transcoding) - if !m.HasAudio() { + if !m.hasAudio() { continue } medias = append(medias, m) @@ -232,48 +240,46 @@ func ListMedias() ([]*Media, error) { return medias, nil } -func (m Media) Save() error { +func (m Media) save() error { b, err := json.MarshalIndent(m, "", " ") if err != nil { return err } - return Overwrite(m.File(), b, 0644) + return overwrite(m.file(), b, 0644) } -func (m Media) File() string { +func (m Media) file() string { return mediaFile(m.ID) } -func (m Media) ImageFile() string { +func (m Media) imageFile() string { return filepath.Join(datadir, m.ID+".jpg") } -func (m Media) VideoFile() string { +func (m Media) videoFile() string { return filepath.Join(datadir, m.ID+".mp4") } -func (m Media) AudioFile() string { +func (m Media) audioFile() string { return filepath.Join(datadir, m.ID+".m4a") } -func (m Media) HasImage() bool { - _, err := os.Stat(m.ImageFile()) +func (m Media) hasImage() bool { + _, err := os.Stat(m.imageFile()) return err == nil } -func (m Media) HasVideo() bool { - _, err := os.Stat(m.VideoFile()) +func (m Media) hasVideo() bool { + _, err := os.Stat(m.videoFile()) return err == nil } -func (m Media) HasAudio() bool { - _, err := os.Stat(m.AudioFile()) +func (m Media) hasAudio() bool { + _, err := os.Stat(m.audioFile()) return err == nil } -// -// List -// +// List represent a playlist type List struct { ID string `json:"id"` Title string `json:"title"` @@ -291,8 +297,8 @@ func listFile(id string) string { return filepath.Join(datadir, id+".playlist") } -func NewList(title string) (*List, error) { - id, err := RandomNumber() +func newList(title string) (*List, error) { + id, err := randomNumber() if err != nil { return nil, err } @@ -302,23 +308,23 @@ func NewList(title string) (*List, error) { Modified: time.Now(), Created: time.Now(), } - return list, list.Save() + return list, list.save() } -func (l *List) File() string { +func (l *List) file() string { return listFile(l.ID) } -func (l *List) Save() error { +func (l *List) save() error { b, err := json.MarshalIndent(l, "", " ") if err != nil { return err } l.Modified = time.Now() - return Overwrite(l.File(), b, 0644) + return overwrite(l.file(), b, 0644) } -func (l *List) HasMedia(media *Media) bool { +func (l *List) hasMedia(media *Media) bool { for _, m := range l.Medias { if m.ID == media.ID { return true @@ -327,30 +333,30 @@ func (l *List) HasMedia(media *Media) bool { return false } -func (l *List) TotalLength() (total int64) { +func (l *List) totalLength() (total int64) { for _, m := range l.Medias { total += m.Length } return total } -func (l *List) ShuffleMedia() error { +func (l *List) shuffleMedia() error { r := rand.New(rand.NewSource(time.Now().Unix())) var medias []*Media for _, i := range r.Perm(len(l.Medias)) { medias = append(medias, l.Medias[i]) } l.Medias = medias - return l.Save() + return l.save() } -func (l *List) AddMedia(media *Media) error { +func (l *List) addMedia(media *Media) error { l.Medias = append(l.Medias, media) - return l.Save() + return l.save() } -func (l *List) RemoveMedia(media *Media) error { - if !l.HasMedia(media) { +func (l *List) removeMedia(media *Media) error { + if !l.hasMedia(media) { return nil } var medias []*Media @@ -361,10 +367,10 @@ func (l *List) RemoveMedia(media *Media) error { medias = append(medias, m) } l.Medias = medias - return l.Save() + return l.save() } -func FindList(id string) (*List, error) { +func findList(id string) (*List, error) { b, err := ioutil.ReadFile(listFile(id)) if err != nil { return nil, err @@ -373,7 +379,7 @@ func FindList(id string) (*List, error) { return &list, json.Unmarshal(b, &list) } -func ListLists() ([]*List, error) { +func listLists() ([]*List, error) { files, err := ioutil.ReadDir(datadir) if err != nil { return nil, err @@ -387,7 +393,7 @@ func ListLists() ([]*List, error) { if !strings.HasSuffix(f.Name(), ".playlist") { continue } - l, err := FindList(strings.TrimSuffix(f.Name(), ".playlist")) + l, err := findList(strings.TrimSuffix(f.Name(), ".playlist")) if err != nil { return nil, err } diff --git a/templates/view.html b/templates/view.html index 647a08d..bf9e4a5 100644 --- a/templates/view.html +++ b/templates/view.html @@ -16,7 +16,7 @@

{{$.Media.Title}}

- {{if $.Media.HasAudio}} + {{if $.Media.hasAudio}} Audio {{end}} diff --git a/utils.go b/utils.go index 6a2bd9a..9a4a6af 100644 --- a/utils.go +++ b/utils.go @@ -10,38 +10,38 @@ import ( "syscall" ) -type DiskInfo struct { +type diskInfo struct { free int64 used int64 } -func (d *DiskInfo) Total() int64 { return d.free + d.used } -func (d *DiskInfo) TotalMB() int64 { return d.Total() / 1024 / 1024 } -func (d *DiskInfo) TotalGB() int64 { return d.TotalMB() / 1024 } +func (d *diskInfo) Total() int64 { return d.free + d.used } +func (d *diskInfo) TotalMB() int64 { return d.Total() / 1024 / 1024 } +func (d *diskInfo) TotalGB() int64 { return d.TotalMB() / 1024 } -func (d *DiskInfo) Free() int64 { return d.free } -func (d *DiskInfo) FreeMB() int64 { return d.free / 1024 / 1024 } -func (d *DiskInfo) FreeGB() int64 { return d.FreeMB() / 1024 } +func (d *diskInfo) Free() int64 { return d.free } +func (d *diskInfo) FreeMB() int64 { return d.free / 1024 / 1024 } +func (d *diskInfo) FreeGB() int64 { return d.FreeMB() / 1024 } -func (d *DiskInfo) Used() int64 { return d.used } -func (d *DiskInfo) UsedMB() int64 { return d.used / 1024 / 1024 } -func (d *DiskInfo) UsedGB() int64 { return d.UsedMB() / 1024 } +func (d *diskInfo) Used() int64 { return d.used } +func (d *diskInfo) UsedMB() int64 { return d.used / 1024 / 1024 } +func (d *diskInfo) UsedGB() int64 { return d.UsedMB() / 1024 } -func (d *DiskInfo) UsedPercent() float64 { +func (d *diskInfo) UsedPercent() float64 { return (float64(d.used) / float64(d.Total())) * 100 } -func NewDiskInfo(path string) (*DiskInfo, error) { +func newDiskInfo(path string) (*diskInfo, error) { var stat syscall.Statfs_t if err := syscall.Statfs(path, &stat); err != nil { return nil, fmt.Errorf("diskinfo failed: %s", err) } free := stat.Bavail * uint64(stat.Bsize) used := (stat.Blocks * uint64(stat.Bsize)) - free - return &DiskInfo{int64(free), int64(used)}, nil + return &diskInfo{int64(free), int64(used)}, nil } -func RandomNumber() (int, error) { +func randomNumber() (int, error) { b := make([]byte, 4) if _, err := rand.Read(b); err != nil { return 0, err @@ -49,7 +49,7 @@ func RandomNumber() (int, error) { return int(binary.LittleEndian.Uint32(b)), nil } -func Overwrite(filename string, data []byte, perm os.FileMode) error { +func overwrite(filename string, data []byte, perm os.FileMode) error { f, err := ioutil.TempFile(filepath.Dir(filename), filepath.Base(filename)+".tmp") if err != nil { return err diff --git a/web.go b/web.go index adb7aca..7f34d68 100644 --- a/web.go +++ b/web.go @@ -78,13 +78,13 @@ var ( ` ) -func Redirect(w http.ResponseWriter, r *http.Request, format string, a ...interface{}) { +func redirect(w http.ResponseWriter, r *http.Request, format string, a ...interface{}) { location := httpPrefix location += fmt.Sprintf(format, a...) http.Redirect(w, r, location, http.StatusFound) } -func Error(w http.ResponseWriter, err error) { +func _error(w http.ResponseWriter, err error) { logger.Error(err) w.WriteHeader(http.StatusInternalServerError) @@ -92,11 +92,11 @@ func Error(w http.ResponseWriter, err error) { fmt.Fprintf(w, errorPageHTML) } -func Prefix(path string) string { +func prefix(path string) string { return httpPrefix + path } -func Log(h httprouter.Handle) httprouter.Handle { +func log(h httprouter.Handle) httprouter.Handle { return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { // Request info addr := r.RemoteAddr @@ -183,7 +183,7 @@ func auth(h httprouter.Handle, role string) httprouter.Handle { } } -func XML(w http.ResponseWriter, data interface{}) { +func toXML(w http.ResponseWriter, data interface{}) { w.Header().Set("Content-Type", "application/xml; charset=utf-8") enc := xml.NewEncoder(w) enc.Indent("", " ") @@ -192,7 +192,7 @@ func XML(w http.ResponseWriter, data interface{}) { } } -func JSON(w http.ResponseWriter, data interface{}) { +func toJSON(w http.ResponseWriter, data interface{}) { w.Header().Set("Content-Type", "application/json; charset=utf-8") enc := json.NewEncoder(w) enc.SetIndent("", " ") @@ -201,7 +201,7 @@ func JSON(w http.ResponseWriter, data interface{}) { } } -func HTML(w http.ResponseWriter, target string, data interface{}) { +func html(w http.ResponseWriter, target string, data interface{}) { t := template.New(target) t.Funcs(funcMap) for _, filename := range AssetNames() { @@ -211,7 +211,7 @@ func HTML(w http.ResponseWriter, target string, data interface{}) { name := strings.TrimPrefix(filename, "templates/") b, err := Asset(filename) if err != nil { - Error(w, err) + _error(w, err) return } @@ -222,14 +222,14 @@ func HTML(w http.ResponseWriter, target string, data interface{}) { tmpl = t.New(name) } if _, err := tmpl.Parse(string(b)); err != nil { - Error(w, err) + _error(w, err) return } } w.Header().Set("Content-Type", "text/html; charset=utf-8") if err := t.Execute(w, data); err != nil { - Error(w, err) + _error(w, err) return } } From dd3d1b625d552cf962ba6837711c3599498f1d4b Mon Sep 17 00:00:00 2001 From: Thomas Krzero Date: Sat, 18 Nov 2017 01:05:30 +0100 Subject: [PATCH 3/3] Had to export some vars for html --- streamlist.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/streamlist.go b/streamlist.go index 1d4cc4d..fc88847 100644 --- a/streamlist.go +++ b/streamlist.go @@ -324,7 +324,8 @@ func (l *List) save() error { return overwrite(l.file(), b, 0644) } -func (l *List) hasMedia(media *Media) bool { +// HasMedia ... +func (l *List) HasMedia(media *Media) bool { for _, m := range l.Medias { if m.ID == media.ID { return true @@ -333,7 +334,8 @@ func (l *List) hasMedia(media *Media) bool { return false } -func (l *List) totalLength() (total int64) { +// TotalLength ... +func (l *List) TotalLength() (total int64) { for _, m := range l.Medias { total += m.Length } @@ -356,7 +358,7 @@ func (l *List) addMedia(media *Media) error { } func (l *List) removeMedia(media *Media) error { - if !l.hasMedia(media) { + if !l.HasMedia(media) { return nil } var medias []*Media