summaryrefslogtreecommitdiff
path: root/pkg/app/app.go
diff options
context:
space:
mode:
authorJames Mills <prologic@shortcircuit.net.au>2020-03-21 09:55:06 +1000
committerJames Mills <prologic@shortcircuit.net.au>2020-03-21 09:55:06 +1000
commit4dae45a68ff1ff32a251a5835b2a2723ae125d1c (patch)
treeb3abe641f39f50ac444aee2bb617d7b4ab44187d /pkg/app/app.go
parent76fa613b7eaf1c8626d2a51901c623af7bf1a665 (diff)
Restructured source code layout, Added rice support for templates and static assets
Diffstat (limited to 'pkg/app/app.go')
-rw-r--r--pkg/app/app.go222
1 files changed, 0 insertions, 222 deletions
diff --git a/pkg/app/app.go b/pkg/app/app.go
deleted file mode 100644
index 0efd22a..0000000
--- a/pkg/app/app.go
+++ /dev/null
@@ -1,222 +0,0 @@
-// Package app manages main application server.
-package app
-
-import (
- "errors"
- "fmt"
- "html/template"
- "log"
- "net"
- "net/http"
- "path"
-
- "github.com/fsnotify/fsnotify"
- "github.com/gorilla/mux"
- "github.com/wybiral/tube/pkg/media"
- "github.com/wybiral/tube/pkg/onionkey"
-)
-
-// App represents main application.
-type App struct {
- Config *Config
- Library *media.Library
- Watcher *fsnotify.Watcher
- Templates *template.Template
- Feed []byte
- Tor *tor
- Listener net.Listener
- Router *mux.Router
-}
-
-// NewApp returns a new instance of App from Config.
-func NewApp(cfg *Config) (*App, error) {
- if cfg == nil {
- cfg = DefaultConfig()
- }
- a := &App{
- Config: cfg,
- }
- // Setup Library
- a.Library = media.NewLibrary()
- // Setup Watcher
- w, err := fsnotify.NewWatcher()
- if err != nil {
- return nil, err
- }
- a.Watcher = w
- // Setup Listener
- ln, err := newListener(cfg.Server)
- if err != nil {
- return nil, err
- }
- a.Listener = ln
- // Setup Templates
- a.Templates = template.Must(template.ParseGlob("templates/*"))
- // Setup Tor
- if cfg.Tor.Enable {
- t, err := newTor(cfg.Tor)
- if err != nil {
- return nil, err
- }
- a.Tor = t
- }
- // Setup Router
- r := mux.NewRouter().StrictSlash(true)
- r.HandleFunc("/", a.indexHandler).Methods("GET")
- r.HandleFunc("/v/{id}.mp4", a.videoHandler).Methods("GET")
- r.HandleFunc("/v/{prefix}/{id}.mp4", a.videoHandler).Methods("GET")
- r.HandleFunc("/t/{id}", a.thumbHandler).Methods("GET")
- r.HandleFunc("/t/{prefix}/{id}", a.thumbHandler).Methods("GET")
- r.HandleFunc("/v/{id}", a.pageHandler).Methods("GET")
- r.HandleFunc("/v/{prefix}/{id}", a.pageHandler).Methods("GET")
- r.HandleFunc("/feed.xml", a.rssHandler).Methods("GET")
- // Static file handler
- fsHandler := http.StripPrefix(
- "/static/",
- http.FileServer(http.Dir("./static/")),
- )
- r.PathPrefix("/static/").Handler(fsHandler).Methods("GET")
- a.Router = r
- return a, nil
-}
-
-// Run imports the library and starts server.
-func (a *App) Run() error {
- if a.Tor != nil {
- var err error
- cs := a.Config.Server
- key := a.Tor.OnionKey
- if key == nil {
- key, err = onionkey.GenerateKey()
- if err != nil {
- return err
- }
- a.Tor.OnionKey = key
- }
- onion, err := key.Onion()
- if err != nil {
- return err
- }
- onion.Ports[80] = fmt.Sprintf("%s:%d", cs.Host, cs.Port)
- err = a.Tor.Controller.AddOnion(onion)
- if err != nil {
- return errors.New("unable to start Tor onion service")
- }
- log.Printf("Onion service: http://%s.onion", onion.ServiceID)
- }
- for _, pc := range a.Config.Library {
- p := &media.Path{
- Path: pc.Path,
- Prefix: pc.Prefix,
- }
- err := a.Library.AddPath(p)
- if err != nil {
- return err
- }
- err = a.Library.Import(p)
- if err != nil {
- return err
- }
- a.Watcher.Add(p.Path)
- }
- buildFeed(a)
- go startWatcher(a)
- return http.Serve(a.Listener, a.Router)
-}
-
-// HTTP handler for /
-func (a *App) indexHandler(w http.ResponseWriter, r *http.Request) {
- log.Printf("/")
- pl := a.Library.Playlist()
- if len(pl) > 0 {
- http.Redirect(w, r, "/v/"+pl[0].ID, 302)
- } else {
- a.Templates.ExecuteTemplate(w, "index.html", &struct {
- Playing *media.Video
- Playlist media.Playlist
- }{
- Playing: &media.Video{ID: ""},
- Playlist: a.Library.Playlist(),
- })
- }
-}
-
-// HTTP handler for /v/id
-func (a *App) pageHandler(w http.ResponseWriter, r *http.Request) {
- vars := mux.Vars(r)
- id := vars["id"]
- prefix, ok := vars["prefix"]
- if ok {
- id = path.Join(prefix, id)
- }
- log.Printf("/v/%s", id)
- playing, ok := a.Library.Videos[id]
- if !ok {
- a.Templates.ExecuteTemplate(w, "index.html", &struct {
- Playing *media.Video
- Playlist media.Playlist
- }{
- Playing: &media.Video{ID: ""},
- Playlist: a.Library.Playlist(),
- })
- return
- }
- w.Header().Set("Content-Type", "text/html; charset=utf-8")
- a.Templates.ExecuteTemplate(w, "index.html", &struct {
- Playing *media.Video
- Playlist media.Playlist
- }{
- Playing: playing,
- Playlist: a.Library.Playlist(),
- })
-}
-
-// HTTP handler for /v/id.mp4
-func (a *App) videoHandler(w http.ResponseWriter, r *http.Request) {
- vars := mux.Vars(r)
- id := vars["id"]
- prefix, ok := vars["prefix"]
- if ok {
- id = path.Join(prefix, id)
- }
- log.Printf("/v/%s", id)
- m, ok := a.Library.Videos[id]
- if !ok {
- return
- }
- title := m.Title
- disposition := "attachment; filename=\"" + title + ".mp4\""
- w.Header().Set("Content-Disposition", disposition)
- w.Header().Set("Content-Type", "video/mp4")
- http.ServeFile(w, r, m.Path)
-}
-
-// HTTP handler for /t/id
-func (a *App) thumbHandler(w http.ResponseWriter, r *http.Request) {
- vars := mux.Vars(r)
- id := vars["id"]
- prefix, ok := vars["prefix"]
- if ok {
- id = path.Join(prefix, id)
- }
- log.Printf("/t/%s", id)
- m, ok := a.Library.Videos[id]
- if !ok {
- return
- }
- w.Header().Set("Cache-Control", "public, max-age=7776000")
- if m.ThumbType == "" {
- w.Header().Set("Content-Type", "image/jpeg")
- http.ServeFile(w, r, "static/defaulticon.jpg")
- } else {
- w.Header().Set("Content-Type", m.ThumbType)
- w.Write(m.Thumb)
- }
-}
-
-// HTTP handler for /feed.xml
-func (a *App) rssHandler(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Cache-Control", "public, max-age=7776000")
- w.Header().Set("Content-Type", "text/xml")
- w.Write(a.Feed)
-}