File size: 3,614 Bytes
89b6a21
 
 
 
 
 
 
 
 
 
127bfda
 
 
89b6a21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127bfda
 
 
89b6a21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127bfda
 
 
89b6a21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import re

from bot.byte_semantics_base import compact_message, format_chat_reply, normalize_text_for_scene
from bot.byte_semantics_constants import (
    MAX_CHAT_MESSAGE_LENGTH,
    MOVIE_TITLE_QUOTE_PATTERN,
    MULTIPART_SEPARATOR,
)


def split_text_for_chat(
    text: str, max_len: int = MAX_CHAT_MESSAGE_LENGTH, max_parts: int = 2
) -> list[str]:
    clean_text = (text or "").strip()
    if not clean_text:
        return []
    if len(clean_text) <= max_len:
        return [clean_text]

    parts: list[str] = []
    remaining = clean_text
    while remaining and len(parts) < max_parts:
        if len(remaining) <= max_len:
            parts.append(remaining.strip())
            remaining = ""
            break

        cut = remaining.rfind("\n", 0, max_len + 1)
        if cut < int(max_len * 0.5):
            sentence_cuts = [
                remaining.rfind(symbol, 0, max_len + 1) for symbol in (". ", "? ", "! ")
            ]
            cut = max(sentence_cuts)
        if cut < int(max_len * 0.5):
            cut = remaining.rfind(" ", 0, max_len + 1)
        if cut <= 0:
            cut = max_len

        chunk = remaining[:cut].strip()
        if chunk:
            parts.append(chunk)
        remaining = remaining[cut:].strip()

    if remaining:
        if parts:
            parts[-1] = compact_message(f"{parts[-1]} {remaining}", max_len=max_len)
        else:
            parts.append(compact_message(remaining, max_len=max_len))

    return [part for part in parts if part][:max_parts]


def extract_multi_reply_parts(answer_text: str, max_parts: int = 2) -> list[str]:
    if not answer_text:
        return []

    raw_parts = [
        segment.strip() for segment in answer_text.split(MULTIPART_SEPARATOR) if segment.strip()
    ]
    if len(raw_parts) >= 2:
        normalized = [format_chat_reply(part) for part in raw_parts[:max_parts]]
        return [part for part in normalized if part]

    chunks = split_text_for_chat(answer_text, max_len=MAX_CHAT_MESSAGE_LENGTH, max_parts=max_parts)
    normalized = [format_chat_reply(chunk) for chunk in chunks]
    return [part for part in normalized if part]


def extract_movie_title(prompt: str) -> str:
    quote_match = MOVIE_TITLE_QUOTE_PATTERN.search(prompt or "")
    if quote_match:
        return normalize_text_for_scene(quote_match.group("title"), max_len=80)

    candidate_match = re.search(
        r"ficha\s*t[eé]cnica(?:\s+(?:do|da|de)\s+filme)?(?:\s+(?:do|da|de))?\s+(?P<title>.+)$",
        prompt or "",
        re.IGNORECASE,
    )
    if not candidate_match:
        return ""

    candidate = candidate_match.group("title").strip(" ?!.:,;")
    if not candidate:
        return ""

    lowered = candidate.lower()
    generic_fragments = (
        "que estamos vendo",
        "que estamos assistindo",
        "que estamos assistindo hoje",
        "agora",
    )
    if any(fragment in lowered for fragment in generic_fragments):
        return ""
    if lowered in {"filme", "hoje", "agora"}:
        return ""

    return normalize_text_for_scene(candidate, max_len=80)


def build_movie_fact_sheet_query(movie_title: str) -> str:
    return (
        f"Monte uma ficha tecnica objetiva do filme '{movie_title}' para chat Twitch. "
        "Responda em no maximo 4 linhas, sem markdown, com alta densidade e sem enrolacao. "
        "Formato obrigatorio: "
        "1) Titulo | Ano | Pais. "
        "2) Direcao | Genero | Duracao. "
        "3) Elenco principal (ate 3 nomes). "
        "4) Nota media | Premios-chave (ou N/D). "
        "Se nao houver confianca em algum dado, escreva N/D."
    )