Skip to content

Instantly share code, notes, and snippets.

@coltoneshaw
Created March 25, 2024 02:28
Show Gist options
  • Save coltoneshaw/082885b086f11645d932a588bd00f472 to your computer and use it in GitHub Desktop.
Save coltoneshaw/082885b086f11645d932a588bd00f472 to your computer and use it in GitHub Desktop.
package main
import (
"encoding/json"
"fmt"
"os"
"strings"
"time"
)
// from the org_users.json file
type OrgUser struct {
ID string `json:"id"`
Name string `json:"name"`
Deleted bool `json:"deleted"`
Profile struct {
Title string `json:"title"`
Email string `json:"email"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
RealName string `json:"real_name_normalized"`
} `json:"profile"`
}
// these come from the users table
type User struct {
ID string `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
FirstName string `json:"firstname"` // Assuming these fields are already present in the users struct
LastName string `json:"lastname"`
Title string `json:"title"`
}
func main() {
// read the org_users.json file
orgUsersData, err := os.ReadFile("org_users.json")
if err != nil {
fmt.Println("Failed to read org users file")
return
}
var orgUsers []OrgUser
if err := json.Unmarshal(orgUsersData, &orgUsers); err != nil {
fmt.Println("Error parsing org_users.json:", err)
return
}
// read the userDump.json file
usersData, err := os.ReadFile("usersDump.json")
if err != nil {
fmt.Println("Failed to read usersDump.json file")
return
}
var users []User
if err := json.Unmarshal(usersData, &users); err != nil {
fmt.Println("Error parsing usersDump.json file:", err)
return
}
var updatedUsers []User
var sqlStatements []string
// loop over every entry in the users array
for _, user := range users {
og := findOrgUser(user, orgUsers)
if og == nil {
fmt.Printf("no org user found for username: %s - email: %s \n", user.Username, user.Email)
continue
}
newUser := User{
ID: user.ID,
Email: og.Profile.Email,
FirstName: og.Profile.FirstName,
LastName: og.Profile.LastName,
Title: og.Profile.Title,
Username: strings.Split(og.Profile.Email, "@")[0],
}
// backup to the realname in the full first name
// this seems to be mostly for bots
if newUser.FirstName == "" && newUser.LastName == "" {
newUser.FirstName = og.Profile.RealName
}
// backup to the username back to the slack username
if newUser.Username == "" {
newUser.Username = og.Name
}
// fallback to setting the email if not exist
if newUser.Email == "" {
newUser.Email = newUser.Username + "@local"
}
updatedUsers = append(updatedUsers, newUser)
}
sqlStatements = append(sqlStatements, "BEGIN;")
// Output or save the SQL statements
for _, user := range updatedUsers {
sql := createUpdateStatement(user)
sqlStatements = append(sqlStatements, sql)
}
sqlStatements = append(sqlStatements, "COMMIT;")
// compare if the email or username already exist in the array
// find the matching one in the orgUsers array
// store these to an array of users
// ends loop
// loop over the array of users and create the sql statements
// write the statements to a file
writeToFile(sqlStatements)
return
}
func findOrgUser(user User, orgUsers []OrgUser) *OrgUser {
for _, ou := range orgUsers {
if strings.ToLower(ou.ID) == strings.ToLower(user.Username) {
return &ou
}
// ou.Name is the username on slack export
if strings.ToLower(ou.Name) == strings.ToLower(user.Username) {
return &ou
}
if strings.ToLower(ou.Profile.Email) == strings.ToLower(user.Email) {
return &ou
}
// sometimes the first `@` might be the user's username
if strings.ToLower(ou.Name) == strings.Split(strings.ToLower(user.Email), "@")[0] {
return &ou
}
// another way to potentially find a user if both initial sides of the username are the same.
if strings.Split(strings.ToLower(ou.Profile.Email), "@")[0] == strings.Split(strings.ToLower(user.Email), "@")[0] {
return &ou
}
}
return nil
}
func createUpdateStatement(user User) string {
return fmt.Sprintf(
"UPDATE users SET firstname = '%s', lastname = '%s', email = '%s', username = '%s', deleteat = %d, authdata = '' WHERE id = '%s';",
user.FirstName,
user.LastName,
user.Email,
user.Username,
time.Now().UnixMilli(),
user.ID)
}
func writeToFile(sqlStatements []string) {
outputFileName := "output.sql"
// Create and open the file for writing, truncate if exists
file, err := os.Create(outputFileName)
if err != nil {
fmt.Printf("Failed to create file: %v", err)
return
}
defer func(file *os.File) {
err := file.Close()
if err != nil {
fmt.Println(err)
}
}(file) // Ensure the file is closed when the function returns
// Iterate through sqlStatements and write each to the file, new line per statement
for _, stmt := range sqlStatements {
if _, err := file.WriteString(stmt + "\n"); err != nil {
fmt.Printf("Failed to write to file: %v", err)
return
}
}
fmt.Printf("SQL statements have been written to %s\n", outputFileName)
return
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment