172 lines
3.6 KiB
Go

package arn
import (
"reflect"
"sort"
"github.com/aerogo/nano"
)
// EditLogEntry is an entry in the editor log.
type EditLogEntry struct {
UserID UserID `json:"userId"`
Action string `json:"action"`
ObjectID ID `json:"objectId"` // The ID of what was edited
ObjectType string `json:"objectType"` // The typename of what was edited
Key string `json:"key"`
OldValue string `json:"oldValue"`
NewValue string `json:"newValue"`
Created string `json:"created"`
hasID
}
// NewEditLogEntry creates a new edit log entry.
func NewEditLogEntry(userID UserID, action string, objectType string, objectID ID, key string, oldValue string, newValue string) *EditLogEntry {
return &EditLogEntry{
hasID: hasID{
ID: GenerateID("EditLogEntry"),
},
UserID: userID,
Action: action,
ObjectType: objectType,
ObjectID: objectID,
Key: key,
OldValue: oldValue,
NewValue: newValue,
Created: DateTimeUTC(),
}
}
// User returns the user the log entry belongs to.
func (entry *EditLogEntry) User() *User {
user, _ := GetUser(entry.UserID)
return user
}
// Object returns the object the log entry refers to.
func (entry *EditLogEntry) Object() interface{} {
obj, _ := DB.Get(entry.ObjectType, entry.ObjectID)
return obj
}
// EditorScore returns the editing score for this log entry.
func (entry *EditLogEntry) EditorScore() int {
switch entry.Action {
case "create":
obj, err := DB.Get(entry.ObjectType, entry.ObjectID)
if err != nil {
return 0
}
v := reflect.Indirect(reflect.ValueOf(obj))
isDraft := v.FieldByName("IsDraft")
if isDraft.Kind() == reflect.Bool && isDraft.Bool() {
// No score for drafts
return 0
}
return 4
case "edit":
score := 4
// Bonus score for editing anime
if entry.ObjectType == "Anime" {
score++
// Bonus score for editing anime synopsis
if entry.Key == "Summary" || entry.Key == "Synopsis" {
score++
}
}
return score
case "delete", "arrayRemove":
return 3
case "arrayAppend":
return 0
}
return 0
}
// ActionHumanReadable returns the human readable version of the action.
func (entry *EditLogEntry) ActionHumanReadable() string {
switch entry.Action {
case "create":
return "Created"
case "edit":
return "Edited"
case "delete":
return "Deleted"
case "arrayAppend":
return "Added an element"
case "arrayRemove":
return "Removed an element"
default:
return entry.Action
}
}
// StreamEditLogEntries returns a stream of all log entries.
func StreamEditLogEntries() <-chan *EditLogEntry {
channel := make(chan *EditLogEntry, nano.ChannelBufferSize)
go func() {
for obj := range DB.All("EditLogEntry") {
channel <- obj.(*EditLogEntry)
}
close(channel)
}()
return channel
}
// AllEditLogEntries returns a slice of all log entries.
func AllEditLogEntries() []*EditLogEntry {
all := make([]*EditLogEntry, 0, DB.Collection("EditLogEntry").Count())
stream := StreamEditLogEntries()
for obj := range stream {
all = append(all, obj)
}
return all
}
// FilterEditLogEntries filters all log entries by a custom function.
func FilterEditLogEntries(filter func(*EditLogEntry) bool) []*EditLogEntry {
var filtered []*EditLogEntry
channel := DB.All("EditLogEntry")
for obj := range channel {
realObject := obj.(*EditLogEntry)
if filter(realObject) {
filtered = append(filtered, realObject)
}
}
return filtered
}
// SortEditLogEntriesLatestFirst puts the latest entries on top.
func SortEditLogEntriesLatestFirst(entries []*EditLogEntry) {
sort.Slice(entries, func(i, j int) bool {
return entries[i].Created > entries[j].Created
})
}