| 
									
										
										
										
											2021-04-22 18:51:49 +02:00
										 |  |  | /* | 
					
						
							|  |  |  |    GoToSocial | 
					
						
							|  |  |  |    Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    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/>. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package util | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"net/url" | 
					
						
							| 
									
										
										
										
											2021-04-24 11:19:18 +02:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2021-04-22 18:51:49 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							|  |  |  | 	// UsersPath is for serving users info | 
					
						
							| 
									
										
										
										
											2021-04-24 11:19:18 +02:00
										 |  |  | 	UsersPath = "users" | 
					
						
							|  |  |  | 	// ActorsPath is for serving actors info | 
					
						
							|  |  |  | 	ActorsPath = "actors" | 
					
						
							| 
									
										
										
										
											2021-04-22 18:51:49 +02:00
										 |  |  | 	// StatusesPath is for serving statuses | 
					
						
							| 
									
										
										
										
											2021-04-24 11:19:18 +02:00
										 |  |  | 	StatusesPath = "statuses" | 
					
						
							| 
									
										
										
										
											2021-04-22 18:51:49 +02:00
										 |  |  | 	// InboxPath represents the webfinger inbox location | 
					
						
							| 
									
										
										
										
											2021-04-24 11:19:18 +02:00
										 |  |  | 	InboxPath = "inbox" | 
					
						
							| 
									
										
										
										
											2021-04-22 18:51:49 +02:00
										 |  |  | 	// OutboxPath represents the webfinger outbox location | 
					
						
							| 
									
										
										
										
											2021-04-24 11:19:18 +02:00
										 |  |  | 	OutboxPath = "outbox" | 
					
						
							| 
									
										
										
										
											2021-04-22 18:51:49 +02:00
										 |  |  | 	// FollowersPath represents the webfinger followers location | 
					
						
							| 
									
										
										
										
											2021-04-24 11:19:18 +02:00
										 |  |  | 	FollowersPath = "followers" | 
					
						
							|  |  |  | 	// FollowingPath represents the webfinger following location | 
					
						
							|  |  |  | 	FollowingPath = "following" | 
					
						
							|  |  |  | 	// LikedPath represents the webfinger liked location | 
					
						
							|  |  |  | 	LikedPath = "liked" | 
					
						
							| 
									
										
										
										
											2021-04-22 18:51:49 +02:00
										 |  |  | 	// CollectionsPath represents the webfinger collections location | 
					
						
							|  |  |  | 	CollectionsPath = "collections" | 
					
						
							|  |  |  | 	// FeaturedPath represents the webfinger featured location | 
					
						
							| 
									
										
										
										
											2021-04-24 11:19:18 +02:00
										 |  |  | 	FeaturedPath = "featured" | 
					
						
							| 
									
										
										
										
											2021-04-26 21:18:39 +02:00
										 |  |  | 	// PublicKeyPath is for serving an account's public key | 
					
						
							|  |  |  | 	PublicKeyPath = "publickey" | 
					
						
							| 
									
										
										
										
											2021-04-22 18:51:49 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-24 18:15:08 +02:00
										 |  |  | // APContextKey is a type used specifically for settings values on contexts within go-fed AP request chains | 
					
						
							|  |  |  | type APContextKey string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							|  |  |  | 	// APActivityKey can be used to set and retrieve the actual go-fed pub.Activity within a context. | 
					
						
							|  |  |  | 	APActivityKey APContextKey = "activity" | 
					
						
							|  |  |  | 	// APUsernameKey can be used to set and retrieve the username of the user being interacted with. | 
					
						
							|  |  |  | 	APUsernameKey APContextKey = "username" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-22 18:51:49 +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 | 
					
						
							| 
									
										
										
										
											2021-04-24 11:19:18 +02:00
										 |  |  | 	HostURL string | 
					
						
							| 
									
										
										
										
											2021-04-22 18:51:49 +02:00
										 |  |  | 	// The web URL of the user, eg., https://example.org/@example_user | 
					
						
							| 
									
										
										
										
											2021-04-24 11:19:18 +02:00
										 |  |  | 	UserURL string | 
					
						
							| 
									
										
										
										
											2021-04-22 18:51:49 +02:00
										 |  |  | 	// The web URL for statuses of this user, eg., https://example.org/@example_user/statuses | 
					
						
							|  |  |  | 	StatusesURL string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// The webfinger URI of this user, eg., https://example.org/users/example_user | 
					
						
							| 
									
										
										
										
											2021-04-24 11:19:18 +02:00
										 |  |  | 	UserURI string | 
					
						
							| 
									
										
										
										
											2021-04-22 18:51:49 +02:00
										 |  |  | 	// The webfinger URI for this user's statuses, eg., https://example.org/users/example_user/statuses | 
					
						
							| 
									
										
										
										
											2021-04-24 11:19:18 +02:00
										 |  |  | 	StatusesURI string | 
					
						
							| 
									
										
										
										
											2021-04-22 18:51:49 +02:00
										 |  |  | 	// The webfinger URI for this user's activitypub inbox, eg., https://example.org/users/example_user/inbox | 
					
						
							| 
									
										
										
										
											2021-04-24 11:19:18 +02:00
										 |  |  | 	InboxURI string | 
					
						
							| 
									
										
										
										
											2021-04-22 18:51:49 +02:00
										 |  |  | 	// The webfinger URI for this user's activitypub outbox, eg., https://example.org/users/example_user/outbox | 
					
						
							| 
									
										
										
										
											2021-04-24 11:19:18 +02:00
										 |  |  | 	OutboxURI string | 
					
						
							| 
									
										
										
										
											2021-04-22 18:51:49 +02:00
										 |  |  | 	// The webfinger URI for this user's followers, eg., https://example.org/users/example_user/followers | 
					
						
							| 
									
										
										
										
											2021-04-24 11:19:18 +02:00
										 |  |  | 	FollowersURI string | 
					
						
							|  |  |  | 	// The webfinger URI for this user's following, eg., https://example.org/users/example_user/following | 
					
						
							|  |  |  | 	FollowingURI string | 
					
						
							|  |  |  | 	// The webfinger URI for this user's liked posts eg., https://example.org/users/example_user/liked | 
					
						
							|  |  |  | 	LikedURI string | 
					
						
							| 
									
										
										
										
											2021-04-22 18:51:49 +02:00
										 |  |  | 	// The webfinger URI for this user's featured collections, eg., https://example.org/users/example_user/collections/featured | 
					
						
							|  |  |  | 	CollectionURI string | 
					
						
							| 
									
										
										
										
											2021-04-26 21:18:39 +02:00
										 |  |  | 	// The URI for this user's public key, eg., https://example.org/users/example_user/publickey | 
					
						
							|  |  |  | 	PublicKeyURI string | 
					
						
							| 
									
										
										
										
											2021-04-22 18:51:49 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // GenerateURIsForAccount throws together a bunch of URIs for the given username, with the given protocol and host. | 
					
						
							|  |  |  | func GenerateURIsForAccount(username string, protocol string, host string) *UserURIs { | 
					
						
							|  |  |  | 	// 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) | 
					
						
							| 
									
										
										
										
											2021-04-24 11:19:18 +02:00
										 |  |  | 	followingURI := fmt.Sprintf("%s/%s", userURI, FollowingPath) | 
					
						
							|  |  |  | 	likedURI := fmt.Sprintf("%s/%s", userURI, LikedPath) | 
					
						
							| 
									
										
										
										
											2021-04-22 18:51:49 +02:00
										 |  |  | 	collectionURI := fmt.Sprintf("%s/%s/%s", userURI, CollectionsPath, FeaturedPath) | 
					
						
							| 
									
										
										
										
											2021-04-26 21:18:39 +02:00
										 |  |  | 	publicKeyURI := fmt.Sprintf("%s/%s", userURI, PublicKeyPath) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-22 18:51:49 +02:00
										 |  |  | 	return &UserURIs{ | 
					
						
							|  |  |  | 		HostURL:     hostURL, | 
					
						
							|  |  |  | 		UserURL:     userURL, | 
					
						
							|  |  |  | 		StatusesURL: statusesURL, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		UserURI:       userURI, | 
					
						
							|  |  |  | 		StatusesURI:   statusesURI, | 
					
						
							|  |  |  | 		InboxURI:      inboxURI, | 
					
						
							|  |  |  | 		OutboxURI:     outboxURI, | 
					
						
							|  |  |  | 		FollowersURI:  followersURI, | 
					
						
							| 
									
										
										
										
											2021-04-24 11:19:18 +02:00
										 |  |  | 		FollowingURI:  followingURI, | 
					
						
							|  |  |  | 		LikedURI:      likedURI, | 
					
						
							| 
									
										
										
										
											2021-04-22 18:51:49 +02:00
										 |  |  | 		CollectionURI: collectionURI, | 
					
						
							| 
									
										
										
										
											2021-04-26 21:18:39 +02:00
										 |  |  | 		PublicKeyURI:  publicKeyURI, | 
					
						
							| 
									
										
										
										
											2021-04-22 18:51:49 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-24 11:19:18 +02:00
										 |  |  | // IsUserPath returns true if the given URL path corresponds to eg /users/example_username | 
					
						
							|  |  |  | func IsUserPath(id *url.URL) bool { | 
					
						
							|  |  |  | 	return userPathRegex.MatchString(strings.ToLower(id.Path)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-24 18:15:08 +02:00
										 |  |  | // IsInboxPath returns true if the given URL path corresponds to eg /users/example_username/inbox | 
					
						
							|  |  |  | func IsInboxPath(id *url.URL) bool { | 
					
						
							|  |  |  | 	return inboxPathRegex.MatchString(strings.ToLower(id.Path)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-24 11:19:18 +02:00
										 |  |  | // IsInstanceActorPath returns true if the given URL path corresponds to eg /actors/example_username | 
					
						
							|  |  |  | func IsInstanceActorPath(id *url.URL) bool { | 
					
						
							|  |  |  | 	return actorPathRegex.MatchString(strings.ToLower(id.Path)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // IsFollowersPath returns true if the given URL path corresponds to eg /users/example_username/followers | 
					
						
							|  |  |  | func IsFollowersPath(id *url.URL) bool { | 
					
						
							|  |  |  | 	return followersPathRegex.MatchString(strings.ToLower(id.Path)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // IsFollowingPath returns true if the given URL path corresponds to eg /users/example_username/following | 
					
						
							|  |  |  | func IsFollowingPath(id *url.URL) bool { | 
					
						
							|  |  |  | 	return followingPathRegex.MatchString(strings.ToLower(id.Path)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // IsLikedPath returns true if the given URL path corresponds to eg /users/example_username/liked | 
					
						
							|  |  |  | func IsLikedPath(id *url.URL) bool { | 
					
						
							| 
									
										
										
										
											2021-04-24 18:15:08 +02:00
										 |  |  | 	return likedPathRegex.MatchString(strings.ToLower(id.Path)) | 
					
						
							| 
									
										
										
										
											2021-04-24 11:19:18 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // IsStatusesPath returns true if the given URL path corresponds to eg /users/example_username/statuses/SOME_UUID_OF_A_STATUS | 
					
						
							|  |  |  | func IsStatusesPath(id *url.URL) bool { | 
					
						
							|  |  |  | 	return statusesPathRegex.MatchString(strings.ToLower(id.Path)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ParseStatusesPath returns the username and uuid from a path such as /users/example_username/statuses/SOME_UUID_OF_A_STATUS | 
					
						
							|  |  |  | func ParseStatusesPath(id *url.URL) (username string, uuid string, err error) { | 
					
						
							|  |  |  | 	matches := statusesPathRegex.FindStringSubmatch(id.Path) | 
					
						
							|  |  |  | 	if len(matches) != 3 { | 
					
						
							|  |  |  | 		err = fmt.Errorf("expected 3 matches but matches length was %d", len(matches)) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	username = matches[1] | 
					
						
							|  |  |  | 	uuid = matches[2] | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ParseUserPath returns the username from a path such as /users/example_username | 
					
						
							|  |  |  | func ParseUserPath(id *url.URL) (username string, err error) { | 
					
						
							|  |  |  | 	matches := userPathRegex.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-04-22 18:51:49 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2021-04-24 18:15:08 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | // ParseInboxPath returns the username from a path such as /users/example_username/inbox | 
					
						
							|  |  |  | func ParseInboxPath(id *url.URL) (username string, err error) { | 
					
						
							|  |  |  | 	matches := inboxPathRegex.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 | 
					
						
							|  |  |  | } |