- README.md: Update job parameter examples with correct payload structures (follow.follow, vote.votecast, reaction.reacttosomething, etc.) - documentation.md: Fix job names (posts.getpublic -> post.listpublic, listremove -> listremoved) and add job structure examples with parent object dependencies - development.md: Minor polish (comprehensive -> thorough)
653 lines
15 KiB
Markdown
653 lines
15 KiB
Markdown
# TrustCafé API Wrapper
|
|
|
|
A Python wrapper for the TrustCafé API, providing a convenient interface to interact with TrustCafé features programmatically.
|
|
|
|
## Table of Contents
|
|
|
|
- [Prerequisites](#prerequisites)
|
|
- [Installation](#installation)
|
|
- [Quick Start](#quick-start)
|
|
- [Authentication](#authentication)
|
|
- [API Reference](#api-reference)
|
|
- [Jobs](#jobs)
|
|
- [Wrappers](#wrappers)
|
|
- [Custom Requests](#custom-requests)
|
|
- [Environment Setup](#environment-setup)
|
|
- [Debug Mode](#debug-mode)
|
|
- [Examples](#examples)
|
|
- [Development](#development)
|
|
- [Testing](#testing)
|
|
|
|
## Prerequisites
|
|
|
|
Before you begin, ensure you have:
|
|
|
|
- **Python 3.11 or higher** installed
|
|
- **API Client ID and Secret** from TrustCafé
|
|
- **python-dotenv** (for `.env` file support) or ability to set environment variables
|
|
|
|
### Getting API Credentials
|
|
|
|
1. Visit your TrustCafé account page:
|
|
- [Production API Access](https://www.trustcafe.io/en/myaccount/apiaccess)
|
|
- [Alpha Environment API Access](https://alpha.wts2.net/en/myaccount/apiaccess)
|
|
|
|
2. Click "Create new client credentials key pair"
|
|
|
|
3. Choose the scopes you need (or select all for full access)
|
|
|
|
4. Click "Save"
|
|
|
|
5. Copy the **client_id** and **client_secret** to your environment:
|
|
- The secret cannot be retrieved later — make sure to save it securely
|
|
- Do not commit these credentials to version control
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
# Using pip
|
|
pip install trustcafeapiwrapper
|
|
|
|
# Using uv (recommended)
|
|
uv add trustcafeapiwrapper
|
|
```
|
|
|
|
## Quick Start
|
|
|
|
The simplest way to get started:
|
|
|
|
```python
|
|
import trustcafeapiwrapper
|
|
import os
|
|
|
|
# Initialize the API client
|
|
API = trustcafeapiwrapper.APIClient(
|
|
client_id=os.getenv("TRUSTCAFE_CLIENT_ID"),
|
|
client_secret=os.getenv("TRUSTCAFE_CLIENT_SECRET"),
|
|
env="alpha", # Options: "alpha" or "production"
|
|
debug=False
|
|
)
|
|
|
|
# Authenticate and get user profile
|
|
API.handle_token()
|
|
profile = API.run_job('userprofile.get', "your-username")
|
|
print(profile)
|
|
```
|
|
|
|
## Authentication
|
|
|
|
The API wrapper handles OAuth2 client-credentials authentication automatically.
|
|
|
|
### Automatic Token Management
|
|
|
|
```python
|
|
API.handle_token()
|
|
```
|
|
|
|
**What it does:**
|
|
- Checks for an existing token file (`token_data_{env}.json`)
|
|
- If found, verifies if the token is still valid
|
|
- If expired or not found, obtains a new access token (~3 month duration)
|
|
- Saves the token to a local file for future requests
|
|
|
|
### Manual Token Management
|
|
|
|
For more control over token storage:
|
|
|
|
```python
|
|
def getMyToken():
|
|
# Retrieve token from your custom storage (database, file, etc.)
|
|
return {
|
|
"access_token": "your_token_here",
|
|
"access_token_timeout": 9999999999 # Unix timestamp
|
|
}
|
|
|
|
def saveMyToken(token_data):
|
|
# Save to your preferred storage
|
|
with open("my_token_cache.json", "w") as f:
|
|
json.dump(token_data, f)
|
|
return True
|
|
|
|
# Set the token manually or pass to initialize
|
|
API = APIClient(
|
|
client_id=os.getenv("client_id"),
|
|
client_secret=os.getenv("client_secret"),
|
|
env="production",
|
|
debug=False
|
|
)
|
|
|
|
# Use existing token or get a new one
|
|
if not API.is_token_valid():
|
|
saveMyToken(API.sign_in())
|
|
```
|
|
|
|
### Token Validation
|
|
|
|
```python
|
|
if API.is_token_valid():
|
|
print("Token is valid")
|
|
else:
|
|
API.handle_token() # Get a new token
|
|
```
|
|
|
|
## Environment Setup
|
|
|
|
The wrapper supports two environments:
|
|
|
|
| Environment | URL | Purpose |
|
|
|------------|-----|---------|
|
|
| `alpha` | `alpha.wts2.net` | Development/staging environment |
|
|
| `production` | `trustcafe.io` | Production environment |
|
|
|
|
```python
|
|
# Alpha environment (default)
|
|
API = APIClient(
|
|
client_id="your-client-id",
|
|
client_secret="your-client-secret",
|
|
env="alpha",
|
|
debug=False
|
|
)
|
|
|
|
# Production environment
|
|
API = APIClient(
|
|
client_id="your-client-id",
|
|
client_secret="your-client-secret",
|
|
env="production",
|
|
debug=False
|
|
)
|
|
|
|
# Change environment dynamically
|
|
API.set_environment("production")
|
|
```
|
|
|
|
## API Reference
|
|
|
|
### Jobs
|
|
|
|
Jobs are pre-built functions that map to specific API endpoints. They return the raw response from the API.
|
|
|
|
#### Post Operations
|
|
|
|
```python
|
|
# Get a specific post
|
|
post = API.run_job('post.get', "post-slug-or-id")
|
|
|
|
# Create a post
|
|
post = API.run_job('post.create', {
|
|
"postText": "This is a test post",
|
|
"parent": {
|
|
"pk": "maintrunk#maintrunk",
|
|
"sk": "maintrunk#maintrunk"
|
|
}
|
|
})
|
|
|
|
# List all posts
|
|
posts = API.run_job('post.listall')
|
|
|
|
# List public posts
|
|
public_posts = API.run_job('post.listpublic')
|
|
|
|
# List posts by a specific branch
|
|
branch_posts = API.run_job('post.listbybranch', "branch-name")
|
|
|
|
# List posts by a user profile
|
|
user_posts = API.run_job('post.listbyuserprofile', "username")
|
|
|
|
# Update a post
|
|
updated_post = API.run_job('post.update', {
|
|
"pk": "post-id",
|
|
"sk": "post-id",
|
|
"newPostText": "Updated text"
|
|
})
|
|
|
|
# Delete a post
|
|
deleted = API.run_job('post.listremoved', "post-id")
|
|
```
|
|
|
|
#### Comment Operations
|
|
|
|
```python
|
|
# Create a comment
|
|
comment = API.run_job('comment.create', {
|
|
"commentText": "This is a comment",
|
|
"parent": {
|
|
"pk": "post-id",
|
|
"sk": "post-id"
|
|
}
|
|
})
|
|
|
|
# Get comments by post ID
|
|
comments = API.run_job('comment.listtbypostid', "post-id")
|
|
```
|
|
|
|
#### User Profile Operations
|
|
|
|
```python
|
|
# Get user profile
|
|
profile = API.run_job('userprofile.get', "username")
|
|
```
|
|
|
|
#### Follow Operations
|
|
|
|
```python
|
|
# Follow a user
|
|
followed = API.run_job('follow.follow', {
|
|
"isFollowing": true,
|
|
"parent": {
|
|
"pk": "userprofile#username",
|
|
"sk": "userprofile#username"
|
|
},
|
|
"followType": "userprofile",
|
|
"parentSlug": "username"
|
|
})
|
|
```
|
|
|
|
#### Vote Operations
|
|
|
|
```python
|
|
# Cast a vote
|
|
voted = API.run_job('vote.votecast', {
|
|
"parent": {
|
|
"pk": "post-id",
|
|
"sk": "post-id",
|
|
"slug": "post-slug",
|
|
"entity": "post"
|
|
},
|
|
"vote": "up" # or "down"
|
|
})
|
|
```
|
|
|
|
#### Reaction Operations
|
|
|
|
```python
|
|
# React to something (post, comment, etc.)
|
|
reactions = API.run_job('reaction.reacttosomething', {
|
|
"parent": {
|
|
"pk": "post-id",
|
|
"sk": "post-id"
|
|
},
|
|
"reaction": "like" # various types supported
|
|
})
|
|
|
|
# Get reactions by parent
|
|
post_reactions = API.run_job('reaction.getbyparent', "parent-id")
|
|
|
|
# List reactions
|
|
reactions_list = API.run_job('reaction.listbyparent', "parent-id")
|
|
```
|
|
|
|
#### Notification Operations
|
|
|
|
```python
|
|
# List all notifications
|
|
notifications = API.run_job('notification.listnotifications')
|
|
|
|
# Mark all as read
|
|
API.run_job('notification.markallasread')
|
|
```
|
|
|
|
#### Trust Operations
|
|
|
|
```python
|
|
# Create or update trust relationship
|
|
trust = API.run_job('trust.createorupdate', {
|
|
"pk": "trust_id",
|
|
"sk": "trust_id",
|
|
"trustType": "positive"
|
|
})
|
|
|
|
# List trust by user initialization
|
|
trusts = API.run_job('trust.listbyusersinit', "username")
|
|
|
|
# List trust by user has
|
|
trusts = API.run_job('trust.listbyuserhas', "username")
|
|
```
|
|
|
|
#### Branch Operations
|
|
|
|
```python
|
|
# Get a specific branch
|
|
branch = API.run_job('branch.get', "branch-name")
|
|
|
|
# List branches (all branches with pagination)
|
|
branches = API.run_job('branch.listbyname')
|
|
```
|
|
|
|
#### Feed Operations
|
|
|
|
```python
|
|
# Get café feed
|
|
feed = API.run_job('feed.cafefeed')
|
|
|
|
# Get following feed
|
|
following_feed = API.run_job('feed.followingfeed')
|
|
```
|
|
|
|
#### Block Operations
|
|
|
|
```python
|
|
# Block a user (function exists but needs implementation)
|
|
# TODO: Add job function for block operations
|
|
```
|
|
|
|
#### Mute Operations
|
|
|
|
```python
|
|
# Mute functionality (to be added)
|
|
# TODO: Add job function for mute operations
|
|
```
|
|
|
|
### Wrappers
|
|
|
|
Wrappers are high-level functions that simplify common operations by handling payload preparation and job execution automatically.
|
|
|
|
#### Using a Wrapper
|
|
|
|
```python
|
|
API.handle_token()
|
|
|
|
# Create a post with a wrapper (recommended for simplicity)
|
|
from trustcafeapiwrapper.wrappers.post.create_post import create_post
|
|
|
|
API.wrapped(create_post(
|
|
"This is a test post created via the wrapper.",
|
|
parent_path="/", # Root path (optional)
|
|
blur_label=None, # Optional blurring
|
|
card_url=None, # Optional card URL
|
|
collaborative=False # Optional collaboration flag
|
|
))
|
|
|
|
# Create a comment
|
|
from trustcafeapiwrapper.wrappers.comment.create_comment import create_comment
|
|
|
|
API.wrapped(create_comment(
|
|
"This is a comment",
|
|
parent_path="/" # Parent path (required)
|
|
))
|
|
```
|
|
|
|
**About Wrappers:**
|
|
- Wrappers simplify common operations
|
|
- They prepare the payload and job execution automatically
|
|
- More wrappers are being added for consistency
|
|
- For flexibility, use Jobs or Custom Requests
|
|
|
|
### Using `run_job` vs. Wrappers
|
|
|
|
| Feature | `run_job` | Wrappers |
|
|
|---------|----------|----------|
|
|
| Simplicity | Higher | Highest for common tasks |
|
|
| Flexibility | Maximum | Optimized for specific use cases |
|
|
| Discovery | Need to know job format | Self-documenting payloads |
|
|
| Customization | Full control | Pre-defined options |
|
|
|
|
**Recommendation:**
|
|
- Use **Wrappers** for common, well-documented operations
|
|
- Use **Jobs** when you need fine-grained control
|
|
- Use **Custom Requests** when neither fits your needs
|
|
|
|
## Custom Requests
|
|
|
|
For operations not covered by jobs or wrappers, use the `make_request` method:
|
|
|
|
```python
|
|
# Make a raw API request
|
|
response = API.make_request(
|
|
method="GET",
|
|
endpoint="content",
|
|
path="post/some-custom-path",
|
|
authenticate=True,
|
|
query_params={"param1": "value1"}
|
|
)
|
|
```
|
|
|
|
**Parameters:**
|
|
- `method` (str): HTTP method - "GET", "POST", "PUT", "DELETE"
|
|
- `endpoint` (str): API endpoint - "content", "auth", "audrey", etc.
|
|
- `path` (str): API path after endpoint
|
|
- `authenticate` (bool): Whether to include authentication token
|
|
- `query_params` (dict): Optional query parameters
|
|
|
|
**Example - Custom Request:**
|
|
```python
|
|
# Get posts from a specific branch with filters
|
|
posts = API.make_request(
|
|
"GET",
|
|
"content",
|
|
"post/ref-subwiki/music",
|
|
query_params={"limit": 10, "offset": 0}
|
|
)
|
|
```
|
|
|
|
## Debug Mode
|
|
|
|
Enable debug mode to see all API requests and responses:
|
|
|
|
```python
|
|
API = APIClient(
|
|
client_id=os.getenv("client_id"),
|
|
client_secret=os.getenv("client_secret"),
|
|
env="production",
|
|
debug=True # Enable debug mode
|
|
)
|
|
|
|
# Now API calls will print request details
|
|
API.handle_token()
|
|
```
|
|
|
|
## Examples
|
|
|
|
### Example 1: Basic Post Creation
|
|
|
|
```python
|
|
import trustcafeapiwrapper
|
|
import os
|
|
|
|
# Setup
|
|
API = trustcafeapiwrapper.APIClient(
|
|
client_id=os.getenv("TRUSTCAFE_CLIENT_ID"),
|
|
client_secret=os.getenv("TRUSTCAFE_CLIENT_SECRET"),
|
|
env="alpha",
|
|
debug=False
|
|
)
|
|
|
|
# Handle authentication
|
|
API.handle_token()
|
|
|
|
# Create a post in the music branch
|
|
from trustcafeapiwrapper.wrappers.post.create_post import create_post
|
|
|
|
API.wrapped(create_post(
|
|
"New music discussion post",
|
|
parent_path="/music",
|
|
blur_label=None,
|
|
card_url=None,
|
|
collaborative=False
|
|
))
|
|
```
|
|
|
|
### Example 2: Following a User and Getting Their Profile
|
|
|
|
```python
|
|
import trustcafeapiwrapper
|
|
import os
|
|
|
|
API = trustcafeapiwrapper.APIClient(
|
|
client_id=os.getenv("TRUSTCAFE_CLIENT_ID"),
|
|
client_secret=os.getenv("TRUSTCAFE_CLIENT_SECRET"),
|
|
env="production"
|
|
)
|
|
|
|
# Follow a user
|
|
follow = API.run_job('follow.follow', {
|
|
"isFollowing": true,
|
|
"parent": {
|
|
"pk": "userprofile#philosopher-jon",
|
|
"sk": "userprofile#philosopher-jon"
|
|
},
|
|
"followType": "userprofile",
|
|
"parentSlug": "philosopher-jon"
|
|
})
|
|
print(f"Followed user: {follow}")
|
|
|
|
# Get their profile
|
|
profile = API.run_job('userprofile.get', "philosopher-jon")
|
|
print(f"Profile data: {profile}")
|
|
```
|
|
|
|
### Example 3: Managing Notifications
|
|
|
|
```python
|
|
import trustcafeapiwrapper
|
|
import os
|
|
|
|
API = trustcafeapiwrapper.APIClient(
|
|
client_id=os.getenv("TRUSTCAFE_CLIENT_ID"),
|
|
client_secret=os.getenv("TRUSTCAFE_CLIENT_SECRET"),
|
|
env="production"
|
|
)
|
|
|
|
API.handle_token()
|
|
|
|
# Check for new notifications
|
|
notifications = API.run_job('notification.listnotifications')
|
|
print(f"Unread notifications: {notifications}")
|
|
|
|
# Mark all as read
|
|
API.run_job('notification.markallasread')
|
|
print("All notifications marked as read")
|
|
```
|
|
|
|
### Example 4: Creating a Collaborative Post
|
|
|
|
```python
|
|
import trustcafeapiwrapper
|
|
import os
|
|
|
|
API = trustcafeapiwrapper.APIClient(
|
|
client_id=os.getenv("TRUSTCAFE_CLIENT_ID"),
|
|
client_secret=os.getenv("TRUSTCAFE_CLIENT_SECRET"),
|
|
env="production"
|
|
)
|
|
|
|
API.handle_token()
|
|
|
|
# Create a collaborative post
|
|
from trustcafeapiwrapper.wrappers.post.create_post import create_post
|
|
|
|
API.wrapped(create_post(
|
|
"Research paper draft - collaborative editing",
|
|
parent_path="/research",
|
|
collaborative=True # Enables collaborative editing
|
|
))
|
|
```
|
|
|
|
## Development
|
|
|
|
### Project Structure
|
|
|
|
```
|
|
trustcafe-api-wrapper/
|
|
├── src/
|
|
│ └── trustcafeapiwrapper/
|
|
│ ├── apiclient.py # Core API client
|
|
│ ├── jobs/ # API job functions
|
|
│ │ ├── post/
|
|
│ │ ├── comment/
|
|
│ │ ├── userprofile/
|
|
│ │ ├── follow/
|
|
│ │ └── ... (all jobs)
|
|
│ ├── wrappers/ # High-level wrappers
|
|
│ │ ├── post/
|
|
│ │ ├── comment/
|
|
│ │ └── ...
|
|
│ └── utils/ # Helper functions
|
|
├── tests/ # Test files
|
|
├── README.md # This file
|
|
├── documentation.md # Basic documentation
|
|
├── development.md # Project notes
|
|
└── pyproject.toml # Project configuration
|
|
```
|
|
|
|
### Adding New Jobs
|
|
|
|
1. Create a new file in `src/trustcafeapiwrapper/jobs/`
|
|
2. Define a function matching the job name
|
|
3. Export it from the module's `__init__.py`
|
|
4. Document the parameters and return value
|
|
|
|
**Example - Adding a Job:**
|
|
```python
|
|
# src/trustcafeapiwrapper/jobs/example/new_job.py
|
|
def my_new_job(API, param1: str, param2: int) -> dict:
|
|
"""
|
|
Create a new job function.
|
|
|
|
Args:
|
|
API: The APIClient instance
|
|
param1 (str): Description of parameter 1
|
|
param2 (int): Description of parameter 2
|
|
|
|
Returns:
|
|
dict: The API response
|
|
"""
|
|
response = API.make_request(
|
|
"POST",
|
|
"endpoint",
|
|
"path/to/resource",
|
|
data={"param1": param1, "param2": param2}
|
|
)
|
|
return response
|
|
```
|
|
|
|
### Known Limitations
|
|
|
|
- **Incomplete Jobs**: Not all available API endpoints have wrapper functions yet
|
|
- **Enums**: Some enum types are not strictly typed
|
|
- **Block Operations**: Block functionality exists in backend but not yet exposed
|
|
- **Mute Operations**: Mute functionality pending implementation
|
|
|
|
### Future Enhancements
|
|
|
|
- Complete coverage of all TrustCafé API endpoints
|
|
- Type hints for better IDE support
|
|
- Async support for better performance
|
|
- Comprehensive test suite
|
|
- Pydantic models for request/response validation
|
|
|
|
## Testing
|
|
|
|
Run the test suite:
|
|
|
|
```bash
|
|
pytest
|
|
```
|
|
|
|
Or run specific tests:
|
|
|
|
```bash
|
|
# Test the API client
|
|
python -m pytest tests/apiclient.py
|
|
|
|
# Run all tests
|
|
python -m pytest tests/
|
|
```
|
|
|
|
## License
|
|
|
|
[Depends on TrustCafé project license]
|
|
|
|
## Support
|
|
|
|
For issues, questions, or contributions:
|
|
- [TrustCafé Website](https://trustcafe.io)
|
|
- [GitLab Repository](https://gitlab.com/trustcafe/trustcafe-api-wrapper)
|
|
- Contact the WikiTribune team
|
|
|
|
## Version History
|
|
|
|
- **0.1.0.13** - Current version with ongoing development
|
|
|
|
---
|
|
|
|
**Note:** This wrapper is for internal WikiTribune/TrustCafé use. Public API endpoints are subject to change.
|