Skip to content

Commit

Permalink
some more edge apis
Browse files Browse the repository at this point in the history
  • Loading branch information
rusq committed Mar 26, 2024
1 parent 6e1b3f6 commit 7d489be
Show file tree
Hide file tree
Showing 13 changed files with 596 additions and 201 deletions.
15 changes: 12 additions & 3 deletions cmd/slackdump/internal/diag/edge.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func runEdge(ctx context.Context, cmd *base.Command, args []string) error {
}

lg.Printf("*** DMs test ***")
dms, err := cl.DMs(ctx)
dms, err := cl.ClientDMs(ctx)
if err != nil {
return err
}
Expand All @@ -67,7 +67,7 @@ func runEdge(ctx context.Context, cmd *base.Command, args []string) error {
}

lg.Printf("*** IMs test ***")
ims, err := cl.IMs(ctx)
ims, err := cl.IMList(ctx)
if err != nil {
return err
}
Expand All @@ -76,14 +76,23 @@ func runEdge(ctx context.Context, cmd *base.Command, args []string) error {
}

lg.Printf("*** Counts ***")
counts, err := cl.Counts(ctx)
counts, err := cl.ClientCounts(ctx)
if err != nil {
return err
}
if err := save("counts.json", counts); err != nil {
return err
}

lg.Print("Conversations Generic Info")
ch, err := cl.ConversationsGenericInfo(ctx, "C065H568ZAT")
if err != nil {
return err
}
if err := save("conversations_generic_info.json", ch); err != nil {
return err
}

return nil
}

Expand Down
58 changes: 50 additions & 8 deletions internal/edge/bookmarks.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,64 @@
package edge

import "encoding/json"
import (
"context"
"encoding/json"
)

// bookmarks.* API

/*
channel: GM27XUQT0
include_folders: true
include_legacy_workflows: true
*/
type bookmarksListForm struct {
BaseRequest
Channel string `json:"channel"`
IncludeFolders bool `json:"include_folders"`
IncludeLegacyWorkflows bool `json:"include_legacy_workflows"`
WebClientFields
}

type bookmarksListResponse struct {
BaseResponse
Bookmarks []json.RawMessage `json:"bookmarks"`
Bookmarks []Bookmark `json:"bookmarks"`
}

type Bookmark struct {
ID string `json:"id"`
ChannelID string `json:"channel_id"`
Title json.RawMessage `json:"title"`
Link string `json:"link"`
Emoji json.RawMessage `json:"emoji"`
IconURL json.RawMessage `json:"icon_url"`
Type string `json:"type"`
EntityID json.RawMessage `json:"entity_id"`
DateCreated int64 `json:"date_created"`
DateUpdated int64 `json:"date_updated"`
Rank string `json:"rank"`
LastUpdatedByUserID string `json:"last_updated_by_user_id"`
LastUpdatedByTeamID string `json:"last_updated_by_team_id"`
ShortcutID string `json:"shortcut_id"`
AppID string `json:"app_id"`
AppActionID string `json:"app_action_id"`
ImageURL json.RawMessage `json:"image_url"`
DateCreate int64 `json:"date_create"`
DateUpdate int64 `json:"date_update"`
ParentID json.RawMessage `json:"parent_id"`
}

//"bookmarks.list"
// BookmarksList lists bookmarks for a channel.
func (cl *Client) BookmarksList(ctx context.Context, channelID string) ([]Bookmark, error) {
form := &bookmarksListForm{
BaseRequest: BaseRequest{Token: cl.token},
Channel: channelID,
IncludeFolders: true,
IncludeLegacyWorkflows: true,
WebClientFields: webclientReason("bookmarks-store/conditional-fetching"),
}
var resp bookmarksListResponse
hr, err := cl.PostForm(ctx, "bookmarks.list", values(form, true))
if err != nil {
return nil, err
}
if err := cl.ParseResponse(&resp, hr); err != nil {
return nil, err
}
return resp.Bookmarks, nil
}
146 changes: 146 additions & 0 deletions internal/edge/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package edge

import (
"context"
"net/url"

"github.com/rusq/slack"
"github.com/rusq/slackdump/v3/internal/fasttime"
)

// client.* API

type clientCountsForm struct {
BaseRequest
ThreadCountsByChannel bool `json:"thread_counts_by_channel"`
OrgWideAware bool `json:"org_wide_aware"`
IncludeFileChannels bool `json:"include_file_channels"`
WebClientFields
}

type ClientCountsResponse struct {
BaseResponse
Channels []ChannelSnapshot `json:"channels,omitempty"`
MPIMs []ChannelSnapshot `json:"mpims,omitempty"`
IMs []ChannelSnapshot `json:"ims,omitempty"`
}

type ChannelSnapshot struct {
ID string `json:"id"`
LastRead fasttime.Time `json:"last_read"`
Latest fasttime.Time `json:"latest"`
HistoryInvalid fasttime.Time `json:"history_invalid"`
MentionCount int `json:"mention_count"`
HasUnreads bool `json:"has_unreads"`
}

