package main import ( "database/sql" "encoding/json" "fmt" "io" "log" "net/url" "os" "path" "strings" _ "github.com/mattn/go-sqlite3" ) var Error *log.Logger func init() { log.SetFlags(log.Lmicroseconds | log.Lshortfile) logFile, err := os.Create("main.log") if err != nil { log.Printf("Error creating log file: %v", err) os.Exit(1) } logger := io.MultiWriter(os.Stdout, logFile) log.SetOutput(logger) Error = log.New(io.MultiWriter(logFile, os.Stderr, os.Stdout), fmt.Sprintf("%sERROR:%s ", "\033[0;101m", "\033[0m"), log.Lmicroseconds|log.Lshortfile) } const projectsFile = `C:\Users\Administrator\Seafile\VSCode\Code\User\globalStorage\state.vscdb` var scanFolders []string = []string{ `C:\Users\Administrator\Seafile\Projects-Clion\ClionProjects`, `C:\Users\Administrator\Seafile\Projects-Elixir\ElixirProjects`, `C:\Users\Administrator\Seafile\Projects-Go\GoProjects`, `C:\Users\Administrator\Seafile\Projects-Idea\IdeaProjects`, `C:\Users\Administrator\Seafile\Projects-Other\Projects`, `C:\Users\Administrator\Seafile\Projects-Pycharm\PycharmProjects`, `C:\Users\Administrator\Seafile\Projects-Rider\RiderProjects`, `C:\Users\Administrator\Seafile\Projects-Webstorm\WebstormProjects`, } func main() { for idx, folder := range scanFolders { scanFolders[idx] = path.Clean(folder) } config, err := ReadDBConfig() if err != nil { Error.Fatalf("Error reading database config: %v", err) return } log.Printf("Loaded %d entries", len(config.Entries)) cleanConfig := CleanConfig(config) log.Printf("%d after cleaning config", len(cleanConfig)) cleaned := 0 for ipath := range cleanConfig { file, err := os.Open(ipath) if err != nil { if os.IsNotExist(err) { log.Printf("Discarding non existing directory %s", ipath) delete(cleanConfig, ipath) cleaned++ } else { // Maybe we fail to open it for some other reason... // Could be it still does exist Error.Printf("Error opening file %s: %v", ipath, err) continue } continue } file.Close() // escaped := url.QueryEscape(relevantPath) // escaped = strings.ReplaceAll(escaped, "%2F", "/") // escaped = strings.ReplaceAll(escaped, "+", "%20") // escaped = "file:///" + escaped // log.Printf("%#v", escaped) } log.Printf("Cleaned %d invalid entries, %d valid entries remain", cleaned, len(cleanConfig)) added := 0 for _, folder := range scanFolders { files, err := os.ReadDir(folder) if err != nil { log.Printf("Error reading folder %s: %v", folder, err) continue } for _, fileEntry := range files { if !fileEntry.IsDir() { continue } newEntry := Entry{ FolderURI: path.Clean(path.Join(folder, fileEntry.Name())), } _, exists := cleanConfig[newEntry.FolderURI] if exists { log.Printf("Folder %s already exists in config", newEntry.FolderURI) continue } cleanConfig[newEntry.FolderURI] = &newEntry added++ } } log.Printf("Added %d new entries from scan folders, now %d total", added, len(cleanConfig)) } func ReadDBConfig() (Config, error) { var res = Config{} conn, err := sql.Open("sqlite3", projectsFile) if err != nil { return res, err } row := conn.QueryRow(`SELECT * FROM ItemTable WHERE key = 'history.recentlyOpenedPathsList'`) var key string var value string err = row.Scan(&key, &value) if err != nil { return res, err } conn.Close() err = json.NewDecoder(strings.NewReader(value)).Decode(&res) if err != nil { return res, fmt.Errorf("error decoding JSON: %v", err) } return res, nil } func CleanConfig(config Config) map[string]*Entry { var res = make(map[string]*Entry) for _, entry := range config.Entries { relevantPath := entry.FileURI if relevantPath == "" { relevantPath = entry.FolderURI } relevantPath = strings.TrimPrefix(relevantPath, "file://") relevantPath = strings.TrimPrefix(relevantPath, "/") decoded, err := url.QueryUnescape(relevantPath) if err != nil { Error.Printf("Error decoding URI %s: %v", relevantPath, err) continue } relevantPath = path.Clean(decoded) res[relevantPath] = &entry } return res } func WriteDBConfig(config Config) error { conn, err := sql.Open("sqlite3", projectsFile) if err != nil { return err } log.Printf("%#v", conn) return nil }