box

package module
v0.0.0-...-1eaf401 Latest Latest
Warning

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

Go to latest
Published: Oct 1, 2026 License: MIT Imports: 43 Imported by: 1

README

CLI helper tool for using client to server ActivityPub

This CLI tool is used to post to ONI and FedBOX services, and should be compatible with any others based on the GoActivityPub library.

It supports OAuth2 authorization.

Getting the source

$ git clone https://git.sr.ht/~mariusor/box
$ cd box

Compiling

$ export CGO_ENABLED=0
$ go build -trimpath -a -ldflags '-s -w -extldflags "-static"' -o $(go env GOPATH)/bin/box ./cmd/box

Examples of commands

Documentation

Index

Constants

View Source
const (
	KByte = 1024
	MByte = 1024 * KByte
)
View Source
const ANSICMilli = "Mon, " + time.StampMilli + " MST 2006"
View Source
const InsecureTLSConnection = false
View Source
const (
	WellKnownOAuthAuthorizationServer = "/.well-known/oauth-authorization-server"
)
View Source
const (
	XdgRuntimeDir = "XDG_RUNTIME_DIR"
)

Variables

View Source
var (
	AppName    = "box"
	AppVersion = "HEAD"
	AppWebsite = "git.sr.ht/~mariusor/box"
)
View Source
var BaseRuntimeDir = "/var/run"
View Source
var DefaultClientID = "https://git.sr.ht/~mariusor/box/blob/master/metadata.json"
View Source
var DefaultClientRedirectURL = "http://" + RandomLocalAddress().String()

DefaultClientRedirectURL is the local URL where we want to receive the OAuth authorization callback.

View Source
var DefaultMimeType = vocab.MimeType("text/markdown")
View Source
var Split = []byte{'\n', '\n', '\n'}
View Source
var (
	TimeNow = func() time.Time { return time.Now().Truncate(time.Millisecond).UTC() }
)

Functions

func AddCollections

func AddCollections[T vocab.Actor | vocab.Object | vocab.Question](it *T) error

func Announce

func Announce(ap *client.C, actor vocab.Actor, iris ...vocab.IRI) (vocab.Item, error)

func Appreciation

func Appreciation(ap *client.C, actor vocab.Actor, typ vocab.ActivityVocabularyType, iris ...vocab.IRI) (vocab.Item, error)

func Author

func Author(b *Client, cred *C2S) *vocab.Actor

func CleanPid

func CleanPid(appName string) error

func CodeVerifier

func CodeVerifier() string

func Collection

func Collection(b *Client, cred *C2S, whichCollection vocab.CollectionPath, ff ...filters.Check) (vocab.Item, error)

func CollectionBitmap

func CollectionBitmap() index.Indexable

CollectionBitmap uses a slightly different logic than a regular index. For collections, instead of storing the item's extracted tokens to the reference of the object's IRI we use the collection IRI as a token, and we store the references to the collection's items in the bitmap.

func CollectionOP

func CollectionOP(ap *client.C, actor vocab.Actor, typ vocab.ActivityVocabularyType, col vocab.IRI, iris ...vocab.IRI) (vocab.Item, error)

func DefaultUserAgent

func DefaultUserAgent() string

func Delete

func Delete(ap *client.C, actor vocab.Actor, iris ...vocab.IRI) (vocab.Item, error)

func Dereference

func Dereference(b *Client, cred *C2S, iris ...vocab.IRI) (vocab.ItemCollection, error)

func ExtractCollectionItems

func ExtractCollectionItems(li vocab.LinkOrIRI) []uint64

ExtractCollectionItems returns the vocab.IRI tokens corresponding to the items in the collection of the received vocab.Item

func Follow

func Follow(ap *client.C, actor vocab.Actor, reason string, toFollow ...vocab.Item) (vocab.Item, error)

func FollowResponse

func FollowResponse(ap *client.C, actor vocab.Actor, typ vocab.ActivityVocabularyType, reason string, respondToFollows ...vocab.Item) (vocab.Item, error)

func Follows

func Follows(b *Client, cred *C2S) (vocab.ItemCollection, error)

func Instance

func Instance(b *Client, cred *C2S) (*vocab.Actor, error)

func ItemCollectionFromItem

func ItemCollectionFromItem(it vocab.Item) vocab.ItemCollection

func ItemMatchesWebfingerResource

func ItemMatchesWebfingerResource(it vocab.Item, maybeHandle string) bool
func LoadFromAlternateLink(ctx context.Context, ap *client.C, iri string) (vocab.Item, error)

func LoadIRI

func LoadIRI(b *Client, cred *C2S, iri vocab.IRI) (vocab.Item, error)

func LoadItems

func LoadItems(b *Client, cred *C2S, iris ...vocab.IRI) (vocab.ItemCollection, error)

func LoadWebFingerActorFromHandle

func LoadWebFingerActorFromHandle(ctx context.Context, cl *client.C, maybeHandle string) (vocab.Item, error)

func LocalAddress

func LocalAddress() *net.TCPAddr

LocalAddress returns a net.TCPAddr struct that can be used for net.ListenTCP meant to be used for the

func Logger

func Logger(b *Client) lw.Logger

func MakeMention

func MakeMention(ap *client.C, instance string) func(name, host string) vocab.Item

func MakeOption

func MakeOption(value string, author vocab.IRI) vocab.Item

func MakeTag

func MakeTag(ap *client.C, instance string) func(name, host string) vocab.Item

func Moderate

func Moderate(ap *client.C, actor vocab.Actor, m Moderation) (vocab.Item, error)

func NeedsCollections

func NeedsCollections(it vocab.Item) bool

func OpenEditor

func OpenEditor(editor, file, content string) ([]byte, error)

func PidPath

func PidPath(appName string) string

func PostNote

func PostNote(ap *client.C, actor vocab.Actor, ob Object) (vocab.Item, error)

func Print

func Print(item vocab.Item) error

func PrintActivityFn

func PrintActivityFn(s io.Writer, fn SearchFn) func(activity *vocab.Activity) error

func PrintActorFn

func PrintActorFn(s io.Writer, fn SearchFn) func(*vocab.Actor) error

func PrintActorIdentifier

func PrintActorIdentifier(s io.Writer, act *vocab.Actor) error

func PrintIntransitiveActivityFn

func PrintIntransitiveActivityFn(s io.Writer, fn SearchFn) func(activity *vocab.IntransitiveActivity) error

func PrintItem

func PrintItem(s io.Writer, fn SearchFn, it vocab.Item) error

func PrintItemIdentifier

func PrintItemIdentifier(s io.Writer, li vocab.LinkOrIRI) error

func PrintItemIdentifiers

func PrintItemIdentifiers(s io.Writer, auth vocab.ItemCollection) error

func PrintListItem

func PrintListItem(s io.Writer, fn SearchFn, i int, li vocab.LinkOrIRI) error

func PrintNaturalLanguage

func PrintNaturalLanguage(s io.Writer, nl vocab.NaturalLanguageValues) error

func PrintObjectFn

func PrintObjectFn(s io.Writer, fn SearchFn) func(*vocab.Object) error

func PrintObjectIdentifier

func PrintObjectIdentifier(s io.Writer, ob *vocab.Object) error

func Question

func Question(ap *client.C, actor vocab.Actor, polls ...Poll) (vocab.Item, error)

func RandomLocalAddress

func RandomLocalAddress() *net.TCPAddr

RandomLocalAddress returns a net.TCPAddr struct that can be used for net.ListenTCP using a random port per application run.

func ReadPid

func ReadPid(appName string) (int, error)

func RemoveFromRecipients

func RemoveFromRecipients(it vocab.Item, recipients ...vocab.Item) vocab.Item

func RenderSource

func RenderSource(source vocab.Source) (vocab.NaturalLanguageValues, error)

func RuntimePath

func RuntimePath() string

func Save

func Save(ap *client.C, activities ...vocab.Item) (vocab.Item, error)

func SaveCredentials

func SaveCredentials(b *Client, cl C2S) error

func SkipCache

func SkipCache(b bool) func(*Client) error

func URLPath

func URLPath(uu vocab.IRI) string

func Undo

