implemented compilation of config file to remove complexity from actual library
This commit is contained in:
parent
be024389ba
commit
cc5b7ae55e
@ -15,7 +15,6 @@ license-files = ["LICENSE"]
|
||||
|
||||
[project.scripts]
|
||||
python-mommy-dev = "python_mommy_venv.__main__:development"
|
||||
python-mommy-generate-config = "python_mommy_venv.__main__:write_current_config"
|
||||
mommify-venv = "python_mommy_venv.__main__:mommify_venv"
|
||||
|
||||
[build-system]
|
||||
|
@ -2,24 +2,33 @@ import random
|
||||
import subprocess
|
||||
import sys
|
||||
from typing import Optional
|
||||
import os
|
||||
import re
|
||||
import signal
|
||||
import json
|
||||
|
||||
from .config import get_mood, get_template_values
|
||||
from .static import RESPONSES, Situation, colors
|
||||
from .responses import COMPILED_CONFIG_FILE
|
||||
from .static import colors
|
||||
|
||||
|
||||
def get_response(situation: Situation, colorize: Optional[bool] = None):
|
||||
def get_response_from_situation(situation: str, colorize: Optional[bool] = None):
|
||||
if colorize is None:
|
||||
colorize = sys.stdout.isatty()
|
||||
|
||||
# get message
|
||||
mood = get_mood()
|
||||
template = random.choice(RESPONSES[mood][situation])
|
||||
message = template.format(**get_template_values(mood))
|
||||
config = json.loads(COMPILED_CONFIG_FILE.read_text())
|
||||
existing_moods = list(config["moods"].keys())
|
||||
template_options = config["moods"][random.choice(existing_moods)][situation]
|
||||
template: str = random.choice(template_options)
|
||||
|
||||
template_values = {}
|
||||
for key, values in config["vars"].items():
|
||||
template_values[key] = random.choice(values)
|
||||
|
||||
message = template.format(**template_values)
|
||||
|
||||
# return message
|
||||
if not colorize:
|
||||
return message
|
||||
return colors.BOLD + message + colors.ENDC
|
||||
|
||||
|
||||
def get_response(code: int, colorize: Optional[bool] = None) -> str:
|
||||
return get_response_from_situation("positive" if code == 0 else "negative")
|
||||
|
@ -5,37 +5,21 @@ import stat
|
||||
import toml
|
||||
|
||||
from . import get_response
|
||||
from .static import Situation
|
||||
from .config import CONFIG_FILES, CONFIG_DIRECTORY, generate_current_configuration
|
||||
|
||||
from .responses import compile_config
|
||||
|
||||
def development():
|
||||
s = "positive"
|
||||
if len(sys.argv) > 1:
|
||||
s = sys.argv[1]
|
||||
|
||||
print(get_response(Situation(s)))
|
||||
compile_config()
|
||||
|
||||
|
||||
def write_current_config():
|
||||
f = "python-mommy.toml"
|
||||
if len(sys.argv) > 1:
|
||||
f = sys.argv[1]
|
||||
|
||||
config_file = CONFIG_DIRECTORY / f
|
||||
print(f"writing to: {config_file}")
|
||||
|
||||
data = toml.dumps(generate_current_configuration())
|
||||
print(data)
|
||||
with config_file.open("w") as f:
|
||||
f.write(data)
|
||||
|
||||
|
||||
WRAPPER_TEMPLATE = """#!{inner_bin}
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import sys, subprocess
|
||||
from python_mommy_venv import get_response, Situation
|
||||
from python_mommy_venv import get_response
|
||||
|
||||
|
||||
INTERPRETER = "{inner_bin}"
|
||||
@ -43,7 +27,7 @@ result = subprocess.run([INTERPRETER] + sys.argv[1:])
|
||||
code = result.returncode
|
||||
|
||||
print()
|
||||
print(get_response(Situation.POSITIVE if code == 0 else Situation.NEGATIVE))
|
||||
print(get_response(code))
|
||||
exit(code=code)
|
||||
"""
|
||||
|
||||
@ -97,7 +81,10 @@ def mommify_pip(path: Path):
|
||||
with path.open("w") as f:
|
||||
f.write(text)
|
||||
|
||||
|
||||
def mommify_venv():
|
||||
compile_config()
|
||||
|
||||
v = ".venv"
|
||||
if len(sys.argv) > 1:
|
||||
v = sys.argv[1]
|
||||
|
@ -1,193 +0,0 @@
|
||||
from typing import Optional, List, Dict, Union
|
||||
import os
|
||||
from os.path import expandvars
|
||||
from sys import platform
|
||||
import logging
|
||||
from pathlib import Path
|
||||
import toml
|
||||
import random
|
||||
|
||||
from .static import RESPONSES
|
||||
|
||||
logger = logging.Logger("mommy_config")
|
||||
|
||||
PREFIXES = [
|
||||
"PYTHON", # first one is always the prefix of the current program
|
||||
"CARGO",
|
||||
]
|
||||
|
||||
|
||||
# env key is just a backup key for compatibility with cargo mommy
|
||||
CONFIG = {
|
||||
"mood": {
|
||||
"defaults": ["chill"]
|
||||
},
|
||||
"emote": {
|
||||
"defaults": ["❤️", "💖", "💗", "💓", "💞"]
|
||||
},
|
||||
"pronoun": {
|
||||
"defaults": ["her"]
|
||||
},
|
||||
"role": {
|
||||
"defaults": ["mommy"]
|
||||
},
|
||||
"affectionate_term": {
|
||||
"defaults": ["girl"],
|
||||
"env_key": "LITTLE"
|
||||
},
|
||||
"denigrating_term": {
|
||||
"spiciness": "yikes",
|
||||
"defaults": ["slut", "toy", "pet", "pervert", "whore"],
|
||||
"env_key": "FUCKING"
|
||||
},
|
||||
"part": {
|
||||
"spiciness": "yikes",
|
||||
"defaults": ["milk"]
|
||||
}
|
||||
}
|
||||
|
||||
MOOD_PRIORITIES: Dict[str, int] = {}
|
||||
for i, mood in enumerate(RESPONSES):
|
||||
MOOD_PRIORITIES[mood] = i
|
||||
|
||||
PREFIXES = [
|
||||
"PYTHON", # first one is always the prefix of the current program
|
||||
"CARGO",
|
||||
]
|
||||
|
||||
for key, value in CONFIG.items():
|
||||
env_keys = [
|
||||
PREFIXES[0] + "_MOMMY_" + key.upper(),
|
||||
"MOMMY_" + key.upper(),
|
||||
*(p + "_MOMMY_" + key.upper() for p in PREFIXES)
|
||||
]
|
||||
|
||||
if value.get("env_key") is not None:
|
||||
env_keys.append(value.get("env_key"))
|
||||
|
||||
for env_key in env_keys:
|
||||
res = os.environ.get(env_key)
|
||||
if res is not None:
|
||||
value["default"] = res.split("/")
|
||||
|
||||
|
||||
def _get_xdg_config_dir() -> Path:
|
||||
res = os.environ.get("XDG_CONFIG_HOME")
|
||||
if res is not None:
|
||||
return Path(res)
|
||||
|
||||
xdg_user_dirs_file = Path(os.environ.get("XDG_CONFIG_HOME") or Path(Path.home(), ".config", "user-dirs.dirs"))
|
||||
xdg_user_dirs_default_file = Path("/etc/xdg/user-dirs.defaults")
|
||||
|
||||
def get_dir_from_xdg_file(xdg_file_path: Path, key_a: str) -> Optional[str]:
|
||||
if not xdg_file_path.exists():
|
||||
logger.info("config file not found in %s", str(xdg_file_path))
|
||||
return
|
||||
|
||||
with xdg_file_path.open("r") as f:
|
||||
for line in f:
|
||||
if line.startswith("#"):
|
||||
continue
|
||||
|
||||
parts = line.split("=")
|
||||
if len(parts) > 2:
|
||||
continue
|
||||
|
||||
key_b = parts[0].lower().strip()
|
||||
value = parts[1].strip().split("#")[0]
|
||||
|
||||
if key_a.lower() == key_b:
|
||||
return value
|
||||
|
||||
logger.info("key %s not found in %s", key_a, str(xdg_file_path))
|
||||
|
||||
res = get_dir_from_xdg_file(xdg_user_dirs_file, "XDG_CONFIG_HOME")
|
||||
if res is not None:
|
||||
return Path(res)
|
||||
|
||||
res = get_dir_from_xdg_file(xdg_user_dirs_default_file, "CONFIG")
|
||||
if res is not None:
|
||||
return Path(Path.home(), res)
|
||||
|
||||
|
||||
res = get_dir_from_xdg_file(xdg_user_dirs_default_file, "XDG_CONFIG_HOME")
|
||||
if res is not None:
|
||||
return Path(Path.home(), res)
|
||||
|
||||
default = Path(Path.home(), ".config")
|
||||
logging.info("falling back to %s", default)
|
||||
return default
|
||||
|
||||
|
||||
CONFIG_DIRECTORY = _get_xdg_config_dir() / "mommy"
|
||||
CONFIG_FILES = [
|
||||
CONFIG_DIRECTORY / "python-mommy.toml",
|
||||
CONFIG_DIRECTORY / "mommy.toml",
|
||||
]
|
||||
|
||||
def load_config_file(config_file: Path) -> bool:
|
||||
global CONFIG
|
||||
if not config_file.exists():
|
||||
return False
|
||||
|
||||
with config_file.open("r") as f:
|
||||
data = toml.load(f)
|
||||
|
||||
for key, value in data.items():
|
||||
if isinstance(value, str):
|
||||
CONFIG[key]["defaults"] = [value]
|
||||
else:
|
||||
CONFIG[key]["defaults"] = value
|
||||
|
||||
return True
|
||||
|
||||
|
||||
for c in CONFIG_FILES:
|
||||
if load_config_file(c):
|
||||
break
|
||||
|
||||
|
||||
# validate config file
|
||||
if True:
|
||||
unfiltered_moods = CONFIG["mood"]["defaults"]
|
||||
CONFIG["mood"]["defaults"] = filtered_moods = []
|
||||
for mood in unfiltered_moods:
|
||||
if mood in RESPONSES:
|
||||
filtered_moods.append(mood)
|
||||
else:
|
||||
logger.warning("mood %s isn't supported", mood)
|
||||
|
||||
|
||||
def get_mood() -> str:
|
||||
return random.choice(CONFIG["mood"]["defaults"])
|
||||
|
||||
def get_template_values(mood: str) -> Dict[str, str]:
|
||||
mood_spice_level = MOOD_PRIORITIES[mood]
|
||||
result = {}
|
||||
|
||||
for key, value in CONFIG.items():
|
||||
spice = value.get("spiciness")
|
||||
allow_key = spice is None
|
||||
if not allow_key:
|
||||
key_spice_level = MOOD_PRIORITIES[spice]
|
||||
allow_key = mood_spice_level >= key_spice_level
|
||||
|
||||
if not allow_key:
|
||||
continue
|
||||
|
||||
result[key] = random.choice(value["defaults"])
|
||||
|
||||
return result
|
||||
|
||||
def generate_current_configuration() -> Dict[str, Union[str, List[str]]]:
|
||||
global CONFIG
|
||||
generated = {}
|
||||
|
||||
for key, definition in CONFIG.items():
|
||||
value = definition["defaults"]
|
||||
if len(value) == 1:
|
||||
value = value[0]
|
||||
|
||||
generated[key] = value
|
||||
|
||||
return generated
|
174
python_mommy_venv/responses.py
Normal file
174
python_mommy_venv/responses.py
Normal file
@ -0,0 +1,174 @@
|
||||
from pathlib import Path
|
||||
import json
|
||||
from typing import Dict, Optional, List
|
||||
import os
|
||||
import logging
|
||||
import toml
|
||||
import random
|
||||
|
||||
|
||||
logger = logging.Logger(__name__)
|
||||
PREFIX = "MOMMY"
|
||||
|
||||
|
||||
RESPONSES_FILE = Path(__file__).parent / "responses.json"
|
||||
ADDITIONAL_ENV_VARS = {
|
||||
"pronoun": "PRONOUNS",
|
||||
"role": "ROLES",
|
||||
"emote": "EMOTES",
|
||||
"mood": "MOODS",
|
||||
}
|
||||
|
||||
def _get_xdg_config_dir() -> Path:
|
||||
res = os.environ.get("XDG_CONFIG_HOME")
|
||||
if res is not None:
|
||||
return Path(res)
|
||||
|
||||
xdg_user_dirs_file = Path(os.environ.get("XDG_CONFIG_HOME") or Path(Path.home(), ".config", "user-dirs.dirs"))
|
||||
xdg_user_dirs_default_file = Path("/etc/xdg/user-dirs.defaults")
|
||||
|
||||
def get_dir_from_xdg_file(xdg_file_path: Path, key_a: str) -> Optional[str]:
|
||||
if not xdg_file_path.exists():
|
||||
logger.info("config file not found in %s", str(xdg_file_path))
|
||||
return
|
||||
|
||||
with xdg_file_path.open("r") as f:
|
||||
for line in f:
|
||||
if line.startswith("#"):
|
||||
continue
|
||||
|
||||
parts = line.split("=")
|
||||
if len(parts) > 2:
|
||||
continue
|
||||
|
||||
key_b = parts[0].lower().strip()
|
||||
value = parts[1].strip().split("#")[0]
|
||||
|
||||
if key_a.lower() == key_b:
|
||||
return value
|
||||
|
||||
logger.info("key %s not found in %s", key_a, str(xdg_file_path))
|
||||
|
||||
res = get_dir_from_xdg_file(xdg_user_dirs_file, "XDG_CONFIG_HOME")
|
||||
if res is not None:
|
||||
return Path(res)
|
||||
|
||||
res = get_dir_from_xdg_file(xdg_user_dirs_default_file, "CONFIG")
|
||||
if res is not None:
|
||||
return Path(Path.home(), res)
|
||||
|
||||
|
||||
res = get_dir_from_xdg_file(xdg_user_dirs_default_file, "XDG_CONFIG_HOME")
|
||||
if res is not None:
|
||||
return Path(Path.home(), res)
|
||||
|
||||
default = Path(Path.home(), ".config")
|
||||
logging.info("falling back to %s", default)
|
||||
return default
|
||||
|
||||
|
||||
CONFIG_DIRECTORY = _get_xdg_config_dir() / "mommy"
|
||||
CONFIG_FILES = [
|
||||
CONFIG_DIRECTORY / "python-mommy.toml",
|
||||
CONFIG_DIRECTORY / "mommy.toml",
|
||||
]
|
||||
COMPILED_CONFIG_FILE = CONFIG_DIRECTORY / "responses.json"
|
||||
|
||||
def _load_config_file(config_file: Path) -> Optional[Dict[str, List[str]]]:
|
||||
global CONFIG
|
||||
if not config_file.exists():
|
||||
return None
|
||||
|
||||
with config_file.open("r") as f:
|
||||
data = toml.load(f)
|
||||
|
||||
result = {}
|
||||
for key, value in data.items():
|
||||
if isinstance(value, str):
|
||||
result[key] = [value]
|
||||
else:
|
||||
result[key] = value
|
||||
|
||||
return result
|
||||
|
||||
|
||||
ADDITIONAL_PROGRAM_PREFIXES = [
|
||||
"cargo", # only as fallback if user already configured cargo
|
||||
]
|
||||
|
||||
def _get_env_var_names(name: str):
|
||||
BASE = PREFIX + "_" + name.upper()
|
||||
yield "PYTHON_" + BASE
|
||||
yield BASE
|
||||
for a in ADDITIONAL_PROGRAM_PREFIXES:
|
||||
yield a + "_" + BASE
|
||||
|
||||
def _get_env_value(name: str) -> Optional[str]:
|
||||
if name in ADDITIONAL_ENV_VARS:
|
||||
for key in _get_env_var_names(ADDITIONAL_ENV_VARS[name]):
|
||||
val = os.environ.get(key)
|
||||
if val is not None:
|
||||
return val
|
||||
|
||||
for key in _get_env_var_names(name):
|
||||
val = os.environ.get(key)
|
||||
if val is not None:
|
||||
return val
|
||||
|
||||
|
||||
|
||||
def compile_config():
|
||||
global RESPONSES_FILE
|
||||
|
||||
data = json.loads(RESPONSES_FILE.read_text())
|
||||
config_definition: Dict[str, dict] = data["vars"]
|
||||
mood_definitions: Dict[str, dict] = data["moods"]
|
||||
|
||||
# environment variables for compatibility with cargo mommy
|
||||
# fill ADDITIONAL_ENV_VARS with the "env_key" values
|
||||
for key, conf in config_definition.items():
|
||||
if "env_key" in conf:
|
||||
ADDITIONAL_ENV_VARS[key] = conf["env_key"]
|
||||
|
||||
# set config to the default values
|
||||
config: Dict[str, List[str]] = {}
|
||||
for key, conf in config_definition.items():
|
||||
config[key] = conf["defaults"]
|
||||
|
||||
# load config file
|
||||
config_file_data: Optional[Dict[str, List[str]]]
|
||||
for c in CONFIG_FILES:
|
||||
config_file_data = _load_config_file(c)
|
||||
if config_file_data is not None:
|
||||
break
|
||||
|
||||
if config_file_data is not None:
|
||||
config.update(config_file_data)
|
||||
|
||||
|
||||
# fill config with env
|
||||
for key, conf in config_definition.items():
|
||||
val = _get_env_value(key)
|
||||
if val is not None:
|
||||
config[key] = val.split("/")
|
||||
|
||||
# validate moods
|
||||
for mood in config["mood"]:
|
||||
if mood not in mood_definitions:
|
||||
supported_moods_str = ", ".join(mood_definitions.keys())
|
||||
print(f"{random.choice(config['role'])} doesn't know how to feel {mood}... {random.choice(config['pronoun'])} moods are {supported_moods_str}")
|
||||
exit(1)
|
||||
|
||||
# compile
|
||||
compiled = {}
|
||||
compiled_moods = compiled["moods"] = {}
|
||||
compiled_vars = compiled["vars"] = {}
|
||||
|
||||
for mood in config["mood"]:
|
||||
compiled_moods[mood] = mood_definitions[mood]
|
||||
del config["mood"]
|
||||
compiled_vars.update(config)
|
||||
|
||||
print("writing compiled config to " + str(COMPILED_CONFIG_FILE))
|
||||
with COMPILED_CONFIG_FILE.open("w") as f:
|
||||
json.dump(compiled, f, indent=4)
|
@ -1,136 +1,4 @@
|
||||
from __future__ import annotations
|
||||
from enum import Enum
|
||||
|
||||
class Situation(Enum):
|
||||
POSITIVE = "positive"
|
||||
NEGATIVE = "negative"
|
||||
OVERFLOW = "overflow "
|
||||
|
||||
|
||||
RESPONSES = {
|
||||
"chill": {
|
||||
Situation.POSITIVE: [
|
||||
"*pets your head*",
|
||||
"*gives you scritches*",
|
||||
"you're such a smart cookie~",
|
||||
"that's a good {affectionate_term}~",
|
||||
"{role} thinks {pronoun} little {affectionate_term} earned a big hug~",
|
||||
"good {affectionate_term}~\n{role}'s so proud of you~",
|
||||
"aww, what a good {affectionate_term}~\n{role} knew you could do it~",
|
||||
"you did it~!",
|
||||
"{role} loves you~",
|
||||
"*gives you a sticker*",
|
||||
"*boops your nose*",
|
||||
"*wraps you in a big hug*",
|
||||
"well done~!\n{role} is so happy for you~",
|
||||
"what a good {affectionate_term} you are~",
|
||||
"that's {role}'s clever little {affectionate_term}~",
|
||||
"you're doing so well~!",
|
||||
"you're making {role} so happy~",
|
||||
"{role} loves {pronoun} cute little {affectionate_term}~"
|
||||
],
|
||||
Situation.NEGATIVE: [
|
||||
"{role} believes in you~",
|
||||
"don't forget to hydrate~",
|
||||
"aww, you'll get it next time~",
|
||||
"do you need {role}'s help~?",
|
||||
"everything's gonna be ok~",
|
||||
"{role} still loves you no matter what~",
|
||||
"oh no did {role}'s little {affectionate_term} make a big mess~?",
|
||||
"{role} knows {pronoun} little {affectionate_term} can do better~",
|
||||
"{role} still loves you~",
|
||||
"{role} thinks {pronoun} little {affectionate_term} is getting close~",
|
||||
"it's ok, {role}'s here for you~",
|
||||
"oh, darling, you're almost there~",
|
||||
"does {role}'s little {affectionate_term} need a bit of a break~?",
|
||||
"oops~! {role} loves you anyways~",
|
||||
"try again for {role}, {affectionate_term}~",
|
||||
"don't worry, {role} knows you can do it~"
|
||||
],
|
||||
Situation.OVERFLOW: [
|
||||
"{role} has executed too many times and needs to take a nap~"
|
||||
]
|
||||
},
|
||||
"ominous": {
|
||||
Situation.POSITIVE: [
|
||||
"What you have set in motion today will be remembered for aeons to come!",
|
||||
"{role} will see to it that {pronoun} little {affectionate_term}'s name is feared~",
|
||||
"{role} is proud of the evil seed {pronoun} {affectionate_term} has planted into this accursed world"
|
||||
],
|
||||
Situation.NEGATIVE: [
|
||||
"Ah, failure? {role} will make sure the stars are right next time",
|
||||
"Does {role}'s little {affectionate_term} need more time for worship~?",
|
||||
"May the mark of the beast stain your flesh forever, {role} will haunt your soul forevermore"
|
||||
],
|
||||
Situation.OVERFLOW: [
|
||||
"THOU HAST DRUNK TOO DEEPLY OF THE FONT"
|
||||
]
|
||||
},
|
||||
"thirsty": {
|
||||
"spiciness": "thirsty",
|
||||
Situation.POSITIVE: [
|
||||
"*tugs your leash*\nthat's a VERY good {affectionate_term}~",
|
||||
"*runs {pronoun} fingers through your hair* good {affectionate_term}~ keep going~",
|
||||
"*smooches your forehead*\ngood job~",
|
||||
"*nibbles on your ear*\nthat's right~\nkeep going~",
|
||||
"*pats your butt*\nthat's a good {affectionate_term}~",
|
||||
"*drags {pronoun} nail along your cheek*\nsuch a good {affectionate_term}~",
|
||||
"*bites {pronoun} lip*\nmhmm~",
|
||||
"give {role} a kiss~",
|
||||
"*heavy breathing against your neck*"
|
||||
],
|
||||
Situation.NEGATIVE: [
|
||||
"you're so cute when you're flustered~",
|
||||
"do you think you're going to get a reward from {role} like that~?",
|
||||
"*grabs your hair and pulls your head back*\nyou can do better than that for {role} can't you~?",
|
||||
"if you don't learn how to code better, {role} is going to put you in time-out~",
|
||||
"does {role} need to give {pronoun} little {affectionate_term} some special lessons~?",
|
||||
"you need to work harder to please {role}~",
|
||||
"gosh you must be flustered~",
|
||||
"are you just keysmashing now~?\ncute~",
|
||||
"is {role}'s little {affectionate_term} having trouble reaching the keyboard~?"
|
||||
],
|
||||
Situation.OVERFLOW: [
|
||||
"you've been a bad little {affectionate_term} and worn out {role}~"
|
||||
]
|
||||
},
|
||||
"yikes": {
|
||||
"spiciness": "yikes",
|
||||
Situation.POSITIVE: [
|
||||
"keep it up and {role} might let you cum you little {denigrating_term}~",
|
||||
"good {denigrating_term}~\nyou've earned five minutes with the buzzy wand~",
|
||||
"mmm~ come taste {role}'s {part}~",
|
||||
"*slides {pronoun} finger in your mouth*\nthat's a good little {denigrating_term}~",
|
||||
"you're so good with your fingers~\n{role} knows where {pronoun} {denigrating_term} should put them next~",
|
||||
"{role} is getting hot~",
|
||||
"that's a good {denigrating_term}~",
|
||||
"yes~\nyes~~\nyes~~~",
|
||||
"{role}'s going to keep {pronoun} good little {denigrating_term}~",
|
||||
"open wide {denigrating_term}.\nyou've earned {role}'s {part}~",
|
||||
"do you want {role}'s {part}?\nkeep this up and you'll earn it~",
|
||||
"oooh~ what a good {denigrating_term} you are~"
|
||||
],
|
||||
Situation.NEGATIVE: [
|
||||
"you filthy {denigrating_term}~\nyou made a mess, now clean it up~\nwith your tongue~",
|
||||
"*picks you up by the throat*\npathetic~",
|
||||
"*drags {pronoun} claws down your back*\ndo it again~",
|
||||
"*brandishes {pronoun} paddle*\ndon't make me use this~",
|
||||
"{denigrating_term}.\n{denigrating_term}~\n{denigrating_term}~~",
|
||||
"get on your knees and beg {role} for forgiveness you {denigrating_term}~",
|
||||
"{role} doesn't think {pronoun} little {denigrating_term} should have permission to wear clothes anymore~",
|
||||
"never forget you belong to {role}~",
|
||||
"does {role} need to put you in the {denigrating_term} wiggler~?",
|
||||
"{role} is starting to wonder if you should just give up and become {pronoun} breeding stock~",
|
||||
"on your knees {denigrating_term}~",
|
||||
"oh dear. {role} is not pleased",
|
||||
"one spank per error sounds appropriate, don't you think {denigrating_term}?",
|
||||
"no more {part} for you {denigrating_term}"
|
||||
],
|
||||
Situation.OVERFLOW: [
|
||||
"brats like you don't get to talk to {role}"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
class colors:
|
||||
HEADER = '\033[95m'
|
||||
|
Loading…
x
Reference in New Issue
Block a user