Files
easystream-main/docs/QUICK_START_GUIDE.md
SamiAhmed7777 f0f346deb9
Some checks failed
EasyStream Test Suite / test (pull_request) Has been cancelled
EasyStream Test Suite / code-quality (pull_request) Has been cancelled
EasyStream Test Suite / integration-test (pull_request) Has been cancelled
Sync current dev state
2025-12-15 17:28:21 -08:00

13 KiB

EasyStream API Quick Start Guide

Get Started in 5 Minutes

This guide will get you up and running with the EasyStream API quickly.

Prerequisites

  • EasyStream installed and running
  • Modern web browser
  • Basic JavaScript knowledge

1. Authentication

Login and Get Token

// The API client is automatically available as 'api'
const result = await api.login('myusername', 'mypassword');

if (result.success) {
    console.log('Logged in!');
    console.log('User:', result.user);
    console.log('Token:', result.token);
    // Token is automatically stored
}

Check if Logged In

if (api.isAuthenticated()) {
    console.log('User is logged in');
} else {
    console.log('Please log in');
}

2. Working with Videos

List Videos

const videos = await api.getVideos({
    page: 1,
    limit: 20,
    sort: 'popular'
});

console.log('Videos:', videos.data.videos);

Get Single Video

const video = await api.getVideo('123456');
console.log('Video:', video.data);

Search Videos

const results = await api.searchVideos('funny cats');
console.log('Found:', results.data.videos);

Like a Video

await api.likeVideo('123456', 'like');
console.log('Video liked!');

Create a Video

const newVideo = await api.createVideo({
    title: 'My Awesome Video',
    description: 'This is a great video',
    privacy: 'public',
    category: 'entertainment'
});

console.log('Created video:', newVideo.data.file_key);

3. User Profiles

Get Current User Profile

const myProfile = await api.getMyProfile();
console.log('My profile:', myProfile.data);

Get Another User's Profile

const userProfile = await api.getUserProfile(123);
console.log('User:', userProfile.data);

Update Profile

await api.updateProfile({
    usr_dname: 'My New Name',
    usr_about: 'I love making videos!'
});

console.log('Profile updated!');

Upload Avatar

<input type="file" id="avatar-input" accept="image/*">
<button onclick="uploadAvatar()">Upload</button>

<script>
async function uploadAvatar() {
    const fileInput = document.getElementById('avatar-input');
    const file = fileInput.files[0];

    if (file) {
        const result = await api.uploadAvatar(file);
        console.log('Avatar uploaded:', result.data.avatar_url);
    }
}
</script>

4. Comments

Get Comments for a Video

const comments = await api.getComments('123456', {
    page: 1,
    sort: 'recent'
});

console.log('Comments:', comments.data.comments);

Post a Comment

const newComment = await api.createComment(
    '123456',              // video file_key
    'Great video!',        // comment text
    null                   // parent_id (null for top-level)
);

console.log('Comment posted:', newComment.data);

Reply to a Comment

const reply = await api.createComment(
    '123456',              // video file_key
    'Thanks!',             // reply text
    789                    // parent comment ID
);

console.log('Reply posted:', reply.data);

5. Subscriptions

Subscribe to a Channel

await api.subscribe(456); // channel user ID
console.log('Subscribed!');

Check if Subscribed

const status = await api.checkSubscription(456);

if (status.data.is_subscribed) {
    console.log('Already subscribed');
} else {
    console.log('Not subscribed');
}

Get Subscription Feed

const feed = await api.getSubscriptionFeed({ page: 1 });
console.log('New videos from subscriptions:', feed.data.videos);

6. Complete Examples

Video Player Page

<!DOCTYPE html>
<html>
<head>
    <title>Watch Video</title>
    <style>
        .video-container { max-width: 800px; margin: 0 auto; }
        .actions button { margin: 5px; }
        .comments { margin-top: 20px; }
    </style>
</head>
<body>
    <div class="video-container">
        <h1 id="video-title"></h1>
        <p id="video-description"></p>

        <div class="actions">
            <button id="like-btn">👍 Like</button>
            <button id="subscribe-btn">Subscribe</button>
            <button id="watch-later-btn">⏰ Watch Later</button>
        </div>

        <div class="comments">
            <h2>Comments</h2>
            <div id="comments-list"></div>

            <form id="comment-form">
                <textarea id="comment-text" placeholder="Add a comment..." required></textarea>
                <button type="submit">Post Comment</button>
            </form>
        </div>
    </div>

    <script src="/f_scripts/fe/js/api-helper.js"></script>
    <script>
    const fileKey = '123456'; // Get from URL

    // Load video and comments
    async function init() {
        try {
            // Load video
            const video = await api.getVideo(fileKey);
            document.getElementById('video-title').textContent = video.data.file_title;
            document.getElementById('video-description').textContent = video.data.file_description;

            // Record view
            await api.recordVideoView(fileKey);

            // Load comments
            await loadComments();

            // Setup buttons
            setupButtons(video.data);

        } catch (error) {
            api.handleError(error);
        }
    }

    async function loadComments() {
        const comments = await api.getComments(fileKey);
        const list = document.getElementById('comments-list');

        list.innerHTML = comments.data.comments.map(c => `
            <div class="comment">
                <strong>${c.usr_dname}</strong>
                <p>${c.comment_text}</p>
                <small>${c.comment_date}</small>
            </div>
        `).join('');
    }

    function setupButtons(video) {
        // Like button
        document.getElementById('like-btn').addEventListener('click', async () => {
            await api.likeVideo(fileKey, 'like');
            alert('Video liked!');
        });

        // Subscribe button
        document.getElementById('subscribe-btn').addEventListener('click', async () => {
            await api.subscribe(video.usr_id);
            alert('Subscribed!');
        });

        // Watch later button
        document.getElementById('watch-later-btn').addEventListener('click', async () => {
            await api.toggleWatchLater(fileKey);
            alert('Added to Watch Later!');
        });

        // Comment form
        document.getElementById('comment-form').addEventListener('submit', async (e) => {
            e.preventDefault();
            const text = document.getElementById('comment-text').value;

            await api.createComment(fileKey, text);
            document.getElementById('comment-text').value = '';
            await loadComments();
        });
    }

    // Start
    init();
    </script>
