greatape/greataped/app/routes/inbox.go

152 wiersze
3.7 KiB
Go

package routes
import (
"activitypub"
"config"
. "contracts"
"db/repos"
"encoding/json"
"server/route"
"time"
"github.com/mitchellh/mapstructure"
)
var InboxPost = route.New(HttpPost, "/u/:username/inbox", func(x IContext) error {
username := x.Request().Params("username")
object := &activitypub.Object{}
if err := x.ParseBodyAndValidate(object); err != nil {
return x.BadRequest("Bad request")
}
user, err := repos.Default.FindUserByUsername(username)
if err != nil {
return err
}
keyId := x.StringUtil().Format("%s://%s/u/%s#main-key", config.PROTOCOL, config.DOMAIN, username)
switch object.Type {
case activitypub.TypeFollow:
{
activity := &activitypub.Activity{}
if err := x.ParseBodyAndValidate(activity); err != nil {
return x.BadRequest("Bad request")
}
url := activity.Actor
var inbox string
{
actor := &activitypub.Actor{}
if err := x.GetActivityStreamSigned(url, keyId, user.PrivateKey, nil, actor); err != nil {
return err
}
inbox = actor.Inbox
}
data, err := json.Marshal(activity)
if err != nil {
return err
}
follower := &repos.Follower{
Target: x.StringUtil().Format("%s://%s/u/%s", config.PROTOCOL, config.DOMAIN, username),
Handle: activity.Actor,
HandleInbox: inbox,
Activity: string(data),
Accepted: false,
}
if err := repos.Default.CreateFollower(follower); err != nil {
return x.Conflict(err)
}
if user.Access == repos.ACCESS_PUBLIC {
data, _ := json.Marshal(&activitypub.Activity{
Context: activitypub.ActivityStreams,
ID: x.StringUtil().Format("%s://%s/%s", config.PROTOCOL, config.DOMAIN, x.GUID()),
Type: activitypub.TypeAccept,
Actor: x.StringUtil().Format("%s://%s/u/%s", config.PROTOCOL, config.DOMAIN, username),
Object: activity,
})
if err := x.PostActivityStreamSigned(inbox, keyId, user.PrivateKey, data, nil); err != nil {
return err
}
if err := repos.Default.AcceptFollower(follower.ID); err != nil {
return err
}
}
return x.Nothing()
}
case activitypub.TypeCreate:
{
activity := &activitypub.Activity{}
if err := x.ParseBodyAndValidate(activity); err != nil {
return x.BadRequest("bad_request")
}
switch activity.Object.(map[string]interface{})["type"] {
case activitypub.TypeNote:
note := &activitypub.Note{}
if err := mapstructure.Decode(activity.Object, note); err != nil {
return x.InternalServerError("decode_failed")
}
message := &repos.IncomingActivity{
Timestamp: time.Now().UnixNano(),
From: note.AttributedTo,
To: note.To[0],
Guid: x.GUID(),
Content: note.Content,
}
if err := repos.Default.CreateIncomingActivity(message); err != nil {
return x.Conflict(err)
}
return x.Nothing()
default:
return x.BadRequest("")
}
}
default:
{
return x.BadRequest("")
}
}
})
var InboxGet = route.New(HttpGet, "/u/:username/inbox", func(x IContext) error {
username := x.Request().Params("username")
actor := x.StringUtil().Format("%s://%s/u/%s", config.PROTOCOL, config.DOMAIN, username)
id := x.StringUtil().Format("%s://%s/u/%s/inbox", config.PROTOCOL, config.DOMAIN, username)
messages, err := repos.Default.FindIncomingActivitiesForUser(actor)
if err != nil {
return err
}
items := []*activitypub.Activity{}
for _, message := range messages {
note := activitypub.NewPublicNote(message.From, message.Content)
activity := note.Wrap(username)
items = append(items, activity)
}
outbox := &activitypub.Outbox{
Context: activitypub.ActivityStreams,
ID: id,
Type: activitypub.TypeOrderedCollection,
TotalItems: len(items),
OrderedItems: items,
}
return x.Activity(outbox)
})