Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,41 @@ name = user.name
subscriptions = user.get_subscriptions()
```

#### Handling Renamed Accounts
Substack allows users to change their handle (username) at any time. When this happens, the old API endpoints return 404 errors. This library automatically handles these redirects by default.
##### Automatic Redirect Handling

```python
from substack_api import User

# This will automatically follow redirects if the handle has changed
user = User("oldhandle") # Will find the user even if they renamed to "newhandle"

# Check if a redirect occurred
if user.was_redirected:
print(f"User was renamed from {user.original_username} to {user.username}")
```

##### Disable Redirect Following

If you prefer to handle 404s yourself:

```python
# Disable automatic redirect following
user = User("oldhandle", follow_redirects=False)
```

##### Manual Handle Resolution

You can also manually resolve handle redirects:

```python
from substack_api import resolve_handle_redirect

new_handle = resolve_handle_redirect("oldhandle")
if new_handle:
print(f"Handle was renamed to: {new_handle}")
```
## Limitations

- This is an unofficial library and not endorsed by Substack
Expand Down
58 changes: 54 additions & 4 deletions docs/api-reference/user.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
# User

The `User` class provides access to Substack user profiles.
The `User` class provides access to Substack user profiles. It also handles renamed Substack handles by following redirects.

## Class Definition

```python
User(username: str)
User(username: str, follow_redirects: bool = True)
```

### Parameters

- `username` (str): The Substack username
- `follow_redirects` (bool): Whether to follow redirects when a handle has been renamed (default: True)

## Methods

### `_fetch_user_data(force_refresh: bool = False) -> Dict[str, Any]`

Fetch the raw user data from the API and cache it.
Fetch the raw user data from the API and cache it. Handles renamed accounts by following redirects when `follow_redirects` is True.

#### Parameters

Expand All @@ -26,6 +27,10 @@ Fetch the raw user data from the API and cache it.

- `Dict[str, Any]`: Full user profile data

#### Raises

- `requests.HTTPError`: If the user cannot be found even after redirect attempts

### `get_raw_data(force_refresh: bool = False) -> Dict[str, Any]`

Get the complete raw user data.
Expand All @@ -46,6 +51,14 @@ Get newsletters the user has subscribed to.

- `List[Dict[str, Any]]`: List of publications the user subscribes to with domain info

### `_update_handle(new_handle: str) -> None`

Update the user's handle and endpoint.

#### Parameters

- `new_handle` (str): The new handle after redirect

## Properties

### `id` -> int
Expand All @@ -60,22 +73,59 @@ Get the user's name.

Get the date when the user's profile was set up.

### `was_redirected` -> bool

Check if this user's handle was redirected from the original.

#### Returns

- `bool`: True if the handle was changed via redirect

## Helper Functions

### `resolve_handle_redirect(old_handle: str, timeout: int = 30) -> Optional[str]`

Resolve a potentially renamed Substack handle by following redirects.

#### Parameters

- `old_handle` (str): The original handle that may have been renamed
- `timeout` (int): Request timeout in seconds

#### Returns

- `Optional[str]`: The new handle if renamed, None if no redirect or on error

## Example Usage

```python
from substack_api import User

# Create a user object
# Create a user object (automatically handles redirects)
user = User("username")

# Create a user object without redirect handling
user_no_redirect = User("username", follow_redirects=False)

# Get basic user information
print(f"User ID: {user.id}")
print(f"Name: {user.name}")
print(f"Profile created: {user.profile_set_up_at}")

# Check if the user was redirected (handle was renamed)
if user.was_redirected:
print(f"Original handle '{user.original_username}' was redirected to '{user.username}'")

# Get the user's subscriptions
subscriptions = user.get_subscriptions()

# Get raw user data
user_data = user.get_raw_data()

# Using the standalone redirect resolver
from substack_api.user import resolve_handle_redirect

new_handle = resolve_handle_redirect("old_username")
if new_handle:
print(f"The handle has been renamed to: {new_handle}")
```
20 changes: 20 additions & 0 deletions docs/user-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ from substack_api import User
# Create a user object
user = User("username")

# Create a user object without redirect handling (if a handle has been renamed)
user = User("username", follow_redirects=False)

# Get basic user information
user_id = user.id
name = user.name
Expand All @@ -80,6 +83,23 @@ subscriptions = user.get_subscriptions()

# Get raw user data
user_data = user.get_raw_data()

# Check if the user was redirected (handle was renamed)
if user.was_redirected:
print(f"Original handle '{user.original_username}' was redirected to '{user.username}'")
```

### Handle Redirects

Substack users sometimes change handles. The `User` class automatically handles these redirects by default:

```python
# This will work even if "old_username" has been renamed to "new_username"
user = User("old_username") # follow_redirects=True by default

# Check if a redirect happened
if user.was_redirected:
print(f"User was redirected from {user.original_username} to {user.username}")
```

## Working with Posts
Expand Down
11 changes: 9 additions & 2 deletions substack_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@
from .category import Category
from .newsletter import Newsletter
from .post import Post
from .user import User
from .user import User, resolve_handle_redirect

__all__ = ["User", "Post", "Category", "Newsletter", "SubstackAuth"]
__all__ = [
"User",
"Post",
"Category",
"Newsletter",
"SubstackAuth",
"resolve_handle_redirect",
]
Loading