func Undo(ap *client.C, actor vocab.Actor, iris ...vocab.IRI) (vocab.Item, error)

func Update

func Update(ap *client.C, actor vocab.Actor, items ...vocab.Item) (vocab.Item, error)

func Upload

func Upload(ap *client.C, actor vocab.Actor, ats ...Attachment) (vocab.Item, error)

func UseBasePath

func UseBasePath(path string) func(*Client) error

func UseLogger

func UseLogger(l lw.Logger) func(b *Client) error

func UseXDGPaths

func UseXDGPaths(app string) func(*Client) error

func ValidCredentials

func ValidCredentials(cl C2S) bool

func WithUserAgent

func WithUserAgent(ua string) func(*Client) error

func WrapFlattenedObjectInActivityOfType

func WrapFlattenedObjectInActivityOfType(actor vocab.Actor, typ vocab.ActivityVocabularyType, ob vocab.Item) vocab.Activity

func WrapObjectInActivityOfType

func WrapObjectInActivityOfType(actor vocab.Actor, typ vocab.ActivityVocabularyType, ob vocab.Item) vocab.Activity

func WrapObjectInAnnounce

func WrapObjectInAnnounce(actor vocab.Actor, ob vocab.Item) vocab.Activity

func WrapObjectInCreate

func WrapObjectInCreate(actor vocab.Actor, ob vocab.Item) vocab.Activity

func WrapObjectInDelete

func WrapObjectInDelete(actor vocab.Actor, ob vocab.Item) vocab.Activity

func WrapObjectInUndo

func WrapObjectInUndo(actor vocab.Actor, ob vocab.Item) vocab.Activity

func WrapObjectInUpdate

func WrapObjectInUpdate(actor vocab.Actor, ob vocab.Item) vocab.Activity

func WriteDataURLFromFile

func WriteDataURLFromFile(file *os.File, content io.Writer) error

func WritePid

func WritePid(appName string) error

Types

type Attachment

type Attachment struct {
	Content
	Audience          Audience
	Exists            bool
	CreateCollections bool
	ID                vocab.IRI
	Type              string

	File  FileMap
	Sizes map[string]image.Point
	// contains filtered or unexported fields
}

func LoadMediaObject

func LoadMediaObject(b *Client, cred *C2S, iris ...vocab.IRI) ([]Attachment, error)

func (Attachment) Original

func (a Attachment) Original() *os.File

type Audience

type Audience struct {
	Recipients       vocab.IRIs
	IncludeFollowers bool
	IsPublic         bool

	InReplyTo vocab.IRIs
}

type C2S

type C2S struct {
	IRI           vocab.IRI
	Conf          oauth2.Config
	Tok           *oauth2.Token
	ProxyURL      vocab.IRI
	WebFingerAcct string
}

func Authorize

func Authorize(ctx context.Context, maybeActor vocab.Item, auth ClientConfig) (*C2S, error)

func LoadAllCredentials

func LoadAllCredentials(b *Client) ([]*C2S, error)

func LoadCredentials

func LoadCredentials(b *Client, iri vocab.IRI) (*C2S, error)

func (*C2S) Client

func (c *C2S) Client(ctx context.Context) *http.Client

func (*C2S) Config

func (c *C2S) Config() *oauth2.Config

func (*C2S) ID

func (c *C2S) ID() vocab.IRI

func (*C2S) Refresh

func (c *C2S) Refresh(ctx context.Context) error

func (*C2S) Sign

func (c *C2S) Sign(r *http.Request) error

func (*C2S) Token

func (c *C2S) Token() *oauth2.Token

func (C2S) Valid

func (c C2S) Valid() bool

type Client

type Client struct {
	// contains filtered or unexported fields
}

func New

func New(initFns ...fn) (*Client, error)

func (*Client) BaseClient

func (b *Client) BaseClient() *http.Client

func (*Client) CachePath

func (b *Client) CachePath() string

func (*Client) Client

func (b *Client) Client(ctx context.Context, cred *C2S) *client.C

func (*Client) DataPath

func (b *Client) DataPath() string

func (*Client) StoragePath

func (b *Client) StoragePath() string

type ClientConfig

