Add load and mark as un/read functionality.
This commit is contained in:
parent
9a42a60278
commit
b2910c8ec0
@ -13,6 +13,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
dryrun = flag.Bool("dryrun", true, "don't actually rename files, just log actions.")
|
||||||
saveFile = flag.String("save", "", "filename to store unread status.")
|
saveFile = flag.String("save", "", "filename to store unread status.")
|
||||||
loadFile = flag.String("load", "", "filename to load unread status.")
|
loadFile = flag.String("load", "", "filename to load unread status.")
|
||||||
maildir = flag.String("maildir", "", "Maildir root")
|
maildir = flag.String("maildir", "", "Maildir root")
|
||||||
@ -21,12 +22,19 @@ var (
|
|||||||
type Status struct {
|
type Status struct {
|
||||||
Hash string `json:"hash"`
|
Hash string `json:"hash"`
|
||||||
Path string `json:"path,omitempthashy"`
|
Path string `json:"path,omitempthashy"`
|
||||||
Unread bool `json:"unread,omitempty"`
|
Read bool `json:"read,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Messages []Status
|
type Messages []Status
|
||||||
|
|
||||||
|
var headers = []string{"to", "from", "cc", "date", "subject"}
|
||||||
|
|
||||||
func (m *Messages) hashMail(path string, info os.FileInfo, err error) error {
|
func (m *Messages) hashMail(path string, info os.FileInfo, err error) error {
|
||||||
|
glog.Infoln("Processing", path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if info.IsDir() {
|
if info.IsDir() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -34,23 +42,32 @@ func (m *Messages) hashMail(path string, info os.FileInfo, err error) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Fatal(err)
|
glog.Fatal(err)
|
||||||
}
|
}
|
||||||
headers := []string{"to", "from", "cc", "date", "subject"}
|
|
||||||
h, err := email.Hash(r, headers)
|
h, err := email.Hash(r, headers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorln(path, err)
|
glog.Errorf("%s %q", path, err.Error())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
md := email.NewInfo(path)
|
md := email.NewInfo(path)
|
||||||
//fmt.Printf("%x %s\n", h.Sum(nil), path)
|
|
||||||
*m = append(*m, Status{
|
*m = append(*m, Status{
|
||||||
Path: path,
|
Path: path,
|
||||||
Hash: fmt.Sprintf("%x", h.Sum(nil)),
|
Hash: fmt.Sprintf("%x", h.Sum(nil)),
|
||||||
Unread: !md.Seen,
|
Read: md.Seen,
|
||||||
})
|
})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Messages) SaveStatus(maildir, saveFile string) error {
|
func (m *Messages) LoadStatus(statusFile string) error {
|
||||||
|
glog.Infof("Loading file %q", statusFile)
|
||||||
|
r, err := os.Open(statusFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer r.Close()
|
||||||
|
dec := json.NewDecoder(r)
|
||||||
|
return dec.Decode(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Messages) SaveStatus(maildir, statusFile string) error {
|
||||||
if err := filepath.Walk(maildir, m.hashMail); err != nil {
|
if err := filepath.Walk(maildir, m.hashMail); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -60,7 +77,8 @@ func (m *Messages) SaveStatus(maildir, saveFile string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := os.Create(saveFile)
|
glog.Infof("Saving file %q", statusFile)
|
||||||
|
f, err := os.Create(statusFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -77,18 +95,91 @@ func (m *Messages) SaveStatus(maildir, saveFile string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m Messages) Reconcile(maildir string) error {
|
||||||
|
hashMap := make(map[string]*Status, len(m))
|
||||||
|
for i, msg := range m {
|
||||||
|
hashMap[msg.Hash] = &m[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
return filepath.Walk(maildir, func(path string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if info.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
glog.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
h, err := email.Hash(r, headers)
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf("%s %q", path, err.Error())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
chksum := fmt.Sprintf("%x", h.Sum(nil))
|
||||||
|
md := email.NewInfo(path)
|
||||||
|
s := hashMap[chksum]
|
||||||
|
glog.V(2).Infof("Comparing flags of %q to %q", path, s.Path)
|
||||||
|
if md.Seen != s.Read {
|
||||||
|
md.Seen = s.Read
|
||||||
|
newPath := md.String()
|
||||||
|
glog.Infof("%s => %s", path, newPath)
|
||||||
|
if !*dryrun {
|
||||||
|
os.Rename(path, newPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m Messages) PrintStats() {
|
||||||
|
r, u, t := 0, 0, 0
|
||||||
|
for _, msg := range m {
|
||||||
|
t++
|
||||||
|
if msg.Read {
|
||||||
|
r++
|
||||||
|
} else {
|
||||||
|
u++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println(r, "read")
|
||||||
|
fmt.Println(u, "unread")
|
||||||
|
fmt.Println(t, "total")
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
defer glog.Flush()
|
defer glog.Flush()
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
m := Messages{}
|
m := Messages{}
|
||||||
|
|
||||||
if *maildir == "" {
|
if *maildir == "" {
|
||||||
glog.Fatal("Must specify Maildir with -maildir")
|
fmt.Println("Must specify Maildir with -maildir")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if *saveFile == "" && *loadFile == "" {
|
||||||
|
fmt.Println("Must specify one of -save or -load")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if *saveFile != "" {
|
if *saveFile != "" {
|
||||||
if err := m.SaveStatus(*maildir, *saveFile); err != nil {
|
if err := m.SaveStatus(*maildir, *saveFile); err != nil {
|
||||||
glog.Fatal(err)
|
glog.Fatal(err)
|
||||||
}
|
}
|
||||||
|
m.PrintStats()
|
||||||
|
}
|
||||||
|
|
||||||
|
if *loadFile != "" {
|
||||||
|
if err := m.LoadStatus(*loadFile); err != nil {
|
||||||
|
glog.Fatal(err)
|
||||||
|
}
|
||||||
|
m.PrintStats()
|
||||||
|
if err := m.Reconcile(*maildir); err != nil {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user