Skip to main content
Glama
restream-client.ts5.58 kB
/** * Restream API Client * Handles authentication and API requests to Restream */ import axios, { AxiosInstance, AxiosError } from 'axios'; import type { RestreamConfig, AuthToken, Channel, UserProfile, Stream, StreamSettings, ApiError, } from './types.js'; export class RestreamClient { private config: RestreamConfig; private axiosInstance: AxiosInstance; private accessToken: string | null = null; private tokenExpiry: number = 0; constructor(config: RestreamConfig) { this.config = config; this.axiosInstance = axios.create({ baseURL: config.baseUrl, headers: { 'Content-Type': 'application/json', }, }); // Add request interceptor to include auth token this.axiosInstance.interceptors.request.use(async (config) => { await this.ensureAuthenticated(); if (this.accessToken) { config.headers.Authorization = `Bearer ${this.accessToken}`; } return config; }); } /** * Ensure we have a valid access token */ private async ensureAuthenticated(): Promise<void> { const now = Date.now(); if (this.accessToken && this.tokenExpiry > now) { return; // Token is still valid } await this.authenticate(); } /** * Authenticate with Restream API using client credentials */ private async authenticate(): Promise<void> { try { const response = await axios.post<AuthToken>( `${this.config.baseUrl}/oauth/token`, { grant_type: 'client_credentials', client_id: this.config.clientId, client_secret: this.config.clientSecret, } ); this.accessToken = response.data.access_token; this.tokenExpiry = Date.now() + response.data.expires_in * 1000; } catch (error) { throw this.handleError(error, 'Authentication failed'); } } /** * Get user profile information */ async getUserProfile(): Promise<UserProfile> { try { const response = await this.axiosInstance.get<UserProfile>('/user/profile'); return response.data; } catch (error) { throw this.handleError(error, 'Failed to fetch user profile'); } } /** * Get all connected channels */ async getChannels(): Promise<Channel[]> { try { const response = await this.axiosInstance.get<{ channels: Channel[] }>('/user/channels'); return response.data.channels || []; } catch (error) { throw this.handleError(error, 'Failed to fetch channels'); } } /** * Get a specific channel by ID */ async getChannel(channelId: string): Promise<Channel> { try { const response = await this.axiosInstance.get<Channel>(`/user/channels/${channelId}`); return response.data; } catch (error) { throw this.handleError(error, `Failed to fetch channel ${channelId}`); } } /** * Enable or disable a channel */ async updateChannelStatus(channelId: string, enabled: boolean): Promise<Channel> { try { const response = await this.axiosInstance.patch<Channel>( `/user/channels/${channelId}`, { enabled } ); return response.data; } catch (error) { throw this.handleError(error, `Failed to update channel ${channelId}`); } } /** * Get current stream information */ async getCurrentStream(): Promise<Stream | null> { try { const response = await this.axiosInstance.get<Stream>('/user/stream'); return response.data; } catch (error) { if (axios.isAxiosError(error) && error.response?.status === 404) { return null; // No active stream } throw this.handleError(error, 'Failed to fetch current stream'); } } /** * Update stream settings */ async updateStreamSettings(settings: StreamSettings): Promise<Stream> { try { const response = await this.axiosInstance.patch<Stream>('/user/stream', settings); return response.data; } catch (error) { throw this.handleError(error, 'Failed to update stream settings'); } } /** * Get stream analytics/statistics */ async getStreamAnalytics(streamId?: string): Promise<any> { try { const endpoint = streamId ? `/streams/${streamId}/analytics` : '/user/analytics'; const response = await this.axiosInstance.get(endpoint); return response.data; } catch (error) { throw this.handleError(error, 'Failed to fetch stream analytics'); } } /** * Start a new stream */ async startStream(settings?: StreamSettings): Promise<Stream> { try { const response = await this.axiosInstance.post<Stream>('/user/stream/start', settings || {}); return response.data; } catch (error) { throw this.handleError(error, 'Failed to start stream'); } } /** * Stop the current stream */ async stopStream(): Promise<void> { try { await this.axiosInstance.post('/user/stream/stop'); } catch (error) { throw this.handleError(error, 'Failed to stop stream'); } } /** * Handle API errors and convert to ApiError */ private handleError(error: unknown, defaultMessage: string): ApiError { if (axios.isAxiosError(error)) { const axiosError = error as AxiosError<any>; return { message: axiosError.response?.data?.message || axiosError.message || defaultMessage, code: axiosError.response?.data?.code, status: axiosError.response?.status, }; } return { message: error instanceof Error ? error.message : defaultMessage, }; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/shaktech786/restream-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server