From a392ab9779fcb92b18c7985416e1a43286fffd8f Mon Sep 17 00:00:00 2001 From: Ethanfel Date: Fri, 26 Jun 2026 12:54:35 +0200 Subject: [PATCH] Expand hardcore interaction pools --- __init__.py | 8 + categories/expression_composition_pools.json | 94 +++ categories/sexual_poses.json | 740 +++++++++++++++++++ docs/prompt-pool-routing-map.md | 45 +- krea_formatter.py | 56 ++ prompt_builder.py | 271 ++++++- 6 files changed, 1203 insertions(+), 11 deletions(-) diff --git a/__init__.py b/__init__.py index 1615aef..65f23fc 100644 --- a/__init__.py +++ b/__init__.py @@ -299,6 +299,8 @@ NODE_INPUT_TOOLTIPS = { "allow_double": "Allow double-penetration or second-contact wording.", "allow_penetration": "Allow vaginal/penetrative sex subcategories.", "allow_foreplay": "Allow hardcore teasing/foreplay setup actions such as kissing, caressing, breast/face touching, and undressing.", + "allow_interaction": "Allow non-act interaction pools such as body worship, clothing transitions, guidance, camera presentation, watching, and aftercare.", + "allow_manual": "Allow manual stimulation pools such as fingering, clit rubbing, and mutual masturbation.", "allow_oral": "Allow oral sex subcategories.", "allow_outercourse": "Allow non-penetrative penis-contact acts such as boobjob/titjob, footjob, penis licking, and testicle sucking.", "allow_anal": "Allow anal subcategories.", @@ -2262,6 +2264,8 @@ class SxCPHardcoreActionFilter: "allow_double": ("BOOLEAN", {"default": False}), "allow_penetration": ("BOOLEAN", {"default": True}), "allow_foreplay": ("BOOLEAN", {"default": True}), + "allow_interaction": ("BOOLEAN", {"default": True}), + "allow_manual": ("BOOLEAN", {"default": True}), "allow_oral": ("BOOLEAN", {"default": True}), "allow_outercourse": ("BOOLEAN", {"default": True}), "allow_anal": ("BOOLEAN", {"default": True}), @@ -2284,6 +2288,8 @@ class SxCPHardcoreActionFilter: allow_double, allow_penetration, allow_foreplay, + allow_interaction, + allow_manual, allow_oral, allow_outercourse, allow_anal, @@ -2297,6 +2303,8 @@ class SxCPHardcoreActionFilter: allow_double=allow_double, allow_penetration=allow_penetration, allow_foreplay=allow_foreplay, + allow_interaction=allow_interaction, + allow_manual=allow_manual, allow_oral=allow_oral, allow_outercourse=allow_outercourse, allow_anal=allow_anal, diff --git a/categories/expression_composition_pools.json b/categories/expression_composition_pools.json index e6c7459..375fb4b 100644 --- a/categories/expression_composition_pools.json +++ b/categories/expression_composition_pools.json @@ -211,6 +211,50 @@ "focused stare while clothing is pulled aside", "close-range lustful eye contact" ], + "hardcore_interaction_expressions": [ + "close-range lustful eye contact", + "breathless body-contact expression", + "focused stare while hands guide the pose", + "flushed reaction to teasing touch", + "heavy-lidded look during body worship", + "mouth open during hands-on guidance", + "controlled dominant stare", + "submissive bitten-lip expression", + "shameless camera-aware expression", + "soft moan while being held", + "hungry stare during clothing movement", + "wide-eyed aroused reaction", + "teasing grin while being watched", + "steady eye contact during the transition" + ], + "hardcore_manual_expressions": [ + "focused pleasure face during manual stimulation", + "bitten-lip reaction to fingers", + "eyes half-closed while being touched", + "breathless open-mouth manual-stimulation expression", + "direct eye contact while fingers work", + "flushed face with hips lifting", + "controlled clit-rubbing reaction", + "messy aroused stare during fingering", + "shameless mutual-masturbation expression", + "glossy eyes and parted lips while hands move", + "strained moan from hand stimulation", + "soft dazed pleasure face" + ], + "hardcore_aftercare_expressions": [ + "spent satisfied expression", + "soft post-sex eye contact", + "breathless relaxed face", + "dazed afterglow stare", + "small exhausted smile", + "heavy-lidded calm expression", + "flushed skin and relaxed mouth", + "tender direct gaze", + "sleepy post-orgasm look", + "messy but satisfied stare", + "quiet intimate expression", + "soft cleanup-focused gaze" + ], "hardcore_penetration_expressions": [ "controlled eye contact during penetration", "focused adult pleasure face during thrusting", @@ -483,6 +527,56 @@ {"text": "close candid creator-shot frame centered on undressing and body contact", "min_people": 2, "max_people": 3}, {"text": "full-body pre-sex foreplay frame with faces, hands, and clothes readable", "min_people": 2, "max_people": 3} ], + "manual_stimulation_compositions": [ + {"text": "close crop on hands, open thighs, and manual contact", "min_people": 1, "max_people": 3}, + {"text": "bed-edge manual-stimulation frame with fingers and face readable", "min_people": 1, "max_people": 3}, + {"text": "mirror-view manual contact composition with hands centered", "min_people": 1, "max_people": 3}, + {"text": "side-profile hand-between-thighs composition", "min_people": 1, "max_people": 3}, + {"text": "overhead manual-stimulation frame with body geometry clear", "min_people": 1, "max_people": 3}, + {"text": "tight creator-shot crop centered on fingers, thighs, and reaction", "min_people": 1, "max_people": 3}, + {"text": "seated lap manual contact frame", "min_people": 2, "max_people": 3}, + {"text": "full-body manual-stimulation composition with hands and expression visible", "min_people": 1, "max_people": 3} + ], + "interaction_compositions": [ + {"text": "close body-interaction frame with hands, faces, and exposed skin readable", "min_people": 2, "max_people": 3}, + {"text": "standing hands-on-body composition with clear body contact", "min_people": 2, "max_people": 3}, + {"text": "bed-edge transition frame with clothing movement and hand placement visible", "min_people": 2, "max_people": 3}, + {"text": "mirror-view interaction composition with bodies and gestures readable", "min_people": 2, "max_people": 3}, + {"text": "tight crop on guidance hands, face, waist, and hips", "min_people": 2, "max_people": 3}, + {"text": "wall-pressed body-control frame with hands and reaction visible", "min_people": 2, "max_people": 3}, + {"text": "couch body-worship composition with mouth, hands, and skin centered", "min_people": 2, "max_people": 3}, + {"text": "full-body transition composition showing the next position clearly", "min_people": 2, "max_people": 3} + ], + "camera_performance_compositions": [ + {"text": "direct-to-camera body presentation with hands and exposed skin centered", "min_people": 1, "max_people": 3}, + {"text": "mirror creator-performance frame with the body presented to the viewer", "min_people": 1, "max_people": 3}, + {"text": "low phone-angle reveal with hands framing the body", "min_people": 1, "max_people": 3}, + {"text": "bed-edge camera presentation with direct eye contact", "min_people": 1, "max_people": 3}, + {"text": "partner-held presentation frame with the body opened toward the camera", "min_people": 2, "max_people": 3}, + {"text": "tight subscriber-view crop centered on presentation gesture", "min_people": 1, "max_people": 3}, + {"text": "vertical creator-shot frame with body display and face readable", "min_people": 1, "max_people": 3}, + {"text": "wide creator-performance frame with hands, hips, and camera awareness visible", "min_people": 1, "max_people": 3} + ], + "group_coordination_compositions": [ + {"text": "wide group coordination frame with watching and touching roles readable", "min_people": 3}, + {"text": "center-body group frame with partners arranged around the subject", "min_people": 3}, + {"text": "mirror-view group interaction showing observer and touching roles", "min_people": 3}, + {"text": "bed-level group coordination composition with hands and faces visible", "min_people": 3}, + {"text": "three-person close frame with one watching and one touching", "min_people": 3, "max_people": 3}, + {"text": "full-room group interaction frame with clear role spacing", "min_people": 3}, + {"text": "side-profile group presentation frame", "min_people": 3}, + {"text": "overhead group coordination frame with bodies separated clearly", "min_people": 3} + ], + "aftercare_compositions": [ + {"text": "post-sex close body-contact frame with hands and faces readable", "min_people": 2}, + {"text": "bed-edge cleanup composition with towel, skin, and aftermath detail visible", "min_people": 2}, + {"text": "side-lying aftercare frame with bodies held close", "min_people": 2}, + {"text": "mirror-view aftermath composition with relaxed bodies and cleanup detail", "min_people": 2}, + {"text": "tight crop on towel, hands, thighs, and spent faces", "min_people": 2}, + {"text": "wide aftermath frame with rumpled sheets and discarded clothing", "min_people": 2}, + {"text": "couch post-sex cuddle composition", "min_people": 2}, + {"text": "shower-bench cleanup frame with hands and wet skin visible", "min_people": 2} + ], "hardcore_explicit_compositions": [ {"text": "full-body explicit sex frame with all adult bodies visible", "min_people": 2}, {"text": "bed-level camera angle focused on genital contact and faces", "min_people": 2, "max_people": 3}, diff --git a/categories/sexual_poses.json b/categories/sexual_poses.json index 47150bf..6138acb 100644 --- a/categories/sexual_poses.json +++ b/categories/sexual_poses.json @@ -203,6 +203,746 @@ ] } }, + { + "name": "Manual stimulation", + "slug": "manual_stimulation", + "min_people": 1, + "min_women": 1, + "inherit_expressions": false, + "inherit_compositions": false, + "weight": 0.85, + "item_label": "Manual action", + "positive_suffix": "Use clear adult manual contact, readable hands, explicit body positioning, exposed skin, warm erotic lighting, crisp comic linework, detailed hatching, and tactile textured paper.", + "prompt_template": "{subject_phrase}, all 21+ consenting adults: {style}. Cast: {cast_summary}. Role graph: {role_graph} Manual action: {item}. Setting: {scene}. Composition: {composition}. Facial expressions: {expression}. Make the scene explicit through adult manual stimulation, visible hands, exposed skin, clear body positioning, and readable reaction. {positive_suffix} Avoid: {negative_prompt}.", + "caption_template": "{trigger}, {scene_kind}, {cast_summary}, {role_graph}, manual stimulation action: {item}, {scene}, {composition}, explicit consensual adult manual stimulation illustration", + "scene_pools": ["hardcore_private_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"], + "expression_pools": ["hardcore_manual_expressions"], + "composition_pools": ["manual_stimulation_compositions"], + "item_templates": [ + "{manual_act} in {position}, with {manual_detail}, {body_contact}, and {visibility}", + "{position} featuring {manual_act}, {hand_detail}, {reaction_detail}, and {visibility}", + "{manual_act} on {surface}, with {manual_detail}, {hand_detail}, and {reaction_detail}", + "manual stimulation setup: {position}, {manual_act}, {body_contact}, and {visibility}", + "{position} while {manual_act}, with {hand_detail}, {manual_detail}, and {reaction_detail}" + ], + "item_axes": { + "position": [ + "reclining open-thigh manual position", + "bed-edge fingering position", + "seated lap manual stimulation position", + "standing wall-braced manual position", + "side-lying clit-rubbing position", + "mirror-facing mutual masturbation position", + "kneeling hand-between-thighs position", + "couch manual stimulation position" + ], + "manual_act": [ + "fingering with fingers working inside the pussy", + "two fingers sliding into the pussy while the other hand holds the thigh open", + "clit rubbing with fingers moving over the clit", + "slow clit stimulation while thighs stay open", + "hand on pussy with fingers spreading and rubbing", + "mutual masturbation with both bodies touching themselves", + "one partner guiding the other's hand between the thighs", + "partner-held vibrator pressed to the clit", + "toy-assisted manual stimulation with one hand controlling the toy", + "wet fingers moving between the thighs" + ], + "manual_detail": [ + "fingers visibly pressing into wet skin", + "hand placement centered between the open thighs", + "one hand holding the thigh open", + "thumb circling the clit", + "fingers sliding against the pussy", + "wet shine on fingers and inner thighs", + "hand guided firmly into place", + "toy and fingers both visible at the contact point" + ], + "hand_detail": [ + "one hand braced on the hip", + "one hand gripping the sheets", + "hands spreading thighs apart", + "fingers hooked at the inner thigh", + "one hand holding the wrist in place", + "both hands visible and active", + "fingers pressing into soft skin", + "hand resting on the lower belly" + ], + "body_contact": [ + "thighs held open", + "hips tilted toward the hand", + "knees spread with the hand centered", + "body arched into the touch", + "legs parted around the active hand", + "torso leaning back with hips exposed", + "bodies pressed close while one hand works", + "one partner leaning over the other" + ], + "reaction_detail": [ + "breathless open mouth", + "focused direct eye contact", + "eyes half-closed from the touch", + "bitten-lip reaction", + "hips lifting toward the hand", + "strained moan with flushed cheeks", + "messy aroused expression", + "controlled pleasure stare" + ], + "visibility": [ + "hands and contact point clearly readable", + "manual stimulation visible between the thighs", + "open thighs and fingers centered", + "hands, pussy, and reaction visible", + "toy or fingers clearly visible", + "body position and hand action readable" + ], + "surface": [ + "rumpled bed sheets", + "a wide couch", + "a hotel bed", + "floor cushions", + "a low mattress", + "a mirror-side bench", + "a soft rug", + "a private shower bench" + ] + } + }, + { + "name": "Body worship and touching", + "slug": "body_worship_touching", + "min_people": 2, + "min_women": 1, + "inherit_expressions": false, + "inherit_compositions": false, + "weight": 0.7, + "item_label": "Body interaction", + "positive_suffix": "Use readable adult body contact, hands and mouth on skin, exposed skin, warm erotic lighting, crisp comic linework, detailed hatching, and tactile textured paper.", + "prompt_template": "{subject_phrase}, all 21+ consenting adults: {style}. Cast: {cast_summary}. Role graph: {role_graph} Body interaction: {item}. Setting: {scene}. Composition: {composition}. Facial expressions: {expression}. Make the scene explicit through adult body worship, close skin contact, mouth and hand placement, exposed skin, and readable body positioning. {positive_suffix} Avoid: {negative_prompt}.", + "caption_template": "{trigger}, {scene_kind}, {cast_summary}, {role_graph}, body worship action: {item}, {scene}, {composition}, explicit consensual adult body-contact illustration", + "scene_pools": ["hardcore_private_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"], + "expression_pools": ["hardcore_interaction_expressions"], + "composition_pools": ["interaction_compositions"], + "item_templates": [ + "{worship_act} in {position}, with {touch_detail}, {face_detail}, and {visibility}", + "{position} featuring {worship_act}, {body_contact}, {touch_detail}, and {reaction_detail}", + "{worship_act} on {surface}, with {body_contact}, {face_detail}, and {visibility}", + "body worship setup: {position}, {worship_act}, {touch_detail}, and {reaction_detail}", + "{position} while {worship_act}, with {body_contact}, {face_detail}, and {visibility}" + ], + "item_axes": { + "position": [ + "reclining body-worship position", + "kneeling nipple-play position", + "bed-edge thigh-kissing body-worship position", + "mirror-facing ass-grab body-worship position", + "standing breast-touch position", + "bed-edge thigh-kissing position", + "side-lying caress position", + "mirror-facing ass-grab position", + "lap-sitting body-contact position", + "couch body-worship position" + ], + "worship_act": [ + "mouth kissing down the chest and stomach", + "nipple licking with one hand cupping the breast", + "nipple sucking while the other hand grips the waist", + "thigh kissing with mouth on inner thighs", + "mouth on inner thighs while hands hold the legs open", + "kissing inner thighs with hands holding the legs open", + "ass grabbing with fingers pressing into soft skin", + "mouth on the stomach while hands roam over hips", + "breast kissing while the body arches upward", + "slow body worship with hands tracing breasts, waist, and thighs", + "kissing across the hips and lower belly", + "face pressed against the body while hands hold the ass" + ], + "touch_detail": [ + "hands cupping breasts", + "fingers squeezing the ass", + "thumbs brushing nipples", + "hands sliding across the lower belly", + "fingers tracing the inner thighs", + "hands gripping the waist", + "one hand holding the chin in place", + "hands spreading the thighs gently" + ], + "face_detail": [ + "mouth pressed to skin", + "lips around a nipple", + "face close to the chest", + "cheek pressed against the stomach", + "mouth near the inner thigh", + "heavy eye contact while kissing the body", + "breath against exposed skin", + "tongue visible on skin" + ], + "body_contact": [ + "chest arched toward the mouth", + "thighs open around the kissing partner", + "hips tilted into the touch", + "body pressed against the wall", + "one body reclined while the other kneels close", + "torso bent toward the touch", + "bodies close enough for skin-on-skin pressure", + "legs draped around the partner" + ], + "reaction_detail": [ + "breathless parted lips", + "eyes half-closed from the touch", + "hands gripping sheets", + "flushed skin and direct eye contact", + "soft moan while being kissed", + "body arching into the mouth", + "head tilted back", + "controlled aroused stare" + ], + "visibility": [ + "mouth, hands, and exposed skin clearly readable", + "breasts, thighs, hands, and faces visible", + "body worship contact centered", + "skin contact and reaction visible", + "hands and mouth placement clear", + "full body-contact geography readable" + ], + "surface": [ + "rumpled bed sheets", + "a hotel bed", + "a wide couch", + "floor cushions", + "a soft rug", + "a mirror-side bench", + "a low mattress", + "a velvet chair" + ] + } + }, + { + "name": "Clothing and position transitions", + "slug": "clothing_position_transitions", + "min_people": 2, + "min_women": 1, + "inherit_expressions": false, + "inherit_compositions": false, + "weight": 0.65, + "item_label": "Transition action", + "positive_suffix": "Use readable adult movement, clothing being moved, hands guiding bodies, exposed skin, warm erotic lighting, crisp comic linework, detailed hatching, and tactile textured paper.", + "prompt_template": "{subject_phrase}, all 21+ consenting adults: {style}. Cast: {cast_summary}. Role graph: {role_graph} Transition action: {item}. Setting: {scene}. Composition: {composition}. Facial expressions: {expression}. Make the scene explicit through adult undressing, position changes, visible hands, exposed skin, and clear movement from one sexual beat to the next. {positive_suffix} Avoid: {negative_prompt}.", + "caption_template": "{trigger}, {scene_kind}, {cast_summary}, {role_graph}, clothing and position transition: {item}, {scene}, {composition}, explicit consensual adult transition illustration", + "scene_pools": ["hardcore_private_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"], + "expression_pools": ["hardcore_interaction_expressions"], + "composition_pools": ["interaction_compositions"], + "item_templates": [ + "{transition_act} in {position}, with {clothing_detail}, {hand_detail}, and {visibility}", + "{position} featuring {transition_act}, {body_contact}, {clothing_detail}, and {movement_detail}", + "{transition_act} on {surface}, with {hand_detail}, {body_contact}, and {visibility}", + "position transition: {position}, {transition_act}, {movement_detail}, and {clothing_detail}", + "{position} while {transition_act}, with {hand_detail}, {body_contact}, and {visibility}" + ], + "item_axes": { + "position": [ + "bed-edge clothing-removal position", + "standing turn-around transition", + "pulling-onto-the-bed transition", + "lifting-legs transition position", + "kneeling-to-standing transition", + "mirror undressing transition", + "couch position-change setup", + "floor-to-bed transition" + ], + "transition_act": [ + "pulling clothing aside before the next act", + "lower garments being pulled down below the hips", + "shirt being opened while bodies press together", + "one partner turning the other around by the hips", + "one partner pulling the other onto the bed", + "legs being lifted and spread into position", + "hips being guided backward into position", + "body being turned from kissing into a rear-facing pose", + "kneeling partner being guided upward by the hands", + "clothes being discarded beside the bodies" + ], + "clothing_detail": [ + "fabric bunched at the waist", + "straps sliding off shoulders", + "panties or lower garments pulled aside", + "shirt open with bare chest visible", + "skirt lifted high around the hips", + "trousers or underwear lowered below the hips", + "garment half removed and hanging from one leg", + "discarded clothing visible on the floor" + ], + "hand_detail": [ + "hands on hips guiding the turn", + "one hand lifting a thigh", + "hands pulling fabric aside", + "one hand on the lower back", + "hands spreading thighs into position", + "fingers hooked into the waistband", + "hands pulling the body closer", + "one hand braced on the bed" + ], + "body_contact": [ + "bodies pressed together during the position change", + "hips angled toward the next pose", + "legs lifted into the frame", + "knees moving apart", + "torso bent forward by the guiding hands", + "body rotated toward the camera", + "one body reclined while the other stands close", + "skin revealed as clothing moves" + ], + "movement_detail": [ + "movement frozen mid-transition", + "clear before-the-next-act body geometry", + "hands actively changing the pose", + "clothing motion visible", + "body weight shifting toward the bed", + "hips and legs visibly being repositioned", + "urgent consensual movement", + "slow teasing repositioning" + ], + "visibility": [ + "clothing movement and hands clearly readable", + "transition body geometry visible", + "fabric, exposed skin, and hand placement centered", + "pose change visible in one frame", + "the next position readable from the body angle", + "hands, hips, and clothing clearly visible" + ], + "surface": [ + "rumpled bed sheets", + "a hotel bed", + "a wide couch", + "a low mattress", + "floor cushions", + "a mirror-side bench", + "a soft rug", + "a dressing-room chair" + ] + } + }, + { + "name": "Dominant guidance and restraint", + "slug": "dominant_guidance", + "min_people": 2, + "min_women": 1, + "inherit_expressions": false, + "inherit_compositions": false, + "weight": 0.55, + "item_label": "Guidance action", + "positive_suffix": "Use consensual adult control, readable hand placement, clear body positioning, exposed skin, warm erotic lighting, crisp comic linework, detailed hatching, and tactile textured paper.", + "prompt_template": "{subject_phrase}, all 21+ consenting adults: {style}. Cast: {cast_summary}. Role graph: {role_graph} Guidance action: {item}. Setting: {scene}. Composition: {composition}. Facial expressions: {expression}. Make the scene explicit through consensual adult guidance, hair or wrist control, body positioning, visible hands, exposed skin, and clear power dynamic. {positive_suffix} Avoid: {negative_prompt}.", + "caption_template": "{trigger}, {scene_kind}, {cast_summary}, {role_graph}, dominant guidance action: {item}, {scene}, {composition}, explicit consensual adult power-dynamic illustration", + "scene_pools": ["hardcore_private_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"], + "expression_pools": ["hardcore_interaction_expressions"], + "composition_pools": ["interaction_compositions"], + "item_templates": [ + "{control_act} in {position}, with {hand_detail}, {body_contact}, and {visibility}", + "{position} featuring {control_act}, {power_detail}, {hand_detail}, and {reaction_detail}", + "{control_act} on {surface}, with {body_contact}, {power_detail}, and {visibility}", + "consensual control setup: {position}, {control_act}, {hand_detail}, and {reaction_detail}", + "{position} while {control_act}, with {power_detail}, {body_contact}, and {visibility}" + ], + "item_axes": { + "position": [ + "standing hair-holding position", + "bed-edge wrist-pinning position", + "kneeling guided-position position", + "wall-pinned body-control position", + "reclining wrists-overhead position", + "mirror-facing dominant guidance position", + "couch hands-on-hips position", + "close dirty-talk guidance position", + "floor-level guided pose" + ], + "control_act": [ + "hair held back while the body is guided closer", + "wrists pinned above the head on the bed", + "one hand holding the jaw while the other guides the hips", + "hands on hips turning the body into position", + "one partner spreading thighs with both hands", + "hair pulled back gently to expose the face", + "wrist held down while the body arches", + "dirty talk whispered close to the ear while one hand holds the waist", + "mouth near the ear giving verbal teasing while the body is held close", + "hands pressing the body into a wall-braced pose", + "chin lifted by fingers during a dominant stare", + "hips pulled back by both hands" + ], + "hand_detail": [ + "fingers tangled in hair", + "one hand wrapped around both wrists", + "hands gripping hips", + "one hand under the chin", + "hands spreading thighs", + "palm pressing between the shoulder blades", + "one hand braced near the head", + "one hand holding the body close during whispering", + "fingers pressing into the waist" + ], + "power_detail": [ + "consensual rough guidance", + "controlled dominant pacing", + "clear guided body position", + "submissive presenting posture", + "dominant hand placement visible", + "steady eye contact during control", + "body held open for the camera", + "dirty talk and verbal teasing visible through mouth-near-ear body language", + "commanding close-range tension" + ], + "body_contact": [ + "body arched under the guiding hands", + "hips pulled toward the partner", + "wrists held against the sheets", + "thighs spread by both hands", + "torso pressed toward the wall", + "body angled by the grip on the hips", + "knees separated while hands hold position", + "head tilted back by the hair hold" + ], + "reaction_detail": [ + "wide-eyed aroused stare", + "bitten-lip submission", + "steady dominant eye contact", + "breathless parted lips", + "flushed controlled expression", + "shameless direct gaze", + "eyes half-closed under control", + "strained moan with consent visible" + ], + "visibility": [ + "hands, wrists, hair, and body position clearly readable", + "control gesture visible without confusion", + "dominant hand placement centered", + "face, hands, and hips visible", + "the guided body position readable", + "consensual power dynamic clear in the pose" + ], + "surface": [ + "rumpled bed sheets", + "a hotel bed", + "against a wall", + "a wide couch", + "floor cushions", + "a low mattress", + "a mirror-side bench", + "a soft rug" + ] + } + }, + { + "name": "Camera performance and presentation", + "slug": "camera_performance", + "min_people": 1, + "min_women": 1, + "inherit_expressions": false, + "inherit_compositions": false, + "weight": 0.6, + "item_label": "Camera performance", + "positive_suffix": "Use creator-shot adult presentation, readable camera-facing pose, exposed skin, clear hand placement, warm erotic lighting, crisp comic linework, detailed hatching, and tactile textured paper.", + "prompt_template": "{subject_phrase}, all 21+ consenting adults: {style}. Cast: {cast_summary}. Role graph: {role_graph} Camera performance: {item}. Setting: {scene}. Composition: {composition}. Facial expressions: {expression}. Make the scene explicit through camera-aware adult presentation, body opened or displayed to the viewer, visible hands, exposed skin, and clean creator-shot framing. {positive_suffix} Avoid: {negative_prompt}.", + "caption_template": "{trigger}, {scene_kind}, {cast_summary}, {role_graph}, camera performance action: {item}, {scene}, {composition}, explicit consensual adult creator-performance illustration", + "scene_pools": ["hardcore_private_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"], + "expression_pools": ["hardcore_interaction_expressions"], + "composition_pools": ["camera_performance_compositions"], + "item_templates": [ + "{performance_act} in {position}, with {presentation_detail}, {hand_detail}, and {visibility}", + "{position} featuring {performance_act}, {camera_detail}, {presentation_detail}, and {reaction_detail}", + "{performance_act} on {surface}, with {hand_detail}, {camera_detail}, and {visibility}", + "creator-performance setup: {position}, {performance_act}, {presentation_detail}, and {reaction_detail}", + "{position} while {performance_act}, with {camera_detail}, {hand_detail}, and {visibility}" + ], + "item_axes": { + "position": [ + "reclining camera-presentation position", + "mirror spread-open presentation", + "standing show-to-camera position", + "bed-edge creator presentation", + "kneeling close-camera reveal", + "side-lying camera-facing display", + "partner-held presentation position", + "couch camera-performance position" + ], + "performance_act": [ + "body presented directly to the camera", + "spreading open for the camera with hands visible", + "partner holding the body open for the camera", + "looking into the camera while exposing the body", + "mirror-facing creator reveal with phone-angle intimacy", + "one hand pointing or guiding attention to the body", + "teasing the camera while a partner watches", + "showing the next action to the camera", + "hands framing breasts, hips, and thighs for the viewer", + "body angled to keep the erotic focus visible" + ], + "presentation_detail": [ + "direct eye contact with the lens", + "hands framing the exposed body", + "body opened toward the viewer", + "hips tilted toward the camera", + "legs placed to keep the body readable", + "partner's hands presenting the body", + "mirror reflection doubling the reveal", + "phone-camera intimacy implied by the framing" + ], + "camera_detail": [ + "creator-shot framing", + "close subscriber-view angle", + "mirror-camera presentation", + "low phone angle", + "tight handheld crop", + "vertical feed-style framing", + "direct-to-camera performance", + "camera-aware body display" + ], + "hand_detail": [ + "hands holding thighs open", + "one hand on the camera-facing hip", + "hands framing breasts", + "partner's hands on the waist", + "one hand pulling fabric aside", + "fingers spread over the lower belly", + "hands braced beside the body", + "one hand touching the face while looking at the camera" + ], + "reaction_detail": [ + "confident direct stare", + "shameless camera-aware grin", + "breathless close-camera expression", + "heavy-lidded creator gaze", + "teasing open mouth", + "controlled performance stare", + "flushed direct eye contact", + "knowing subscriber-camera expression" + ], + "visibility": [ + "camera-facing action clearly readable", + "hands, exposed skin, and body opening centered", + "presentation gesture visible", + "body display and camera awareness clear", + "partner hands and creator gaze visible", + "mirror or lens-directed pose readable" + ], + "surface": [ + "rumpled bed sheets", + "a hotel bed", + "a mirror-side bench", + "a wide couch", + "floor cushions", + "a low mattress", + "a soft rug", + "a private shower bench" + ] + } + }, + { + "name": "Group coordination and watching", + "slug": "group_coordination", + "min_people": 3, + "inherit_expressions": false, + "inherit_compositions": false, + "weight": 0.55, + "item_label": "Group interaction", + "positive_suffix": "Use readable adult group coordination, clear body spacing, visible watching/touching roles, exposed skin, warm erotic lighting, crisp comic linework, detailed hatching, and tactile textured paper.", + "prompt_template": "{subject_phrase}, all 21+ consenting adults: {style}. Cast: {cast_summary}. Role graph: {role_graph} Group interaction: {item}. Setting: {scene}. Composition: {composition}. Facial expressions: {expression}. Make the scene explicit through adult group coordination, watching, guiding hands, body presentation, exposed skin, and clear role spacing. {positive_suffix} Avoid: {negative_prompt}.", + "caption_template": "{trigger}, {scene_kind}, {cast_summary}, {role_graph}, group coordination action: {item}, {scene}, {composition}, explicit consensual adult group-interaction illustration", + "scene_pools": ["hardcore_group_scenes", "hardcore_private_scenes"], + "expression_pools": ["hardcore_group_expressions"], + "composition_pools": ["group_coordination_compositions"], + "item_templates": [ + "{coordination_act} with {arrangement}, {touch_detail}, {reaction_detail}, and {visibility}", + "{arrangement} featuring {coordination_act}, {body_contact}, {watching_detail}, and {visibility}", + "{coordination_act} on {surface}, with {touch_detail}, {watching_detail}, and {body_contact}", + "group coordination setup: {arrangement}, {coordination_act}, {watching_detail}, and {visibility}", + "{arrangement} while {coordination_act}, with {touch_detail}, {reaction_detail}, and {visibility}" + ], + "item_axes": { + "arrangement": [ + "one central body with partners arranged around them", + "one partner watching while another touches the central body", + "two partners guiding the central body into position", + "one partner behind and one partner in front without penetration", + "a waiting-turn arrangement beside the bed", + "partners framing the body from both sides", + "one partner kneeling while another stands close", + "mirror-view group coordination arrangement" + ], + "coordination_act": [ + "one partner watches while another caresses the body", + "two partners hold the body open for the camera", + "one partner kisses while another touches breasts and hips", + "partners take turns touching and presenting the central body", + "one partner guides the face while another guides the hips", + "watching partner keeps a hand on the shoulder", + "two partners coordinate hands across breasts, waist, and thighs", + "one partner waits close while the other controls the pose" + ], + "touch_detail": [ + "hands on breasts, hips, and thighs", + "one hand holding the chin", + "hands spreading thighs", + "one partner gripping the waist", + "hands framing the exposed body", + "one partner touching from behind", + "fingers tangled in hair", + "one hand braced on the bed" + ], + "watching_detail": [ + "watching partner keeps eye contact", + "one partner looks down at the action", + "waiting partner stays close in frame", + "side partner watches with hands on skin", + "partners exchange direct looks", + "one partner watches from beside the bed", + "mirror reflection shows the observer", + "all faces remain readable" + ], + "body_contact": [ + "central body held open", + "bodies pressed around the center", + "partners close enough to touch from both sides", + "central hips angled toward the camera", + "knees spread by guiding hands", + "skin-on-skin contact from multiple sides", + "body framed by surrounding hands", + "clear spacing between each role" + ], + "reaction_detail": [ + "mixed hungry stares", + "central body flushed and breathless", + "watching partner focused and close", + "several direct camera-aware looks", + "one partner smiling while another concentrates", + "shared aroused expressions", + "heavy-lidded group tension", + "focused adult anticipation" + ], + "visibility": [ + "all roles readable in one frame", + "watching, touching, and presenting roles clear", + "hands and faces visible across the group", + "central body and surrounding partners visible", + "group spacing clear without action confusion", + "body presentation and observer reaction visible" + ], + "surface": [ + "rumpled bed sheets", + "a hotel bed", + "floor cushions", + "a wide couch", + "a low mattress", + "a velvet lounge", + "a soft rug", + "a private suite floor" + ] + } + }, + { + "name": "Aftercare and cleanup", + "slug": "aftercare_cleanup", + "min_people": 2, + "inherit_expressions": false, + "inherit_compositions": false, + "weight": 0.35, + "item_label": "Aftermath interaction", + "positive_suffix": "Use adult post-sex intimacy, readable bodies and hands, visible aftermath details, warm erotic lighting, crisp comic linework, detailed hatching, and tactile textured paper.", + "prompt_template": "{subject_phrase}, all 21+ consenting adults: {style}. Cast: {cast_summary}. Role graph: {role_graph} Aftermath interaction: {item}. Setting: {scene}. Composition: {composition}. Facial expressions: {expression}. Make the scene explicit through adult post-sex closeness, cleanup, visible skin, relaxed body contact, aftermath details, and readable hands and faces. {positive_suffix} Avoid: {negative_prompt}.", + "caption_template": "{trigger}, {scene_kind}, {cast_summary}, {role_graph}, aftercare and cleanup action: {item}, {scene}, {composition}, explicit consensual adult post-sex aftermath illustration", + "scene_pools": ["hardcore_climax_scenes", "hardcore_bed_scenes", "hardcore_private_scenes"], + "expression_pools": ["hardcore_aftercare_expressions"], + "composition_pools": ["aftercare_compositions"], + "item_templates": [ + "{aftercare_act} in {position}, with {cleanup_detail}, {body_contact}, and {visibility}", + "{position} featuring {aftercare_act}, {touch_detail}, {cleanup_detail}, and {reaction_detail}", + "{aftercare_act} on {surface}, with {body_contact}, {touch_detail}, and {visibility}", + "post-sex aftermath setup: {position}, {aftercare_act}, {cleanup_detail}, and {reaction_detail}", + "{position} while {aftercare_act}, with {touch_detail}, {body_contact}, and {visibility}" + ], + "item_axes": { + "position": [ + "reclining post-sex cuddle position", + "bed-edge cleanup position", + "side-lying aftercare position", + "kneeling towel-cleanup position", + "mirror aftermath position", + "couch post-sex closeness position", + "lap-held aftercare position", + "shower-bench cleanup position" + ], + "aftercare_act": [ + "kissing after sex with bodies still close", + "one partner wiping skin with a towel", + "post-sex cuddle with hands on the body", + "one partner checking the other's face while holding them close", + "cleanup with a wet cloth across the thighs", + "exhausted bodies resting together after orgasm", + "one partner kissing cum or sweat from skin", + "gentle caressing after the explicit act", + "bodies still tangled in the aftermath", + "one partner holding the other against the chest" + ], + "cleanup_detail": [ + "towel visible in one hand", + "wet cloth wiping skin", + "aftermath fluids still visible on skin", + "rumpled sheets and discarded clothing nearby", + "hands wiping thighs and belly", + "skin shiny with sweat and aftermath", + "one hand smoothing hair away from the face", + "messy bedding and relaxed limbs" + ], + "touch_detail": [ + "hands resting on the lower back", + "one hand cupping the face", + "fingers brushing hair aside", + "hands wrapped around the waist", + "one hand on the thigh", + "bodies held chest to chest", + "gentle hand on the stomach", + "arms wrapped around shoulders" + ], + "body_contact": [ + "bodies lying close together", + "legs tangled on the sheets", + "one body curled against the other", + "skin pressed together in relaxed contact", + "one partner kneeling close with a towel", + "thighs relaxed and open after the scene", + "body resting against a partner's chest", + "both bodies exhausted but close" + ], + "reaction_detail": [ + "spent satisfied expression", + "soft post-sex eye contact", + "breathless relaxed face", + "dazed afterglow stare", + "small exhausted smile", + "heavy-lidded calm expression", + "flushed skin and relaxed mouth", + "tender direct gaze" + ], + "visibility": [ + "aftercare gesture clearly visible", + "cleanup object and body contact readable", + "hands, faces, and aftermath details visible", + "post-sex closeness centered", + "towel or cloth action clear", + "relaxed bodies and visible skin readable" + ], + "surface": [ + "rumpled bed sheets", + "a hotel bed", + "a wide couch", + "floor cushions", + "a low mattress", + "a shower bench", + "a soft rug", + "a velvet chaise" + ] + } + }, { "name": "Penetrative sex", "slug": "penetrative_sex", diff --git a/docs/prompt-pool-routing-map.md b/docs/prompt-pool-routing-map.md index 081da66..61fe83a 100644 --- a/docs/prompt-pool-routing-map.md +++ b/docs/prompt-pool-routing-map.md @@ -85,6 +85,7 @@ These recipes identify the intended road before editing prompt text. | Keep character/location but change only sexual pose | `Global Seed` or fixed seed config -> builder/pair | Keep `person_seed` and `scene_seed` fixed; change `pose_seed` and usually `role_seed`; for hardcore categories check `content_seed_axis` | `sexual_poses.json`, `hardcore_position_config`, Krea `_hardcore_action_sentence` | | Generate a specific hardcore oral/blowjob scene | `Hardcore Position Pool` -> `Hardcore Action Filter` -> `Insta/OF Prompt Pair` or `Prompt Builder` | Use `focus=oral_only` or disable non-oral families; keep `allow_oral=true`; constrain position pool to kneeling/standing/oral variants when needed | `sexual_poses.json` oral subcategory/templates, `_apply_hardcore_position_config_to_subcategory`, `_hardcore_action_sentence` | | Generate POV oral or POV penetration | `Man Slot` with POV presence -> `character_cast` -> pair/builder -> Krea2 formatter | POV man must be in the cast; use metadata into Krea2; normal camera directive is suppressed by POV | `_pov_hardcore_pose_sentence`, `_pov_action_phrase`, `_cast_prose` omit-label handling | +| Generate porn-scene interaction beats | `Hardcore Position Pool` -> `Hardcore Action Filter` -> pair/builder | Use `focus=interaction_only` for kissing/body worship/transitions/guidance/camera/watching/aftercare, or `focus=manual_only` for fingering/clit/manual stimulation; constrain keys such as `camera_showing`, `wrist_pinning`, `fingering`, `aftercare` | `sexual_poses.json` interaction/manual subcategories, `_role_graph`, Krea `_is_foreplay_text` / `_hardcore_action_sentence` | | Same woman, same room, softcore and hardcore outputs | `Character Slot/Profile` -> `Insta/OF Options` -> `Insta/OF Prompt Pair` | `continuity=same_creator_same_room`; set `softcore_cast` as needed; use pair metadata into formatter | `build_insta_of_pair`, `softcore_row`, `hardcore_row`, pair metadata fields | | Same cast in softcore and hardcore | Character slot chain -> `Insta/OF Options` | `softcore_cast=same_as_hardcore`; configure partner slots/outfits if needed | `_insta_of_partner_styling`, character slot clothing, pair Krea branch | | Change only outfit/clothing | Character clothing or category content route | Keep `person_seed`, `scene_seed`, `pose_seed`; change `content_seed`; slot `softcore_outfit` overrides Insta/OF outfit | `SxCP Character Clothing`, `INSTA_OF_SOFTCORE_OUTFITS`, category item templates | @@ -205,7 +206,7 @@ This table is the first stop when the selected content is wrong. | `default_categories.json` men casual subcategories | Male casual outfit/items and men-specific casual pools | Same as above | Medium if men are part of a mixed cast and clothing detail is too strong | | `default_categories.json` couple casual subcategories | Couple outfit/action-ish soft poses and couple pools | Same as above | Medium because labels and partner styling can duplicate pair mode | | `erotic_clothes.json` | Provocative/erotic clothing categories and softcore creator scenes | `content`, `scene`, `expression`, `composition` | Medium because nude/implied-nude wording can conflict with clothes | -| `sexual_poses.json` foreplay/oral/outercourse/penetration/etc. | Hardcore action item templates, role graphs, axis values, hardcore pool references | `pose` for pose-content route, also `role`; sometimes `content` aliases matter | High because Krea2 rewrites action and POV position text | +| `sexual_poses.json` foreplay/interaction/manual/oral/outercourse/penetration/etc. | Hardcore action and porn-scene interaction templates, role graphs, axis values, hardcore pool references | `pose` for pose-content route, also `role`; sometimes `content` aliases matter | High because Krea2 rewrites action and POV position text | | `location_pools.json` | Reusable scene pools and legacy scene extensions | `scene` | Medium when a camera-aware adapter changes scene/composition wording | | `expression_composition_pools.json` | Reusable expressions and framing/composition pools | `expression`, `composition` | Medium because formatter may label or suppress expressions | | `generate_prompt_batches.py` legacy pools | Built-in generator clothing, pose, expression, scene, composition lists | Main row seed plus axis config through legacy adapter | Medium because legacy prompt format is field-label heavy | @@ -268,6 +269,10 @@ Edit targets: - Normal pose pools: legacy `g.POSES`, `g.EVOCATIVE_POSES`, or JSON `poses`. - Hardcore positions/actions: `categories/sexual_poses.json`. +- Hardcore interaction beats: `categories/sexual_poses.json` subcategories + `foreplay_teasing`, `manual_stimulation`, `body_worship_touching`, + `clothing_position_transitions`, `dominant_guidance`, + `camera_performance`, `group_coordination`, and `aftercare_cleanup`. - Position filtering UI: `build_hardcore_position_pool_json`, `build_hardcore_action_filter_json`, `_apply_hardcore_position_config_to_subcategory`. - Krea2 action rewrite, POV position rewrite, cleanup: `krea_formatter.py`. @@ -358,8 +363,8 @@ Hardcore row: - Category is always `Hardcore sexual poses`. - Cast count comes from `SxCP Insta/OF Options`. -- Position/action can be constrained by `SxCP Hardcore Position Pool` and - `SxCP Hardcore Action Filter`. +- Position/action/interaction can be constrained by `SxCP Hardcore Position + Pool` and `SxCP Hardcore Action Filter`. - Clothing comes from character slot hardcore clothing first, then fallback `hardcore_clothing_continuity`. - Men receive default hardcore clothing if visible and not configured. @@ -410,7 +415,7 @@ plain prompt text. When debugging, inspect these fields before editing pools. | `character_cast_slots` | Character slot chain | POV/camera/formatters | Raw configured slots. | | `character_slot_status`, `character_profile_status` | Character/profile application | Debug | Explains whether slot/profile was applied or skipped. | | `pov_character_labels` | Character slot presence mode | Krea/prompt/camera | Labels omitted from visible cast and rewritten as first-person POV. | -| `hardcore_position_config` | Hardcore position/filter nodes | Debug | Active hardcore family/position/action constraints. | +| `hardcore_position_config` | Hardcore position/filter nodes | Debug | Active hardcore family/position/action/interaction constraints, including `interaction_only` and `manual_only`. | | `negative_prompt` | Category/pair/default negative route | Formatter output | Base negative text before formatter extras. | | `trigger` | Builder input | Formatter/fallback/debug | Active trigger after fallback to default. | @@ -453,11 +458,40 @@ flowchart TD What each part owns: - `sexual_poses.json`: available positions, families, action templates, role - graph templates, and action-specific pool references. + graph templates, interaction templates, and action-specific pool references. - `prompt_builder.py`: filters which templates/axes remain available. - `krea_formatter.py`: rewrites the selected action into model-readable prose, including POV variants and cleanup. +Current broad hardcore families: + +| Family / focus | Subcategories | +| --- | --- | +| `penetrative` / `penetration_only` | `penetrative_sex` | +| `foreplay` / `foreplay_only` | `foreplay_teasing` | +| `interaction` / `interaction_only` | `foreplay_teasing`, `body_worship_touching`, `clothing_position_transitions`, `dominant_guidance`, `camera_performance`, `group_coordination`, `aftercare_cleanup` | +| `manual` / `manual_only` | `manual_stimulation` | +| `oral` / `oral_only` | `oral_sex` | +| `outercourse` / `outercourse_only` | `outercourse_sex`, `manual_stimulation` | +| `anal` / `anal_only` | `anal_double_penetration` | +| `climax` / `climax_only` | `cumshot_climax` | +| `threesome` / `threesome_only` | `threesomes` | +| `group` / `group_only` | `group_sex_orgy` | + +The action filter also has independent gates for toys, double-contact, +penetration, foreplay, interaction, manual stimulation, oral, outercourse, anal, +and climax. Keep `allow_interaction=true` when using the broader interaction +family; keep `allow_manual=true` when manual stimulation should remain possible. +`allow_anal=false` blocks anal-sex wording, not ordinary ass-touching interaction +phrases such as ass grabbing or body worship. + +Interaction selector keys include kissing/caressing/undressing, body worship, +nipple play, ass grabbing, thigh kissing, hair holding, wrist pinning, dirty +talk, position transitions, guided positioning, camera presentation, watching, +aftercare, cleanup, fingering, clit rubbing, and mutual masturbation. These keys +are still routed through `hardcore_position_config.positions`, so they are +controlled by the same `pose`/`role` debug path as other hardcore action keys. + If one action keeps recurring, inspect: 1. The enabled position family/action flags. @@ -614,6 +648,7 @@ or pool appears there but not in this map, update the relevant route table. | Wrong expression intensity | Character slot expression settings, `_expression_entries_for_intensity`, expression pools. | | Expression appears when disabled | `_disable_row_expression`, formatter expression extraction. | | Same hardcore action repeats | Hardcore filter config, `sexual_poses.json` weights, `_apply_hardcore_position_config_to_subcategory`. | +| Hardcore interaction beat falls back to penetration/oral | `sexual_poses.json` interaction subcategory, `_role_graph`, and Krea `_is_foreplay_text` / `_hardcore_pose_anchor`. | | Raw hardcore prompt position is vague | `sexual_poses.json` item templates and role graph templates. | | Krea2 hardcore prompt position is vague | `_hardcore_action_sentence` or `_pov_hardcore_pose_sentence`. | | Man appears described in POV | POV labels, `_cast_prose` omit labels, `_pov_action_phrase`. | diff --git a/krea_formatter.py b/krea_formatter.py index 65fe847..16afcba 100644 --- a/krea_formatter.py +++ b/krea_formatter.py @@ -839,6 +839,17 @@ def _is_outercourse_text(*parts: Any) -> bool: "hand stroking", "hand wraps around", "manual stimulation", + "fingering", + "fingers inside", + "fingers in pussy", + "hand on pussy", + "fingers on pussy", + "fingers sliding against the pussy", + "open-thigh manual", + "clit rubbing", + "clit", + "clitoris", + "mutual masturbation", "footjob", "soles wrap around", "soles", @@ -904,6 +915,51 @@ def _is_foreplay_text(*parts: Any) -> bool: "pulling clothing", "sliding straps", "unbuttoning", + "body worship", + "nipple", + "mouth on skin", + "kissing down", + "ass grabbing", + "gripping the ass", + "thigh kissing", + "inner thighs", + "hair held", + "holding hair", + "hair pulled back", + "wrist", + "wrists", + "pinning", + "guided", + "guiding", + "turning the body", + "position transition", + "pulling onto the bed", + "lifting and spreading", + "spreading thighs", + "dirty talk", + "whispering", + "camera performance", + "presented directly to the camera", + "present her body", + "showing to camera", + "spread open for the camera", + "watching partner", + "waiting turn", + "group coordination", + "aftercare", + "cleanup", + "wiping", + "towel", + "post-sex", + "fingering", + "fingers inside", + "hand on pussy", + "fingers on pussy", + "clit rubbing", + "clit", + "clitoris", + "manual stimulation", + "mutual masturbation", ) ) diff --git a/prompt_builder.py b/prompt_builder.py index d99b526..206f76d 100644 --- a/prompt_builder.py +++ b/prompt_builder.py @@ -300,6 +300,8 @@ HARDCORE_POSITION_FAMILY_CHOICES = [ "any", "penetrative", "foreplay", + "interaction", + "manual", "oral", "outercourse", "anal", @@ -311,6 +313,8 @@ HARDCORE_POSITION_FOCUS_CHOICES = [ "keep_pool", "penetration_only", "foreplay_only", + "interaction_only", + "manual_only", "oral_only", "outercourse_only", "anal_only", @@ -341,6 +345,22 @@ HARDCORE_POSITION_KEY_CHOICES = [ "breast_touch", "face_touch", "undressing", + "body_worship", + "nipple_play", + "ass_grab", + "thigh_kissing", + "hair_holding", + "wrist_pinning", + "dirty_talk", + "position_transition", + "guided_positioning", + "camera_showing", + "watching", + "aftercare", + "cleanup", + "fingering", + "clit_rubbing", + "mutual_masturbation", "boobjob", "testicle_sucking", "penis_licking", @@ -353,17 +373,34 @@ HARDCORE_POSITION_FAMILY_SUBCATEGORIES = { "any": [ "penetrative_sex", "foreplay_teasing", + "body_worship_touching", + "clothing_position_transitions", + "dominant_guidance", + "camera_performance", + "manual_stimulation", "oral_sex", "outercourse_sex", "anal_double_penetration", "threesomes", + "group_coordination", "group_sex_orgy", "cumshot_climax", + "aftercare_cleanup", ], "penetrative": ["penetrative_sex"], "foreplay": ["foreplay_teasing"], + "interaction": [ + "foreplay_teasing", + "body_worship_touching", + "clothing_position_transitions", + "dominant_guidance", + "camera_performance", + "group_coordination", + "aftercare_cleanup", + ], + "manual": ["manual_stimulation"], "oral": ["oral_sex"], - "outercourse": ["outercourse_sex"], + "outercourse": ["outercourse_sex", "manual_stimulation"], "anal": ["anal_double_penetration"], "climax": ["cumshot_climax"], "threesome": ["threesomes"], @@ -392,6 +429,22 @@ HARDCORE_POSITION_KEY_MATCHES = { "breast_touch": ("breast", "breasts", "nipple", "cupping breasts", "touching breasts"), "face_touch": ("face", "cheek", "jaw", "chin", "hand on the cheek", "fingers under the chin"), "undressing": ("undressing", "removing clothing", "removing clothes", "pulling clothing", "sliding straps", "unbuttoning"), + "body_worship": ("body worship", "worship", "kissing down", "mouth on skin", "kissing the body"), + "nipple_play": ("nipple", "nipples", "licking nipples", "sucking nipples", "nipple play"), + "ass_grab": ("ass grab", "ass-grab", "ass grabbing", "hand on the ass", "squeezing the ass"), + "thigh_kissing": ("thigh kiss", "thigh kissing", "kissing thighs", "mouth on inner thighs"), + "hair_holding": ("hair holding", "hair held", "holding hair", "hair pulled back"), + "wrist_pinning": ("wrist", "wrists", "pinning wrists", "wrists pinned", "hands pinned"), + "dirty_talk": ("dirty talk", "whispering", "mouth near the ear", "telling", "verbal teasing"), + "position_transition": ("transition", "turning around", "pulling onto the bed", "moving into position", "position change"), + "guided_positioning": ("guiding", "guided", "guides", "lifting legs", "spreading thighs", "pulling hips", "turning the body"), + "camera_showing": ("camera", "showing to camera", "presenting to camera", "spread open for camera", "creator-shot"), + "watching": ("watching", "voyeur", "waiting turn", "partner watches", "onlooker"), + "aftercare": ("aftercare", "cuddling", "kissing after", "holding close", "post-sex"), + "cleanup": ("cleanup", "wiping", "cleaning", "towel", "wet cloth"), + "fingering": ("fingering", "fingers inside", "fingers in pussy", "finger stimulation"), + "clit_rubbing": ("clit", "clitoris", "clit rubbing", "rubbing the clit", "fingers on clit"), + "mutual_masturbation": ("mutual masturbation", "both touching themselves", "masturbating together", "hands on their own bodies"), "boobjob": ("boobjob", "titjob", "breast-sex", "breast sex"), "testicle_sucking": ("testicle", "balls-licking", "balls licking", "balls and mouth"), "penis_licking": ("penis-licking", "penis licking", "tongue along", "tongue licking"), @@ -400,7 +453,23 @@ HARDCORE_POSITION_KEY_MATCHES = { "open_thighs": ("thighs open", "legs spread", "open thighs", "legs open", "reclining with thighs open"), "front_back": ("front-and-back", "front and back", "one behind and one in front", "between two partners"), } -HARDCORE_POSITION_AXIS_KEYS = {"position", "body_position", "body_arrangement", "arrangement"} +HARDCORE_POSITION_AXIS_KEYS = { + "position", + "body_position", + "body_arrangement", + "arrangement", + "tease_act", + "touch_detail", + "manual_act", + "manual_detail", + "worship_act", + "transition_act", + "control_act", + "performance_act", + "coordination_act", + "aftercare_act", + "cleanup_detail", +} CAMERA_ORBIT_FRAMING_CHOICES = [ "from_zoom", "wide", @@ -2347,6 +2416,8 @@ def _empty_hardcore_position_config() -> dict[str, Any]: "allow_double": True, "allow_penetration": True, "allow_foreplay": True, + "allow_interaction": True, + "allow_manual": True, "allow_oral": True, "allow_outercourse": True, "allow_anal": True, @@ -2376,6 +2447,8 @@ def _parse_hardcore_position_config(value: str | dict[str, Any] | None) -> dict[ "allow_double", "allow_penetration", "allow_foreplay", + "allow_interaction", + "allow_manual", "allow_oral", "allow_outercourse", "allow_anal", @@ -2401,6 +2474,8 @@ def _hardcore_position_summary(config: dict[str, Any]) -> str: ("allow_double", "double"), ("allow_penetration", "penetration"), ("allow_foreplay", "foreplay"), + ("allow_interaction", "interaction"), + ("allow_manual", "manual"), ("allow_oral", "oral"), ("allow_outercourse", "outercourse"), ("allow_anal", "anal"), @@ -2446,6 +2521,8 @@ def build_hardcore_action_filter_json( allow_double: bool = False, allow_penetration: bool = True, allow_foreplay: bool = True, + allow_interaction: bool = True, + allow_manual: bool = True, allow_oral: bool = True, allow_outercourse: bool = True, allow_anal: bool = True, @@ -2457,6 +2534,8 @@ def build_hardcore_action_filter_json( focus_family = { "penetration_only": "penetrative", "foreplay_only": "foreplay", + "interaction_only": "interaction", + "manual_only": "manual", "oral_only": "oral", "outercourse_only": "outercourse", "anal_only": "anal", @@ -2470,6 +2549,8 @@ def build_hardcore_action_filter_json( config["allow_double"] = bool(allow_double) config["allow_penetration"] = bool(allow_penetration) config["allow_foreplay"] = bool(allow_foreplay) + config["allow_interaction"] = bool(allow_interaction) + config["allow_manual"] = bool(allow_manual) config["allow_oral"] = bool(allow_oral) config["allow_outercourse"] = bool(allow_outercourse) config["allow_anal"] = bool(allow_anal) @@ -2481,6 +2562,8 @@ def build_hardcore_action_filter_json( for enabled, family in ( (config["allow_penetration"], "penetrative"), (config["allow_foreplay"], "foreplay"), + (config["allow_interaction"], "interaction"), + (config["allow_manual"], "manual"), (config["allow_oral"], "oral"), (config["allow_outercourse"], "outercourse"), (config["allow_anal"], "anal"), @@ -2493,6 +2576,12 @@ def build_hardcore_action_filter_json( if focus == "foreplay_only": config["allow_foreplay"] = True + config["allow_interaction"] = True + elif focus == "interaction_only": + config["allow_interaction"] = True + config["allow_foreplay"] = True + elif focus == "manual_only": + config["allow_manual"] = True elif focus == "oral_only": config["allow_oral"] = True config["allow_penetration"] = False @@ -2530,6 +2619,20 @@ def _hardcore_allowed_subcategory_slugs(config: dict[str, Any]) -> set[str]: allowed.difference_update({"penetrative_sex", "anal_double_penetration", "threesomes", "group_sex_orgy"}) if not config.get("allow_foreplay", True): allowed.discard("foreplay_teasing") + if not config.get("allow_interaction", True): + allowed.difference_update( + { + "foreplay_teasing", + "body_worship_touching", + "clothing_position_transitions", + "dominant_guidance", + "camera_performance", + "group_coordination", + "aftercare_cleanup", + } + ) + if not config.get("allow_manual", True): + allowed.discard("manual_stimulation") if not config.get("allow_oral", True): allowed.discard("oral_sex") if not config.get("allow_outercourse", True): @@ -2582,7 +2685,7 @@ def _hardcore_text_blocked_by_action(text: str, axis_name: str, config: dict[str return True if not config.get("allow_anal", True) and ( axis_name == "anal_act" - or any(term in text for term in (" anal", "ass", "rear-entry anal")) + or any(term in text for term in (" anal", "anal sex", "anal penetration", "anus", "rear-entry anal", "penis entering ass", "thrusts into her ass", "thrusts into his ass")) ): return True if not config.get("allow_oral", True) and ( @@ -2626,6 +2729,68 @@ def _hardcore_text_blocked_by_action(text: str, axis_name: str, config: dict[str ) ): return True + if not config.get("allow_interaction", True) and ( + axis_name + in ( + "tease_act", + "touch_detail", + "clothing_detail", + "foreplay_detail", + "face_detail", + "body_contact", + "mood_detail", + "worship_act", + "transition_act", + "control_act", + "performance_act", + "coordination_act", + "aftercare_act", + "cleanup_detail", + ) + or any( + term in text + for term in ( + "kiss", + "kissing", + "caress", + "body worship", + "nipple", + "ass grab", + "thigh", + "hair holding", + "wrists", + "dirty talk", + "whispering", + "undressing", + "position transition", + "guided", + "camera", + "watching", + "aftercare", + "cleanup", + "wiping", + ) + ) + ): + return True + if not config.get("allow_manual", True) and ( + axis_name in ("manual_act", "manual_detail") + or any( + term in text + for term in ( + "fingering", + "fingers inside", + "clit", + "clitoris", + "manual stimulation", + "mutual masturbation", + "masturbating together", + "fingers on pussy", + "fingers on clit", + ) + ) + ): + return True if not config.get("allow_climax", True) and ( axis_name in ("climax_act", "climax_hint", "climax_detail", "fluid_detail", "fluid_location") or any(term in text for term in ("climax", "cum", "semen", "ejaculat", "creampie", "post-orgasm", "post-penetration")) @@ -6067,6 +6232,74 @@ def _role_graph( f"hands caressing skin while clothing is pulled aside." ) + def interaction_text() -> str: + return " ".join( + str(part or "").lower() + for part in ( + item_text, + *((item_axis_values or {}).values()), + ) + ) + + def manual_position_graph(primary: str, partner: str = "") -> str: + text = interaction_text() + if not partner: + if "mutual" in text: + return f"{primary} faces the camera with thighs open, both hands on her body for solo mutual-style masturbation framing." + return f"{primary} reclines with thighs open, one hand between her legs and fingers visibly stimulating her pussy." + if "mutual" in text: + return f"{primary} and {partner} sit close facing each other, both touching themselves while keeping hands, faces, and bodies visible." + if "clit" in text or "clitoris" in text: + return f"{primary} reclines with thighs open while {partner}'s hand is between her legs, fingers rubbing her clit as her hips tilt toward the touch." + if "toy" in text or "vibrator" in text: + return f"{primary} reclines with thighs open while {partner} holds a vibrator or toy against her clit, one hand keeping her thigh open." + return f"{primary} reclines with thighs open while {partner}'s hand is between her legs, fingers visibly stimulating her pussy." + + def interaction_position_graph(primary: str, partner: str, third: str = "") -> str: + text = interaction_text() + if "aftercare" in slug or any(term in text for term in ("aftercare", "cleanup", "wiping", "towel", "post-sex", "cuddle")): + if "cleanup" in text or "wiping" in text or "towel" in text: + return f"{primary} reclines after sex while {partner} kneels close and wipes her skin with a towel, hands and relaxed body contact visible." + return f"{primary} and {partner} lie close together after sex, bodies relaxed and hands resting on skin in a post-sex cuddle." + if "camera_performance" in slug or any(term in text for term in ("camera", "presenting", "showing", "viewer", "creator-shot")): + if third: + return f"{primary} faces the camera while {partner} and {third} hold and present her body, hands framing the exposed skin for the viewer." + return f"{primary} faces the camera and presents her body while {partner}'s hands hold her hips or thighs open for a clear creator-shot reveal." + if "body_worship" in slug or any(term in text for term in ("body worship", "nipple", "thigh", "mouth on skin", "kissing down", "ass grabbing")): + if "ass" in text: + return f"{primary} stands or kneels with hips angled back while {partner}'s hands grip her ass, fingers pressing into skin." + if "thigh" in text: + return f"{primary} reclines with thighs open while {partner} kneels close and kisses along her inner thighs, hands holding her legs in place." + if "nipple" in text or "breast" in text: + return f"{primary} arches toward {partner} while {partner}'s mouth is on her breast and one hand cups or squeezes the other breast." + return f"{primary} reclines or leans back while {partner} kisses down her body, hands tracing breasts, waist, hips, and thighs." + if "clothing_position" in slug or any(term in text for term in ("transition", "turning", "pulling onto", "lifting", "guided backward", "clothing", "garment")): + if "turn" in text or "rear-facing" in text: + return f"{partner}'s hands turn {primary} around by the hips, clothing partly moved aside as her body rotates into the next pose." + if "legs" in text or "thigh" in text: + return f"{primary} lies back while {partner} lifts and spreads her legs into position, hands and clothing movement clearly visible." + return f"{primary} and {partner} are mid-transition, with {partner}'s hands moving clothing aside and guiding {primary}'s hips toward the next pose." + if "dominant" in slug or any(term in text for term in ("hair", "wrist", "wrists", "jaw", "chin", "guided", "dominant", "control", "dirty talk", "whisper", "mouth near the ear", "verbal teasing")): + if "dirty talk" in text or "whisper" in text or "mouth near the ear" in text or "verbal teasing" in text: + return f"{partner} leans close to {primary}'s ear for dirty talk while holding her waist and keeping their bodies pressed close." + if "wrist" in text or "wrists" in text: + return f"{primary} lies back while {partner} pins her wrists above her head, both bodies close and the consensual control gesture clearly visible." + if "hair" in text: + return f"{partner} holds {primary}'s hair back while guiding her body closer, face and hair-hold gesture visible." + if "thigh" in text or "spread" in text: + return f"{primary} reclines with thighs open while {partner}'s hands spread her legs and hold the position for the camera." + return f"{partner} guides {primary}'s body with hands on her jaw, waist, and hips, keeping the consensual control gesture readable." + return foreplay_position_graph(primary, partner) + + def group_coordination_graph(primary: str, partner: str, third: str) -> str: + observer = third or any_person({primary, partner}) + text = interaction_text() + if "camera" in text or "hold" in text or "present" in text: + return f"{primary} is centered while {partner} and {observer} hold and present the body for the camera, each role clearly visible." + if "watch" in text or "waiting" in text: + return f"{primary} is centered while {partner} touches her body and {observer} watches close beside them, hands and faces readable." + return f"{primary} is centered while {partner} touches her body and {observer} stays close as the watching or guiding partner." + def mentions_ass(text: str) -> bool: return bool( re.search( @@ -6346,6 +6579,10 @@ def _role_graph( if people_count == 1: solo = people[0] if women_count == 1: + if "manual_stimulation" in slug: + return manual_position_graph(solo) + if "camera_performance" in slug: + return f"{solo} faces the camera and presents her body with hands framing the exposed skin in a solo creator-shot pose." if "cumshot" in slug or "climax" in slug: return f"{solo} is shown in a solo explicit orgasm pose with thighs open, one hand on her body, and visible arousal on skin and sheets." return f"{solo} is shown in a solo explicit adult pose with self-touch, open body framing, and direct camera awareness." @@ -6357,7 +6594,16 @@ def _role_graph( a, b = _pick_distinct(rng, women, 2) c = any_woman({a, b}) if len(women) >= 3 else "" used = {a, b} - if "foreplay" in slug: + if "manual_stimulation" in slug: + graph = manual_position_graph(a, b) + elif "group_coordination" in slug and c: + graph = group_coordination_graph(a, b, c) + used.add(c) + elif any(token in slug for token in ("foreplay", "body_worship", "clothing_position", "dominant_guidance", "camera_performance", "aftercare")): + graph = interaction_position_graph(a, b, c) + if c and "camera_performance" in slug: + used.add(c) + elif "foreplay" in slug: graph = foreplay_position_graph(a, b) elif "outercourse" in slug: graph = f"{a} kneels close to {b}'s body and uses mouth, hands, breasts, or feet for explicit non-penetrative contact." @@ -6379,7 +6625,14 @@ def _role_graph( a, b = _pick_distinct(rng, men, 2) c = any_man({a, b}) if len(men) >= 3 else "" used = {a, b} - if "foreplay" in slug: + if "manual_stimulation" in slug: + graph = f"{a} and {b} sit or recline close together with hands visibly stimulating bodies in a manual sex setup." + elif "group_coordination" in slug and c: + graph = group_coordination_graph(a, b, c) + used.add(c) + elif any(token in slug for token in ("foreplay", "body_worship", "clothing_position", "dominant_guidance", "camera_performance", "aftercare")): + graph = f"{a} and {b} press close together, kissing and caressing skin while clothing is pulled aside." + elif "foreplay" in slug: graph = f"{a} and {b} press close together, kissing and caressing skin while clothing is pulled aside." elif "outercourse" in slug: graph = f"{a} and {b} keep explicit non-penetrative penis contact visible with hands, mouth, or feet." @@ -6401,7 +6654,13 @@ def _role_graph( woman = any_woman() man = any_man() third = any_person({woman, man}) if people_count >= 3 else "" - if "foreplay" in slug: + if "manual_stimulation" in slug: + graph = manual_position_graph(woman, man) + elif "group_coordination" in slug: + graph = group_coordination_graph(woman, man, third) + elif any(token in slug for token in ("foreplay", "body_worship", "clothing_position", "dominant_guidance", "camera_performance", "aftercare")): + graph = interaction_position_graph(woman, man, third) + elif "foreplay" in slug: graph = foreplay_position_graph(woman, man) elif "outercourse" in slug: graph = outercourse_position_graph(woman, man)