catbase/util/files/main.go

228 lines
6.0 KiB
Go

package main
import (
"encoding/json"
"flag"
"io"
"io/ioutil"
"net/http"
"net/url"
"os"
"path/filepath"
"strconv"
"strings"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
var (
token = flag.String("token", "", "Slack API token")
channel = flag.String("channel", "", "Slack channel ID")
limit = flag.Int("limit", 10000, "Number of items to return")
types = flag.String("types", "images,pdfs", "Type of object")
path = flag.String("path", "./", "Path to save files")
)
func main() {
flag.Parse()
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
for {
files, count := getFiles()
for _, f := range files {
downloadFile(f)
deleteFile(f)
}
if count == 1 {
break
}
}
}
func getFiles() ([]slackFile, int) {
files := fileResp{}
log.Debug().Msg("Getting files")
body := mkReq("https://slack.com/api/files.list",
"token", *token,
"count", strconv.Itoa(*limit),
"types", *types,
)
err := json.Unmarshal(body, &files)
checkErr(err)
log.Info().
Int("count", files.Paging.Count).
Bool("ok", files.Ok)
if !files.Ok {
log.Error().Interface("files", files)
}
return files.Files, files.Paging.Pages
}
func deleteFile(f slackFile) {
body := mkReq("https://slack.com/api/files.delete",
"token", *token,
"file", f.ID,
)
del := delResp{}
err := json.Unmarshal(body, &del)
checkErr(err)
if !del.Ok {
log.Fatal().
Bytes("body", body).
Str("id", f.ID).
Msg("Couldn't delete")
}
log.Info().
Str("id", f.ID).
Msg("Deleted")
}
func downloadFile(f slackFile) {
url := strings.Replace(f.URLPrivateDownload, "\\", "", -1) // because fuck slack
fname := filepath.Join(*path, f.ID+f.Name)
log.Info().
Str("url", url).
Msg("Downloading")
client := &http.Client{}
req, err := http.NewRequest("GET", url, nil)
checkErr(err)
req.Header.Add("Authorization", "Bearer "+*token)
resp, err := client.Do(req)
checkErr(err)
defer resp.Body.Close()
out, err := os.Create(fname)
checkErr(err)
defer out.Close()
io.Copy(out, resp.Body)
log.Info().
Str("id", f.ID).
Msg("Downloaded")
}
func checkErr(err error) {
if err != nil {
log.Fatal().Err(err)
}
}
func mkReq(path string, arg ...string) []byte {
if len(arg)%2 != 0 {
log.Fatal().Msg("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
}
type delResp struct {
Ok bool
}
type fileResp struct {
Ok bool `json:"ok"`
Files []slackFile `json:"files"`
Paging struct {
Count int `json:"count"`
Total int `json:"total"`
Page int `json:"page"`
Pages int `json:"pages"`
} `json:"paging"`
}
type slackFile struct {
ID string `json:"id"`
Created int `json:"created"`
Timestamp int `json:"timestamp"`
Name string `json:"name"`
Title string `json:"title"`
Mimetype string `json:"mimetype"`
Filetype string `json:"filetype"`
PrettyType string `json:"pretty_type"`
User string `json:"user"`
Editable bool `json:"editable"`
Size int `json:"size"`
Mode string `json:"mode"`
IsExternal bool `json:"is_external"`
ExternalType string `json:"external_type"`
IsPublic bool `json:"is_public"`
PublicURLShared bool `json:"public_url_shared"`
DisplayAsBot bool `json:"display_as_bot"`
Username string `json:"username"`
URLPrivate string `json:"url_private"`
URLPrivateDownload string `json:"url_private_download"`
Thumb64 string `json:"thumb_64"`
Thumb80 string `json:"thumb_80"`
Thumb360 string `json:"thumb_360"`
Thumb360W int `json:"thumb_360_w"`
Thumb360H int `json:"thumb_360_h"`
Thumb480 string `json:"thumb_480,omitempty"`
Thumb480W int `json:"thumb_480_w,omitempty"`
Thumb480H int `json:"thumb_480_h,omitempty"`
Thumb160 string `json:"thumb_160"`
Thumb720 string `json:"thumb_720,omitempty"`
Thumb720W int `json:"thumb_720_w,omitempty"`
Thumb720H int `json:"thumb_720_h,omitempty"`
Thumb800 string `json:"thumb_800,omitempty"`
Thumb800W int `json:"thumb_800_w,omitempty"`
Thumb800H int `json:"thumb_800_h,omitempty"`
Thumb960 string `json:"thumb_960,omitempty"`
Thumb960W int `json:"thumb_960_w,omitempty"`
Thumb960H int `json:"thumb_960_h,omitempty"`
Thumb1024 string `json:"thumb_1024,omitempty"`
Thumb1024W int `json:"thumb_1024_w,omitempty"`
Thumb1024H int `json:"thumb_1024_h,omitempty"`
ImageExifRotation int `json:"image_exif_rotation"`
OriginalW int `json:"original_w"`
OriginalH int `json:"original_h"`
Permalink string `json:"permalink"`
PermalinkPublic string `json:"permalink_public"`
Channels []string `json:"channels"`
Groups []interface{} `json:"groups"`
Ims []interface{} `json:"ims"`
CommentsCount int `json:"comments_count"`
InitialComment struct {
ID string `json:"id"`
Created int `json:"created"`
Timestamp int `json:"timestamp"`
User string `json:"user"`
IsIntro bool `json:"is_intro"`
Comment string `json:"comment"`
} `json:"initial_comment,omitempty"`
Reactions []struct {
Name string `json:"name"`
Users []string `json:"users"`
Count int `json:"count"`
} `json:"reactions,omitempty"`
}