diff --git a/adapter/anonAp.go b/adapter/anonAp.go new file mode 100644 index 0000000..f27c27c --- /dev/null +++ b/adapter/anonAp.go @@ -0,0 +1,138 @@ +package adapter + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "os" + "time" + + "forge.lightcrystal.systems/lightcrystal/underbbs/models" +) + +type anonAPAdapter struct { + data *chan models.SocketData + server string + client http.Client +} + +type apLink struct { + Href string + Rel string + Type string +} + +type apIcon struct { + MediaType string + Type string + Url string +} + +type apActor struct { + Icon apIcon + Id string + Name string + PreferredUsername string + Summary string + Url string +} + +type webFinger struct { + Links []apLink +} + +func (self *anonAPAdapter) Init(data *chan models.SocketData, server string) error { + self.data = data + self.server = server + return nil +} + +func getBodyJson(res *http.Response) []byte { + l := res.ContentLength + jsonData := make([]byte, l) + res.Body.Read(jsonData) + return jsonData +} + +func (self *anonAPAdapter) makeApRequest(method, url string, data io.Reader) (*http.Response, error) { + req, err := http.NewRequest(method, url, data) + if err != nil { + return nil, err + } + + req.Header.Set("Accept", "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"") + return self.client.Do(req) +} + +func toMsg(activity map[string]interface{}) *models.Message { + return nil +} + +func (self *anonAPAdapter) send(data models.SocketData) { + if self.data != nil { + *self.data <- data + } else { + fmt.Fprintln(os.Stderr, string(data.ToDatagram())) + } +} + +func toAuthor(actor apActor) *models.Author { + curtime := time.Now().UnixMilli() + self := &models.Author{ + Datagram: models.Datagram{ + Id: actor.Id, + Uri: actor.Url, + Type: "author", + Created: curtime, + Updated: &curtime, + }, + Name: actor.PreferredUsername, + ProfileData: actor.Summary, + ProfilePic: actor.Icon.Url, + } + return self +} + +func (self *anonAPAdapter) Fetch(etype string, ids []string) error { + for _, id := range ids { + switch etype { + case "author": // webfinger lookup on id + 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, nil) + if err != nil { + return err + } + authorData := getBodyJson(res) + actor := apActor{} + json.Unmarshal(authorData, &actor) + author := toAuthor(actor) + if author != nil { + self.send(author) + } + case "byAuthor": + case "message": + case "children": + case "convoy": + default: + break + } + } + return nil +} diff --git a/adapter/honk.go b/adapter/honk.go index d8f9f35..b2e8b28 100644 --- a/adapter/honk.go +++ b/adapter/honk.go @@ -19,6 +19,10 @@ type HonkAdapter struct { token string } +func (self *HonkAdapter) isAnonymous() bool { + return self.token == "" +} + func (self *HonkAdapter) send(data SocketData) { if self.data != nil { *self.data <- data @@ -36,8 +40,13 @@ func (self *HonkAdapter) Init(settings Settings, data *chan SocketData) error { parts := strings.Split(*settings.Handle, "@") self.username = parts[1] self.server = "https://" + parts[2] - self.password = *settings.Password self.nickname = settings.Nickname + + if settings.Password == nil { + // we're anonymous! + return nil + } + self.password = *settings.Password // store all the settings // make a request to get the token r, err := http.PostForm(self.server+"/dologin", url.Values{ @@ -65,6 +74,34 @@ func (self *HonkAdapter) Subscribe(string) []error { } func (self *HonkAdapter) Fetch(etype string, ids []string) error { + // if we're anonymous, we can fetch the data as raw AP + // KISS + if self.isAnonymous() { + aaa := anonAPAdapter{} + aaa.Init(self.data, self.server) + return aaa.Fetch(etype, ids) + } + + for _, _ = range ids { + switch etype { + case "byAuthor": + // gethonks + case "message": + // use honk-canonical XID + case "author": + if self.isAnonymous() { + // if we are using @user@server, translate it to https://server/u/user + } else { + // otherwise, use the URL as such + } + case "children": + // use honk-canonical XID + case "convoy": + if self.isAnonymous() { + } else { + } + } + } return nil } diff --git a/go.mod b/go.mod index 812a4ba..1773968 100644 --- a/go.mod +++ b/go.mod @@ -3,11 +3,11 @@ module forge.lightcrystal.systems/lightcrystal/underbbs go 1.22.0 require ( + forge.lightcrystal.systems/nilix/quartzgun v0.4.2 github.com/McKael/madon v2.3.0+incompatible github.com/nbd-wtf/go-nostr v0.31.2 github.com/yitsushi/go-misskey v1.1.6 golang.org/x/time v0.5.0 - hacklab.nilfm.cc/quartzgun v0.3.2 nhooyr.io/websocket v1.8.11 ) diff --git a/go.sum b/go.sum index 6c0b038..f9614ba 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +forge.lightcrystal.systems/nilix/quartzgun v0.4.2 h1:S4ae33noQ+ilMvAKNh50KfwLb+SQqeXKZSoWMRsjEoM= +forge.lightcrystal.systems/nilix/quartzgun v0.4.2/go.mod h1:hIXDh7AKtAVekjR6RIFW94d/c7cCQbyh8mzaTmP/pM8= github.com/McKael/madon v2.3.0+incompatible h1:xMUA+Fy4saDV+8tN3MMnwJUoYWC//5Fy8LeOqJsRNIM= github.com/McKael/madon v2.3.0+incompatible/go.mod h1:+issnvJjN1rpjAHZwXRB/x30uHh/NoQR7QaojJK/lSI= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= @@ -63,7 +65,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -hacklab.nilfm.cc/quartzgun v0.3.2 h1:PmRFZ/IgsXVWyNn1iOsQ/ZeMnOQIQy0PzFakhXBdZoU= -hacklab.nilfm.cc/quartzgun v0.3.2/go.mod h1:P6qK4HB0CD/xfyRq8wdEGevAPFDDmv0KCaESSvv93LU= nhooyr.io/websocket v1.8.11 h1:f/qXNc2/3DpoSZkHt1DQu6rj4zGC8JmkkLkWss0MgN0= nhooyr.io/websocket v1.8.11/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= diff --git a/server/api.go b/server/api.go index 57d1b03..b18e829 100644 --- a/server/api.go +++ b/server/api.go @@ -6,9 +6,9 @@ import ( "fmt" "forge.lightcrystal.systems/lightcrystal/underbbs/adapter" "forge.lightcrystal.systems/lightcrystal/underbbs/models" - "hacklab.nilfm.cc/quartzgun/renderer" - "hacklab.nilfm.cc/quartzgun/router" - "hacklab.nilfm.cc/quartzgun/util" + "forge.lightcrystal.systems/nilix/quartzgun/renderer" + "forge.lightcrystal.systems/nilix/quartzgun/router" + "forge.lightcrystal.systems/nilix/quartzgun/util" "html/template" "log" "net/http" diff --git a/server/server.go b/server/server.go index 3d88cde..9cb384a 100644 --- a/server/server.go +++ b/server/server.go @@ -5,9 +5,9 @@ import ( "errors" "forge.lightcrystal.systems/lightcrystal/underbbs/adapter" "forge.lightcrystal.systems/lightcrystal/underbbs/models" + "forge.lightcrystal.systems/nilix/quartzgun/cookie" + "forge.lightcrystal.systems/nilix/quartzgun/renderer" "golang.org/x/time/rate" - "hacklab.nilfm.cc/quartzgun/cookie" - "hacklab.nilfm.cc/quartzgun/renderer" "io/ioutil" "log" "net/http"