func (n *NickSearch) Month(m string) (string, error) {
	if _, ok := n.months[m]; !ok {
		return "", errors.New("month not found")
	}
	f, err := os.Open(filepath.Join(n.path, m))
	if err != nil {
		return "", err
	}
	nickfiles, err := f.Readdirnames(0)
	if err != nil {
		return "", err
	}
	for _, file := range nickfiles {
		if !strings.Contains(file, ".nicks") {
			continue
		}
		nicks := NickCaseMap{}
		err := ReadNickList(nicks, filepath.Join(n.path, m, file))
		if err != nil {
			return "", err
		}
		if nick, ok := nicks[n.nick]; ok {
			return nick, nil
		}
	}
	return "", errors.New("user not found in " + m)
}
Month searches for a nick in m
package common
import (
	"bytes"
	"errors"
	"io"
	"os"
	"path/filepath"
	"strings"
	"time"
)
var empty struct{}
type NickStore interface {
	Add(string)
	Remove(string)
}
func ReadNickList(n NickStore, path string) error {
	buf, err := ReadCompressedFile(path)
	if err != nil {
		return err
	}
	offset := 0
	for i, v := range buf {
		if v == 0 {
			n.Add(string(buf[offset:i]))
			offset = i + 1
		}
	}
	return nil
}
type NickList map[string]struct{}
func (n NickList) Add(nick string) {
	n[nick] = empty
}
func (n NickList) Remove(nick string) {
	delete(n, nick)
}
func (n NickList) WriteTo(path string) error {
	buf := bytes.NewBuffer([]byte{})
	for nick := range n {
		buf.WriteString(nick)
		buf.WriteByte(0)
	}
	f, err := WriteCompressedFile(path+".writing", buf.Bytes())
	if err != nil {
		return err
	}
	return os.Rename(f.Name(), strings.Replace(f.Name(), ".writing", "", -1))
}
type NickListLower map[string]struct{}
func (n NickListLower) Add(nick string) {
	n[strings.ToLower(nick)] = empty
}
func (n NickListLower) Remove(nick string) {
	delete(n, strings.ToLower(nick))
}
type NickCaseMap map[string]string
func (n NickCaseMap) Add(nick string) {
	n[strings.ToLower(nick)] = nick
}
func (n NickCaseMap) Remove(nick string) {
	delete(n, strings.ToLower(nick))
}
type NickSearch struct {
	nick   string
	path   string
	months map[string]struct{}
	date   time.Time
}
func NewNickSearch(path string, nick string) (*NickSearch, error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	names, err := f.Readdirnames(0)
	if err != nil {
		return nil, err
	}
	months := make(map[string]struct{}, len(names))
	for _, name := range names {
		months[name] = struct{}{}
	}
	return &NickSearch{
		nick:   strings.ToLower(nick),
		path:   path,
		months: months,
		date:   time.Now().UTC().Add(24 * time.Hour),
	}, nil
}
func (n *NickSearch) Next() (*NickSearchResult, error) {
	for {
		n.date = n.date.Add(-24 * time.Hour)
		if _, ok := n.months[n.date.Format("January 2006")]; !ok {
			return nil, io.EOF
		}
		nicks := NickCaseMap{}
		ReadNickList(nicks, n.path+n.date.Format("/January 2006/2006-01-02")+".nicks")
		if nick, ok := nicks[n.nick]; ok {
			return &NickSearchResult{nick, n.date}, nil
		}
	}
}