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

@ -55,6 +55,58 @@ type apActor struct {
Url string 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 { type apActivity struct {
Id string Id string
Content string Content string
@ -66,8 +118,6 @@ type apActivity struct {
Attachment []apAttachment Attachment []apAttachment
To string To string
Url string Url string
Actor *string
Object *string
InReplyTo *string InReplyTo *string
} }
@ -85,6 +135,10 @@ func (self *anonAPAdapter) Init(data *chan models.SocketData, server, protocol,
func getBodyJson(res *http.Response) []byte { func getBodyJson(res *http.Response) []byte {
l := res.ContentLength l := res.ContentLength
// 4k is a reasonable max size if we get unknown length right?
if l < 0 {
l = 4096
}
jsonData := make([]byte, l) jsonData := make([]byte, l)
res.Body.Read(jsonData) res.Body.Read(jsonData)
return jsonData return jsonData
@ -196,6 +250,74 @@ func (self *anonAPAdapter) Fetch(etype string, ids []string) error {
} }
case "byAuthor": case "byAuthor":
// get outbox // 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 // for each item in outbox, check if it's a Create/Update or an Announce
// Create/Update you can directly deserialize the object // 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 // if it's an Announce, try to get the object and deserialize it, build a boost out of it