ap

package
v1.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 21, 2026 License: AGPL-3.0 Imports: 18 Imported by: 0

Documentation

Overview

Package ap implements the ActivityPub protocol for the klistr bridge.

Index

Constants

View Source
const (
	PublicURI         = "https://www.w3.org/ns/activitystreams#Public"
	ActivityStreamsNS = "https://www.w3.org/ns/activitystreams"
	SecurityNS        = "https://w3id.org/security/v1"
	NostrProtocolURI  = "https://github.com/nostr-protocol/nostr"
)

Variables

View Source
var DefaultContext = []interface{}{
	ActivityStreamsNS,
	SecurityNS,
	map[string]interface{}{
		"Hashtag":       "as:Hashtag",
		"sensitive":     "as:sensitive",
		"schema":        "http://schema.org#",
		"PropertyValue": "schema:PropertyValue",
		"value":         "schema:value",
		"EmojiReact":    "http://joinmastodon.org/ns#EmojiReact",
		"Emoji":         "http://joinmastodon.org/ns#Emoji",
		"Zap":           "https://mostr.pub/ns#Zap",
		"proxyOf":       "https://mostr.pub/ns#proxyOf",
		"proxied":       "https://mostr.pub/ns#proxied",
		"protocol":      "https://mostr.pub/ns#protocol",
		"authoritative": "https://mostr.pub/ns#authoritative",
		"quoteUrl":      "as:quoteUrl",
	},
}

Context is the standard JSON-LD @context for ActivityPub objects.

Functions

func ActivityToMap

func ActivityToMap(v interface{}) map[string]interface{}

ActivityToMap converts an Activity struct to a generic map for sending.

func BuildAccept

func BuildAccept(followActivity map[string]interface{}, localActorID string) map[string]interface{}

BuildAccept creates an AP Accept activity for a Follow.

func BuildCreate

func BuildCreate(note *Note, localDomain string) map[string]interface{}

BuildCreate wraps a Note in a Create activity.

func BuildFollow

func BuildFollow(followerID, followedID string) map[string]interface{}

BuildFollow creates an AP Follow activity.

func BuildUpdate

func BuildUpdate(actor *Actor) map[string]interface{}

BuildUpdate wraps an Actor in an Update activity.

func DeliverActivity

func DeliverActivity(ctx context.Context, inbox string, activity map[string]interface{}, keyID string, privKey *rsa.PrivateKey) error

DeliverActivity sends an ActivityPub activity to a remote inbox using HTTP signatures.

func FetchObject

func FetchObject(ctx context.Context, rawURL string) (map[string]interface{}, error)

FetchObject fetches an ActivityPub object from a remote URL. Returns the raw JSON or an error. Results are cached.

func GetActorInbox

func GetActorInbox(ctx context.Context, actorID string) (string, error)

GetActorInbox returns the inbox URL for an AP actor.

func InvalidateCache

func InvalidateCache(rawURL string)

InvalidateCache removes a URL from the object cache.

func IsActor

func IsActor(obj map[string]interface{}) bool

IsActor returns true if the object type is an actor type.

func IsActorID

func IsActorID(s string) bool

IsActorID returns true if the ID looks like an AP actor URL.

func IsLocalID

func IsLocalID(apID, localDomain string) bool

IsLocalID returns true if the AP ID belongs to our local domain.

func IsProxyEvent

func IsProxyEvent(event *nostr.Event) bool

IsProxyEvent returns true if this event was created by the bridge (has a proxy tag).

func IsRepost

func IsRepost(event *nostr.Event) bool

IsRepost returns true if a kind-1 event is a pure repost (no content, has quote tag).

func NostrDate

func NostrDate(ts nostr.Timestamp) string

NostrDate formats a Unix timestamp as an ISO 8601 string.

func ParseNostrDate

func ParseNostrDate(s string) nostr.Timestamp

ParseNostrDate parses an ISO 8601 date string into a Unix timestamp.

func ToEmojiReact

func ToEmojiReact(event *nostr.Event, tc *TransmuteContext) map[string]interface{}

ToEmojiReact converts a kind-7 emoji reaction to an AP EmojiReact.

func VerifySignature

func VerifySignature(req *http.Request) (string, error)

VerifySignature verifies an incoming HTTP signature. Returns the keyID if valid, or an error.

func WithContext

func WithContext(v interface{}) map[string]interface{}

WithContext wraps an object with the default AP @context.

Types

type APHandler

type APHandler struct {
	LocalDomain   string
	LocalActorURL string // full URL of the local AP actor
	Signer        interface {
		SignAsUser(event *nostr.Event) error
		Sign(event *nostr.Event, apID string) error
		PublicKey(apID string) (string, error)
		LocalPublicKey() string
	}
	Publisher interface {
		Publish(ctx context.Context, event *nostr.Event) error
	}
	Store interface {
		AddObject(apID, nostrID string) error
		AddFollow(followerID, followedID string) error
		GetNostrIDForObject(apID string) (string, bool)
	}
	Federator  *Federator
	NostrRelay string
}

