initial commit

This commit is contained in:
Chris Sexton 2018-06-29 10:42:56 -04:00
commit 88e73ca726
5 changed files with 306 additions and 0 deletions

1
AUTHORS Executable file
View File

@ -0,0 +1 @@
Chris Sexton <chris dot sexton at gmail dot com>

14
LICENSE Executable file
View File

@ -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.

57
emojytool/emojytool.go Normal file
View File

@ -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)
}

220
gethistory/gethistory.go Normal file
View File

@ -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"`
}

14
readme.adoc Normal file
View File

@ -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.