simplified + added mutators
This commit is contained in:
parent
745fda9bbe
commit
bdc32ac5fa
58
src/feed.py
58
src/feed.py
@ -16,7 +16,7 @@ from sqlalchemy import select, insert, delete, and_
|
||||
from sqlalchemy.exc import NoResultFound
|
||||
from textwrap import shorten
|
||||
|
||||
import mutators
|
||||
from mutators import mutator_map
|
||||
from errors import IllegalFeed
|
||||
from db import DatabaseManager, RssSourceModel, FeedChannelModel
|
||||
from utils import get_rss_data, get_unparsed_feed
|
||||
@ -69,55 +69,21 @@ class Article:
|
||||
)
|
||||
|
||||
def mutate(self, mutator: dict):
|
||||
"""
|
||||
Apply a mutation to a certain text attribute of
|
||||
this Article instance.
|
||||
"""
|
||||
|
||||
log.debug("Applying mutator '%s'", mutator["name"])
|
||||
|
||||
match mutator["value"]:
|
||||
mutator_value = mutator["value"]
|
||||
|
||||
case "UWU_TITLE":
|
||||
self.title = mutators.uwu(self.title)
|
||||
|
||||
case "UWU_DESC":
|
||||
self.description = mutators.uwu(self.description)
|
||||
|
||||
case "GIB_TITLE":
|
||||
self.title = mutators.gibberish(self.title)
|
||||
|
||||
case "GIB_DESC":
|
||||
self.description = mutators.gibberish(self.description)
|
||||
|
||||
case "L3_TITLE":
|
||||
self.title = mutators.leet(self.title)
|
||||
|
||||
case "L3_DESC":
|
||||
self.description = mutators.leet(self.description)
|
||||
|
||||
case "REV_TITLE":
|
||||
self.title = mutators.reverse(self.title)
|
||||
|
||||
case "REV_DESC":
|
||||
self.description = mutators.reverse(self.description)
|
||||
|
||||
case "RND_TITLE":
|
||||
self.title = mutators.shuffle(self.title)
|
||||
|
||||
case "RND_DESC":
|
||||
self.description = mutators.shuffle(self.description)
|
||||
|
||||
case "PGL_TITLE":
|
||||
self.title = mutators.pig_latin(self.title)
|
||||
|
||||
case "PGL_DESC":
|
||||
self.description = mutators.pig_latin(self.description)
|
||||
|
||||
case "RCS_TITLE":
|
||||
self.title = mutators.random_case(self.title)
|
||||
|
||||
case "RCS_DESC":
|
||||
self.description = mutators.random_case(self.description)
|
||||
|
||||
case _:
|
||||
log.warn("Unknown mutator value '%s', skipping", mutator["value"])
|
||||
if mutator_value in mutator_map:
|
||||
attr, func = mutator_map[mutator_value]
|
||||
setattr(self, attr, func(getattr(self, attr)))
|
||||
log.debug("mutated %s, to: %s", attr, getattr(self, attr))
|
||||
else:
|
||||
log.warn("Unknown mutator value '%s', skipping", mutator["value"])
|
||||
|
||||
async def get_thumbnail_url(self, session: aiohttp.ClientSession) -> str | None:
|
||||
"""Returns the thumbnail URL for an article.
|
||||
|
316
src/mutators.py
316
src/mutators.py
@ -2,50 +2,334 @@ import random
|
||||
|
||||
import uwuify
|
||||
|
||||
# For l33t sp34k translation
|
||||
leet_map = {'a': '4', 'e': '3', 'i': '1', 'o': '0', 's': '5', 't': '7'}
|
||||
|
||||
# For upside-down translation
|
||||
upside_down_dict = str.maketrans(
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890,.!?\"'",
|
||||
"ɐqɔpǝɟƃɥᴉɾʞlɯuodbɹsʇnʌʍxʎz∀BↃᗡƎℲ⅁HIſ⋊⅃WNOԀΌᴚS⊥∩ΛMX⅄Z⇂2Ɛᔭ59Ɫ860˙‘¡¿,'"
|
||||
)
|
||||
|
||||
# For gothic script
|
||||
gothic_dict = {
|
||||
'a': '𝔞', 'b': '𝔟', 'c': '𝔠', 'd': '𝔡', 'e': '𝔢', 'f': '𝔣', 'g': '𝔤', 'h': '𝔥', 'i': '𝔦', 'j': '𝔧',
|
||||
'k': '𝔨', 'l': '𝔩', 'm': '𝔪', 'n': '𝔫', 'o': '𝔬', 'p': '𝔭', 'q': '𝔮', 'r': '𝔯', 's': '𝔰', 't': '𝔱',
|
||||
'u': '𝔲', 'v': '𝔳', 'w': '𝔴', 'x': '𝔵', 'y': '𝔶', 'z': '𝔷', 'A': '𝔄', 'B': '𝔅', 'C': 'ℭ', 'D': '𝔇',
|
||||
'E': '𝔈', 'F': '𝔉', 'G': '𝔊', 'H': 'ℌ', 'I': 'ℑ', 'J': '𝔍', 'K': '𝔎', 'L': '𝔏', 'M': '𝔐', 'N': '𝔑',
|
||||
'O': '𝔒', 'P': '𝔓', 'Q': '𝔔', 'R': 'ℜ', 'S': '𝔖', 'T': '𝔗', 'U': '𝔘', 'V': '𝔙', 'W': '𝔚', 'X': '𝔛',
|
||||
'Y': '𝔜', 'Z': 'ℨ'
|
||||
}
|
||||
|
||||
# For emoji substitution
|
||||
emoji_dict = {
|
||||
'a': '🅰️', 'b': '🅱️', 'c': '🌜', 'd': '🌛', 'e': '📧', 'f': '🎏', 'g': '🌀', 'h': '♓', 'i': 'ℹ️',
|
||||
'j': '🎷', 'k': '🎋', 'l': '👢', 'm': 'Ⓜ️', 'n': '♑', 'o': '⚽', 'p': '🅿️', 'q': '🍳', 'r': '🌱',
|
||||
's': '💲', 't': '🌴', 'u': '⛎', 'v': '♈', 'w': '🔱', 'x': '❎', 'y': '🍸', 'z': 'Ⓩ'
|
||||
}
|
||||
|
||||
# For Zalgo translation
|
||||
zalgo_chars = [chr(random.randint(768, 879)) for _ in range(3)]
|
||||
|
||||
# For morse code translation
|
||||
morse_code_dict = {
|
||||
'A': '.-', 'B': '-...', 'C': '-.-.', 'D': '-..', 'E': '.', 'F': '..-.', 'G': '--.', 'H': '....',
|
||||
'I': '..', 'J': '.---', 'K': '-.-', 'L': '.-..', 'M': '--', 'N': '-.', 'O': '---', 'P': '.--.',
|
||||
'Q': '--.-', 'R': '.-.', 'S': '...', 'T': '-', 'U': '..-', 'V': '...-', 'W': '.--', 'X': '-..-',
|
||||
'Y': '-.--', 'Z': '--..', '1': '.----', '2': '..---', '3': '...--', '4': '....-', '5': '.....',
|
||||
'6': '-....', '7': '--...', '8': '---..', '9': '----.', '0': '-----', ',': '--..--', '.': '.-.-.-',
|
||||
'?': '..--..', '/': '-..-.', '-': '-....-', '(': '-.--.', ')': '-.--.-', ' ': '/'
|
||||
}
|
||||
|
||||
def uwu(text: str) -> str:
|
||||
"""
|
||||
Returns an 'uwuified' version of the given string.
|
||||
"""
|
||||
|
||||
return uwuify.uwu(text)
|
||||
|
||||
def gibberish(text: str) -> str:
|
||||
"""
|
||||
Returns a given string, but each character is randomy re-ordered.
|
||||
"""
|
||||
|
||||
return " ".join(["".join(
|
||||
random.sample(word, len(word)))
|
||||
for word in text.split()
|
||||
])
|
||||
|
||||
def leet(text: str) -> str:
|
||||
"""
|
||||
Translates a given string into 'l33t sp34k' and returns it.
|
||||
"""
|
||||
|
||||
return "".join([
|
||||
leet_map.get(char.lower(), char)
|
||||
for char in text
|
||||
for char in text.upper()
|
||||
])
|
||||
|
||||
def reverse(text: str) -> str:
|
||||
"""
|
||||
Returns the passed string in reverse.
|
||||
"""
|
||||
|
||||
return text[::-1]
|
||||
|
||||
def shuffle(text: str) -> str:
|
||||
"""
|
||||
Returns a given string, where each word is randomly shuffled.
|
||||
"""
|
||||
|
||||
words = text.split()
|
||||
random.shuffle(words)
|
||||
return " ".join(words)
|
||||
|
||||
def _pig_latin_word(word: str) -> str:
|
||||
first_vowel = 0
|
||||
for char in word:
|
||||
if char in "aeiou":
|
||||
break
|
||||
|
||||
first_vowel += 1
|
||||
|
||||
if first_vowel == 0:
|
||||
return word + "way"
|
||||
|
||||
else:
|
||||
return word[first_vowel:] + word[:first_vowel] + "ay"
|
||||
|
||||
def pig_latin(text: str) -> str:
|
||||
"""
|
||||
Takes a given string, translates it to 'pig latin' and returns it.
|
||||
"""
|
||||
|
||||
def _pig_latin_word(word: str) -> str:
|
||||
first_vowel = 0
|
||||
for char in word:
|
||||
if char in "aeiou":
|
||||
break
|
||||
|
||||
first_vowel += 1
|
||||
|
||||
if first_vowel == 0:
|
||||
return word + "way"
|
||||
|
||||
else:
|
||||
return word[first_vowel:] + word[:first_vowel] + "ay"
|
||||
|
||||
return " ".join([_pig_latin_word(word) for word in text.split()])
|
||||
|
||||
def random_case(text: str) -> str:
|
||||
"""
|
||||
Randomly converts each character of a given string to upper
|
||||
or lower case, and returns the result.
|
||||
"""
|
||||
|
||||
return "".join([
|
||||
char.upper() if random.random() > 0.5 else char.lower()
|
||||
for char in text
|
||||
])
|
||||
])
|
||||
|
||||
def upside_down_text(text: str) -> str:
|
||||
"""
|
||||
Returns an upside-down translation of the given string.
|
||||
"""
|
||||
|
||||
return text.translate(upside_down_dict)[::-1]
|
||||
|
||||
def gothic_script(text: str) -> str:
|
||||
"""
|
||||
Returns a 'gothic script' version of the given string.
|
||||
"""
|
||||
|
||||
return ''.join(gothic_dict.get(c, c) for c in text)
|
||||
|
||||
def emoji_substitution(text: str) -> str:
|
||||
"""
|
||||
Uses an emoji substitution sipher on the given string,
|
||||
and returns the result.
|
||||
"""
|
||||
|
||||
return ''.join(emoji_dict.get(c.lower(), c) for c in text)
|
||||
|
||||
def small_caps(text: str) -> str:
|
||||
"""
|
||||
Translates a given string to it's small caps ascii counterpart,
|
||||
and returns the result.
|
||||
"""
|
||||
|
||||
def _to_small_caps(c: str) -> str:
|
||||
if "a" <= c <= "z":
|
||||
return chr(ord(c) + 0x1D00 - ord("a"))
|
||||
elif "A" <= c <= "Z":
|
||||
return chr(ord(c) + 0x1D00 - ord("A"))
|
||||
else:
|
||||
return c
|
||||
|
||||
return ''.join(_to_small_caps(c) for c in text)
|
||||
|
||||
def zalgo(text: str) -> str:
|
||||
return "".join(
|
||||
c + "".join(random.choices(
|
||||
zalgo_chars, k=random.randint(1, 3)
|
||||
)) for c in text
|
||||
)
|
||||
|
||||
def morse_code(text: str) -> str:
|
||||
return " ".join(morse_code_dict.get(c.upper(), c) for c in text)
|
||||
|
||||
def to_binary(text: str) -> str:
|
||||
return ' '.join(format(ord(c), '08b') for c in text)
|
||||
|
||||
def to_hexadecimal(text: str) -> str:
|
||||
return ' '.join(format(ord(c), '02x') for c in text)
|
||||
|
||||
def remove_vowels(text: str) -> str:
|
||||
return ''.join(c for c in text if c.lower() not in 'aeiou')
|
||||
|
||||
def double_characters(text: str) -> str:
|
||||
return ''.join(c*2 for c in text)
|
||||
|
||||
def randomly_inserted_emoji(text: str) -> str:
|
||||
emojis = ['😀', '😂', '😍', '😎', '😊', '😜']
|
||||
return ' '.join(word + random.choice(emojis) for word in text.split())
|
||||
|
||||
def baby_talk(text: str) -> str:
|
||||
replacements = {'r': 'w', 'l': 'w', 'th': 'd', 'u': 'oo'}
|
||||
baby_text = []
|
||||
for word in text.split():
|
||||
for k, v in replacements.items():
|
||||
word = word.replace(k, v)
|
||||
baby_text.append(word)
|
||||
return " ".join(baby_text)
|
||||
|
||||
def pirate_speak(text: str) -> str:
|
||||
replacements = {'hello': 'ahoy', 'my': 'me', 'friend': 'matey', 'is': 'be', 'am': 'be', 'are': 'be'}
|
||||
pirate_text = [
|
||||
replacements.get(word.lower(), word)
|
||||
for word in text.split()
|
||||
]
|
||||
return " ".join(pirate_text) + ", arrr!"
|
||||
|
||||
def valley_girl(text: str) -> str:
|
||||
valley_text = []
|
||||
for word in text.split():
|
||||
valley_text.append(word)
|
||||
if random.random() < 0.3:
|
||||
valley_text.append("like")
|
||||
|
||||
return ' '.join(valley_text) + ", you know?"
|
||||
|
||||
def degeneracy(text: str) -> str:
|
||||
cute_phrases = ['kawaii', 'nya~', 'uwu', '^_^', 'rawr']
|
||||
cute_text = []
|
||||
for word in text.split():
|
||||
cute_text.append(word)
|
||||
if random.random() < 0.3:
|
||||
cute_text.append(random.choice(cute_phrases))
|
||||
return " ".join(cute_text)
|
||||
|
||||
def cat_speak(text: str) -> str:
|
||||
cat_text = []
|
||||
for word in text.split():
|
||||
cat_text.append(word)
|
||||
if random.random() < 0.3:
|
||||
cat_text.append('meow')
|
||||
|
||||
return " ".join(cat_text)
|
||||
|
||||
def nerdify(text: str) -> str:
|
||||
nerdy_phrases = ['quark', 'photon', 'nanobot', 'AI', 'quantum', 'algorithm']
|
||||
words = text.split()
|
||||
return ' '.join(word + random.choice(nerdy_phrases) if random.random() < 0.3 else word for word in words)
|
||||
|
||||
def backward_words(text: str) -> str:
|
||||
return ' '.join(word[::-1] for word in text.split())
|
||||
|
||||
def random_gibberish(text: str) -> str:
|
||||
gibberish_words = ['blorpy', 'snorf', 'flibber', 'zoodle', 'womp', 'glarb']
|
||||
words = text.split()
|
||||
return ' '.join(random.choice(gibberish_words) if random.random() < 0.3 else word for word in words)
|
||||
|
||||
def insert_random_animal_sounds(text: str) -> str:
|
||||
animal_sounds = ['moo', 'oink', 'meow', 'woof', 'quack', 'neigh']
|
||||
result = []
|
||||
for word in text.split():
|
||||
result.append(word)
|
||||
if random.random() < 0.3:
|
||||
result.append(random.choice(animal_sounds))
|
||||
return ' '.join(result)
|
||||
|
||||
def shakespearean_speak(text: str) -> str:
|
||||
shakespearean_dict = {
|
||||
'you': 'thou', 'your': 'thy', 'you\'re': 'thou art', 'are': 'art', 'am': 'am', 'is': 'is', 'have': 'hast',
|
||||
'will': 'wilt', 'today': 'this day', 'hello': 'hail', 'goodbye': 'farewell'
|
||||
}
|
||||
words = text.split()
|
||||
return ' '.join(shakespearean_dict.get(word.lower(), word) for word in words)
|
||||
|
||||
def robot_speak(text: str) -> str:
|
||||
robot_noises = ['beep', 'boop', 'whirr', 'click', 'buzz']
|
||||
words = text.split()
|
||||
return ' '.join(random.choice(robot_noises) if word.isalpha() and random.random() < 0.2 else word for word in words)
|
||||
|
||||
def emojify(text: str) -> str:
|
||||
emoji_dict = {
|
||||
'happy': '😄', 'sad': '😢', 'angry': '😡', 'love': '❤️', 'laugh': '😂', 'cry': '😭', 'sleepy': '😴',
|
||||
'surprise': '😮', 'cool': '😎', 'fire': '🔥', 'party': '🎉', 'star': '⭐'
|
||||
}
|
||||
words = text.split()
|
||||
return ' '.join(emoji_dict.get(word.lower(), word) for word in words)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Maps instructions for an Article item to mutate attributes.
|
||||
mutator_map = {
|
||||
"UWU_TITLE": ("title", uwu),
|
||||
"UWU_DESC": ("description", uwu),
|
||||
"GIB_TITLE": ("title", gibberish),
|
||||
"GIB_DESC": ("description", gibberish),
|
||||
"L3_TITLE": ("title", leet),
|
||||
"L3_DESC": ("description", leet),
|
||||
"REV_TITLE": ("title", reverse),
|
||||
"REV_DESC": ("description", reverse),
|
||||
"RND_TITLE": ("title", shuffle),
|
||||
"RND_DESC": ("description", shuffle),
|
||||
"PGL_TITLE": ("title", pig_latin),
|
||||
"PGL_DESC": ("description", pig_latin),
|
||||
"RNC_TITLE": ("title", random_case),
|
||||
"RNC_DESC": ("description", random_case),
|
||||
"UDT_TITLE": ("title", upside_down_text),
|
||||
"UDT_DESC": ("description", upside_down_text),
|
||||
"GS_TITLE": ("title", gothic_script),
|
||||
"GS_DESC": ("description", gothic_script),
|
||||
"EMJ_TITLE": ("title", emoji_substitution),
|
||||
"EMJ_DESC": ("description", emoji_substitution),
|
||||
"SML_TITLE": ("title", small_caps),
|
||||
"SML_DESC": ("description", small_caps),
|
||||
"ZGO_TITLE": ("title", zalgo),
|
||||
"ZGO_DESC": ("description", zalgo),
|
||||
"MC_TITLE": ("title", morse_code),
|
||||
"MC_DESC": ("description", morse_code),
|
||||
"BIN_TITLE": ("title", to_binary),
|
||||
"BIN_DESC": ("description", to_binary),
|
||||
"HEX_TITLE": ("title", to_hexadecimal),
|
||||
"HEX_DESC": ("description", to_hexadecimal),
|
||||
"RMV_TITLE": ("title", remove_vowels),
|
||||
"RMV_DESC": ("description", remove_vowels),
|
||||
"DBL_TITLE": ("title", double_characters),
|
||||
"DBL_DESC": ("description", double_characters),
|
||||
"RNE_TITLE": ("title", randomly_inserted_emoji),
|
||||
"RNE_DESC": ("description", randomly_inserted_emoji),
|
||||
"PIR_TITLE": ("title", pirate_speak),
|
||||
"PIR_DESC": ("description", pirate_speak),
|
||||
"VAL_TITLE": ("title", valley_girl),
|
||||
"VAL_DESC": ("description", valley_girl),
|
||||
"DEG_TITLE": ("title", degeneracy),
|
||||
"DEG_DESC": ("description", degeneracy),
|
||||
"CAT_TITLE": ("title", cat_speak),
|
||||
"CAT_DESC": ("description", cat_speak),
|
||||
"NRD_TITLE": (),
|
||||
"NRD_DESC": (),
|
||||
"BKW_TITLE": (),
|
||||
"BKW_DESC": (),
|
||||
"RNG_TITLE": (),
|
||||
"RNG_DESC": (),
|
||||
"RAS_TITLE": (),
|
||||
"RAS_DESC": (),
|
||||
"SHK_TITLE": (),
|
||||
"SHK_DESC": (),
|
||||
"RBT_TITLE": (),
|
||||
"RBT_DESC": (),
|
||||
"EMI_TITLE": (),
|
||||
"EMI_DESC": (),
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user