package main import ( "bytes" "fmt" "io" "log" "os" "path/filepath" "regexp" "strings" "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) } } // Watcher directory directory := config.Section("").Key("watcher_dir").String() // Hugo content directory destDir := config.Section("").Key("hugo_dir").String() // Creating watcher watcher, err := fsnotify.NewWatcher() if err != nil { fmt.Println("Error creating the watcher:", err) return } defer watcher.Close() // Add directory to the watcher err = filepath.Walk(directory, 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 }) if err != nil { fmt.Println("Error adding directory to the watcher:", err) return } // 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) processModifiedFile(event.Name, directory, destDir) 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) } } } func processModifiedFile(filePath, directory, destDir string) { // Slugified file name without extension fileName := strings.TrimSuffix(filepath.Base(filePath), filepath.Ext(filePath)) slug := slug.Make(fileName) // Creating destination directory newDir := filepath.Join(destDir, slug) err := os.MkdirAll(newDir, os.ModePerm) if err != nil { fmt.Println("Error creating directory:", err) return } // Copy modified file to the new destination newFilePath := filepath.Join(newDir, "index.md") 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 } } 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 }