summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--internal/transport/dereference_test.go2
-rw-r--r--internal/typeutils/internaltoas.go36
-rw-r--r--internal/typeutils/internaltoas_test.go8
-rw-r--r--internal/typeutils/wrap_test.go2
-rw-r--r--internal/uris/helpers.go44
-rw-r--r--internal/uris/uri.go209
-rw-r--r--internal/util/paging.go6
-rw-r--r--internal/webpush/realsender.go33
8 files changed, 224 insertions, 116 deletions
diff --git a/internal/transport/dereference_test.go b/internal/transport/dereference_test.go
index 836ba2ba5..4c284700a 100644
--- a/internal/transport/dereference_test.go
+++ b/internal/transport/dereference_test.go
@@ -185,7 +185,7 @@ func (suite *DereferenceTestSuite) TestDerefLocalStatus() {
"replies": {
"first": {
"id": "http://localhost:8080/users/the_mighty_zork/statuses/01F8MHAMCHF6Y650WCRSCP4WMY/replies?page=true",
- "next": "http://localhost:8080/users/the_mighty_zork/statuses/01F8MHAMCHF6Y650WCRSCP4WMY/replies?only_other_accounts=false\u0026page=true",
+ "next": "http://localhost:8080/users/the_mighty_zork/statuses/01F8MHAMCHF6Y650WCRSCP4WMY/replies?page=true\u0026only_other_accounts=false",
"partOf": "http://localhost:8080/users/the_mighty_zork/statuses/01F8MHAMCHF6Y650WCRSCP4WMY/replies",
"type": "CollectionPage"
},
diff --git a/internal/typeutils/internaltoas.go b/internal/typeutils/internaltoas.go
index ce1501e1a..7cf736993 100644
--- a/internal/typeutils/internaltoas.go
+++ b/internal/typeutils/internaltoas.go
@@ -24,6 +24,7 @@ import (
"errors"
"fmt"
"net/url"
+ "strconv"
"strings"
"code.superseriousbusiness.org/activity/pub"
@@ -1042,7 +1043,7 @@ func (c *Converter) MentionToAS(ctx context.Context, m *gtsmodel.Mention) (vocab
domain = m.TargetAccount.Domain
}
username := m.TargetAccount.Username
- nameString := fmt.Sprintf("@%s@%s", username, domain)
+ nameString := "@" + username + "@" + domain
nameProp := streams.NewActivityStreamsNameProperty()
nameProp.AppendXMLSchemaString(nameString)
mention.SetActivityStreamsName(nameProp)
@@ -1104,7 +1105,7 @@ func (c *Converter) EmojiToAS(ctx context.Context, e *gtsmodel.Emoji) (vocab.Too
emoji.SetJSONLDId(idProp)
nameProp := streams.NewActivityStreamsNameProperty()
- nameString := fmt.Sprintf(":%s:", e.Shortcode)
+ nameString := ":" + e.Shortcode + ":"
nameProp.AppendXMLSchemaString(nameString)
emoji.SetActivityStreamsName(nameProp)
@@ -1490,7 +1491,7 @@ func (c *Converter) BlockToAS(ctx context.Context, b *gtsmodel.Block) (vocab.Act
// }
// }
func (c *Converter) StatusToASRepliesCollection(ctx context.Context, status *gtsmodel.Status, onlyOtherAccounts bool) (vocab.ActivityStreamsCollection, error) {
- collectionID := fmt.Sprintf("%s/replies", status.URI)
+ collectionID := status.URI + "/replies"
collectionIDURI, err := url.Parse(collectionID)
if err != nil {
return nil, err
@@ -1509,7 +1510,7 @@ func (c *Converter) StatusToASRepliesCollection(ctx context.Context, status *gts
// first.id
firstPageIDProp := streams.NewJSONLDIdProperty()
- firstPageID, err := url.Parse(fmt.Sprintf("%s?page=true", collectionID))
+ firstPageID, err := url.Parse(collectionID + "?page=true")
if err != nil {
return nil, gtserror.NewErrorInternalError(err)
}
@@ -1518,7 +1519,8 @@ func (c *Converter) StatusToASRepliesCollection(ctx context.Context, status *gts
// first.next
nextProp := streams.NewActivityStreamsNextProperty()
- nextPropID, err := url.Parse(fmt.Sprintf("%s?only_other_accounts=%t&page=true", collectionID, onlyOtherAccounts))
+ nextPropIDStr := collectionID + "?page=true&only_other_accounts=" + strconv.FormatBool(onlyOtherAccounts)
+ nextPropID, err := url.Parse(nextPropIDStr)
if err != nil {
return nil, gtserror.NewErrorInternalError(err)
}
@@ -1553,15 +1555,15 @@ func (c *Converter) StatusToASRepliesCollection(ctx context.Context, status *gts
// ]
// }
func (c *Converter) StatusURIsToASRepliesPage(ctx context.Context, status *gtsmodel.Status, onlyOtherAccounts bool, minID string, replies map[string]*url.URL) (vocab.ActivityStreamsCollectionPage, error) {
- collectionID := fmt.Sprintf("%s/replies", status.URI)
+ collectionID := status.URI + "/replies"
page := streams.NewActivityStreamsCollectionPage()
// .id
pageIDProp := streams.NewJSONLDIdProperty()
- pageIDString := fmt.Sprintf("%s?page=true&only_other_accounts=%t", collectionID, onlyOtherAccounts)
+ pageIDString := collectionID + "?page=true&only_other_accounts=" + strconv.FormatBool(onlyOtherAccounts)
if minID != "" {
- pageIDString = fmt.Sprintf("%s&min_id=%s", pageIDString, minID)
+ pageIDString += "&min_id=" + minID
}
pageID, err := url.Parse(pageIDString)
@@ -1593,9 +1595,9 @@ func (c *Converter) StatusURIsToASRepliesPage(ctx context.Context, status *gtsmo
// .next
nextProp := streams.NewActivityStreamsNextProperty()
- nextPropIDString := fmt.Sprintf("%s?only_other_accounts=%t&page=true", collectionID, onlyOtherAccounts)
+ nextPropIDString := collectionID + "?page=true&only_other_accounts=" + strconv.FormatBool(onlyOtherAccounts)
if highestID != "" {
- nextPropIDString = fmt.Sprintf("%s&min_id=%s", nextPropIDString, highestID)
+ nextPropIDString += "&min_id=" + minID
}
nextPropID, err := url.Parse(nextPropIDString)
@@ -1643,12 +1645,12 @@ func (c *Converter) StatusesToASOutboxPage(ctx context.Context, outboxID string,
// .id
pageIDProp := streams.NewJSONLDIdProperty()
- pageID := fmt.Sprintf("%s?page=true", outboxID)
+ pageID := outboxID + "?page=true"
if minID != "" {
- pageID = fmt.Sprintf("%s&minID=%s", pageID, minID)
+ pageID += "&min_id=" + minID
}
if maxID != "" {
- pageID = fmt.Sprintf("%s&maxID=%s", pageID, maxID)
+ pageID += "&max_id=" + maxID
}
pageIDURI, err := url.Parse(pageID)
if err != nil {
@@ -1691,7 +1693,7 @@ func (c *Converter) StatusesToASOutboxPage(ctx context.Context, outboxID string,
// .next
if lowest != "" {
nextProp := streams.NewActivityStreamsNextProperty()
- nextPropIDString := fmt.Sprintf("%s?page=true&max_id=%s", outboxID, lowest)
+ nextPropIDString := outboxID + "?page=true&max_id=" + lowest
nextPropIDURI, err := url.Parse(nextPropIDString)
if err != nil {
return nil, err
@@ -1703,7 +1705,7 @@ func (c *Converter) StatusesToASOutboxPage(ctx context.Context, outboxID string,
// .prev
if highest != "" {
prevProp := streams.NewActivityStreamsPrevProperty()
- prevPropIDString := fmt.Sprintf("%s?page=true&min_id=%s", outboxID, highest)
+ prevPropIDString := outboxID + "?page=true&min_id=" + highest
prevPropIDURI, err := url.Parse(prevPropIDString)
if err != nil {
return nil, err
@@ -1854,7 +1856,7 @@ func (c *Converter) PollVoteToASCreates(
ap.AppendTo(create, pollAuthorIRI)
// Create ID formatted as: {$voterIRI}/activity#vote{$index}/{$statusIRI}.
- createID := fmt.Sprintf("%s/activity#vote%d/%s", author.URI, i, poll.Status.URI)
+ createID := author.URI + "/activity#vote" + strconv.Itoa(i) + "/" + poll.Status.URI
ap.MustSet(ap.SetJSONLDIdStr, ap.WithJSONLDId(create), createID)
// Set Create actor appropriately.
@@ -1867,7 +1869,7 @@ func (c *Converter) PollVoteToASCreates(
note := streams.NewActivityStreamsNote()
// For AP IRI generate from author URI + poll ID + vote choice.
- id := fmt.Sprintf("%s#%s/votes/%d", author.URI, poll.ID, choice)
+ id := author.URI + "#" + poll.ID + "/votes/" + strconv.Itoa(choice)
ap.MustSet(ap.SetJSONLDIdStr, ap.WithJSONLDId(note), id)
// Attach new name property to note with vote choice.
diff --git a/internal/typeutils/internaltoas_test.go b/internal/typeutils/internaltoas_test.go
index f3e19bb81..5c3e52ddb 100644
--- a/internal/typeutils/internaltoas_test.go
+++ b/internal/typeutils/internaltoas_test.go
@@ -600,7 +600,7 @@ func (suite *InternalToASTestSuite) TestStatusToAS() {
"replies": {
"first": {
"id": "http://localhost:8080/users/the_mighty_zork/statuses/01F8MHAMCHF6Y650WCRSCP4WMY/replies?page=true",
- "next": "http://localhost:8080/users/the_mighty_zork/statuses/01F8MHAMCHF6Y650WCRSCP4WMY/replies?only_other_accounts=false\u0026page=true",
+ "next": "http://localhost:8080/users/the_mighty_zork/statuses/01F8MHAMCHF6Y650WCRSCP4WMY/replies?page=true\u0026only_other_accounts=false",
"partOf": "http://localhost:8080/users/the_mighty_zork/statuses/01F8MHAMCHF6Y650WCRSCP4WMY/replies",
"type": "CollectionPage"
},
@@ -702,7 +702,7 @@ func (suite *InternalToASTestSuite) TestStatusWithTagsToASWithIDs() {
"replies": {
"first": {
"id": "http://localhost:8080/users/admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R/replies?page=true",
- "next": "http://localhost:8080/users/admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R/replies?only_other_accounts=false\u0026page=true",
+ "next": "http://localhost:8080/users/admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R/replies?page=true\u0026only_other_accounts=false",
"partOf": "http://localhost:8080/users/admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R/replies",
"type": "CollectionPage"
},
@@ -822,7 +822,7 @@ func (suite *InternalToASTestSuite) TestStatusWithTagsToASFromDB() {
"replies": {
"first": {
"id": "http://localhost:8080/users/admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R/replies?page=true",
- "next": "http://localhost:8080/users/admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R/replies?only_other_accounts=false\u0026page=true",
+ "next": "http://localhost:8080/users/admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R/replies?page=true\u0026only_other_accounts=false",
"partOf": "http://localhost:8080/users/admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R/replies",
"type": "CollectionPage"
},
@@ -927,7 +927,7 @@ func (suite *InternalToASTestSuite) TestStatusToASWithMentions() {
"replies": {
"first": {
"id": "http://localhost:8080/users/admin/statuses/01FF25D5Q0DH7CHD57CTRS6WK0/replies?page=true",
- "next": "http://localhost:8080/users/admin/statuses/01FF25D5Q0DH7CHD57CTRS6WK0/replies?only_other_accounts=false\u0026page=true",
+ "next": "http://localhost:8080/users/admin/statuses/01FF25D5Q0DH7CHD57CTRS6WK0/replies?page=true\u0026only_other_accounts=false",
"partOf": "http://localhost:8080/users/admin/statuses/01FF25D5Q0DH7CHD57CTRS6WK0/replies",
"type": "CollectionPage"
},
diff --git a/internal/typeutils/wrap_test.go b/internal/typeutils/wrap_test.go
index c0c51b37a..4f630124b 100644
--- a/internal/typeutils/wrap_test.go
+++ b/internal/typeutils/wrap_test.go
@@ -130,7 +130,7 @@ func (suite *WrapTestSuite) TestWrapNoteInCreate() {
"replies": {
"first": {
"id": "http://localhost:8080/users/the_mighty_zork/statuses/01F8MHAMCHF6Y650WCRSCP4WMY/replies?page=true",
- "next": "http://localhost:8080/users/the_mighty_zork/statuses/01F8MHAMCHF6Y650WCRSCP4WMY/replies?only_other_accounts=false\u0026page=true",
+ "next": "http://localhost:8080/users/the_mighty_zork/statuses/01F8MHAMCHF6Y650WCRSCP4WMY/replies?page=true\u0026only_other_accounts=false",
"partOf": "http://localhost:8080/users/the_mighty_zork/statuses/01F8MHAMCHF6Y650WCRSCP4WMY/replies",
"type": "CollectionPage"
},
diff --git a/internal/uris/helpers.go b/internal/uris/helpers.go
new file mode 100644
index 000000000..410bb47e2
--- /dev/null
+++ b/internal/uris/helpers.go
@@ -0,0 +1,44 @@
+// 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/>.
+
+package uris
+
+// helper functions for string building that are designed
+// to be easily inlineable, and much faster than fmt.Sprintf().
+//
+// you can check this by ensuring these funcs are not output in:
+// go build -gcflags='-m=2' ./internal/uris/ 2>&1 | grep 'cannot inline'
+
+func buildURL1(proto, host, path1 string) string {
+ return proto + "://" + host + "/" + path1
+}
+
+func buildURL2(proto, host, path1, path2 string) string {
+ return proto + "://" + host + "/" + path1 + "/" + path2
+}
+
+func buildURL4(proto, host, path1, path2, path3, path4 string) string {
+ return proto + "://" + host + "/" + path1 + "/" + path2 + "/" + path3 + "/" + path4
+}
+
+func buildURL5(proto, host, path1, path2, path3, path4, path5 string) string {
+ return proto + "://" + host + "/" + path1 + "/" + path2 + "/" + path3 + "/" + path4 + "/" + path5
+}
+
+func buildPath4(path1, path2, path3, path4 string) string {
+ return path1 + "/" + path2 + "/" + path3 + "/" + path4
+}
diff --git a/internal/uris/uri.go b/internal/uris/uri.go
index d4bc2d829..d7ae9fe75 100644
--- a/internal/uris/uri.go
+++ b/internal/uris/uri.go
@@ -50,73 +50,127 @@ const (
RejectsPath = "rejects" // RejectsPath represents the activitypub Reject's location
)
-// UserURIs contains a bunch of UserURIs and URLs for a user, host, account, etc.
+// 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
+
+ // 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
+
+ // 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
+
+ // The web URL for statuses of this user,
+ // eg., https://example.org/@example_user/statuses
StatusesURL string
- // The activitypub URI of this user, eg., https://example.org/users/example_user
+ // The activitypub URI of this user,
+ // eg., https://example.org/users/example_user
UserURI string
- // The activitypub URI for this user's statuses, eg., https://example.org/users/example_user/statuses
+
+ // The activitypub URI for this user's statuses,
+ // eg., https://example.org/users/example_user/statuses
StatusesURI string
- // The activitypub URI for this user's activitypub inbox, eg., https://example.org/users/example_user/inbox
+
+ // The activitypub URI for this user's activitypub inbox,
+ // eg., https://example.org/users/example_user/inbox
InboxURI string
- // The activitypub URI for this user's activitypub outbox, eg., https://example.org/users/example_user/outbox
+
+ // The activitypub URI for this user's activitypub outbox,
+ // eg., https://example.org/users/example_user/outbox
OutboxURI string
- // The activitypub URI for this user's followers, eg., https://example.org/users/example_user/followers
+
+ // The activitypub URI for this user's followers,
+ // eg., https://example.org/users/example_user/followers
FollowersURI string
- // The activitypub URI for this user's following, eg., https://example.org/users/example_user/following
+
+ // The activitypub URI for this user's following,
+ // eg., https://example.org/users/example_user/following
FollowingURI string
- // The activitypub URI for this user's liked posts eg., https://example.org/users/example_user/liked
+
+ // The activitypub URI for this user's liked posts.
+ // eg., https://example.org/users/example_user/liked
LikedURI string
- // The activitypub URI for this user's featured collections, eg., https://example.org/users/example_user/collections/featured
+
+ // The activitypub URI for this user's featured collections,
+ // eg., https://example.org/users/example_user/collections/featured
FeaturedCollectionURI string
- // The URI for this user's public key, eg., https://example.org/users/example_user/publickey
+
+ // The URI for this user's public key,
+ // eg., https://example.org/users/example_user/publickey
PublicKeyURI string
}
// GenerateURIForFollow returns the AP URI for a new follow -- something like:
// https://example.org/users/whatever_user/follow/01F7XTH1QGBAPMGF49WJZ91XGC
func GenerateURIForFollow(username string, thisFollowID string) string {
- protocol := config.GetProtocol()
+ proto := config.GetProtocol()
host := config.GetHost()
- return fmt.Sprintf("%s://%s/%s/%s/%s/%s", protocol, host, UsersPath, username, FollowPath, thisFollowID)
+ return buildURL4(proto,
+ host,
+ UsersPath,
+ username,
+ FollowPath,
+ thisFollowID,
+ )
}
// GenerateURIForLike returns the AP URI for a new like/fave -- something like:
// https://example.org/users/whatever_user/liked/01F7XTH1QGBAPMGF49WJZ91XGC
func GenerateURIForLike(username string, thisFavedID string) string {
- protocol := config.GetProtocol()
+ proto := config.GetProtocol()
host := config.GetHost()
- return fmt.Sprintf("%s://%s/%s/%s/%s/%s", protocol, host, UsersPath, username, LikedPath, thisFavedID)
+ return buildURL4(proto,
+ host,
+ UsersPath,
+ username,
+ LikedPath,
+ thisFavedID,
+ )
}
// GenerateURIForUpdate returns the AP URI for a new update activity -- something like:
// https://example.org/users/whatever_user#updates/01F7XTH1QGBAPMGF49WJZ91XGC
func GenerateURIForUpdate(username string, thisUpdateID string) string {
- protocol := config.GetProtocol()
+ proto := config.GetProtocol()
host := config.GetHost()
- return fmt.Sprintf("%s://%s/%s/%s#%s/%s", protocol, host, UsersPath, username, UpdatePath, thisUpdateID)
+ return buildURL4(proto,
+ host,
+ UsersPath,
+ username,
+ UpdatePath,
+ thisUpdateID,
+ )
}
// GenerateURIForBlock returns the AP URI for a new block activity -- something like:
// https://example.org/users/whatever_user/blocks/01F7XTH1QGBAPMGF49WJZ91XGC
func GenerateURIForBlock(username string, thisBlockID string) string {
- protocol := config.GetProtocol()
+ proto := config.GetProtocol()
host := config.GetHost()
- return fmt.Sprintf("%s://%s/%s/%s/%s/%s", protocol, host, UsersPath, username, BlocksPath, thisBlockID)
+ return buildURL4(proto,
+ host,
+ UsersPath,
+ username,
+ BlocksPath,
+ thisBlockID,
+ )
}
// 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()
+ proto := config.GetProtocol()
host := config.GetHost()
- return fmt.Sprintf("%s://%s/%s/%s/%s/%s", protocol, host, UsersPath, username, MovesPath, thisMoveID)
+ return buildURL4(proto,
+ host,
+ UsersPath,
+ username,
+ MovesPath,
+ thisMoveID,
+ )
}
// GenerateURIForReport returns the API URI for a new Flag activity -- something like:
@@ -125,57 +179,74 @@ func GenerateURIForMove(username string, thisMoveID string) string {
// 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()
+ proto := config.GetProtocol()
host := config.GetHost()
- return fmt.Sprintf("%s://%s/%s/%s", protocol, host, ReportsPath, thisReportID)
+ return buildURL2(proto,
+ host,
+ ReportsPath,
+ thisReportID,
+ )
}
// GenerateURIForEmailConfirm returns a link for email confirmation -- something like:
// https://example.org/confirm_email?token=490e337c-0162-454f-ac48-4b22bb92a205
func GenerateURIForEmailConfirm(token string) string {
- protocol := config.GetProtocol()
+ proto := config.GetProtocol()
host := config.GetHost()
- return fmt.Sprintf("%s://%s/%s?token=%s", protocol, host, ConfirmEmailPath, token)
+ return buildURL1(proto, host, ConfirmEmailPath) + "?token=" + token
}
// GenerateURIForAccept returns the AP URI for a new Accept activity -- something like:
// https://example.org/users/whatever_user/accepts/01F7XTH1QGBAPMGF49WJZ91XGC
func GenerateURIForAccept(username string, thisAcceptID string) string {
- protocol := config.GetProtocol()
+ proto := config.GetProtocol()
host := config.GetHost()
- return fmt.Sprintf("%s://%s/%s/%s/%s/%s", protocol, host, UsersPath, username, AcceptsPath, thisAcceptID)
+ return buildURL4(proto,
+ host,
+ UsersPath,
+ username,
+ AcceptsPath,
+ thisAcceptID,
+ )
}
// 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()
+ proto := config.GetProtocol()
host := config.GetHost()
- return fmt.Sprintf("%s://%s/%s/%s/%s/%s", protocol, host, UsersPath, username, RejectsPath, thisRejectID)
+ return buildURL4(proto,
+ host,
+ UsersPath,
+ username,
+ RejectsPath,
+ thisRejectID,
+ )
}
-// GenerateURIsForAccount throws together a bunch of URIs for the given username, with the given protocol and host.
-func GenerateURIsForAccount(username string) *UserURIs {
- protocol := config.GetProtocol()
+// GenerateURIsForAccount throws together a bunch of URIs
+// for the given username, with the given protocol and host.
+func GenerateURIsForAccount(username string) UserURIs {
+ proto := config.GetProtocol()
host := config.GetHost()
- // 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)
+ // URLs for serving web requests.
+ hostURL := proto + "://" + host
+ userURL := hostURL + "/@" + username
+ statusesURL := 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)
- publicKeyURI := fmt.Sprintf("%s/%s", userURI, PublicKeyPath)
-
- return &UserURIs{
+ userURI := hostURL + "/" + UsersPath + "/" + username
+ statusesURI := userURI + "/" + StatusesPath
+ inboxURI := userURI + "/" + InboxPath
+ outboxURI := userURI + "/" + OutboxPath
+ followersURI := userURI + "/" + FollowersPath
+ followingURI := userURI + "/" + FollowingPath
+ likedURI := userURI + "/" + LikedPath
+ collectionURI := userURI + "/" + CollectionsPath + "/" + FeaturedPath
+ publicKeyURI := userURI + "/" + PublicKeyPath
+
+ return UserURIs{
HostURL: hostURL,
UserURL: userURL,
StatusesURL: statusesURL,
@@ -205,19 +276,16 @@ func URIForAttachment(
mediaID string,
extension string,
) string {
- const format = "%s://%s/%s/%s/%s/%s/%s.%s"
-
- return fmt.Sprintf(
- format,
- config.GetProtocol(),
- config.GetHost(),
+ proto := config.GetProtocol()
+ host := config.GetHost()
+ return buildURL5(proto,
+ host,
FileserverPath,
accountID,
mediaType,
mediaSize,
mediaID,
- extension,
- )
+ ) + "." + extension
}
// StoragePathForAttachment generates a storage
@@ -233,16 +301,12 @@ func StoragePathForAttachment(
mediaID string,
extension string,
) string {
- const format = "%s/%s/%s/%s.%s"
-
- return fmt.Sprintf(
- format,
+ return buildPath4(
accountID,
mediaType,
mediaSize,
mediaID,
- extension,
- )
+ ) + "." + extension
}
// URIForEmoji generates an
@@ -252,12 +316,10 @@ func StoragePathForAttachment(
//
// "https://example.org/emoji/01FPST9QK4V5XWS3F9Z4F2G1X7"
func URIForEmoji(emojiID string) string {
- const format = "%s://%s/%s/%s"
-
- return fmt.Sprintf(
- format,
- config.GetProtocol(),
- config.GetHost(),
+ proto := config.GetProtocol()
+ host := config.GetHost()
+ return buildURL2(proto,
+ host,
EmojiPath,
emojiID,
)
@@ -265,9 +327,14 @@ func URIForEmoji(emojiID string) string {
// URIForTag generates an activitypub uri for a tag.
func URIForTag(name string) string {
- protocol := config.GetProtocol()
+ proto := config.GetProtocol()
host := config.GetHost()
- return fmt.Sprintf("%s://%s/%s/%s", protocol, host, TagsPath, strings.ToLower(name))
+ name = strings.ToLower(name)
+ return buildURL2(proto,
+ host,
+ TagsPath,
+ name,
+ )
}
// IsUserPath returns true if the given URL path corresponds to eg /users/example_username
diff --git a/internal/util/paging.go b/internal/util/paging.go
index 712498313..69bacd2cd 100644
--- a/internal/util/paging.go
+++ b/internal/util/paging.go
@@ -18,8 +18,8 @@
package util
import (
- "fmt"
"net/url"
+ "strconv"
"strings"
apimodel "code.superseriousbusiness.org/gotosocial/internal/api/model"
@@ -71,7 +71,7 @@ func PackagePageableResponse(params PageableResponseParams) (*apimodel.PageableR
nextRaw := params.NextMaxIDKey + "=" + params.NextMaxIDValue
if params.Limit != 0 {
- nextRaw = fmt.Sprintf("limit=%d&", params.Limit) + nextRaw
+ nextRaw = "limit=" + strconv.Itoa(params.Limit) + "&" + nextRaw
}
for _, p := range params.ExtraQueryParams {
@@ -96,7 +96,7 @@ func PackagePageableResponse(params PageableResponseParams) (*apimodel.PageableR
prevRaw := params.PrevMinIDKey + "=" + params.PrevMinIDValue
if params.Limit != 0 {
- prevRaw = fmt.Sprintf("limit=%d&", params.Limit) + prevRaw
+ prevRaw = "limit=" + strconv.Itoa(params.Limit) + "&" + prevRaw
}
for _, p := range params.ExtraQueryParams {
diff --git a/internal/webpush/realsender.go b/internal/webpush/realsender.go
index 99472c815..831c5e4f2 100644
--- a/internal/webpush/realsender.go
+++ b/internal/webpush/realsender.go
@@ -20,7 +20,6 @@ package webpush
import (
"context"
"encoding/json"
- "fmt"
"io"
"net/http"
"slices"
@@ -299,41 +298,37 @@ func formatNotificationTitle(
switch notification.NotificationType {
case gtsmodel.NotificationFollow:
- return fmt.Sprintf("%s followed you", displayNameOrAcct)
+ return displayNameOrAcct + " followed you"
case gtsmodel.NotificationFollowRequest:
- return fmt.Sprintf("%s requested to follow you", displayNameOrAcct)
+ return displayNameOrAcct + " requested to followed you"
case gtsmodel.NotificationMention:
- return fmt.Sprintf("%s mentioned you", displayNameOrAcct)
+ return displayNameOrAcct + " mentioned you"
case gtsmodel.NotificationReblog:
- return fmt.Sprintf("%s boosted your post", displayNameOrAcct)
+ return displayNameOrAcct + " boosted your post"
case gtsmodel.NotificationFavourite:
- return fmt.Sprintf("%s faved your post", displayNameOrAcct)
+ return displayNameOrAcct + " faved your post"
case gtsmodel.NotificationPoll:
if subscription.AccountID == notification.TargetAccountID {
return "Your poll has ended"
}
- return fmt.Sprintf("%s's poll has ended", displayNameOrAcct)
+ return displayNameOrAcct + "'s poll has ended"
case gtsmodel.NotificationStatus:
- return fmt.Sprintf("%s posted", displayNameOrAcct)
+ return displayNameOrAcct + " posted"
case gtsmodel.NotificationAdminSignup:
- return fmt.Sprintf("%s requested to sign up", displayNameOrAcct)
+ return displayNameOrAcct + " requested to sign up"
case gtsmodel.NotificationPendingFave:
- return fmt.Sprintf("%s faved your post, which requires your approval", displayNameOrAcct)
+ return displayNameOrAcct + " faved your post, which requires your approval"
case gtsmodel.NotificationPendingReply:
- return fmt.Sprintf("%s mentioned you, which requires your approval", displayNameOrAcct)
+ return displayNameOrAcct + " mentioned you, which requires your approval"
case gtsmodel.NotificationPendingReblog:
- return fmt.Sprintf("%s boosted your post, which requires your approval", displayNameOrAcct)
+ return displayNameOrAcct + " boosted your post, which requires your approval"
case gtsmodel.NotificationAdminReport:
- return fmt.Sprintf("%s submitted a report", displayNameOrAcct)
+ return displayNameOrAcct + " submitted a report"
case gtsmodel.NotificationUpdate:
- return fmt.Sprintf("%s updated their post", displayNameOrAcct)
+ return displayNameOrAcct + " updated their post"
default:
log.Warnf(ctx, "Unknown notification type: %d", notification.NotificationType)
- return fmt.Sprintf(
- "%s did something (unknown notification type %d)",
- displayNameOrAcct,
- notification.NotificationType,
- )
+ return displayNameOrAcct + " did something (unknown notification type)"
}
}