package hp import ( "context" "database/sql" "io/ioutil" "os" "path/filepath" "time" "git.eeqj.de/sneak/goutil" // db driver: _ "github.com/mattn/go-sqlite3" "github.com/rs/zerolog/log" ) func (hp *HistoryPoster) postURLs(ctx context.Context, cancel context.CancelFunc) { log.Info().Msg("finding history files") files, err := findHistoryFiles() if err != nil { hp.shutdown(err.Error(), -1) } for _, v := range files { hl, err := dumpHistoryFromChromeHistoryFile(v) if err != nil { log.Error(). Err(err). Msg("unable to read history from file") hp.shutdown(err.Error(), -1) } for _, hitem := range hl { hp.processURLFromHistory(hitem) } } } func (hp *HistoryPoster) processURLFromHistory(hi historyItem) { log.Debug(). Str("url", hi.URL). Msg("got url to process") if hp.store.URLAlreadySeen(hi.URL) { return } log.Debug(). Str("url", hi.URL). Msg("url is new, must be posted") err := hp.postURL(hi) if err != nil { log.Error(). Err(err). Msg("url could not be posted :(") } else { hp.store.MarkURLSeen(hi.URL) } } func (hp *HistoryPoster) postURL(hi historyItem) error { // FIXME // panic("unimplemented") return nil } func findHistoryFiles() ([]string, error) { // FIXME make this support safari one day home := os.Getenv("HOME") chromeDir := home + "/Library/Application Support/Google/Chrome" defaultProfileDir := chromeDir + "/Default" output := make([]string, 0) output = append(output, defaultProfileDir+"/History") otherProfiles, err := filepath.Glob(chromeDir + "/Profile *") if err != nil { return nil, err } for _, v := range otherProfiles { output = append(output, v+"/History") } // FIXME check to see if these files actually exist or not return output, nil } type historyItem struct { lastVisitTime time.Time URL string title string visitCount int } func dumpHistoryFromChromeHistoryFile(path string) ([]historyItem, error) { tempdir, err := ioutil.TempDir(os.Getenv("TMPDIR"), "historyposter") if err != nil { return nil, err } log.Debug(). Str("tempdir", tempdir). Msg("created tempdir") dbfn := tempdir + "/History" err = goutil.CopyFile(path, dbfn) if err != nil { log.Error(). Str("source", path). Str("target", dbfn). Err(err). Msg("unable to copy history file") return nil, err } log.Debug(). Str("dbfn", dbfn). Msg("copied history file") defer func() { os.RemoveAll(tempdir) log.Debug(). Str("tempdir", tempdir). Msg("removed tempdir") }() db, err := sql.Open("sqlite3", dbfn) if err != nil { return nil, err } log.Debug(). Str("dbfn", dbfn). Msg("history file opened") defer func() { db.Close() log.Debug(). Str("filename", dbfn). Msg("closed history file") }() query := ` SELECT last_visit_time, url, title, visit_count FROM urls ORDER BY last_visit_time DESC ` rows, err := db.Query(query) if err != nil { return nil, err } if rows.Err() != nil { return nil, rows.Err() } defer rows.Close() output := make([]historyItem, 0) for rows.Next() { // log.Debug().Msg("processing row") var lastVisitTime int64 var url string var title string var visitCount int err := rows.Scan(&lastVisitTime, &url, &title, &visitCount) if err != nil { log.Debug().Err(err).Msg("row error") return nil, err } t := goutil.TimeFromWebKit(lastVisitTime).UTC() hi := historyItem{ lastVisitTime: t, URL: url, title: title, visitCount: visitCount, } output = append(output, hi) } // pp.Print(output) return output, nil }