| 
									
										
										
										
											2023-03-12 16:00:57 +01:00
										 |  |  | // GoToSocial | 
					
						
							|  |  |  | // Copyright (C) GoToSocial Authors admin@gotosocial.org | 
					
						
							|  |  |  | // SPDX-License-Identifier: AGPL-3.0-or-later | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // This program is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU Affero General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  | // GNU Affero General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Affero General Public License | 
					
						
							|  |  |  | // along with this program.  If not, see <http://www.gnu.org/licenses/>. | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-20 15:19:53 +01:00
										 |  |  | package uris | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"net/url" | 
					
						
							| 
									
										
										
										
											2023-07-31 15:47:35 +02:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2021-09-01 18:29:25 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-07 13:31:39 +01:00
										 |  |  | 	"github.com/superseriousbusiness/gotosocial/internal/config" | 
					
						
							| 
									
										
										
										
											2021-09-01 18:29:25 +02:00
										 |  |  | 	"github.com/superseriousbusiness/gotosocial/internal/regexes" | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							| 
									
										
										
										
											2021-12-20 15:19:53 +01:00
										 |  |  | 	UsersPath        = "users"         // UsersPath is for serving users info | 
					
						
							|  |  |  | 	StatusesPath     = "statuses"      // StatusesPath is for serving statuses | 
					
						
							|  |  |  | 	InboxPath        = "inbox"         // InboxPath represents the activitypub inbox location | 
					
						
							|  |  |  | 	OutboxPath       = "outbox"        // OutboxPath represents the activitypub outbox location | 
					
						
							|  |  |  | 	FollowersPath    = "followers"     // FollowersPath represents the activitypub followers location | 
					
						
							|  |  |  | 	FollowingPath    = "following"     // FollowingPath represents the activitypub following location | 
					
						
							|  |  |  | 	LikedPath        = "liked"         // LikedPath represents the activitypub liked location | 
					
						
							|  |  |  | 	CollectionsPath  = "collections"   // CollectionsPath represents the activitypub collections location | 
					
						
							|  |  |  | 	FeaturedPath     = "featured"      // FeaturedPath represents the activitypub featured location | 
					
						
							|  |  |  | 	PublicKeyPath    = "main-key"      // PublicKeyPath is for serving an account's public key | 
					
						
							|  |  |  | 	FollowPath       = "follow"        // FollowPath used to generate the URI for an individual follow or follow request | 
					
						
							|  |  |  | 	UpdatePath       = "updates"       // UpdatePath is used to generate the URI for an account update | 
					
						
							|  |  |  | 	BlocksPath       = "blocks"        // BlocksPath is used to generate the URI for a block | 
					
						
							| 
									
										
										
										
											2024-03-13 13:53:29 +01:00
										 |  |  | 	MovesPath        = "moves"         // MovesPath is used to generate the URI for a move | 
					
						
							| 
									
										
										
										
											2023-01-10 15:19:05 +01:00
										 |  |  | 	ReportsPath      = "reports"       // ReportsPath is used to generate the URI for a report/flag | 
					
						
							| 
									
										
										
										
											2021-12-20 15:19:53 +01:00
										 |  |  | 	ConfirmEmailPath = "confirm_email" // ConfirmEmailPath is used to generate the URI for an email confirmation link | 
					
						
							|  |  |  | 	FileserverPath   = "fileserver"    // FileserverPath is a path component for serving attachments + media | 
					
						
							|  |  |  | 	EmojiPath        = "emoji"         // EmojiPath represents the activitypub emoji location | 
					
						
							| 
									
										
										
										
											2023-07-31 15:47:35 +02:00
										 |  |  | 	TagsPath         = "tags"          // TagsPath represents the activitypub tags location | 
					
						
							| 
									
										
										
										
											2024-08-24 11:49:37 +02:00
										 |  |  | 	AcceptsPath      = "accepts"       // AcceptsPath represents the activitypub Accept's location | 
					
						
							|  |  |  | 	RejectsPath      = "rejects"       // RejectsPath represents the activitypub Reject's location | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // UserURIs contains a bunch of UserURIs and URLs for a user, host, account, etc. | 
					
						
							|  |  |  | type UserURIs struct { | 
					
						
							|  |  |  | 	// The web URL of the instance host, eg https://example.org | 
					
						
							|  |  |  | 	HostURL string | 
					
						
							|  |  |  | 	// The web URL of the user, eg., https://example.org/@example_user | 
					
						
							|  |  |  | 	UserURL string | 
					
						
							|  |  |  | 	// The web URL for statuses of this user, eg., https://example.org/@example_user/statuses | 
					
						
							|  |  |  | 	StatusesURL string | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-20 15:19:53 +01:00
										 |  |  | 	// The activitypub URI of this user, eg., https://example.org/users/example_user | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | 	UserURI string | 
					
						
							| 
									
										
										
										
											2021-12-20 15:19:53 +01:00
										 |  |  | 	// The activitypub URI for this user's statuses, eg., https://example.org/users/example_user/statuses | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | 	StatusesURI string | 
					
						
							| 
									
										
										
										
											2021-12-20 15:19:53 +01:00
										 |  |  | 	// The activitypub URI for this user's activitypub inbox, eg., https://example.org/users/example_user/inbox | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | 	InboxURI string | 
					
						
							| 
									
										
										
										
											2021-12-20 15:19:53 +01:00
										 |  |  | 	// The activitypub URI for this user's activitypub outbox, eg., https://example.org/users/example_user/outbox | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | 	OutboxURI string | 
					
						
							| 
									
										
										
										
											2021-12-20 15:19:53 +01:00
										 |  |  | 	// The activitypub URI for this user's followers, eg., https://example.org/users/example_user/followers | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | 	FollowersURI string | 
					
						
							| 
									
										
										
										
											2021-12-20 15:19:53 +01:00
										 |  |  | 	// The activitypub URI for this user's following, eg., https://example.org/users/example_user/following | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | 	FollowingURI string | 
					
						
							| 
									
										
										
										
											2021-12-20 15:19:53 +01:00
										 |  |  | 	// The activitypub URI for this user's liked posts eg., https://example.org/users/example_user/liked | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | 	LikedURI string | 
					
						
							| 
									
										
										
										
											2021-12-20 15:19:53 +01:00
										 |  |  | 	// The activitypub URI for this user's featured collections, eg., https://example.org/users/example_user/collections/featured | 
					
						
							| 
									
										
										
										
											2023-03-01 18:52:44 +01:00
										 |  |  | 	FeaturedCollectionURI string | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | 	// The URI for this user's public key, eg., https://example.org/users/example_user/publickey | 
					
						
							|  |  |  | 	PublicKeyURI string | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-21 15:48:26 +02:00
										 |  |  | // GenerateURIForFollow returns the AP URI for a new follow -- something like: | 
					
						
							| 
									
										
										
										
											2021-06-13 18:42:28 +02:00
										 |  |  | // https://example.org/users/whatever_user/follow/01F7XTH1QGBAPMGF49WJZ91XGC | 
					
						
							| 
									
										
										
										
											2021-12-07 13:31:39 +01:00
										 |  |  | func GenerateURIForFollow(username string, thisFollowID string) string { | 
					
						
							| 
									
										
										
										
											2022-05-30 13:41:24 +01:00
										 |  |  | 	protocol := config.GetProtocol() | 
					
						
							|  |  |  | 	host := config.GetHost() | 
					
						
							| 
									
										
										
										
											2021-05-28 22:47:18 +02:00
										 |  |  | 	return fmt.Sprintf("%s://%s/%s/%s/%s/%s", protocol, host, UsersPath, username, FollowPath, thisFollowID) | 
					
						
							| 
									
										
										
										
											2021-05-24 18:49:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-30 13:12:00 +02:00
										 |  |  | // GenerateURIForLike returns the AP URI for a new like/fave -- something like: | 
					
						
							| 
									
										
										
										
											2021-06-13 18:42:28 +02:00
										 |  |  | // https://example.org/users/whatever_user/liked/01F7XTH1QGBAPMGF49WJZ91XGC | 
					
						
							| 
									
										
										
										
											2021-12-07 13:31:39 +01:00
										 |  |  | func GenerateURIForLike(username string, thisFavedID string) string { | 
					
						
							| 
									
										
										
										
											2022-05-30 13:41:24 +01:00
										 |  |  | 	protocol := config.GetProtocol() | 
					
						
							|  |  |  | 	host := config.GetHost() | 
					
						
							| 
									
										
										
										
											2021-05-28 22:47:18 +02:00
										 |  |  | 	return fmt.Sprintf("%s://%s/%s/%s/%s/%s", protocol, host, UsersPath, username, LikedPath, thisFavedID) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // GenerateURIForUpdate returns the AP URI for a new update activity -- something like: | 
					
						
							| 
									
										
										
										
											2021-06-13 18:42:28 +02:00
										 |  |  | // https://example.org/users/whatever_user#updates/01F7XTH1QGBAPMGF49WJZ91XGC | 
					
						
							| 
									
										
										
										
											2021-12-07 13:31:39 +01:00
										 |  |  | func GenerateURIForUpdate(username string, thisUpdateID string) string { | 
					
						
							| 
									
										
										
										
											2022-05-30 13:41:24 +01:00
										 |  |  | 	protocol := config.GetProtocol() | 
					
						
							|  |  |  | 	host := config.GetHost() | 
					
						
							| 
									
										
										
										
											2021-05-28 22:47:18 +02:00
										 |  |  | 	return fmt.Sprintf("%s://%s/%s/%s#%s/%s", protocol, host, UsersPath, username, UpdatePath, thisUpdateID) | 
					
						
							| 
									
										
										
										
											2021-05-21 15:48:26 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-11 16:22:21 +02:00
										 |  |  | // GenerateURIForBlock returns the AP URI for a new block activity -- something like: | 
					
						
							|  |  |  | // https://example.org/users/whatever_user/blocks/01F7XTH1QGBAPMGF49WJZ91XGC | 
					
						
							| 
									
										
										
										
											2021-12-07 13:31:39 +01:00
										 |  |  | func GenerateURIForBlock(username string, thisBlockID string) string { | 
					
						
							| 
									
										
										
										
											2022-05-30 13:41:24 +01:00
										 |  |  | 	protocol := config.GetProtocol() | 
					
						
							|  |  |  | 	host := config.GetHost() | 
					
						
							| 
									
										
										
										
											2021-07-11 16:22:21 +02:00
										 |  |  | 	return fmt.Sprintf("%s://%s/%s/%s/%s/%s", protocol, host, UsersPath, username, BlocksPath, thisBlockID) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-13 13:53:29 +01:00
										 |  |  | // GenerateURIForMove returns the AP URI for a new Move activity -- something like: | 
					
						
							|  |  |  | // https://example.org/users/whatever_user/moves/01F7XTH1QGBAPMGF49WJZ91XGC | 
					
						
							|  |  |  | func GenerateURIForMove(username string, thisMoveID string) string { | 
					
						
							|  |  |  | 	protocol := config.GetProtocol() | 
					
						
							|  |  |  | 	host := config.GetHost() | 
					
						
							|  |  |  | 	return fmt.Sprintf("%s://%s/%s/%s/%s/%s", protocol, host, UsersPath, username, MovesPath, thisMoveID) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-10 15:19:05 +01:00
										 |  |  | // GenerateURIForReport returns the API URI for a new Flag activity -- something like: | 
					
						
							|  |  |  | // https://example.org/reports/01GP3AWY4CRDVRNZKW0TEAMB5R | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // This path specifically doesn't contain any info about the user who did the reporting, | 
					
						
							|  |  |  | // to protect their privacy. | 
					
						
							|  |  |  | func GenerateURIForReport(thisReportID string) string { | 
					
						
							|  |  |  | 	protocol := config.GetProtocol() | 
					
						
							|  |  |  | 	host := config.GetHost() | 
					
						
							|  |  |  | 	return fmt.Sprintf("%s://%s/%s/%s", protocol, host, ReportsPath, thisReportID) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-31 15:46:23 +01:00
										 |  |  | // GenerateURIForEmailConfirm returns a link for email confirmation -- something like: | 
					
						
							|  |  |  | // https://example.org/confirm_email?token=490e337c-0162-454f-ac48-4b22bb92a205 | 
					
						
							| 
									
										
										
										
											2021-12-07 13:31:39 +01:00
										 |  |  | func GenerateURIForEmailConfirm(token string) string { | 
					
						
							| 
									
										
										
										
											2022-05-30 13:41:24 +01:00
										 |  |  | 	protocol := config.GetProtocol() | 
					
						
							|  |  |  | 	host := config.GetHost() | 
					
						
							| 
									
										
										
										
											2021-10-31 15:46:23 +01:00
										 |  |  | 	return fmt.Sprintf("%s://%s/%s?token=%s", protocol, host, ConfirmEmailPath, token) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-24 11:49:37 +02:00
										 |  |  | // GenerateURIForAccept returns the AP URI for a new Accept activity -- something like: | 
					
						
							| 
									
										
										
										
											2024-07-26 12:04:28 +02:00
										 |  |  | // https://example.org/users/whatever_user/accepts/01F7XTH1QGBAPMGF49WJZ91XGC | 
					
						
							|  |  |  | func GenerateURIForAccept(username string, thisAcceptID string) string { | 
					
						
							|  |  |  | 	protocol := config.GetProtocol() | 
					
						
							|  |  |  | 	host := config.GetHost() | 
					
						
							|  |  |  | 	return fmt.Sprintf("%s://%s/%s/%s/%s/%s", protocol, host, UsersPath, username, AcceptsPath, thisAcceptID) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-24 11:49:37 +02:00
										 |  |  | // GenerateURIForReject returns the AP URI for a new Reject activity -- something like: | 
					
						
							|  |  |  | // https://example.org/users/whatever_user/rejects/01F7XTH1QGBAPMGF49WJZ91XGC | 
					
						
							|  |  |  | func GenerateURIForReject(username string, thisRejectID string) string { | 
					
						
							|  |  |  | 	protocol := config.GetProtocol() | 
					
						
							|  |  |  | 	host := config.GetHost() | 
					
						
							|  |  |  | 	return fmt.Sprintf("%s://%s/%s/%s/%s/%s", protocol, host, UsersPath, username, RejectsPath, thisRejectID) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | // GenerateURIsForAccount throws together a bunch of URIs for the given username, with the given protocol and host. | 
					
						
							| 
									
										
										
										
											2021-12-07 13:31:39 +01:00
										 |  |  | func GenerateURIsForAccount(username string) *UserURIs { | 
					
						
							| 
									
										
										
										
											2022-05-30 13:41:24 +01:00
										 |  |  | 	protocol := config.GetProtocol() | 
					
						
							|  |  |  | 	host := config.GetHost() | 
					
						
							| 
									
										
										
										
											2021-12-07 13:31:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | 	// The below URLs are used for serving web requests | 
					
						
							|  |  |  | 	hostURL := fmt.Sprintf("%s://%s", protocol, host) | 
					
						
							|  |  |  | 	userURL := fmt.Sprintf("%s/@%s", hostURL, username) | 
					
						
							|  |  |  | 	statusesURL := fmt.Sprintf("%s/%s", userURL, StatusesPath) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// the below URIs are used in ActivityPub and Webfinger | 
					
						
							|  |  |  | 	userURI := fmt.Sprintf("%s/%s/%s", hostURL, UsersPath, username) | 
					
						
							|  |  |  | 	statusesURI := fmt.Sprintf("%s/%s", userURI, StatusesPath) | 
					
						
							|  |  |  | 	inboxURI := fmt.Sprintf("%s/%s", userURI, InboxPath) | 
					
						
							|  |  |  | 	outboxURI := fmt.Sprintf("%s/%s", userURI, OutboxPath) | 
					
						
							|  |  |  | 	followersURI := fmt.Sprintf("%s/%s", userURI, FollowersPath) | 
					
						
							|  |  |  | 	followingURI := fmt.Sprintf("%s/%s", userURI, FollowingPath) | 
					
						
							|  |  |  | 	likedURI := fmt.Sprintf("%s/%s", userURI, LikedPath) | 
					
						
							|  |  |  | 	collectionURI := fmt.Sprintf("%s/%s/%s", userURI, CollectionsPath, FeaturedPath) | 
					
						
							| 
									
										
										
										
											2021-06-26 16:21:40 +02:00
										 |  |  | 	publicKeyURI := fmt.Sprintf("%s/%s", userURI, PublicKeyPath) | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return &UserURIs{ | 
					
						
							|  |  |  | 		HostURL:     hostURL, | 
					
						
							|  |  |  | 		UserURL:     userURL, | 
					
						
							|  |  |  | 		StatusesURL: statusesURL, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-01 18:52:44 +01:00
										 |  |  | 		UserURI:               userURI, | 
					
						
							|  |  |  | 		StatusesURI:           statusesURI, | 
					
						
							|  |  |  | 		InboxURI:              inboxURI, | 
					
						
							|  |  |  | 		OutboxURI:             outboxURI, | 
					
						
							|  |  |  | 		FollowersURI:          followersURI, | 
					
						
							|  |  |  | 		FollowingURI:          followingURI, | 
					
						
							|  |  |  | 		LikedURI:              likedURI, | 
					
						
							|  |  |  | 		FeaturedCollectionURI: collectionURI, | 
					
						
							|  |  |  | 		PublicKeyURI:          publicKeyURI, | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-10 19:29:26 +01:00
										 |  |  | // URIForAttachment generates a URI for | 
					
						
							|  |  |  | // an attachment/emoji/header etc. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Will produce something like: | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //	"https://example.org/fileserver/01FPST95B8FC3HG3AGCDKPQNQ2/attachment/original/01FPST9QK4V5XWS3F9Z4F2G1X7.gif" | 
					
						
							|  |  |  | func URIForAttachment( | 
					
						
							|  |  |  | 	accountID string, | 
					
						
							|  |  |  | 	mediaType string, | 
					
						
							|  |  |  | 	mediaSize string, | 
					
						
							|  |  |  | 	mediaID string, | 
					
						
							|  |  |  | 	extension string, | 
					
						
							|  |  |  | ) string { | 
					
						
							|  |  |  | 	const format = "%s://%s/%s/%s/%s/%s/%s.%s" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return fmt.Sprintf( | 
					
						
							|  |  |  | 		format, | 
					
						
							|  |  |  | 		config.GetProtocol(), | 
					
						
							|  |  |  | 		config.GetHost(), | 
					
						
							|  |  |  | 		FileserverPath, | 
					
						
							|  |  |  | 		accountID, | 
					
						
							|  |  |  | 		mediaType, | 
					
						
							|  |  |  | 		mediaSize, | 
					
						
							|  |  |  | 		mediaID, | 
					
						
							|  |  |  | 		extension, | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2021-12-20 15:19:53 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-10 19:29:26 +01:00
										 |  |  | // StoragePathForAttachment generates a storage | 
					
						
							|  |  |  | // path for an attachment/emoji/header etc. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Will produce something like: | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //	"01FPST95B8FC3HG3AGCDKPQNQ2/attachment/original/01FPST9QK4V5XWS3F9Z4F2G1X7.gif" | 
					
						
							|  |  |  | func StoragePathForAttachment( | 
					
						
							|  |  |  | 	accountID string, | 
					
						
							|  |  |  | 	mediaType string, | 
					
						
							|  |  |  | 	mediaSize string, | 
					
						
							|  |  |  | 	mediaID string, | 
					
						
							|  |  |  | 	extension string, | 
					
						
							|  |  |  | ) string { | 
					
						
							|  |  |  | 	const format = "%s/%s/%s/%s.%s" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return fmt.Sprintf( | 
					
						
							|  |  |  | 		format, | 
					
						
							|  |  |  | 		accountID, | 
					
						
							|  |  |  | 		mediaType, | 
					
						
							|  |  |  | 		mediaSize, | 
					
						
							|  |  |  | 		mediaID, | 
					
						
							|  |  |  | 		extension, | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // URIForEmoji generates an | 
					
						
							|  |  |  | // ActivityPub URI for an emoji. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Will produce something like: | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //	"https://example.org/emoji/01FPST9QK4V5XWS3F9Z4F2G1X7" | 
					
						
							|  |  |  | func URIForEmoji(emojiID string) string { | 
					
						
							|  |  |  | 	const format = "%s://%s/%s/%s" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return fmt.Sprintf( | 
					
						
							|  |  |  | 		format, | 
					
						
							|  |  |  | 		config.GetProtocol(), | 
					
						
							|  |  |  | 		config.GetHost(), | 
					
						
							|  |  |  | 		EmojiPath, | 
					
						
							|  |  |  | 		emojiID, | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2021-12-20 15:19:53 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-10 19:29:26 +01:00
										 |  |  | // URIForTag generates an activitypub uri for a tag. | 
					
						
							|  |  |  | func URIForTag(name string) string { | 
					
						
							| 
									
										
										
										
											2023-07-31 15:47:35 +02:00
										 |  |  | 	protocol := config.GetProtocol() | 
					
						
							|  |  |  | 	host := config.GetHost() | 
					
						
							|  |  |  | 	return fmt.Sprintf("%s://%s/%s/%s", protocol, host, TagsPath, strings.ToLower(name)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | // IsUserPath returns true if the given URL path corresponds to eg /users/example_username | 
					
						
							|  |  |  | func IsUserPath(id *url.URL) bool { | 
					
						
							| 
									
										
										
										
											2021-09-01 18:29:25 +02:00
										 |  |  | 	return regexes.UserPath.MatchString(id.Path) | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-26 14:17:10 +01:00
										 |  |  | // IsUserWebPath returns true if the given URL path corresponds to eg /@example_username | 
					
						
							|  |  |  | func IsUserWebPath(id *url.URL) bool { | 
					
						
							|  |  |  | 	return regexes.UserWebPath.MatchString(id.Path) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | // IsInboxPath returns true if the given URL path corresponds to eg /users/example_username/inbox | 
					
						
							|  |  |  | func IsInboxPath(id *url.URL) bool { | 
					
						
							| 
									
										
										
										
											2021-09-01 18:29:25 +02:00
										 |  |  | 	return regexes.InboxPath.MatchString(id.Path) | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // IsOutboxPath returns true if the given URL path corresponds to eg /users/example_username/outbox | 
					
						
							|  |  |  | func IsOutboxPath(id *url.URL) bool { | 
					
						
							| 
									
										
										
										
											2021-09-01 18:29:25 +02:00
										 |  |  | 	return regexes.OutboxPath.MatchString(id.Path) | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // IsFollowersPath returns true if the given URL path corresponds to eg /users/example_username/followers | 
					
						
							|  |  |  | func IsFollowersPath(id *url.URL) bool { | 
					
						
							| 
									
										
										
										
											2021-09-01 18:29:25 +02:00
										 |  |  | 	return regexes.FollowersPath.MatchString(id.Path) | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // IsFollowingPath returns true if the given URL path corresponds to eg /users/example_username/following | 
					
						
							|  |  |  | func IsFollowingPath(id *url.URL) bool { | 
					
						
							| 
									
										
										
										
											2021-09-01 18:29:25 +02:00
										 |  |  | 	return regexes.FollowingPath.MatchString(id.Path) | 
					
						
							| 
									
										
										
										
											2021-06-13 18:42:28 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // IsFollowPath returns true if the given URL path corresponds to eg /users/example_username/follow/SOME_ULID_OF_A_FOLLOW | 
					
						
							|  |  |  | func IsFollowPath(id *url.URL) bool { | 
					
						
							| 
									
										
										
										
											2021-09-01 18:29:25 +02:00
										 |  |  | 	return regexes.FollowPath.MatchString(id.Path) | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // IsLikedPath returns true if the given URL path corresponds to eg /users/example_username/liked | 
					
						
							|  |  |  | func IsLikedPath(id *url.URL) bool { | 
					
						
							| 
									
										
										
										
											2021-09-01 18:29:25 +02:00
										 |  |  | 	return regexes.LikedPath.MatchString(id.Path) | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-13 18:42:28 +02:00
										 |  |  | // IsLikePath returns true if the given URL path corresponds to eg /users/example_username/liked/SOME_ULID_OF_A_STATUS | 
					
						
							| 
									
										
										
										
											2021-05-24 18:49:48 +02:00
										 |  |  | func IsLikePath(id *url.URL) bool { | 
					
						
							| 
									
										
										
										
											2021-09-01 18:29:25 +02:00
										 |  |  | 	return regexes.LikePath.MatchString(id.Path) | 
					
						
							| 
									
										
										
										
											2021-05-24 18:49:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-13 18:42:28 +02:00
										 |  |  | // IsStatusesPath returns true if the given URL path corresponds to eg /users/example_username/statuses/SOME_ULID_OF_A_STATUS | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | func IsStatusesPath(id *url.URL) bool { | 
					
						
							| 
									
										
										
										
											2021-09-01 18:29:25 +02:00
										 |  |  | 	return regexes.StatusesPath.MatchString(id.Path) | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-26 16:21:40 +02:00
										 |  |  | // IsPublicKeyPath returns true if the given URL path corresponds to eg /users/example_username/main-key | 
					
						
							|  |  |  | func IsPublicKeyPath(id *url.URL) bool { | 
					
						
							| 
									
										
										
										
											2021-09-01 18:29:25 +02:00
										 |  |  | 	return regexes.PublicKeyPath.MatchString(id.Path) | 
					
						
							| 
									
										
										
										
											2021-06-26 16:21:40 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-11 16:22:21 +02:00
										 |  |  | // IsBlockPath returns true if the given URL path corresponds to eg /users/example_username/blocks/SOME_ULID_OF_A_BLOCK | 
					
						
							|  |  |  | func IsBlockPath(id *url.URL) bool { | 
					
						
							| 
									
										
										
										
											2021-09-01 18:29:25 +02:00
										 |  |  | 	return regexes.BlockPath.MatchString(id.Path) | 
					
						
							| 
									
										
										
										
											2021-07-11 16:22:21 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-10 15:19:05 +01:00
										 |  |  | // IsReportPath returns true if the given URL path corresponds to eg /reports/SOME_ULID_OF_A_REPORT | 
					
						
							|  |  |  | func IsReportPath(id *url.URL) bool { | 
					
						
							|  |  |  | 	return regexes.ReportPath.MatchString(id.Path) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-26 12:04:28 +02:00
										 |  |  | // IsAcceptsPath returns true if the given URL path corresponds to eg /users/example_username/accepts/SOME_ULID_OF_AN_ACCEPT | 
					
						
							|  |  |  | func IsAcceptsPath(id *url.URL) bool { | 
					
						
							|  |  |  | 	return regexes.AcceptsPath.MatchString(id.Path) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-13 18:42:28 +02:00
										 |  |  | // ParseStatusesPath returns the username and ulid from a path such as /users/example_username/statuses/SOME_ULID_OF_A_STATUS | 
					
						
							|  |  |  | func ParseStatusesPath(id *url.URL) (username string, ulid string, err error) { | 
					
						
							| 
									
										
										
										
											2021-09-01 18:29:25 +02:00
										 |  |  | 	matches := regexes.StatusesPath.FindStringSubmatch(id.Path) | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | 	if len(matches) != 3 { | 
					
						
							|  |  |  | 		err = fmt.Errorf("expected 3 matches but matches length was %d", len(matches)) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	username = matches[1] | 
					
						
							| 
									
										
										
										
											2021-06-13 18:42:28 +02:00
										 |  |  | 	ulid = matches[2] | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ParseUserPath returns the username from a path such as /users/example_username | 
					
						
							|  |  |  | func ParseUserPath(id *url.URL) (username string, err error) { | 
					
						
							| 
									
										
										
										
											2021-09-01 18:29:25 +02:00
										 |  |  | 	matches := regexes.UserPath.FindStringSubmatch(id.Path) | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | 	if len(matches) != 2 { | 
					
						
							|  |  |  | 		err = fmt.Errorf("expected 2 matches but matches length was %d", len(matches)) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	username = matches[1] | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-26 14:17:10 +01:00
										 |  |  | // ParseUserPath returns the username from a path such as /@example_username | 
					
						
							|  |  |  | func ParseUserWebPath(id *url.URL) (username string, err error) { | 
					
						
							|  |  |  | 	matches := regexes.UserWebPath.FindStringSubmatch(id.Path) | 
					
						
							|  |  |  | 	if len(matches) != 2 { | 
					
						
							|  |  |  | 		err = fmt.Errorf("expected 2 matches but matches length was %d", len(matches)) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	username = matches[1] | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | // ParseInboxPath returns the username from a path such as /users/example_username/inbox | 
					
						
							|  |  |  | func ParseInboxPath(id *url.URL) (username string, err error) { | 
					
						
							| 
									
										
										
										
											2021-09-01 18:29:25 +02:00
										 |  |  | 	matches := regexes.InboxPath.FindStringSubmatch(id.Path) | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | 	if len(matches) != 2 { | 
					
						
							|  |  |  | 		err = fmt.Errorf("expected 2 matches but matches length was %d", len(matches)) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	username = matches[1] | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ParseOutboxPath returns the username from a path such as /users/example_username/outbox | 
					
						
							|  |  |  | func ParseOutboxPath(id *url.URL) (username string, err error) { | 
					
						
							| 
									
										
										
										
											2021-09-01 18:29:25 +02:00
										 |  |  | 	matches := regexes.OutboxPath.FindStringSubmatch(id.Path) | 
					
						
							| 
									
										
										
										
											2021-05-08 14:25:55 +02:00
										 |  |  | 	if len(matches) != 2 { | 
					
						
							|  |  |  | 		err = fmt.Errorf("expected 2 matches but matches length was %d", len(matches)) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	username = matches[1] | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-05-23 18:07:04 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | // ParseFollowersPath returns the username from a path such as /users/example_username/followers | 
					
						
							|  |  |  | func ParseFollowersPath(id *url.URL) (username string, err error) { | 
					
						
							| 
									
										
										
										
											2021-09-01 18:29:25 +02:00
										 |  |  | 	matches := regexes.FollowersPath.FindStringSubmatch(id.Path) | 
					
						
							| 
									
										
										
										
											2021-05-23 18:07:04 +02:00
										 |  |  | 	if len(matches) != 2 { | 
					
						
							|  |  |  | 		err = fmt.Errorf("expected 2 matches but matches length was %d", len(matches)) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	username = matches[1] | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ParseFollowingPath returns the username from a path such as /users/example_username/following | 
					
						
							|  |  |  | func ParseFollowingPath(id *url.URL) (username string, err error) { | 
					
						
							| 
									
										
										
										
											2021-09-01 18:29:25 +02:00
										 |  |  | 	matches := regexes.FollowingPath.FindStringSubmatch(id.Path) | 
					
						
							| 
									
										
										
										
											2021-05-23 18:07:04 +02:00
										 |  |  | 	if len(matches) != 2 { | 
					
						
							|  |  |  | 		err = fmt.Errorf("expected 2 matches but matches length was %d", len(matches)) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	username = matches[1] | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-05-24 18:49:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-13 18:42:28 +02:00
										 |  |  | // ParseLikedPath returns the username and ulid from a path such as /users/example_username/liked/SOME_ULID_OF_A_STATUS | 
					
						
							|  |  |  | func ParseLikedPath(id *url.URL) (username string, ulid string, err error) { | 
					
						
							| 
									
										
										
										
											2021-09-01 18:29:25 +02:00
										 |  |  | 	matches := regexes.LikePath.FindStringSubmatch(id.Path) | 
					
						
							| 
									
										
										
										
											2021-05-24 18:49:48 +02:00
										 |  |  | 	if len(matches) != 3 { | 
					
						
							|  |  |  | 		err = fmt.Errorf("expected 3 matches but matches length was %d", len(matches)) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	username = matches[1] | 
					
						
							| 
									
										
										
										
											2021-06-13 18:42:28 +02:00
										 |  |  | 	ulid = matches[2] | 
					
						
							| 
									
										
										
										
											2021-05-24 18:49:48 +02:00
										 |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-07-11 16:22:21 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | // ParseBlockPath returns the username and ulid from a path such as /users/example_username/blocks/SOME_ULID_OF_A_BLOCK | 
					
						
							|  |  |  | func ParseBlockPath(id *url.URL) (username string, ulid string, err error) { | 
					
						
							| 
									
										
										
										
											2021-09-01 18:29:25 +02:00
										 |  |  | 	matches := regexes.BlockPath.FindStringSubmatch(id.Path) | 
					
						
							| 
									
										
										
										
											2021-07-11 16:22:21 +02:00
										 |  |  | 	if len(matches) != 3 { | 
					
						
							|  |  |  | 		err = fmt.Errorf("expected 3 matches but matches length was %d", len(matches)) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	username = matches[1] | 
					
						
							|  |  |  | 	ulid = matches[2] | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-01-10 15:19:05 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | // ParseReportPath returns the ulid from a path such as /reports/SOME_ULID_OF_A_REPORT | 
					
						
							|  |  |  | func ParseReportPath(id *url.URL) (ulid string, err error) { | 
					
						
							|  |  |  | 	matches := regexes.ReportPath.FindStringSubmatch(id.Path) | 
					
						
							|  |  |  | 	if len(matches) != 2 { | 
					
						
							|  |  |  | 		err = fmt.Errorf("expected 2 matches but matches length was %d", len(matches)) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ulid = matches[1] | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } |