package services import ( "CatsOfMastodonBotGo/internal/models" "context" "encoding/json" "fmt" "net/http" "strings" "gorm.io/gorm" "gorm.io/gorm/clause" ) type PostService struct { db *gorm.DB } // Constructor func NewPostService(db *gorm.DB) *PostService { return &PostService{db: db} } func (*PostService) GetPostsFromApi(ctx context.Context, tag string, instance string) (error, []models.Post) { var requestUrl = instance + "/api/v1/timelines/tag/" + tag + "?limit=40" req, err := http.NewRequestWithContext(ctx, "GET", requestUrl, nil) if err != nil { return err, nil } resp, err := http.DefaultClient.Do(req) if err != nil { return err, nil } if resp.StatusCode != 200 || strings.Split(strings.ToLower(resp.Header.Get("Content-Type")), ";")[0] != "application/json" { return fmt.Errorf("Status code:", resp.StatusCode, " Content-Type:", resp.Header.Get("Content-Type")), nil } var posts []models.Post = nil err = json.NewDecoder(resp.Body).Decode(&posts) if err != nil { return err, nil } // defer: it basically means "do this later when the function returns" defer resp.Body.Close() if posts == nil { return fmt.Errorf("no posts found for tag %s on instance %s", tag, instance), nil } return nil, posts } func (ps *PostService) GetExistingPostIds() []string { var existingPostIds []string ps.db.Model(&models.Post{}).Pluck("id", &existingPostIds) return existingPostIds } func (ps *PostService) GetExistingAccountIds() []string { var existingAccountIds []string ps.db.Model(&models.Account{}).Pluck("acc_id", &existingAccountIds) return existingAccountIds } func (*PostService) GetNewPosts(existingPostIds []string, posts []models.Post) []models.Post { var newPosts []models.Post = nil for _, post := range posts { if !arrayContains(existingPostIds, post.ID) && len(post.Attachments) > 0 && !post.Account.IsBot { newPosts = append(newPosts, post) } } return newPosts } func (*PostService) GetNewAccounts(existingAccountIds []string, posts []models.Post) []models.Account { var newAccounts []models.Account = nil for _, post := range posts { if !arrayContains(existingAccountIds, post.Account.AccId) { newAccounts = append(newAccounts, post.Account) } } return newAccounts } func (ps *PostService) InsertNewPosts(newPosts []models.Post) int { return int(ps.db.Create(&newPosts).RowsAffected) } func (ps *PostService) InsertNewAccounts(newAccounts []models.Account) int { return int(ps.db.Clauses(clause.OnConflict{UpdateAll: true}).Create(&newAccounts).RowsAffected) } // From this point on, its for the api endpoints func (ps *PostService) GetRandomPost() models.Post { var post models.Post ps.db. Preload("Account"). Preload("Attachments"). Order("RANDOM()"). First(&post) return post } func (ps *PostService) ApproveMedia(mediaId string) bool { return ps.db.Model(&models.MediaAttachment{}). Where("id = ?", mediaId). Update("approved", true).RowsAffected > 0 } func (ps *PostService) RejectMedia(mediaId string) bool { return ps.db.Model(&models.MediaAttachment{}). Where("id = ?", mediaId). Update("rejected", true).RowsAffected > 0 } func arrayContains(arr []string, str string) bool { for _, a := range arr { if a == str { return true } } return false }