Skip to content

Commit 84145cb

Browse files
authored
Add Slack message parsing (#1)
## Describe your changes Set up repository and add the Slack message parsing script. ## Checklist before requesting a review - [x] The code runs successfully. ```commandline michaelp@MacBook-Air-18 golang-scripting % go run ./cmd/slackMessageParser/main.go 2024/07/15 23:38:39 the ./SlackMessages directory does not exist exit status 1 ```
1 parent 1f852ea commit 84145cb

File tree

8 files changed

+255
-1
lines changed

8 files changed

+255
-1
lines changed

.github/pull_request_template.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<!---
2+
Please write your PR name in the present imperative tense. Examples of present imperative tense are:
3+
"Fix issue in the dispatcher where…", "Improve our handling of…", etc."
4+
5+
For more information on Pull Requests, you can reference here:
6+
https://success.vanillaforums.com/kb/articles/228-using-pull-requests-to-contribute
7+
-->
8+
## Describe your changes
9+
10+
11+
## Non-obvious technical information
12+
13+
14+
## Checklist before requesting a review
15+
- [ ] The code runs successfully.
16+
17+
```commandline
18+
HERE IS SOME COMMAND LINE OUTPUT
19+
```

.github/workflows/audit.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: Audit
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
11+
audit:
12+
runs-on: ubuntu-20.04
13+
steps:
14+
- uses: actions/checkout@v2
15+
16+
- name: Set up Go
17+
uses: actions/setup-go@v2
18+
with:
19+
go-version: 1.22
20+
21+
- name: Verify dependencies
22+
run: go mod verify
23+
24+
- name: Build
25+
run: go build -v ./...
26+
27+
- name: Run go vet
28+
run: go vet ./...
29+
30+
- name: Install staticcheck
31+
run: go install honnef.co/go/tools/cmd/staticcheck@latest
32+
33+
- name: Run staticcheck
34+
run: staticcheck ./...

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,8 @@
2020
# Go workspace file
2121
go.work
2222
go.work.sum
23+
24+
# IDE directories and misc. files
25+
.idea
26+
.vscode
27+
**/.DS_Store

Makefile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
default: lint
2+
3+
.PHONY: init
4+
init:
5+
go mod download
6+
7+
.PHONY: lint
8+
lint:
9+
go mod tidy
10+
go fmt ./...
11+
go vet ./...
12+
staticcheck ./...

README.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,13 @@
1-
# golang-scripting
1+
# Various Scripts in the Key of Golang
22
Various scripts written in Golang.
3+
4+
## Scripts
5+
6+
### Slack Message Parser
7+
8+
9+
#### Instructions
10+
```console
11+
cp [YOUR_ARCHIVE_PATH_HERE]/*.json ./SlackMessages/
12+
go run slack_message_parser.go
13+
```

cmd/slackMessageParser/main.go

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
/*
2+
* Copyright (c) 2024 Michael Plunkett (https://github.com/michplunkett)
3+
* All rights reserved.
4+
* Used to parse Slack messages.
5+
*/
6+
7+
package main
8+
9+
import (
10+
"encoding/json"
11+
"fmt"
12+
"log"
13+
"os"
14+
"path/filepath"
15+
"strconv"
16+
"strings"
17+
"time"
18+
19+
"github.com/gocarina/gocsv"
20+
)
21+
22+
type Message struct {
23+
TimeStamp string
24+
UserID string `json:"user"`
25+
TS string `json:"ts"`
26+
Type string `json:"type"`
27+
ClientMessageID string `json:"client_msg_id"`
28+
Text string `json:"text,omitempty"`
29+
UserProfile *UserProfile `json:"user_profile,omitempty"`
30+
Attachments *[]*Attachment `json:"attachments,omitempty"`
31+
Files *[]File `json:"files,omitempty"`
32+
IsUpload bool `json:"upload,omitempty"`
33+
}
34+
35+
type UserProfile struct {
36+
ProfileImage string `json:"image_72,omitempty"`
37+
FirstName string `json:"first_name,omitempty"`
38+
RealName string `json:"real_name,omitempty"`
39+
DisplayName string `json:"display_name,omitempty"`
40+
Name string `json:"name,omitempty"`
41+
}
42+
43+
type Attachment struct {
44+
Text string `json:"text"`
45+
Fallback string `json:"fallback"`
46+
FromURL string `json:"from_url"`
47+
ServiceName string `json:"service_name"`
48+
ID int `json:"id"`
49+
OriginalURL string `json:"original_url"`
50+
}
51+
52+
type File struct {
53+
ID string `json:"id"`
54+
Name string `json:"name"`
55+
Title string `json:"title"`
56+
MimeType string `json:"mimetype"`
57+
FileType string `json:"pretty_type"`
58+
IsExternal bool `json:"is_external"`
59+
IsPublic bool `json:"is_public"`
60+
DownloadLink string `json:"url_private_download"`
61+
Height int `json:"original_w"`
62+
Width int `json:"original_h"`
63+
}
64+
65+
type CSVRecord struct {
66+
TimeStamp string
67+
UserID string
68+
UserName string
69+
RealName string
70+
MessageType string
71+
Text string
72+
Attachments []string
73+
Files []string
74+
}
75+
76+
func main() {
77+
if _, err := os.Stat("../../SlackMessages"); os.IsNotExist(err) {
78+
log.Fatal("the ./SlackMessages directory does not exist")
79+
}
80+
81+
files, err := filepath.Glob("../../SlackMessages/*.json")
82+
if err != nil {
83+
log.Fatal(err)
84+
}
85+
86+
if len(files) == 0 {
87+
log.Fatal("could not find *.json files in the ./SlackMessages directory")
88+
}
89+
90+
messages := make([]*Message, 0)
91+
92+
for _, file := range files {
93+
bytes, err := os.ReadFile(file)
94+
if err != nil {
95+
fmt.Printf("error occured while opening %s: %+v\n", file, err)
96+
continue
97+
}
98+
99+
fileMessages := make([]*Message, 0)
100+
err = json.Unmarshal(bytes, &fileMessages)
101+
if err != nil {
102+
fmt.Printf("error occured while parsing JSON from %s: %+v\n", file, err)
103+
continue
104+
}
105+
106+
messages = append(messages, fileMessages...)
107+
}
108+
109+
csvRecords := make([]*CSVRecord, 0)
110+
for _, msg := range messages {
111+
record := &CSVRecord{
112+
UserID: msg.UserID,
113+
UserName: "",
114+
RealName: "",
115+
MessageType: msg.Type,
116+
Attachments: make([]string, 0),
117+
Files: make([]string, 0),
118+
}
119+
120+
timeStampSplit := strings.Split(msg.TS, ".")
121+
seconds, err := strconv.ParseInt(timeStampSplit[0], 10, 64)
122+
if err != nil {
123+
fmt.Printf("error occured while parsing seconds: %+v\n", err)
124+
continue
125+
}
126+
127+
nanoseconds, err := strconv.ParseInt(timeStampSplit[1], 10, 64)
128+
if err != nil {
129+
fmt.Printf("error occured while parsing nanoseconds: %+v\n", err)
130+
continue
131+
}
132+
133+
record.TimeStamp = time.Unix(seconds, nanoseconds).Format(time.RFC3339)
134+
135+
if msg.UserProfile != nil {
136+
record.UserName = msg.UserProfile.Name
137+
record.RealName = msg.UserProfile.RealName
138+
}
139+
140+
if msg.Text != "" {
141+
record.Text = msg.Text
142+
}
143+
144+
if msg.Attachments != nil {
145+
for _, attachment := range *msg.Attachments {
146+
record.Attachments = append(record.Attachments, attachment.OriginalURL)
147+
}
148+
}
149+
150+
if msg.Files != nil {
151+
for _, file := range *msg.Files {
152+
record.Files = append(record.Files, file.DownloadLink)
153+
}
154+
}
155+
156+
csvRecords = append(csvRecords, record)
157+
}
158+
159+
csvFile, err := os.Create("../../slack_records.csv")
160+
if err != nil {
161+
log.Fatal(err)
162+
}
163+
defer csvFile.Close()
164+
165+
_ = gocsv.MarshalFile(csvRecords, csvFile)
166+
}

go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module github.com/michplunkett/golang-scripting
2+
3+
go 1.22.4
4+
5+
require github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1 h1:FWNFq4fM1wPfcK40yHE5UO3RUdSNPaBC+j3PokzA6OQ=
2+
github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI=

0 commit comments

Comments
 (0)