Prep for reactions, some fixes and improvements
Some checks failed
/ docker (push) Failing after 1m35s
Some checks failed
/ docker (push) Failing after 1m35s
This commit is contained in:
parent
4b62c32247
commit
8947d97825
13 changed files with 262 additions and 43 deletions
30
activitypub/translators/emote.go
Normal file
30
activitypub/translators/emote.go
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package translators
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"git.mstar.dev/mstar/linstrom/config"
|
||||||
|
"git.mstar.dev/mstar/linstrom/storage-new/dbgen"
|
||||||
|
)
|
||||||
|
|
||||||
|
func EmoteTagFromStorage(ctx context.Context, id string) (*Tag, error) {
|
||||||
|
emote, err := dbgen.Emote.Where(dbgen.Emote.ID.Eq(id)).First()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
emoteId := config.GlobalConfig.General.GetFullPublicUrl() + "/api/activitypub/emote/" + id
|
||||||
|
emoteMedia, err := MediaFromStorage(ctx, emote.MetadataId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out := Tag{
|
||||||
|
Type: "Emoji",
|
||||||
|
Name: emote.Name,
|
||||||
|
Href: nil,
|
||||||
|
Id: &emoteId,
|
||||||
|
Updated: &emote.UpdatedAt,
|
||||||
|
Icon: emoteMedia,
|
||||||
|
}
|
||||||
|
|
||||||
|
return &out, nil
|
||||||
|
}
|
|
@ -1,5 +1,14 @@
|
||||||
package translators
|
package translators
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.mstar.dev/mstar/linstrom/activitypub"
|
||||||
|
"git.mstar.dev/mstar/linstrom/config"
|
||||||
|
"git.mstar.dev/mstar/linstrom/storage-new/dbgen"
|
||||||
|
)
|
||||||
|
|
||||||
type ActivityLikeOut struct {
|
type ActivityLikeOut struct {
|
||||||
Context any `json:"@context"`
|
Context any `json:"@context"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
|
@ -10,3 +19,37 @@ type ActivityLikeOut struct {
|
||||||
MkReaction *string `json:"_misskey_reaction,omitempty"`
|
MkReaction *string `json:"_misskey_reaction,omitempty"`
|
||||||
Tags []Tag `json:"tag,omitempty"`
|
Tags []Tag `json:"tag,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LikeFromStorage(ctx context.Context, id string) (*ActivityLikeOut, error) {
|
||||||
|
reaction, err := dbgen.Reaction.
|
||||||
|
Where(dbgen.Reaction.ID.Eq(id)).
|
||||||
|
Preload(dbgen.Reaction.Emote).
|
||||||
|
First()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
like := &ActivityLikeOut{
|
||||||
|
Type: "Like",
|
||||||
|
Id: config.GlobalConfig.General.GetFullPublicUrl() + "/api/activitypub/activity/like/" + id,
|
||||||
|
Actor: activitypub.UserIdToApUrl(reaction.ReactorId),
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(reaction.NoteId, "http") {
|
||||||
|
like.Object = reaction.NoteId
|
||||||
|
} else {
|
||||||
|
like.Object = config.GlobalConfig.General.GetFullPublicUrl() + "/api/activitypub/note/" + reaction.NoteId
|
||||||
|
}
|
||||||
|
if reaction.Content.Valid {
|
||||||
|
like.Content = &reaction.Content.String
|
||||||
|
like.MkReaction = &reaction.Content.String
|
||||||
|
}
|
||||||
|
if reaction.Emote != nil {
|
||||||
|
like.Content = &reaction.Emote.Name
|
||||||
|
like.MkReaction = &reaction.Emote.Name
|
||||||
|
emote, err := EmoteTagFromStorage(ctx, reaction.Emote.ID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
like.Tags = append(like.Tags, *emote)
|
||||||
|
}
|
||||||
|
return like, nil
|
||||||
|
}
|
||||||
|
|
26
activitypub/translators/media.go
Normal file
26
activitypub/translators/media.go
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
package translators
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"git.mstar.dev/mstar/linstrom/storage-new/dbgen"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Media struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Url string `json:"url"`
|
||||||
|
MediaType string `json:"mediaType"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func MediaFromStorage(ctx context.Context, id string) (*Media, error) {
|
||||||
|
metadata, err := dbgen.MediaMetadata.Where(dbgen.MediaMetadata.ID.Eq(id)).First()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
data := Media{
|
||||||
|
Type: "Image", // FIXME: Change this to a sort of dynamic detection based on mimetype
|
||||||
|
MediaType: metadata.Type,
|
||||||
|
Url: metadata.Location,
|
||||||
|
}
|
||||||
|
return &data, nil
|
||||||
|
}
|
|
@ -103,16 +103,17 @@ func NoteFromStorage(ctx context.Context, id string) (*ObjectNote, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
pubUrl := webshared.UserPublicUrl(target.ID)
|
||||||
data.Tags = append(data.Tags, Tag{
|
data.Tags = append(data.Tags, Tag{
|
||||||
Type: "Mention",
|
Type: "Mention",
|
||||||
Href: webshared.UserPublicUrl(target.ID),
|
Href: &pubUrl,
|
||||||
Name: target.Username,
|
Name: target.Username,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
for _, tag := range note.Tags {
|
for _, tag := range note.Tags {
|
||||||
data.Tags = append(data.Tags, Tag{
|
data.Tags = append(data.Tags, Tag{
|
||||||
Type: "Hashtag",
|
Type: "Hashtag",
|
||||||
Href: tag.TagUrl,
|
Href: &tag.TagUrl,
|
||||||
Name: tag.Tag,
|
Name: tag.Tag,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,11 +21,7 @@ type UserKey struct {
|
||||||
Owner string `json:"owner"`
|
Owner string `json:"owner"`
|
||||||
Pem string `json:"publicKeyPem"`
|
Pem string `json:"publicKeyPem"`
|
||||||
}
|
}
|
||||||
type Media struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
Url string `json:"url"`
|
|
||||||
MediaType string `json:"mediaType"`
|
|
||||||
}
|
|
||||||
type User struct {
|
type User struct {
|
||||||
Context []any `json:"@context"`
|
Context []any `json:"@context"`
|
||||||
Id string `json:"id"`
|
Id string `json:"id"`
|
||||||
|
|
|
@ -65,14 +65,6 @@ type ConfigStorage struct {
|
||||||
Port int `toml:"port"`
|
Port int `toml:"port"`
|
||||||
SslMode *string `toml:"ssl_mode"`
|
SslMode *string `toml:"ssl_mode"`
|
||||||
TimeZone *string `toml:"time_zone"`
|
TimeZone *string `toml:"time_zone"`
|
||||||
// Url to redis server. If empty, no redis is used
|
|
||||||
RedisUrl *string `toml:"redis_url,omitempty"`
|
|
||||||
// The maximum size of the in-memory cache in bytes
|
|
||||||
MaxInMemoryCacheSize int64 `toml:"max_in_memory_cache_size"`
|
|
||||||
// The time to live for in app in memory cache items, in seconds
|
|
||||||
MaxInMemoryCacheTTL int `toml:"max_in_memory_cache_ttl"`
|
|
||||||
// The time to live for items in redis, in seconds
|
|
||||||
MaxRedisCacheTTL *int `toml:"max_redis_cache_ttl"`
|
|
||||||
// Key used for encrypting sensitive information in the db
|
// Key used for encrypting sensitive information in the db
|
||||||
// DO NOT CHANGE THIS AFTER SETUP
|
// DO NOT CHANGE THIS AFTER SETUP
|
||||||
EncryptionKey string `toml:"encryption_key"`
|
EncryptionKey string `toml:"encryption_key"`
|
||||||
|
|
|
@ -14,6 +14,14 @@ type Server struct {
|
||||||
client *minio.Client
|
client *minio.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO: Figure out an api for a microservice for transcoding media, see https://tech.lgbt/@lina/114682780787448797
|
||||||
|
- Read endpoint from config
|
||||||
|
- Try to reach transcoder
|
||||||
|
- If transcoder is alive, use it for transcoding
|
||||||
|
- If not alive, store files as is
|
||||||
|
*/
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrNoBucketAccess = errors.New("can't access configured bucket")
|
ErrNoBucketAccess = errors.New("can't access configured bucket")
|
||||||
)
|
)
|
||||||
|
@ -50,7 +58,7 @@ func NewServer() (*Server, error) {
|
||||||
return &Server{client: client}, nil
|
return &Server{client: client}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a userId and filename into a proper filepath for s3.
|
// UsernameFilename converts a userId and filename into a proper filepath for s3.
|
||||||
// Reason for this is that the userId for external users is a valid url which needs to be encoded
|
// Reason for this is that the userId for external users is a valid url which needs to be encoded
|
||||||
func UsernameFilename(userId, filename string) string {
|
func UsernameFilename(userId, filename string) string {
|
||||||
return userId + "//" + filename
|
return userId + "//" + filename
|
||||||
|
|
|
@ -27,7 +27,7 @@ func newEmote(db *gorm.DB, opts ...gen.DOOption) emote {
|
||||||
|
|
||||||
tableName := _emote.emoteDo.TableName()
|
tableName := _emote.emoteDo.TableName()
|
||||||
_emote.ALL = field.NewAsterisk(tableName)
|
_emote.ALL = field.NewAsterisk(tableName)
|
||||||
_emote.ID = field.NewUint(tableName, "id")
|
_emote.ID = field.NewString(tableName, "id")
|
||||||
_emote.CreatedAt = field.NewTime(tableName, "created_at")
|
_emote.CreatedAt = field.NewTime(tableName, "created_at")
|
||||||
_emote.UpdatedAt = field.NewTime(tableName, "updated_at")
|
_emote.UpdatedAt = field.NewTime(tableName, "updated_at")
|
||||||
_emote.DeletedAt = field.NewField(tableName, "deleted_at")
|
_emote.DeletedAt = field.NewField(tableName, "deleted_at")
|
||||||
|
@ -73,7 +73,7 @@ type emote struct {
|
||||||
emoteDo
|
emoteDo
|
||||||
|
|
||||||
ALL field.Asterisk
|
ALL field.Asterisk
|
||||||
ID field.Uint
|
ID field.String
|
||||||
CreatedAt field.Time
|
CreatedAt field.Time
|
||||||
UpdatedAt field.Time
|
UpdatedAt field.Time
|
||||||
DeletedAt field.Field
|
DeletedAt field.Field
|
||||||
|
@ -99,7 +99,7 @@ func (e emote) As(alias string) *emote {
|
||||||
|
|
||||||
func (e *emote) updateTableName(table string) *emote {
|
func (e *emote) updateTableName(table string) *emote {
|
||||||
e.ALL = field.NewAsterisk(table)
|
e.ALL = field.NewAsterisk(table)
|
||||||
e.ID = field.NewUint(table, "id")
|
e.ID = field.NewString(table, "id")
|
||||||
e.CreatedAt = field.NewTime(table, "created_at")
|
e.CreatedAt = field.NewTime(table, "created_at")
|
||||||
e.UpdatedAt = field.NewTime(table, "updated_at")
|
e.UpdatedAt = field.NewTime(table, "updated_at")
|
||||||
e.DeletedAt = field.NewField(table, "deleted_at")
|
e.DeletedAt = field.NewField(table, "deleted_at")
|
||||||
|
|
|
@ -30,6 +30,8 @@ func newNoteToFeed(db *gorm.DB, opts ...gen.DOOption) noteToFeed {
|
||||||
_noteToFeed.ID = field.NewUint64(tableName, "id")
|
_noteToFeed.ID = field.NewUint64(tableName, "id")
|
||||||
_noteToFeed.CreatedAt = field.NewTime(tableName, "created_at")
|
_noteToFeed.CreatedAt = field.NewTime(tableName, "created_at")
|
||||||
_noteToFeed.NoteId = field.NewString(tableName, "note_id")
|
_noteToFeed.NoteId = field.NewString(tableName, "note_id")
|
||||||
|
_noteToFeed.FeedId = field.NewUint64(tableName, "feed_id")
|
||||||
|
_noteToFeed.Reason = field.NewString(tableName, "reason")
|
||||||
_noteToFeed.Note = noteToFeedBelongsToNote{
|
_noteToFeed.Note = noteToFeedBelongsToNote{
|
||||||
db: db.Session(&gorm.Session{}),
|
db: db.Session(&gorm.Session{}),
|
||||||
|
|
||||||
|
@ -399,6 +401,17 @@ func newNoteToFeed(db *gorm.DB, opts ...gen.DOOption) noteToFeed {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_noteToFeed.Feed = noteToFeedBelongsToFeed{
|
||||||
|
db: db.Session(&gorm.Session{}),
|
||||||
|
|
||||||
|
RelationField: field.NewRelation("Feed", "models.Feed"),
|
||||||
|
Owner: struct {
|
||||||
|
field.RelationField
|
||||||
|
}{
|
||||||
|
RelationField: field.NewRelation("Feed.Owner", "models.User"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
_noteToFeed.fillFieldMap()
|
_noteToFeed.fillFieldMap()
|
||||||
|
|
||||||
return _noteToFeed
|
return _noteToFeed
|
||||||
|
@ -411,8 +424,12 @@ type noteToFeed struct {
|
||||||
ID field.Uint64
|
ID field.Uint64
|
||||||
CreatedAt field.Time
|
CreatedAt field.Time
|
||||||
NoteId field.String
|
NoteId field.String
|
||||||
|
FeedId field.Uint64
|
||||||
|
Reason field.String
|
||||||
Note noteToFeedBelongsToNote
|
Note noteToFeedBelongsToNote
|
||||||
|
|
||||||
|
Feed noteToFeedBelongsToFeed
|
||||||
|
|
||||||
fieldMap map[string]field.Expr
|
fieldMap map[string]field.Expr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -431,6 +448,8 @@ func (n *noteToFeed) updateTableName(table string) *noteToFeed {
|
||||||
n.ID = field.NewUint64(table, "id")
|
n.ID = field.NewUint64(table, "id")
|
||||||
n.CreatedAt = field.NewTime(table, "created_at")
|
n.CreatedAt = field.NewTime(table, "created_at")
|
||||||
n.NoteId = field.NewString(table, "note_id")
|
n.NoteId = field.NewString(table, "note_id")
|
||||||
|
n.FeedId = field.NewUint64(table, "feed_id")
|
||||||
|
n.Reason = field.NewString(table, "reason")
|
||||||
|
|
||||||
n.fillFieldMap()
|
n.fillFieldMap()
|
||||||
|
|
||||||
|
@ -447,10 +466,12 @@ func (n *noteToFeed) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *noteToFeed) fillFieldMap() {
|
func (n *noteToFeed) fillFieldMap() {
|
||||||
n.fieldMap = make(map[string]field.Expr, 4)
|
n.fieldMap = make(map[string]field.Expr, 7)
|
||||||
n.fieldMap["id"] = n.ID
|
n.fieldMap["id"] = n.ID
|
||||||
n.fieldMap["created_at"] = n.CreatedAt
|
n.fieldMap["created_at"] = n.CreatedAt
|
||||||
n.fieldMap["note_id"] = n.NoteId
|
n.fieldMap["note_id"] = n.NoteId
|
||||||
|
n.fieldMap["feed_id"] = n.FeedId
|
||||||
|
n.fieldMap["reason"] = n.Reason
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,12 +479,15 @@ func (n noteToFeed) clone(db *gorm.DB) noteToFeed {
|
||||||
n.noteToFeedDo.ReplaceConnPool(db.Statement.ConnPool)
|
n.noteToFeedDo.ReplaceConnPool(db.Statement.ConnPool)
|
||||||
n.Note.db = db.Session(&gorm.Session{Initialized: true})
|
n.Note.db = db.Session(&gorm.Session{Initialized: true})
|
||||||
n.Note.db.Statement.ConnPool = db.Statement.ConnPool
|
n.Note.db.Statement.ConnPool = db.Statement.ConnPool
|
||||||
|
n.Feed.db = db.Session(&gorm.Session{Initialized: true})
|
||||||
|
n.Feed.db.Statement.ConnPool = db.Statement.ConnPool
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n noteToFeed) replaceDB(db *gorm.DB) noteToFeed {
|
func (n noteToFeed) replaceDB(db *gorm.DB) noteToFeed {
|
||||||
n.noteToFeedDo.ReplaceDB(db)
|
n.noteToFeedDo.ReplaceDB(db)
|
||||||
n.Note.db = db.Session(&gorm.Session{})
|
n.Note.db = db.Session(&gorm.Session{})
|
||||||
|
n.Feed.db = db.Session(&gorm.Session{})
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -675,6 +699,91 @@ func (a noteToFeedBelongsToNoteTx) Unscoped() *noteToFeedBelongsToNoteTx {
|
||||||
return &a
|
return &a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type noteToFeedBelongsToFeed struct {
|
||||||
|
db *gorm.DB
|
||||||
|
|
||||||
|
field.RelationField
|
||||||
|
|
||||||
|
Owner struct {
|
||||||
|
field.RelationField
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a noteToFeedBelongsToFeed) Where(conds ...field.Expr) *noteToFeedBelongsToFeed {
|
||||||
|
if len(conds) == 0 {
|
||||||
|
return &a
|
||||||
|
}
|
||||||
|
|
||||||
|
exprs := make([]clause.Expression, 0, len(conds))
|
||||||
|
for _, cond := range conds {
|
||||||
|
exprs = append(exprs, cond.BeCond().(clause.Expression))
|
||||||
|
}
|
||||||
|
a.db = a.db.Clauses(clause.Where{Exprs: exprs})
|
||||||
|
return &a
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a noteToFeedBelongsToFeed) WithContext(ctx context.Context) *noteToFeedBelongsToFeed {
|
||||||
|
a.db = a.db.WithContext(ctx)
|
||||||
|
return &a
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a noteToFeedBelongsToFeed) Session(session *gorm.Session) *noteToFeedBelongsToFeed {
|
||||||
|
a.db = a.db.Session(session)
|
||||||
|
return &a
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a noteToFeedBelongsToFeed) Model(m *models.NoteToFeed) *noteToFeedBelongsToFeedTx {
|
||||||
|
return ¬eToFeedBelongsToFeedTx{a.db.Model(m).Association(a.Name())}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a noteToFeedBelongsToFeed) Unscoped() *noteToFeedBelongsToFeed {
|
||||||
|
a.db = a.db.Unscoped()
|
||||||
|
return &a
|
||||||
|
}
|
||||||
|
|
||||||
|
type noteToFeedBelongsToFeedTx struct{ tx *gorm.Association }
|
||||||
|
|
||||||
|
func (a noteToFeedBelongsToFeedTx) Find() (result *models.Feed, err error) {
|
||||||
|
return result, a.tx.Find(&result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a noteToFeedBelongsToFeedTx) Append(values ...*models.Feed) (err error) {
|
||||||
|
targetValues := make([]interface{}, len(values))
|
||||||
|
for i, v := range values {
|
||||||
|
targetValues[i] = v
|
||||||
|
}
|
||||||
|
return a.tx.Append(targetValues...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a noteToFeedBelongsToFeedTx) Replace(values ...*models.Feed) (err error) {
|
||||||
|
targetValues := make([]interface{}, len(values))
|
||||||
|
for i, v := range values {
|
||||||
|
targetValues[i] = v
|
||||||
|
}
|
||||||
|
return a.tx.Replace(targetValues...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a noteToFeedBelongsToFeedTx) Delete(values ...*models.Feed) (err error) {
|
||||||
|
targetValues := make([]interface{}, len(values))
|
||||||
|
for i, v := range values {
|
||||||
|
targetValues[i] = v
|
||||||
|
}
|
||||||
|
return a.tx.Delete(targetValues...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a noteToFeedBelongsToFeedTx) Clear() error {
|
||||||
|
return a.tx.Clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a noteToFeedBelongsToFeedTx) Count() int64 {
|
||||||
|
return a.tx.Count()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a noteToFeedBelongsToFeedTx) Unscoped() *noteToFeedBelongsToFeedTx {
|
||||||
|
a.tx = a.tx.Unscoped()
|
||||||
|
return &a
|
||||||
|
}
|
||||||
|
|
||||||
type noteToFeedDo struct{ gen.DO }
|
type noteToFeedDo struct{ gen.DO }
|
||||||
|
|
||||||
type INoteToFeedDo interface {
|
type INoteToFeedDo interface {
|
||||||
|
|
|
@ -27,13 +27,14 @@ func newReaction(db *gorm.DB, opts ...gen.DOOption) reaction {
|
||||||
|
|
||||||
tableName := _reaction.reactionDo.TableName()
|
tableName := _reaction.reactionDo.TableName()
|
||||||
_reaction.ALL = field.NewAsterisk(tableName)
|
_reaction.ALL = field.NewAsterisk(tableName)
|
||||||
_reaction.ID = field.NewUint(tableName, "id")
|
_reaction.ID = field.NewString(tableName, "id")
|
||||||
_reaction.CreatedAt = field.NewTime(tableName, "created_at")
|
_reaction.CreatedAt = field.NewTime(tableName, "created_at")
|
||||||
_reaction.UpdatedAt = field.NewTime(tableName, "updated_at")
|
_reaction.UpdatedAt = field.NewTime(tableName, "updated_at")
|
||||||
_reaction.DeletedAt = field.NewField(tableName, "deleted_at")
|
_reaction.DeletedAt = field.NewField(tableName, "deleted_at")
|
||||||
_reaction.NoteId = field.NewString(tableName, "note_id")
|
_reaction.NoteId = field.NewString(tableName, "note_id")
|
||||||
_reaction.ReactorId = field.NewString(tableName, "reactor_id")
|
_reaction.ReactorId = field.NewString(tableName, "reactor_id")
|
||||||
_reaction.EmoteId = field.NewField(tableName, "emote_id")
|
_reaction.EmoteId = field.NewField(tableName, "emote_id")
|
||||||
|
_reaction.Content = field.NewField(tableName, "content")
|
||||||
_reaction.Note = reactionBelongsToNote{
|
_reaction.Note = reactionBelongsToNote{
|
||||||
db: db.Session(&gorm.Session{}),
|
db: db.Session(&gorm.Session{}),
|
||||||
|
|
||||||
|
@ -424,13 +425,14 @@ type reaction struct {
|
||||||
reactionDo
|
reactionDo
|
||||||
|
|
||||||
ALL field.Asterisk
|
ALL field.Asterisk
|
||||||
ID field.Uint
|
ID field.String
|
||||||
CreatedAt field.Time
|
CreatedAt field.Time
|
||||||
UpdatedAt field.Time
|
UpdatedAt field.Time
|
||||||
DeletedAt field.Field
|
DeletedAt field.Field
|
||||||
NoteId field.String
|
NoteId field.String
|
||||||
ReactorId field.String
|
ReactorId field.String
|
||||||
EmoteId field.Field
|
EmoteId field.Field
|
||||||
|
Content field.Field
|
||||||
Note reactionBelongsToNote
|
Note reactionBelongsToNote
|
||||||
|
|
||||||
Reactor reactionBelongsToReactor
|
Reactor reactionBelongsToReactor
|
||||||
|
@ -452,13 +454,14 @@ func (r reaction) As(alias string) *reaction {
|
||||||
|
|
||||||
func (r *reaction) updateTableName(table string) *reaction {
|
func (r *reaction) updateTableName(table string) *reaction {
|
||||||
r.ALL = field.NewAsterisk(table)
|
r.ALL = field.NewAsterisk(table)
|
||||||
r.ID = field.NewUint(table, "id")
|
r.ID = field.NewString(table, "id")
|
||||||
r.CreatedAt = field.NewTime(table, "created_at")
|
r.CreatedAt = field.NewTime(table, "created_at")
|
||||||
r.UpdatedAt = field.NewTime(table, "updated_at")
|
r.UpdatedAt = field.NewTime(table, "updated_at")
|
||||||
r.DeletedAt = field.NewField(table, "deleted_at")
|
r.DeletedAt = field.NewField(table, "deleted_at")
|
||||||
r.NoteId = field.NewString(table, "note_id")
|
r.NoteId = field.NewString(table, "note_id")
|
||||||
r.ReactorId = field.NewString(table, "reactor_id")
|
r.ReactorId = field.NewString(table, "reactor_id")
|
||||||
r.EmoteId = field.NewField(table, "emote_id")
|
r.EmoteId = field.NewField(table, "emote_id")
|
||||||
|
r.Content = field.NewField(table, "content")
|
||||||
|
|
||||||
r.fillFieldMap()
|
r.fillFieldMap()
|
||||||
|
|
||||||
|
@ -475,7 +478,7 @@ func (r *reaction) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *reaction) fillFieldMap() {
|
func (r *reaction) fillFieldMap() {
|
||||||
r.fieldMap = make(map[string]field.Expr, 10)
|
r.fieldMap = make(map[string]field.Expr, 11)
|
||||||
r.fieldMap["id"] = r.ID
|
r.fieldMap["id"] = r.ID
|
||||||
r.fieldMap["created_at"] = r.CreatedAt
|
r.fieldMap["created_at"] = r.CreatedAt
|
||||||
r.fieldMap["updated_at"] = r.UpdatedAt
|
r.fieldMap["updated_at"] = r.UpdatedAt
|
||||||
|
@ -483,6 +486,7 @@ func (r *reaction) fillFieldMap() {
|
||||||
r.fieldMap["note_id"] = r.NoteId
|
r.fieldMap["note_id"] = r.NoteId
|
||||||
r.fieldMap["reactor_id"] = r.ReactorId
|
r.fieldMap["reactor_id"] = r.ReactorId
|
||||||
r.fieldMap["emote_id"] = r.EmoteId
|
r.fieldMap["emote_id"] = r.EmoteId
|
||||||
|
r.fieldMap["content"] = r.Content
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,19 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
import "gorm.io/gorm"
|
import (
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
// Emotes are combinations of a name, the server it originated from
|
// Emotes are combinations of a name, the server it originated from
|
||||||
// and the media for it
|
// and the media for it. Only represents custom emotes, not characters found in unicode
|
||||||
//
|
//
|
||||||
// TODO: Include the case of unicode icons being used as emote
|
// TODO: Include the case of unicode icons being used as emote
|
||||||
type Emote struct {
|
type Emote struct {
|
||||||
gorm.Model // Standard gorm model for id and timestamps
|
ID string `gorm:"primarykey"`
|
||||||
|
CreatedAt time.Time
|
||||||
|
UpdatedAt time.Time
|
||||||
|
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||||||
Metadata MediaMetadata // The media used by this emote
|
Metadata MediaMetadata // The media used by this emote
|
||||||
MetadataId string // Id of the media information, primarily for gorm
|
MetadataId string // Id of the media information, primarily for gorm
|
||||||
// Name of the emote. Also the text for using it in a message (ex. :bob:)
|
// Name of the emote. Also the text for using it in a message (ex. :bob:)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"time"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
@ -10,12 +11,15 @@ import (
|
||||||
// A reaction may contain some content text. If yes, this is the reaction.
|
// A reaction may contain some content text. If yes, this is the reaction.
|
||||||
// It also may contain a specifically linked emote (via tag). If yes, this is the reaction and takes precedence over the content
|
// It also may contain a specifically linked emote (via tag). If yes, this is the reaction and takes precedence over the content
|
||||||
type Reaction struct {
|
type Reaction struct {
|
||||||
gorm.Model
|
ID string `gorm:"primarykey"`
|
||||||
|
CreatedAt time.Time
|
||||||
|
UpdatedAt time.Time
|
||||||
|
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||||||
Note Note
|
Note Note
|
||||||
NoteId string
|
NoteId string
|
||||||
Reactor User
|
Reactor User
|
||||||
ReactorId string
|
ReactorId string
|
||||||
Emote *Emote // Emote is optional. If not set, use the default emote of the server
|
Emote *Emote // Emote is optional. If not set, use the default emote of the server
|
||||||
EmoteId sql.NullInt64
|
EmoteId sql.NullString
|
||||||
Content sql.NullString // Content/text of the reaction. Used for example in cases where a unicode character is sent as emote reaction
|
Content sql.NullString // Content/text of the reaction. Used for example in cases where a unicode character is sent as emote reaction
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,17 +6,17 @@ import (
|
||||||
|
|
||||||
func BuildActivitypubRouter() http.Handler {
|
func BuildActivitypubRouter() http.Handler {
|
||||||
router := http.NewServeMux()
|
router := http.NewServeMux()
|
||||||
router.HandleFunc("/user/{id}", users)
|
router.HandleFunc("GET /user/{id}", users)
|
||||||
router.HandleFunc("/user/{id}/inbox", userInbox)
|
router.HandleFunc("POST /user/{id}/inbox", userInbox)
|
||||||
router.HandleFunc("/user/{id}/followers", userFollowers)
|
router.HandleFunc("GET /user/{id}/followers", userFollowers)
|
||||||
router.HandleFunc("/user/{id}/following", userFollowing)
|
router.HandleFunc("GET /user/{id}/following", userFollowing)
|
||||||
router.HandleFunc("/activity/accept/{id}", activityAccept)
|
router.HandleFunc("GET /activity/accept/{id}", activityAccept)
|
||||||
router.HandleFunc("/activity/create/{id}", activityCreate)
|
router.HandleFunc("GET /activity/create/{id}", activityCreate)
|
||||||
router.HandleFunc("/activity/delete/{id}", activityDelete)
|
router.HandleFunc("GET /activity/delete/{id}", activityDelete)
|
||||||
router.HandleFunc("/activity/reject/{id}", activityReject)
|
router.HandleFunc("GET /activity/reject/{id}", activityReject)
|
||||||
router.HandleFunc("/activity/update/{id}", activityUpdate)
|
router.HandleFunc("GET /activity/update/{id}", activityUpdate)
|
||||||
router.HandleFunc("/activity/follow/{id}", activityFollow)
|
router.HandleFunc("GET /activity/follow/{id}", activityFollow)
|
||||||
router.HandleFunc("/note/{id}", objectNote)
|
router.HandleFunc("GET /note/{id}", objectNote)
|
||||||
router.HandleFunc("/note/{id}/reactions", noteReactions)
|
router.HandleFunc("GET /note/{id}/reactions", noteReactions)
|
||||||
return router
|
return router
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue