diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..9775100 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,19 @@ + +## Describe your changes + + +## Non-obvious technical information + + +## Checklist before requesting a review +- [ ] The code runs successfully. + +```commandline +HERE IS SOME COMMAND LINE OUTPUT +``` diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml new file mode 100644 index 0000000..f2fffad --- /dev/null +++ b/.github/workflows/audit.yml @@ -0,0 +1,34 @@ +name: Audit + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + + audit: + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: 1.22 + + - name: Verify dependencies + run: go mod verify + + - name: Build + run: go build -v ./... + + - name: Run go vet + run: go vet ./... + + - name: Install staticcheck + run: go install honnef.co/go/tools/cmd/staticcheck@latest + + - name: Run staticcheck + run: staticcheck ./... diff --git a/.gitignore b/.gitignore index 6f6f5e6..e0f7ecc 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,8 @@ # Go workspace file go.work go.work.sum + +# IDE directories and misc. files +.idea +.vscode +**/.DS_Store diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1c050c8 --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +default: lint + +.PHONY: init +init: + go mod download + +.PHONY: lint +lint: + go mod tidy + go fmt ./... + go vet ./... + staticcheck ./... diff --git a/README.md b/README.md index 42eda70..223d684 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,13 @@ -# golang-scripting +# Various Scripts in the Key of Golang Various scripts written in Golang. + +## Scripts + +### Slack Message Parser + + +#### Instructions +```console +cp [YOUR_ARCHIVE_PATH_HERE]/*.json ./SlackMessages/ +go run slack_message_parser.go +``` diff --git a/cmd/slackMessageParser/main.go b/cmd/slackMessageParser/main.go new file mode 100644 index 0000000..aea22af --- /dev/null +++ b/cmd/slackMessageParser/main.go @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2024 Michael Plunkett (https://github.com/michplunkett) + * All rights reserved. + * Used to parse Slack messages. + */ + +package main + +import ( + "encoding/json" + "fmt" + "log" + "os" + "path/filepath" + "strconv" + "strings" + "time" + + "github.com/gocarina/gocsv" +) + +type Message struct { + TimeStamp string + UserID string `json:"user"` + TS string `json:"ts"` + Type string `json:"type"` + ClientMessageID string `json:"client_msg_id"` + Text string `json:"text,omitempty"` + UserProfile *UserProfile `json:"user_profile,omitempty"` + Attachments *[]*Attachment `json:"attachments,omitempty"` + Files *[]File `json:"files,omitempty"` + IsUpload bool `json:"upload,omitempty"` +} + +type UserProfile struct { + ProfileImage string `json:"image_72,omitempty"` + FirstName string `json:"first_name,omitempty"` + RealName string `json:"real_name,omitempty"` + DisplayName string `json:"display_name,omitempty"` + Name string `json:"name,omitempty"` +} + +type Attachment struct { + Text string `json:"text"` + Fallback string `json:"fallback"` + FromURL string `json:"from_url"` + ServiceName string `json:"service_name"` + ID int `json:"id"` + OriginalURL string `json:"original_url"` +} + +type File struct { + ID string `json:"id"` + Name string `json:"name"` + Title string `json:"title"` + MimeType string `json:"mimetype"` + FileType string `json:"pretty_type"` + IsExternal bool `json:"is_external"` + IsPublic bool `json:"is_public"` + DownloadLink string `json:"url_private_download"` + Height int `json:"original_w"` + Width int `json:"original_h"` +} + +type CSVRecord struct { + TimeStamp string + UserID string + UserName string + RealName string + MessageType string + Text string + Attachments []string + Files []string +} + +func main() { + if _, err := os.Stat("../../SlackMessages"); os.IsNotExist(err) { + log.Fatal("the ./SlackMessages directory does not exist") + } + + files, err := filepath.Glob("../../SlackMessages/*.json") + if err != nil { + log.Fatal(err) + } + + if len(files) == 0 { + log.Fatal("could not find *.json files in the ./SlackMessages directory") + } + + messages := make([]*Message, 0) + + for _, file := range files { + bytes, err := os.ReadFile(file) + if err != nil { + fmt.Printf("error occured while opening %s: %+v\n", file, err) + continue + } + + fileMessages := make([]*Message, 0) + err = json.Unmarshal(bytes, &fileMessages) + if err != nil { + fmt.Printf("error occured while parsing JSON from %s: %+v\n", file, err) + continue + } + + messages = append(messages, fileMessages...) + } + + csvRecords := make([]*CSVRecord, 0) + for _, msg := range messages { + record := &CSVRecord{ + UserID: msg.UserID, + UserName: "", + RealName: "", + MessageType: msg.Type, + Attachments: make([]string, 0), + Files: make([]string, 0), + } + + timeStampSplit := strings.Split(msg.TS, ".") + seconds, err := strconv.ParseInt(timeStampSplit[0], 10, 64) + if err != nil { + fmt.Printf("error occured while parsing seconds: %+v\n", err) + continue + } + + nanoseconds, err := strconv.ParseInt(timeStampSplit[1], 10, 64) + if err != nil { + fmt.Printf("error occured while parsing nanoseconds: %+v\n", err) + continue + } + + record.TimeStamp = time.Unix(seconds, nanoseconds).Format(time.RFC3339) + + if msg.UserProfile != nil { + record.UserName = msg.UserProfile.Name + record.RealName = msg.UserProfile.RealName + } + + if msg.Text != "" { + record.Text = msg.Text + } + + if msg.Attachments != nil { + for _, attachment := range *msg.Attachments { + record.Attachments = append(record.Attachments, attachment.OriginalURL) + } + } + + if msg.Files != nil { + for _, file := range *msg.Files { + record.Files = append(record.Files, file.DownloadLink) + } + } + + csvRecords = append(csvRecords, record) + } + + csvFile, err := os.Create("../../slack_records.csv") + if err != nil { + log.Fatal(err) + } + defer csvFile.Close() + + _ = gocsv.MarshalFile(csvRecords, csvFile) +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..37af3fe --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module github.com/michplunkett/golang-scripting + +go 1.22.4 + +require github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..e47b2a7 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1 h1:FWNFq4fM1wPfcK40yHE5UO3RUdSNPaBC+j3PokzA6OQ= +github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI=