@@ 26,11 26,13 @@ var (
flagVerbose bool
flagDisableDownload bool
flagPrivateOnly bool
+ flagStats bool
flagQuiet bool
flagPrivateMessages bool
)
var FileFlags flag.FlagSet
+var EmojiFlags flag.FlagSet
var MessageFlags flag.FlagSet
var ChannelFlags flag.FlagSet
var ClientFlags flag.FlagSet
@@ 57,6 59,16 @@ func initFileFlags() {
FileFlags.BoolVar(&flagDisableDownload, "n", false, "Don't download the files, just list them")
}
+func initEmojiFlags() {
+ EmojiFlags.StringVar(&flagUserAgent, "a", UA, "User-Agent string")
+ EmojiFlags.BoolVar(&flagQuiet, "q", false, "Do not output information, just ensure that everything is in order")
+ EmojiFlags.BoolVar(&flagStats, "s", false, "Generate per-user statistics on emojis")
+ EmojiFlags.StringVar(&flagToken, "t", "", "Set the authorization token for API and undocumented API calls")
+ EmojiFlags.StringVar(&flagSlackURL, "u", "", "Slack subdomain e.g. 'fakename' will call 'fakename.slack.com'")
+ EmojiFlags.StringVar(&flagConfigFile, "c", "", "JSON configuration file. Flags override config variables.")
+ EmojiFlags.StringVar(&flagOutput, "o", "", "Output file for channels")
+}
+
func initMessageFlags() {
MessageFlags.StringVar(&flagUserAgent, "a", UA, "User-Agent string")
MessageFlags.StringVar(&flagXCookie, "x", "", "Set the slack 'x' cookie for 'Visitor session cookie'")
@@ 111,6 123,9 @@ Globally used flags:
in the source "examples/config.json". Flags should
override settings in configuation.
Command specific flags:
+ emoji: Retrieves information about emojis
+ -o: output file
+ -s: per user stats
files: Retrieves all files on a Slack server
-n: Do not download the documents only retrieve their information
-q query: query is used for Slack search. Currently all built in
@@ 194,6 209,12 @@ func main() {
return
}
switch os.Args[1] {
+ case "emoji":
+ initEmojiFlags()
+ err := EmojiFlags.Parse(os.Args[2:])
+ if err == flag.ErrHelp {
+ return
+ }
case "files":
initFileFlags()
err := FileFlags.Parse(os.Args[2:])
@@ 246,6 267,27 @@ func main() {
return
}
switch os.Args[1] {
+ case "emoji":
+ items, err := sm.GetEmojiInfo(flagToken)
+ if err != nil {
+ sm.Log.Printf("Error: %s\n", err.Error())
+ return
+ }
+ sm.Log.Printf("Count: %d\n", items.Count)
+ if flagStats {
+ var count = make(map[string]int)
+ for _, emoji := range items.EmojiList {
+ count[emoji.AddedBy]++
+ }
+ for n, c := range count {
+ sm.Log.Printf("%s | %d", n, c)
+ }
+
+ } else {
+ for _, emoji := range items.EmojiList {
+ sm.Log.Printf("%s | %s | %d", emoji.Name, emoji.AddedBy, emoji.Created)
+ }
+ }
case "files":
items, err := sm.GetFileList(flagToken, flagQuery)
if err != nil {
@@ 419,7 461,7 @@ func main() {
}
}
default:
- sm.Log.Printf("Valid commands are: check channels messages files help")
+ sm.Log.Printf("Valid commands are: check channels emoji messages files help")
return
}
}
@@ 0,0 1,103 @@
+package smack
+
+import (
+ "encoding/json"
+ "errors"
+ "io/ioutil"
+ "net/http"
+ "strconv"
+ "time"
+)
+
+type EmojiList struct {
+ Ok bool
+ Count int `json:"custom_emoji_total_count"`
+ Pagination EmojiPages `json:"paging"`
+ EmojiList []Emoji `json:"emoji"`
+}
+
+type EmojiPages struct {
+ Count int
+ Pages int
+ Page int
+}
+
+type Emoji struct {
+ Name string
+ Alias string `json:"alias_for"`
+ IsAlias int `json:"is_alias"`
+ AddedBy string `json:"user_display_name"`
+ URL string `json:"url"`
+ Created int
+}
+
+func (s *Smack) GetEmojiInfo(token string) (EmojiList, error) {
+ var forms = map[string]string{
+ "token": token,
+ "page": "1",
+ "count": "100",
+ "_x_reason": "customize-emoji-new-query",
+ "_x_mode": "online",
+ }
+ b, mw, err := addMultipart(forms)
+ if err != nil {
+ return EmojiList{}, err
+ }
+ s.Request, err = http.NewRequest("POST", "https://"+s.URL+APIEmojiList, b)
+ if err != nil {
+ return EmojiList{}, err
+ }
+ s.Headers["Content-Type"] = mw
+ s.applyHeaders()
+ var client http.Client
+ res, err := client.Do(s.Request)
+ if err != nil {
+ return EmojiList{}, err
+ }
+ if res.StatusCode != http.StatusOK {
+ return EmojiList{}, errors.New("Bad HTTP status " + res.Status)
+ }
+ body, err := ioutil.ReadAll(res.Body)
+ var f EmojiList
+ err = json.Unmarshal(body, &f)
+ if f.Pagination.Pages > 1 {
+ for p := 2; p < f.Pagination.Pages; p++ {
+ var forms = map[string]string{
+ "token": token,
+ "page": strconv.Itoa(p),
+ "count": "100",
+ "_x_reason": "customize-emoji-new-query",
+ "_x_mode": "online",
+ }
+ b, mw, err := addMultipart(forms)
+ if err != nil {
+ return EmojiList{}, err
+ }
+ s.Request, err = http.NewRequest("POST", "https://"+s.URL+APIEmojiList, b)
+ if err != nil {
+ return EmojiList{}, err
+ }
+ s.Headers["Content-Type"] = mw
+ s.applyHeaders()
+ var client http.Client
+ time.Sleep(1000 * time.Millisecond)
+ res, err := client.Do(s.Request)
+ if err != nil {
+ return EmojiList{}, err
+ }
+ if res.StatusCode != http.StatusOK {
+ if res.Status == "429" {
+ time.Sleep(5000 * time.Millisecond)
+ p = p - 1
+ continue
+ }
+ return EmojiList{}, errors.New("Bad HTTP status " + res.Status)
+ }
+ body, err := ioutil.ReadAll(res.Body)
+ var e EmojiList
+ err = json.Unmarshal(body, &e)
+ f.EmojiList = append(f.EmojiList, e.EmojiList...)
+ }
+ }
+ return f, nil
+}