type ClientConfig struct {
	UserAgent    string
	Interactive  bool
	ClientID     string
	ClientSecret string
	RedirectURL  string
	IssuedAt     time.Time
	Expiration   time.Duration
}

func FetchOAuth2ClientIDMetadata

func FetchOAuth2ClientIDMetadata(ctx context.Context, cl *http.Client) (*ClientConfig, error)

func TryOAuth2ClientRegistration

func TryOAuth2ClientRegistration(ctx context.Context, cl *http.Client, actor vocab.IRI) (*ClientConfig, error)

type ClientRegistrationRequest

type ClientRegistrationRequest struct {
	// RedirectUris Array of redirection URI strings for use in redirect-based flows
	// such as the authorization code and implicit flows.  As required by
	// Section 2 of OAuth 2.0 [RFC6749], clients using flows with
	// redirection MUST register their redirection URI values.
	// Authorization servers that support dynamic registration for
	// redirect-based flows MUST implement support for this metadata
	// value.
	RedirectUris []string `json:"redirect_uris"`

	// ClientName
	// Human-readable string name of the client to be presented to the
	// end-user during authorization.  If omitted, the authorization
	// server MAY display the raw "client_id" value to the end-user
	// instead.  It is RECOMMENDED that clients always send this field.
	// The value of this field MAY be internationalized, as described in
	// Section 2.2.
	ClientName string `json:"client_name"`

	// TokenEndpointAuthMethod
	// String indicator of the requested authentication method for the
	// token endpoint.  Values defined by this specification are:
	// *  "none": The client is a public client as defined in OAuth 2.0,
	//    Section 2.1, and does not have a client secret.
	// *  "client_secret_post": The client uses the HTTP POST parameters
	//    as defined in OAuth 2.0, Section 2.3.1.
	// *  "client_secret_basic": The client uses HTTP Basic as defined in
	//    OAuth 2.0, Section 2.3.1.
	// Additional values can be defined via the IANA "OAuth Token
	// Endpoint Authentication Methods" registry established in
	// Section 4.2.  Absolute URIs can also be used as values for this
	// parameter without being registered.  If unspecified or omitted,
	// the default is "client_secret_basic", denoting the HTTP Basic
	// authentication scheme as specified in Section 2.3.1 of OAuth 2.0.
	TokenEndpointAuthMethod string `json:"token_endpoint_auth_method"`

	// GrantTypes
	// Array of OAuth 2.0 grant type strings that the client can use at
	// the token endpoint.  These grant types are defined as follows:
	// *  "authorization_code": The authorization code grant type defined
	//    in OAuth 2.0, Section 4.1.
	// *  "implicit": The implicit grant type defined in OAuth 2.0,
	//    Section 4.2.
	// *  "password": The resource owner password credentials grant type
	//    defined in OAuth 2.0, Section 4.3.
	// *  "client_credentials": The client credentials grant type defined
	//    in OAuth 2.0, Section 4.4.
	// *  "refresh_token": The refresh token grant type defined in OAuth
	//    2.0, Section 6.
	// *  "urn:ietf:params:oauth:grant-type:jwt-bearer": The JWT Bearer
	//    Token Grant Type defined in OAuth JWT Bearer Token Profiles
	//    [RFC7523].
	// *  "urn:ietf:params:oauth:grant-type:saml2-bearer": The SAML 2.0
	//    Bearer Assertion Grant defined in OAuth SAML 2 Bearer Token
	//    Profiles [RFC7522].
	// If the token endpoint is used in the grant type, the value of this
	// parameter MUST be the same as the value of the "grant_type"
	// parameter passed to the token endpoint defined in the grant type
	// definition.  Authorization servers MAY allow for other values as
	// defined in the grant type extension process described in OAuth
	// 2.0, Section 4.5.  If omitted, the default behavior is that the
	// client will use only the "authorization_code" Grant Type.
	GrantTypes []string `json:"grant_types"`

	// ResponseTypes
	// Array of the OAuth 2.0 response type strings that the client can
	// use at the authorization endpoint.  These response types are
	// defined as follows:
	// *  "code": The authorization code response type defined in OAuth
	//    2.0, Section 4.1.
	// *  "token": The implicit response type defined in OAuth 2.0,
	//    Section 4.2.
	//  If the authorization endpoint is used by the grant type, the value
	// of this parameter MUST be the same as the value of the
	// "response_type" parameter passed to the authorization endpoint
	// defined in the grant type definition.  Authorization servers MAY
	// allow for other values as defined in the grant type extension
	// process is described in OAuth 2.0, Section 4.5.  If omitted, the
	// default is that the client will use only the "code" response type.
	ResponseTypes []string `json:"response_types,omitempty"`

	// ClientURI
	// URL string of a web page providing information about the client.
	// If present, the server SHOULD display this URL to the end-user in
	// a clickable fashion.  It is RECOMMENDED that clients always send
	// this field.  The value of this field MUST point to a valid web
	// page.  The value of this field MAY be internationalized, as
	// described in Section 2.2.
	ClientURI string `json:"client_uri,omitempty"`

	// LogoURI
	// URL string that references a logo for the client.  If present, the
	// server SHOULD display this image to the end-user during approval.
	// The value of this field MUST point to a valid image file.  The
	// value of this field MAY be internationalized, as described in
	// Section 2.2.
	LogoURI string `json:"logo_uri,omitempty"`

	// Scope
	// String containing a space-separated list of scope values (as
	// described in Section 3.3 of OAuth 2.0 [RFC6749]) that the client
	// can use when requesting access tokens.  The semantics of values in
	// this list are service specific.  If omitted, an authorization
	// server MAY register a client with a default set of scopes.
	Scope string `json:"scope,omitempty"`

	// Contacts
	// Array of strings representing ways to contact people responsible
	// for this client, typically email addresses.  The authorization
	// server MAY make these contact addresses available to end-users for
	// support requests for the client.  See Section 6 for information on
	// Privacy Considerations.
	Contacts []string `json:"contacts,omitempty"`

	// TosURI
	// URL string that points to a human-readable terms of service
	// document for the client that describes a contractual relationship
	// between the end-user and the client that the end-user accepts when
	// authorizing the client.  The authorization server SHOULD display
	// this URL to the end-user if it is provided.  The value of this
	// field MUST point to a valid web page.  The value of this field MAY
	// be internationalized, as described in Section 2.2.
	TosURI string `json:"tos_uri,omitempty"`

	// PolicyURI
	// URL string that points to a human-readable privacy policy document
	// that describes how the deployment organization collects, uses,
	// retains, and discloses personal data.  The authorization server
	// SHOULD display this URL to the end-user if it is provided.  The
	// value of this field MUST point to a valid web page.  The value of
	// this field MAY be internationalized, as described in Section 2.2.
	PolicyURI string `json:"policy_uri,omitempty"`

	// JwksURI
	// URL string referencing the client's JSON Web Key (JWK) Set
	// [RFC7517] document, which contains the client's public keys.  The
	// value of this field MUST point to a valid JWK Set document.  These
	// keys can be used by higher-level protocols that use signing or
	// encryption.  For instance, these keys might be used by some
	// applications for validating signed requests made to the token
	// endpoint when using JWTs for client authentication [RFC7523].  Use
	// of this parameter is preferred over the "jwks" parameter, as it
	// allows for easier key rotation.  The "jwks_uri" and "jwks"
	// parameters MUST NOT both be present in the same request or
	// response.
	JwksURI string `json:"jwks_uri,omitempty"`

	// Jwks
	// Client's JSON Web Key Set [RFC7517] document value, which contains
	// the client's public keys.  The value of this field MUST be a JSON
	// object containing a valid JWK Set.  These keys can be used by
	// higher-level protocols that use signing or encryption.  This
	// parameter is intended to be used by clients that cannot use the
	// "jwks_uri" parameter, such as native clients that cannot host
	// public URLs.  The "jwks_uri" and "jwks" parameters MUST NOT both
	// be present in the same request or response.
	Jwks json.RawMessage `json:"jwks,omitempty"`

	// SoftwareID
	// A unique identifier string (e.g., a Universally Unique Identifier
	// (UUID)) assigned by the client developer or software publisher
	// used by registration endpoints to identify the client software to
	// be dynamically registered.  Unlike "client_id", which is issued by
	// the authorization server and SHOULD vary between instances, the
	// "software_id" SHOULD remain the same for all instances of the
	// client software.  The "software_id" SHOULD remain the same across
	SoftwareID string `json:"software_id,omitempty"`
}

