forked from rusq/slackdump
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchannels.go
117 lines (104 loc) · 3.24 KB
/
channels.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package slackdump
import (
"context"
"fmt"
"io"
"os"
"runtime/trace"
"strings"
"text/tabwriter"
"github.com/slack-go/slack"
)
// Channels keeps slice of channels
type Channels []slack.Channel
// getChannels list all conversations for a user. `chanTypes` specifies
// the type of messages to fetch. See github.com/rusq/slack docs for possible
// values
func (sd *SlackDumper) getChannels(ctx context.Context, chanTypes []string) (Channels, error) {
ctx, task := trace.NewTask(ctx, "getChannels")
defer task.End()
limiter := newLimiter(tier2, sd.options.limiterBurst, int(sd.options.limiterBoost))
if chanTypes == nil {
chanTypes = allChanTypes
}
params := &slack.GetConversationsParameters{Types: chanTypes}
allChannels := make([]slack.Channel, 0, 50)
for {
var (
chans []slack.Channel
nextcur string
)
if err := withRetry(ctx, limiter, sd.options.conversationRetries, func() error {
var err error
trace.WithRegion(ctx, "GetConversations", func() {
chans, nextcur, err = sd.client.GetConversations(params)
})
return err
}); err != nil {
return nil, err
}
allChannels = append(allChannels, chans...)
if nextcur == "" {
break
}
params.Cursor = nextcur
limiter.Wait(ctx)
}
return allChannels, nil
}
// GetChannels list all conversations for a user. `chanTypes` specifies
// the type of messages to fetch. See github.com/rusq/slack docs for possible
// values
func (sd *SlackDumper) GetChannels(ctx context.Context, chanTypes ...string) (Channels, error) {
return sd.getChannels(ctx, chanTypes)
}
// ToText outputs Channels cs to io.Writer w in Text format.
func (cs Channels) ToText(sd *SlackDumper, w io.Writer) (err error) {
const strFormat = "%s\t%s\t%s\t%s\n"
writer := tabwriter.NewWriter(w, 0, 0, 2, ' ', 0)
defer writer.Flush()
fmt.Fprintf(writer, strFormat, "ID", "Arch", "Saved", "What")
for i, ch := range cs {
who := sd.whoThisChannelFor(&ch)
archived := "-"
if cs[i].IsArchived || sd.IsUserDeleted(ch.User) {
archived = "arch"
}
saved := "-"
if _, err := os.Stat(ch.ID + ".json"); err == nil {
saved = "saved"
}
fmt.Fprintf(writer, strFormat, ch.ID, archived, saved, who)
}
return nil
}
// whoThisChannelFor return the proper name of the addressee of the channel
// Parameters: channel and userIdMap - mapping slackID to users
func (sd *SlackDumper) whoThisChannelFor(channel *slack.Channel) (who string) {
switch {
case channel.IsIM:
who = "@" + sd.username(channel.User)
case channel.IsMpIM:
who = strings.Replace(channel.Purpose.Value, " messaging with", "", -1)
case channel.IsPrivate:
who = "🔒 " + channel.NameNormalized
default:
who = "#" + channel.NameNormalized
}
return who
}
// username tries to resolve the username by ID. If the internal users map is not
// initialised, it will return the ID, otherwise, if the user is not found in
// cache, it will assume that the user is external, and return the ID with
// "external" prefix.
func (sd *SlackDumper) username(id string) string {
if sd.UserIndex == nil {
// no user cache, use the IDs.
return id
}
user, ok := sd.UserIndex[id]
if !ok {
return "<external>:" + id
}
return user.Name
}