diff --git a/imap.go b/imap.go index 8fb957a..72bdbc7 100644 --- a/imap.go +++ b/imap.go @@ -2,6 +2,7 @@ package main import ( "bytes" + "container/list" "fmt" "html/template" "io" @@ -10,6 +11,7 @@ import ( "sort" "strconv" "strings" + "sync" /* _ "golang.org/x/net/html" @@ -32,6 +34,30 @@ type MailBox struct { Client *imapclient.Client } +type Index struct { + index map[string][]string + mu sync.RWMutex +} + +func NewIndex() *Index { + return &Index{ + index: make(map[string][]string), + } +} +func (idx *Index) Add(word, id string) { + idx.mu.Lock() + defer idx.mu.Unlock() + ids, ok := idx.index[word] + if !ok { + idx.index[word] = []string{id} + return + } + for _, existingID := range ids { + if existingID == id { + return + } + } +} func (mb *MailBox) Configure(conf *MailBoxConfiguration) error { mb.Server = conf.Server @@ -88,20 +114,68 @@ func (mb *MailBox) ListFolders() ([]string, error) { } return folders, nil } -func (mb *MailBox) GetMessages() ([]Post, error) { +func (mb *MailBox) Search(req string, posts []Post) ([]Post, error) { + index := NewIndex() + for _, post := range posts { + text := string(post.HTML) + post.Text + words := strings.Split(text, " ") + for _, word := range words { + word = strings.ToLower(strings.Trim(word, " .,:;(){}[]?!\"'`")) + if len(word) > 2 { + index.Add(word, post.Id) + } + + } + + } + stems := strings.Split(req, " ") + var results []Post + + added := make(map[string]bool) + for _, stem := range stems { + stem = strings.ToLower(strings.Trim(stem, " .,:;(){}[]?!\"'`")) + if len(stem) > 2 { + ids, ok := index.index[stem] + if ok { + for _, id := range ids { + if added[id] { + continue + } + for _, post := range posts { + if post.Id == id { + results = append(results, post) + added[id] = true + break + } + } + } + } + + } + } + + return results, nil +} +func (mb *MailBox) GetMessages() ([]Post, error) { inbox, err := mb.Client.Select(mb.InBox, nil).Wait() if err != nil { log.Fatal("Error selecting mailbox:", mb.InBox, err) } log.Println("Inbox has", inbox.NumMessages, "messages") + inbox, err = mb.Client.Select(mb.InBox, nil).Wait() + if err != nil { + log.Fatal("Error selecting mailbox:", mb.InBox, err) + } + log.Println("Inbox has", inbox.NumMessages, "messages") + if inbox.NumMessages <= 0 { return nil, fmt.Errorf("nomessages") } posts := make([]Post, 0) for i := uint32(1); i <= inbox.NumMessages; i++ { - var post Post + seqSet := imap.SeqSetNum(i) bodySection := &imap.FetchItemBodySection{} fetchOptions := &imap.FetchOptions{ @@ -112,6 +186,7 @@ func (mb *MailBox) GetMessages() ([]Post, error) { if err != nil { log.Fatal("Error fetching mails:", err) } + var post Post post.Title = strings.Trim(messages[0].Envelope.Subject, "\t ") if !strings.HasPrefix(strings.ToLower(post.Title), "blog ") { continue @@ -131,6 +206,7 @@ func (mb *MailBox) GetMessages() ([]Post, error) { if err != nil { return nil, err } + for { part, err := mailReader.NextPart() if err == io.EOF { @@ -197,6 +273,7 @@ func (mb *MailBox) GetMessages() ([]Post, error) { } } posts = append(posts, post) + } sort.Slice(posts, func(i, j int) bool { return posts[i].DateTime.After(posts[j].DateTime) @@ -221,3 +298,7 @@ func findHTMLNode(node *html.Node) (*html.Node, error) { } return nil, fmt.Errorf("notfound") } + +type Queue struct { + list *list.List +}