234 lines
5.7 KiB
Go
234 lines
5.7 KiB
Go
package main
|
||
|
||
import (
|
||
crand "crypto/rand"
|
||
"encoding/hex"
|
||
"fmt"
|
||
"io"
|
||
"math/rand"
|
||
"net/http"
|
||
"os"
|
||
"path/filepath"
|
||
"regexp"
|
||
"strings"
|
||
"time"
|
||
|
||
configs "goFiber/config"
|
||
database "goFiber/database/config"
|
||
"goFiber/database/models"
|
||
|
||
"gorm.io/gorm"
|
||
"gorm.io/gorm/logger"
|
||
)
|
||
|
||
var nonSlugChars = regexp.MustCompile(`[^a-z0-9\-]+`)
|
||
var multiDash = regexp.MustCompile(`-+`)
|
||
|
||
func randHex(n int) string {
|
||
b := make([]byte, n)
|
||
_, _ = crand.Read(b)
|
||
return hex.EncodeToString(b)[:n]
|
||
}
|
||
|
||
func ensureUploadsDir() error {
|
||
p := "./uploads/posts"
|
||
return os.MkdirAll(p, 0755)
|
||
}
|
||
|
||
func slugify(s string) string {
|
||
repl := strings.NewReplacer(
|
||
"ç", "c", "Ç", "c",
|
||
"ğ", "g", "Ğ", "g",
|
||
"ı", "i", "İ", "i",
|
||
"ö", "o", "Ö", "o",
|
||
"ş", "s", "Ş", "s",
|
||
"ü", "u", "Ü", "u",
|
||
)
|
||
s = repl.Replace(strings.TrimSpace(strings.ToLower(s)))
|
||
s = strings.ReplaceAll(s, " ", "-")
|
||
s = nonSlugChars.ReplaceAllString(s, "-")
|
||
s = multiDash.ReplaceAllString(s, "-")
|
||
s = strings.Trim(s, "-")
|
||
if s == "" {
|
||
return "item"
|
||
}
|
||
return s
|
||
}
|
||
|
||
func ensureUniqueCategorySlug(db *gorm.DB, base string) string {
|
||
slug := base
|
||
i := 1
|
||
for {
|
||
var count int64
|
||
_ = db.Model(&models.Category{}).Where("slug = ?", slug).Count(&count).Error
|
||
if count == 0 {
|
||
return slug
|
||
}
|
||
i++
|
||
slug = fmt.Sprintf("%s-%d", base, i)
|
||
}
|
||
}
|
||
|
||
func ensureUniquePostSlug(db *gorm.DB, base string) string {
|
||
slug := base
|
||
i := 1
|
||
for {
|
||
var count int64
|
||
_ = db.Model(&models.Post{}).Where("slug = ?", slug).Count(&count).Error
|
||
if count == 0 {
|
||
return slug
|
||
}
|
||
i++
|
||
slug = fmt.Sprintf("%s-%d", base, i)
|
||
}
|
||
}
|
||
|
||
func downloadImage(destDir string, idx int) (string, error) {
|
||
url := fmt.Sprintf("https://picsum.photos/1200/800?random=%d", idx)
|
||
resp, err := http.Get(url)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
defer resp.Body.Close()
|
||
filename := fmt.Sprintf("post_%d_%s.jpg", idx, randHex(6))
|
||
outPath := filepath.Join(destDir, filename)
|
||
out, err := os.Create(outPath)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
defer out.Close()
|
||
_, err = io.Copy(out, resp.Body)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
return "uploads/posts/" + filename, nil
|
||
}
|
||
|
||
func main() {
|
||
fmt.Println("Seeder starting...")
|
||
|
||
// load config to get DB_URL
|
||
configs.LoadConfig()
|
||
|
||
// ensure uploads dir
|
||
if err := ensureUploadsDir(); err != nil {
|
||
fmt.Println("failed to create uploads dir:", err)
|
||
os.Exit(1)
|
||
}
|
||
|
||
// Require DB_URL / configured DB. Do not fallback to sqlite.
|
||
database.ConnectDB()
|
||
if database.DB == nil {
|
||
fmt.Println("Database not configured or connection failed. Please set DB_URL in .env and ensure database is reachable.")
|
||
os.Exit(1)
|
||
}
|
||
// set GORM logger to Silent for seeding to reduce noise
|
||
var db *gorm.DB = database.DB.Session(&gorm.Session{Logger: logger.Default.LogMode(logger.Silent)})
|
||
fmt.Println("Using configured DB")
|
||
|
||
// auto-migrate minimal models used
|
||
err := db.AutoMigrate(&models.Category{}, &models.Tag{}, &models.Post{}, &models.Comment{})
|
||
if err != nil {
|
||
fmt.Println("AutoMigrate failed:", err)
|
||
os.Exit(1)
|
||
}
|
||
|
||
rand.Seed(time.Now().UnixNano())
|
||
|
||
// create categories
|
||
cats := []models.Category{}
|
||
catNames := []string{"Teknoloji", "Yazilim", "Guncel", "Yasam", "Egitim", "Spor", "Saglik", "Finans"}
|
||
for _, n := range catNames {
|
||
baseSlug := slugify(n)
|
||
var c models.Category
|
||
if err := db.Where("title = ?", n).First(&c).Error; err == nil {
|
||
// Ensure old records have a valid unique slug.
|
||
if strings.TrimSpace(c.Slug) == "" {
|
||
c.Slug = ensureUniqueCategorySlug(db, baseSlug)
|
||
_ = db.Save(&c).Error
|
||
}
|
||
cats = append(cats, c)
|
||
continue
|
||
}
|
||
|
||
c = models.Category{
|
||
Title: n,
|
||
Slug: ensureUniqueCategorySlug(db, baseSlug),
|
||
Description: fmt.Sprintf("%s kategorisi seed verisi", n),
|
||
}
|
||
res := db.Create(&c)
|
||
if res.Error != nil {
|
||
fmt.Println("Failed to create category", n, ":", res.Error)
|
||
continue
|
||
}
|
||
cats = append(cats, c)
|
||
fmt.Println("Created category:", c.Title, "slug:", c.Slug)
|
||
}
|
||
|
||
// create tags
|
||
tags := []models.Tag{}
|
||
tagNames := []string{"go", "fiber", "backend", "mysql", "redis", "jwt", "api", "docker", "cloud", "devops", "security", "testing"}
|
||
for _, n := range tagNames {
|
||
var t models.Tag
|
||
if err := db.Where("name = ?", n).First(&t).Error; err == nil {
|
||
tags = append(tags, t)
|
||
continue
|
||
}
|
||
t = models.Tag{Name: n}
|
||
res := db.Create(&t)
|
||
if res.Error != nil {
|
||
fmt.Println("Failed to create tag", n, ":", res.Error)
|
||
continue
|
||
}
|
||
tags = append(tags, t)
|
||
fmt.Println("Created tag:", t.Name)
|
||
}
|
||
|
||
// create posts
|
||
dest := "./uploads/posts"
|
||
targetPosts := 39
|
||
for i := 1; i <= targetPosts; i++ {
|
||
imgPath, err := downloadImage(dest, i)
|
||
if err != nil {
|
||
fmt.Println("image download failed for", i, "— using fallback path. err:", err)
|
||
imgPath = fmt.Sprintf("uploads/posts/fallback_%d.jpg", i)
|
||
}
|
||
|
||
title := fmt.Sprintf("Seed Post %d", i)
|
||
baseSlug := slugify(title)
|
||
uniqueSlug := ensureUniquePostSlug(db, baseSlug)
|
||
p := models.Post{
|
||
Title: title,
|
||
Slug: uniqueSlug,
|
||
Content: fmt.Sprintf("Bu bir test icerigidir. Gonderi numarasi %d.", i),
|
||
}
|
||
|
||
// randomly attach 1-2 categories
|
||
nc := rand.Intn(2) + 1
|
||
permCats := rand.Perm(len(cats))[:nc]
|
||
for _, idx := range permCats {
|
||
p.Categories = append(p.Categories, cats[idx])
|
||
}
|
||
// attach 1-3 tags
|
||
nx := rand.Intn(3) + 1
|
||
permTags := rand.Perm(len(tags))[:nx]
|
||
for _, idx := range permTags {
|
||
p.Tags = append(p.Tags, tags[idx])
|
||
}
|
||
|
||
// assign a single relative image path (NOT JSON array)
|
||
p.Images = imgPath
|
||
|
||
res := db.Create(&p)
|
||
if res.Error != nil {
|
||
fmt.Println("Failed to create post", title, ":", res.Error)
|
||
} else {
|
||
fmt.Println("Created post", p.Title, "slug:", p.Slug)
|
||
}
|
||
}
|
||
|
||
fmt.Printf("Seeding done — %d posts targeted.\n", targetPosts)
|
||
// print reminder where images are
|
||
fmt.Println("Images saved to ./uploads/posts — check files.")
|
||
}
|