updating youtube
This commit is contained in:
@@ -18,14 +18,29 @@ from urllib.parse import urlparse, parse_qs
|
|||||||
|
|
||||||
# ------------- YouTube helpers -------------
|
# ------------- YouTube helpers -------------
|
||||||
|
|
||||||
YOUTUBE_EMBED_TMPL = (
|
def fetch_youtube_oembed_html(youtube_url: str, timeout: int = 10) -> str | None:
|
||||||
'<div class="yt-container" style="position:relative;aspect-ratio:16/9;max-width:800px;margin:1rem 0">'
|
"""
|
||||||
'<iframe src="https://www.youtube.com/embed/{vid}" '
|
Get YouTube oEmbed HTML exactly as provided and wrap it as a Ghost embed card.
|
||||||
'title="YouTube video" loading="lazy" '
|
"""
|
||||||
'style="position:absolute;inset:0;width:100%;height:100%;border:0" '
|
try:
|
||||||
'allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" '
|
resp = requests.get(
|
||||||
'allowfullscreen></iframe></div>'
|
"https://www.youtube.com/oembed",
|
||||||
)
|
params={"url": youtube_url, "format": "json"},
|
||||||
|
headers={"User-Agent": "ghost-bot/1.0"},
|
||||||
|
timeout=timeout,
|
||||||
|
)
|
||||||
|
resp.raise_for_status()
|
||||||
|
data = resp.json()
|
||||||
|
html = data.get("html")
|
||||||
|
if not html:
|
||||||
|
return None
|
||||||
|
# Wrap in Ghost embed card container; do NOT alter the iframe attributes.
|
||||||
|
return f'<figure class="kg-card kg-embed-card">{html}</figure>'
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def youtube_thumbnail_url(video_id: str) -> str:
|
||||||
|
return f"https://i.ytimg.com/vi/{video_id}/hqdefault.jpg"
|
||||||
|
|
||||||
def extract_youtube_id(url: str) -> Optional[str]:
|
def extract_youtube_id(url: str) -> Optional[str]:
|
||||||
try:
|
try:
|
||||||
@@ -242,13 +257,18 @@ class GhostTask:
|
|||||||
# --- YouTube embed / fallback
|
# --- YouTube embed / fallback
|
||||||
vid = post.get("yt_videoid") or extract_youtube_id(linkURL)
|
vid = post.get("yt_videoid") or extract_youtube_id(linkURL)
|
||||||
if vid:
|
if vid:
|
||||||
# iframe (web) + thumbnail (email-safe) + lien
|
watch_url = f"https://www.youtube.com/watch?v={vid}"
|
||||||
thumb = f"https://i.ytimg.com/vi/{vid}/hqdefault.jpg"
|
|
||||||
parts.append(YOUTUBE_EMBED_TMPL.format(vid=vid))
|
# Try provider HTML via oEmbed (as Ghost does)
|
||||||
parts.append(f'<p><a href="https://www.youtube.com/watch?v={vid}">Voir sur YouTube</a></p>')
|
embed_html = fetch_youtube_oembed_html(watch_url, timeout=10)
|
||||||
parts.append(f'<p><a href="https://www.youtube.com/watch?v={vid}"><img src="{thumb}" alt="YouTube thumbnail" style="max-width:100%;height:auto;border:0" /></a></p>')
|
if embed_html:
|
||||||
if not first_image:
|
parts.append(embed_html)
|
||||||
first_image = thumb
|
else:
|
||||||
|
# Fallback: leave the plain URL on its own line so Ghost may still auto-embed
|
||||||
|
parts.append(f'\n<p>{watch_url}</p>\n')
|
||||||
|
|
||||||
|
# Minimal fallback link (non-intrusive for email/web)
|
||||||
|
parts.append(f'<p><a href="{watch_url}">Voir sur YouTube</a></p>')
|
||||||
else:
|
else:
|
||||||
# --- Texte + lien
|
# --- Texte + lien
|
||||||
ftext = ""
|
ftext = ""
|
||||||
@@ -267,6 +287,7 @@ class GhostTask:
|
|||||||
if link.get("type") in ("image/jpg", "image/jpeg", "image/png", "image/webp"):
|
if link.get("type") in ("image/jpg", "image/jpeg", "image/png", "image/webp"):
|
||||||
imgUrl = link.get("href")
|
imgUrl = link.get("href")
|
||||||
if imgUrl:
|
if imgUrl:
|
||||||
|
imgUrl = imgUrl.replace("/250x250/", "/990x320/")
|
||||||
if not first_image:
|
if not first_image:
|
||||||
first_image = imgUrl
|
first_image = imgUrl
|
||||||
parts.append(f'<figure><img src="{html.escape(imgUrl)}" loading="lazy"></figure>')
|
parts.append(f'<figure><img src="{html.escape(imgUrl)}" loading="lazy"></figure>')
|
||||||
@@ -320,7 +341,7 @@ class GhostTask:
|
|||||||
# (Re)charge les feeds
|
# (Re)charge les feeds
|
||||||
feeds_file = os.environ.get("FEEDS_FILE", "/data/feeds.txt")
|
feeds_file = os.environ.get("FEEDS_FILE", "/data/feeds.txt")
|
||||||
if not os.path.isfile(feeds_file):
|
if not os.path.isfile(feeds_file):
|
||||||
feeds_file = os.environ.get("FEEDS_FILE_FALLBACK", r"c:\workspace\Substack_JV\feeds.txt")
|
feeds_file = os.environ.get("FEEDS_FILE_FALLBACK", r"f:\workspace\Substack_JV\feeds.txt")
|
||||||
feeds: List[RSSfeed] = []
|
feeds: List[RSSfeed] = []
|
||||||
with open(feeds_file, encoding="utf-8") as f:
|
with open(feeds_file, encoding="utf-8") as f:
|
||||||
lines = [line.strip() for line in f if line.strip()]
|
lines = [line.strip() for line in f if line.strip()]
|
||||||
@@ -393,7 +414,7 @@ async def main():
|
|||||||
feeds: List[RSSfeed] = []
|
feeds: List[RSSfeed] = []
|
||||||
feeds_file = os.environ.get("FEEDS_FILE", "/data/feeds.txt")
|
feeds_file = os.environ.get("FEEDS_FILE", "/data/feeds.txt")
|
||||||
if not os.path.isfile(feeds_file):
|
if not os.path.isfile(feeds_file):
|
||||||
feeds_file = os.environ.get("FEEDS_FILE_FALLBACK", r"c:\workspace\Substack_JV\feeds.txt")
|
feeds_file = os.environ.get("FEEDS_FILE_FALLBACK", r"f:\workspace\Substack_JV\feeds.txt")
|
||||||
with open(feeds_file, encoding="utf-8") as f:
|
with open(feeds_file, encoding="utf-8") as f:
|
||||||
for line in f:
|
for line in f:
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
|
|||||||
Reference in New Issue
Block a user