fix: never let a guessed threshold hold an account out of sending
The profile check was allowed to set state 'unestablished', which made isSendable() false, which made canAcceptPost() false — so a flagged account never attempted an invitation and the functional probe could never run. The one signal with real authority was gated behind the one that is guessing, and because each check pushed retryAt forward by another interval, accounts that send perfectly well were held indefinitely. Reddit does not publish the thresholds its chat gate applies, so ours are a guess and are now advisory only. Sending is held solely by a live rejection, tracked as sendingHeld on the account summary and keyed off by the attention feed, the sending state and the Accounts page. Reason strings now say "below the configured floor of N" rather than "needs N", and the Accounts page distinguishes "Sending on hold" from "Below thresholds", stating outright that the latter is our own number and the account is still sending. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
89eb4583f8
commit
3a40651930
9 files changed
+164
-71
No files matched your search
@@ -32,25 +32,36 @@ function retryLabel(retryAt: number | null): string {
|
||||
}
|
||||
|
||||
/**
|
||||
* A new account cannot start chats until Reddit considers it established. The
|
||||
* bot holds it out of sending and re-tests it, so this panel exists to explain
|
||||
* why an account looks idle.
|
||||
* Two different situations share this panel: Reddit actively refusing
|
||||
* invitations from the account (sending is on hold), and the account merely
|
||||
* sitting below our own configured thresholds (nothing is blocked). Conflating
|
||||
* them reads as a broken account when it is only a soft signal.
|
||||
*/
|
||||
function EstablishmentDetail({ establishment }: { establishment: AccountEstablishmentSummary }) {
|
||||
const isUnestablished = establishment.state === 'unestablished';
|
||||
const belowThresholds = establishment.state === 'unestablished' && !establishment.sendingHeld;
|
||||
return (
|
||||
<div className="account-establishment">
|
||||
{isUnestablished ? (
|
||||
{establishment.sendingHeld ? (
|
||||
<>
|
||||
<p className="account-establishment-reason">
|
||||
{establishment.reasons.length > 0
|
||||
? establishment.reasons.join('; ')
|
||||
: 'Reddit will not accept chat invitations from this account yet.'}
|
||||
{establishment.lastProbeFailure
|
||||
?? 'Reddit rejected an invitation from this account as unestablished.'}
|
||||
</p>
|
||||
<p className="field-hint">Outbound sending is on hold. {retryLabel(establishment.retryAt)}</p>
|
||||
</>
|
||||
) : null}
|
||||
{establishment.lastProbeFailure && !isUnestablished ? (
|
||||
{belowThresholds ? (
|
||||
<>
|
||||
<p className="account-establishment-reason">
|
||||
{establishment.reasons.join('; ')}
|
||||
</p>
|
||||
<p className="field-hint">
|
||||
Still sending normally — these are our own configured thresholds, not limits Reddit
|
||||
publishes. The account is only held back if Reddit actually rejects an invitation.
|
||||
</p>
|
||||
</>
|
||||
) : null}
|
||||
{establishment.lastProbeFailure && !establishment.sendingHeld ? (
|
||||
<p className="field-hint">Last rejection: {establishment.lastProbeFailure}</p>
|
||||
) : null}
|
||||
<dl className="account-establishment-metrics">
|
||||
@@ -69,9 +80,9 @@ function EstablishmentDetail({ establishment }: { establishment: AccountEstablis
|
||||
|
||||
function establishmentPill(establishment: AccountEstablishmentSummary | null | undefined) {
|
||||
if (!establishment || establishment.state === 'unknown') return null;
|
||||
return establishment.state === 'unestablished'
|
||||
? <span className="pill warning">Not established</span>
|
||||
: <span className="pill success">Established</span>;
|
||||
if (establishment.sendingHeld) return <span className="pill warning">Sending on hold</span>;
|
||||
if (establishment.state === 'unestablished') return <span className="pill neutral">Below thresholds</span>;
|
||||
return <span className="pill success">Established</span>;
|
||||
}
|
||||
|
||||
function sessionLabel(status: ReturnType<typeof useLoginStatusQuery>['data']): string {
|
||||
@@ -120,7 +131,7 @@ export function AccountsPage() {
|
||||
: null;
|
||||
const accounts = accountsQuery.data ?? [];
|
||||
const pausedCount = accounts.filter((account) => !account.isRunning).length;
|
||||
const unestablished = accounts.filter((account) => account.establishment?.state === 'unestablished');
|
||||
const heldAccounts = accounts.filter((account) => account.establishment?.sendingHeld);
|
||||
|
||||
return (
|
||||
<div className="page accounts-page">
|
||||
@@ -146,16 +157,16 @@ export function AccountsPage() {
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{unestablished.length > 0 ? (
|
||||
{heldAccounts.length > 0 ? (
|
||||
<div className="state-banner is-warning" role="status">
|
||||
<strong>
|
||||
{unestablished.length === 1
|
||||
? `u/${unestablished[0].redditUsername} is not established yet.`
|
||||
: `${unestablished.length} accounts are not established yet.`}
|
||||
{heldAccounts.length === 1
|
||||
? `u/${heldAccounts[0].redditUsername} cannot start chats yet.`
|
||||
: `${heldAccounts.length} accounts cannot start chats yet.`}
|
||||
</strong>
|
||||
<span>
|
||||
Reddit will not accept chat invitations from a new account, so outbound sending is on hold
|
||||
for it. The bot re-tests periodically and resumes on its own.
|
||||
Reddit rejected an invitation from a new account, so outbound sending is on hold for it.
|
||||
The bot re-tests periodically and resumes on its own.
|
||||
</span>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
Reference in new issue
Block a user