type ClientRegistrationResponse

type ClientRegistrationResponse struct {
	// ClientID REQUIRED. OAuth 2.0 client identifier string.  It SHOULD NOT be
	//	currently valid for any other registered client, though an
	//	authorization server MAY issue the same client identifier to
	//	multiple instances of a registered client at its discretion.
	ClientID string `json:"client_id"`

	// ClientSecret
	// OPTIONAL.  OAuth 2.0 client secret string.  If issued, this MUST
	// be unique for each "client_id" and SHOULD be unique for multiple
	// instances of a client using the same "client_id".  This value is
	// used by confidential clients to authenticate to the token
	// endpoint, as described in OAuth 2.0 [RFC6749], Section 2.3.1.
	ClientSecret string `json:"client_secret"`

	// IssuedAt OPTIONAL.  Time at which the client identifier was issued.  The
	// time is represented as the number of seconds from
	// 1970-01-01T00:00:00Z as measured in UTC until the date/time of
	// issuance.
	IssuedAt int64 `json:"client_id_issued_at"`

	// Expires REQUIRED if "client_secret" is issued.  Time at which the client
	// secret will expire or 0 if it will not expire.  The time is
	// represented as the number of seconds from 1970-01-01T00:00:00Z as
	// measured in UTC until the date/time of expiration.
	Expires int64 `json:"client_secret_expires_at"`
}