func (cl *Client) ClientCounts(ctx context.Context) (ClientCountsResponse, error) {
form := clientCountsForm{
BaseRequest: BaseRequest{Token: cl.token},
ThreadCountsByChannel: true,
OrgWideAware: true,
IncludeFileChannels: true,
WebClientFields: webclientReason("client-counts-api/fetchClientCounts"),
}

resp, err := cl.PostForm(ctx, "client.counts", values(form, true))
if err != nil {
return ClientCountsResponse{}, err
}
r := ClientCountsResponse{}
if err := cl.ParseResponse(&r, resp); err != nil {
return ClientCountsResponse{}, err
}
return r, nil
}

type clientDMsForm struct {
BaseRequest
Count int `json:"count"`
IncludeClosed bool `json:"include_closed"`
IncludeChannel bool `json:"include_channel"`
ExcludeBots bool `json:"exclude_bots"`
Cursor string `json:"cursor,omitempty"`
WebClientFields
}

func (d clientDMsForm) Values() url.Values {
return values(d, true)
}

type clientDMsResponse struct {
BaseResponse
IMs []ClientDM `json:"ims,omitempty"`
MPIMs []ClientDM `json:"mpims,omitempty"` //TODO
}

type ClientDM struct {
ID string `json:"id"`
// Message slack.Message `json:"message,omitempty"`
Channel Channel `json:"channel,omitempty"`
Latest fasttime.Time `json:"latest,omitempty"` // i.e. "1710632873.037269"
}

type Channel struct {
ID string `json:"id"`
Created slack.JSONTime `json:"created"`
IsFrozen bool `json:"is_frozen"`
IsArchived bool `json:"is_archived"`
IsIM bool `json:"is_im"`
IsOrgShared bool `json:"is_org_shared"`
ContextTeamID string `json:"context_team_id"`
Updated slack.JSONTime `json:"updated"`
User string `json:"user"`
LastRead fasttime.Time `json:"last_read"`
Latest fasttime.Time `json:"latest"`
IsOpen bool `json:"is_open"`
}

func (c Channel) SlackChannel() slack.Channel {
return slack.Channel{
GroupConversation: slack.GroupConversation{
Conversation: slack.Conversation{
ID: c.ID,
Created: c.Created,
IsIM: c.IsIM,
IsOrgShared: c.IsOrgShared,
LastRead: c.LastRead.SlackString(),
},
IsArchived: c.IsArchived,
},
}

}

func (cl *Client) ClientDMs(ctx context.Context) ([]ClientDM, error) {
form := clientDMsForm{
BaseRequest: BaseRequest{Token: cl.token},
Count: 250,
IncludeClosed: true,
IncludeChannel: true,
ExcludeBots: false,
Cursor: "",
WebClientFields: webclientReason("dms-tab-populate"),
}
lim := tier2.limiter()
var IMs []ClientDM
for {
resp, err := cl.PostFormRaw(ctx, cl.webapiURL("client.dms"), form.Values())
if err != nil {
return nil, err
}
r := clientDMsResponse{}
if err := cl.ParseResponse(&r, resp); err != nil {
return nil, err
}
IMs = append(IMs, r.IMs...)
if r.ResponseMetadata.NextCursor == "" {
break
}
form.Cursor = r.ResponseMetadata.NextCursor
if err := lim.Wait(ctx); err != nil {
return nil, err
}
}
return IMs, nil
}
55 changes: 55 additions & 0 deletions internal/edge/conversations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package edge

import (
"context"
"encoding/json"

"github.com/rusq/slack"
)

// conversations.* API

// conversationsGenericInfoForm is the request to conversations.genericInfo
type conversationsGenericInfoForm struct {
BaseRequest
UpdatedChannels string `json:"updated_channels"` // i.e. {"C065H568ZAT":0}
WebClientFields
}

type conversationsGenericInfoResponse struct {
BaseResponse
Channels []slack.Channel `json:"channels"`
UnchangedChannelIDs []string `json:"unchanged_channel_ids"`
}

func (cl *Client) ConversationsGenericInfo(ctx context.Context, channelID ...string) ([]slack.Channel, error) {
updChannel := make(map[string]int, len(channelID))
for _, id := range channelID {
updChannel[id] = 0
}
b, err := json.Marshal(updChannel)
if err != nil {
return nil, err
}
form := conversationsGenericInfoForm{
BaseRequest: BaseRequest{
Token: cl.token,
},
UpdatedChannels: string(b),
WebClientFields: WebClientFields{
XReason: "fallback:UnknownFetchManager",
XMode: "online",
XSonic: true,
XAppName: "client",
},
}
resp, err := cl.PostForm(ctx, "conversations.genericInfo", values(form, true))
if err != nil {
return nil, err
}
var r conversationsGenericInfoResponse
if err := cl.ParseResponse(&r, resp); err != nil {
return nil, err
}
return r.Channels, nil
}
Loading

0 comments on commit 7d489be

Please sign in to comment.