Skip to content

Commit

Permalink
Merge pull request #67 from planetary-social/remove_unfollows
Browse files Browse the repository at this point in the history
Remove unfollows
  • Loading branch information
dcadenas authored Sep 14, 2024
2 parents e26e9c8 + 57b4681 commit 2a8545e
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 135 deletions.
26 changes: 5 additions & 21 deletions service/adapters/apns/apns.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,30 +140,21 @@ func FollowChangePayload(followChange domain.FollowChangeBatch) ([]byte, error)

func FollowChangePayloadWithValidation(followChange domain.FollowChangeBatch, validate bool) ([]byte, error) {
alertMessage := ""
totalNpubs := len(followChange.Follows) + len(followChange.Unfollows)
totalNpubs := len(followChange.Follows)
if validate && totalNpubs > MAX_TOTAL_NPUBS {
return nil, errors.New("FollowChangeBatch for followee " + followChange.Followee.Hex() + " has too many npubs (" + fmt.Sprint(totalNpubs) + "). MAX_TOTAL_NPUBS is " + fmt.Sprint(MAX_TOTAL_NPUBS))
}

singleChange := totalNpubs == 1

if singleChange {
isFollow := len(followChange.Follows) == 1
if strings.HasPrefix(followChange.FriendlyFollower, "npub") {
if isFollow {
alertMessage = "You have a new follower!"
} else {
alertMessage = "You've been unfollowed!"
}
alertMessage = "You have a new follower!"
} else {
if isFollow {
alertMessage = followChange.FriendlyFollower + " is a new follower!"
} else {
alertMessage = followChange.FriendlyFollower + " has unfollowed you!"
}
alertMessage = followChange.FriendlyFollower + " is a new follower!"
}
} else {
alertMessage = fmt.Sprintf("You have %d new followers and %d unfollows!", len(followChange.Follows), len(followChange.Unfollows))
alertMessage = fmt.Sprintf("You have %d new followers!", len(followChange.Follows))
}

followeeNpub, error := nip19.EncodePublicKey(followChange.Followee.Hex())
Expand All @@ -176,25 +167,18 @@ func FollowChangePayloadWithValidation(followChange domain.FollowChangeBatch, va
return nil, errors.Wrap(error, "error encoding follow npubs")
}

npubUnfollows, error := pubkeysToNpubs(followChange.Unfollows)
if error != nil {
return nil, errors.Wrap(error, "error encoding unfollow npubs")
}

// See https://developer.apple.com/documentation/usernotifications/generating-a-remote-notification

var data map[string]interface{}

if singleChange {
data = map[string]interface{}{
"follows": npubFollows,
"unfollows": npubUnfollows,
"friendlyFollower": followChange.FriendlyFollower,
}
} else {
data = map[string]interface{}{
"follows": npubFollows,
"unfollows": npubUnfollows,
"follows": npubFollows,
}
}

Expand Down
80 changes: 9 additions & 71 deletions service/adapters/apns/apns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ func TestFollowChangePayload_SingleFollow(t *testing.T) {
Followee: pk1,
FriendlyFollower: "npub_someFollower",
Follows: []domain.PublicKey{pk2},
Unfollows: nil,
}

payload, err := apns.FollowChangePayload(batch)
Expand All @@ -36,44 +35,6 @@ func TestFollowChangePayload_SingleFollow(t *testing.T) {
},
"data": map[string]interface{}{
"follows": []interface{}{pk2Npub}, // Use []interface{}
"unfollows": []interface{}{},
"friendlyFollower": batch.FriendlyFollower,
},
}

var actualPayload map[string]interface{}
err = json.Unmarshal(payload, &actualPayload)
require.NoError(t, err)

require.Equal(t, expectedPayload, actualPayload)
}