APHandler handles incoming ActivityPub activities and converts them to Nostr events.

func (*APHandler) HandleActivity

func (h *APHandler) HandleActivity(ctx context.Context, raw json.RawMessage) error

HandleActivity processes an incoming ActivityPub activity.

type Activity

type Activity struct {
	Context   interface{} `json:"@context,omitempty"`
	ID        string      `json:"id"`
	Type      string      `json:"type"`
	Actor     string      `json:"actor"`
	Object    interface{} `json:"object"`
	To        []string    `json:"to,omitempty"`
	CC        []string    `json:"cc,omitempty"`
	Published string      `json:"published,omitempty"`
	ProxyOf   []Proxy     `json:"proxyOf,omitempty"`
}

Activity is a generic ActivityPub activity.

func ToAnnounce

func ToAnnounce(event *nostr.Event, tc *TransmuteContext) *Activity

ToAnnounce converts a kind-1 quote post or kind-6 repost to an AP Announce. Returns nil if no quote/repost target is found.

func ToDelete

func ToDelete(event *nostr.Event, tc *TransmuteContext) *Activity

ToDelete converts a kind-5 deletion event to an AP Delete.

func ToLike

func ToLike(event *nostr.Event, tc *TransmuteContext) *Activity

ToLike converts a kind-7 "+" reaction to an AP Like.

type Actor

type Actor struct {
	Context           interface{}     `json:"@context,omitempty"`
	ID                string          `json:"id"`
	Type              string          `json:"type"`
	Name              string          `json:"name,omitempty"`
	PreferredUsername string          `json:"preferredUsername"`
	Summary           string          `json:"summary,omitempty"`
	Inbox             string          `json:"inbox"`
	Outbox            string          `json:"outbox,omitempty"`
	Followers         string          `json:"followers,omitempty"`
	Following         string          `json:"following,omitempty"`
	PublicKey         *PublicKey      `json:"publicKey,omitempty"`
	Icon              *Image          `json:"icon,omitempty"`
	Image             *Image          `json:"image,omitempty"`
	Attachment        []PropertyValue `json:"attachment,omitempty"`
	Tag               []interface{}   `json:"tag,omitempty"`
	URL               string          `json:"url,omitempty"`
	Endpoints         *Endpoints      `json:"endpoints,omitempty"`
	ProxyOf           []Proxy         `json:"proxyOf,omitempty"`
}

Actor represents an ActivityPub actor (Person, Service, etc.).

func FetchActor

func FetchActor(ctx context.Context, actorURL string) (*Actor, error)

FetchActor fetches and parses an AP Actor object.

func ToActor

func ToActor(event *nostr.Event, tc *TransmuteContext) *Actor

ToActor converts a Nostr kind-0 metadata event to an AP Actor.

type Attachment

type Attachment struct {
	Type      string `json:"type"`
	URL       string `json:"url"`
	MediaType string `json:"mediaType,omitempty"`
	Blurhash  string `json:"blurhash,omitempty"`
	Width     int    `json:"width,omitempty"`
	Height    int    `json:"height,omitempty"`
}

Attachment represents media attached to a Note.

type Emoji

type Emoji struct {
	Type string `json:"type"`
	Name string `json:"name"`
	Icon *Image `json:"icon,omitempty"`
}

Emoji is a custom emoji tag.

type Endpoints

type Endpoints struct {
	SharedInbox string `json:"sharedInbox,omitempty"`
}

Endpoints holds shared inbox and other endpoints.

type Federator

type Federator struct {
	LocalDomain string
	KeyID       string // e.g. "https://example.com/actor#main-key"
	PrivateKey  *rsa.PrivateKey
	// GetFollowers returns AP follower IDs for a local AP actor URL.
	GetFollowers func(actorURL string) ([]string, error)
}

Federator handles outbound federation of AP activities.

func (*Federator) Federate

func (f *Federator) Federate(ctx context.Context, activity map[string]interface{})

Federate distributes an activity to all relevant inboxes. It resolves follower lists, fetches actor inboxes, and delivers via HTTP.

type Generator

type Generator struct {
	Type string `json:"type"`
	Name string `json:"name"`
	URL  string `json:"url,omitempty"`
}

Generator describes the application that created an object.

type Hashtag

type Hashtag struct {
	Type string `json:"type"`
	Href string `json:"href"`
	Name string `json:"name"`
}

Hashtag represents a hashtag tag on a Note.

type Image

type Image struct {
	Type string `json:"type"`
	URL  string `json:"url"`
}

Image represents an ActivityPub Image object.

type IncomingActivity

