aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README7
-rw-r--r--README.md26
-rw-r--r--TODO2
-rw-r--r--http/server.go2
-rw-r--r--main.go4
-rw-r--r--resources/outbox.go21
-rw-r--r--resources/profile.go9
-rwxr-xr-xsample-cgi-handler.sh13
-rw-r--r--urls/urls.go34
9 files changed, 89 insertions, 29 deletions
diff --git a/README b/README
deleted file mode 100644
index 2b1f7db..0000000
--- a/README
+++ /dev/null
@@ -1,7 +0,0 @@
-# Communique
-
-Communique aims to be an activitypub platform that abstracts outboxes/inboxes away from
-handler implementations.
-
-1) handlers are defined in a config file
-2) these are read into the registry which allows lookup by name or by fqdn \ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..3c2dcd0
--- /dev/null
+++ b/README.md
@@ -0,0 +1,26 @@
+# Communique
+
+Communique aims to be an activitypub platform that abstracts outboxes/inboxes away from
+handler implementations.
+
+1) handlers are defined in a config file
+2) these are read into the registry which allows lookup by name or by fqdn
+
+
+# CGI
+
+Communique uses CGI as the API between itself and your scripts. These scripts are only run **internally** and are never executed from a TCP request.
+
+## Response API
+
+Your CGI script MUST emit a valid CGI response.
+
+Your CGI script reponse MUST be of content type `application/activity+json`.
+
+Your CGI script reponse MUST be an `OrderedCollection` of ActivityStream `Object`s.
+
+See `sample-cgi-handler.sh` for an example
+
+## Processing
+
+Communique will iterate through this collection of objects and add them to the outbox for the handler for that script, if they have not been posted in the last hour. **(TODO make the dedupe window configurable)** \ No newline at end of file
diff --git a/TODO b/TODO
index 0cf7355..8c3610f 100644
--- a/TODO
+++ b/TODO
@@ -1,5 +1,5 @@
* CGI response API
- * Array of activitystream Note's?
+ *DONE Array of activitystream Note's?
* dedup
* outbox pagination
* badger GC https://dgraph.io/docs/badger/get-started/#garbage-collection
diff --git a/http/server.go b/http/server.go
index 5d0a689..b3d3c9b 100644
--- a/http/server.go
+++ b/http/server.go
@@ -39,6 +39,7 @@ func (s *Server) Start(zapWriter io.Writer) {
actorParam := c.Param("actor")
resource, _ := s.registry.Profile(actorParam)
if resource != nil {
+ c.Writer.Header().Set("Content-Type", "application/activity+json")
c.JSON(http.StatusOK, resource)
} else {
c.JSON(http.StatusNotFound, nil)
@@ -68,6 +69,7 @@ func (s *Server) Start(zapWriter io.Writer) {
resource, _ = s.registry.Outbox(actorParam)
}
if resource != nil {
+ c.Writer.Header().Set("Content-Type", "application/activity+json")
c.JSON(http.StatusOK, resource)
} else {
c.JSON(http.StatusNotFound, nil)
diff --git a/main.go b/main.go
index fe2bb30..aa92f9f 100644
--- a/main.go
+++ b/main.go
@@ -30,7 +30,9 @@ func main() {
log.Debugf("Loaded TOML Config: %+v", cfg)
// DB
- db, err := badger.Open(badger.DefaultOptions(cfg.DbPath))
+ dbOpts := badger.DefaultOptions(cfg.DbPath)
+ // dbOpts.Logger = log // TODO needs to adapt Warningf to Warnf
+ db, err := badger.Open(dbOpts)
if err != nil {
log.Fatal(err)
}
diff --git a/resources/outbox.go b/resources/outbox.go
index 4dd022b..93bed92 100644
--- a/resources/outbox.go
+++ b/resources/outbox.go
@@ -1,23 +1,20 @@
package resources
import (
- "fmt"
- "net/url"
- "path"
-
+ "git.capotej.com/capotej/communique/urls"
"github.com/dgraph-io/badger/v3"
"github.com/go-fed/activity/streams"
)
func RenderOutboxPage(name, domain string, db *badger.DB) (map[string]interface{}, error) {
- id, err := url.Parse(path.Join("https://", domain, "actors", name, "outbox") + "?page=true")
+ id, err := urls.UrlOutboxPage(name, domain)
if err != nil {
- return nil, fmt.Errorf("could not partse url: %w", err)
+ return nil, err
}
- partOf, err := url.Parse(path.Join("https://", domain, "actors", name, "outbox"))
+ partOf, err := urls.UrlOutbox(name, domain)
if err != nil {
- return nil, fmt.Errorf("could not partse url: %w", err)
+ return nil, err
}
oc := streams.NewActivityStreamsOrderedCollectionPage()
@@ -69,15 +66,15 @@ func RenderOutboxPage(name, domain string, db *badger.DB) (map[string]interface{
}
func RenderOutbox(name, domain string, db *badger.DB) (map[string]interface{}, error) {
- id, err := url.Parse(path.Join("https://", domain, "actors", name, "outbox") + "?page=true")
+ id, err := urls.UrlOutbox(name, domain)
if err != nil {
- return nil, fmt.Errorf("could not partse url: %w", err)
+ return nil, err
}
- first, err := url.Parse(path.Join("https://", domain, "actors", name, "outbox") + "?page=true")
+ first, err := urls.UrlOutboxPage(name, domain)
if err != nil {
- return nil, fmt.Errorf("could not partse url: %w", err)
+ return nil, err
}
oc := streams.NewActivityStreamsOrderedCollection()
diff --git a/resources/profile.go b/resources/profile.go
index b62a9c5..971b11c 100644
--- a/resources/profile.go
+++ b/resources/profile.go
@@ -1,17 +1,14 @@
package resources
import (
- "fmt"
- "net/url"
- "path"
-
+ "git.capotej.com/capotej/communique/urls"
"github.com/go-fed/activity/streams"
)
func RenderProfile(name, domain string) (map[string]interface{}, error) {
- u, err := url.Parse(path.Join("https://", domain, "actors", name, "inbox"))
+ u, err := urls.UrlInbox(name, domain)
if err != nil {
- return nil, fmt.Errorf("could not partse url: %w", err)
+ return nil, err
}
inb := streams.NewActivityStreamsInboxProperty()
diff --git a/sample-cgi-handler.sh b/sample-cgi-handler.sh
index afd4ada..7cef511 100755
--- a/sample-cgi-handler.sh
+++ b/sample-cgi-handler.sh
@@ -1,5 +1,14 @@
#!/bin/bash
-echo "Content-type: text/plain"
+echo "Content-type: application/activity+json"
echo ""
-echo "This is a random value from bash: $RANDOM on $(date)"
+echo '{
+ "@context": "https://www.w3.org/ns/activitystreams",
+ "type": "OrderedCollection",
+ "totalItems": 1,
+ "items": [
+ {
+ "type": "Note",
+ "content": "hi"
+ },
+ ]}'
exit 0
diff --git a/urls/urls.go b/urls/urls.go
new file mode 100644
index 0000000..5f563a7
--- /dev/null
+++ b/urls/urls.go
@@ -0,0 +1,34 @@
+package urls
+
+import (
+ "fmt"
+ "net/url"
+ "path"
+)
+
+func UrlInbox(name, domain string) (*url.URL, error) {
+ u, err := url.Parse(path.Join("https://", domain, "actors", name, "inbox"))
+ if err != nil {
+ return nil, fmt.Errorf("could not build inbox url: %w", err)
+ }
+ return u, nil
+}
+
+func UrlOutbox(name, domain string) (*url.URL, error) {
+ u, err := url.Parse(path.Join("https://", domain, "actors", name, "outbox"))
+ if err != nil {
+ return nil, fmt.Errorf("could not build outbox url: %w", err)
+ }
+ return u, nil
+}
+
+func UrlOutboxPage(name, domain string) (*url.URL, error) {
+ u, err := UrlOutbox(name, domain)
+ if err != nil {
+ return nil, fmt.Errorf("could not build outbox page url: %w", err)
+ }
+ q := u.Query()
+ q.Set("page", "true")
+ u.RawQuery = q.Encode()
+ return u, nil
+}