neofeels/ttbp/ttbp.go

204 lines
4.4 KiB
Go

package ttbp
import (
"bufio"
"encoding/json"
"os"
"path"
"sort"
"time"
"git.tilde.town/nbsp/neofeels/config"
)
var (
PathVar = "/var/global/ttbp"
PathVarWWW = path.Join(PathVar, "www")
PathLive = "https://tilde.town/~"
PathUserFile = path.Join(PathVar, "users.txt")
PathGraff = path.Join(PathVar, "graffiti")
PathWall = path.Join(PathGraff, "wall.txt")
PathWallLock = path.Join(PathGraff, ".lock")
)
type User struct {
Name string
Publishing bool
PublishDir string
LastPublished time.Time
}
// GetUsers gets all users with a valid ttbp config, with their name, publishing
// settings, and date of last publish, if any.
func GetUsers() (users []User) {
userDirs, _ := os.ReadDir("/home")
for _, user := range userDirs {
if !user.IsDir() {
continue
}
if file, err := os.Open(path.Join("/home", user.Name(), ".ttbp/config/ttbprc")); err == nil {
defer file.Close()
// get user config
var config config.Config
decoder := json.NewDecoder(file)
err = decoder.Decode(&config)
if err != nil {
continue
}
// get last published file
entries, err := os.ReadDir(path.Join("/home", user.Name(), ".ttbp/entries"))
if err != nil {
continue
}
var lastPublished time.Time = *new(time.Time)
if len(entries) > 0 {
info, err := entries[len(entries)-1].Info()
if err != nil {
continue
}
lastPublished = info.ModTime()
}
users = append(users, User{
Name: user.Name(),
Publishing: config.Publishing,
PublishDir: config.PublishDir,
LastPublished: lastPublished,
})
}
}
return users
}
// SortUsersByRecent sorts users, putting the users with the most recent
// published feels at the beginning.
func SortUsersByRecent(users []User) []User {
sort.Slice(users, func(i, j int) bool {
return users[i].LastPublished.After(users[j].LastPublished)
})
return users
}
type Post struct {
Date time.Time
LastEdited time.Time
Words int
Author string
}
func GetPostsForUser(user string) (posts []Post) {
postFiles, err := os.ReadDir(path.Join("/home", user, ".ttbp/entries"))
if err != nil {
return
}
for _, post := range postFiles {
// retrieve date of file
// assume file ends in .txt
fileDate, err := time.Parse("20060102.txt", post.Name())
if err != nil {
continue
}
if file, err := os.Open(path.Join("/home", user, ".ttbp/entries", post.Name())); err == nil {
defer file.Close()
// get number of words in file
scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanWords)
count := 0
for scanner.Scan() {
count++
}
// get modtime of file
stat, err := file.Stat()
if err != nil {
continue
}
posts = append([]Post{Post{
Author: user,
Date: fileDate,
LastEdited: stat.ModTime(),
Words: count,
}}, posts...)
}
}
return
}
// SortUsersByRecent sorts posts, putting the posts that were most recently
// edited first in the list.
func SortPostsByRecent(posts []Post) []Post {
sort.Slice(posts, func(i, j int) bool {
return posts[i].LastEdited.After(posts[j].LastEdited)
})
return posts
}
type Subscriptions struct {
users []string
}
func GetSubscriptions() *Subscriptions {
file, err := os.OpenFile(path.Join(os.Getenv("HOME"), ".ttbp/config/subs"), os.O_RDONLY|os.O_CREATE, 0644)
if err != nil {
return &Subscriptions{}
}
defer file.Close()
var users []string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
users = append(users, scanner.Text())
}
return &Subscriptions{
users: users,
}
}
func (subscriptions *Subscriptions) IsSubscribed(user User) bool {
for _, sub := range subscriptions.users {
if sub == user.Name {
return true
}
}
return false
}
func (subscriptions *Subscriptions) Subscribe(user User) {
subscriptions.users = append(subscriptions.users, user.Name)
subscriptions.write()
}
func (subscriptions *Subscriptions) Unsubscribe(user User) {
for i, sub := range subscriptions.users {
if sub == user.Name {
subscriptions.users = append(subscriptions.users[:i], subscriptions.users[i+1:]...)
subscriptions.write()
return
}
}
}
func (subscriptions *Subscriptions) write() {
file, err := os.Create(path.Join(os.Getenv("HOME"), ".ttbp/config/subs"))
if err != nil {
return
}
defer file.Close()
writer := bufio.NewWriter(file)
for _, line := range subscriptions.users {
_, err := writer.WriteString(line + "\n")
if err != nil {
return
}
}
writer.Flush()
}