docs
This commit is contained in:
parent
0979457d75
commit
a7a5eee66f
6 changed files with 36 additions and 0 deletions
|
@ -17,6 +17,7 @@ import (
|
|||
"github.com/wybiral/tube/pkg/media"
|
||||
)
|
||||
|
||||
// App represents main application.
|
||||
type App struct {
|
||||
Config *Config
|
||||
Library *media.Library
|
||||
|
@ -26,6 +27,7 @@ type App struct {
|
|||
Router *mux.Router
|
||||
}
|
||||
|
||||
// NewApp returns a new instance of App from Config.
|
||||
func NewApp(cfg *Config) (*App, error) {
|
||||
if cfg == nil {
|
||||
cfg = DefaultConfig()
|
||||
|
@ -33,24 +35,30 @@ func NewApp(cfg *Config) (*App, error) {
|
|||
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 Router
|
||||
r := mux.NewRouter().StrictSlash(true)
|
||||
r.HandleFunc("/", a.indexHandler).Methods("GET")
|
||||
r.HandleFunc("/v/{id}.mp4", a.videoHandler).Methods("GET")
|
||||
r.HandleFunc("/t/{id}", a.thumbHandler).Methods("GET")
|
||||
r.HandleFunc("/v/{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/")),
|
||||
|
@ -60,6 +68,7 @@ func NewApp(cfg *Config) (*App, error) {
|
|||
return a, nil
|
||||
}
|
||||
|
||||
// Run imports the library and starts server.
|
||||
func (a *App) Run() error {
|
||||
path := a.Config.LibraryPath
|
||||
err := a.Library.Import(path)
|
||||
|
@ -71,6 +80,7 @@ func (a *App) Run() error {
|
|||
return http.Serve(a.Listener, a.Router)
|
||||
}
|
||||
|
||||
// Watch the library path and update Library with changes.
|
||||
func (a *App) watch() {
|
||||
for {
|
||||
e, ok := <-a.Watcher.Events
|
||||
|
@ -92,6 +102,7 @@ func (a *App) watch() {
|
|||
}
|
||||
}
|
||||
|
||||
// HTTP handler for /
|
||||
func (a *App) indexHandler(w http.ResponseWriter, r *http.Request) {
|
||||
log.Printf("/")
|
||||
pl := a.Library.Playlist()
|
||||
|
@ -108,6 +119,7 @@ func (a *App) indexHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
// HTTP handler for /v/id
|
||||
func (a *App) pageHandler(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
id := vars["id"]
|
||||
|
@ -133,6 +145,7 @@ func (a *App) pageHandler(w http.ResponseWriter, r *http.Request) {
|
|||
})
|
||||
}
|
||||
|
||||
// HTTP handler for /v/id.mp4
|
||||
func (a *App) videoHandler(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
id := vars["id"]
|
||||
|
@ -149,6 +162,7 @@ func (a *App) videoHandler(w http.ResponseWriter, r *http.Request) {
|
|||
http.ServeFile(w, r, path)
|
||||
}
|
||||
|
||||
// HTTP handler for /t/id
|
||||
func (a *App) thumbHandler(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
id := vars["id"]
|
||||
|
@ -167,6 +181,7 @@ func (a *App) thumbHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
// HTTP handler for /feed.xml
|
||||
func (a *App) rssHandler(w http.ResponseWriter, r *http.Request) {
|
||||
cfg := a.Config.Feed
|
||||
now := time.Now()
|
||||
|
|
|
@ -5,17 +5,20 @@ import (
|
|||
"os"
|
||||
)
|
||||
|
||||
// Config settings for main App.
|
||||
type Config struct {
|
||||
LibraryPath string `json:"library"`
|
||||
Server *ServerConfig `json:"server"`
|
||||
Feed *FeedConfig `json:"feed"`
|
||||
}
|
||||
|
||||
// ServerConfig settings for App Server.
|
||||
type ServerConfig struct {
|
||||
Host string `json:"host"`
|
||||
Port int `json:"port"`
|
||||
}
|
||||
|
||||
// FeedConfig settings for App Feed.
|
||||
type FeedConfig struct {
|
||||
ExternalURL string `json:"external_url"`
|
||||
Title string `json:"title"`
|
||||
|
@ -28,6 +31,7 @@ type FeedConfig struct {
|
|||
Copyright string `json:"copyright"`
|
||||
}
|
||||
|
||||
// DefaultConfig returns Config initialized with default values.
|
||||
func DefaultConfig() *Config {
|
||||
return &Config{
|
||||
LibraryPath: "videos",
|
||||
|
@ -41,6 +45,7 @@ func DefaultConfig() *Config {
|
|||
}
|
||||
}
|
||||
|
||||
// ReadFile reads a JSON file into Config.
|
||||
func (c *Config) ReadFile(path string) error {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
// Instead of using the default new.Listener this file will construct a custom
|
||||
// one. The main purpose for this is to have more control over the settings
|
||||
// (like keep-alive) and to retrieve the assigned port when using port 0.
|
||||
|
||||
package app
|
||||
|
||||
import (
|
||||
|
|
|
@ -9,11 +9,13 @@ import (
|
|||
"sync"
|
||||
)
|
||||
|
||||
// Library manages importing and retrieving video data.
|
||||
type Library struct {
|
||||
mu sync.RWMutex
|
||||
Videos map[string]*Video
|
||||
}
|
||||
|
||||
// NewLibrary returns new instance of Library.
|
||||
func NewLibrary() *Library {
|
||||
lib := &Library{
|
||||
Videos: make(map[string]*Video),
|
||||
|
@ -21,6 +23,7 @@ func NewLibrary() *Library {
|
|||
return lib
|
||||
}
|
||||
|
||||
// Import adds all valid videos from a given path.
|
||||
func (lib *Library) Import(path string) error {
|
||||
files, err := ioutil.ReadDir(path)
|
||||
if err != nil {
|
||||
|
@ -36,6 +39,7 @@ func (lib *Library) Import(path string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Add adds a single video from a given file path.
|
||||
func (lib *Library) Add(path string) error {
|
||||
v, err := ParseVideo(path)
|
||||
if err != nil {
|
||||
|
@ -48,6 +52,7 @@ func (lib *Library) Add(path string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Remove removes a single video from a given file path.
|
||||
func (lib *Library) Remove(path string) {
|
||||
name := filepath.Base(path)
|
||||
// ID is name without extension
|
||||
|
@ -65,6 +70,7 @@ func (lib *Library) Remove(path string) {
|
|||
}
|
||||
}
|
||||
|
||||
// Playlist returns a sorted Playlist of all videos.
|
||||
func (lib *Library) Playlist() Playlist {
|
||||
lib.mu.RLock()
|
||||
defer lib.mu.RUnlock()
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
package media
|
||||
|
||||
// Playlist holds an array of videos capable of sorting by Timestamp.
|
||||
type Playlist []*Video
|
||||
|
||||
// Len returns length of array (for sorting).
|
||||
func (p Playlist) Len() int {
|
||||
return len(p)
|
||||
}
|
||||
|
||||
// Swap swaps two values in array by index (for sorting).
|
||||
func (p Playlist) Swap(i, j int) {
|
||||
p[i], p[j] = p[j], p[i]
|
||||
}
|
||||
|
||||
// Less returns true if p[i] Timestamp is after p[j] (for sorting).
|
||||
func (p Playlist) Less(i, j int) bool {
|
||||
return p[i].Timestamp.After(p[j].Timestamp)
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"github.com/dhowden/tag"
|
||||
)
|
||||
|
||||
// Video represents metadata for a single video.
|
||||
type Video struct {
|
||||
ID string
|
||||
Title string
|
||||
|
@ -20,6 +21,7 @@ type Video struct {
|
|||
Timestamp time.Time
|
||||
}
|
||||
|
||||
// ParseVideo parses a video file's metadata and returns a Video.
|
||||
func ParseVideo(path string) (*Video, error) {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
|
|
Loading…
Reference in a new issue