initial commit
This commit is contained in:
commit
88e73ca726
|
@ -0,0 +1,14 @@
|
|||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified
|
||||
copies of this license document, and changing it is allowed as long
|
||||
as the name is changed.
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
// © 2018 the slacktricks Authors under the WTFPL license. See AUTHORS for the list of authors.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var dataDir = flag.String("data", "data", "Where to save emoji")
|
||||
|
||||
type emojyResp struct {
|
||||
Emoji map[string]string
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
f, err := ioutil.ReadAll(bufio.NewReader(os.Stdin))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var resp emojyResp
|
||||
if err := json.Unmarshal(f, &resp); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
count := 0
|
||||
for k, v := range resp.Emoji {
|
||||
if !strings.HasPrefix(v, "alias") {
|
||||
ext := filepath.Ext(v)
|
||||
resp, err := http.Get(v)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fname := fmt.Sprintf("%s%s", k, ext)
|
||||
f, err := os.Create(filepath.Join(*dataDir, fname))
|
||||
defer f.Close()
|
||||
b, err := io.Copy(f, resp.Body)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
log.Printf("Saved %d bytes to %s", b, fname)
|
||||
count++
|
||||
}
|
||||
}
|
||||
log.Printf("Saved %d emojys", count)
|
||||
}
|
|
@ -0,0 +1,220 @@
|
|||
// © 2018 the slacktricks Authors under the WTFPL license. See AUTHORS for the list of authors.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var (
|
||||
token = flag.String("token", "", "Slack API token")
|
||||
channel = flag.String("channel", "", "Slack channel ID")
|
||||
limit = flag.Int("limit", 100, "Number of items to return")
|
||||
byChannel = flag.Bool("byChannel", false, "Arrange data by channel (default by user)")
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
users := getUsers()
|
||||
history := getHistory(*channel)
|
||||
|
||||
if !*byChannel {
|
||||
for _, u := range users.Members {
|
||||
writeUser(history, u)
|
||||
}
|
||||
} else {
|
||||
writeChannel(history)
|
||||
}
|
||||
}
|
||||
|
||||
func getUsers() userResp {
|
||||
users := userResp{}
|
||||
|
||||
log.Printf("Getting users")
|
||||
body := mkReq("https://slack.com/api/users.list",
|
||||
"token", *token,
|
||||
)
|
||||
|
||||
err := json.Unmarshal(body, &users)
|
||||
checkErr(err)
|
||||
|
||||
return users
|
||||
}
|
||||
|
||||
func getHistory(ch string) []histResp {
|
||||
history := []histResp{}
|
||||
cursor := ""
|
||||
for {
|
||||
log.Printf("Getting history cursor: '%s'", cursor)
|
||||
body := mkReq("https://slack.com/api/conversations.history",
|
||||
"token", *token,
|
||||
"channel", ch,
|
||||
"limit", strconv.Itoa(*limit),
|
||||
"cursor", cursor,
|
||||
)
|
||||
resp := histResp{}
|
||||
err := json.Unmarshal(body, &resp)
|
||||
checkErr(err)
|
||||
history = append(history, resp)
|
||||
if resp.ResponseMetadata.NextCursor == "" {
|
||||
break
|
||||
} else {
|
||||
cursor = resp.ResponseMetadata.NextCursor
|
||||
}
|
||||
}
|
||||
|
||||
return history
|
||||
}
|
||||
|
||||
func checkErr(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func mkReq(path string, arg ...string) []byte {
|
||||
if len(arg)%2 != 0 {
|
||||
log.Fatal("Bad request arg number.")
|
||||
}
|
||||
|
||||
u, err := url.Parse(path)
|
||||
checkErr(err)
|
||||
|
||||
q := u.Query()
|
||||
for i := 0; i < len(arg); i += 2 {
|
||||
key := arg[i]
|
||||
val := arg[i+1]
|
||||
if val != "" {
|
||||
q.Set(key, val)
|
||||
}
|
||||
}
|
||||
u.RawQuery = q.Encode()
|
||||
|
||||
resp, err := http.Get(u.String())
|
||||
checkErr(err)
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
checkErr(err)
|
||||
|
||||
return body
|
||||
}
|
||||
|
||||
func writeChannel(history []histResp) {
|
||||
fname := *channel + ".json"
|
||||
f, err := os.Create(fname)
|
||||
checkErr(err)
|
||||
defer f.Close()
|
||||
|
||||
j, err := json.Marshal(history)
|
||||
checkErr(err)
|
||||
f.Write(j)
|
||||
|
||||
reactionCount := map[string]int{}
|
||||
for _, h := range history {
|
||||
for _, m := range h.Messages {
|
||||
if len(m.Reactions) > 0 {
|
||||
for _, r := range m.Reactions {
|
||||
reactionCount[r.Name] += r.Count
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("%+v", reactionCount)
|
||||
}
|
||||
|
||||
func writeUser(history []histResp, u user) {
|
||||
// open file and write shit out
|
||||
fname := u.Name + ".txt"
|
||||
id := u.ID
|
||||
|
||||
f, err := os.OpenFile(fname, os.O_RDWR|os.O_CREATE, 0755)
|
||||
checkErr(err)
|
||||
defer f.Close()
|
||||
|
||||
for _, h := range history {
|
||||
for _, m := range h.Messages {
|
||||
if m.User == id {
|
||||
fmt.Fprintf(f, "%s\n", m.Text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type histResp struct {
|
||||
Ok bool `json:"ok"`
|
||||
Messages []struct {
|
||||
Type string `json:"type"`
|
||||
User string `json:"user"`
|
||||
Text string `json:"text"`
|
||||
Ts string `json:"ts"`
|
||||
Reactions []reaction `json:"reactions"`
|
||||
} `json:"messages"`
|
||||
HasMore bool `json:"has_more"`
|
||||
PinCount int `json:"pin_count"`
|
||||
ResponseMetadata struct {
|
||||
NextCursor string `json:"next_cursor"`
|
||||
} `json:"response_metadata"`
|
||||
}
|
||||
|
||||
type reaction struct {
|
||||
Name string `json:"name"`
|
||||
Users []string `json:"users"`
|
||||
Count int `json:"count"`
|
||||
}
|
||||
|
||||
type user struct {
|
||||
ID string `json:"id"`
|
||||
TeamID string `json:"team_id"`
|
||||
Name string `json:"name"`
|
||||
Deleted bool `json:"deleted"`
|
||||
Color string `json:"color"`
|
||||
RealName string `json:"real_name"`
|
||||
Tz string `json:"tz"`
|
||||
TzLabel string `json:"tz_label"`
|
||||
TzOffset int `json:"tz_offset"`
|
||||
Profile struct {
|
||||
AvatarHash string `json:"avatar_hash"`
|
||||
StatusText string `json:"status_text"`
|
||||
StatusEmoji string `json:"status_emoji"`
|
||||
RealName string `json:"real_name"`
|
||||
DisplayName string `json:"display_name"`
|
||||
RealNameNormalized string `json:"real_name_normalized"`
|
||||
DisplayNameNormalized string `json:"display_name_normalized"`
|
||||
Email string `json:"email"`
|
||||
Image24 string `json:"image_24"`
|
||||
Image32 string `json:"image_32"`
|
||||
Image48 string `json:"image_48"`
|
||||
Image72 string `json:"image_72"`
|
||||
Image192 string `json:"image_192"`
|
||||
Image512 string `json:"image_512"`
|
||||
Team string `json:"team"`
|
||||
} `json:"profile"`
|
||||
IsAdmin bool `json:"is_admin"`
|
||||
IsOwner bool `json:"is_owner"`
|
||||
IsPrimaryOwner bool `json:"is_primary_owner"`
|
||||
IsRestricted bool `json:"is_restricted"`
|
||||
IsUltraRestricted bool `json:"is_ultra_restricted"`
|
||||
IsBot bool `json:"is_bot"`
|
||||
Updated int `json:"updated"`
|
||||
IsAppUser bool `json:"is_app_user,omitempty"`
|
||||
Has2Fa bool `json:"has_2fa"`
|
||||
}
|
||||
|
||||
type userResp struct {
|
||||
Ok bool `json:"ok"`
|
||||
Members []user `json:"members"`
|
||||
CacheTs int `json:"cache_ts"`
|
||||
ResponseMetadata struct {
|
||||
NextCursor string `json:"next_cursor"`
|
||||
} `json:"response_metadata"`
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
= Slack Tricks
|
||||
|
||||
Just a collection of silly slack utils that have come in handy.
|
||||
|
||||
== emojytool
|
||||
|
||||
Back up your slack "emojy" as local image files. Suitable for mass exodus from
|
||||
Slack.
|
||||
|
||||
== gethistory
|
||||
|
||||
Grab the available history from slack. This works by user for text hisory,
|
||||
suitable for babbler purposes or by channel if more detailed information is
|
||||
desired.
|
Loading…
Reference in New Issue