Align outercourse action routing
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from typing import Any
|
||||
|
||||
|
||||
OUTERCOURSE_BOOBJOB = "boobjob"
|
||||
OUTERCOURSE_TESTICLE = "testicle_sucking"
|
||||
OUTERCOURSE_PENIS_LICKING = "penis_licking"
|
||||
OUTERCOURSE_HANDJOB = "handjob"
|
||||
OUTERCOURSE_FOOTJOB = "footjob"
|
||||
OUTERCOURSE_GENERIC = "generic"
|
||||
|
||||
|
||||
OUTERCOURSE_ACTION_KIND_CHOICES = {
|
||||
OUTERCOURSE_BOOBJOB,
|
||||
OUTERCOURSE_TESTICLE,
|
||||
OUTERCOURSE_PENIS_LICKING,
|
||||
OUTERCOURSE_HANDJOB,
|
||||
OUTERCOURSE_FOOTJOB,
|
||||
OUTERCOURSE_GENERIC,
|
||||
}
|
||||
|
||||
|
||||
def _clean(value: Any) -> str:
|
||||
text = "" if value is None else str(value)
|
||||
text = text.replace("\n", " ")
|
||||
text = re.sub(r"\s+", " ", text).strip()
|
||||
text = re.sub(r"\s+([,.;:])", r"\1", text)
|
||||
return text
|
||||
|
||||
|
||||
def normalize_outercourse_action_kind(value: Any, default: str = OUTERCOURSE_GENERIC) -> str:
|
||||
text = re.sub(r"[^a-z0-9]+", "_", _clean(value).lower()).strip("_")
|
||||
aliases = {
|
||||
"breast_sex": OUTERCOURSE_BOOBJOB,
|
||||
"titjob": OUTERCOURSE_BOOBJOB,
|
||||
"tit_job": OUTERCOURSE_BOOBJOB,
|
||||
"testicle": OUTERCOURSE_TESTICLE,
|
||||
"testicles": OUTERCOURSE_TESTICLE,
|
||||
"ball_licking": OUTERCOURSE_TESTICLE,
|
||||
"balls_licking": OUTERCOURSE_TESTICLE,
|
||||
"balls": OUTERCOURSE_TESTICLE,
|
||||
"penis_lick": OUTERCOURSE_PENIS_LICKING,
|
||||
"penis_tongue": OUTERCOURSE_PENIS_LICKING,
|
||||
"hand_job": OUTERCOURSE_HANDJOB,
|
||||
"two_handed_handjob": OUTERCOURSE_HANDJOB,
|
||||
"foot_job": OUTERCOURSE_FOOTJOB,
|
||||
"feet_job": OUTERCOURSE_FOOTJOB,
|
||||
}
|
||||
text = aliases.get(text, text)
|
||||
return text if text in OUTERCOURSE_ACTION_KIND_CHOICES else default
|
||||
|
||||
|
||||
def infer_outercourse_action_kind(*parts: Any) -> str:
|
||||
text = " ".join(_clean(part).lower() for part in parts if _clean(part))
|
||||
if not text:
|
||||
return OUTERCOURSE_GENERIC
|
||||
if any(
|
||||
term in text
|
||||
for term in (
|
||||
"boobjob",
|
||||
"titjob",
|
||||
"tit job",
|
||||
"breast sex",
|
||||
"breast-sex",
|
||||
"breasts tightly around",
|
||||
"breasts around",
|
||||
"breasts firmly together",
|
||||
"penis squeezed between both breasts",
|
||||
"penis shaft compressed between breasts",
|
||||
"soft flesh squeezed around the penis",
|
||||
)
|
||||
):
|
||||
return OUTERCOURSE_BOOBJOB
|
||||
if any(
|
||||
term in text
|
||||
for term in (
|
||||
"testicle",
|
||||
"balls licking",
|
||||
"balls-licking",
|
||||
"balls held",
|
||||
"balls close",
|
||||
"balls and mouth",
|
||||
"mouth and tongue on the viewer's balls",
|
||||
"mouth and tongue on the pov viewer's balls",
|
||||
"mouth and tongue licking the viewer's balls",
|
||||
"mouth and tongue licking the pov viewer's balls",
|
||||
)
|
||||
):
|
||||
return OUTERCOURSE_TESTICLE
|
||||
if any(
|
||||
term in text
|
||||
for term in (
|
||||
"penis licking",
|
||||
"penis-licking",
|
||||
"tongue along",
|
||||
"tongue runs along",
|
||||
"tongue running along",
|
||||
"tongue licking",
|
||||
"underside of the penis",
|
||||
)
|
||||
):
|
||||
return OUTERCOURSE_PENIS_LICKING
|
||||
if any(
|
||||
term in text
|
||||
for term in (
|
||||
"handjob",
|
||||
"hand job",
|
||||
"hand wrapped",
|
||||
"hand wraps around",
|
||||
"hand stroking",
|
||||
"both hands stroking",
|
||||
"two-handed",
|
||||
"one hand grips",
|
||||
"one hand wrapped around",
|
||||
)
|
||||
):
|
||||
return OUTERCOURSE_HANDJOB
|
||||
if any(
|
||||
term in text
|
||||
for term in (
|
||||
"footjob",
|
||||
"foot job",
|
||||
"soles",
|
||||
"toes curled",
|
||||
"feet stroking",
|
||||
"feet and penis",
|
||||
"both feet",
|
||||
)
|
||||
):
|
||||
return OUTERCOURSE_FOOTJOB
|
||||
return OUTERCOURSE_GENERIC
|
||||
|
||||
|
||||
def outercourse_context_text(*parts: Any) -> str:
|
||||
return " ".join(_clean(part).lower() for part in parts if _clean(part))
|
||||
Reference in New Issue
Block a user