parent
5939bbd09d
commit
b1c46a86aa
@ -1,58 +1,11 @@ |
||||
package app |
||||
|
||||
import ( |
||||
"errors" |
||||
"owl-blogs/domain/model" |
||||
"reflect" |
||||
) |
||||
|
||||
type EntryTypeRegistry struct { |
||||
types map[string]model.Entry |
||||
} |
||||
type EntryTypeRegistry = TypeRegistry[model.Entry] |
||||
|
||||
func NewEntryTypeRegistry() *EntryTypeRegistry { |
||||
return &EntryTypeRegistry{types: map[string]model.Entry{}} |
||||
} |
||||
|
||||
func (r *EntryTypeRegistry) entryType(entry model.Entry) string { |
||||
return reflect.TypeOf(entry).Elem().Name() |
||||
} |
||||
|
||||
func (r *EntryTypeRegistry) Register(entry model.Entry) error { |
||||
t := r.entryType(entry) |
||||
if _, ok := r.types[t]; ok { |
||||
return errors.New("entry type already registered") |
||||
} |
||||
r.types[t] = entry |
||||
return nil |
||||
} |
||||
|
||||
func (r *EntryTypeRegistry) Types() []model.Entry { |
||||
types := []model.Entry{} |
||||
for _, t := range r.types { |
||||
types = append(types, t) |
||||
} |
||||
return types |
||||
} |
||||
|
||||
func (r *EntryTypeRegistry) TypeName(entry model.Entry) (string, error) { |
||||
t := r.entryType(entry) |
||||
if _, ok := r.types[t]; !ok { |
||||
return "", errors.New("entry type not registered") |
||||
} |
||||
return t, nil |
||||
} |
||||
|
||||
func (r *EntryTypeRegistry) Type(name string) (model.Entry, error) { |
||||
if _, ok := r.types[name]; !ok { |
||||
return nil, errors.New("entry type not registered") |
||||
} |
||||
|
||||
val := reflect.ValueOf(r.types[name]) |
||||
if val.Kind() == reflect.Ptr { |
||||
val = reflect.Indirect(val) |
||||
} |
||||
newEntry := reflect.New(val.Type()).Interface().(model.Entry) |
||||
|
||||
return newEntry, nil |
||||
return NewTypeRegistry[model.Entry]() |
||||
} |
||||
|
@ -0,0 +1,57 @@ |
||||
package app |
||||
|
||||
import ( |
||||
"errors" |
||||
"reflect" |
||||
) |
||||
|
||||
type TypeRegistry[T any] struct { |
||||
types map[string]T |
||||
} |
||||
|
||||
func NewTypeRegistry[T any]() *TypeRegistry[T] { |
||||
return &TypeRegistry[T]{types: map[string]T{}} |
||||
} |
||||
|
||||
func (r *TypeRegistry[T]) entryType(entry T) string { |
||||
return reflect.TypeOf(entry).Elem().Name() |
||||
} |
||||
|
||||
func (r *TypeRegistry[T]) Register(entry T) error { |
||||
t := r.entryType(entry) |
||||
if _, ok := r.types[t]; ok { |
||||
return errors.New("entry type already registered") |
||||
} |
||||
r.types[t] = entry |
||||
return nil |
||||
} |
||||
|
||||
func (r *TypeRegistry[T]) Types() []T { |
||||
types := []T{} |
||||
for _, t := range r.types { |
||||
types = append(types, t) |
||||
} |
||||
return types |
||||
} |
||||
|
||||
func (r *TypeRegistry[T]) TypeName(entry T) (string, error) { |
||||
t := r.entryType(entry) |
||||
if _, ok := r.types[t]; !ok { |
||||
return "", errors.New("entry type not registered") |
||||
} |
||||
return t, nil |
||||
} |
||||
|
||||
func (r *TypeRegistry[T]) Type(name string) (T, error) { |
||||
if _, ok := r.types[name]; !ok { |
||||
return *new(T), errors.New("entry type not registered") |
||||
} |
||||
|
||||
val := reflect.ValueOf(r.types[name]) |
||||
if val.Kind() == reflect.Ptr { |
||||
val = reflect.Indirect(val) |
||||
} |
||||
newEntry := reflect.New(val.Type()).Interface().(T) |
||||
|
||||
return newEntry, nil |
||||
} |
@ -0,0 +1,11 @@ |
||||
package app |
||||
|
||||
import ( |
||||
"owl-blogs/domain/model" |
||||
) |
||||
|
||||
type InteractionTypeRegistry = TypeRegistry[model.Interaction] |
||||
|
||||
func NewInteractionTypeRegistry() *InteractionTypeRegistry { |
||||
return NewTypeRegistry[model.Interaction]() |
||||
} |
@ -0,0 +1,18 @@ |
||||
package app |
||||
|
||||
import "owl-blogs/app/repository" |
||||
|
||||
type WebmentionService struct { |
||||
InteractionRepository repository.InteractionRepository |
||||
EntryRepository repository.EntryRepository |
||||
} |
||||
|
||||
func NewWebmentionService( |
||||
interactionRepository repository.InteractionRepository, |
||||
entryRepository repository.EntryRepository, |
||||
) *WebmentionService { |
||||
return &WebmentionService{ |
||||
InteractionRepository: interactionRepository, |
||||
EntryRepository: entryRepository, |
||||
} |
||||
} |
@ -0,0 +1,53 @@ |
||||
package model |
||||
|
||||
import "time" |
||||
|
||||
type InteractionContent string |
||||
|
||||
// Interaction is a generic interface for all interactions with entries
|
||||
// These interactions can be:
|
||||
// - Webmention, Pingback, Trackback
|
||||
// - Likes, Comments on third party sites
|
||||
// - Comments on the site itself
|
||||
type Interaction interface { |
||||
ID() string |
||||
EntryID() string |
||||
Content() InteractionContent |
||||
CreatedAt() time.Time |
||||
MetaData() interface{} |
||||
|
||||
SetID(id string) |
||||
SetEntryID(entryID string) |
||||
SetCreatedAt(createdAt time.Time) |
||||
SetMetaData(metaData interface{}) |
||||
} |
||||
|
||||
type InteractionBase struct { |
||||
id string |
||||
entryID string |
||||
createdAt time.Time |
||||
} |
||||
|
||||
func (i *InteractionBase) ID() string { |
||||
return i.id |
||||
} |
||||
|
||||
func (i *InteractionBase) EntryID() string { |
||||
return i.entryID |
||||
} |
||||
|
||||
func (i *InteractionBase) CreatedAt() time.Time { |
||||
return i.createdAt |
||||
} |
||||
|
||||
func (i *InteractionBase) SetID(id string) { |
||||
i.id = id |
||||
} |
||||
|
||||
func (i *InteractionBase) SetEntryID(entryID string) { |
||||
i.entryID = entryID |
||||
} |
||||
|
||||
func (i *InteractionBase) SetCreatedAt(createdAt time.Time) { |
||||
i.createdAt = createdAt |
||||
} |
@ -0,0 +1,67 @@ |
||||
package infra |
||||
|
||||
import ( |
||||
"owl-blogs/app" |
||||
"owl-blogs/app/repository" |
||||
"owl-blogs/domain/model" |
||||
|
||||
"github.com/jmoiron/sqlx" |
||||
) |
||||
|
||||
type sqlInteraction struct { |
||||
Id string `db:"id"` |
||||
Type string `db:"type"` |
||||
EntryId string `db:"entry_id"` |
||||
CreatedAt string `db:"created_at"` |
||||
MetaData string `db:"meta_data"` |
||||
} |
||||
|
||||
type DefaultInteractionRepo struct { |
||||
typeRegistry *app.InteractionTypeRegistry |
||||
db *sqlx.DB |
||||
} |
||||
|
||||
func NewInteractionRepo(db Database, register *app.InteractionTypeRegistry) repository.InteractionRepository { |
||||
sqlxdb := db.Get() |
||||
|
||||
// Create tables if not exists
|
||||
sqlxdb.MustExec(` |
||||
CREATE TABLE IF NOT EXISTS interactions ( |
||||
id TEXT PRIMARY KEY, |
||||
type TEXT NOT NULL, |
||||
entry_id TEXT NOT NULL, |
||||
created_at DATETIME NOT NULL, |
||||
meta_data TEXT NOT NULL |
||||
); |
||||
`) |
||||
|
||||
return &DefaultInteractionRepo{ |
||||
db: sqlxdb, |
||||
typeRegistry: register, |
||||
} |
||||
} |
||||
|
||||
// Create implements repository.InteractionRepository.
|
||||
func (*DefaultInteractionRepo) Create(interaction model.Interaction) error { |
||||
panic("unimplemented") |
||||
} |
||||
|
||||
// Delete implements repository.InteractionRepository.
|
||||
func (*DefaultInteractionRepo) Delete(interaction model.Interaction) error { |
||||
panic("unimplemented") |
||||
} |
||||
|
||||
// FindAll implements repository.InteractionRepository.
|
||||
func (*DefaultInteractionRepo) FindAll(entryId string) ([]model.Interaction, error) { |
||||
panic("unimplemented") |
||||
} |
||||
|
||||
// FindById implements repository.InteractionRepository.
|
||||
func (*DefaultInteractionRepo) FindById(id string) (model.Interaction, error) { |
||||
panic("unimplemented") |
||||
} |
||||
|
||||
// Update implements repository.InteractionRepository.
|
||||
func (*DefaultInteractionRepo) Update(interaction model.Interaction) error { |
||||
panic("unimplemented") |
||||
} |
@ -0,0 +1,25 @@ |
||||
package interactions |
||||
|
||||
import "owl-blogs/domain/model" |
||||
|
||||
type Webmention struct { |
||||
model.InteractionBase |
||||
meta WebmentionInteractionMetaData |
||||
} |
||||
|
||||
type WebmentionInteractionMetaData struct { |
||||
Source string |
||||
Target string |
||||
} |
||||
|
||||
func (i *Webmention) Content() model.InteractionContent { |
||||
return model.InteractionContent(i.meta.Source) |
||||
} |
||||
|
||||
func (i *Webmention) MetaData() interface{} { |
||||
return &i.meta |
||||
} |
||||
|
||||
func (i *Webmention) SetMetaData(metaData interface{}) { |
||||
i.meta = *metaData.(*WebmentionInteractionMetaData) |
||||
} |
Loading…
Reference in new issue