Skip to content

Backend API for youtube Stats #147

Open
GauravOP-03 wants to merge 3 commits intoscriptaiapp:mainfrom
GauravOP-03:backend-stats-api
Open

Backend API for youtube Stats #147
GauravOP-03 wants to merge 3 commits intoscriptaiapp:mainfrom
GauravOP-03:backend-stats-api

Conversation

@GauravOP-03
Copy link
Copy Markdown
Collaborator

📝 Description

Extend the API layer to support the new plan-based usage limits and YouTube analytics features. This includes integrating Supabase RPC functions for quota enforcement, exposing richer YouTube stats endpoints, and wiring story-builder creation/validation through the shared @repo/validation schema.

🎯 Type of Change

  • 🐛 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • 📚 Documentation update (API behavior / responses)
  • 🎨 Style/UI changes (formatting, missing semi colons, etc; no logic change)
  • ♻️ Refactoring (no functional changes, code improvements)
  • ⚡ Performance improvements
  • 🧪 Adding or updating tests
  • 🔧 Configuration changes

🧪 Testing

  • I have tested my changes locally
  • I have added tests for my changes
  • All existing tests pass
  • I have tested on different browsers/devices (if applicable)

Examples to mention:

  • Called /youtube/channel-stats with and without forceSync=true for a connected channel.

📋 Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation (this PR description / API docs)
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • I have checked my code and corrected any misspellings
  • I have read the Contributing Guide

📸 Screenshots (if applicable)

Before:

  • /youtube/channel-stats did not exist or did not expose plan-aware quota state.

After:

  • /youtube/channel-stats returns channel analytics plus fields like plan, remaining, daily_limit, usage_count, cooldown_minutes, cooldown_remaining, can_use_now.

🔧 Technical Details

  • YouTube API integration (apps/api/src/youtube)

    • YoutubeController:
      • Guarded by SupabaseAuthGuard and uses getUserId to derive the current user.
      • Endpoints:
        • GET /youtube/trained-videos: returns the list of videos stored in youtube_channels.youtube_trained_videos.
        • POST /youtube/trained-videos: saves the current selection of trained videos to youtube_channels.youtube_trained_videos.
        • GET /youtube/channel-stats?forceSync=: returns aggregated channel stats and quota information, optionally forcing a fresh sync from YouTube when forceSync=true.
    • YoutubeService:
      • Centralized YouTube integration using axios and SupabaseService:
        • getVideoMetadata:
          • Validates videoUrl via regex.
          • Uses the configured YOUTUBE_API_KEY.
          • Calls https://www.googleapis.com/youtube/v3/videos and returns { title, thumbnail } with robust error handling for invalid URLs and API failures.
        • getChannelVideos:
          • Loads the user’s youtube_channels row (channel id + OAuth tokens).
          • Resolves a valid access token using resolveAccessToken, which verifies the current token and refreshes it via oauth2.googleapis.com/token when needed, persisting the new token back to Supabase.
          • Calls YouTube search API to fetch videos for the channel and then calls the videos API to enrich them with view counts.
          • Returns a typed videos: ChannelVideoItem[] plus nextPageToken for pagination.
        • getTrainedVideos / saveTrainedVideos:
          • Persist and retrieve youtube_trained_videos from youtube_channels as a typed ChannelVideoItem[].
        • getChannelStats:
          • When forceSync=true:
            • Calls the new Supabase RPC use_feature(p_user_id uuid) to enforce daily limits and cooldowns before hitting the YouTube API.
              • If use_feature returns allowed=false, responds with 400 and the function’s message (e.g. limit reached or cooldown active).
            • Fetches:
              • Channel-level stats via channels?part=snippet,statistics&mine=true.
              • Top videos by view count via search (order=viewCount).
              • Recent videos via search (order=date).
              • Video details and engagement metrics via videos?part=statistics,contentDetails.
            • Maps API results into typed ChannelStatsItem objects and computes:
              • totalViews, totalVideos, avgViewsPerVideo, avgLikesPerVideo.
            • Writes channel stats and cached video lists into youtube_channels:
              • channel_name, subscriber_count, view_count, video_count, top_videos, recent_videos, last_synced_at.
            • Returns a ChannelStats object that includes:
              • Channel metadata and aggregates.
              • Quota fields from use_feature: cooldown_minutes, can_use_now, plan, remaining, daily_limit, usage_count, cooldown_remaining.
              • Channel metadata from DB: custom_url, country, default_language, thumbnail.
          • When forceSync is not set or false:
            • Reads cached stats from youtube_channels (including top_videos, recent_videos, last_synced_at, usage_count, and channel metadata).
            • Calls Supabase RPC get_feature_usage(p_user_id uuid) to get a read-only view of the current quota and cooldown state.
            • Returns the same ChannelStats shape, but without calling the YouTube APIs, which is cheaper and respects usage limits.
      • resolveAccessToken:
        • Validates the existing access token via tokeninfo, and if invalid, uses the stored refresh_token plus configured GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET to obtain a new access token.
        • Updates youtube_channels.provider_token and updated_at with the new token.
  • Schema reuse

    • The API now uses:
      • ChannelVideoItem, ChannelStatsItem, ChannelStats from @repo/validation so the returned JSON from YouTube endpoints matches the shared frontend/backend types.

🚀 Deployment Notes

  • Ensure Supabase migrations (including plans_v2 and new functions use_feature and get_feature_usage) are applied before deploying this API code.
  • No additional infra changes; standard rollout of the API service is sufficient once the DB is up to date.

🔍 Review Notes

  • Pay special attention to:
    • Error handling and edge cases around YouTube OAuth token refresh and API failures.
    • Correctness of quota enforcement around use_feature and get_feature_usage (e.g. what happens at day boundaries and when forceSync=true).
    • That the shapes returned from the YouTube endpoints match the shared @repo/validation types and the frontend expectations.

📊 Performance Impact

  • No performance impact
  • Performance improvement
  • Performance regression (explain below)

Details:

  • Cached YouTube channel stats and video lists in youtube_channels are reused when forceSync is not requested, reducing calls to the YouTube API.
  • Database-level quota checks prevent unnecessary external API calls once a user hits their daily limits or is in cooldown.

🔒 Security Considerations

  • No security implications
  • Security improvement
  • Potential security concern (explain below)

Details:

  • All new endpoints are behind SupabaseAuthGuard and perform per-user queries using user_id.
  • OAuth tokens are never exposed to the client; token refresh happens server-side and new tokens are stored back into Supabase securely.
  • Quota enforcement via Supabase functions helps limit abuse of expensive YouTube API calls.

🎉 Additional Notes

  • These changes align the API with the new Supabase schema and shared TypeScript models so that story builder and YouTube stats features can scale safely with clear, typed contracts across the stack.

@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Feb 27, 2026

@GauravOP-03 is attempting to deploy a commit to the afrin127329's projects Team on Vercel.

A member of the Team first needs to authorize it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant