Discord.js对接Google Sheets作为机器人数据库的认证问题求助
解决Discord机器人对接Google Sheets的认证问题
核心问题说明
你现在使用的Web类型OAuth2凭证并不适合Discord机器人这类无前端交互的后台服务。这类凭证需要用户手动授权,而服务账号凭证才是专为服务器端无交互场景设计的,也是你最初成功使用的方案。下面分两种场景给出解决方案:
方案一:回到服务账号凭证(推荐,最适配机器人场景)
1. 重新生成服务账号凭证
- 登录Google Cloud控制台,进入你的项目
- 导航到「IAM与管理」→「服务账号」
- 创建/选择目标服务账号,点击「添加密钥」→「创建新密钥」,选择JSON格式下载,这个文件就是你最初使用的包含
private_key的凭证
2. 配置表格权限
- 打开目标Google Sheets,点击右上角「共享」
- 输入服务账号凭证里的
client_email字段值,赋予编辑权限,保存
3. 使用原代码对接(替换新凭证)
把新下载的服务账号凭证JSON替换掉原sheet.json,运行你最初的代码即可,无需修改逻辑:
const { GoogleSpreadsheet } = require('google-spreadsheet'); const sheet = require('./sheet.json') // 替换为新的服务账号凭证 const doc = new GoogleSpreadsheet('<你的表格ID>'); async function initSheet() { await doc.useServiceAccountAuth(sheet); await doc.loadInfo() } bot.on('ready', () => { initSheet() })
方案二:适配Web类型OAuth2凭证(不推荐,需手动授权一次)
如果一定要用Web类型凭证,需要完成OAuth2授权流程并存储刷新令牌,步骤如下:
1. 首次授权获取刷新令牌
安装依赖:
npm install googleapis google-spreadsheet
运行以下代码生成授权链接,复制到浏览器打开完成授权,拿到返回的code:
const { google } = require('googleapis'); const fs = require('fs'); const credentials = require('./web-credentials.json'); // 你的Web类型凭证 const oauth2Client = new google.auth.OAuth2( credentials.web.client_id, credentials.web.client_secret, 'http://localhost:3000/callback' // 本地回调地址,无需启动服务,授权后会跳转并显示code ); // 生成授权URL const authUrl = oauth2Client.generateAuthUrl({ access_type: 'offline', // 必须添加才能获取refresh_token scope: ['https://www.googleapis.com/auth/spreadsheets'] // 表格读写权限 }); console.log('请访问以下链接授权:', authUrl); // 替换成你拿到的code,运行后会生成tokens.json存储令牌 async function saveTokens(code) { const { tokens } = await oauth2Client.getToken(code); oauth2Client.setCredentials(tokens); fs.writeFileSync('./tokens.json', JSON.stringify(tokens)); console.log('令牌已保存'); } // 首次运行时取消注释并传入code // saveTokens('你从浏览器拿到的code');
2. 机器人启动时加载令牌并对接表格
使用以下代码完成认证,令牌过期会自动刷新并保存:
const { GoogleSpreadsheet } = require('google-spreadsheet'); const { google } = require('googleapis'); const fs = require('fs'); const credentials = require('./web-credentials.json'); const tokens = require('./tokens.json'); const oauth2Client = new google.auth.OAuth2( credentials.web.client_id, credentials.web.client_secret ); oauth2Client.setCredentials(tokens); // 监听令牌更新,自动保存新令牌 oauth2Client.on('tokens', (newTokens) => { fs.writeFileSync('./tokens.json', JSON.stringify(newTokens)); }); const doc = new GoogleSpreadsheet('<你的表格ID>'); async function initSheet() { await doc.useOAuth2Client(oauth2Client); await doc.loadInfo(); console.log('表格初始化完成'); } bot.on('ready', () => { initSheet() })
报错原因解析
gapi is not defined:gapi是浏览器端的Google API库,Node.js环境无法直接使用,需改用googleapis库You must initialize some kind of auth before making any requests:Web类型凭证格式不符合服务账号认证的要求,不能直接用useServiceAccountAuth,需改用OAuth2客户端认证fetchUserGoogleCredsFromDatabase() is not defined:这是官方示例中的自定义函数,需要你自己实现从文件/数据库读取令牌的逻辑,对应上面代码中读取tokens.json的部分
内容的提问来源于stack exchange,提问作者Howlita
相关产品推荐
相关产品推荐

