152 lines
2.3 KiB
Go
152 lines
2.3 KiB
Go
package templates
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"html/template"
|
|
"slices"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func dict(values ...any) (map[string]any, error) {
|
|
if len(values)%2 != 0 {
|
|
return nil, fmt.Errorf("dict expects even number of values, got %d", len(values))
|
|
}
|
|
out := make(map[string]any, len(values)/2)
|
|
for i := 0; i < len(values); i += 2 {
|
|
key, ok := values[i].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("dict key at index %d is not a string", i)
|
|
}
|
|
out[key] = values[i+1]
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
func jsonAttr(v any) (template.HTMLAttr, error) {
|
|
b, err := json.Marshal(v)
|
|
if err != nil {
|
|
return "", fmt.Errorf("json marshal: %w", err)
|
|
}
|
|
return template.HTMLAttr(b), nil
|
|
}
|
|
|
|
func genresParams(genres []int) string {
|
|
if len(genres) == 0 {
|
|
return ""
|
|
}
|
|
var b strings.Builder
|
|
for i, g := range genres {
|
|
if i > 0 {
|
|
b.WriteByte('&')
|
|
}
|
|
b.WriteString("genres=")
|
|
b.WriteString(strconv.Itoa(g))
|
|
}
|
|
return b.String()
|
|
}
|
|
|
|
func hasGenre(id int, genres []int) bool {
|
|
return slices.Contains(genres, id)
|
|
}
|
|
|
|
func div(a, b float64) float64 {
|
|
if b == 0 {
|
|
return 0
|
|
}
|
|
return a / b
|
|
}
|
|
|
|
func ceilDiv(a, b int) int {
|
|
if b == 0 {
|
|
return 0
|
|
}
|
|
return (a + b - 1) / b
|
|
}
|
|
|
|
func idiv(a, b int) int {
|
|
if b == 0 {
|
|
return 0
|
|
}
|
|
return a / b
|
|
}
|
|
|
|
func atoi(v any) int {
|
|
s, ok := v.(string)
|
|
if !ok {
|
|
return 0
|
|
}
|
|
n, err := strconv.Atoi(s)
|
|
if err != nil {
|
|
return 0
|
|
}
|
|
return n
|
|
}
|
|
|
|
func seq(v any) []int {
|
|
count := 0
|
|
switch n := v.(type) {
|
|
case int:
|
|
count = n
|
|
case int64:
|
|
if n > int64(^uint(0)>>1) {
|
|
count = 0
|
|
} else {
|
|
count = int(n)
|
|
}
|
|
}
|
|
if count <= 0 {
|
|
return []int{}
|
|
}
|
|
res := make([]int, count)
|
|
for i := 0; i < count; i++ {
|
|
res[i] = i
|
|
}
|
|
return res
|
|
}
|
|
|
|
func toInt(v any) int {
|
|
switch n := v.(type) {
|
|
case int:
|
|
return n
|
|
case int64:
|
|
if n > int64(^uint(0)>>1) {
|
|
return 0
|
|
}
|
|
return int(n)
|
|
case float64:
|
|
if n > float64(int(^uint(0)>>1)) {
|
|
return 0
|
|
}
|
|
return int(n)
|
|
case string:
|
|
i, err := strconv.Atoi(n)
|
|
if err != nil {
|
|
return 0
|
|
}
|
|
return i
|
|
default:
|
|
return 0
|
|
}
|
|
}
|
|
|
|
func percent(current, total float64) float64 {
|
|
if total == 0 {
|
|
return 0
|
|
}
|
|
return (current / total) * 100
|
|
}
|
|
|
|
func formatDate(dateStr string) string {
|
|
t, err := time.Parse(time.RFC3339, dateStr)
|
|
if err != nil {
|
|
t, err = time.Parse("2006-01-02T15:04:05+00:00", dateStr)
|
|
if err != nil {
|
|
return dateStr
|
|
}
|
|
}
|
|
return t.Format("Jan 2, 2006")
|
|
}
|