Merge pull request #1 from BuyMyMojo/GO-version
Move Go version to main branch
This commit is contained in:
commit
5bb1b449e7
9 changed files with 392 additions and 7 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -117,4 +117,5 @@ toxic/
|
||||||
fuck/
|
fuck/
|
||||||
coffin/
|
coffin/
|
||||||
1800/
|
1800/
|
||||||
*.csv
|
*.csv
|
||||||
|
User ID Parser/.vscode/launch.json
|
||||||
|
|
BIN
Locate ID/LocateID
Executable file
BIN
Locate ID/LocateID
Executable file
Binary file not shown.
141
Locate ID/LocateID.go
Normal file
141
Locate ID/LocateID.go
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/csv"
|
||||||
|
"flag"
|
||||||
|
"io/fs"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
CsvInput string
|
||||||
|
UID string
|
||||||
|
CsvOutput string
|
||||||
|
)
|
||||||
|
|
||||||
|
// struct for getting just user ID out of csv file
|
||||||
|
type DiscordCSV struct {
|
||||||
|
UserID string
|
||||||
|
Author string
|
||||||
|
Date string
|
||||||
|
Content string
|
||||||
|
Attachments string
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
|
||||||
|
flag.StringVar(&UID, "id", "", "User ID to locate")
|
||||||
|
flag.StringVar(&CsvInput, "i", "", "The csv or folder to search")
|
||||||
|
flag.StringVar(&CsvOutput, "o", "", "Output CSV to save mesages from user")
|
||||||
|
flag.Parse()
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Opens input and gets info
|
||||||
|
fileInfo, err := os.Stat(CsvInput)
|
||||||
|
if err != nil {
|
||||||
|
// error handling
|
||||||
|
println(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if CsvOutput != "" {
|
||||||
|
OutFile, err := os.OpenFile(CsvOutput, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
OutFile.WriteString("UID, Author, Date, Content, Attachments, Found in\n")
|
||||||
|
OutFile.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// checks if input is directory or file
|
||||||
|
if fileInfo.IsDir() {
|
||||||
|
// file is a directory
|
||||||
|
files, err := ioutil.ReadDir(CsvInput) // CsvInput
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// For each file in folder
|
||||||
|
for _, file := range files {
|
||||||
|
if !file.IsDir() {
|
||||||
|
file_path := CsvInput + file.Name()
|
||||||
|
process(file_path, file)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// file is not a directory
|
||||||
|
files, err := os.Stat(CsvInput) // CsvInput
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
process(CsvInput, files)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func process(inFile string, fileInfo fs.FileInfo) {
|
||||||
|
var messages []string
|
||||||
|
|
||||||
|
// Read CSV file
|
||||||
|
lines, err := ReadCsv(inFile)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, line := range lines {
|
||||||
|
data := DiscordCSV{
|
||||||
|
UserID: line[0],
|
||||||
|
Author: line[1],
|
||||||
|
Date: line[2],
|
||||||
|
Content: line[3],
|
||||||
|
Attachments: line[4],
|
||||||
|
}
|
||||||
|
if UID == data.UserID {
|
||||||
|
messages = append(messages, data.UserID+","+data.Author+","+data.Date+","+data.Content+","+data.Attachments+","+fileInfo.Name())
|
||||||
|
println(data.UserID + "," + data.Author + "," + data.Date + "," + data.Content + "," + data.Attachments + "," + fileInfo.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if CsvOutput != "" {
|
||||||
|
OutFile, err := os.OpenFile(CsvOutput, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
for _, message := range messages {
|
||||||
|
OutFile.WriteString(message + "\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadCsv(filename string) ([][]string, error) {
|
||||||
|
|
||||||
|
// Open CSV file
|
||||||
|
f, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
return [][]string{}, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
// Read File into a Variable
|
||||||
|
lines, err := csv.NewReader(f).ReadAll()
|
||||||
|
if err != nil {
|
||||||
|
return [][]string{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func contains(s []string, str string) bool {
|
||||||
|
for _, v := range s {
|
||||||
|
if v == str {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
25
Locate ID/build.sh
Executable file
25
Locate ID/build.sh
Executable file
|
@ -0,0 +1,25 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
package="./LocateID.go"
|
||||||
|
|
||||||
|
package_split=(${package//\// })
|
||||||
|
package_name="LocateID"
|
||||||
|
|
||||||
|
platforms=("windows/amd64" "windows/386" "linux/amd64" "linux/386" "linux/arm64" "linux/arm")
|
||||||
|
|
||||||
|
for platform in "${platforms[@]}"
|
||||||
|
do
|
||||||
|
platform_split=(${platform//\// })
|
||||||
|
GOOS=${platform_split[0]}
|
||||||
|
GOARCH=${platform_split[1]}
|
||||||
|
output_name=$package_name'-'$GOOS'-'$GOARCH
|
||||||
|
if [ $GOOS = "windows" ]; then
|
||||||
|
output_name+='.exe'
|
||||||
|
fi
|
||||||
|
|
||||||
|
env GOOS=$GOOS GOARCH=$GOARCH go build -o ./build/$output_name $package
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo 'An error has occurred! Aborting the script execution...'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
3
Locate ID/go.mod
Normal file
3
Locate ID/go.mod
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
module main
|
||||||
|
|
||||||
|
go 1.17
|
30
README.md
30
README.md
|
@ -1,11 +1,29 @@
|
||||||
# Discord Chat Exporter csv parser
|
# Discord Chat Exporter csv parsers
|
||||||
[](https://wakatime.com/badge/github/BuyMyMojo/discord-chat-parser)
|
|
||||||
|
|
||||||
|
<sub> Now with a much faster version written in go! </sub>
|
||||||
|
|
||||||
this tool will take a csv (or a folder of them) from Discord Chat Exporter and create a new list of unique IDs.
|
## How to use the go version
|
||||||
Made to get all active users from a discord server.
|
|
||||||
|
|
||||||
|
To run the go versions all you need to do is download the executable for your platform and run it from the terminal/powershell:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./IdParser[.exe] -i [Path to folder/file] -o [Path to output .csv (Defaults to ./out.csv)]
|
||||||
|
```
|
||||||
|
|
||||||
> py ./main.py [csv file or dir] [output csv]
|
|
||||||
|
|
||||||
Use the same output between multiple runs works and takes into account old data to ensure no dupes
|
Use the same output between multiple runs works and takes into account old data to ensure no dupes
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./LocateID[.exe] -i [Path to folder/fil] -id "[User ID in quotes]" -o [Path to output csv (Optional)]
|
||||||
|
```
|
||||||
|
|
||||||
|
## How to use the Python version
|
||||||
|
|
||||||
|
```bash
|
||||||
|
py ./main.py [csv file or dir] [output csv]
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the same output between multiple runs works and takes into account old data to ensure no dupes
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
py ./locate_id.py [User ID] [csv file or dir]
|
||||||
|
```
|
||||||
|
|
169
User ID Parser/IdParser.go
Normal file
169
User ID Parser/IdParser.go
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/csv"
|
||||||
|
"errors"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Variables used for command line parameters
|
||||||
|
var (
|
||||||
|
CsvInput string
|
||||||
|
CsvOutput string
|
||||||
|
unique_old []string
|
||||||
|
unique_ids []string
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
|
||||||
|
flag.StringVar(&CsvInput, "i", "", "Input csv or folder [required]")
|
||||||
|
flag.StringVar(&CsvOutput, "o", "out.csv", "Output CSV")
|
||||||
|
flag.Parse()
|
||||||
|
}
|
||||||
|
|
||||||
|
// struct for getting just user ID out of csv file
|
||||||
|
type DiscordCSV struct {
|
||||||
|
UserID string
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
// Check if there is no input and exits if true
|
||||||
|
if CsvInput == "" {
|
||||||
|
println("No input given, use -h for help on how to use this program")
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Opens input and gets info
|
||||||
|
fileInfo, err := os.Stat(CsvInput)
|
||||||
|
if err != nil {
|
||||||
|
// error handling
|
||||||
|
println(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// checks if input is directory or file
|
||||||
|
if fileInfo.IsDir() {
|
||||||
|
// file is a directory
|
||||||
|
files, err := ioutil.ReadDir(CsvInput)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// For each file in folder
|
||||||
|
for _, file := range files {
|
||||||
|
if !file.IsDir() {
|
||||||
|
process(CsvInput + file.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// file is not a directory
|
||||||
|
process(CsvInput)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func process(CsvPath string) {
|
||||||
|
|
||||||
|
if _, err := os.Stat(CsvOutput); err == nil {
|
||||||
|
// path/to/whatever exists
|
||||||
|
|
||||||
|
// Read CSV file
|
||||||
|
lines, err := ReadCsv(CsvOutput)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
// Loop through lines & turn into object
|
||||||
|
for _, line := range lines {
|
||||||
|
data := DiscordCSV{
|
||||||
|
UserID: line[0],
|
||||||
|
}
|
||||||
|
unique_old = append(unique_old, data.UserID)
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteCSV(CsvPath)
|
||||||
|
|
||||||
|
} else if errors.Is(err, os.ErrNotExist) {
|
||||||
|
// path/to/whatever does *not* exist
|
||||||
|
OutFile, err := os.Create(CsvOutput)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
OutFile.Close()
|
||||||
|
|
||||||
|
WriteCSV(CsvPath)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Schrodinger: file may or may not exist. See err for details.
|
||||||
|
|
||||||
|
// Therefore, do *NOT* use !os.IsNotExist(err) to test for file existence
|
||||||
|
println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteCSV(InFile string) {
|
||||||
|
// Create DiscordIDs list
|
||||||
|
var DiscordIDs []string
|
||||||
|
|
||||||
|
// Read CSV file
|
||||||
|
lines, err := ReadCsv(InFile)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
OutFile, err := os.OpenFile(CsvOutput, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
|
||||||
|
|
||||||
|
// Loop through lines & add to DiscordIDs list
|
||||||
|
for _, line := range lines {
|
||||||
|
data := DiscordCSV{
|
||||||
|
UserID: line[0],
|
||||||
|
}
|
||||||
|
if !contains(DiscordIDs, data.UserID) {
|
||||||
|
DiscordIDs = append(DiscordIDs, data.UserID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if ID is already in list
|
||||||
|
// if it isnt then it gets writen to list
|
||||||
|
for _, ID := range DiscordIDs {
|
||||||
|
if !contains(unique_old, ID) {
|
||||||
|
OutFile.WriteString(ID + "\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadCsv(filename string) ([][]string, error) {
|
||||||
|
|
||||||
|
// Open CSV file
|
||||||
|
f, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
return [][]string{}, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
// Read File into a Variable
|
||||||
|
lines, err := csv.NewReader(f).ReadAll()
|
||||||
|
if err != nil {
|
||||||
|
return [][]string{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func contains(s []string, str string) bool {
|
||||||
|
for _, v := range s {
|
||||||
|
if v == str {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
25
User ID Parser/build.sh
Executable file
25
User ID Parser/build.sh
Executable file
|
@ -0,0 +1,25 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
package="./IdParser.go"
|
||||||
|
|
||||||
|
package_split=(${package//\// })
|
||||||
|
package_name="IdParser"
|
||||||
|
|
||||||
|
platforms=("windows/amd64" "windows/386" "linux/amd64" "linux/386" "linux/arm64" "linux/arm")
|
||||||
|
|
||||||
|
for platform in "${platforms[@]}"
|
||||||
|
do
|
||||||
|
platform_split=(${platform//\// })
|
||||||
|
GOOS=${platform_split[0]}
|
||||||
|
GOARCH=${platform_split[1]}
|
||||||
|
output_name=$package_name'-'$GOOS'-'$GOARCH
|
||||||
|
if [ $GOOS = "windows" ]; then
|
||||||
|
output_name+='.exe'
|
||||||
|
fi
|
||||||
|
|
||||||
|
env GOOS=$GOOS GOARCH=$GOARCH go build -o ./build/$output_name $package
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo 'An error has occurred! Aborting the script execution...'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
3
User ID Parser/go.mod
Normal file
3
User ID Parser/go.mod
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
module main
|
||||||
|
|
||||||
|
go 1.17
|
Reference in a new issue