notwonderful / trovo-sdk
PHP SDK for Trovo.live API — OAuth, channels, users, chat, clips, drops and more
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/notwonderful/trovo-sdk
Requires
- php: ^8.3
- guzzlehttp/guzzle: ^7.0
Requires (Dev)
- phpunit/phpunit: ^11.0
README
PHP 8.3+ SDK for the Trovo.live API.
Installation
composer require notwonderful/trovo-sdk
Quick Start
use Notwonderful\TrovoSdk\TrovoClient; use Notwonderful\TrovoSdk\Config; use Notwonderful\TrovoSdk\Enum\Scope; $trovo = new TrovoClient(new Config( clientId: 'your_client_id', clientSecret: 'your_client_secret', redirectUri: 'https://example.com/callback', ));
Authentication
OAuth 2.0 Authorization Code Flow
// 1. Redirect user to Trovo login $url = $trovo->getAuthorizationCodeUrl( scopes: [Scope::UserDetailsSelf, Scope::ChannelDetailsSelf], state: 'random_csrf_token', ); // 2. After redirect, exchange code for tokens $token = $trovo->exchangeCode($_GET['code']); // $token->accessToken, $token->refreshToken, $token->expiresIn // 3. Set the token for subsequent API calls $trovo->setAccessToken($token->accessToken);
OAuth 2.0 Implicit Flow
$url = $trovo->getImplicitFlowUrl( scopes: [Scope::UserDetailsSelf], state: 'random_csrf_token', ); // Access token will be in the URL fragment after redirect
Token Management
// Refresh $newToken = $trovo->refreshToken($token->refreshToken); // Validate $info = $trovo->validateToken($token->accessToken); // $info->uid, $info->scopes, $info->expireTs, $info->isExpired() // Revoke $trovo->revokeToken($token->accessToken);
API Usage
Categories
// Top categories (sorted by popularity) $categories = $trovo->categories()->getTopCategories(); // returns Category[] — id, name, shortName, iconUrl, desc // Search $result = $trovo->categories()->search(query: 'apex', limit: 10); // $result->items (Category[]), $result->hasMore
Channels
// Top live channels with pagination $page = $trovo->channels()->getTopChannels(limit: 20); // $page->items (Channel[]), $page->totalPage, $page->cursor, $page->token // Next page $page2 = $trovo->channels()->getTopChannels( limit: 20, after: true, token: $page->token, cursor: $page->cursor, ); // Channel info by ID or username $channel = $trovo->channels()->getById(channelId: 100000031); $channel = $trovo->channels()->getById(username: 'username'); // Own channel with stream key (requires channel_details_self) $my = $trovo->channels()->getMy(); // $my->streamKey, $my->isLive, $my->title, ... // Update channel (requires channel_update_self) use Notwonderful\TrovoSdk\Enum\AudienceType; $trovo->channels()->update( channelId: 100000031, liveTitle: 'New title', categoryId: '10023', languageCode: 'EN', audiType: AudienceType::Teen, ); // Followers $followers = $trovo->channels()->getFollowers(channelId: 100000031, limit: 50); // $followers->items (Follower[]), $followers->total, $followers->totalPage // Viewers (grouped by role) $viewers = $trovo->channels()->getViewers(channelId: 100000031); // $viewers['chatters']['moderators']['viewers'], $viewers['total'], ...
Users
// Lookup by usernames $users = $trovo->users()->getByUsernames(['user1', 'user2']); // returns User[] — userId, userName, nickName, channelId // Authenticated user info (requires user_details_self) $me = $trovo->users()->getUserInfo(); // $me->userId, $me->userName, $me->email, $me->profilePic
Subscribers
use Notwonderful\TrovoSdk\Enum\SortDirection; // Requires channel_subscriptions scope $subs = $trovo->subscribers()->get( channelId: 100000031, limit: 50, offset: 0, direction: SortDirection::Desc, ); // $subs->items (Subscriber[]), $subs->total // Subscriber: userId, username, displayName, subCreatedAt, subLv, subTier
Emotes
use Notwonderful\TrovoSdk\Enum\EmoteType; $emotes = $trovo->emotes()->get( emoteType: EmoteType::All, channelIds: [100000031], ); // Raw array: globalEmotes, eventEmotes, customizedEmotes
Streams & Past Streams
// Live stream URLs (restricted access) $urls = $trovo->streams()->getLiveStreamUrls(channelId: 100000031); // returns StreamUrl[] — playUrl, desc (resolution) // Past streams use Notwonderful\TrovoSdk\Enum\Period; $past = $trovo->streams()->getPastStreams( channelId: 100000031, period: Period::Month, limit: 10, ); // $past->items (PastStream[]), $past->total, $past->totalPage
Clips
$clips = $trovo->clips()->get( channelId: 100000031, period: Period::Week, limit: 20, ); // $clips->items (Clip[]) — clipId, title, url, thumbnail, duration, views, likes
Chat
// Send to own channel (requires chat_send_self) $trovo->chat()->sendToMyChannel('Hello!'); // Send to another channel (requires chat_send_self + send_to_my_channel) $trovo->chat()->sendToChannel('Hello!', channelId: 100000031); // Delete message (requires manage_messages) $trovo->chat()->deleteMessage( channelId: '100000031', messageId: 'msg_123', userId: '100000021', ); // Chat commands (requires manage_messages) $result = $trovo->chat()->performCommand('mod @username', channelId: 100000031); // $result->isSuccess, $result->displayMsg
Drops (App Access Token)
Drops APIs use Trovo Signature (HMAC-SHA1) automatically:
use Notwonderful\TrovoSdk\Enum\FulfillmentStatus; $drops = $trovo->drops()->getEntitlements( limit: 50, fulfillmentStatus: FulfillmentStatus::Claimed, ); // $drops->items (DropEntitlement[]), $drops->total, $drops->hasMore $results = $trovo->drops()->updateEntitlements( entitlementIds: ['ent_1', 'ent_2'], fulfillmentStatus: FulfillmentStatus::Fulfilled, ); // returns DropUpdateResult[] — entitlementId, status, isSuccess()
Laravel Integration
The package auto-registers its ServiceProvider via Laravel's package discovery.
Add credentials to your .env:
TROVO_CLIENT_ID=your_client_id TROVO_CLIENT_SECRET=your_client_secret TROVO_REDIRECT_URI=https://example.com/callback
Optionally publish the config:
php artisan vendor:publish --tag=trovo-config
Then resolve from the container:
use Notwonderful\TrovoSdk\TrovoClient; $trovo = app(TrovoClient::class); $categories = $trovo->categories()->getTopCategories();
Or inject via constructor:
public function __construct(private TrovoClient $trovo) {}
Error Handling
use Notwonderful\TrovoSdk\Exception\ApiException; use Notwonderful\TrovoSdk\Exception\AuthenticationException; use Notwonderful\TrovoSdk\Exception\RateLimitException; try { $user = $trovo->users()->getUserInfo(); } catch (RateLimitException $e) { // $e->limit, $e->remaining, $e->resetsAt, $e->getSecondsUntilReset() sleep($e->getSecondsUntilReset()); } catch (AuthenticationException $e) { // Access token missing or not set } catch (ApiException $e) { // $e->statusCode (HTTP), $e->trovoErrorCode, $e->trovoError, $e->getMessage() }
Custom HTTP Client
Implement HttpClientInterface to use your own HTTP client or for testing:
use Notwonderful\TrovoSdk\Http\HttpClientInterface; $trovo = new TrovoClient($config, new MyCustomHttpClient());
Available Scopes
| Enum | Value | Description |
|---|---|---|
Scope::UserDetailsSelf |
user_details_self |
View email and user profile |
Scope::ChannelDetailsSelf |
channel_details_self |
View channel details + stream key |
Scope::ChannelUpdateSelf |
channel_update_self |
Update channel settings |
Scope::ChannelSubscriptions |
channel_subscriptions |
Get subscribers list |
Scope::ChatSendSelf |
chat_send_self |
Send chat messages |
Scope::SendToMyChannel |
send_to_my_channel |
Allow others to send to your channel |
Scope::ManageMessages |
manage_messages |
Delete messages and chat commands |
Support
If you like this package, please consider giving it a star ⭐ on GitHub!