thread-master/backend/internal/model/threads_account/usecase/api_smoke.go

169 lines
5.6 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package usecase
import (
"context"
"fmt"
"strings"
app "haixun-backend/internal/library/errors"
"haixun-backend/internal/library/errors/code"
libthreads "haixun-backend/internal/library/threadsapi"
domusecase "haixun-backend/internal/model/threads_account/domain/usecase"
)
func (u *threadsAccountUseCase) RunAPISmokeTest(
ctx context.Context,
tenantID, ownerUID, accountID string,
) ([]domusecase.APISmokeTestItem, error) {
account, err := u.assertOwned(ctx, tenantID, ownerUID, accountID)
if err != nil {
return nil, err
}
token, err := u.ResolveAccountAPIAccessToken(ctx, tenantID, ownerUID, accountID)
if err != nil {
return nil, err
}
client := libthreads.NewClient(token)
if !client.Enabled() {
return nil, app.For(code.ThreadsAccount).InputMissingRequired("Threads API token 無效")
}
var out []domusecase.APISmokeTestItem
add := func(scope, name, status, message string, count int) {
out = append(out, domusecase.APISmokeTestItem{
Scope: scope, Name: name, Status: status, Message: message, Count: count,
})
}
run := func(scope, name string, fn func() (int, string, error)) {
count, detail, err := fn()
if err != nil {
msg := err.Error()
if libthreads.IsPermissionError(err) {
msg += "(請確認 Meta App 已授權此 scope且帳號在測試人員名單"
}
add(scope, name, "error", msg, 0)
return
}
if detail != "" {
add(scope, name, "ok", detail, count)
return
}
add(scope, name, "ok", fmt.Sprintf("成功(%d 筆)", count), count)
}
profile, profileErr := libthreads.GetMeProfile(ctx, token)
userID := strings.TrimSpace(account.ThreadsUserID)
username := strings.TrimSpace(account.Username)
if profileErr == nil && profile != nil {
if userID == "" {
userID = profile.ID.String()
}
if username == "" {
username = profile.Username
}
}
run("threads_basic", "GET /me 個人資料", func() (int, string, error) {
if profileErr != nil {
return 0, "", profileErr
}
return 1, "user_id=" + profile.ID.String() + " @" + profile.Username, nil
})
if userID == "" {
add("threads_basic", "GET /{user-id}/threads 貼文列表", "error", "缺少 threads_user_id請重新 OAuth", 0)
} else {
var sampleMediaID string
run("threads_basic", "GET /{user-id}/threads 貼文列表", func() (int, string, error) {
items, err := client.UserThreads(ctx, userID, 5)
if err != nil {
return 0, "", err
}
if len(items) > 0 {
sampleMediaID = items[0].ID
}
return len(items), "", nil
})
if sampleMediaID != "" {
run("threads_manage_insights", "GET /{media-id}/insights 貼文互動", func() (int, string, error) {
stats, err := client.GetMediaStats(ctx, sampleMediaID)
if err != nil {
return 0, "", err
}
return 1, fmt.Sprintf("likes=%d replies=%d views=%d", stats.LikeCount, stats.ReplyCount, stats.Views), nil
})
run("threads_read_replies", "GET /{media-id}/replies 留言列表", func() (int, string, error) {
items, err := client.MediaReplies(ctx, sampleMediaID, 5)
if err != nil {
return 0, "", err
}
return len(items), "", nil
})
} else {
add("threads_manage_insights", "GET /{media-id}/insights 貼文互動", "skip", "帳號尚無貼文,略過", 0)
add("threads_read_replies", "GET /{media-id}/replies 留言列表", "skip", "帳號尚無貼文,略過", 0)
}
}
run("threads_keyword_search", "GET /keyword_search 關鍵字搜尋", func() (int, string, error) {
items, err := client.KeywordSearch(ctx, libthreads.KeywordSearchOptions{
Query: "threads", Limit: 5, SearchType: "TOP",
})
if err != nil {
return 0, "", err
}
return len(items), "", nil
})
if username != "" {
run("threads_profile_discovery", "GET /profile_lookup 帳號查詢", func() (int, string, error) {
res, err := client.ProfileLookup(ctx, username)
if err != nil {
return 0, "", err
}
return 1, "@" + res.Username + " name=" + res.Name, nil
})
} else {
add("threads_profile_discovery", "GET /profile_lookup 帳號查詢", "skip", "缺少 username略過", 0)
}
if userID != "" {
run("threads_manage_mentions", "GET /{user-id}/mentions 提及", func() (int, string, error) {
items, err := client.UserMentions(ctx, userID, 5)
if err != nil {
return 0, "", err
}
return len(items), "", nil
})
run("threads_manage_insights", "GET /{user-id}/threads_insights 洞察", func() (int, string, error) {
items, err := client.UserInsights(ctx, userID, nil)
if err != nil {
return 0, "", err
}
return len(items), fmt.Sprintf("%d 項指標", len(items)), nil
})
} else {
add("threads_manage_mentions", "GET /{user-id}/mentions 提及", "skip", "缺少 threads_user_id", 0)
add("threads_manage_insights", "GET /{user-id}/threads_insights 洞察", "skip", "缺少 threads_user_id", 0)
}
run("threads_location_tagging", "GET /location_search 地點搜尋", func() (int, string, error) {
items, err := client.LocationSearch(ctx, "Taipei", 5)
if err != nil {
return 0, "", err
}
return len(items), "", nil
})
add("threads_content_publish", "POST 發文 / 回覆", "manual",
"請用產品 APIPOST /personas/:id/copy-drafts/:draftId/publish 或 outreach-drafts/publish", 0)
add("threads_delete", "DELETE /{media-id} 刪文", "manual",
"會真的刪除貼文,請在 Threads 後台或自行呼叫 DeleteMedia 測試", 0)
add("threads_manage_replies", "POST 隱藏留言", "manual",
"會改變留言狀態,請用 HideReply(reply_id) 手動測試", 0)
add("threads_share_to_instagram", "POST 同步到 IG", "manual",
"需已連結 IG 且會真的 crosspost請用 ShareToInstagram(media_id) 手動測試", 0)
return out, nil
}