2024-03-12 15:49:08 +01:00
|
|
|
package services
|
|
|
|
|
|
|
|
import (
|
|
|
|
"io"
|
|
|
|
"log/slog"
|
|
|
|
"os"
|
2024-06-11 11:27:17 +02:00
|
|
|
"path/filepath"
|
2024-03-12 15:49:08 +01:00
|
|
|
"strings"
|
|
|
|
|
2024-09-30 20:16:29 +02:00
|
|
|
"gitlab.unjx.de/flohoss/godash/pkg/media"
|
2024-03-12 15:49:08 +01:00
|
|
|
"gopkg.in/yaml.v3"
|
|
|
|
)
|
|
|
|
|
2024-06-11 11:27:17 +02:00
|
|
|
const storageFolder = "storage/"
|
|
|
|
const iconsFolder = storageFolder + "icons/"
|
|
|
|
const bookmarkFile = storageFolder + "bookmarks.yaml"
|
2024-03-12 15:49:08 +01:00
|
|
|
const defaultConfig = `links:
|
|
|
|
- category: "Code"
|
|
|
|
entries:
|
|
|
|
- name: "Github"
|
|
|
|
url: "https://github.com"
|
|
|
|
|
|
|
|
applications:
|
|
|
|
- category: "Code"
|
|
|
|
entries:
|
2024-06-11 18:36:49 +02:00
|
|
|
- name: "GitHub"
|
2024-09-30 12:05:12 +02:00
|
|
|
icon: "shi/github.svg"
|
2024-06-11 18:36:49 +02:00
|
|
|
ignore_color: true
|
|
|
|
url: "https://github.com"
|
|
|
|
- name: "Home Assistant"
|
2024-09-30 14:14:09 +02:00
|
|
|
icon: "shi/home-assistant.svg"
|
2024-06-11 18:36:49 +02:00
|
|
|
url: "https://www.home-assistant.io/"`
|
2024-03-12 15:49:08 +01:00
|
|
|
|
|
|
|
func init() {
|
2024-06-11 11:27:17 +02:00
|
|
|
folders := []string{storageFolder, iconsFolder}
|
2024-03-12 15:49:08 +01:00
|
|
|
for _, path := range folders {
|
|
|
|
err := os.MkdirAll(path, 0755)
|
|
|
|
if err != nil {
|
|
|
|
slog.Error(err.Error())
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
slog.Debug("folders created", "folders", folders)
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewBookmarkService() *BookmarkService {
|
|
|
|
bs := BookmarkService{}
|
|
|
|
bs.parseBookmarks()
|
2024-09-30 12:05:12 +02:00
|
|
|
bs.replaceIconStrings()
|
2024-03-12 15:49:08 +01:00
|
|
|
return &bs
|
|
|
|
}
|
|
|
|
|
|
|
|
func (bs *BookmarkService) GetAllBookmarks() *Bookmarks {
|
|
|
|
return &bs.bookmarks
|
|
|
|
}
|
|
|
|
|
|
|
|
func (bs *BookmarkService) createDefaultConfigFile() {
|
|
|
|
slog.Info("Creating default config file: " + bookmarkFile)
|
|
|
|
err := os.WriteFile(bookmarkFile, []byte(defaultConfig), 0755)
|
|
|
|
if err != nil {
|
|
|
|
slog.Error(err.Error())
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (bs *BookmarkService) readBookmarksFile() []byte {
|
|
|
|
file, err := os.Open(bookmarkFile)
|
|
|
|
if err != nil {
|
|
|
|
bs.createDefaultConfigFile()
|
|
|
|
file, err = os.Open(bookmarkFile)
|
|
|
|
if err != nil {
|
|
|
|
slog.Error(err.Error())
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
defer file.Close()
|
|
|
|
byteValue, err := io.ReadAll(file)
|
|
|
|
if err != nil {
|
|
|
|
slog.Error(err.Error())
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return byteValue
|
|
|
|
}
|
|
|
|
|
2024-09-30 12:05:12 +02:00
|
|
|
func (bs *BookmarkService) replaceIconStrings() {
|
2024-06-11 18:36:49 +02:00
|
|
|
for i, v := range bs.bookmarks.Applications {
|
|
|
|
for j, bookmark := range v.Entries {
|
2024-09-30 12:05:12 +02:00
|
|
|
ext := filepath.Ext(bookmark.Icon)
|
|
|
|
if ext != ".svg" {
|
|
|
|
slog.Error("icon must be an svg file")
|
|
|
|
continue
|
|
|
|
}
|
2024-09-30 21:14:47 +02:00
|
|
|
var data, lightData []byte
|
|
|
|
var err error
|
2024-09-30 12:05:12 +02:00
|
|
|
if strings.HasPrefix(bookmark.Icon, "shi/") {
|
2024-09-30 21:14:47 +02:00
|
|
|
data, lightData, err = downloadIcons(handleSelfHostedIcons(bookmark.Icon, ext))
|
2024-09-30 20:16:29 +02:00
|
|
|
if err != nil {
|
2024-09-30 21:14:47 +02:00
|
|
|
slog.Error(err.Error())
|
|
|
|
continue
|
2024-09-30 20:16:29 +02:00
|
|
|
}
|
2024-09-30 21:14:47 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
if strings.HasPrefix(bookmark.Icon, "si/") {
|
|
|
|
data, lightData, err = downloadIcons(handleSimpleIcons(bookmark.Icon, ext))
|
2024-09-30 20:16:29 +02:00
|
|
|
if err != nil {
|
2024-09-30 21:14:47 +02:00
|
|
|
slog.Error(err.Error())
|
2024-09-30 12:05:12 +02:00
|
|
|
continue
|
|
|
|
}
|
2024-03-12 15:49:08 +01:00
|
|
|
}
|
2024-09-30 21:14:47 +02:00
|
|
|
bs.bookmarks.Applications[i].Entries[j].Icon = string(data)
|
|
|
|
bs.bookmarks.Applications[i].Entries[j].IconLight = string(lightData)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func downloadIcons(title, url, lightTitle, lightUrl string) ([]byte, []byte, error) {
|
|
|
|
data, err := downloadIcon(title, url)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
lightData, _ := downloadIcon(lightTitle, lightUrl)
|
|
|
|
return data, lightData, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func downloadIcon(title, url string) ([]byte, error) {
|
|
|
|
filePath := iconsFolder + title
|
|
|
|
data, err := os.ReadFile(filePath)
|
|
|
|
if err != nil {
|
|
|
|
data, err = media.DownloadSelfHostedIcon(url, title, filePath)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2024-03-12 15:49:08 +01:00
|
|
|
}
|
|
|
|
}
|
2024-09-30 21:14:47 +02:00
|
|
|
return data, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func handleSelfHostedIcons(icon, ext string) (string, string, string, string) {
|
|
|
|
ext = strings.TrimPrefix(ext, ".")
|
|
|
|
title := strings.Replace(icon, "shi/", "", 1)
|
|
|
|
url := "https://cdn.jsdelivr.net/gh/selfhst/icons/" + ext + "/" + title
|
|
|
|
lightTitle := strings.Replace(title, ".svg", "-light.svg", 1)
|
|
|
|
lightUrl := "https://cdn.jsdelivr.net/gh/selfhst/icons/" + ext + "/" + lightTitle
|
|
|
|
return title, url, lightTitle, lightUrl
|
|
|
|
}
|
|
|
|
|
|
|
|
func handleSimpleIcons(icon, ext string) (string, string, string, string) {
|
|
|
|
title := strings.Replace(icon, "si/", "", 1)
|
|
|
|
url := "https://cdn.simpleicons.org/" + strings.TrimSuffix(title, ext)
|
|
|
|
lightTitle := strings.Replace(title, ".svg", "-light.svg", 1)
|
|
|
|
lightUrl := "https://cdn.simpleicons.org/" + strings.TrimSuffix(title, ext) + "/white"
|
|
|
|
return title, url, lightTitle, lightUrl
|
2024-03-12 15:49:08 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (bs *BookmarkService) parseBookmarks() {
|
|
|
|
byteValue := bs.readBookmarksFile()
|
|
|
|
err := yaml.Unmarshal(byteValue, &bs.bookmarks)
|
|
|
|
if err != nil {
|
|
|
|
slog.Error(err.Error())
|
|
|
|
return
|
|
|
|
}
|
2024-06-11 18:36:49 +02:00
|
|
|
}
|