mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 04:55:42 +09:00
208 lines
8.6 KiB
TypeScript
208 lines
8.6 KiB
TypeScript
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
import {DeletionReasons} from '@fluxer/constants/src/Core';
|
|
import type {ValueOf} from '@fluxer/constants/src/ValueOf';
|
|
|
|
export type EnforcementRuleKey =
|
|
| 'spam'
|
|
| 'service_abuse'
|
|
| 'raids'
|
|
| 'automation'
|
|
| 'intimate_images'
|
|
| 'fraud'
|
|
| 'child_safety'
|
|
| 'privacy'
|
|
| 'harassment'
|
|
| 'payments'
|
|
| 'unwanted_sexual_content'
|
|
| 'violent_content'
|
|
| 'ban_evasion'
|
|
| 'hate'
|
|
| 'malware'
|
|
| 'impersonation'
|
|
| 'threats'
|
|
| 'violent_extremism'
|
|
| 'self_harm'
|
|
| 'adult_content'
|
|
| 'illegal_activity'
|
|
| 'harmful_deception'
|
|
| 'report_abuse'
|
|
| 'age_requirement'
|
|
| 'copyright';
|
|
|
|
type EnforcementHandling = 'standard' | 'protected' | 'restricted';
|
|
|
|
export type EnforcementKind =
|
|
| 'warning'
|
|
| 'suspension'
|
|
| 'closure'
|
|
| 'feature_limit'
|
|
| 'content_removal'
|
|
| 'profile_reset'
|
|
| 'community_removal';
|
|
|
|
export type EnforcementLimit = 'direct_messages' | 'reports' | 'purchases';
|
|
|
|
export type EnforcementReasonCode = Exclude<
|
|
ValueOf<typeof DeletionReasons>,
|
|
typeof DeletionReasons.USER_REQUESTED | typeof DeletionReasons.OTHER | typeof DeletionReasons.INACTIVITY
|
|
>;
|
|
|
|
interface EnforcementRule {
|
|
policy: 'guidelines' | 'terms';
|
|
anchor: string;
|
|
barsNewAccounts: boolean;
|
|
showOnNetworkScreen: boolean;
|
|
}
|
|
|
|
interface EnforcementReason {
|
|
rule: EnforcementRuleKey;
|
|
handling: EnforcementHandling;
|
|
kinds: ReadonlyArray<EnforcementKind> | 'any';
|
|
}
|
|
|
|
export const ACCOUNT_DELETION_MIN_DAYS = 14;
|
|
export const ENFORCEMENT_APPEAL_WINDOW_DAYS = 60;
|
|
export const ENFORCEMENT_CLOSURE_MIN_DAYS = ENFORCEMENT_APPEAL_WINDOW_DAYS + ACCOUNT_DELETION_MIN_DAYS;
|
|
|
|
const HARASSMENT_ANCHOR = '1-harassment-threats-and-privacy';
|
|
const VIOLENCE_ANCHOR = '3-violence-extremism-and-self-harm';
|
|
const SEXUAL_CONTENT_ANCHOR = '4-sexual-content-and-protection-of-minors';
|
|
const ILLEGAL_ACTIVITY_ANCHOR = '5-illegal-and-dangerous-activity';
|
|
const SERVICE_ABUSE_ANCHOR = '6-spam-and-service-abuse';
|
|
|
|
function guidelinesRule(anchor: string, showOnNetworkScreen: boolean): EnforcementRule {
|
|
return {policy: 'guidelines', anchor, barsNewAccounts: true, showOnNetworkScreen};
|
|
}
|
|
|
|
export const ENFORCEMENT_RULES: Readonly<Record<EnforcementRuleKey, EnforcementRule>> = {
|
|
spam: guidelinesRule(SERVICE_ABUSE_ANCHOR, true),
|
|
service_abuse: guidelinesRule(SERVICE_ABUSE_ANCHOR, true),
|
|
raids: guidelinesRule(HARASSMENT_ANCHOR, true),
|
|
automation: guidelinesRule(SERVICE_ABUSE_ANCHOR, true),
|
|
intimate_images: guidelinesRule(HARASSMENT_ANCHOR, false),
|
|
fraud: guidelinesRule(ILLEGAL_ACTIVITY_ANCHOR, false),
|
|
child_safety: guidelinesRule(SEXUAL_CONTENT_ANCHOR, false),
|
|
privacy: guidelinesRule(HARASSMENT_ANCHOR, false),
|
|
harassment: guidelinesRule(HARASSMENT_ANCHOR, false),
|
|
payments: {
|
|
policy: 'terms',
|
|
anchor: '4-4-failed-payments-and-disputes',
|
|
barsNewAccounts: true,
|
|
showOnNetworkScreen: false,
|
|
},
|
|
unwanted_sexual_content: guidelinesRule(HARASSMENT_ANCHOR, false),
|
|
violent_content: guidelinesRule(VIOLENCE_ANCHOR, true),
|
|
ban_evasion: guidelinesRule(SERVICE_ABUSE_ANCHOR, false),
|
|
hate: guidelinesRule('2-hate-and-discrimination', false),
|
|
malware: guidelinesRule(ILLEGAL_ACTIVITY_ANCHOR, false),
|
|
impersonation: guidelinesRule(SERVICE_ABUSE_ANCHOR, true),
|
|
threats: guidelinesRule(HARASSMENT_ANCHOR, false),
|
|
violent_extremism: guidelinesRule(VIOLENCE_ANCHOR, false),
|
|
self_harm: guidelinesRule(VIOLENCE_ANCHOR, false),
|
|
adult_content: guidelinesRule(SEXUAL_CONTENT_ANCHOR, true),
|
|
illegal_activity: guidelinesRule(ILLEGAL_ACTIVITY_ANCHOR, false),
|
|
harmful_deception: guidelinesRule('7-harmful-deception-and-manipulated-media', false),
|
|
report_abuse: guidelinesRule('8-reporting', true),
|
|
age_requirement: {
|
|
policy: 'terms',
|
|
anchor: '1-agreement-and-eligibility',
|
|
barsNewAccounts: false,
|
|
showOnNetworkScreen: false,
|
|
},
|
|
copyright: {policy: 'terms', anchor: '3-4-copyright', barsNewAccounts: true, showOnNetworkScreen: true},
|
|
};
|
|
|
|
const RESTRICTED_KINDS: ReadonlyArray<EnforcementKind> = ['suspension', 'content_removal'];
|
|
const PAYMENT_KINDS: ReadonlyArray<EnforcementKind> = ['warning', 'suspension', 'closure', 'feature_limit'];
|
|
|
|
export const ENFORCEMENT_REASONS: Readonly<Record<EnforcementReasonCode, EnforcementReason>> = {
|
|
[DeletionReasons.SPAM]: {rule: 'spam', handling: 'standard', kinds: 'any'},
|
|
[DeletionReasons.CHEATING_OR_EXPLOITATION]: {rule: 'service_abuse', handling: 'standard', kinds: 'any'},
|
|
[DeletionReasons.COORDINATED_RAIDING]: {rule: 'raids', handling: 'standard', kinds: 'any'},
|
|
[DeletionReasons.AUTOMATION_OR_SELFBOT]: {rule: 'automation', handling: 'standard', kinds: 'any'},
|
|
[DeletionReasons.NONCONSENSUAL_SEXUAL_CONTENT]: {rule: 'intimate_images', handling: 'protected', kinds: 'any'},
|
|
[DeletionReasons.SCAM_OR_SOCIAL_ENGINEERING]: {rule: 'fraud', handling: 'standard', kinds: 'any'},
|
|
[DeletionReasons.CHILD_SEXUAL_CONTENT]: {rule: 'child_safety', handling: 'restricted', kinds: RESTRICTED_KINDS},
|
|
[DeletionReasons.PRIVACY_VIOLATION_OR_DOXXING]: {rule: 'privacy', handling: 'protected', kinds: 'any'},
|
|
[DeletionReasons.HARASSMENT_OR_BULLYING]: {rule: 'harassment', handling: 'protected', kinds: 'any'},
|
|
[DeletionReasons.PAYMENT_FRAUD]: {rule: 'payments', handling: 'standard', kinds: PAYMENT_KINDS},
|
|
[DeletionReasons.CHILD_SAFETY_VIOLATION]: {rule: 'child_safety', handling: 'restricted', kinds: RESTRICTED_KINDS},
|
|
[DeletionReasons.BILLING_DISPUTE_OR_ABUSE]: {rule: 'payments', handling: 'standard', kinds: PAYMENT_KINDS},
|
|
[DeletionReasons.UNSOLICITED_EXPLICIT_CONTENT]: {
|
|
rule: 'unwanted_sexual_content',
|
|
handling: 'protected',
|
|
kinds: 'any',
|
|
},
|
|
[DeletionReasons.GRAPHIC_VIOLENCE]: {rule: 'violent_content', handling: 'standard', kinds: 'any'},
|
|
[DeletionReasons.BAN_EVASION]: {
|
|
rule: 'ban_evasion',
|
|
handling: 'standard',
|
|
kinds: ['warning', 'suspension', 'closure'],
|
|
},
|
|
[DeletionReasons.TOKEN_OR_CREDENTIAL_SCAM]: {rule: 'fraud', handling: 'standard', kinds: 'any'},
|
|
[DeletionReasons.HATE_SPEECH_OR_EXTREMIST_CONTENT]: {rule: 'hate', handling: 'standard', kinds: 'any'},
|
|
[DeletionReasons.MALICIOUS_LINKS_OR_MALWARE]: {rule: 'malware', handling: 'standard', kinds: 'any'},
|
|
[DeletionReasons.IMPERSONATION_OR_FAKE_IDENTITY]: {rule: 'impersonation', handling: 'standard', kinds: 'any'},
|
|
[DeletionReasons.THREATS_OR_VIOLENT_SPEECH]: {rule: 'threats', handling: 'protected', kinds: 'any'},
|
|
[DeletionReasons.VIOLENT_EXTREMISM]: {rule: 'violent_extremism', handling: 'restricted', kinds: RESTRICTED_KINDS},
|
|
[DeletionReasons.SELF_HARM_PROMOTION]: {
|
|
rule: 'self_harm',
|
|
handling: 'standard',
|
|
kinds: ['warning', 'suspension', 'content_removal', 'profile_reset', 'community_removal'],
|
|
},
|
|
[DeletionReasons.SEXUAL_CONTENT_PLACEMENT]: {rule: 'adult_content', handling: 'standard', kinds: 'any'},
|
|
[DeletionReasons.ILLEGAL_GOODS_OR_ACTIVITY]: {rule: 'illegal_activity', handling: 'standard', kinds: 'any'},
|
|
[DeletionReasons.HARMFUL_DECEPTION]: {rule: 'harmful_deception', handling: 'standard', kinds: 'any'},
|
|
[DeletionReasons.REPORTING_ABUSE]: {
|
|
rule: 'report_abuse',
|
|
handling: 'standard',
|
|
kinds: ['warning', 'feature_limit', 'suspension'],
|
|
},
|
|
[DeletionReasons.UNDERAGE_ACCOUNT]: {rule: 'age_requirement', handling: 'standard', kinds: ['closure']},
|
|
[DeletionReasons.COPYRIGHT]: {
|
|
rule: 'copyright',
|
|
handling: 'standard',
|
|
kinds: ['warning', 'content_removal', 'profile_reset', 'community_removal'],
|
|
},
|
|
};
|
|
|
|
const ENFORCEMENT_SPAMMER_LIMIT_RULES: ReadonlySet<EnforcementRuleKey> = new Set([
|
|
'spam',
|
|
'automation',
|
|
'fraud',
|
|
'malware',
|
|
]);
|
|
|
|
const ENFORCEMENT_LIMIT_RULES: Readonly<Record<EnforcementLimit, ReadonlySet<EnforcementRuleKey>>> = {
|
|
direct_messages: ENFORCEMENT_SPAMMER_LIMIT_RULES,
|
|
reports: new Set(['report_abuse']),
|
|
purchases: new Set(['payments']),
|
|
};
|
|
|
|
const ACCOUNT_KINDS: ReadonlySet<EnforcementKind> = new Set(['suspension', 'closure']);
|
|
|
|
export function isAccountKind(kind: EnforcementKind): boolean {
|
|
return ACCOUNT_KINDS.has(kind);
|
|
}
|
|
|
|
export function isEnforcementReasonCode(code: number | null | undefined): code is EnforcementReasonCode {
|
|
return code !== null && code !== undefined && Object.hasOwn(ENFORCEMENT_REASONS, code);
|
|
}
|
|
|
|
export function enforcementReasonOf(code: number | null | undefined): EnforcementReason | null {
|
|
return isEnforcementReasonCode(code) ? ENFORCEMENT_REASONS[code] : null;
|
|
}
|
|
|
|
const ENFORCEMENT_LIMITS = Object.keys(ENFORCEMENT_LIMIT_RULES) as ReadonlyArray<EnforcementLimit>;
|
|
|
|
export function isEnforcementLimitAllowed(code: EnforcementReasonCode, limit: EnforcementLimit): boolean {
|
|
return ENFORCEMENT_LIMIT_RULES[limit].has(ENFORCEMENT_REASONS[code].rule);
|
|
}
|
|
|
|
export function isEnforcementKindAllowed(code: EnforcementReasonCode, kind: EnforcementKind): boolean {
|
|
const {kinds} = ENFORCEMENT_REASONS[code];
|
|
if (kinds !== 'any' && !kinds.includes(kind)) return false;
|
|
return kind !== 'feature_limit' || ENFORCEMENT_LIMITS.some((limit) => isEnforcementLimitAllowed(code, limit));
|
|
}
|