← back to Goodquestion Ai

scripts/youtube-auth.cjs

71 lines

/**
 * YouTube OAuth2 Authorization Flow
 * Run once to get a refresh token, then youtube-upload.cjs uses it automatically.
 */
const { google } = require('googleapis');
const http = require('http');
const url = require('url');
const fs = require('fs');
const path = require('path');

require('dotenv').config({ path: require('path').join(__dirname, '..', '.env') });
const CLIENT_ID = process.env.YOUTUBE_CLIENT_ID;
const CLIENT_SECRET = process.env.YOUTUBE_CLIENT_SECRET;
const REDIRECT_URI = process.env.YOUTUBE_REDIRECT_URI || 'http://localhost:3456/oauth/callback';
const TOKEN_PATH = path.join(__dirname, '..', '.youtube-token.json');

const oauth2Client = new google.auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI);

const SCOPES = [
  'https://www.googleapis.com/auth/youtube.upload',
  'https://www.googleapis.com/auth/youtube',
];

// Generate auth URL
const authUrl = oauth2Client.generateAuthUrl({
  access_type: 'offline',
  scope: SCOPES,
  prompt: 'consent',
});

console.log('\n=== YouTube OAuth Authorization ===\n');
console.log('Open this URL in your browser:\n');
console.log(authUrl);
console.log('\nWaiting for authorization callback on port 3456...\n');

// Start local server to catch the callback
const server = http.createServer(async (req, res) => {
  const queryParams = url.parse(req.url, true).query;

  if (queryParams.code) {
    try {
      const { tokens } = await oauth2Client.getToken(queryParams.code);

      // Save tokens
      fs.writeFileSync(TOKEN_PATH, JSON.stringify(tokens, null, 2));

      res.writeHead(200, { 'Content-Type': 'text/html' });
      res.end('<h1>Authorization successful!</h1><p>You can close this tab. Token saved.</p>');

      console.log('Token saved to:', TOKEN_PATH);
      console.log('You can now use youtube-upload.cjs to upload videos.\n');

      server.close();
    } catch (err) {
      res.writeHead(500, { 'Content-Type': 'text/html' });
      res.end(`<h1>Error</h1><p>${err.message}</p>`);
      console.error('Token exchange failed:', err.message);
      server.close();
    }
  } else if (queryParams.error) {
    res.writeHead(400, { 'Content-Type': 'text/html' });
    res.end(`<h1>Authorization denied</h1><p>${queryParams.error}</p>`);
    console.error('Authorization denied:', queryParams.error);
    server.close();
  }
});

server.listen(3456, () => {
  console.log('Callback server listening on port 3456');
});