Harden conversation replies and prioritize newest candidates
This commit is contained in:
1 parent
f98c5c732d
commit
b8e4a1bb88
23 files changed
+598
-113
No files matched your search
@@ -0,0 +1,70 @@
|
||||
export interface BoundaryMessage {
|
||||
text: string;
|
||||
isSelf: boolean;
|
||||
}
|
||||
|
||||
const MEDIA_NOUN = String.raw`(?:pic|pics|picture|pictures|photo|photos|selfie|selfies|snap|snaps|image|images|video|videos|nude|nudes|content)`;
|
||||
const MEDIA_VERB = String.raw`(?:send(?:ing)?|shar(?:e|ing)|show(?:ing)?|giv(?:e|ing)|drop(?:ping)?|swap(?:ping)?|trad(?:e|ing))`;
|
||||
|
||||
const EXPLICIT_MEDIA_REFUSAL_PATTERNS = [
|
||||
new RegExp(String.raw`\b(?:no|not|never|won't|wouldn't|don't|do not|can't|cannot)\b[^.\n]{0,60}\b${MEDIA_NOUN}\b`, 'i'),
|
||||
new RegExp(String.raw`\b(?:won't|wouldn't|don't|do not|not going to|never)\b[^.\n]{0,40}\b${MEDIA_VERB}\b`, 'i'),
|
||||
new RegExp(String.raw`\b(?:zero|no) interest\b[^.\n]{0,60}\b(?:${MEDIA_VERB}|${MEDIA_NOUN}|anything|something)\b`, 'i'),
|
||||
new RegExp(String.raw`\b(?:rather not|not comfortable)\b[^.\n]{0,60}\b(?:${MEDIA_VERB}|${MEDIA_NOUN})\b`, 'i'),
|
||||
];
|
||||
|
||||
const CONTEXTUAL_MEDIA_REFUSAL_PATTERNS = [
|
||||
/^(?:no|nope|nah|no thanks|not really|rather not|pass)(?:,? thanks)?[.!\s]*$/i,
|
||||
/^(?:i(?:'m| am)|im|we(?:'re| are)|we're) good(?: thanks)?[.!\s]*$/i,
|
||||
/\b(?:zero interest|not interested|no interest)\b/i,
|
||||
/\b(?:not sending|won't send|wouldn't send|don't send|do not send)\b/i,
|
||||
];
|
||||
|
||||
const FULL_STOP_PATTERNS = [
|
||||
/\bstop\b/i,
|
||||
/\bleave me alone\b/i,
|
||||
/\b(?:do not|don't) message\b/i,
|
||||
/\bback off\b/i,
|
||||
/^(?:(?:i'm|i am|im)\s+)?not interested[.!\s]*$/i,
|
||||
/\b(?:creepy|uncomfortable|weirdest (?:reddit )?approach)\b/i,
|
||||
];
|
||||
|
||||
export function containsMediaRequest(text: string): boolean {
|
||||
return new RegExp(String.raw`\b${MEDIA_VERB}\b[^.!?\n]{0,60}\b${MEDIA_NOUN}\b`, 'i').test(text)
|
||||
|| new RegExp(String.raw`\b(?:can|could|would|will) you\b[^.!?\n]{0,60}\b(?:${MEDIA_VERB}\b[^.!?\n]{0,30})?\b${MEDIA_NOUN}\b`, 'i').test(text)
|
||||
|| new RegExp(String.raw`\bgot any (?:more )?${MEDIA_NOUN}\b`, 'i').test(text);
|
||||
}
|
||||
|
||||
export function isFullConversationStop(text: string): boolean {
|
||||
return FULL_STOP_PATTERNS.some((pattern) => pattern.test(text));
|
||||
}
|
||||
|
||||
export function isMediaRefusal(text: string, mediaWasRequested: boolean): boolean {
|
||||
const normalized = text.replaceAll('’', "'");
|
||||
if (EXPLICIT_MEDIA_REFUSAL_PATTERNS.some((pattern) => pattern.test(normalized))) return true;
|
||||
return mediaWasRequested && CONTEXTUAL_MEDIA_REFUSAL_PATTERNS.some((pattern) => pattern.test(normalized.trim()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect recipient limits in sequence so short phrases such as "I'm good"
|
||||
* only become a media boundary when they directly follow a media request.
|
||||
*/
|
||||
export function detectConversationBoundaries(messages: readonly BoundaryMessage[]): string[] {
|
||||
const boundaries: string[] = [];
|
||||
let lastSelfRequestedMedia = false;
|
||||
|
||||
for (const message of messages) {
|
||||
if (message.isSelf) {
|
||||
lastSelfRequestedMedia = containsMediaRequest(message.text);
|
||||
continue;
|
||||
}
|
||||
if (isMediaRefusal(message.text, lastSelfRequestedMedia)) {
|
||||
boundaries.push('does not want to send photos or videos');
|
||||
}
|
||||
if (isFullConversationStop(message.text)) {
|
||||
boundaries.push('does not want further sexual escalation');
|
||||
}
|
||||
}
|
||||
|
||||
return [...new Set(boundaries)];
|
||||
}
|
||||
Reference in new issue
Block a user