musicutil/commands/genhtml/genhtml.go

182 lines
4.2 KiB
Go
Raw Normal View History

2022-02-22 14:02:58 +00:00
package genhtml
import (
"fmt"
"html"
"os"
"sort"
"github.com/akamensky/argparse"
"github.com/rs/zerolog/log"
"gitlab.com/ChaotiCryptidz/musicutil/types"
"gitlab.com/ChaotiCryptidz/musicutil/utils"
)
type GenHTMLCommandArgs struct {
Source *string
Dest *string
Title *string
Description *string
}
func RegisterGenHTMLCommand(parser *argparse.Parser) (*argparse.Command, *GenHTMLCommandArgs) {
cmd := parser.NewCommand("genhtml", "generates a html file or multiple html files for showing music library")
arguments := &GenHTMLCommandArgs{}
arguments.Source = cmd.String("s", "src", &argparse.Options{
Required: true,
Validate: func(args []string) error {
fileInfo, err := os.Stat(args[0])
if err != nil {
return fmt.Errorf("Source does not exist")
}
if !fileInfo.IsDir() {
return fmt.Errorf("Source is not a directory")
}
return nil
},
})
arguments.Dest = cmd.String("d", "dest", &argparse.Options{Required: true})
arguments.Title = cmd.String("", "title", &argparse.Options{Default: ""})
arguments.Description = cmd.String("", "description", &argparse.Options{Default: ""})
return cmd, arguments
}
type GenHTMLCommand struct {
Args *GenHTMLCommandArgs
Files []*types.File
}
func NewGenHTMLCommand(args *GenHTMLCommandArgs) *GenHTMLCommand {
return &GenHTMLCommand{
Args: args,
Files: make([]*types.File, 0),
}
}
func (c *GenHTMLCommand) scan_for_music() {
log.Info().Msg("Scanning For Music")
files, err := utils.ScanForMusic(*c.Args.Source)
if err != nil {
panic(err)
}
c.Files = files
}
func (c *GenHTMLCommand) load_tag_information() {
log.Info().Msg("Loading Tag Information")
for _, file := range c.Files {
log.Info().Str("file", file.JoinFilename()).Msg("Loading Tags")
tags, err := utils.ExtractTags(file)
if err != nil {
panic(err)
}
file.Tags = tags
}
}
func (c *GenHTMLCommand) Run() {
log.Info().Msg("Generating HTML")
c.scan_for_music()
c.load_tag_information()
sort.Slice(c.Files, func(i, j int) bool {
if c.Files[i].PathFromSource != c.Files[j].PathFromSource {
return c.Files[i].PathFromSource < c.Files[j].PathFromSource
}
if c.Files[i].Tags.Title != c.Files[j].Tags.Title {
return c.Files[i].Tags.Title < c.Files[j].Tags.Title
}
return c.Files[i].Tags.Artist < c.Files[j].Tags.Artist
})
html_content := ""
html_content = html_content + fmt.Sprintf(`
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://unpkg.com/purecss@2.0.6/build/pure-min.css">
<title>%s</title>
<meta property="og:title" content="%s" />
<meta property="og:description" content="%s" />
</head>
<body>
`, *c.Args.Title, *c.Args.Title, *c.Args.Description)
html_content = html_content + tableForFiles(c.Files, true)
html_content = html_content + "</body></html>"
html_file, err := os.Create(*c.Args.Dest + "/index.html")
if err != nil {
log.Fatal().Err(err).Msg("Could not write HTML file")
}
defer html_file.Close()
html_file.Write([]byte(html_content))
}
func tableForFiles(files []*types.File, includesPath bool) string {
html_content := ""
path_head := ""
if includesPath {
path_head = "<th>Path</th>"
}
html_content += fmt.Sprintf(`
<table class="pure-table pure-table-horizontal">
<thead>
<tr>
%s
<th>Title</th>
<th>Artist</th>
<th>Format</th>
</tr>
</thead>
<tbody>
`, path_head)
isOdd := true
for _, file := range files {
tdClass := "pure-table-even"
if isOdd {
tdClass = "pure-table-odd"
}
data_title := html.EscapeString(file.Tags.Title)
data_artist := html.EscapeString(file.Tags.Artist)
data_extension := html.EscapeString(file.Extension)
path_data := ""
if includesPath {
data_path := html.EscapeString(file.PathFromSource)
path_data = fmt.Sprintf("<td>%s</td>", data_path)
}
html_content = html_content + fmt.Sprintf(`
<tr class="%s">
%s
<td>%s</td>
<td>%s</td>
<td>%s</td>
</tr>
`, tdClass, path_data, data_title, data_artist, data_extension)
isOdd = !isOdd
}
html_content = html_content + `
</tbody>
</table>
`
return html_content
}