type IncomingActivity struct {
	Context   interface{}     `json:"@context,omitempty"`
	ID        string          `json:"id"`
	Type      string          `json:"type"`
	Actor     string          `json:"actor"`
	Object    json.RawMessage `json:"object"`
	To        []string        `json:"to,omitempty"`
	CC        []string        `json:"cc,omitempty"`
	Published string          `json:"published,omitempty"`
	Content   string          `json:"content,omitempty"`
}

IncomingActivity is used for parsing incoming activities where the object might be a string reference or an embedded object.

type KeyPair

type KeyPair struct {
	Private   *rsa.PrivateKey
	Public    *rsa.PublicKey
	PublicPEM string
}

KeyPair holds the RSA key pair used for ActivityPub HTTP signatures.

func LoadOrGenerateKeyPair

func LoadOrGenerateKeyPair(privatePath, publicPath string) (*KeyPair, error)

LoadOrGenerateKeyPair loads an RSA key pair from PEM files, or generates a new one if the files do not exist. This means zero-setup for new installs.

type Mention

type Mention struct {
	Type string `json:"type"`
	Href string `json:"href"`
	Name string `json:"name,omitempty"`
}

Mention is a tag pointing to another actor.

type NodeInfo

type NodeInfo struct {
	Version           string           `json:"version"`
	Software          NodeInfoSoftware `json:"software"`
	Protocols         []string         `json:"protocols"`
	Usage             NodeInfoUsage    `json:"usage"`
	OpenRegistrations bool             `json:"openRegistrations"`
}

NodeInfo structures.

type NodeInfoSoftware

type NodeInfoSoftware struct {
	Name    string `json:"name"`
	Version string `json:"version"`
}

type NodeInfoUsage

type NodeInfoUsage struct {
	Users NodeInfoUsers `json:"users"`
}

type NodeInfoUsers

type NodeInfoUsers struct {
	Total          int `json:"total"`
	ActiveMonth    int `json:"activeMonth"`
	ActiveHalfYear int `json:"activeHalfYear"`
}

type Note

type Note struct {
	Context      interface{}   `json:"@context,omitempty"`
	ID           string        `json:"id"`
	Type         string        `json:"type"`
	AttributedTo string        `json:"attributedTo"`
	Content      string        `json:"content"`
	Published    string        `json:"published,omitempty"`
	To           []string      `json:"to,omitempty"`
	CC           []string      `json:"cc,omitempty"`
	Tag          []interface{} `json:"tag,omitempty"`
	Attachment   []Attachment  `json:"attachment,omitempty"`
	InReplyTo    string        `json:"inReplyTo,omitempty"`
	QuoteURL     string        `json:"quoteUrl,omitempty"`
	Sensitive    bool          `json:"sensitive,omitempty"`
	Summary      string        `json:"summary,omitempty"`
	Generator    *Generator    `json:"generator,omitempty"`
	ProxyOf      []Proxy       `json:"proxyOf,omitempty"`
}

Note represents an ActivityPub Note.

func ToNote

func ToNote(event *nostr.Event, tc *TransmuteContext) *Note

ToNote converts a Nostr kind-1 text note to an AP Note.

type OrderedCollection

type OrderedCollection struct {
	Context      interface{} `json:"@context"`
	ID           string      `json:"id"`
	Type         string      `json:"type"`
	TotalItems   int         `json:"totalItems"`
	OrderedItems interface{} `json:"orderedItems"`
}

OrderedCollection is a paginated AP collection.

type PropertyValue

type PropertyValue struct {
	Type  string `json:"type"`
	Name  string `json:"name"`
	Value string `json:"value"`
}

PropertyValue is a key-value pair, used for profile fields.

type Proxy

type Proxy struct {
	Protocol      string `json:"protocol"`
	Proxied       string `json:"proxied"`
	Authoritative bool   `json:"authoritative,omitempty"`
}

Proxy links an AP object back to its Nostr origin.

type PublicKey

type PublicKey struct {
	ID           string `json:"id"`
	Owner        string `json:"owner"`
	PublicKeyPem string `json:"publicKeyPem"`
}

PublicKey represents an RSA public key attached to an actor.

type TransmuteContext

type TransmuteContext struct {
	LocalDomain      string
	LocalActorURL    string // full URL of the local AP actor, e.g. "https://domain.com/users/alice"
	PublicKeyPem     string
	GetAPIDForObject func(nostrID string) (string, bool)
}

TransmuteContext provides dependencies for Nostr→AP conversion.

type WebFingerLink struct {
	Rel      string `json:"rel"`
	Type     string `json:"type,omitempty"`
	Href     string `json:"href,omitempty"`
	Template string `json:"template,omitempty"`
}

type WebFingerResponse

type WebFingerResponse struct {
	Subject string          `json:"subject"`
	Aliases []string        `json:"aliases,omitempty"`
	Links   []WebFingerLink `json:"links"`
}

WebFinger response structures.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL
⌂ 换网址