FetchCurrentPublished returns the most recently published version of appID, or (nil, nil) if never published. page_size=2 suffices: Feishu disallows a new version while an in-progress one exists, so the first status==1 item with publish_time is the live one.
(ctx context.Context, client APIClient, appID string)
| 28 | // FetchCurrentPublished returns the most recently published version of appID, or (nil, nil) if never published. |
| 29 | // page_size=2 suffices: Feishu disallows a new version while an in-progress one exists, so the first status==1 item with publish_time is the live one. |
| 30 | func FetchCurrentPublished(ctx context.Context, client APIClient, appID string) (*AppVersion, error) { |
| 31 | path := fmt.Sprintf( |
| 32 | "/open-apis/application/v6/applications/%s/app_versions?lang=zh_cn&page_size=2", |
| 33 | appID, |
| 34 | ) |
| 35 | raw, err := client.CallAPI(ctx, "GET", path, nil) |
| 36 | if err != nil { |
| 37 | return nil, err |
| 38 | } |
| 39 | |
| 40 | var envelope struct { |
| 41 | Data struct { |
| 42 | Items []struct { |
| 43 | VersionID string `json:"version_id"` |
| 44 | Version string `json:"version"` |
| 45 | Status int `json:"status"` |
| 46 | PublishTime json.RawMessage `json:"publish_time"` |
| 47 | EventInfos []struct { |
| 48 | EventType string `json:"event_type"` |
| 49 | } `json:"event_infos"` |
| 50 | Scopes []struct { |
| 51 | Scope string `json:"scope"` |
| 52 | TokenTypes []string `json:"token_types"` |
| 53 | } `json:"scopes"` |
| 54 | } `json:"items"` |
| 55 | } `json:"data"` |
| 56 | } |
| 57 | if err := json.Unmarshal(raw, &envelope); err != nil { |
| 58 | return nil, fmt.Errorf("decode app_versions response: %w", err) |
| 59 | } |
| 60 | |
| 61 | for _, it := range envelope.Data.Items { |
| 62 | if it.Status != appVersionStatusPublished || !publishTimeSet(it.PublishTime) { |
| 63 | continue |
| 64 | } |
| 65 | v := &AppVersion{ |
| 66 | VersionID: it.VersionID, |
| 67 | Version: it.Version, |
| 68 | } |
| 69 | for _, e := range it.EventInfos { |
| 70 | if e.EventType != "" { |
| 71 | v.EventTypes = append(v.EventTypes, e.EventType) |
| 72 | } |
| 73 | } |
| 74 | for _, s := range it.Scopes { |
| 75 | if s.Scope != "" && containsString(s.TokenTypes, "tenant") { |
| 76 | v.TenantScopes = append(v.TenantScopes, s.Scope) |
| 77 | } |
| 78 | } |
| 79 | return v, nil |
| 80 | } |
| 81 | return nil, nil |
| 82 | } |
| 83 | |
| 84 | // publishTimeSet rejects null and empty-string; any other value is a real publish_time. |
| 85 | func publishTimeSet(raw json.RawMessage) bool { |