type Content

type Content struct {
	Name    vocab.NaturalLanguageValues
	Summary vocab.NaturalLanguageValues
	Content vocab.NaturalLanguageValues
	Source  vocab.Source
}

func FromTemplate

func FromTemplate(data []byte) Content

type FileMap

type FileMap map[string]*os.File

func (FileMap) Close

func (fm FileMap) Close() error

type Moderation

type Moderation struct {
	Type    vocab.ActivityVocabularyType
	Reason  vocab.NaturalLanguageValues
	Targets vocab.IRIs
}

type OAuthAuthorizationMetadata

type OAuthAuthorizationMetadata struct {
	Issuer                                     vocab.IRI `json:"issuer"`
	AuthorizationEndpoint                      string    `json:"authorization_endpoint"`
	TokenEndpoint                              string    `json:"token_endpoint"`
	TokenEndpointAuthMethodsSupported          []string  `json:"token_endpoint_auth_methods_supported,omitempty"`
	TokenEndpointAuthSigningAlgValuesSupported []string  `json:"token_endpoint_auth_signing_alg_values_supported,omitempty"`
	RegistrationEndpoint                       string    `json:"registration_endpoint"`
	GrantTypesSupported                        []string  `json:"grant_types_supported,omitempty"`
	ScopesSupported                            []string  `json:"scopes_supported,omitempty"`
	ResponseTypesSupported                     []string  `json:"response_types_supported,omitempty"`
}

OAuthAuthorizationMetadata is the metadata returned by RFC8414 well known oauth-authorization-server end-point

https://datatracker.ietf.org/doc/html/rfc8414#section-3.2

type Object

type Object struct {
	Content
	Audience          Audience
	ID                vocab.IRI
	Exists            bool
	CreateCollections bool
	Type              string

	Attachments []string
	URL         []string
	// contains filtered or unexported fields
}

func LoadTextObject

func LoadTextObject(b *Client, cred *C2S, iris ...vocab.IRI) ([]Object, error)

type Poll

type Poll struct {
	Content
	Audience Audience
	ID       vocab.IRI
	IsMulti  bool
	Options  []string
}

type RequestAuthorizer

type RequestAuthorizer interface {
	SetAuthHeader(*http.Request)
}

type SearchFn

type SearchFn func(...filters.Check) (vocab.ItemCollection, error)

Directories

Path Synopsis
cmd
box command
internal
tui

Jump to

Keyboard shortcuts

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