How to resolve the 302 error when integrating a Discord bot with Excel sheets

Seeking assistance with my automation project

I am building a Discord bot that pulls messages from my server and logs them into an Excel spreadsheet using Apps Script. The strange part is that during manual testing with the testDoPost function, everything works without a hitch, and the data successfully populates my spreadsheet.

The webhook setup appears correct, and the deployment is accurate, but when a message is sent from Discord, the bot seems to completely ignore it. Instead, I keep encountering this error: “last_error_message”: “Wrong response from the webhook: 302 Moved Temporarily”

// Discord Bot with Excel Integration
// Captures messages via webhook and stores information in the spreadsheet

const SPREADSHEET_NAME = 'MyData'; // Expected spreadsheet name

// Securely store Discord token
function setDiscordToken() {
  const ui = SpreadsheetApp.getUi();
  const response = ui.prompt('Enter Discord Token', 'Please provide your Discord bot token:', ui.ButtonSet.OK_CANCEL);

  if (response.getSelectedButton() == ui.Button.OK) {
    const token = response.getResponseText().trim();
    if (token) {
      PropertiesService.getScriptProperties().setProperty('DISCORD_TOKEN', token);
      ui.alert('Token saved successfully!');
    }
  }
}

// Retrieve the stored Discord token
function getDiscordToken() {
  const token = PropertiesService.getScriptProperties().getProperty('DISCORD_TOKEN');
  if (!token) {
    throw new Error('Discord token missing. Run setDiscordToken() first.');
  }
  return token;
}

// Handle GET requests
function doGet(e) {
  return HtmlService.createHtmlOutput("Webhook active and ready to receive Discord updates.");
}

// Process incoming webhook data
function doPost(e) {
  try {
    if (!e || !e.postData || !e.postData.contents) {
      return ContentService.createTextOutput(JSON.stringify({ result: 'error', info: 'Missing data' }))
                           .setMimeType(ContentService.MimeType.JSON);
    }

    const webhookData = JSON.parse(e.postData.contents);
    
    if (!webhookData.message || !webhookData.message.content) {
      return ContentService.createTextOutput(JSON.stringify({ result: 'error', info: 'No message content' }))
                           .setMimeType(ContentService.MimeType.JSON);
    }

    const messageText = webhookData.message.content;
    const channelId = webhookData.message.channel.id;

    // Process messages starting with "!" and containing digits
    if (messageText.startsWith('!') && /\d/.test(messageText)) {
      const idMatch = messageText.match(/!(\d+)/);
      const quantityMatch = messageText.match(/(\d+)x/);
      const priceMatch = messageText.match(/(\d+\.\d+)\$/);
      const platformMatch = messageText.match(/\$([a-zA-Z0-9]+)/);

      if (idMatch && quantityMatch && priceMatch && platformMatch) {
        const recordId = idMatch[1];
        const quantity = quantityMatch[1];
        const price = priceMatch[1];
        const platform = platformMatch[1];

        const targetSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SPREADSHEET_NAME);
        if (!targetSheet) {
          sendDiscordResponse(channelId, `Error: Spreadsheet "${SPREADSHEET_NAME}" not found.`);
          return ContentService.createTextOutput(JSON.stringify({ result: 'error', info: 'Spreadsheet missing' }))
                               .setMimeType(ContentService.MimeType.JSON);
        }

        targetSheet.appendRow([recordId, quantity, price, platform]);
        sendDiscordResponse(channelId, 'Data saved to spreadsheet!');
      } else {
        sendDiscordResponse(channelId, 'Wrong format. Use: !id quantityx price$platform');
      }
    }

    return ContentService.createTextOutput(JSON.stringify({ result: 'success' }))
                         .setMimeType(ContentService.MimeType.JSON);

  } catch (error) {
    return ContentService.createTextOutput(JSON.stringify({ result: 'error', info: error.message }))
                         .setMimeType(ContentService.MimeType.JSON);
  }
}

// Send response back to Discord
function sendDiscordResponse(channelId, message) {
  const DISCORD_TOKEN = getDiscordToken();
  const apiUrl = `https://discord.com/api/channels/${channelId}/messages`;
  
  const requestData = {
    content: message
  };
  
  const requestOptions = {
    method: 'post',
    headers: {
      'Authorization': `Bot ${DISCORD_TOKEN}`,
      'Content-Type': 'application/json'
    },
    payload: JSON.stringify(requestData)
  };

  try {
    UrlFetchApp.fetch(apiUrl, requestOptions);
  } catch (error) {
    Logger.log('Failed to send Discord message: ' + error.message);
  }
}

// Configure webhook endpoint
function configureWebhook() {
  const DISCORD_TOKEN = getDiscordToken();
  const appUrl = 'https://script.google.com/macros/s/.../exec';
  const webhookUrl = `https://discord.com/api/webhooks/set?url=${encodeURIComponent(appUrl)}`;
  
  try {
    const response = UrlFetchApp.fetch(webhookUrl);
    Logger.log('Webhook configured: ' + response.getContentText());
  } catch (error) {
    Logger.log('Webhook setup failed: ' + error.message);
  }
}

// Test function
function testDoPost() {
  const mockEvent = {
    postData: {
      contents: JSON.stringify({
        message: {
          content: "!456 78x 90.12$testPlatform",
          channel: {
            id: 987654321
          }
        }
      })
    }
  };
  
  doPost(mockEvent);
}

I’ve tried numerous solutions: recreating the bot, resetting the webhook repeatedly, redeploying the script, yet nothing seems to resolve the issue. Given that the code was generated with AI support, there might be aspects that I’m overlooking. Any insights on what might be causing this 302 error would be greatly appreciated!

Had this exact problem a few months ago - drove me nuts for days. Your doPost function is probably returning JSON responses, but Apps Script webhooks expect plain text by default. Change all your ContentService responses to just return ContentService.createTextOutput(‘OK’) or HtmlService.createHtmlOutput(‘success’). The 302 redirect happens when Apps Script can’t handle the response format you’re sending back to Discord. Also check your webhook URL ends with /exec not /dev - that causes redirects too.

that 302 error means ur Apps Script is redirecting instead of sending back a proper response. check ur deployment settings - make sure it’s “execute as: me” and “who has access: anyone.” this catches a lot of people. also, u need the webapp URL for your Discord webhook, not the editor URL.

The 302 error is coming from authentication issues with your Apps Script deployment. Discord’s webhook request is hitting an auth wall that’s causing the redirect. Check that your web app is deployed with “Execute as: Me” and “Who has access: Anyone” - but more importantly, make sure you’re using the right deployment URL in Discord. I see you’re using a placeholder URL in your configureWebhook function, but that’s not how Discord webhooks work - you set them up directly in your Discord server settings and point them to your Apps Script URL. That webhook configuration function won’t work with Discord’s system.

This topic was automatically closed 4 days after the last reply. New replies are no longer allowed.