Skip to content

Commit

Permalink
Endpoints for following
Browse files Browse the repository at this point in the history
  • Loading branch information
ilmari-h committed Nov 11, 2024
1 parent 6d5b348 commit b4eac81
Show file tree
Hide file tree
Showing 10 changed files with 1,779 additions and 5 deletions.
1 change: 1 addition & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ jobs:
TAPESTRY_API_KEY: ${{ secrets.TAPESTRY_API_KEY }}
TAPESTRY_API_BASE_URL: ${{ secrets.TAPESTRY_API_BASE_URL }}
run: |
cd tests
go test --run TestProfileOperations
go test --run TestContentOperations
go test --run TestCommentOperations
Expand Down
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,21 @@

[![API tests](https://github.com/Access-Labs-Inc/tapestry-go/actions/workflows/go.yml/badge.svg)](https://github.com/Access-Labs-Inc/tapestry-go/actions/workflows/go.yml)

Bindings for the Tapestry API documented at <https://tapestry.apidocumentation.com/reference>
Bindings for the Tapestry API.

Tapestry documentation: <https://docs.usetapestry.dev/documentation/what-is-tapestry>

Tapestry API reference: <https://tapestry.apidocumentation.com/reference>


## Completness
- Profiles
- [x] Find or create a profile
- [ ] Get profiles
- [x] Get a profile by ID
- [x] Update a profile
- [ ] get followers
- [ ] get following
- [x] get followers
- [x] get following
- [ ] Get a list of profiles in a user's network that also follow a given profile

- Contents
Expand All @@ -33,5 +38,5 @@ Bindings for the Tapestry API documented at <https://tapestry.apidocumentation.c
- [x] Delete a like

- Followers
- [ ] Follow a profile
- [ ] Unfollow a profile
- [x] Follow a profile
- [x] Unfollow a profile
88 changes: 88 additions & 0 deletions api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,3 +298,91 @@ func TestLikeOperations(t *testing.T) {
t.Errorf("Expected like count 0 after delete, got %d", contentAfterDelete.SocialCounts.LikeCount)
}
}

func generateSolanaAddress() string {
const charset = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
const length = 32
b := make([]byte, length)
for i := range b {
b[i] = charset[time.Now().UnixNano()%int64(len(charset))]
}
return string(b)
}

func TestFollowerOperations(t *testing.T) {
// Create two additional test profiles with random Solana addresses
follower1, err := client.FindOrCreateProfile(FindOrCreateProfileParameters{
WalletAddress: generateSolanaAddress(),
Username: "follower1_" + time.Now().Format("20060102150405"),
})
if err != nil {
t.Fatalf("Failed to create follower1: %v", err)
}

follower2, err := client.FindOrCreateProfile(FindOrCreateProfileParameters{
WalletAddress: generateSolanaAddress(),
Username: "follower2_" + time.Now().Format("20060102150405"),
})
if err != nil {
t.Fatalf("Failed to create follower2: %v", err)
}

// Add followers to test profile
err = client.AddFollower(follower1.Profile.ID, testProfile.Profile.ID)
if err != nil {
t.Fatalf("Failed to add follower1: %v", err)
}

err = client.AddFollower(follower2.Profile.ID, testProfile.Profile.ID)
if err != nil {
t.Fatalf("Failed to add follower2: %v", err)
}

// Also make follower1 follow follower2
err = client.AddFollower(follower1.Profile.ID, follower2.Profile.ID)
if err != nil {
t.Fatalf("Failed to make follower1 follow follower2: %v", err)
}

// Verify followers of test profile
followers, err := client.GetFollowers(testProfile.Profile.ID)
if err != nil {
t.Fatalf("GetFollowers failed: %v", err)
}
if len(followers.Profiles) != 2 {
t.Errorf("Expected 2 followers, got %d", len(followers.Profiles))
}

// Verify following for follower1
following, err := client.GetFollowing(follower1.Profile.ID)
if err != nil {
t.Fatalf("GetFollowing failed: %v", err)
}
if len(following.Profiles) != 2 {
t.Errorf("Expected follower1 to be following 2 profiles, got %d", len(following.Profiles))
}

// Remove one follower and verify
err = client.RemoveFollower(follower1.Profile.ID, testProfile.Profile.ID)
if err != nil {
t.Fatalf("RemoveFollower failed: %v", err)
}

// Verify updated follower count
updatedFollowers, err := client.GetFollowers(testProfile.Profile.ID)
if err != nil {
t.Fatalf("GetFollowers after removal failed: %v", err)
}
if len(updatedFollowers.Profiles) != 1 {
t.Errorf("Expected 1 follower after removal, got %d", len(updatedFollowers.Profiles))
}

// Verify updated following count for follower1
updatedFollowing, err := client.GetFollowing(follower1.Profile.ID)
if err != nil {
t.Fatalf("GetFollowing after removal failed: %v", err)
}
if len(updatedFollowing.Profiles) != 1 {
t.Errorf("Expected follower1 to be following 1 profile after removal, got %d", len(updatedFollowing.Profiles))
}
}
67 changes: 67 additions & 0 deletions followers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package tapestry

import (
"encoding/json"
"fmt"
"net/http"
"strings"
)

type FollowRequest struct {
StartID string `json:"startId"`
EndID string `json:"endId"`
}

func (c *TapestryClient) AddFollower(startID, endID string) error {
url := fmt.Sprintf("%s/followers/add?apiKey=%s", c.tapestryApiBaseUrl, c.apiKey)

jsonBody, err := json.Marshal(FollowRequest{
StartID: startID,
EndID: endID,
})
if err != nil {
return fmt.Errorf("error marshaling request: %w", err)
}

resp, err := http.Post(url, "application/json", strings.NewReader(string(jsonBody)))
if err != nil {
return fmt.Errorf("error making request: %w", err)
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return fmt.Errorf("unexpected status code: %d", resp.StatusCode)
}

return nil
}

func (c *TapestryClient) RemoveFollower(startID, endID string) error {
url := fmt.Sprintf("%s/followers/remove?apiKey=%s", c.tapestryApiBaseUrl, c.apiKey)

jsonBody, err := json.Marshal(FollowRequest{
StartID: startID,
EndID: endID,
})
if err != nil {
return fmt.Errorf("error marshaling request: %w", err)
}

req, err := http.NewRequest(http.MethodPost, url, strings.NewReader(string(jsonBody)))
if err != nil {
return fmt.Errorf("error creating request: %w", err)
}
req.Header.Set("Content-Type", "application/json")

resp, err := http.DefaultClient.Do(req)
if err != nil {
return fmt.Errorf("error making request: %w", err)
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return fmt.Errorf("unexpected status code: %d", resp.StatusCode)
}

return nil
}
Loading

0 comments on commit b4eac81

Please sign in to comment.