feat: flag accounts Reddit considers unestablished and re-test them
New accounts cannot start chats until Reddit considers them established. Until now the bot would burn a candidate on every invitation Reddit was always going to reject, with nothing in the dashboard explaining why the account looked idle. Two signals feed the verdict. A periodic profile check reads the account's own age, karma and email verification from about.json and compares them against configurable thresholds — that is what flags a brand new account before it wastes anything. A rejected invitation is authoritative: Reddit has told us directly, so the account is held out of sending with a backoff that doubles per rejection, and a delivered invitation clears the flag outright. An unestablished account takes no new posts (canAcceptPost), raises an attention item, reports an `unestablished` sending state, and shows its age/karma evidence on the Accounts page. An unchecked account is always allowed through, so a first run is never blocked. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c43e534cf1
commit
89eb4583f8
25 files changed
+1425
-11
No files matched your search
@@ -164,6 +164,36 @@ export const ConfigSchema = z.object({
|
||||
killOnSellerKeyword: true,
|
||||
aiReplyScreening: { enabled: false, killConfidence: 0.8, flagConfidence: 0.6 },
|
||||
}),
|
||||
/**
|
||||
* New Reddit accounts cannot start chats until Reddit considers them
|
||||
* established. Rather than burning candidates on invitations Reddit will
|
||||
* reject, an account is flagged and held out of outbound sending, then
|
||||
* re-tested on an interval.
|
||||
*/
|
||||
accountEstablishment: z.object({
|
||||
enabled: z.boolean().default(true),
|
||||
/** How often an account's own age/karma profile is refreshed. */
|
||||
profileCheckIntervalMs: z.number().int().min(60_000).default(6 * 60 * 60_000),
|
||||
minAccountAgeDays: z.number().min(0).default(7),
|
||||
minTotalKarma: z.number().int().min(0).default(20),
|
||||
minCommentKarma: z.number().int().min(0).default(5),
|
||||
requireVerifiedEmail: z.boolean().default(false),
|
||||
/**
|
||||
* How long to hold an account out of sending after Reddit rejects an
|
||||
* invitation for being too new. Doubles per consecutive rejection.
|
||||
*/
|
||||
probeRetryBaseMs: z.number().int().min(60_000).default(4 * 60 * 60_000),
|
||||
probeRetryMaxMs: z.number().int().min(60_000).default(48 * 60 * 60_000),
|
||||
}).default({
|
||||
enabled: true,
|
||||
profileCheckIntervalMs: 6 * 60 * 60_000,
|
||||
minAccountAgeDays: 7,
|
||||
minTotalKarma: 20,
|
||||
minCommentKarma: 5,
|
||||
requireVerifiedEmail: false,
|
||||
probeRetryBaseMs: 4 * 60 * 60_000,
|
||||
probeRetryMaxMs: 48 * 60 * 60_000,
|
||||
}),
|
||||
pushNotifications: z.object({
|
||||
enabled: z.boolean().default(false),
|
||||
/** Base URL of the ntfy server, e.g. https://ntfy.example.com. */
|
||||
|
||||
Reference in new issue
Block a user