basically finish anonAp adapter, it can fetch a user's profile, their outbox, or an individual note

This commit is contained in:
Iris Lightshard 2024-12-01 09:02:12 -07:00
parent 194a5aed48
commit a2017e3de8
Signed by: Iris Lightshard
GPG key ID: 688407174966CAF3

View file

@ -13,9 +13,9 @@ import (
)
type anonAPAdapter struct {
data *chan models.SocketData
server string
client http.Client
data *chan models.SocketData
server string
client http.Client
protocol string
nickname string
}
@ -27,17 +27,17 @@ type apLink struct {
}
type apAttachment struct {
MediaType string
Type string
Name string
Summary string
Url string
MediaType string
Type string
Name string
Summary string
Url string
}
type apTag struct {
Href string
Name string
Type string
Href string
Name string
Type string
}
type apIcon struct {
@ -55,20 +55,70 @@ type apActor struct {
Url string
}
type apOutbox struct {
OrderedItems []interface{} `json:"-"`
RawOrderedItems []json.RawMessage `json:"OrderedItems"`
}
func (self *apOutbox) UnmarshalJSON(b []byte) error {
type obInternal apOutbox
err := json.Unmarshal(b, (*obInternal)(self))
if err != nil {
return err
}
for _, raw := range self.RawOrderedItems {
var i apOutboxItem
err := json.Unmarshal(raw, &i)
var x interface{}
switch i.Type {
case "Create":
fallthrough
case "Update":
x = &apOutboxItemCreateUpdate{}
case "Announce":
x = &apOutboxItemAnnounce{}
}
err = json.Unmarshal(raw, &x)
if err != nil {
return err
}
self.OrderedItems = append(self.OrderedItems, x)
}
return nil
}
type apOutboxItem struct {
Actor string
Id string
Type string
To string
Published string
}
type apOutboxItemCreateUpdate struct {
Object apActivity
apOutboxItem
}
type apOutboxItemAnnounce struct {
Object string
apOutboxItem
}
type apActivity struct {
Id string
Content string
AttributedTo string
Context string
Conversation string
Published string
Tag []apTag
Attachment []apAttachment
To string
Url string
Actor *string
Object *string
InReplyTo *string
Id string
Content string
AttributedTo string
Context string
Conversation string
Published string
Tag []apTag
Attachment []apAttachment
To string
Url string
InReplyTo *string
}
type webFinger struct {
@ -85,6 +135,10 @@ func (self *anonAPAdapter) Init(data *chan models.SocketData, server, protocol,
func getBodyJson(res *http.Response) []byte {
l := res.ContentLength
// 4k is a reasonable max size if we get unknown length right?
if l < 0 {
l = 4096
}
jsonData := make([]byte, l)
res.Body.Read(jsonData)
return jsonData
@ -101,36 +155,36 @@ func (self *anonAPAdapter) makeApRequest(method, url string, data io.Reader) (*h
}
func (self *anonAPAdapter) toMsg(activity apActivity) *models.Message {
t, err := time.Parse(time.RFC3339, activity.Published)
if err != nil {
t = time.Now()
}
vis := strings.Split(activity.To, "#")
if len(vis) > 1 {
activity.To = vis[1]
}
m := &models.Message{
Datagram: models.Datagram{
Id: activity.Id,
Uri: activity.Url,
Type: "message",
Created: t.UnixMilli(),
Updated: nil,
Protocol: self.protocol,
Adapter: self.nickname,
},
Author: activity.AttributedTo,
Content: activity.Content,
ReplyTo: activity.InReplyTo,
Visibility: activity.To,
}
t, err := time.Parse(time.RFC3339, activity.Published)
if err != nil {
t = time.Now()
}
vis := strings.Split(activity.To, "#")
if len(vis) > 1 {
activity.To = vis[1]
}
m := &models.Message{
Datagram: models.Datagram{
Id: activity.Id,
Uri: activity.Url,
Type: "message",
Created: t.UnixMilli(),
Updated: nil,
Protocol: self.protocol,
Adapter: self.nickname,
},
Author: activity.AttributedTo,
Content: activity.Content,
ReplyTo: activity.InReplyTo,
Visibility: activity.To,
}
for _, a := range activity.Attachment {
m.Attachments = append(m.Attachments, models.Attachment{
Src: a.Url,
Desc: a.Summary,
})
}
for _, a := range activity.Attachment {
m.Attachments = append(m.Attachments, models.Attachment{
Src: a.Url,
Desc: a.Summary,
})
}
return m
}
@ -147,13 +201,13 @@ func (self *anonAPAdapter) toAuthor(actor apActor) *models.Author {
curtime := time.Now().UnixMilli()
a := &models.Author{
Datagram: models.Datagram{
Id: actor.Id,
Uri: actor.Url,
Type: "author",
Created: curtime,
Updated: &curtime,
Id: actor.Id,
Uri: actor.Url,
Type: "author",
Created: curtime,
Updated: &curtime,
Protocol: self.protocol,
Adapter: self.nickname,
Adapter: self.nickname,
},
Name: actor.PreferredUsername,
ProfileData: actor.Summary,
@ -195,22 +249,90 @@ func (self *anonAPAdapter) Fetch(etype string, ids []string) error {
self.send(author)
}
case "byAuthor":
// get outbox
// for each item in outbox, check if it's a Create/Update or an Announce
// Create/Update you can directly deserialize the object
// if it's an Announce, try to get the object and deserialize it, build a boost out of it
// get outbox
if string([]byte{id[0]}) == "@" {
id = id[1:]
}
res, err := http.Get(self.server + "/.well-known/webfinger?resource=acct:" + id)
if err != nil {
return err
}
data := getBodyJson(res)
wf := webFinger{}
json.Unmarshal(data, &wf)
var profile string
for _, l := range wf.Links {
if l.Rel == "self" {
profile = l.Href
break
}
}
res, err = self.makeApRequest("GET", profile+"/outbox", nil)
if err != nil {
return err
}
obData := getBodyJson(res)
ob := apOutbox{}
ob.UnmarshalJSON(obData)
for _, i := range ob.OrderedItems {
switch a := i.(type) {
case *apOutboxItemCreateUpdate:
msg := self.toMsg(a.Object)
if msg != nil {
self.send(msg)
}
case *apOutboxItemAnnounce:
res, err = self.makeApRequest("GET", a.Object, nil)
if err != nil {
return err
}
fmt.Println(a.Object)
activityData := getBodyJson(res)
activity := apActivity{}
json.Unmarshal(activityData, &activity)
ogMsg := self.toMsg(activity)
if ogMsg != nil {
self.send(ogMsg)
}
t, err := time.Parse(time.RFC3339, a.Published)
if err != nil {
t = time.Now()
}
vis := strings.Split(a.To, "#")
if len(vis) > 1 {
a.To = vis[1]
}
boostMsg := models.Message{
Datagram: models.Datagram{
Id: a.Id,
Uri: a.Id,
Protocol: self.protocol,
Adapter: self.nickname,
Type: "message",
Created: t.UnixMilli(),
},
Author: a.Actor,
RenoteId: &ogMsg.Id,
Visibility: a.To,
}
self.send(boostMsg)
}
}
// for each item in outbox, check if it's a Create/Update or an Announce
// Create/Update you can directly deserialize the object
// if it's an Announce, try to get the object and deserialize it, build a boost out of it
case "message":
res, err := self.makeApRequest("GET", id, nil)
if err != nil {
return err
}
activityData := getBodyJson(res)
activity := apActivity{}
json.Unmarshal(activityData, &activity)
message := self.toMsg(activity)
if message != nil {
self.send(message)
}
res, err := self.makeApRequest("GET", id, nil)
if err != nil {
return err
}
activityData := getBodyJson(res)
activity := apActivity{}
json.Unmarshal(activityData, &activity)
message := self.toMsg(activity)
if message != nil {
self.send(message)
}
case "children":
case "convoy":
default: