Created
March 25, 2024 02:28
-
-
Save coltoneshaw/082885b086f11645d932a588bd00f472 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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