You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
180 lines
4.3 KiB
180 lines
4.3 KiB
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
"unicode"
|
|
|
|
"github.com/google/uuid"
|
|
"golang.org/x/text/transform"
|
|
"golang.org/x/text/unicode/norm"
|
|
"gopkg.in/yaml.v2"
|
|
)
|
|
|
|
type MediaStore struct {
|
|
StoreLocation string
|
|
}
|
|
|
|
func InitMediaStore(storeLocation string) (*MediaStore, error) {
|
|
err := os.MkdirAll(filepath.Join(storeLocation, ".current"), os.ModePerm)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &MediaStore{StoreLocation: storeLocation}, nil
|
|
}
|
|
|
|
func (store *MediaStore) GetUniqueID() string {
|
|
return uuid.New().String()
|
|
}
|
|
|
|
func (store *MediaStore) AddFile(fileName string) (*os.File, error) {
|
|
filename := filepath.Join(store.StoreLocation, ".current", fileName)
|
|
return os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666)
|
|
}
|
|
|
|
func (store *MediaStore) CommitPhoto(id string, timestamp time.Time, caption string) error {
|
|
return store.commitMedia(id, timestamp, caption, "photo")
|
|
}
|
|
|
|
func (store *MediaStore) CommitVideo(id string, timestamp time.Time, caption string) error {
|
|
return store.commitMedia(id, timestamp, caption, "video")
|
|
}
|
|
|
|
func (store *MediaStore) commitMedia(id string, timestamp time.Time, caption string, mediaType string) error {
|
|
entry := [1]map[string]string{{
|
|
"type": mediaType,
|
|
"date": timestamp.Format("2006-01-02T15:04:05-0700"),
|
|
"caption": caption,
|
|
"id": id,
|
|
}}
|
|
|
|
yamlData, err := yaml.Marshal(entry)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return appendToFile(filepath.Join(store.StoreLocation, ".current", "chat.yaml"), yamlData)
|
|
}
|
|
|
|
func appendToFile(filename string, data []byte) error {
|
|
f, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer f.Close()
|
|
if _, err = f.Write(data); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (store *MediaStore) GetCurrentAlbum() (string, error) {
|
|
yamlData, err := ioutil.ReadFile(filepath.Join(store.StoreLocation, ".current", "meta.yaml"))
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
// the album has not yet a name, it is not an error
|
|
return "", nil
|
|
} else {
|
|
return "", err
|
|
}
|
|
}
|
|
|
|
var metadata map[string]string = make(map[string]string)
|
|
err = yaml.UnmarshalStrict(yamlData, &metadata)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return metadata["title"], nil
|
|
}
|
|
|
|
func (store *MediaStore) CloseAlbum() error {
|
|
yamlData, err := ioutil.ReadFile(filepath.Join(store.StoreLocation, ".current", "meta.yaml"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var metadata map[string]string = make(map[string]string)
|
|
err = yaml.UnmarshalStrict(yamlData, &metadata)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
date, err := time.Parse("2006-01-02T15:04:05-0700", metadata["date"])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
folderName := date.Format("2006-01-02") + "-" + sanitizeAlbumName(metadata["title"])
|
|
err = os.Rename(filepath.Join(store.StoreLocation, ".current"), filepath.Join(store.StoreLocation, folderName))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func fileExists(filename string) bool {
|
|
_, err := os.Stat(filename)
|
|
return err == nil
|
|
}
|
|
|
|
func (store *MediaStore) NewAlbum(title string) error {
|
|
if fileExists(filepath.Join(store.StoreLocation, ".current/")) {
|
|
if fileExists(filepath.Join(store.StoreLocation, "/.current/meta.yaml")) {
|
|
err := store.CloseAlbum()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
err := os.MkdirAll(filepath.Join(store.StoreLocation, ".current/"), os.ModePerm)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
metadata := map[string]string{
|
|
"title": title,
|
|
"date": time.Now().Format("2006-01-02T15:04:05-0700"),
|
|
}
|
|
|
|
yamlData, err := yaml.Marshal(metadata)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = ioutil.WriteFile(filepath.Join(store.StoreLocation, ".current", "meta.yaml"), yamlData, 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func sanitizeAlbumName(albumName string) string {
|
|
albumName = strings.ToLower(albumName)
|
|
t := transform.Chain(norm.NFD, transform.RemoveFunc(func(r rune) bool {
|
|
return unicode.Is(unicode.Mn, r)
|
|
}), norm.NFC)
|
|
albumName, _, _ = transform.String(t, albumName)
|
|
|
|
reg, err := regexp.Compile("\\s+")
|
|
if err != nil {
|
|
panic(fmt.Errorf("Cannot compile regex: %s", err))
|
|
}
|
|
albumName = reg.ReplaceAllString(albumName, "-")
|
|
|
|
reg, err = regexp.Compile("[^-a-zA-Z0-9_]+")
|
|
if err != nil {
|
|
panic(fmt.Errorf("Cannot compile regex: %s", err))
|
|
}
|
|
albumName = reg.ReplaceAllString(albumName, "")
|
|
|
|
return albumName
|
|
}
|
|
|