123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- package tiktok
- import (
- "encoding/json"
- "fmt"
- "net/http"
- "time"
- "git.linuxforward.com/byom/byom-trends/config"
- "git.linuxforward.com/byom/byom-trends/logger"
- "github.com/sirupsen/logrus"
- )
- type Client struct {
- httpClient *http.Client
- apiKey string
- baseURL string
- logger *logrus.Entry
- }
- type ProfileStats struct {
- Username string `json:"username"`
- FollowerCount int64 `json:"follower_count"`
- FollowingCount int64 `json:"following_count"`
- VideoCount int64 `json:"video_count"`
- LikeCount int64 `json:"like_count"`
- Engagement float64 `json:"engagement"`
- VerifiedStatus bool `json:"verified_status"`
- }
- type Video struct {
- ID string `json:"id"`
- Description string `json:"description"`
- CreateTime time.Time `json:"create_time"`
- Duration int `json:"duration"`
- LikeCount int64 `json:"like_count"`
- CommentCount int64 `json:"comment_count"`
- ShareCount int64 `json:"share_count"`
- ViewCount int64 `json:"view_count"`
- ThumbnailURL string `json:"thumbnail_url"`
- VideoURL string `json:"video_url"`
- MusicInfo string `json:"music_info"`
- HashTags []string `json:"hashtags"`
- }
- func NewClient(cfg *config.TikTokConfig) *Client {
- return &Client{
- httpClient: &http.Client{
- Timeout: time.Second * 10,
- },
- apiKey: cfg.APIKey,
- baseURL: cfg.BaseURL,
- logger: logger.NewLogger("tiktok-client"),
- }
- }
- func (c *Client) GetProfileStats(username string) (*ProfileStats, error) {
- url := fmt.Sprintf("%s/users/%s", c.baseURL, username)
- req, err := http.NewRequest("GET", url, nil)
- if err != nil {
- return nil, fmt.Errorf("create request: %w", err)
- }
- req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.apiKey))
- resp, err := c.httpClient.Do(req)
- if err != nil {
- return nil, fmt.Errorf("do request: %w", err)
- }
- defer resp.Body.Close()
- if resp.StatusCode != http.StatusOK {
- return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
- }
- var stats ProfileStats
- if err := json.NewDecoder(resp.Body).Decode(&stats); err != nil {
- return nil, fmt.Errorf("decode response: %w", err)
- }
- return &stats, nil
- }
- func (c *Client) GetRecentVideos(username string, limit int) ([]Video, error) {
- url := fmt.Sprintf("%s/users/%s/videos?limit=%d", c.baseURL, username, limit)
- req, err := http.NewRequest("GET", url, nil)
- if err != nil {
- return nil, fmt.Errorf("create request: %w", err)
- }
- req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.apiKey))
- resp, err := c.httpClient.Do(req)
- if err != nil {
- return nil, fmt.Errorf("do request: %w", err)
- }
- defer resp.Body.Close()
- if resp.StatusCode != http.StatusOK {
- return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
- }
- var videos []Video
- if err := json.NewDecoder(resp.Body).Decode(&videos); err != nil {
- return nil, fmt.Errorf("decode response: %w", err)
- }
- return videos, nil
- }
- func (c *Client) CalculateEngagement(videos []Video) float64 {
- if len(videos) == 0 {
- return 0
- }
- var totalEngagement int64
- for _, video := range videos {
- // TikTok engagement includes likes, comments, shares, and views
- totalEngagement += video.LikeCount + video.CommentCount + video.ShareCount + video.ViewCount
- }
- return float64(totalEngagement) / float64(len(videos))
- }
- func (c *Client) GetTrendingHashtags(videos []Video) map[string]int {
- hashtags := make(map[string]int)
- for _, video := range videos {
- for _, tag := range video.HashTags {
- hashtags[tag]++
- }
- }
- return hashtags
- }
|