Discord Webhook 速率限制

Mar*_*ner 7 javascript rate-limiting webhooks discord discord.js

我正在开发一个私人浏览器扩展,它从网页中提取一些信息并通过 webhook 将其发布到 Discord 频道。

浏览器扩展会评估x-ratelimit-...响应标头以观察速率限制限制。

在进行“垃圾邮件测试”时,似乎正确遵守了速率限制限制,并且到目前为止一切正常。但是,即使ratelimit-remaining是 > ,我仍然时不时地在发送一堆消息(15+)后受到速率限制0

为了解决这个问题,我已经停止了 time ratelimit-remainingis1并且还在ratelimit-reset时间戳中添加了一个额外的秒。但这似乎没有帮助。

let rateLimitRemaining = 5;
let rateLimitReset = 0;

function sendContent()
{
    if ( contentQueue.length > 0 )
    {
        console.log( "Messages in content queue: " + contentQueue.length );

        let content = contentQueue[ 0 ];
        let dateTimestamp = getCurrentUTCTimestamp();

        // Don't send if remaining rate limit is <= 1 and current UTC time is less than reset timestamp
        if ( rateLimitRemaining <= 1 && dateTimestamp <= rateLimitReset )
            return;

        contentQueue.shift();

        let url = "...";
        sendMessage( content, url );
    }
}

function sendMessage( content, url )
{
    let payload = JSON.stringify( { "content": content } );
    $.ajax(
    {
        contentType: 'application/json',
        method: "POST",
        url: url,
        data: payload,
        dataType: 'json'
    } ).done( function( response, status, jqXHR )
    {
        rateLimitRemaining = parseInt( jqXHR.getResponseHeader( 'x-ratelimit-remaining' ) );
        // Add an additional second to the reset timestamp
        rateLimitReset = parseInt( jqXHR.getResponseHeader( 'x-ratelimit-reset' ) ) + 1;

        let timeToResetRemaining = rateLimitReset - getCurrentUTCTimestamp();
        console.log( '[' + getCurrentDateTime() + '] Content sent to webhook. Remaining until rate limit: ' + rateLimitRemaining + ' / Reset @ ' + rateLimitReset + ' (' + getCurrentUTCTimestamp() + ') (' + timeToResetRemaining + ')' );
    } ).fail( function( jqXHR, status, error )
    {
        let response = jqXHR.responseJSON;

        // If we got rate limited, respect the retry_after delay
        if ( response.hasOwnProperty( 'message' ) && response.message.indexOf( 'rate limited' ) !== 0 )
        {
            rateLimitRemaining = 0;
            rateLimitReset = getCurrentUTCTimestamp() + Math.ceil( response.retry_after / 1000 ) + 1;
        }

        console.log( '[' + getCurrentDateTime() + '] Error sending request to webhook.' );
        console.log( response );
    } );
}
Run Code Online (Sandbox Code Playgroud)

速率受限,即使剩余请求数为 3

同样奇怪的是,触发速率限制的相同请求的x-ratelimit-remaining响应标头 > 0。

速率限制响应头 > 0

我在这里想念什么?我的错误在哪里?我是否需要采取x-ratelimit-bucketx-ratelimit-reset-after考虑藏汉?

小智 0

根据不和谐的开发人员文档,标头中的速率限制不为零似乎确实很奇怪。不确定您的应用程序中是否存在这种情况,但它确实提到“控制表情符号的路由不遵循正常的速率限制约定。这些路由在每个公会的基础上受到特别限制,以防止滥用。这意味着我们返回的配额API 可能不准确,您可能会遇到 429。”

开发人员文档指出,您应该依靠 Retry-After 标头或 retry-after 字段来确定重试时间,因此最好这样做而不是其他标头。无论剩余标头是否可用,API 速率限制的更好模式是将所有查询添加到队列中,成功时将其从队列中删除,失败时出现 429 状态,为队列设置超时基于 Retry-After 标头。这将确保您的请求继续得到处理。您绝对可以在浏览器端 javascript 中执行此操作,但是我将把它作为练习留给读者,因为无论如何它可能不是最好的方法(见下文)。

如果您打算让其他人使用此代码或发布它,那么您将不希望直接从浏览器调用 API,因为它将允许访问您的 Webhook 凭据。相反,让您的浏览器针对服务器进行身份验证,然后隐藏您的 Webhook 凭据。然后,如果您要在服务器上使用 Node.js,我建议您使用 Discord.js SDK,它会自动处理速率限制。