package handlers import ( "database/sql" "encoding/json" "fmt" "net/http" "time" ) // SocialMediaAccount representerar ett kopplat socialt media-konto type SocialMediaAccount struct { ID string `json:"id"` Platform string `json:"platform"` AccountName string `json:"account_name"` DisplayName string `json:"display_name"` Followers int `json:"followers"` Following int `json:"following"` Posts int `json:"posts"` ProfileURL string `json:"profile_url"` AvatarURL string `json:"avatar_url"` IsConnected bool `json:"is_connected"` LastSynced time.Time `json:"last_synced"` CreatedAt time.Time `json:"created_at"` } // SocialMediaPost representerar ett inlägg type SocialMediaPost struct { ID string `json:"id"` AccountID string `json:"account_id"` Platform string `json:"platform"` Content string `json:"content"` MediaURL string `json:"media_url,omitempty"` Likes int `json:"likes"` Comments int `json:"comments"` Shares int `json:"shares"` Reach int `json:"reach"` PostedAt time.Time `json:"posted_at"` Status string `json:"status"` } // SocialMediaStats representerar aggregerad statistik type SocialMediaStats struct { TotalFollowers int `json:"total_followers"` TotalPosts int `json:"total_posts"` TotalEngagement int `json:"total_engagement"` Accounts int `json:"accounts"` } // SocialMediaHandler hanterar sociala media-konton type SocialMediaHandler struct { db *sql.DB } // NewSocialMediaHandler skapar en ny handler func NewSocialMediaHandler(db *sql.DB) *SocialMediaHandler { return &SocialMediaHandler{db: db} } // InitDB skapar tabeller för sociala media func (h *SocialMediaHandler) InitDB() error { _, err := h.db.Exec(` CREATE TABLE IF NOT EXISTS social_media_accounts ( id TEXT PRIMARY KEY, platform TEXT NOT NULL, account_name TEXT NOT NULL, display_name TEXT, followers INTEGER DEFAULT 0, following INTEGER DEFAULT 0, posts INTEGER DEFAULT 0, profile_url TEXT, avatar_url TEXT, is_connected BOOLEAN DEFAULT false, last_synced TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) `) if err != nil { return err } _, err = h.db.Exec(` CREATE TABLE IF NOT EXISTS social_media_posts ( id TEXT PRIMARY KEY, account_id TEXT NOT NULL, platform TEXT NOT NULL, content TEXT, media_url TEXT, likes INTEGER DEFAULT 0, comments INTEGER DEFAULT 0, shares INTEGER DEFAULT 0, reach INTEGER DEFAULT 0, posted_at TIMESTAMP, status TEXT DEFAULT 'published', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (account_id) REFERENCES social_media_accounts(id) ) `) return err } // ListAccounts listar alla kopplade konton func (h *SocialMediaHandler) ListAccounts(w http.ResponseWriter, r *http.Request) { rows, err := h.db.Query(` SELECT id, platform, account_name, display_name, followers, following, posts, profile_url, avatar_url, is_connected, last_synced, created_at FROM social_media_accounts ORDER BY platform, account_name `) if err != nil { writeJSON(w, http.StatusInternalServerError, map[string]interface{}{ "ok": false, "error": err.Error(), }) return } defer rows.Close() var accounts []SocialMediaAccount for rows.Next() { var a SocialMediaAccount var lastSynced sql.NullTime err := rows.Scan( &a.ID, &a.Platform, &a.AccountName, &a.DisplayName, &a.Followers, &a.Following, &a.Posts, &a.ProfileURL, &a.AvatarURL, &a.IsConnected, &lastSynced, &a.CreatedAt, ) if err != nil { continue } if lastSynced.Valid { a.LastSynced = lastSynced.Time } accounts = append(accounts, a) } if accounts == nil { accounts = []SocialMediaAccount{} } writeJSON(w, http.StatusOK, map[string]interface{}{ "ok": true, "accounts": accounts, }) } // GetStats returnerar aggregerad statistik func (h *SocialMediaHandler) GetStats(w http.ResponseWriter, r *http.Request) { var stats SocialMediaStats err := h.db.QueryRow(` SELECT COALESCE(SUM(followers), 0), COALESCE(SUM(posts), 0), COUNT(*) FROM social_media_accounts WHERE is_connected = true `).Scan(&stats.TotalFollowers, &stats.TotalPosts, &stats.Accounts) if err != nil { writeJSON(w, http.StatusInternalServerError, map[string]interface{}{ "ok": false, "error": err.Error(), }) return } writeJSON(w, http.StatusOK, map[string]interface{}{ "ok": true, "stats": stats, }) } // AddAccount lägger till ett nytt konto func (h *SocialMediaHandler) AddAccount(w http.ResponseWriter, r *http.Request) { var req struct { Platform string `json:"platform"` AccountName string `json:"account_name"` DisplayName string `json:"display_name"` ProfileURL string `json:"profile_url"` } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeJSON(w, http.StatusBadRequest, map[string]interface{}{ "ok": false, "error": "invalid request", }) return } id := fmt.Sprintf("%s_%d", req.Platform, time.Now().Unix()) _, err := h.db.Exec(` INSERT INTO social_media_accounts (id, platform, account_name, display_name, profile_url, is_connected) VALUES (?, ?, ?, ?, ?, true) `, id, req.Platform, req.AccountName, req.DisplayName, req.ProfileURL) if err != nil { writeJSON(w, http.StatusInternalServerError, map[string]interface{}{ "ok": false, "error": err.Error(), }) return } writeJSON(w, http.StatusOK, map[string]interface{}{ "ok": true, "account": map[string]interface{}{ "id": id, "platform": req.Platform, "name": req.AccountName, }, }) } // ListPosts listar inlägg func (h *SocialMediaHandler) ListPosts(w http.ResponseWriter, r *http.Request) { accountID := r.URL.Query().Get("account_id") platform := r.URL.Query().Get("platform") query := ` SELECT id, account_id, platform, content, media_url, likes, comments, shares, reach, posted_at, status FROM social_media_posts WHERE 1=1 ` var args []interface{} if accountID != "" { query += " AND account_id = ?" args = append(args, accountID) } if platform != "" { query += " AND platform = ?" args = append(args, platform) } query += " ORDER BY posted_at DESC LIMIT 50" rows, err := h.db.Query(query, args...) if err != nil { writeJSON(w, http.StatusInternalServerError, map[string]interface{}{ "ok": false, "error": err.Error(), }) return } defer rows.Close() var posts []SocialMediaPost for rows.Next() { var p SocialMediaPost var postedAt sql.NullTime err := rows.Scan( &p.ID, &p.AccountID, &p.Platform, &p.Content, &p.MediaURL, &p.Likes, &p.Comments, &p.Shares, &p.Reach, &postedAt, &p.Status, ) if err != nil { continue } if postedAt.Valid { p.PostedAt = postedAt.Time } posts = append(posts, p) } if posts == nil { posts = []SocialMediaPost{} } writeJSON(w, http.StatusOK, map[string]interface{}{ "ok": true, "posts": posts, }) }