# retoor <retoor@molodetz.nl>
from __future__ import annotations
import re
from devplacepy.services.jobs.isslop.analysis.domsignals.base import DomPageContext, dom_check
from devplacepy.services.jobs.isslop.analysis.signals import (
AXIS_ORIGIN,
SEVERITY_MEDIUM,
SEVERITY_WEAK,
Signal,
)
CLICHE_PHRASES: tuple[str, ...] = (
r"unlock (the )?(power|potential) of",
r"unleash the power of",
r"take your .{1,40} to the next level",
r"elevate your",
r"seamlessly integrat(e|es|ion)",
r"revolutioniz(e|ing) the way",
r"whether you('re| are) a .{1,30} or (a )?.{1,30}",
r"delve into",
r"dive into the world of",
r"embark on a journey",
r"push(ing)? the boundaries of",
r"at the forefront of",
r"game[- ]chang(er|ing)",
r"pave the way for",
r"bridging the gap between",
r"navigate the complexities of",
r"foster a culture of",
r"harness the power of",
r"cutting[- ]edge",
r"future[- ]proof",
r"world[- ]class",
r"enterprise[- ]grade",
r"streamline(d)?",
r"empower(ing)?",
r"supercharg(e|ed|ing)",
)
CLICHE_PATTERN = re.compile("|".join(CLICHE_PHRASES), re.IGNORECASE)
BUZZWORDS: tuple[str, ...] = ("delve", "crucial", "intricate", "nuanced", "myriad", "realm", "tapestry", "landscape")
BUZZWORD_THRESHOLD: int = 3
BUZZWORD_PATTERNS: tuple[re.Pattern[str], ...] = tuple(
re.compile(rf"\b{word}\b", re.IGNORECASE) for word in BUZZWORDS
)
HEADING_EMOJI_PATTERN = re.compile(r"[\U0001F300-\U0001FAFF✅⭐✨\U0001F680]")
FAQ_PATTERNS: tuple[re.Pattern[str], ...] = (
re.compile(r"^what is\b", re.IGNORECASE),
re.compile(r"^how does .{1,30} work\??$", re.IGNORECASE),
re.compile(r"^is (it|.{1,20}) secure\??$", re.IGNORECASE),
re.compile(r"^can i cancel", re.IGNORECASE),
re.compile(r"^do you offer a? ?(free trial|refund)", re.IGNORECASE),
)
FAQ_PATTERN_THRESHOLD: int = 3
def _heading_texts(page: DomPageContext) -> list[str]:
return [
str(heading.get("text", ""))
for heading in (page.dom.get("headings") or [])
if isinstance(heading, dict) and heading.get("text")
]
def _text_blob(page: DomPageContext) -> str:
parts = list(_heading_texts(page))
for image in page.dom.get("images", []) or []:
if isinstance(image, dict) and image.get("alt"):
parts.append(str(image["alt"]))
meta = page.dom.get("meta", {}) or {}
description = meta.get("description") if isinstance(meta, dict) else ""
if description:
parts.append(str(description))
return "\n".join(parts)
def _detect_template_copy(blob: str) -> Signal | None:
match = CLICHE_PATTERN.search(blob)
if not match:
return None
return Signal(
"TEMPLATE_COPY_DOM",
"Stock AI landing-page cliche phrase in rendered copy",
SEVERITY_MEDIUM,
AXIS_ORIGIN,
1.5,
0,
match.group(0)[:150],
)
def _detect_buzzword_cluster(blob: str) -> Signal | None:
hits = [pattern.pattern for pattern in BUZZWORD_PATTERNS if pattern.search(blob)]
if len(hits) < BUZZWORD_THRESHOLD:
return None
return Signal(
"AI_BUZZWORD_CLUSTER",
f"Elevated buzzword cluster ({len(hits)} distinct terms)",
SEVERITY_WEAK,
AXIS_ORIGIN,
1.0,
0,
", ".join(hits),
)
def _detect_emoji_heading(page: DomPageContext) -> Signal | None:
for text in _heading_texts(page):
if HEADING_EMOJI_PATTERN.search(text):
return Signal(
"EMOJI_HEADING_DOM",
"Emoji embedded inside a rendered heading",
SEVERITY_MEDIUM,
AXIS_ORIGIN,
1.0,
0,
text[:100],
)
return None
def _detect_generic_faq_template(page: DomPageContext) -> Signal | None:
texts = _heading_texts(page)
matched = 0
for pattern in FAQ_PATTERNS:
if any(pattern.search(text.strip()) for text in texts):
matched += 1
if matched < FAQ_PATTERN_THRESHOLD:
return None
return Signal(
"GENERIC_FAQ_TEMPLATE",
f"Generic templated FAQ question set ({matched} canonical patterns matched)",
SEVERITY_MEDIUM,
AXIS_ORIGIN,
1.5,
0,
f"{matched} FAQ patterns matched",
)
@dom_check
def detect_copy_signals(page: DomPageContext) -> list[Signal]:
blob = _text_blob(page)
findings: list[Signal] = []
for signal in (
_detect_template_copy(blob),
_detect_buzzword_cluster(blob),
_detect_emoji_heading(page),
_detect_generic_faq_template(page),
):
if signal is not None:
findings.append(signal)
return findings