mirror of
https://github.com/Dingo-Shenanigans/ReSkate.git
synced 2026-10-18 12:05:21 +02:00
36 lines
1.3 KiB
C++
36 lines
1.3 KiB
C++
#pragma once
|
|
#include <algorithm>
|
|
#include <cstdint>
|
|
#include <string>
|
|
#include <string_view>
|
|
|
|
namespace dingosdk {
|
|
// Chat flood control, the same for the sender, the host, a dedicated server and every
|
|
// receiver: a few lines at once, then one every 1.5 s, and never the same line twice within
|
|
// 15 s. Receivers allow one line of slack for lines that arrive bunched up.
|
|
struct ChatRate {
|
|
static constexpr double burst = 4, interval_us = 1500000;
|
|
static constexpr std::uint64_t repeat_us = 15000000;
|
|
enum class Verdict { accepted, too_fast, repeated };
|
|
double tokens = burst;
|
|
std::uint64_t refilled{}, previous_at{};
|
|
std::string previous;
|
|
Verdict accept(std::uint64_t now, std::string_view text, double slack = 0) {
|
|
const double limit = burst + slack;
|
|
if (!refilled || now < refilled) {
|
|
tokens = limit;
|
|
} else {
|
|
tokens = std::min(limit, tokens + static_cast<double>(now - refilled) / interval_us);
|
|
}
|
|
refilled = now;
|
|
if (!previous.empty() && text == previous && now >= previous_at && now - previous_at < repeat_us)
|
|
return Verdict::repeated;
|
|
if (tokens < 1) return Verdict::too_fast;
|
|
tokens -= 1;
|
|
previous.assign(text);
|
|
previous_at = now;
|
|
return Verdict::accepted;
|
|
}
|
|
};
|
|
} // namespace dingosdk
|