</body>
</html>

Browse Videos Page

<!DOCTYPE html>
<html>
<head>
    <title>Browse Videos</title>
    <style>
        .video-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px; }
        .video-card { border: 1px solid #ddd; padding: 15px; }
        .filters { margin-bottom: 20px; }
    </style>
</head>
<body>
    <div class="container">
        <h1>Browse Videos</h1>

        <div class="filters">
            <select id="sort-select">
                <option value="recent">Recent</option>
                <option value="popular">Popular</option>
                <option value="featured">Featured</option>
            </select>

            <input type="text" id="search-input" placeholder="Search videos...">
            <button id="search-btn">Search</button>
        </div>

        <div class="video-grid" id="video-grid"></div>

        <button id="load-more">Load More</button>
    </div>

    <script src="/f_scripts/fe/js/api-helper.js"></script>
    <script>
    let currentPage = 1;
    let currentSort = 'recent';
    let searchQuery = '';

    async function loadVideos(append = false) {
        try {
            let result;

            if (searchQuery) {
                result = await api.searchVideos(searchQuery, {
                    page: currentPage,
                    limit: 20
                });
            } else {
                result = await api.getVideos({
                    page: currentPage,
                    limit: 20,
                    sort: currentSort
                });
            }

            displayVideos(result.data.videos, append);

            // Show/hide load more button
            const loadMoreBtn = document.getElementById('load-more');
            if (currentPage >= result.data.pagination.pages) {
                loadMoreBtn.style.display = 'none';
            } else {
                loadMoreBtn.style.display = 'block';
            }

        } catch (error) {
            api.handleError(error);
        }
    }

    function displayVideos(videos, append = false) {
        const grid = document.getElementById('video-grid');

        if (!append) {
            grid.innerHTML = '';
        }

        videos.forEach(video => {
            const card = document.createElement('div');
            card.className = 'video-card';
            card.innerHTML = `
                <h3>${video.file_title}</h3>
                <p>${video.file_description}</p>
                <p>
                    <small>
                        By ${video.usr_dname}                        ${video.file_views} views •
                        ${video.like_count} likes
                    </small>
                </p>
                <button onclick="watchVideo('${video.file_key}')">
                    Watch
                </button>
            `;
            grid.appendChild(card);
        });
    }

    window.watchVideo = function(fileKey) {
        window.location.href = `/watch.php?v=${fileKey}`;
    };

    // Sort change
    document.getElementById('sort-select').addEventListener('change', (e) => {
        currentSort = e.target.value;
        currentPage = 1;
        loadVideos(false);
    });

    // Search
    document.getElementById('search-btn').addEventListener('click', () => {
        searchQuery = document.getElementById('search-input').value;
        currentPage = 1;
        loadVideos(false);
    });

    // Load more
    document.getElementById('load-more').addEventListener('click', () => {
        currentPage++;
        loadVideos(true);
    });

    // Initial load
    loadVideos();
    </script>
</body>
</html>

7. Error Handling

Always wrap API calls in try-catch:

try {
    const result = await api.someAPICall();
    // Handle success
} catch (error) {
    // Handle error
    console.error('Error:', error.message);

    // Use built-in error handler
    api.handleError(error);

    // Or custom handling
    if (error.message.includes('Authentication')) {
        window.location.href = '/signin';
    } else {
        alert('Error: ' + error.message);
    }
}

8. Common Patterns

Loading State

async function loadData() {
    showLoading(); // Your loading function

    try {
        const result = await api.getVideos();
        displayData(result.data);
    } catch (error) {
        api.handleError(error);
    } finally {
        hideLoading(); // Always hide loading
    }
}

Infinite Scroll

let currentPage = 1;
let loading = false;

window.addEventListener('scroll', async () => {
    if (loading) return;

    const scrolledToBottom =
        window.innerHeight + window.scrollY >= document.body.offsetHeight - 500;

    if (scrolledToBottom) {
        loading = true;
        currentPage++;

        try {
            const result = await api.getVideos({ page: currentPage });
            appendVideos(result.data.videos);
        } catch (error) {
            api.handleError(error);
        } finally {
            loading = false;
        }
    }
});
let searchTimeout;

document.getElementById('search-input').addEventListener('input', (e) => {
    clearTimeout(searchTimeout);

    searchTimeout = setTimeout(async () => {
        const query = e.target.value;

        if (query.length >= 2) {
            const results = await api.searchVideos(query);
            displaySearchResults(results.data.videos);
        }
    }, 300); // Wait 300ms after user stops typing
});

9. Browser Console Testing

Test API calls directly in the browser console:

// Check authentication
api.isAuthenticated()

// Login
await api.login('username', 'password')

// Get videos
await api.getVideos({ page: 1 })

// Get current user
await api.getMyProfile()

// View stored token
localStorage.getItem('jwt_token')

// Clear token
api.clearToken()

10. Next Steps


Support

If you encounter issues:

  1. Check browser console for errors
  2. Check Network tab to see API requests/responses
  3. Verify you're logged in: api.isAuthenticated()
  4. Check API documentation for correct parameters

Last Updated: January 2025