[READ ONLY MIRROR] Open Source TikTok alternative built on AT Protocol github.com/sprksocial/client
flutter atproto video dart
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774import 'package:flutter_test/flutter_test.dart';import 'package:poptart_lex/com/atproto/label/defs.dart';import 'package:spark/src/core/moderation/moderation.dart';
void main() { final now = DateTime.utc(2026, 8, 8, 12);
group('ModerationEngine lifecycle', () { test('ignores negated labels', () { final decision = _engine().evaluate( [_label(val: 'sexual', neg: true)], target: ModerationTarget.content, now: now, );
expect(decision.causes, isEmpty); });
test('ignores expired labels including the exact expiry instant', () { final decision = _engine().evaluate( [ _label(val: 'sexual', exp: now.subtract(const Duration(seconds: 1))), _label(val: 'sexual', exp: now), _label(val: 'sexual', exp: now.add(const Duration(seconds: 1))), ], target: ModerationTarget.content, now: now, );
expect(decision.causes, hasLength(1)); expect( decision.causes.single.label.exp, now.add(const Duration(seconds: 1)), ); });
test('ignores unknown label values', () { final decision = _engine().evaluate( [_label(val: 'not-defined')], target: ModerationTarget.content, now: now, );
expect(decision.causes, isEmpty); });
test('ignores unsupported custom self-labels', () { final engine = _engine( definitions: { 'did:plc:author': [_definition('custom')], }, );
final decision = engine.evaluate( [_label(src: 'did:plc:author', val: 'custom')], target: ModerationTarget.content, subjectDid: 'did:plc:author', now: now, );
expect(decision.causes, isEmpty); });
test('allows supported built-in self-labels', () { final decision = _engine().evaluate( [_label(src: 'did:plc:author', val: 'sexual')], target: ModerationTarget.content, subjectDid: 'did:plc:author', now: now, );
expect(decision.causes.single.definition.identifier, 'sexual'); });
test('ignores moderation-only built-in values when self-applied', () { final decision = _engine().evaluate( [_label(src: 'did:plc:author', val: 'dmca-violation')], target: ModerationTarget.content, subjectDid: 'did:plc:author', now: now, );
expect(decision.causes, isEmpty); });
test('uses the configured labeler policy and metadata for self-labels', () { final engine = _engine( definitions: { 'did:plc:moderator': [ _definition( 'nudity', blurs: 'media', locales: const [ LabelValueDefinitionStrings( lang: 'en', name: 'Labeler Nudity', description: 'Labeler-authored description.', ), ], ), ], }, labelPreferences: const [ ModerationLabelPreference( value: 'nudity', labelerDid: 'did:plc:moderator', setting: ModerationSetting.hide, ), ], selfLabelerDid: 'did:plc:moderator', );
final decision = engine.evaluate( [_label(src: 'did:plc:author', val: 'nudity')], target: ModerationTarget.content, subjectDid: 'did:plc:author', preferredLocales: const ['en'], now: now, );
expect(decision.causes.single.setting, ModerationSetting.hide); expect(decision.causes.single.definition.definedBy, 'did:plc:moderator'); expect(decision.causes.single.strings?.name, 'Labeler Nudity'); expect(decision.causes.single.sourceDid, 'did:plc:author'); expect(decision.forContext(ModerationContext.contentList).filter, isTrue); });
test( 'keeps same-valued labels from different sources as distinct causes', () { final engine = _engine( definitions: { 'did:plc:alpha': [_definition('topic')], 'did:plc:beta': [_definition('topic')], }, );
final decision = engine.evaluate( [ _label(src: 'did:plc:alpha', val: 'topic'), _label(src: 'did:plc:beta', val: 'topic'), ], target: ModerationTarget.content, now: now, );
expect(decision.causes.map((cause) => cause.sourceDid), { 'did:plc:alpha', 'did:plc:beta', }); }, ); });
group('imperative labels', () { for (final value in ['!hide', '!takedown']) { test('$value cannot be ignored and is non-overridable', () { final engine = _engine( labelPreferences: [ ModerationLabelPreference( value: value, labelerDid: 'did:plc:labeler', setting: ModerationSetting.ignore, ), ], ); final decision = engine.evaluate( [_label(val: value)], target: ModerationTarget.content, now: now, );
expect(decision.causes.single.setting, ModerationSetting.hide); expect( decision.forContext(ModerationContext.contentList).filter, isTrue, ); expect(decision.forContext(ModerationContext.contentView).blur, isTrue); expect( decision.forContext(ModerationContext.contentView).noOverride, isTrue, ); }); }
test('!no-promote excludes promotion without changing ordinary UI', () { final decision = _engine().evaluate( [_label(val: '!no-promote')], target: ModerationTarget.content, now: now, );
expect(decision.excludeFromPromotion, isTrue); for (final context in ModerationContext.values) { final ui = decision.forContext(context); expect(ui.filter, isFalse, reason: context.name); expect(ui.blur, isFalse, reason: context.name); expect(ui.alert, isFalse, reason: context.name); expect(ui.inform, isFalse, reason: context.name); } });
test('!no-unauthenticated is ignored for signed-in viewers', () { final decision = _engine(authenticated: true).evaluate( [_label(val: '!no-unauthenticated')], target: ModerationTarget.content, now: now, );
expect(decision.causes, isEmpty); });
test('!no-unauthenticated hides from signed-out viewers', () { final decision = _engine(authenticated: false).evaluate( [_label(val: '!no-unauthenticated')], target: ModerationTarget.content, now: now, );
expect(decision.hideFromUnauthenticated, isTrue); expect(decision.forContext(ModerationContext.contentList).filter, isTrue); expect(decision.forContext(ModerationContext.contentView).blur, isTrue); expect( decision.forContext(ModerationContext.contentView).noOverride, isTrue, ); }); });
group('Spark warn policy', () { test('non-adult media hide still conceals a direct content view', () { final engine = _engine( definitions: { 'did:plc:labeler': [ _definition('media-hide', blurs: 'media', defaultSetting: 'hide'), ], }, ); final decision = engine.evaluate( [_label(val: 'media-hide')], target: ModerationTarget.content, now: now, );
expect(decision.forContext(ModerationContext.contentList).filter, isTrue); expect(decision.forContext(ModerationContext.contentView).blur, isTrue); expect(decision.forContext(ModerationContext.contentMedia).blur, isTrue); });
test('warn adds content blur while preserving an alert', () { final engine = _engine( definitions: { 'did:plc:labeler': [ _definition('alert-only', severity: 'alert', blurs: 'none'), ], }, ); final decision = engine.evaluate( [_label(val: 'alert-only')], target: ModerationTarget.content, now: now, );
final ui = decision.forContext(ModerationContext.contentView); expect(ui.blur, isTrue); expect(ui.alert, isTrue); expect(ui.inform, isFalse); expect( decision.causes.single.definition.severity, ModerationSeverity.alert, ); });
test('warn keeps information badge-only without explicit blur', () { final engine = _engine( definitions: { 'did:plc:labeler': [ _definition('info-only', severity: 'inform', blurs: 'none'), ], }, ); final decision = engine.evaluate( [_label(val: 'info-only')], target: ModerationTarget.content, now: now, );
final ui = decision.forContext(ModerationContext.contentView); expect(ui.blur, isFalse); expect(ui.inform, isTrue); expect(ui.alert, isFalse); expect(decision.forContext(ModerationContext.contentList).blur, isFalse); expect(decision.forContext(ModerationContext.contentMedia).blur, isFalse); expect( decision.causes.single.definition.severity, ModerationSeverity.inform, ); });
test('inform still applies an explicit media blur', () { final engine = _engine( definitions: { 'did:plc:labeler': [ _definition('info-media', severity: 'inform', blurs: 'media'), ], }, ); final decision = engine.evaluate( [_label(val: 'info-media')], target: ModerationTarget.content, now: now, );
expect(decision.forContext(ModerationContext.contentView).blur, isTrue); expect(decision.forContext(ModerationContext.contentMedia).blur, isTrue); });
test('non-inform warn blurs every content context', () { final engine = _engine( definitions: { 'did:plc:labeler': [_definition('topic')], }, ); final decision = engine.evaluate( [_label(val: 'topic')], target: ModerationTarget.content, now: now, );
for (final context in [ ModerationContext.contentList, ModerationContext.contentView, ModerationContext.contentMedia, ]) { expect(decision.forContext(context).blur, isTrue, reason: context.name); } expect(decision.forContext(ModerationContext.profileView).blur, isFalse); });
test('non-inform warn blurs every profile context', () { final engine = _engine( definitions: { 'did:plc:labeler': [_definition('topic')], }, ); final decision = engine.evaluate( [_label(val: 'topic')], target: ModerationTarget.profile, now: now, );
for (final context in [ ModerationContext.profileList, ModerationContext.profileView, ModerationContext.avatar, ModerationContext.banner, ModerationContext.displayName, ]) { expect(decision.forContext(context).blur, isTrue, reason: context.name); } expect(decision.forContext(ModerationContext.contentView).blur, isFalse); });
test('non-inform warn on an account blurs every supported context', () { final engine = _engine( definitions: { 'did:plc:labeler': [_definition('topic')], }, ); final decision = engine.evaluate( [_label(val: 'topic')], target: ModerationTarget.account, now: now, );
for (final context in ModerationContext.values) { expect(decision.forContext(context).blur, isTrue, reason: context.name); } }); });
group('decisions and contexts', () { test('partitions profile-record labels from account labels', () { final decision = _engine().evaluateProfileLabels( [ _label( val: 'doxxing', uri: 'at://did:plc:subject/app.bsky.actor.profile/self', ), _label(val: 'doxxing', uri: 'did:plc:subject'), ], subjectDid: 'did:plc:subject', now: now, );
expect(decision.causes, hasLength(2)); expect( decision.causes .singleWhere( (cause) => cause.label.uri.endsWith('/app.bsky.actor.profile/self'), ) .target, ModerationTarget.profile, ); expect( decision.causes .singleWhere((cause) => cause.label.uri == 'did:plc:subject') .target, ModerationTarget.account, ); });
test('keeps Spark profile-record labels out of account content', () { final decision = _engine().evaluateProfileLabels( [ _label( val: 'doxxing', uri: 'at://did:plc:subject/so.sprk.actor.profile/self', ), ], subjectDid: 'did:plc:subject', now: now, );
expect(decision.causes.single.target, ModerationTarget.profile); expect(decision.forContext(ModerationContext.profileView).blur, isTrue); expect(decision.forContext(ModerationContext.contentList).blur, isFalse); });
test('keeps profile-record imperatives out of authored content', () { for (final namespace in [ 'app.bsky.actor.profile', 'so.sprk.actor.profile', ]) { for (final value in ['!hide', '!takedown', '!warn']) { final decision = _engine().evaluateProfileLabels( [_label(val: value, uri: 'at://did:plc:subject/$namespace/self')], subjectDid: 'did:plc:subject', now: now, );
expect(decision.causes.single.target, ModerationTarget.profile); expect( decision.forContext(ModerationContext.profileView).blur, isTrue, reason: '$namespace $value profile', ); for (final context in [ ModerationContext.contentList, ModerationContext.contentView, ModerationContext.contentMedia, ]) { final ui = decision.forContext(context); expect(ui.filter, isFalse, reason: '$namespace $value $context'); expect(ui.blur, isFalse, reason: '$namespace $value $context'); expect(ui.alert, isFalse, reason: '$namespace $value $context'); expect(ui.inform, isFalse, reason: '$namespace $value $context'); } } } });
test('classifies profile-record imperatives exactly once', () { final decision = _engine(authenticated: false).evaluateProfileLabels( [ _label( val: '!no-unauthenticated', uri: 'at://did:plc:subject/app.bsky.actor.profile/self', ), ], subjectDid: 'did:plc:subject', now: now, );
expect(decision.causes, hasLength(1)); expect(decision.causes.single.target, ModerationTarget.account); expect(decision.hideFromUnauthenticated, isTrue); expect(decision.forContext(ModerationContext.contentView).blur, isTrue); });
test( 'merges account, profile, and content decisions without losing targets', () { final engine = _engine( definitions: { 'did:plc:labeler': [_definition('topic')], }, ); final merged = ModerationDecision.merge([ engine.evaluate( [_label(val: 'topic')], target: ModerationTarget.account, now: now, ), engine.evaluate( [_label(val: 'topic')], target: ModerationTarget.content, now: now, ), ]);
expect(merged.causes.map((cause) => cause.target), [ ModerationTarget.account, ModerationTarget.content, ]); expect( merged.forContext(ModerationContext.contentView).blurs, hasLength(2), ); }, );
test('hide filters matching list contexts only', () { final engine = _engine( definitions: { 'did:plc:labeler': [_definition('topic', defaultSetting: 'hide')], }, );
final content = engine.evaluate( [_label(val: 'topic')], target: ModerationTarget.content, now: now, ); expect(content.forContext(ModerationContext.contentList).filter, isTrue); expect(content.forContext(ModerationContext.profileList).filter, isFalse);
final profile = engine.evaluate( [_label(val: 'topic')], target: ModerationTarget.profile, now: now, ); expect(profile.forContext(ModerationContext.profileList).filter, isFalse); expect(profile.forContext(ModerationContext.contentList).filter, isFalse); });
test('does not filter the current user or lock away an override', () { final decision = _engine(currentUserDid: 'did:plc:me').evaluate( [_label(val: '!hide')], target: ModerationTarget.account, subjectDid: 'did:plc:me', now: now, );
expect(decision.isSubjectCurrentUser, isTrue); expect( decision.forContext(ModerationContext.profileList).filter, isFalse, ); expect(decision.forContext(ModerationContext.profileView).blur, isTrue); expect( decision.forContext(ModerationContext.profileView).noOverride, isFalse, ); });
test('adult-disabled content is forced hidden and non-overridable', () { final decision = _engine( adultContentEnabled: false, labelPreferences: const [ ModerationLabelPreference( value: 'sexual', setting: ModerationSetting.ignore, ), ], ).evaluate( [_label(val: 'sexual')], target: ModerationTarget.content, now: now, );
expect(decision.causes.single.setting, ModerationSetting.hide); expect(decision.causes.single.noOverride, isTrue); expect(decision.forContext(ModerationContext.contentList).filter, isTrue); expect(decision.forContext(ModerationContext.contentView).blur, isTrue); expect( decision.forContext(ModerationContext.contentView).noOverride, isTrue, ); expect(decision.forContext(ModerationContext.contentMedia).blur, isTrue); expect( decision.forContext(ModerationContext.contentMedia).noOverride, isTrue, ); });
test('source-specific ignore suppresses only that source', () { final engine = _engine( definitions: { 'did:plc:alpha': [_definition('topic')], 'did:plc:beta': [_definition('topic')], }, labelPreferences: const [ ModerationLabelPreference( value: 'topic', labelerDid: 'did:plc:alpha', setting: ModerationSetting.ignore, ), ModerationLabelPreference( value: 'topic', labelerDid: 'did:plc:beta', setting: ModerationSetting.warn, ), ], ); final decision = engine.evaluate( [ _label(src: 'did:plc:alpha', val: 'topic'), _label(src: 'did:plc:beta', val: 'topic'), ], target: ModerationTarget.content, now: now, );
expect(decision.causes.single.sourceDid, 'did:plc:beta'); });
test('ignores labels from non-configured sources', () { final engine = _engine( configuredLabelerDids: const {'did:plc:configured'}, ); final decision = engine.evaluate( [ _label(src: 'did:plc:removed', val: '!hide'), _label(src: 'did:plc:removed', val: 'porn'), _label(src: 'did:plc:configured', val: '!warn'), ], target: ModerationTarget.content, now: now, );
expect(decision.causes, hasLength(1)); expect(decision.causes.single.sourceDid, 'did:plc:configured'); expect(decision.causes.single.definition.identifier, '!warn'); });
test('keeps supported self labels from non-configured authors', () { final decision = _engine(configuredLabelerDids: const {}).evaluate( [_label(src: 'did:plc:author', val: 'sexual')], target: ModerationTarget.content, subjectDid: 'did:plc:author', now: now, );
expect(decision.causes.single.sourceDid, 'did:plc:author'); expect(decision.causes.single.definition.identifier, 'sexual'); });
test('selects labeler-authored cause strings for the viewer locale', () { final engine = _engine( definitions: { 'did:plc:labeler': [ _definition( 'topic', locales: const [ LabelValueDefinitionStrings( lang: 'en', name: 'English', description: 'Description', ), LabelValueDefinitionStrings( lang: 'es', name: 'Español', description: 'Descripción', ), ], ), ], }, );
final decision = engine.evaluate( [_label(val: 'topic')], target: ModerationTarget.content, preferredLocales: const ['es-MX'], now: now, );
expect(decision.causes.single.strings?.name, 'Español'); });
test('orders non-overridable, hide, blur, and notice causes', () { final engine = _engine( definitions: { 'did:plc:labeler': [ _definition('hidden', defaultSetting: 'hide'), _definition('media', blurs: 'media'), _definition('notice', severity: 'alert'), ], }, ); final decision = engine.evaluate( [ _label(val: 'notice'), _label(val: 'media'), _label(val: 'hidden'), _label(val: '!hide'), ], target: ModerationTarget.content, now: now, );
expect(decision.causes.map((cause) => cause.definition.identifier), [ '!hide', 'hidden', 'media', 'notice', ]); expect(decision.causes.map((cause) => cause.priority), [1, 2, 5, 8]); }); });}
ModerationEngine _engine({ Map<String, Iterable<LabelValueDefinition>> definitions = const {}, List<ModerationLabelPreference> labelPreferences = const [], bool adultContentEnabled = true, bool authenticated = true, String? currentUserDid, String? selfLabelerDid, Set<String> configuredLabelerDids = const {'did:plc:labeler'},}) { return ModerationEngine( definitions: ModerationLabelDefinitions.fromLabelers({ for (final did in configuredLabelerDids) did: const [], ...definitions, }), preferences: ModerationPreferences( labels: labelPreferences, adultContentEnabled: adultContentEnabled, authenticated: authenticated, ), currentUserDid: currentUserDid, selfLabelerDid: selfLabelerDid, );}
LabelValueDefinition _definition( String identifier, { String severity = 'none', String blurs = 'none', String? defaultSetting, bool? adultOnly, List<LabelValueDefinitionStrings> locales = const [],}) { return LabelValueDefinition( identifier: identifier, severity: LabelValueDefinitionSeverity.valueOf(severity)!, blurs: LabelValueDefinitionBlurs.valueOf(blurs)!, defaultSetting: LabelValueDefinitionDefaultSetting.valueOf(defaultSetting), adultOnly: adultOnly, locales: locales, );}
Label _label({ String src = 'did:plc:labeler', required String val, String uri = 'at://did:plc:subject/app.bsky.feed.post/1', bool? neg, DateTime? exp,}) { return Label( src: src, uri: uri, val: val, neg: neg, cts: DateTime.utc(2026), exp: exp, );}