mirror of
https://github.com/thebaer/cdr.git
synced 2024-11-15 01:31:01 +00:00
Add cdr preview
subcommand
This serves the mixtape site by running `cdr preview`
This commit is contained in:
parent
c26beff32d
commit
f0aa182c03
66
cmd/cdr/generate.go
Normal file
66
cmd/cdr/generate.go
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/thebaer/cdr"
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
cmdServe = cli.Command{
|
||||||
|
Name: "preview",
|
||||||
|
Usage: "serve the mixtape site",
|
||||||
|
Action: serveAction,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func newMixtape(wd string) (*cdr.Mixtape, error) {
|
||||||
|
m := &cdr.Mixtape{Tracks: []cdr.Track{}}
|
||||||
|
|
||||||
|
filepath.Walk(wd, func(path string, i os.FileInfo, err error) error {
|
||||||
|
if !i.IsDir() && !strings.HasPrefix(i.Name(), ".") && i.Name() != "index.html" {
|
||||||
|
t, err := cdr.NewTrack(i.Name())
|
||||||
|
if err == nil {
|
||||||
|
log.Printf("Skipping track %s: %v", i.Name(), err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
log.Println("Adding track", t.Title)
|
||||||
|
m.Tracks = append(m.Tracks, *t)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func serveAction(c *cli.Context) error {
|
||||||
|
wd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
m, err := newMixtape(wd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.RequestURI != "/" {
|
||||||
|
log.Printf("GET %s", r.RequestURI)
|
||||||
|
http.ServeFile(w, r, filepath.Join(wd, r.RequestURI))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err := cdr.Render(m, w)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[ERROR] Render failed! %s", err)
|
||||||
|
}
|
||||||
|
log.Printf("GET /")
|
||||||
|
})
|
||||||
|
|
||||||
|
return http.ListenAndServe(":9991", nil)
|
||||||
|
}
|
@ -16,6 +16,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
app.Commands = []*cli.Command{
|
app.Commands = []*cli.Command{
|
||||||
|
&cmdServe,
|
||||||
&cmdClean,
|
&cmdClean,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
26
render.go
Normal file
26
render.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
//go:generate inline -o templates.go -p cdr templates/parts.tmpl
|
||||||
|
|
||||||
|
package cdr
|
||||||
|
|
||||||
|
import (
|
||||||
|
"html/template"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Render(m *Mixtape, w io.Writer) error {
|
||||||
|
partsRawTmpl, err := ReadAsset("templates/parts.tmpl", false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
mixtapeRawTmpl, err := ioutil.ReadFile("mixtape.tmpl")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
t, err := template.New("mixtape").Parse(string(mixtapeRawTmpl) + string(partsRawTmpl))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
t.ExecuteTemplate(w, "mixtape", m)
|
||||||
|
return nil
|
||||||
|
}
|
12
sanitize.go
12
sanitize.go
@ -13,17 +13,16 @@ import (
|
|||||||
|
|
||||||
var trackNameReg = regexp.MustCompile("^([0-9]{2}).+")
|
var trackNameReg = regexp.MustCompile("^([0-9]{2}).+")
|
||||||
|
|
||||||
func NewTrack(file string) *Track {
|
func NewTrack(file string) (*Track, error) {
|
||||||
f, err := os.Open(file)
|
f, err := os.Open(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error loading file: %v", err)
|
return nil, fmt.Errorf("error loading file: %v", err)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
m, err := tag.ReadFrom(f)
|
m, err := tag.ReadFrom(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil, fmt.Errorf("unable to read file: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Track{
|
return &Track{
|
||||||
@ -36,7 +35,10 @@ func NewTrack(file string) *Track {
|
|||||||
// RenameTrack takes a filename, opens it, reads the metadata, and returns both
|
// RenameTrack takes a filename, opens it, reads the metadata, and returns both
|
||||||
// the old and new filename.
|
// the old and new filename.
|
||||||
func RenameTrack(file string) string {
|
func RenameTrack(file string) string {
|
||||||
t := NewTrack(file)
|
t, err := NewTrack(file)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// Extract playlist track number from filename
|
// Extract playlist track number from filename
|
||||||
fMatch := trackNameReg.FindStringSubmatch(t.Filename)
|
fMatch := trackNameReg.FindStringSubmatch(t.Filename)
|
||||||
|
81
templates.go
Normal file
81
templates.go
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
// Code generated by "inline -o templates.go -p cdr templates/parts.tmpl" -- DO NOT EDIT --
|
||||||
|
|
||||||
|
package cdr
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ReadAsset(file string, useLocal bool) ([]byte, error) {
|
||||||
|
if useLocal {
|
||||||
|
return ioutil.ReadFile(file)
|
||||||
|
}
|
||||||
|
if f, ok := files[file]; ok {
|
||||||
|
return []byte(f), nil
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("file doesn't exist.")
|
||||||
|
}
|
||||||
|
|
||||||
|
var files = map[string]string{
|
||||||
|
"templates/parts.tmpl": `{{define "player"}}
|
||||||
|
{{with $x := index . 0}}
|
||||||
|
<audio id="player" preload="auto" tabindex="0" controls>
|
||||||
|
<source src="{{$x.Filename}}">
|
||||||
|
</audio>
|
||||||
|
{{end}}
|
||||||
|
<ol id="playlist">
|
||||||
|
{{range $i, $el := .}}
|
||||||
|
<li{{if eq $i 0}} class="active"{{end}}>
|
||||||
|
<a href="{{$el.Filename}}">{{$el.Artist}} - {{$el.Title}}</a>
|
||||||
|
</li>
|
||||||
|
{{end}}
|
||||||
|
</ol>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{define "full-player"}}
|
||||||
|
{{template "player" .}}
|
||||||
|
{{template "playlist-js"}}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{define "playlist-js"}}
|
||||||
|
<script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function() {
|
||||||
|
init();
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
var current = 0;
|
||||||
|
var $audio = $('#player');
|
||||||
|
var $playlist = $('#playlist');
|
||||||
|
var $tracks = $playlist.find('li a');
|
||||||
|
var len = $tracks.length - 1;
|
||||||
|
$playlist.on('click', 'a', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
link = $(this);
|
||||||
|
current = link.parent().index();
|
||||||
|
run(link, $audio[0]);
|
||||||
|
});
|
||||||
|
$audio[0].addEventListener('ended', function (e) {
|
||||||
|
current++;
|
||||||
|
if (current == len) {
|
||||||
|
current = 0;
|
||||||
|
link = $playlist.find('a')[0];
|
||||||
|
} else {
|
||||||
|
link = $playlist.find('a')[current];
|
||||||
|
}
|
||||||
|
run($(link), $audio[0]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function run($link, $player) {
|
||||||
|
$player.src = $link.attr('href');
|
||||||
|
par = $link.parent();
|
||||||
|
par.addClass('active').siblings().removeClass('active');
|
||||||
|
$player.load();
|
||||||
|
$player.play();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{{end}}`,
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user