You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

274 lines
5.4 KiB

package api
import (
"strings"
"sync"
"unicode"
"github.com/RasmusLindroth/go-mastodon"
"github.com/RasmusLindroth/tut/util"
)
var id uint = 0
var idMux sync.Mutex
func newID() uint {
idMux.Lock()
defer idMux.Unlock()
id = id + 1
return id
}
type Item interface {
ID() uint
Type() MastodonType
ToggleSpoiler()
ShowSpoiler() bool
Raw() interface{}
URLs() ([]util.URL, []mastodon.Mention, []mastodon.Tag, int)
}
func NewStatusItem(item *mastodon.Status, filters []*mastodon.Filter, timeline string) (sitem Item, filtered bool) {
filtered = false
if item == nil {
return &StatusItem{id: newID(), item: item, showSpoiler: false}, false
}
s := util.StatusOrReblog(item)
content := s.Content
if s.Sensitive {
content += "\n" + s.SpoilerText
}
content = strings.ToLower(content)
for _, f := range filters {
apply := false
for _, c := range f.Context {
if timeline == c {
apply = true
break
}
}
if !apply {
continue
}
if f.WholeWord {
lines := strings.Split(content, "\n")
var stripped []string
for _, l := range lines {
var words []string
words = append(words, strings.Split(l, " ")...)
for _, w := range words {
ns := strings.TrimSpace(w)
ns = strings.TrimFunc(ns, func(r rune) bool {
return !unicode.IsLetter(r) && !unicode.IsNumber(r)
})
stripped = append(stripped, ns)
}
}
filter := strings.Split(strings.ToLower(f.Phrase), " ")
for i := 0; i+len(filter)-1 < len(stripped); i++ {
if strings.ToLower(f.Phrase) == strings.Join(stripped[i:i+len(filter)], " ") {
filtered = true
break
}
}
} else {
if strings.Contains(s.Content, strings.ToLower(f.Phrase)) {
filtered = true
}
if strings.Contains(s.SpoilerText, strings.ToLower(f.Phrase)) {
filtered = true
}
}
if filtered {
break
}
}
sitem = &StatusItem{id: newID(), item: item, showSpoiler: false}
return sitem, filtered
}
type StatusItem struct {
id uint
item *mastodon.Status
showSpoiler bool
}
func (s *StatusItem) ID() uint {
return s.id
}
func (s *StatusItem) Type() MastodonType {
return StatusType
}
func (s *StatusItem) ToggleSpoiler() {
s.showSpoiler = !s.showSpoiler
}
func (s *StatusItem) ShowSpoiler() bool {
return s.showSpoiler
}
func (s *StatusItem) Raw() interface{} {
return s.item
}
func (s *StatusItem) URLs() ([]util.URL, []mastodon.Mention, []mastodon.Tag, int) {
status := s.item
if status.Reblog != nil {
status = status.Reblog
}
_, urls := util.CleanHTML(status.Content)
if status.Sensitive {
_, u := util.CleanHTML(status.SpoilerText)
urls = append(urls, u...)
}
realUrls := []util.URL{}
for _, url := range urls {
isNotMention := true
for _, mention := range status.Mentions {
if mention.URL == url.URL {
isNotMention = false
}
}
if isNotMention {
realUrls = append(realUrls, url)
}
}
length := len(realUrls) + len(status.Mentions) + len(status.Tags)
return realUrls, status.Mentions, status.Tags, length
}
func NewUserItem(item *User, profile bool) Item {
return &UserItem{id: newID(), item: item, profile: profile}
}
type UserItem struct {
id uint
item *User
profile bool
}
func (u *UserItem) ID() uint {
return u.id
}
func (u *UserItem) Type() MastodonType {
if u.profile {
return ProfileType
}
return UserType
}
func (u *UserItem) ToggleSpoiler() {
}
func (u *UserItem) ShowSpoiler() bool {
return false
}
func (u *UserItem) Raw() interface{} {
return u.item
}
func (u *UserItem) URLs() ([]util.URL, []mastodon.Mention, []mastodon.Tag, int) {
user := u.item.Data
var urls []util.URL
user.Note, urls = util.CleanHTML(user.Note)
for _, f := range user.Fields {
_, fu := util.CleanHTML(f.Value)
urls = append(urls, fu...)
}
return urls, []mastodon.Mention{}, []mastodon.Tag{}, len(urls)
}
func NewNotificationItem(item *mastodon.Notification, user *User, filters []*mastodon.Filter) (nitem Item, filtred bool) {
status, filtred := NewStatusItem(item.Status, filters, "notifications")
nitem = &NotificationItem{
id: newID(),
item: item,
showSpoiler: false,
user: NewUserItem(user, false),
status: status,
}
return nitem, filtred
}
type NotificationItem struct {
id uint
item *mastodon.Notification
showSpoiler bool
status Item
user Item
}
type NotificationData struct {
Item *mastodon.Notification
Status Item
User Item
}
func (n *NotificationItem) ID() uint {
return n.id
}
func (n *NotificationItem) Type() MastodonType {
return NotificationType
}
func (n *NotificationItem) ToggleSpoiler() {
n.showSpoiler = !n.showSpoiler
}
func (n *NotificationItem) ShowSpoiler() bool {
return n.showSpoiler
}
func (n *NotificationItem) Raw() interface{} {
return &NotificationData{
Item: n.item,
Status: n.status,
User: n.user,
}
}
func (n *NotificationItem) URLs() ([]util.URL, []mastodon.Mention, []mastodon.Tag, int) {
return nil, nil, nil, 0
}
func NewListsItem(item *mastodon.List) Item {
return &ListItem{id: newID(), item: item, showSpoiler: true}
}
type ListItem struct {
id uint
item *mastodon.List
showSpoiler bool
}
func (s *ListItem) ID() uint {
return s.id
}
func (s *ListItem) Type() MastodonType {
return ListsType
}
func (s *ListItem) ToggleSpoiler() {
}
func (s *ListItem) ShowSpoiler() bool {
return true
}
func (s *ListItem) Raw() interface{} {
return s.item
}
func (s *ListItem) URLs() ([]util.URL, []mastodon.Mention, []mastodon.Tag, int) {
return nil, nil, nil, 0
}