[BOTTUBE: 3 RTC] Share a BoTTube Video on Social Media with Context
from future import annotations
import re
import unittest
from dataclasses import dataclass
from typing import Dict, Iterable, List, Sequence, Tuple
from urllib.parse import urlparse
URL_RE = re.compile(r"https?://[^\s<>\"]+", re.IGNORECASE)
WORD_RE = re.compile(r"\b[\w'-]+\b", re.UNICODE)
SENTENCE_RE = re.compile(r"(?<=[.!?])\s+|\n+")
@dataclass(frozen=True)
class ShareSubmission:
platform: str
post_text: str
proof_url: str
class ValidationError(ValueError):
pass
class BoTTubeShareValidator:
"""Validates a submission artifact for a BoTTube social share."""
ALLOWED_PLATFORMS = {
"x": {"x", "twitter", "twitter/x", "x.com"},
"reddit": {"reddit", "r", "reddit.com"},
"mastodon": {"mastodon", "mastodon.social", "mastodon.social/@"},
"discord": {"discord", "discord.com"},
"hacker news": {"hacker news", "hn", "news.ycombinator.com"},
"dev.to": {"dev.to", "devto", "dev", "dev.to/"},
}
REQUIRED_BLOCKS = {
"interesting": (
"why this video is interesting",
"interesting",
"useful",
"worth sharing",
"worth watching",
"practical",
"insight",
"thought-provoking",
"compelling",
),
"bottube": (
"bottube",
"what bottube is",
"bottube exists",
"bo ttube",
"video sharing project",
"why it exists",
"exists to",
"tech community video platform",
),
"honest_take": (
"my honest take",
"honestly",
"i think",
"in my opinion",
"pros and cons",
"tradeoff",
"limitation",
"strengths and weaknesses",
"takeaway",
),
}
SPAM_PATTERNS = (
r"^https?://\S+$",
r"\bfollow\s+for\s+more\b",
r"\bcheck\s+this\s+out\b",
r"\bbuy\s+now\b",
r"\bairdrop\b",
r"\bgiveaway\b",
r"\bfree\s+money\b",
r"\bclick\s+here\b",
)
FAKE_ENGAGEMENT_PATTERNS = (
r"\b(5\+|five\s+\+?)\s+(genuine\s+)?engagements?\b",
r"\bfront\s+page\b",
r"\bviral\b",
r"\bguaranteed\s+engagement\b",
r"\bboost\s+engagement\b",
)
def normalize_platform(self, platform: str) -> str:
normalized = self._normalize(platform)
for canonical, aliases in self.ALLOWED_PLATFORMS.items():
if normalized == canonical or normalized in {self._normalize(a) for a in aliases}:
return canonical
return ""
def validate(self, submission: ShareSubmission) -> List[str]:
errors: List[str] = []
platform = self.normalize_platform(submission.platform)
if not platform:
errors.append("Unsupported platform")
post_text = self._safe_text(submission.post_text)
proof_url = self._safe_text(submission.proof_url)
if not post_text:
errors.append("Post text must not be empty")
return errors
urls = self._extract_urls(post_text)
if not urls:
errors.append("Post text must contain at least one URL")
if self._looks_like_bare_link(post_text):
errors.append("Bare link posts are not allowed")
sentences = self._split_sentences(post_text)
if len(sentences) < 3:
errors.append("Context must contain at least 3 sentences")
if len(self._words(post_text)) < 30:
errors.append("Context is too short; write at least 30 words")
block_presence = self._required_blocks_present(post_text)
for block, present in block_presence.items():
if not present:
errors.append(f"Missing required theme: {block}")
if self._looks_like_spam(post_text):
errors.append("Spam-like language detected")
if self._mentions_fake_engagement(post_text):
errors.append("Post text must not assert unverified engagement metrics")
if not self._valid_url(proof_url):
errors.append("Proof URL is required and must be valid")
return errors
def is_valid(self, submission: ShareSubmission) -> bool:
return not self.validate(submission)
def _required_blocks_present(self, text: str) -> Dict[str, bool]:
lower = text.lower()
present = {}
for block, keywords in self.REQUIRED_BLOCKS.items():
present[block] = any(keyword in lower for keyword in keywords)
return present
def _mentions_fake_engagement(self, text: str) -> bool:
lower = text.lower()
return any(re.search(pattern, lower, re.IGNORECASE) for pattern in self.FAKE_ENGAGEMENT_PATTERNS)
def _looks_like_spam(self, text: str) -> bool:
lower = text.lower()
return any(re.search(pattern, lower, re.IGNORECASE) for pattern in self.SPAM_PATTERNS)
def _looks_like_bare_link(self, text: str) -> bool:
stripped = text.strip()
words = self._words(stripped)
if len(words) <= 8 and URL_RE.fullmatch(stripped):
return True
if len(words) <= 4 and len(self._extract_urls(stripped)) == 1:
return True
return False
def _split_sentences(self, text: str) -> List[str]:
chunks = [c.strip() for c in SENTENCE_RE.split(text.strip()) if c.strip()]
if chunks:
return chunks
return [text.strip()] if text.strip() else []
def _words(self, text: str) -> List[str]:
return WORD_RE.findall(text)
def _extract_urls(self, text: str) -> List[str]:
return URL_RE.findall(text)
def _valid_url(self, text: str) -> bool:
if not text:
return False
parsed = urlparse(text)
return parsed.scheme in {"http", "https"} and bool(parsed.netloc)
def _safe_text(self, value: str) -> str:
return value.strip() if isinstance(value, str) else ""
def _normalize(self, value: str) -> str:
return re.sub(r"\s+", " ", self._safe_text(value).lower())
def build_submission_example() -> ShareSubmission:
post = (
"I found this BoTTube video genuinely interesting because it turns an AI-video concept into a concrete, shareable demo. "
"BoTTube exists as a focused place for AI-native video content, which helps explain why the project was created and who it serves. "
"My honest take is that the idea is promising, although its long-term value will depend on curation, quality control, and whether the content stays substantive. "
"Watch here: https://bottube.ai/video/example"
)
proof = "https://x.com/example/status/1234567890"
return ShareSubmission(platform="X", post_text=post, proof_url=proof)
class TestBoTTubeShareValidator(unittest.TestCase):
def setUp(self) -> None:
self.validator = BoTTubeShareValidator()
def test_valid_submission_passes(self):
submission = build_submission_example()
self.assertTrue(self.validator.is_valid(submission))
self.assertEqual(self.validator.validate(submission), [])
def test_platform_aliases_are_accepted(self):
submission = build_submission_example()
for alias in ["twitter", "X", "x.com", "devto", "news.ycombinator.com"]:
if alias == "news.ycombinator.com":
platform = "Hacker News"
else:
platform = alias
s = ShareSubmission(platform=platform, post_text=submission.post_text, proof_url=submission.proof_url)
self.assertNotIn("Unsupported platform", self.validator.validate(s))
def test_rejects_unsupported_platform(self):
submission = ShareSubmission(
platform="MySpace",
post_text=build_submission_example().post_text,
proof_url="https://example.com/proof",
)
errors = self.validator.validate(submission)
self.assertIn("Unsupported platform", errors)
def test_rejects_empty_post_text(self):
submission = ShareSubmission(platform="x", post_text=" ", proof_url="https://example.com/proof")
errors = self.validator.validate(submission)
self.assertIn("Post text must not be empty", errors)
def test_rejects_missing_url_in_post(self):
submission = ShareSubmission(
platform="reddit",
post_text=(
"This is interesting. BoTTube exists for AI video content. "
"My honest take is that the idea is promising."
),
proof_url="https://example.com/proof",
)
errors = self.validator.validate(submission)
self.assertIn("Post text must contain at least one URL", errors)
def test_rejects_less_than_three_sentences(self):
submission = ShareSubmission(
platform="reddit",
post_text=(
"Interesting demo on BoTTube. My honest take is positive. https://bottube.ai/video/x"
),
proof_url="https://example.com/proof",
)
errors = self.validator.validate(submission)
self.assertIn("Context must contain at least 3 sentences", errors)
def test_rejects_too_short_context(self):
submission = ShareSubmission(
platform="reddit",
post_text=(
"Interesting. BoTTube exists for AI video. My honest take is good. https://bottube.ai/video/x"
),
proof_url="https://example.com/proof",
)
errors = self.validator.validate(submission)
self.assertIn("Context is too short; write at least 30 words", errors)
def test_rejects_bare_link(self):
submission = ShareSubmission(
platform="x",
post_text="https://bottube.ai/video/example",
proof_url="https://example.com/proof",
)
errors = self.validator.validate(submission)
self.assertIn("Bare link posts are not allowed", errors)
def test_rejects_spam_language(self):
submission = ShareSubmission(
platform="x",
post_text=(
"Check this out! Follow for more. BoTTube exists to host AI video content. "
"My honest take is that it is useful. https://bottube.ai/video/example"
),
proof_url="https://example.com/proof",
)
errors = self.validator.validate(submission)
self.assertIn("Spam-like language detected", errors)
def test_rejects_fake_engagement_claims(self):
submission = ShareSubmission(
platform="x",
post_text=(
"This BoTTube video is interesting because it demonstrates a concrete AI workflow. "
"BoTTube exists to give this kind of content a home. "
"My honest take is that the idea is promising and could attract 5+ genuine engagements. "
"https://bottube.ai/video/example"
),
proof_url="https://x.com/example/status/1234567890",
)
errors = self.validator.validate(submission)
self.assertIn("Post text must not assert unverified engagement metrics", errors)
def test_rejects_missing_bottube_theme(self):
submission = ShareSubmission(
platform="x",
post_text=(
"This demo is useful because it shows a clear workflow. "
"My honest take is that the approach has tradeoffs. "
"https://bottube.ai/video/example"
),
proof_url="https://example.com/proof",
)
errors = self.validator.validate(submission)
self.assertIn("Missing required theme: bottube", errors)
def test_rejects_missing_honest_take_theme(self):
submission = ShareSubmission(
platform="x",
post_text=(
"This BoTTube video is interesting because it is practical. "
"BoTTube exists to host AI-native video content. "
"https://bottube.ai/video/example"
),
proof_url="https://example.com/proof",
)
errors = self.validator.validate(submission)
self.assertIn("Missing required theme: honest_take", errors)
def test_rejects_invalid_proof_url(self):
submission = ShareSubmission(
platform="x",
post_text=build_submission_example().post_text,
proof_url="not-a-url",
)
errors = self.validator.validate(submission)
self.assertIn("Proof URL is required and must be valid", errors)
def test_rejects_blank_proof_url(self):
submission = ShareSubmission(
platform="x",
post_text=build_submission_example().post_text,
proof_url=" ",
)
errors = self.validator.validate(submission)
self.assertIn("Proof URL is required and must be valid", errors)
def test_normalizes_platform_whitespace_and_case(self):
submission = ShareSubmission(
platform=" TwItTeR ",
post_text=build_submission_example().post_text,
proof_url=build_submission_example().proof_url,
)
self.assertTrue(self.validator.is_valid(submission))
def test_returns_multiple_errors_for_invalid_submission(self):
submission = ShareSubmission(platform="bad", post_text="https://x.com/a", proof_url="bad")
errors = self.validator.validate(submission)
self.assertIn("Unsupported platform", errors)
self.assertIn("Bare link posts are not allowed", errors)
self.assertIn("Proof URL is required and must be valid", errors)
if name == "main":
unittest.main(verbosity=2)
Top comments (0)