272 lines
5.1 KiB
Go
272 lines
5.1 KiB
Go
package client
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"html/template"
|
|
"hummingbard/config"
|
|
"io"
|
|
"io/ioutil"
|
|
"log"
|
|
"math"
|
|
"os"
|
|
"path/filepath"
|
|
"reflect"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type BasePage struct {
|
|
Name string `json:"name"`
|
|
LoggedInUser interface{} `json:"logged_in_user"`
|
|
Nonce string `json:"nonce"`
|
|
}
|
|
|
|
type Template struct {
|
|
*template.Template
|
|
}
|
|
|
|
var fMap = template.FuncMap{
|
|
"InsertJS": insertJS,
|
|
"InsertCSS": insertCSS,
|
|
"FormatTime": formatTime,
|
|
"Map": mapp,
|
|
"FileSize": FileSize,
|
|
"ToString": ToString,
|
|
"IsLastItem": IsLastItem,
|
|
"StripMXCPrefix": StripMXCPrefix,
|
|
"AspectRatio": AspectRatio,
|
|
"IsUserProfile": isUserProfile,
|
|
"RandomString": randomString,
|
|
"Title": title,
|
|
"Sum": sum,
|
|
"Concat": concat,
|
|
"Trunc": truncate,
|
|
"HasColon": hasColon,
|
|
}
|
|
|
|
func hasColon(s string) bool {
|
|
return strings.Contains(s, ":")
|
|
}
|
|
|
|
func truncate(s string, i int) string {
|
|
|
|
runes := []rune(s)
|
|
if len(runes) > i {
|
|
return string(runes[:i])
|
|
}
|
|
|
|
return s
|
|
}
|
|
|
|
func concat(values ...string) string {
|
|
return strings.Trim(strings.Join(values, ""), "")
|
|
}
|
|
|
|
func sum(i, g int) int {
|
|
return i + g
|
|
}
|
|
|
|
func title(s string) string {
|
|
return strings.Title(s)
|
|
}
|
|
|
|
func randomString(i int) string {
|
|
return RandomString(i)
|
|
}
|
|
|
|
func isUserProfile(s string) bool {
|
|
conf, err := config.Read()
|
|
if err != nil {
|
|
log.Println(err)
|
|
}
|
|
return strings.Contains(s, "@") && strings.Contains(s, conf.Client.Domain)
|
|
}
|
|
|
|
func AspectRatio(x, y string) string {
|
|
height, err := strconv.Atoi(x)
|
|
if err != nil {
|
|
log.Println(err)
|
|
}
|
|
width, err := strconv.Atoi(y)
|
|
if err != nil {
|
|
log.Println(err)
|
|
}
|
|
|
|
return fmt.Sprintf(`%d %d`, height, width)
|
|
}
|
|
|
|
func mapp(values ...interface{}) (map[string]interface{}, error) {
|
|
if len(values)%2 != 0 {
|
|
return nil, errors.New("invalid dict call")
|
|
}
|
|
dict := make(map[string]interface{}, len(values)/2)
|
|
for i := 0; i < len(values); i += 2 {
|
|
key, ok := values[i].(string)
|
|
if !ok {
|
|
return nil, errors.New("dict keys must be strings")
|
|
}
|
|
dict[key] = values[i+1]
|
|
}
|
|
return dict, nil
|
|
}
|
|
|
|
func formatTime(t int64) string {
|
|
ut := time.Unix(t, 0)
|
|
log.Println(ut)
|
|
log.Println(ut)
|
|
log.Println(ut)
|
|
return fmt.Sprintf(`%s`, ut)
|
|
}
|
|
|
|
func insertJS(name string) template.HTML {
|
|
|
|
root := "static/js"
|
|
files, err := ioutil.ReadDir(root)
|
|
if err != nil {
|
|
}
|
|
|
|
var scr string
|
|
|
|
for _, file := range files {
|
|
x := strings.Split(file.Name(), ".")
|
|
if name == x[0] && x[len(x)-1] == "js" {
|
|
scr = fmt.Sprintf("/static/js/%s", file.Name())
|
|
return template.HTML(scr)
|
|
}
|
|
}
|
|
scr = fmt.Sprintf("/static/js/%s.js", "missing")
|
|
return template.HTML(scr)
|
|
}
|
|
|
|
func insertCSS(name string) template.HTML {
|
|
|
|
root := "static/css"
|
|
files, err := ioutil.ReadDir(root)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
var scr string
|
|
|
|
for _, file := range files {
|
|
x := strings.Split(file.Name(), ".")
|
|
if name == x[0] && x[len(x)-1] == "css" {
|
|
scr = fmt.Sprintf("/static/css/%s", file.Name())
|
|
return template.HTML(scr)
|
|
}
|
|
}
|
|
return template.HTML("")
|
|
}
|
|
|
|
func NewTemplate() (*Template, error) {
|
|
|
|
tmpl, err := findAndParseTemplates([]interface{}{"templates"}, fMap)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
return tmpl, err
|
|
}
|
|
|
|
func (c *Client) ReloadTemplates() {
|
|
tmpl, err := findAndParseTemplates([]interface{}{"templates"}, fMap)
|
|
|
|
if err != nil {
|
|
log.Printf("parsing: %s", err)
|
|
}
|
|
c.Templates = tmpl
|
|
}
|
|
|
|
func (t *Template) execute(wr io.Writer, name string, data interface{}) error {
|
|
|
|
pdat := reflect.TypeOf(data)
|
|
|
|
newdat := reflect.New(pdat)
|
|
|
|
t.ExecuteTemplate(wr, name, newdat)
|
|
|
|
return nil
|
|
}
|
|
|
|
func findAndParseTemplates(rootDir interface{}, funcMap template.FuncMap) (*Template, error) {
|
|
root := template.New("")
|
|
|
|
tempo := &Template{root}
|
|
|
|
var err error
|
|
|
|
for _, x := range rootDir.([]interface{}) {
|
|
cleanRoot := filepath.Clean(x.(string))
|
|
pfx := len(cleanRoot) + 1
|
|
err = filepath.Walk(cleanRoot, func(path string, info os.FileInfo, e1 error) error {
|
|
if !info.IsDir() && strings.HasSuffix(path, ".html") {
|
|
if e1 != nil {
|
|
return e1
|
|
}
|
|
|
|
b, e2 := ioutil.ReadFile(path)
|
|
if e2 != nil {
|
|
return e2
|
|
}
|
|
|
|
name := path[pfx:]
|
|
|
|
t := tempo.New(name).Funcs(funcMap)
|
|
t, e2 = t.Parse(string(b))
|
|
if e2 != nil {
|
|
return e2
|
|
}
|
|
}
|
|
|
|
return nil
|
|
})
|
|
}
|
|
|
|
return tempo, err
|
|
}
|
|
|
|
func IsLastItem(index, length int) bool {
|
|
return index == length-1
|
|
}
|
|
|
|
func Round(val float64, roundOn float64, places int) (newVal float64) {
|
|
var round float64
|
|
pow := math.Pow(10, float64(places))
|
|
digit := pow * val
|
|
_, div := math.Modf(digit)
|
|
if div >= roundOn {
|
|
round = math.Ceil(digit)
|
|
} else {
|
|
round = math.Floor(digit)
|
|
}
|
|
newVal = round / pow
|
|
return
|
|
}
|
|
|
|
func FileSize(t float64) string {
|
|
suffixes := []string{"Bytes", "KB", "MB", "GB"}
|
|
|
|
base := math.Log(float64(t)) / math.Log(1024)
|
|
getSize := Round(math.Pow(1024, base-math.Floor(base)), .5, 2)
|
|
getSuffix := suffixes[int(math.Floor(base))]
|
|
|
|
return strconv.FormatFloat(getSize, 'f', -1, 64) + " " + string(getSuffix)
|
|
}
|
|
|
|
func ToString(value interface{}) string {
|
|
switch v := value.(type) {
|
|
case string:
|
|
return v
|
|
case int:
|
|
return strconv.Itoa(v)
|
|
case uint:
|
|
return fmt.Sprint(v)
|
|
case float64:
|
|
return fmt.Sprint(v)
|
|
default:
|
|
return ""
|
|
}
|
|
}
|