diff options
Diffstat (limited to 'registry')
-rw-r--r-- | registry/index.go | 117 | ||||
-rw-r--r-- | registry/types.go | 56 |
2 files changed, 173 insertions, 0 deletions
diff --git a/registry/index.go b/registry/index.go new file mode 100644 index 0000000..85277fc --- /dev/null +++ b/registry/index.go @@ -0,0 +1,117 @@ +package registry + +import ( + "log" + "sort" + "strings" + "time" +) + +// NewUserIndex returns a new instance of a user index +func NewUserIndex() *UserIndex { + return &UserIndex{} +} + +// AddUser inserts a new user into the index. The *Data struct +// contains the nickname and the time the user was added. +func (index UserIndex) AddUser(nick string, url string) { + rfc3339date, err := time.Now().MarshalText() + if err != nil { + log.Printf("Error formatting user add time as RFC3339: %v\n", err) + } + imutex.Lock() + index[url] = &Data{nick: nick, date: time.Now(), apidate: rfc3339date} + imutex.Unlock() +} + +// DelUser removes a user from the index completely. +func (index UserIndex) DelUser(url string) { + imutex.Lock() + delete(index, url) + imutex.Unlock() +} + +// QueryUser checks the user index for nicknames that contain the +// nickname provided as an argument. Entries are returned sorted +// by the date they were added to the index. +func (index UserIndex) QueryUser(name string) []string { + var timekey = map[time.Time]string{} + var sortedkeys TimeSlice + var users []string + imutex.RLock() + for k, v := range index { + if strings.Contains(v.nick, name) { + timekey[v.date] = v.nick + "\t" + k + "\t" + string(v.apidate) + sortedkeys = append(sortedkeys, v.date) + } + } + imutex.RUnlock() + sort.Sort(sortedkeys) + for _, e := range sortedkeys { + users = append(users, timekey[e]) + } + + return users +} + +// QueryTag returns all the known statuses that +// contain the provided tag. +func (index UserIndex) QueryTag(tag string) []string { + var statusmap StatusMapSlice + i := 0 + imutex.RLock() + for _, v := range index { + statusmap[i] = v.FindTag(tag) + i++ + } + imutex.RUnlock() + + return statusmap.SortByTime() +} + +// FindTag takes a user's tweets and looks for a given tag. +// Returns the tweets with the tag as a []string. +func (userdata *Data) FindTag(tag string) StatusMap { + var statuses StatusMap + for k, e := range userdata.status { + parts := strings.Split(e, "\t") + statusslice := strings.Split(parts[3], " ") + for _, v := range statusslice { + if v[1:] == tag { + statuses[k] = e + break + } + } + } + + return statuses +} + +// SortByTime returns a string slice of the statuses sorted by time +func (sm StatusMapSlice) SortByTime() []string { + var tagmap StatusMap + var times TimeSlice + var statuses []string + for _, e := range sm { + for k, v := range e { + tagmap[k] = v + } + } + for k := range tagmap { + times = append(times, k) + } + sort.Sort(times) + for _, e := range times { + statuses = append(statuses, tagmap[e]) + } + + return statuses +} + +// GetStatuses returns the string slice containing a user's statuses +func (index UserIndex) GetStatuses(url string) StatusMap { + imutex.RLock() + status := index[url].status + imutex.RUnlock() + return status +} diff --git a/registry/types.go b/registry/types.go new file mode 100644 index 0000000..d3e421a --- /dev/null +++ b/registry/types.go @@ -0,0 +1,56 @@ +package registry + +import ( + "sync" + "time" +) + +// Indexer allows for other uses of the Index functions +type Indexer interface { + AddUser(string, string) + DelUser(string) +} + +// UserIndex provides an index of users by URL +type UserIndex map[string]*Data + +// Data from user's twtxt.txt +type Data struct { + nick string + date time.Time + apidate []byte + status StatusMap +} + +// StatusMap holds the statuses posted by a given user. A standard +// time.Time value is used as the key, with the status as a string. +type StatusMap map[time.Time]string + +// StatusMapSlice is a slice of StatusMaps. Useful for sorting the +// output of queries. +type StatusMapSlice []StatusMap + +// Mutex to control access to the User Index. +var imutex = sync.RWMutex{} + +// TimeSlice is used for sorting by timestamp. +type TimeSlice []time.Time + +// Len returns the length of the slice to be sorted. +// This helps satisfy sort.Interface with respect to TimeSlice. +func (t TimeSlice) Len() int { + return len(t) +} + +// Less returns true if the timestamp at index i is before the +// timestamp at index j in TimeSlice. +// This helps satisfy sort.Interface with respect to TimeSlice. +func (t TimeSlice) Less(i, j int) bool { + return t[i].Before(t[j]) +} + +// Swap transposes the timestampss at the two given indices. +// This helps satisfy sort.Interface with respect to TimeSlice. +func (t TimeSlice) Swap(i, j int) { + t[i], t[j] = t[j], t[i] +} |