A collection of Osprey rules for ATProto

Compare changes

Choose any two refs to compare.

+4
config/labels.yaml
··· 55 55 valid_for: [UserId] 56 56 connotation: neutral 57 57 description: Account that is relatively new found to making slur posts. 58 + coordinated-abuse: 59 + valid_for: [UserId] 60 + connotation: neutral 61 + description: Account which is engaging in coordinated abuse.
+99
lists/nsfw_tags.yaml
··· 1 + - onlyfans 2 + - fansly 3 + - blowjob 4 + - dick 5 + - cock 6 + - nsfw 7 + - pussy 8 + - pov 9 + - thick 10 + - ass 11 + - boobs 12 + - 18+ 13 + - nsfwsky 14 + - nsfwtwt 15 + - skyhub 16 + - lewd 17 + - findom 18 + - femdom 19 + - findomme 20 + - spoiled 21 + - leather 22 + - nude 23 + - sexy 24 + - bbw 25 + - simp 26 + - sub 27 + - content 28 + - realnsfw 29 + - gooning 30 + - gooner 31 + - anal 32 + - hugedildo 33 + - dildo 34 + - tits 35 + - nsfwbsky 36 + - egirl 37 + - sizequeen 38 + - cammodel 39 + - brat 40 + - gothurbate 41 + - altgirl 42 + - dirtytalk 43 + - switch 44 + - fetish 45 + - kinky 46 + - kink 47 + - kinks 48 + - cum 49 + - freeonlyfans 50 + - freefansly 51 + - freeslut 52 + - horny 53 + - submissive 54 + - pawg 55 + - snowbunny 56 + - sub 57 + - chudai 58 + - porn 59 + - redhead 60 + - teen 61 + - erotic 62 + - goonsky 63 + - private 64 + - suck 65 + - of 66 + - tease 67 + - nolimit 68 + - holes 69 + - pyt 70 + - tight 71 + - petite 72 + - nolimits 73 + - muscleworship 74 + - daddy 75 + - mommy 76 + - hunk 77 + - gayporn 78 + - verbal 79 + - hung 80 + - bwc 81 + - latina 82 + - swallow 83 + - ebony 84 + - backshot 85 + - backshots 86 + - loli 87 + - wet 88 + - breedable 89 + - breedkink 90 + - breed 91 + - hairy 92 + - hairywoman 93 + - hairyman 94 + - allnatural 95 + - camgirl 96 + - bdsm 97 + - bondage 98 + - abdl 99 + - diaper
+25
rules/identity/elon_handle.sml
··· 1 + Import( 2 + rules=[ 3 + 'models/base.sml', 4 + 'models/identity.sml', 5 + ], 6 + ) 7 + 8 + _Gate = RegexMatch(target=IdentityEventHandle, pattern=r'^elon-?(musk|reeves).+\.bsky\.social$') 9 + 10 + ElonHandleRule = Rule( 11 + when_all=[_Gate], 12 + description='Likely Elon spam handle', 13 + ) 14 + 15 + WhenRules( 16 + rules_any=[ElonHandleRule], 17 + then=[ 18 + AtprotoLabel( 19 + entity=UserId, 20 + label='elon-handle', 21 + comment='Lihkely Elon spam handle', 22 + expiration_in_hours=None, 23 + ), 24 + ], 25 + )
+1
rules/identity/index.sml
··· 6 6 ) 7 7 8 8 Require(rule='rules/identity/update_handle.sml') 9 + Require(rule='rules/identity/elon_handle.sml')
+1 -1
rules/identity/update_handle.sml
··· 12 12 ) 13 13 14 14 HandleChangedRule = Rule( 15 - when_all=[AccountAgeSecondsUnwrapped >= 300], 15 + when_all=[AccountAgeSecondsUnwrapped >= 3600], 16 16 description='User has updated their handle recently.', 17 17 ) 18 18
+55
rules/record/post/bsky_store.sml
··· 1 + Import( 2 + rules=[ 3 + 'models/base.sml', 4 + 'models/record/base.sml', 5 + 'models/record/post.sml', 6 + ], 7 + ) 8 + 9 + _AgeGate = AccountAgeSecondsUnwrapped <= Day or PostsCount <= 5 10 + 11 + _BskyStoreDisplayName = RegexMatch(target=DisplayName, pattern=r'(?i)^bl?sky ?sto?re$') 12 + 13 + _DisplayNameGate = _BskyStoreDisplayName == True and _AgeGate 14 + 15 + _HasDomain = SimpleListContains( 16 + cache_name='bsky_store_post_domains', 17 + list=['tinyurl.com'], 18 + phrases=PostAllDomains, 19 + ) != None 20 + 21 + _HasWord = SimpleListContains( 22 + cache_name='bsky_store_post_phrases', 23 + list=[ 24 + 'sold', 25 + 'order', 26 + 't-shirt', 27 + 'tshirt', 28 + 'store', 29 + 'sell', 30 + 'bought', 31 + 'buy', 32 + ], 33 + phrases=PostTextTokens, 34 + ) != None 35 + 36 + _HasFuckIce = RegexMatch(target=PostText, pattern=r'(?i)fuck-?ice.+off') 37 + 38 + _PostGate = ((_HasDomain and _HasWord) or _HasFuckIce) and _AgeGate 39 + 40 + BskyStorePostRule = Rule( 41 + when_all=[_DisplayNameGate or _PostGate], 42 + description='Likely Bsky store account', 43 + ) 44 + 45 + WhenRules( 46 + rules_any=[BskyStorePostRule], 47 + then=[ 48 + AtprotoLabel( 49 + entity=UserId, 50 + label='shopping-spam', 51 + comment='Bluesky store shopping spam', 52 + expiration_in_hours=None, 53 + ), 54 + ], 55 + )
+2
rules/record/post/index.sml
··· 13 13 Require(rule='rules/record/post/new_account_slurs.sml') 14 14 Require(rule='rules/record/post/negative_posting.sml') 15 15 Require(rule='rules/record/post/toxic_posting.sml') 16 + Require(rule='rules/record/post/bsky_store.sml') 17 + Require(rule='rules/record/post/nsfw_tags.sml') 16 18 17 19 # Replies Only 18 20 Require(
+32
rules/record/post/nsfw_tags.sml
··· 1 + Import( 2 + rules=[ 3 + 'models/base.sml', 4 + 'models/record/base.sml', 5 + 'models/record/post.sml', 6 + ], 7 + ) 8 + 9 + _FoundTag = ListContains( 10 + list='nsfw_tags', 11 + phrases=FacetTagList, 12 + ) 13 + 14 + _FoundTagUnwrapped: str = ResolveOptional(optional_value=_FoundTag) 15 + 16 + NsfwTagsRule = Rule( 17 + when_all=[ 18 + _FoundTag != None, 19 + ], 20 + description='Post contains NSFW hashtags', 21 + ) 22 + 23 + WhenRules( 24 + rules_any=[NsfwTagsRule], 25 + then=[ 26 + AtprotoLabel( 27 + entity=AtUri, 28 + label='likely-nsfw', 29 + comment=f'Post contains one or many NSFW hashtags: {_FoundTagUnwrapped}', 30 + ), 31 + ], 32 + )
-21
rules/record/post/toxic_posting.sml
··· 20 20 when_all=[_Gate], 21 21 ) 22 22 23 - ToxicPostRule = Rule( 24 - when_all=[ 25 - _Gate, 26 - PostIsReply, 27 - ], 28 - description='This post is toxic', 29 - ) 30 - 31 23 ToxicPostingRule = Rule( 32 24 when_all=[ToxicPostCount >= 10 or _ToxicPostCountHour >= 4], 33 25 description='User has made three or more toxic posts in a four hour window', 34 - ) 35 - 36 - WhenRules( 37 - rules_any=[ToxicPostRule], 38 - then=[ 39 - AtprotoLabel( 40 - entity=AtUri, 41 - label='toxic-post', 42 - comment='This post is toxic', 43 - expiration_in_hours=None, 44 - cid=Cid, 45 - ), 46 - ], 47 26 ) 48 27 49 28 WhenRules(
+28
rules/record/profile/bsky_store.sml
··· 1 + Import( 2 + rules=[ 3 + 'models/base.sml', 4 + 'models/record/base.sml', 5 + 'models/record/profile.sml', 6 + ], 7 + ) 8 + 9 + _BskyStoreDisplayName = RegexMatch(target=ProfileDisplayName, pattern=r'(?i)^bl?sky ?sto?re$') 10 + 11 + _Gate = _BskyStoreDisplayName == True and (AccountAgeSecondsUnwrapped <= Day or PostsCount <= 5) 12 + 13 + BskyStoreProfileRule = Rule( 14 + when_all=[_Gate], 15 + description='Likely Bsky store account', 16 + ) 17 + 18 + WhenRules( 19 + rules_any=[BskyStoreProfileRule], 20 + then=[ 21 + AtprotoLabel( 22 + entity=UserId, 23 + label='shopping-spam', 24 + comment='Bluesky store shopping spam', 25 + expiration_in_hours=None, 26 + ), 27 + ], 28 + )
+3
rules/record/profile/index.sml
··· 9 9 Require( 10 10 rule='rules/record/profile/hailey_profile.sml', 11 11 ) 12 + Require( 13 + rule='rules/record/profile/bsky_store.sml', 14 + )