about summary refs log blame commit diff stats
path: root/registry/types.go
blob: eb8eee18e81751ae150970c1560cc25c5325b21d (plain) (tree)



















































































































































                                                                    
/*
Copyright (c) 2019 Ben Morrison (gbmor)

This file is part of Registry.

Registry is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Registry is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Registry.  If not, see <https://www.gnu.org/licenses/>.
*/

// Package registry implements functions and types that assist
// in the creation and management of a twtxt registry.
package registry // import "git.sr.ht/~gbmor/getwtxt/registry"

import (
	"net"
	"net/http"
	"sync"
	"time"
)

// Registrar implements the minimum amount of methods
// for a functioning Registry.
type Registrar interface {
	Put(user *User) error
	Get(urlKey string) (*User, error)
	DelUser(urlKey string) error
	UpdateUser(urlKey string) error
	GetUserStatuses(urlKey string) (TimeMap, error)
	GetStatuses() (TimeMap, error)
}

// User holds a given user's information
// and statuses.
type User struct {
	// Provided to aid in concurrency-safe
	// reads and writes. In most cases, the
	// mutex in the associated Index should be
	// used instead. This mutex is provided
	// should the library user need to access
	// a User independently of an Index.
	Mu sync.RWMutex

	// Nick is the user-specified nickname.
	Nick string

	// The URL of the user's twtxt file
	URL string

	// The reported last modification date
	// of the user's twtxt.txt file.
	LastModified string

	// The IP address of the user is optionally
	// recorded when submitted via POST.
	IP net.IP

	// The timestamp, in RFC3339 format,
	// reflecting when the user was added.
	Date string

	// A TimeMap of the user's statuses
	// from their twtxt file.
	Status TimeMap
}

// Registry enables the bulk of a registry's
// user data storage and access.
type Registry struct {
	// Provided to aid in concurrency-safe
	// reads and writes to a given registry
	// Users map.
	Mu sync.RWMutex

	// The registry's user data is contained
	// in this map. The functions within this
	// library expect the key to be the URL of
	// a given user's twtxt file.
	Users map[string]*User

	// The client to use for HTTP requests.
	// If nil is passed to NewIndex(), a
	// client with a 10 second timeout
	// and all other values as default is
	// used.
	HTTPClient *http.Client
}

// TimeMap holds extracted and processed user data as a
// string. A time.Time value is used as the key.
type TimeMap map[time.Time]string

// TimeSlice is a slice of time.Time used for sorting
// a TimeMap by timestamp.
type TimeSlice []time.Time

// NewUser returns a pointer to an initialized User
func NewUser() *User {
	return &User{
		Mu:     sync.RWMutex{},
		Status: NewTimeMap(),
	}
}

// New returns an initialized Registry instance.
func New(client *http.Client) *Registry {
	return &Registry{
		Mu:         sync.RWMutex{},
		Users:      make(map[string]*User),
		HTTPClient: client,
	}
}

// NewTimeMap returns an initialized TimeMap.
func NewTimeMap() TimeMap {
	return make(TimeMap)
}

// Len returns the length of the TimeSlice to be sorted.
// This helps satisfy sort.Interface.
func (t TimeSlice) Len() int {
	return len(t)
}

// Less returns true if the timestamp at index i is after
// the timestamp at index j in a given TimeSlice. This results
// in a descending (reversed) sort order for timestamps rather
// than ascending.
// This helps satisfy sort.Interface.
func (t TimeSlice) Less(i, j int) bool {
	return t[i].After(t[j])
}

// Swap transposes the timestamps at the two given indices
// for the TimeSlice receiver.
// This helps satisfy sort.Interface.
func (t TimeSlice) Swap(i, j int) {
	t[i], t[j] = t[j], t[i]
}