Discord bot 无法访问 Google Sheets 获取错误请求缺少有效的 API 密钥

Posted

技术标签:

【中文标题】Discord bot 无法访问 Google Sheets 获取错误请求缺少有效的 API 密钥【英文标题】:Discord bot unable to get access to the Google Sheets getting error The request is missing a valid API key 【发布时间】:2021-05-15 22:03:20 【问题描述】:

我的 Discord 机器人尝试访问 Google Sheets API v4.0 时遇到问题。我希望它读取、写入和更新工作表中的数据。我的代码适用于 Node.js 应用程序,但是当我将代码放入 Discord 机器人时,它给了我这个错误:

UnhandledPromiseRejectionWarning: Error: The request is missing a valid API key

我不明白为什么会出现此错误。我什至为我的 Discord 机器人创建了一个服务帐户。

这是 Discord 机器人的代码。

require('dotenv').config();

const sheet = require('./sheet');
const  Client  = require('discord.js');
const  sheets  = require('googleapis/build/src/apis/sheets');
const client = new Client();

图纸文件代码:

const google = require('googleapis');
const keys = require('./keys.json');

const client  = new google.auth.JWT(
    keys.client_email,
    keys.private_key_id,
    keys.private_key,
    ['https://www.googleapis.com/auth/spreadsheets']
);

client.authorize(function(err,tokens)

    if(err)
        console.log(err);
        return;
    
    // else
    //     console.log('Connected');
    //     gsrun(client);
    // 
);

const getdata = async function gsrun(cl)

    const gsapi = google.sheets(version:'v4',auth:cl);

    const opt = 
        spreadsheetId:'1LzdhD4rb2FdElTyQCAkgb5oyeGeu0d9rT2abS4n_4i8',
        range: 'A2:B5'
    ;

    let data =  await gsapi.spreadsheets.values.get(opt);

    console.log(data.data.values);

exports.getdata = getdata;

我已授予对工作表 discordbotapi@nodejs-api-testing-discordbot.iam.gserviceaccount.com 的 bot 电子邮件 ID 的访问权限。我还启用了 Google Sheets API。我在哪里出错了?

【问题讨论】:

你怎么称呼getdata()?看起来您从未通过在client.authorize() 中收到的令牌。 @ZsoltMeszaros 我不知道,但它在节点 js 应用程序中运行良好。当我在 discord .js 中使用我的代码时出现问题,它给了我这个奇怪的错误! 我认为它运行良好,因为一旦获得授权,您就将其称为 gsrun(client)。现在,您只导出一个函数,没有任何授权,而且我认为您在导入getdata 后不会通过client @ZsoltMeszaros 所以根据你的说法,我应该用它导出我的授权,然后在那里授权。这里应该用什么方法来解决它。 @COdeingNinja 我有一个不和谐的机器人,它具有相同的前提,它使用 googleapis 将信息附加到电子表格。我所做的是创建单独的函数,一个用于通过 Discord 收集消息,然后一个用于 googleapi 附加功能。然后我只是创建了一个包含数组的全局变量并将其传递给附加函数。可能是另一种尝试的方法。 【参考方案1】:

当你在没有 Discord.js 的 Node.js 中尝试它时,你没有导出任何东西,你只是在授权成功后调用了 gsrun(client),所以它工作正常。问题是现在您尝试在没有任何授权的情况下使用getData。尽管您的代码中有client.authorize,但您从不使用它。

为了解决这个问题,我会在这里至少做两个不同的功能;一个用于生成客户端,一个用于获取请求本身并将它们都导出。

为了生成一个客户端,我将它包装在一个 Promise 中。这样我以后可以使用 async/await 。此函数将使用 JWT 创建一个客户端,执行授权,并根据 client.authorize() 的结果与客户端解析或拒绝承诺。

function connect() 
  return new Promise((resolve, reject) => 
    const scope = ['https://www.googleapis.com/auth/spreadsheets'];
    const  client_email, private_key, private_key_id  = keys;
    const client = new google.auth.JWT(
      client_email,
      private_key_id,
      private_key,
      scope,
    );

    client.authorize((err) => 
      if (err) 
        reject(err);
       else 
        resolve(client);
      
    );
  );

现在您可以使用const client = await connect() 简单地连接并获取客户端。

第二部分是从电子表格中获取一些数据。再一次,我会把它包装在一个承诺中。该函数将接受客户端(我们刚刚在上面创建)以及带有电子表格 ID 和范围的选项。在 Promise 中,您只需使用选项调用 API 端点:

function getData(client, options) 
  return new Promise((resolve, reject) => 
    const endpoint = google.sheets( version: 'v4', auth: client );

    endpoint.spreadsheets.values.get(options, (err, data) => 
      if (err) 
        reject(err);
       else 
        // or resolve with data.data.values if you only want the values
        resolve(data.data);
      
    );
  );

您可以将这两者都导出到一个对象中。这是完整的sheet.js 文件:

const  google  = require('googleapis');

const keys = require('./keys.json');

function connect() 
  return new Promise((resolve, reject) => 
    const scope = ['https://www.googleapis.com/auth/spreadsheets'];
    const  client_email, private_key, private_key_id  = keys;
    const client = new google.auth.JWT(
      client_email,
      private_key_id,
      private_key,
      scope,
    );

    client.authorize((err) => 
      if (err) 
        reject(err);
       else 
        resolve(client);
      
    );
  );


function getData(client, options) 
  return new Promise((resolve, reject) => 
    const endpoint = google.sheets( version: 'v4', auth: client );

    endpoint.spreadsheets.values.get(options, (err, data) => 
      if (err) 
        reject(err);
       else 
        resolve(data.data);
      
    );
  );


module.exports =  connect, getData ;

然后,您可以将其导入您的机器人文件并在其中使用它先进行连接,然后获取值:

const  Client  = require('discord.js');
const  connect, getData  = require('./sheet');

const client = new Client();

client.on('message', async (message) => 
  if (message.author.bot) return;

  const auth = await connect();

  const options = 
    spreadsheetId: '1LzdhD4rb2FdElTyQCAkgb5oyeGeu0d9rT2abS4n_4i8',
    range: 'A2:B5',
  ;
  const  values  = await getData(auth, options);

  message.channel.send(values);
);

【讨论】:

以上是关于Discord bot 无法访问 Google Sheets 获取错误请求缺少有效的 API 密钥的主要内容,如果未能解决你的问题,请参考以下文章

Discord Bot 回复自己,无法识别 message.author.bot

无法使用 NPM 安装“discord-music-bot”

discord bot 缺少权限,但授予管理员访问权限

Discord Bot 读取 Google 表格并在表格中返回值。我想在没有表格格式的消息中返回值 ar CSV

Discord Bot 无法识别命令名称

Discord Bot 无法发送消息