rewrote config to be compliant with cargo mommy

This commit is contained in:
Hazel Noack 2025-07-28 12:20:05 +02:00
parent 66db5acc76
commit bd9fcd1edc
4 changed files with 189 additions and 88 deletions

View File

@ -9,8 +9,7 @@ THIS IS A PORT OF [Gankra/cargo-mommy](https://github.com/Gankra/cargo-mommy)
# TODO # TODO
- edit executable in .venv/pyenv.cfg - make compatibility with https://github.com/Gankra/cargo-mommy/blob/main/responses.json
- link it to a mommy wrapper
# Installation # Installation

View File

@ -6,22 +6,18 @@ import os
import re import re
import signal import signal
from .config import CONFIG from .config import get_mood, get_template_values
from .static import RESPONSES, Situation, colors from .static import RESPONSES, Situation, colors
def _expand_template(template: str) -> str:
for key, value in CONFIG.items():
template = template.replace(key, random.choice(value))
return template + " " + random.choice(CONFIG["MOMMYS_EMOTES"])
def get_response(situation: Situation, colorize: Optional[bool] = None): def get_response(situation: Situation, colorize: Optional[bool] = None):
if colorize is None: if colorize is None:
colorize = sys.stdout.isatty() colorize = sys.stdout.isatty()
# get message # get message
possible_templates = RESPONSES[random.choice(CONFIG["MOMMYS_MOODS"])][situation] mood = get_mood()
message = _expand_template(random.choice(possible_templates)) template = random.choice(RESPONSES[mood][situation])
message = template.format(**get_template_values(mood))
# return message # return message
if not colorize: if not colorize:

View File

@ -1,11 +1,11 @@
from typing import Optional, List from typing import Optional, List, Dict
import os import os
from os.path import expandvars from os.path import expandvars
from sys import platform from sys import platform
import logging import logging
from pathlib import Path from pathlib import Path
import configparser
import toml import toml
import random
from .static import RESPONSES from .static import RESPONSES
@ -34,46 +34,61 @@ def _get_var(key: str, fallback: str) -> List[str]:
return (value or fallback).split("/") return (value or fallback).split("/")
_DEFAULT_CONFIG = {key: _get_var(key, value) for key, value in { # env key is just a backup key for compatibility with cargo mommy
"MOMMYS_ROLE": "mommy", CONFIG = {
"MOMMYS_PRONOUNS": "her", "mood": {
"MOMMYS_LITTLE": "girl", "defaults": ["chill"]
"MOMMYS_EMOTES": "❤️/💖/💗/💓/💞", },
"MOMMYS_PARTS": "milk", "emote": {
"MOMMYS_FUCKING": "slut/toy/pet/pervert/whore", "defaults": ["❤️", "💖", "💗", "💓", "💞"]
# needs validation },
"MOMMYS_MOODS": "chill", "pronoun": {
}.items()} "defaults": ["her"]
},
"role": {
"defaults": ["mommy"]
},
CONFIG = {} "affectionate_term": {
"defaults": ["girl"],
"env_key": "LITTLE"
},
def load_config(data: Optional[dict] = None): "denigrating_term": {
global CONFIG "spiciness": "yikes",
data = data if data is not None else {} "defaults": ["slut", "toy", "pet", "pervert", "whore"],
"env_key": "FUCKING"
data = { },
**_DEFAULT_CONFIG, "part": {
**data, "spiciness": "yikes",
"defaults": ["milk"]
}
} }
# convert toml keys from snake_case to UPPER_CASE MOOD_PRIORITIES: Dict[str, int] = {}
data = { for i, mood in enumerate(RESPONSES):
key.upper(): value MOOD_PRIORITIES[mood] = i
for key, value in data.items()
}
# validate needed values PREFIXES = [
unfiltered_moods = data["MOMMYS_MOODS"] "PYTHON", # first one is always the prefix of the current program
data["MOMMYS_MOODS"] = filtered_moods = [] "CARGO",
for mood in unfiltered_moods: ]
if mood in RESPONSES:
filtered_moods.append(mood)
else:
logger.warning("mood %s isn't supported", mood)
CONFIG = data 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("/")
load_config()
def _get_xdg_config_dir() -> Path: def _get_xdg_config_dir() -> Path:
res = os.environ.get("XDG_CONFIG_HOME") res = os.environ.get("XDG_CONFIG_HOME")
@ -130,12 +145,18 @@ CONFIG_FILES = [
] ]
def load_config_file(config_file: Path) -> bool: def load_config_file(config_file: Path) -> bool:
global CONFIG
if not config_file.exists(): if not config_file.exists():
return False return False
with config_file.open("r") as f: with config_file.open("r") as f:
data = toml.load(f) data = toml.load(f)
load_config(data=data)
for key, value in data.items():
if isinstance(value, str):
CONFIG[key]["default"] = [value]
else:
CONFIG[key]["default"] = value
return True return True
@ -143,3 +164,36 @@ def load_config_file(config_file: Path) -> bool:
for c in CONFIG_FILES: for c in CONFIG_FILES:
if load_config_file(c): if load_config_file(c):
break 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

