first commit

This commit is contained in:
Beyhan Oğur
2026-04-26 21:46:42 +03:00
commit 2a5b661443
202 changed files with 49770 additions and 0 deletions

250
cmd/seeder/main.go Normal file
View File

@@ -0,0 +1,250 @@
package main
import (
"fmt"
"io"
"log"
"math/rand"
"net/http"
"os"
"path/filepath"
"strings"
"time"
database "goGin/app/database/config"
"goGin/app/database/models"
configs "goGin/config"
"gorm.io/gorm"
)
func main() {
// Config ve DB yükle
configs.LoadConfig()
database.ConnectDB()
db := database.DB
if db == nil {
log.Fatal("Veritabanı bağlantısı kurulamadı!")
}
log.Println("Seeder başladı...")
// create a local random generator to avoid deprecated rand.Seed usage
r := rand.New(rand.NewSource(time.Now().UnixNano()))
// 1. Kullanıcıyı Kontrol Et / Oluştur (ID: 2)
var user models.User
result := db.First(&user, 2)
if result.Error != nil {
if result.Error == gorm.ErrRecordNotFound {
log.Println("Kullanıcı (ID: 2) bulunamadı, oluşturuluyor...")
user = models.User{
ID: 2,
UserName: "fakeuser",
Email: "fakeuser@example.com",
Password: "password123", // Hashlenmemiş, sadece test için
}
isAdmin := false
emailVerified := true
user.IsAdmin = &isAdmin
user.EmailVerified = &emailVerified
if err := db.Create(&user).Error; err != nil {
log.Printf("Kullanıcı oluşturulurken hata: %v", err)
user.ID = 0
if err2 := db.Create(&user).Error; err2 != nil {
log.Fatal("Kullanıcı oluşturulamadı:", err2)
}
}
} else {
log.Fatal("Veritabanı hatası:", result.Error)
}
} else {
log.Println("Kullanıcı (ID: 2) mevcut.")
}
// 2. Kategorileri Oluştur
categories := []struct {
Title string
Subs []string
}{
{"Teknoloji", []string{"Yazılım", "Donanım", "Yapay Zeka", "Mobil"}},
{"Yaşam", []string{"Sağlık", "Spor", "Gezi", "Dekorasyon"}},
{"Yemek", []string{"Tatlılar", "Ana Yemekler", "İçecekler"}},
{"Sanat", []string{"Sinema", "Müzik", "Edebiyat"}},
}
var createdCategories []models.Category
for _, catData := range categories {
parent := models.Category{
Title: catData.Title,
Slug: slugify(catData.Title),
}
if err := db.Where("slug = ?", parent.Slug).FirstOrCreate(&parent).Error; err != nil {
log.Printf("Kategori hatası (%s): %v", parent.Title, err)
continue
}
createdCategories = append(createdCategories, parent)
for _, subTitle := range catData.Subs {
sub := models.Category{
Title: subTitle,
Slug: slugify(subTitle),
ParentID: &parent.ID,
}
if err := db.Where("slug = ?", sub.Slug).FirstOrCreate(&sub).Error; err != nil {
log.Printf("Alt kategori hatası (%s): %v", subTitle, err)
continue
}
createdCategories = append(createdCategories, sub)
}
}
// 3. Etiketleri Oluştur
tagNames := []string{"Go", "Gin", "Web", "Api", "Tutorial", "Coding", "Life", "Nature", "Food", "Travel"}
var createdTags []models.Tag
for _, name := range tagNames {
tag := models.Tag{Name: name}
if err := db.Where("name = ?", name).FirstOrCreate(&tag).Error; err != nil {
log.Printf("Etiket hatası (%s): %v", name, err)
continue
}
createdTags = append(createdTags, tag)
}
// 4. Postları Oluştur (40 adet)
postCount := 40
titles := []string{
"Go ile Web Geliştirme", "Gin Framework İpuçları", "Veritabanı Optimizasyonu",
"Modern Web Tasarımı", "Yapay Zeka Geleceği", "sağlıklı Yaşam Sırları",
"Dünya Turu Rehberi", "Lezzetli Pizza Tarifi", "Film İncelemesi: Joker",
"Müzik ve Ruh Hali", "Kodlama Pratikleri", "Cloud Computing Temelleri",
}
images := []string{
"https://images.unsplash.com/photo-1518770660439-4636190af475?auto=format&fit=crop&w=1000&q=80",
"https://images.unsplash.com/photo-1498050108023-c5249f4df085?auto=format&fit=crop&w=1000&q=80",
"https://images.unsplash.com/photo-1461749280684-dccba630e2f6?auto=format&fit=crop&w=1000&q=80",
"https://images.unsplash.com/photo-1504674900247-0877df9cc836?auto=format&fit=crop&w=1000&q=80",
"https://images.unsplash.com/photo-1472214103451-9374bd1c798e?auto=format&fit=crop&w=1000&q=80",
"https://images.unsplash.com/photo-1493770348161-369560ae357d?auto=format&fit=crop&w=1000&q=80",
"https://images.unsplash.com/photo-1470225620780-dba8ba36b745?auto=format&fit=crop&w=1000&q=80",
"https://images.unsplash.com/photo-1454165804606-c3d57bc86b40?auto=format&fit=crop&w=1000&q=80",
"https://images.unsplash.com/photo-1542291026-7eec264c27ff?auto=format&fit=crop&w=1000&q=80",
"https://images.unsplash.com/photo-1515378791036-0648a3ef77b2?auto=format&fit=crop&w=1000&q=80",
}
// Resimlerin indirileceği hedef klasör
uploadDir := "uploads/posts"
if err := os.MkdirAll(uploadDir, os.ModePerm); err != nil {
log.Fatalf("Klasör oluşturulamadı: %v", err)
}
log.Println("Postlar oluşturuluyor ve resimler indiriliyor...")
for i := 0; i < postCount; i++ {
// use local rand generator
title := fmt.Sprintf("%s %d", titles[r.Intn(len(titles))], i+1)
// Resim İndirme İşlemi
remoteURL := images[r.Intn(len(images))]
fileName := fmt.Sprintf("seed-post-%d-%d.jpg", i+1, time.Now().Unix())
filePath := filepath.Join(uploadDir, fileName)
if _, err := os.Stat(filePath); os.IsNotExist(err) {
if err := downloadFile(filePath, remoteURL); err != nil {
log.Printf("Resim indirilemedi (%s): %v", remoteURL, err)
}
}
dbImagePath := fmt.Sprintf("/uploads/posts/%s", fileName)
post := models.Post{
Title: title,
Slug: slugify(title),
Content: fmt.Sprintf("<p>Bu otomatik oluşturulmuş bir içeriktir: %s. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>", title),
Images: dbImagePath,
}
if err := db.Create(&post).Error; err != nil {
log.Printf("Post oluşturma hatası: %v", err)
continue
}
// İlişkiler
numCats := r.Intn(3) + 1
for j := 0; j < numCats; j++ {
cat := createdCategories[r.Intn(len(createdCategories))]
if err := db.Model(&post).Association("Categories").Append(&cat); err != nil {
log.Printf("Kategori ilişkilendirme hatası (post %d, cat %d): %v", post.ID, cat.ID, err)
}
}
numTags := r.Intn(4) + 1
for j := 0; j < numTags; j++ {
tag := createdTags[r.Intn(len(createdTags))]
if err := db.Model(&post).Association("Tags").Append(&tag); err != nil {
log.Printf("Tag ilişkilendirme hatası (post %d, tag %d): %v", post.ID, tag.ID, err)
}
}
numComments := r.Intn(6)
for c := 0; c < numComments; c++ {
comment := models.Comment{
PostID: post.ID,
UserID: user.ID,
Body: fmt.Sprintf("Bu harika bir yazı! Yorum #%d", c+1),
}
if err := db.Create(&comment).Error; err != nil {
log.Printf("Yorum oluşturma hatası: %v", err)
}
}
time.Sleep(50 * time.Millisecond)
}
log.Println("Tüm işlemler başarıyla tamamlandı!")
}
func downloadFile(filepath string, url string) error {
resp, err := http.Get(url)
if err != nil {
return err
}
defer func() {
if cerr := resp.Body.Close(); cerr != nil {
log.Printf("error closing response body: %v", cerr)
}
}()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("bad status: %s", resp.Status)
}
out, err := os.Create(filepath)
if err != nil {
return err
}
defer func() {
if cerr := out.Close(); cerr != nil {
log.Printf("error closing file: %v", cerr)
}
}()
_, err = io.Copy(out, resp.Body)
return err
}
func slugify(s string) string {
s = strings.ToLower(s)
s = strings.ReplaceAll(s, " ", "-")
s = strings.ReplaceAll(s, "ı", "i")
s = strings.ReplaceAll(s, "ğ", "g")
s = strings.ReplaceAll(s, "ü", "u")
s = strings.ReplaceAll(s, "ş", "s")
s = strings.ReplaceAll(s, "ö", "o")
s = strings.ReplaceAll(s, "ç", "c")
timestamp := time.Now().UnixNano()
return fmt.Sprintf("%s-%d", s, timestamp)
}