about summary refs log tree commit diff stats
path: root/registry
diff options
context:
space:
mode:
authorBen Morrison <ben@gbmor.dev>2019-05-14 02:55:40 -0400
committerBen Morrison <ben@gbmor.dev>2019-05-14 02:55:40 -0400
commita8ba50b53f45e06af03f5ef98e759539394a3c0c (patch)
treea5bfb512d6fcd208e2d050d9f06406e48d9c9185 /registry
parent7728f92e4f4b00d617ece97d9c6a88125821d874 (diff)
downloadgetwtxt-a8ba50b53f45e06af03f5ef98e759539394a3c0c.tar.gz
package cache renamed to package registry
Diffstat (limited to 'registry')
-rw-r--r--registry/index.go117
-rw-r--r--registry/types.go56
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]
+}