package main import ( crand "crypto/rand" "encoding/hex" "fmt" "io" "math/rand" "net/http" "os" "path/filepath" "regexp" "strings" "time" configs "ares/config" database "ares/database/config" "ares/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 image paths (seed: same path for all sizes) p.Images = imgPath p.ImagesMid = imgPath p.ImagesMin = 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.") }