2024-04-09 20:06:34 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2024-04-09 21:00:34 +02:00
|
|
|
"bufio"
|
2024-04-09 20:06:34 +02:00
|
|
|
"bytes"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
2024-04-09 21:00:34 +02:00
|
|
|
"io/ioutil"
|
2024-04-09 20:06:34 +02:00
|
|
|
"log"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"regexp"
|
|
|
|
"strings"
|
2024-04-09 21:00:34 +02:00
|
|
|
"time"
|
2024-04-09 20:06:34 +02:00
|
|
|
|
|
|
|
"github.com/fsnotify/fsnotify"
|
|
|
|
"github.com/gosimple/slug"
|
|
|
|
"gopkg.in/ini.v1"
|
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
|
|
|
|
// Read the config file
|
|
|
|
home, err := os.UserHomeDir()
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalln(err)
|
|
|
|
}
|
|
|
|
config, err := ini.Load(home + "/.config/obs2hugo/obs2hugo.ini")
|
|
|
|
if err != nil {
|
|
|
|
config, err = ini.Load(home + "/.config/obs2hugo.ini")
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalln(err)
|
|
|
|
}
|
|
|
|
}
|
2024-04-10 10:59:53 +02:00
|
|
|
// Watcher directories
|
|
|
|
watcherDirs := config.Section("").Key("watcher_dirs").String()
|
2024-04-09 20:06:34 +02:00
|
|
|
|
|
|
|
// Hugo content directory
|
2024-04-10 10:59:53 +02:00
|
|
|
destDirs := config.Section("").Key("hugo_dirs").String()
|
|
|
|
|
|
|
|
watcherDirsList := strings.Split(watcherDirs, ":")
|
|
|
|
destDirsList := strings.Split(destDirs, ":")
|
|
|
|
|
|
|
|
if len(watcherDirsList) != len(destDirsList) {
|
|
|
|
fmt.Println("Error: watcher_dirs and hugo_dirs must have the same number of elements")
|
|
|
|
return
|
|
|
|
}
|
2024-04-09 20:06:34 +02:00
|
|
|
|
2024-04-09 20:21:52 +02:00
|
|
|
// Creating watcher
|
2024-04-09 20:06:34 +02:00
|
|
|
watcher, err := fsnotify.NewWatcher()
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println("Error creating the watcher:", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
defer watcher.Close()
|
|
|
|
|
2024-04-10 10:59:53 +02:00
|
|
|
// Add directories to the watcher
|
|
|
|
for _, dir := range watcherDirsList {
|
|
|
|
err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println("Error accessing to the directory:", err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if info.IsDir() {
|
|
|
|
return watcher.Add(path)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
})
|
2024-04-09 20:06:34 +02:00
|
|
|
if err != nil {
|
2024-04-10 10:59:53 +02:00
|
|
|
fmt.Println("Error adding directory to the watcher:", err)
|
|
|
|
return
|
2024-04-09 20:06:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Watcher event loop
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case event := <-watcher.Events:
|
|
|
|
switch {
|
|
|
|
case event.Op&fsnotify.Create == fsnotify.Create:
|
|
|
|
fmt.Println("New file:", event.Name)
|
|
|
|
// TBD
|
|
|
|
case event.Op&fsnotify.Write == fsnotify.Write:
|
|
|
|
fmt.Println("File modified:", event.Name)
|
2024-04-10 10:59:53 +02:00
|
|
|
triggerDir := getTriggerDirectory(event.Name, watcherDirsList)
|
|
|
|
if triggerDir == "" {
|
|
|
|
fmt.Println("Error: Unable to determine trigger directory for event:", event.Name)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
newDestDir := getDestinationDirectory(triggerDir, watcherDirsList, destDirsList)
|
|
|
|
if newDestDir == "" {
|
|
|
|
fmt.Println("Error: Unable to determine destination directory for trigger directory:", triggerDir)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
processModifiedFile(event.Name, triggerDir, newDestDir)
|
2024-04-09 20:06:34 +02:00
|
|
|
case event.Op&fsnotify.Remove == fsnotify.Remove:
|
|
|
|
fmt.Println("File deleted:", event.Name)
|
|
|
|
// TBD
|
|
|
|
case event.Op&fsnotify.Rename == fsnotify.Rename:
|
|
|
|
fmt.Println("File renamed:", event.Name)
|
|
|
|
// TBD
|
|
|
|
}
|
|
|
|
case err := <-watcher.Errors:
|
|
|
|
fmt.Println("Watcher error:", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-10 10:59:53 +02:00
|
|
|
// Function to determine which watcher directory triggered the event
|
|
|
|
func getTriggerDirectory(eventPath string, dirs []string) string {
|
|
|
|
for _, dir := range dirs {
|
|
|
|
if strings.HasPrefix(eventPath, dir) {
|
|
|
|
return dir
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function to determine the destination directory for the trigger directory
|
|
|
|
func getDestinationDirectory(triggerDir string, watcherDirsList, destDirsList []string) string {
|
|
|
|
for i, dir := range watcherDirsList {
|
|
|
|
if dir == triggerDir {
|
|
|
|
return destDirsList[i]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
2024-04-09 20:06:34 +02:00
|
|
|
func processModifiedFile(filePath, directory, destDir string) {
|
|
|
|
// Slugified file name without extension
|
|
|
|
fileName := strings.TrimSuffix(filepath.Base(filePath), filepath.Ext(filePath))
|
|
|
|
slug := slug.Make(fileName)
|
|
|
|
|
2024-04-09 20:59:11 +02:00
|
|
|
// Creating destination directory
|
2024-04-09 20:06:34 +02:00
|
|
|
newDir := filepath.Join(destDir, slug)
|
|
|
|
err := os.MkdirAll(newDir, os.ModePerm)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println("Error creating directory:", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-04-09 20:59:11 +02:00
|
|
|
// Copy modified file to the new destination
|
2024-04-09 20:06:34 +02:00
|
|
|
newFilePath := filepath.Join(newDir, "index.md")
|
2024-04-09 21:00:34 +02:00
|
|
|
|
|
|
|
// Check if the file already has frontmatter
|
|
|
|
hasFrontmatter, err := checkFrontmatter(filePath)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println("Error checking frontmatter:", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the file doesn't have frontmatter, add it
|
|
|
|
if !hasFrontmatter {
|
|
|
|
err = addFrontmatter(filePath, fileName)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println("Error adding frontmatter:", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-09 20:06:34 +02:00
|
|
|
err = copyFile(filePath, newFilePath)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println("Error copying file:", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Move images to the gallery directory
|
|
|
|
err = moveImagesToGallery(filePath, newDir, directory)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println("Error moving images to the gallery:", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-09 21:00:34 +02:00
|
|
|
// Function to check if the file already has frontmatter
|
|
|
|
func checkFrontmatter(filePath string) (bool, error) {
|
|
|
|
file, err := os.Open(filePath)
|
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
defer file.Close()
|
|
|
|
|
|
|
|
scanner := bufio.NewScanner(file)
|
|
|
|
for scanner.Scan() {
|
|
|
|
line := scanner.Text()
|
|
|
|
if line == "---" {
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function to add frontmatter to the file
|
|
|
|
func addFrontmatter(filePath, title string) error {
|
|
|
|
// Read the content of the original file
|
|
|
|
content, err := ioutil.ReadFile(filePath)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a new temporary file with the frontmatter added
|
|
|
|
tempFilePath := filePath + ".tmp"
|
|
|
|
frontmatter := fmt.Sprintf("---\ntitle: %s\ndate: %s\ndraft: false\ntags: micropost\n---\n\n", title, time.Now().Format("2006-01-02 15:04:05 -0700"))
|
|
|
|
err = ioutil.WriteFile(tempFilePath, []byte(frontmatter+string(content)), os.ModePerm)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Replace the original file with the temporary file
|
|
|
|
fmt.Println("Rename:", tempFilePath, filePath)
|
|
|
|
err = os.Rename(tempFilePath, filePath)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-04-09 20:06:34 +02:00
|
|
|
func copyFile(src, dst string) error {
|
|
|
|
sourceFile, err := os.Open(src)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer sourceFile.Close()
|
|
|
|
|
|
|
|
newFile, err := os.Create(dst)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer newFile.Close()
|
|
|
|
|
|
|
|
_, err = io.Copy(newFile, sourceFile)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func moveImagesToGallery(filePath, destDir, directory string) error {
|
|
|
|
// Routes
|
|
|
|
destFilePath := filepath.Join(destDir, "index.md")
|
|
|
|
slugDir := slug.Make(strings.TrimSuffix(filepath.Base(filePath), filepath.Ext(filePath)))
|
|
|
|
galleryDir := filepath.Join(destDir, "gallery")
|
|
|
|
|
|
|
|
// Read file content
|
|
|
|
content, err := os.ReadFile(filePath)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Regexp to find the markdown images
|
|
|
|
re := regexp.MustCompile(`!\[\[([^]]+)\]\]`)
|
|
|
|
matches := re.FindAllStringSubmatch(string(content), -1)
|
|
|
|
|
|
|
|
// Create gallery dir if it doesn't exist
|
|
|
|
if _, err := os.Stat(galleryDir); os.IsNotExist(err) {
|
|
|
|
err := os.Mkdir(galleryDir, os.ModePerm)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Move every image found
|
|
|
|
for _, match := range matches {
|
|
|
|
imagePath := match[1]
|
|
|
|
imageName := filepath.Base(imagePath)
|
|
|
|
ext := filepath.Ext(imageName)
|
|
|
|
slugName := slug.Make(strings.TrimSuffix(imageName, ext))
|
|
|
|
imageSrc := filepath.Join(directory, imagePath)
|
|
|
|
imageDest := filepath.Join(galleryDir, slugName+ext)
|
|
|
|
// Open source file
|
|
|
|
srcFile, err := os.Open(imageSrc)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Error opening source file %s: %s\n", imageSrc, err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
defer srcFile.Close()
|
|
|
|
|
|
|
|
// Create destination file
|
|
|
|
destFile, err := os.Create(imageDest)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Error creating destination file %s: %s\n", imageDest, err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
defer destFile.Close()
|
|
|
|
|
|
|
|
// Copy source to destination
|
|
|
|
_, err = io.Copy(destFile, srcFile)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Error copying file %s to %s: %s\n", imageSrc, imageDest, err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// Modify link text
|
|
|
|
newImageMarkdown := fmt.Sprintf("![%s](%s/gallery/%s)", strings.TrimSuffix(slugName, ext), slugDir, slugName+ext)
|
|
|
|
content = bytes.Replace(content, []byte(match[0]), []byte(newImageMarkdown), -1)
|
|
|
|
|
|
|
|
fmt.Printf("Image %s was copied to %s\n", imageSrc, imageDest)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Replace [gallery] pattern
|
|
|
|
content = bytes.Replace(content, []byte("[gallery]"), []byte("{{< gallery match=\"gallery/*\" sortOrder=\"asc\" rowHeight=\"150\" margins=\"5\" thumbnailResizeOptions=\"600x600 q90 Lanczos\" previewType=\"blur\" embedPreview=\"true\" >}}"), -1)
|
|
|
|
|
|
|
|
// Write markdown file new content
|
|
|
|
err = os.WriteFile(destFilePath, content, os.ModePerm)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Error writing file content to the file: %s: %s\n", filePath, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|