func TestFollowChangePayload_SingleUnfollow(t *testing.T) {
pk1, pk1Npub := fixtures.PublicKeyAndNpub()
pk2, pk2Npub := fixtures.PublicKeyAndNpub()

batch := domain.FollowChangeBatch{
Followee: pk1,
FriendlyFollower: "npub_someFollower",
Follows: nil,
Unfollows: []domain.PublicKey{pk2},
}

payload, err := apns.FollowChangePayload(batch)
require.NoError(t, err)

expectedAlert := "You've been unfollowed!"
expectedPayload := map[string]interface{}{
"aps": map[string]interface{}{
"alert": expectedAlert,
"sound": "default",
"badge": float64(1), // Convert badge to float64
"thread-id": pk1Npub,
"interruption-level": "passive",
},
"data": map[string]interface{}{
"follows": []interface{}{},
"unfollows": []interface{}{pk2Npub}, // Use []interface{}
"friendlyFollower": batch.FriendlyFollower,
},
}
Expand All @@ -89,19 +50,17 @@ func TestFollowChangePayload_MultipleFollowsUnfollows(t *testing.T) {
pk1, pk1Npub := fixtures.PublicKeyAndNpub()
pk2, pk2Npub := fixtures.PublicKeyAndNpub()
pk3, pk3Npub := fixtures.PublicKeyAndNpub()
pk4, pk4Npub := fixtures.PublicKeyAndNpub()

batch := domain.FollowChangeBatch{
Followee: pk1,
FriendlyFollower: "FriendlyUser",
Follows: []domain.PublicKey{pk2, pk3},
Unfollows: []domain.PublicKey{pk4},
}

payload, err := apns.FollowChangePayload(batch)
require.NoError(t, err)

expectedAlert := "You have 2 new followers and 1 unfollows!"
expectedAlert := "You have 2 new followers!"
expectedPayload := map[string]interface{}{
"aps": map[string]interface{}{
"alert": expectedAlert,
Expand All @@ -111,8 +70,7 @@ func TestFollowChangePayload_MultipleFollowsUnfollows(t *testing.T) {
"interruption-level": "passive",
},
"data": map[string]interface{}{
"follows": []interface{}{pk2Npub, pk3Npub}, // Use []interface{}
"unfollows": []interface{}{pk4Npub}, // Use []interface{}
"follows": []interface{}{pk2Npub, pk3Npub}, // Use []interface{}
},
}

Expand All @@ -131,7 +89,6 @@ func TestFollowChangePayload_SingleFollow_WithFriendlyFollower(t *testing.T) {
Followee: pk1,
FriendlyFollower: "John Doe",
Follows: []domain.PublicKey{pk2},
Unfollows: nil,
}

payload, err := apns.FollowChangePayload(batch)
Expand All @@ -148,7 +105,6 @@ func TestFollowChangePayload_SingleFollow_WithFriendlyFollower(t *testing.T) {
},
"data": map[string]interface{}{
"follows": []interface{}{pk2Npub}, // Use []interface{}
"unfollows": []interface{}{},
"friendlyFollower": batch.FriendlyFollower,
},
}
Expand All @@ -171,18 +127,16 @@ func TestFollowChangePayload_BatchedFollow_WithNoFriendlyFollower(t *testing.T)
pk1, pk1Npub := fixtures.PublicKeyAndNpub()
pk2, pk2Npub := fixtures.PublicKeyAndNpub()
pk3, pk3Npub := fixtures.PublicKeyAndNpub()
pk4, pk4Npub := fixtures.PublicKeyAndNpub()

batch := domain.FollowChangeBatch{
Followee: pk1,
Follows: []domain.PublicKey{pk2, pk3},
Unfollows: []domain.PublicKey{pk4},
Followee: pk1,
Follows: []domain.PublicKey{pk2, pk3},
}

payload, err := apns.FollowChangePayload(batch)
require.NoError(t, err)

expectedAlert := "You have 2 new followers and 1 unfollows!"
expectedAlert := "You have 2 new followers!"
expectedPayload := map[string]interface{}{
"aps": map[string]interface{}{
"alert": expectedAlert,
Expand All @@ -192,8 +146,7 @@ func TestFollowChangePayload_BatchedFollow_WithNoFriendlyFollower(t *testing.T)
"interruption-level": "passive",
},
"data": map[string]interface{}{
"follows": []interface{}{pk2Npub, pk3Npub}, // Use []interface{}
"unfollows": []interface{}{pk4Npub},
"follows": []interface{}{pk2Npub, pk3Npub}, // Use []interface{}
},
}

Expand All @@ -217,17 +170,12 @@ func TestFollowChangePayload_Exceeds4096Bytes_With59TotalNpubs(t *testing.T) {
Followee: pk1,
FriendlyFollower: "npub_someFollower_wont_be_added",
Follows: []domain.PublicKey{},
Unfollows: []domain.PublicKey{},
}

for i := 0; i < 29; i++ { // 29 follows
for i := 0; i < 59; i++ {
follow, _ := fixtures.PublicKeyAndNpub()
batch.Follows = append(batch.Follows, follow)
}
for i := 0; i < 30; i++ { // 30 unfollows
unfollow, _ := fixtures.PublicKeyAndNpub()
batch.Unfollows = append(batch.Unfollows, unfollow)
}

payload, err := apns.FollowChangePayloadWithValidation(batch, false)
require.NoError(t, err)
Expand All @@ -245,17 +193,12 @@ func TestFollowChangePayload_ValidPayload_With58TotalNpubs_IsValid(t *testing.T)
Followee: pk1,
FriendlyFollower: "npub_someFollower_wont_be_added",
Follows: []domain.PublicKey{},
Unfollows: []domain.PublicKey{},
}

for i := 0; i < 29; i++ { // 29 follows
for i := 0; i < 58; i++ {
follow, _ := fixtures.PublicKeyAndNpub()
batch.Follows = append(batch.Follows, follow)
}
for i := 0; i < 29; i++ { // 29 unfollows
unfollow, _ := fixtures.PublicKeyAndNpub()
batch.Unfollows = append(batch.Unfollows, unfollow)
}

payload, err := apns.FollowChangePayloadWithValidation(batch, true) // With validation
require.NoError(t, err)
Expand All @@ -273,17 +216,12 @@ func TestFollowChangePayload_InvalidPayload_With59TotalNpubs_Fails_With_Validati
Followee: pk1,
FriendlyFollower: "npub_someFollower_wont_be_added",
Follows: []domain.PublicKey{},
Unfollows: []domain.PublicKey{},
}

for i := 0; i < 29; i++ { // 29 follows
for i := 0; i < 59; i++ { // 29 follows
follow, _ := fixtures.PublicKeyAndNpub()
batch.Follows = append(batch.Follows, follow)
}
for i := 0; i < 30; i++ { // 30 unfollows
unfollow, _ := fixtures.PublicKeyAndNpub()
batch.Unfollows = append(batch.Unfollows, unfollow)
}

payload, err := apns.FollowChangePayload(batch) // This always validates
require.Error(t, err)
Expand Down
20 changes: 3 additions & 17 deletions service/domain/follow_change_batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,13 @@ type FollowChangeBatch struct {
Followee PublicKey `json:"followee"`
FriendlyFollower string `json:"friendlyFollower"`
Follows []PublicKey `json:"follows"`
Unfollows []PublicKey `json:"unfollows"`
}

func (f *FollowChangeBatch) UnmarshalJSON(data []byte) error {
var temp struct {
Followee string `json:"followee"`
FriendlyFollower string `json:"friendlyFollower"`
Follows []string `json:"follows"`
Unfollows []string `json:"unfollows"`
}

if err := json.Unmarshal(data, &temp); err != nil {
Expand All @@ -46,14 +44,6 @@ func (f *FollowChangeBatch) UnmarshalJSON(data []byte) error {
}
}

f.Unfollows = make([]PublicKey, len(temp.Unfollows))
for i, npub := range temp.Unfollows {
f.Unfollows[i], err = NewPublicKeyFromNpub(npub)
if err != nil {
return errors.New("invalid npub for unfollow: " + err.Error())
}
}

return nil
}

Expand All @@ -63,13 +53,9 @@ func (f FollowChangeBatch) String() string {
friendlyFollowee = f.Followee.Hex()
}

if len(f.Follows)+len(f.Unfollows) == 1 {
if len(f.Follows) == 1 {
return fmt.Sprintf("Follow: %s -----> %s", f.FriendlyFollower, friendlyFollowee)
} else {
return fmt.Sprintf("Unfollow: %s --x--> %s", f.FriendlyFollower, friendlyFollowee)
}
if len(f.Follows) == 1 {
return fmt.Sprintf("Follow: %s -----> %s", f.FriendlyFollower, friendlyFollowee)
}

return fmt.Sprintf("Follow aggregate: %d follows, %d unfollows for %s", len(f.Follows), len(f.Unfollows), friendlyFollowee)
return fmt.Sprintf("Follow aggregate: %d followers for %s", len(f.Follows), friendlyFollowee)
}
31 changes: 5 additions & 26 deletions service/domain/follow_change_batch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,11 @@ func TestFollowChangeBatch_UnmarshalJSON_Valid(t *testing.T) {
pk1, pk1Npub := fixtures.PublicKeyAndNpub()
pk2, pk2Npub := fixtures.PublicKeyAndNpub()
pk3, pk3Npub := fixtures.PublicKeyAndNpub()
pk4, pk4Npub := fixtures.PublicKeyAndNpub()

jsonData := `{
"followee": "` + pk1Npub + `",
"friendlyFollower": "FriendlyUser",
"follows": ["` + pk2Npub + `", "` + pk3Npub + `"],
"unfollows": ["` + pk4Npub + `"]
"follows": ["` + pk2Npub + `", "` + pk3Npub + `"]
}`

var batch domain.FollowChangeBatch
Expand All @@ -29,7 +27,6 @@ func TestFollowChangeBatch_UnmarshalJSON_Valid(t *testing.T) {
assert.Equal(t, pk1, batch.Followee)
assert.Equal(t, "FriendlyUser", batch.FriendlyFollower)
assert.Equal(t, []domain.PublicKey{pk2, pk3}, batch.Follows)
assert.Equal(t, []domain.PublicKey{pk4}, batch.Unfollows)
}

func TestFollowChangeBatch_UnmarshalJSON_InvalidFollowee(t *testing.T) {
Expand All @@ -38,8 +35,7 @@ func TestFollowChangeBatch_UnmarshalJSON_InvalidFollowee(t *testing.T) {
jsonData := `{
"followee": "invalid",
"friendlyFollower": "FriendlyUser",
"follows": ["` + pk1Npub + `"],
"unfollows": []
"follows": ["` + pk1Npub + `"]
}`

var batch domain.FollowChangeBatch
Expand All @@ -54,8 +50,7 @@ func TestFollowChangeBatch_UnmarshalJSON_InvalidFollows(t *testing.T) {
jsonData := `{
"followee": "` + pk1Npub + `",
"friendlyFollower": "FriendlyUser",
"follows": ["invalid"],
"unfollows": []
"follows": ["invalid"]
}`

var batch domain.FollowChangeBatch
Expand All @@ -78,33 +73,17 @@ func TestFollowChangeBatch_String_SingleFollow(t *testing.T) {
assert.Equal(t, expected, batch.String())
}

func TestFollowChangeBatch_String_SingleUnfollow(t *testing.T) {
pk1, pk1Npub := fixtures.PublicKeyAndNpub()
pk2, _ := fixtures.PublicKeyAndNpub()

batch := domain.FollowChangeBatch{
Followee: pk1,
FriendlyFollower: "FriendlyUser",
Unfollows: []domain.PublicKey{pk2},
}

expected := "Unfollow: FriendlyUser --x--> " + pk1Npub
assert.Equal(t, expected, batch.String())
}

func TestFollowChangeBatch_String_MultipleFollowsUnfollows(t *testing.T) {
func TestFollowChangeBatch_String_MultipleFollows(t *testing.T) {
pk1, pk1Npub := fixtures.PublicKeyAndNpub()
pk2, _ := fixtures.PublicKeyAndNpub()
pk3, _ := fixtures.PublicKeyAndNpub()
pk4, _ := fixtures.PublicKeyAndNpub()

batch := domain.FollowChangeBatch{
Followee: pk1,
FriendlyFollower: "FriendlyUser",
Follows: []domain.PublicKey{pk2, pk3},
Unfollows: []domain.PublicKey{pk4},
}

expected := "Follow aggregate: 2 follows, 1 unfollows for " + pk1Npub
expected := "Follow aggregate: 2 followers for " + pk1Npub
assert.Equal(t, expected, batch.String())
}

0 comments on commit 2a8545e

Please sign in to comment.