more thoughts
This commit is contained in:
parent
dce1006228
commit
836a54599b
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
||||
config.json
|
||||
/friend
|
||||
|
91
handlers.go
91
handlers.go
@ -7,38 +7,99 @@ import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
)
|
||||
|
||||
type APIError struct {
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// since we only have the single username to worry about, we just wrap everything up here
|
||||
func UserExistsMiddleware(user string, h http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
userID := chi.URLParam(r, "user")
|
||||
if userID != user {
|
||||
RespondJSON(w, APIError{Error: "account not found"}, http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
h.ServeHTTP(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
func RespondJSON(w http.ResponseWriter, content any, statuscode int) {
|
||||
b, err := json.Marshal(content)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(statuscode)
|
||||
w.Write(b)
|
||||
}
|
||||
|
||||
func WebFingerHandler(wf *Webfinger) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
requestedResource := r.URL.Query().Get("resource")
|
||||
res, err := wf.FingerResource(requestedResource)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte(`{"error": "account not found"}`))
|
||||
RespondJSON(w, APIError{Error: "account not found"}, http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
b, err := json.Marshal(res)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Write(b)
|
||||
RespondJSON(w, res, http.StatusOK)
|
||||
}
|
||||
}
|
||||
|
||||
func ProfileHandler(pp *ProfileProvider) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
userID := chi.URLParam(r, "user")
|
||||
res, err := pp.Get(userID)
|
||||
res, err := pp.Get()
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte(`{"error": "account not found"}`))
|
||||
RespondJSON(w, APIError{Error: "account not found"}, http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
b, err := json.Marshal(res)
|
||||
RespondJSON(w, res, http.StatusOK)
|
||||
}
|
||||
}
|
||||
|
||||
// client retrieves messages for user
|
||||
func GetInboxHandler(streams *InMemoryStreams) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
stream, err := streams.GetActivitiesToUser()
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
RespondJSON(w, APIError{Error: err.Error()}, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Write(b)
|
||||
RespondJSON(w, stream, http.StatusOK)
|
||||
}
|
||||
}
|
||||
|
||||
// handle incoming activities for user
|
||||
func PostInboxHandler(streams *InMemoryStreams) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
err := streams.AddActivityToUser()
|
||||
if err != nil {
|
||||
RespondJSON(w, APIError{Error: err.Error()}, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
RespondJSON(w, nil, http.StatusOK)
|
||||
}
|
||||
}
|
||||
|
||||
// other servers/clients read a user's activities
|
||||
func GetOutboxHandler(streams *InMemoryStreams) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
stream, err := streams.GetActivitiesFromUser()
|
||||
if err != nil {
|
||||
RespondJSON(w, APIError{Error: err.Error()}, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
RespondJSON(w, stream, http.StatusOK)
|
||||
}
|
||||
}
|
||||
|
||||
// client adds new activity for user
|
||||
func PostOutboxHandler(streams *InMemoryStreams) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
err := streams.AddActivityFromUser()
|
||||
if err != nil {
|
||||
RespondJSON(w, APIError{Error: err.Error()}, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
RespondJSON(w, nil, http.StatusOK)
|
||||
}
|
||||
}
|
||||
|
16
main.go
16
main.go
@ -8,18 +8,28 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
wf, err := NewWebfinger("dma", "hello.yetaga.in")
|
||||
// this will be configurable in the future obviously
|
||||
username := "dma"
|
||||
domain := "hello.yetaga.in"
|
||||
|
||||
wf, err := NewWebfinger(username, domain)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
pp, err := NewProfileProvider("hello.yetaga.in")
|
||||
pp, err := NewProfileProvider(username, domain)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
st := &InMemoryStreams{}
|
||||
|
||||
r := chi.NewRouter()
|
||||
r.Get("/.well-known/webfinger", WebFingerHandler(wf))
|
||||
r.Get("/users/{user}", ProfileHandler(pp))
|
||||
r.Get("/users/{user}", UserExistsMiddleware(username, ProfileHandler(pp)))
|
||||
r.Get("/users/{user}/inbox", UserExistsMiddleware(username, GetInboxHandler(st)))
|
||||
r.Post("/users/{user}/inbox", UserExistsMiddleware(username, PostInboxHandler(st)))
|
||||
r.Get("/users/{user}/outbox", UserExistsMiddleware(username, GetOutboxHandler(st)))
|
||||
r.Post("/users/{user}/outbox", UserExistsMiddleware(username, PostOutboxHandler(st)))
|
||||
r.Post("/inbox", PostInboxHandler(st)) // "shared" inbox
|
||||
|
||||
log.Println("listening on http://0.0.0.0:8008")
|
||||
err = http.ListenAndServe(":8008", r)
|
||||
|
14
profile.go
14
profile.go
@ -13,7 +13,7 @@ type Actor struct {
|
||||
PublicKey PublicKey `json:"publicKey,omitempty"`
|
||||
|
||||
Inbox string `json:"inbox,omitempty"`
|
||||
Outbox string `json:"outbo,omitempty"`
|
||||
Outbox string `json:"outbox,omitempty"`
|
||||
Followers string `json:"followers,omitempty"`
|
||||
Following string `json:"following,omitempty"`
|
||||
|
||||
@ -36,22 +36,24 @@ type PublicKey struct {
|
||||
}
|
||||
|
||||
type ProfileProvider struct {
|
||||
username string
|
||||
domain string
|
||||
}
|
||||
|
||||
func NewProfileProvider(domain string) (*ProfileProvider, error) {
|
||||
func NewProfileProvider(username, domain string) (*ProfileProvider, error) {
|
||||
return &ProfileProvider{
|
||||
username: username,
|
||||
domain: domain,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (pp *ProfileProvider) Get(userID string) (*Actor, error) {
|
||||
userRoot := fmt.Sprintf("https://%s/users/%s", pp.domain, userID)
|
||||
func (pp *ProfileProvider) Get() (*Actor, error) {
|
||||
userRoot := fmt.Sprintf("https://%s/users/%s", pp.domain, pp.username)
|
||||
return &Actor{
|
||||
ID: userRoot,
|
||||
Type: "Person",
|
||||
URL: fmt.Sprintf("https://%s/@%s", pp.domain, userID),
|
||||
Name: userID,
|
||||
URL: fmt.Sprintf("https://%s/@%s", pp.domain, pp.username),
|
||||
Name: pp.username,
|
||||
Inbox: userRoot + "/inbox",
|
||||
Outbox: userRoot + "/outbox",
|
||||
Followers: userRoot + "/followers",
|
||||
|
36
streams.go
36
streams.go
@ -1,6 +1,9 @@
|
||||
package main
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Stream struct {
|
||||
Context string `json:"@context"`
|
||||
@ -27,12 +30,33 @@ type Object struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type Streams struct{}
|
||||
type InMemoryStreams struct {
|
||||
}
|
||||
|
||||
func (s *Streams) Inbox()
|
||||
// view activities from other people directed to out user
|
||||
func (s *InMemoryStreams) GetActivitiesToUser() (*Stream, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (s *Streams) Outbox()
|
||||
// view activities created by our user
|
||||
func (s *InMemoryStreams) GetActivitiesFromUser() (*Stream, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (s *Streams) Followers()
|
||||
// insert activities from other people directed to our user
|
||||
func (s *InMemoryStreams) AddActivityToUser() error {
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (s *Streams) Followed()
|
||||
// insert activities from our user to be dispatched
|
||||
func (s *InMemoryStreams) AddActivityFromUser() error {
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (s *InMemoryStreams) Followers() (*Stream, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (s *InMemoryStreams) Followed() (*Stream, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user