View File

@ -1,8 +1,11 @@
from __future__ import annotations
from enum import Enum from enum import Enum
class Situation(Enum): class Situation(Enum):
POSITIVE = "positive" POSITIVE = "positive"
NEGATIVE = "negative" NEGATIVE = "negative"
OVERFLOW = "overflow "
RESPONSES = { RESPONSES = {
"chill": { "chill": {
@ -10,72 +13,121 @@ RESPONSES = {
"*pets your head*", "*pets your head*",
"*gives you scritches*", "*gives you scritches*",
"you're such a smart cookie~", "you're such a smart cookie~",
"that's a good MOMMYS_LITTLE~", "that's a good {affectionate_term}~",
"MOMMYS_ROLE thinks MOMMYS_PRONOUNS little MOMMYS_LITTLE earned a big hug~", "{role} thinks {pronoun} little {affectionate_term} earned a big hug~",
"good MOMMYS_LITTLE~\nMOMMYS_ROLE's so proud of you~", "good {affectionate_term}~\n{role}'s so proud of you~",
"aww, what a good MOMMYS_LITTLE~\nMOMMYS_ROLE knew you could do it~", "aww, what a good {affectionate_term}~\n{role} knew you could do it~",
"you did it~!", "you did it~!",
"MOMMYS_ROLE loves you~", "{role} loves you~",
"*gives you a sticker*" "*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: [ Situation.NEGATIVE: [
"MOMMYS_ROLE believes in you~", "{role} believes in you~",
"don't forget to hydrate~", "don't forget to hydrate~",
"aww, you'll get it next time~", "aww, you'll get it next time~",
"do you need MOMMYS_ROLE's help~?", "do you need {role}'s help~?",
"MOMMYS_ROLE still loves you no matter what~", "everything's gonna be ok~",
"oh no did MOMMYS_ROLE's little MOMMYS_LITTLE make a big mess~?", "{role} still loves you no matter what~",
"MOMMYS_ROLE knows MOMMYS_PRONOUNS little MOMMYS_LITTLE can do better~", "oh no did {role}'s little {affectionate_term} make a big mess~?",
"MOMMYS_ROLE still loves you~", "{role} knows {pronoun} little {affectionate_term} can do better~",
"just a little further, sweetie~" "{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": { "thirsty": {
"spiciness": "thirsty",
Situation.POSITIVE: [ Situation.POSITIVE: [
"*tugs your leash*\nthat's a VERY good MOMMYS_LITTLE~", "*tugs your leash*\nthat's a VERY good {affectionate_term}~",
"*runs MOMMYS_PRONOUNS fingers through your hair* good MOMMYS_LITTLE~ keep going~", "*runs {pronoun} fingers through your hair* good {affectionate_term}~ keep going~",
"*smooches your forehead*\ngood job~", "*smooches your forehead*\ngood job~",
"*nibbles on your ear*\nthat's right~\nkeep going~", "*nibbles on your ear*\nthat's right~\nkeep going~",
"*pats your butt*\nthat's a good MOMMYS_LITTLE~", "*pats your butt*\nthat's a good {affectionate_term}~",
"*drags MOMMYS_PRONOUNS nail along your cheek*\nsuch a good MOMMYS_LITTLE~", "*drags {pronoun} nail along your cheek*\nsuch a good {affectionate_term}~",
"*bites MOMMYS_PRONOUNS lip*\nmhmm~", "*bites {pronoun} lip*\nmhmm~",
"give MOMMYS_PRONOUNS a kiss~", "give {role} a kiss~",
"*heavy breathing against your neck*" "*heavy breathing against your neck*"
], ],
Situation.NEGATIVE: [ Situation.NEGATIVE: [
"do you think you're going to get a reward from MOMMYS_ROLE like that~?", "you're so cute when you're flustered~",
"*grabs your hair and pulls your head back*\nyou can do better than that for MOMMYS_ROLE can't you~?", "do you think you're going to get a reward from {role} like that~?",
"if you don't learn how to code better, MOMMYS_ROLE is going to put you in time-out~", "*grabs your hair and pulls your head back*\nyou can do better than that for {role} can't you~?",
"does MOMMYS_ROLE need to give MOMMYS_PRONOUNS little MOMMYS_LITTLE some special lessons~?", "if you don't learn how to code better, {role} is going to put you in time-out~",
"you need to work harder to please MOMMYS_ROLE~", "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~", "gosh you must be flustered~",
"are you just keysmashing now~?\ncute~", "are you just keysmashing now~?\ncute~",
"is MOMMYS_ROLE's little MOMMYS_LITTLE having trouble reaching the keyboard~?" "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": { "yikes": {
"spiciness": "yikes",
Situation.POSITIVE: [ Situation.POSITIVE: [
"keep it up and MOMMYS_ROLE might let you cum you little MOMMYS_FUCKING~", "keep it up and {role} might let you cum you little {denigrating_term}~",
"good MOMMYS_FUCKING~\nyou've earned five minutes with the buzzy wand~", "good {denigrating_term}~\nyou've earned five minutes with the buzzy wand~",
"mmm~ come taste MOMMYS_ROLE's MOMMYS_PARTS~", "mmm~ come taste {role}'s {part}~",
"*slides MOMMYS_PRONOUNS finger in your mouth*\nthat's a good little MOMMYS_FUCKING~", "*slides {pronoun} finger in your mouth*\nthat's a good little {denigrating_term}~",
"you're so good with your fingers~\nMOMMYS_ROLE knows where MOMMYS_PRONOUNS MOMMYS_FUCKING should put them next~", "you're so good with your fingers~\n{role} knows where {pronoun} {denigrating_term} should put them next~",
"MOMMYS_ROLE is getting hot~", "{role} is getting hot~",
"that's a good MOMMYS_FUCKING~", "that's a good {denigrating_term}~",
"yes~\nyes~~\nyes~~~", "yes~\nyes~~\nyes~~~",
"MOMMYS_ROLE's going to keep MOMMYS_PRONOUNS good little MOMMYS_FUCKING~" "{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: [ Situation.NEGATIVE: [
"you filthy MOMMYS_FUCKING~\nyou made a mess, now clean it up~\nwith your tongue~", "you filthy {denigrating_term}~\nyou made a mess, now clean it up~\nwith your tongue~",
"*picks you up by the throat*\npathetic~", "*picks you up by the throat*\npathetic~",
"*drags MOMMYS_PRONOUNS claws down your back*\ndo it again~", "*drags {pronoun} claws down your back*\ndo it again~",
"*brandishes MOMMYS_PRONOUNS paddle*\ndon't make me use this~", "*brandishes {pronoun} paddle*\ndon't make me use this~",
"MOMMYS_FUCKING.\nMOMMYS_FUCKING~\nMOMMYS_FUCKING~~", "{denigrating_term}.\n{denigrating_term}~\n{denigrating_term}~~",
"get on your knees and beg MOMMYS_ROLE for forgiveness you MOMMYS_FUCKING~", "get on your knees and beg {role} for forgiveness you {denigrating_term}~",
"MOMMYS_ROLE doesn't think MOMMYS_PRONOUNS little MOMMYS_FUCKING should have permission to wear clothes anymore~", "{role} doesn't think {pronoun} little {denigrating_term} should have permission to wear clothes anymore~",
"never forget you belong to MOMMYS_ROLE~", "never forget you belong to {role}~",
"does MOMMYS_ROLE need to put you in the MOMMYS_FUCKING wiggler~?", "does {role} need to put you in the {denigrating_term} wiggler~?",
"MOMMYS_ROLE is starting to wonder if you should just give up and become MOMMYS_PRONOUNS breeding stock~" "{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}"
] ]
} }
} }