File size: 4,568 Bytes
0498eff | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | from __future__ import annotations
import re
DEFAULT_EXPRESSION_1 = "calm expression"
DEFAULT_EXPRESSION_2 = "neutral expression"
DEFAULT_EXPRESSION_3 = "slight smug smile"
# Matches:
# expression.1=...
# expression.2: ...
# expression_tag1=...
# expression1=...
_EXPR_RE = re.compile(
r"^expression(?:\.|_tag)?([1-5])\s*[:=]\s*(.*)$",
flags=re.IGNORECASE,
)
_SKIN_RE = re.compile(
r"^skin(?:\.|_tag)?([1-5])\s*[:=]",
flags=re.IGNORECASE,
)
_AESTHETIC_RE = re.compile(
r"^aesthetic(?:\.|_tag)?([1-5])\s*[:=]",
flags=re.IGNORECASE,
)
_EQUIP_RE = re.compile(
r"^(?:equip|equipment)\.",
flags=re.IGNORECASE,
)
_GPT_BAM_BLOCK_RE = re.compile(
r"GPT_BAM_START###(.*?)###GPT_BAM_END",
flags=re.IGNORECASE | re.DOTALL,
)
def _split_segments(payload: str) -> list[str]:
"""Split a GPT_BAM payload into ### segments, removing empty/newline-only parts."""
payload = (payload or "").replace("\r", "\n")
return [seg.strip() for seg in payload.split("###") if seg.strip()]
def _is_expression_segment(seg: str) -> bool:
return _EXPR_RE.match(seg) is not None
def _find_insertion_index(segments: list[str]) -> int:
"""
Where to insert expression.1/2/3 if no expression exists yet:
1) first existing expression position
2) after last skin tag
3) after last aesthetic tag
4) after last equip.* tag
5) otherwise at end
"""
first_expr_idx = None
last_skin_idx = None
last_aesthetic_idx = None
last_equip_idx = None
for i, seg in enumerate(segments):
if _is_expression_segment(seg) and first_expr_idx is None:
first_expr_idx = i
if _SKIN_RE.match(seg):
last_skin_idx = i
if _AESTHETIC_RE.match(seg):
last_aesthetic_idx = i
if _EQUIP_RE.match(seg):
last_equip_idx = i
if first_expr_idx is not None:
return first_expr_idx
if last_skin_idx is not None:
return last_skin_idx + 1
if last_aesthetic_idx is not None:
return last_aesthetic_idx + 1
if last_equip_idx is not None:
return last_equip_idx + 1
return len(segments)
def _rewrite_payload(payload: str) -> str:
segments = _split_segments(payload)
insertion_index = _find_insertion_index(segments)
new_expression_segments = [
f"expression.1={DEFAULT_EXPRESSION_1}",
f"expression.2={DEFAULT_EXPRESSION_2}",
f"expression.3={DEFAULT_EXPRESSION_3}",
]
out_segments: list[str] = []
inserted = False
for i, seg in enumerate(segments):
if not inserted and i == insertion_index:
out_segments.extend(new_expression_segments)
inserted = True
# Remove ALL existing expression.1..5 / expression_tag1..5
if _is_expression_segment(seg):
continue
out_segments.append(seg)
if not inserted:
out_segments.extend(new_expression_segments)
return "###".join(out_segments)
def _rewrite_gpt_bam_text(text: str) -> str:
"""
If a GPT_BAM block is found, only rewrite that block and preserve any text outside it.
If no GPT_BAM block is found, treat the whole input as a raw payload and rewrite it.
"""
text = text or ""
match = _GPT_BAM_BLOCK_RE.search(text)
if not match:
# Fallback: treat entire text as payload and wrap it back into GPT_BAM
rewritten_payload = _rewrite_payload(text)
return f"GPT_BAM_START###{rewritten_payload}###GPT_BAM_END"
original_payload = match.group(1)
rewritten_payload = _rewrite_payload(original_payload)
new_block = f"GPT_BAM_START###{rewritten_payload}###GPT_BAM_END"
return text[:match.start()] + new_block + text[match.end():]
class BAM_expression_default:
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"BAM-format_In": ("STRING", {"multiline": True, "default": ""}),
}
}
RETURN_TYPES = ("STRING",)
RETURN_NAMES = ("BAM-format_OUT",)
FUNCTION = "apply"
CATEGORY = "BAM"
def apply(self, **kwargs):
bam_in = kwargs.get("BAM-format_In", "")
bam_out = _rewrite_gpt_bam_text(bam_in)
return (bam_out,)
NODE_CLASS_MAPPINGS = {
"BAM_expression_default": BAM_expression_default,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"BAM_expression_default": "BAM_expression_default",
} |