2
0
Fork 0

Modified the way videos work in textoutpc.

This commit is contained in:
Thomas Touhey 2018-07-29 21:55:18 +02:00
parent 1f80dd6772
commit 8f7732a07f
No known key found for this signature in database
GPG Key ID: 2ECEB0517AD947FB
6 changed files with 132 additions and 68 deletions

View File

@ -12,12 +12,13 @@ from io import StringIO as _StringIO
from ._options import TextoutOptions as Options, \
TextoutBlockTag as BlockTag, TextoutInlineTag as InlineTag, \
TextoutParagraphTag as ParagraphTag, TextoutListTag as _TextoutListTag, \
TextoutListElementTag as _TextoutListElementTag, TextoutSmiley as Smiley
TextoutListElementTag as _TextoutListElementTag, TextoutSmiley as Smiley, \
TextoutVideo as Video
from ._translate import Translator as _Translator
__all__ = ["version", "tohtml", "tolightscript",
"Options", "BlockTag", "ParagraphTag", "InlineTag",
"ListTag", "ListElementTag", "Smiley"]
"ListTag", "ListElementTag", "Smiley", "Video"]
version = "0.2"

View File

@ -22,7 +22,7 @@ from ._html import SmileyConvertor as _htmlsm
__all__ = ["TextoutOptions",
"TextoutTag", "TextoutBlockTag", "TextoutInlineTag", "TextoutParagraphTag",
"TextoutSmiley"]
"TextoutSmiley", "TextoutVideo"]
def _getargscount(func):
try:
@ -59,7 +59,7 @@ class TextoutTag:
aliases = ()
def __init__(self, name, value, ot, tweaks):
def __init__(self, name, value, ot, tweaks, options):
""" Initialize the textout tag with the documented members. """
# Store internal data.
@ -68,6 +68,7 @@ class TextoutTag:
self.__value = value
self.__output_type = ot
self.__tweaks = tweaks
self.__options = options
self.output_type = ot
@ -155,6 +156,9 @@ class TextoutTag:
except KeyError:
return default
def video(self, *args, **kwargs):
return self.__options.get_video(*args, **kwargs)
# Role-specific base tag classes.
class TextoutBlockTag(TextoutTag):
@ -194,6 +198,19 @@ class TextoutSmiley:
return f"{self.__class__.__name__}(aliases = {repr(self.aliases)}, " \
f"url = {repr(self.url)})"
# ---
# Videos.
# ---
class TextoutVideo:
""" Base class for videos. """
def __init__(self, url):
raise ValueError("no URL supported")
def embed(self):
return "http://example.org/"
# ---
# Options extractor and manager.
# ---
@ -215,6 +232,7 @@ class TextoutOptions:
def __init__(self, *modules, default = True):
self._aliases = {}
self._s_aliases = {}
self._videos = []
if default:
self.add(_get_builtin_module())
@ -245,6 +263,10 @@ class TextoutOptions:
self._htmlsm = None
return True
if _isclass(element) and issubclass(element, TextoutVideo):
if not any(video is element for video in self._videos):
self._videos.append(element)
def __extract(self, module):
""" Extract options from a module. """
@ -284,15 +306,22 @@ class TextoutOptions:
self._htmlsm = _htmlsm(self._s_aliases)
return self._htmlsm.convert(text)
def get_video(self, url):
""" Get a video using its URL. """
for video in self._videos:
try:
v = video(url)
except:
continue
break
else:
raise ValueError("invalid video URL")
return v
def get_tag(self, name):
""" Get the tag class corresponding to a name. """
return self._aliases[name]
try:
als = self._aliases[name]
return als(name, value, output_type, tweaks)
except:
return None
# End of file.

View File

@ -628,7 +628,7 @@ class Translator:
if not self.inline_mode:
self.push_tag(_TagData(_TextoutParagraphTag(None, None,
self.output_type, self.tweaks), None, ''))
self.output_type, self.tweaks, self.options), None, ''))
# We want to get our elements out of the element stream (Lephe
# told me that the `TextoutStream` class was actually a lexer,
@ -740,7 +740,8 @@ class Translator:
value = self.process_text(value)
try:
tag = tag(tagdata.name, value, self.output_type, self.tweaks)
tag = tag(tagdata.name, value, self.output_type, self.tweaks,
self.options)
except:
self.put_text(tagdata.full)
continue
@ -761,7 +762,7 @@ class Translator:
if dat.type == dat.BLOCK and dat.super and not dat.raw \
and not dat.inlined:
self.push_tag(_TagData(_TextoutParagraphTag(None, None,
self.output_type, self.tweaks), None, ''))
self.output_type, self.tweaks, self.options), None, ''))
# End of file, it seems! Let's close the tags, flush the text
# and just resume our lives from there.

View File

@ -4,7 +4,6 @@
# This file is part of the textoutpc project, which is MIT-licensed.
#******************************************************************************
import re as _re
import urllib.parse as _urlparse
from html import escape as _htmlescape
@ -12,10 +11,6 @@ from .. import BlockTag as _BlockTag
__all__ = ["VideoTag"]
_hexcode = _re.compile('[a-zA-Z0-9_-]+')
_numcode = _re.compile('^/[0-9]+$')
_dailypath = _re.compile('^/video/([a-z0-9]+)$')
class VideoTag(_BlockTag):
""" The video tag, puts a preview of the video whose URL is given.
Only a few 'big' services are supported for now.
@ -72,52 +67,21 @@ class VideoTag(_BlockTag):
if fl:
self._float = True
def _getvideo(self, url):
""" Try to get the video type for preprocessing. """
url = _urlparse.urlparse(url)
if not url.scheme in ('http', 'https'):
raise Exception
if url.netloc == "youtu.be":
self._id = url.path[1:]
if not _hexcode.match(self._id):
raise Exception
self._type = "youtube"
elif url.netloc in ('youtube.com', 'www.youtube.com'):
if url.path != '/watch':
raise Exception
self._id = _urlparse.parse_qs(url.query)['v'][0]
if not _hexcode.fullmatch(self._id):
raise Exception
self._type = "youtube"
elif url.netloc in ('dailymotion.com', 'www.dailymotion.com'):
self._code = _dailypath.match(url.path).groups()[0]
self._type = "dailymotion"
elif url.netloc in ('vimeo.com', 'www.vimeo.com'):
self._code = url.path[1:]
if not _numcode.match(self._code):
raise Exception
self._type = "vimeo"
else:
raise Exception
def preprocess(self, content):
self._url = content
try:
self._getvideo(content)
self._video = self.video(content)
except:
url = _urlparse.urlparse(content)
if not url.scheme in ('http', 'https'):
raise Exception("No allowed prefix!")
self._type = None
self._video = content
def content_html(self):
""" Produce the embed code for the given type. """
if not self._type:
url = _htmlescape(self._url)
if isinstance(self._video, str):
url = _htmlescape(self._video)
return '<p><a href="{}">{}</a></p>'.format(url, url)
align = "float-" + (self._align or "left") if self._align \
@ -129,19 +93,8 @@ class VideoTag(_BlockTag):
f' style="padding-bottom: {self._ratio}%"' \
if self._ratio != round(9 / 16, 4) else "")
if self._type == "youtube":
code += '<iframe ' \
'src="https://www.youtube.com/embed/{}" frameborder="0" ' \
'allowfullscreen></iframe>'.format(self._id)
elif self._type == "dailymotion":
code += '<iframe frameborder="0" ' \
'src="https://www.dailymotion.com/embed/video/{}">' \
'</iframe>'.format(self._code)
elif self._type == "vimeo":
code += '<iframe src="https://player.vimeo.com/video/{}' \
'?title=0&byline=0&portrait=0" frameborder="0" ' \
'webkitAllowFullScreen allowFullScreen>' \
'</iframe>'.format(self._code)
code += '<iframe src="{}" frameborder="0" allowfullscreen>' \
'</iframe>'.format(self._video.embed())
return code + '</div>'

View File

@ -0,0 +1,79 @@
#!/usr/bin/env python3
#******************************************************************************
# Copyright (C) 2018 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
# This file is part of the textoutpc project, which is MIT-licensed.
#******************************************************************************
import re as _re
import urllib.parse as _urlparse
from .. import Video as _Video
__all__ = ["YouTubeVideo", "DailymotionVideo", "VimeoVideo"]
class YouTubeVideo(_Video):
""" Get a video from Youtube. """
_hexcode = _re.compile('[a-zA-Z0-9_-]+')
def __init__(self, url):
url = _urlparse.urlparse(url)
if not url.scheme in ('http', 'https'):
raise Exception
if url.netloc == "youtu.be":
self._id = url.path[1:]
if not self._hexcode.match(self._id):
raise ValueError("invalid id")
elif url.netloc in ('youtube.com', 'www.youtube.com'):
if url.path != '/watch':
raise ValueError("invalid id")
self._id = _urlparse.parse_qs(url.query)['v'][0]
if not self._hexcode.fullmatch(self._id):
raise Exception
else:
raise ValueError("unknown URL")
def embed(self):
return f"https://www.youtube.com/embed/{self._id}"
class DailymotionVideo(_Video):
""" Get a video from Dailymotion. """
_dailypath = _re.compile('^/video/([a-z0-9]+)$')
def __init__(self, url):
url = _urlparse.urlparse(url)
if not url.scheme in ('http', 'https'):
raise Exception
if url.netloc in ('dailymotion.com', 'www.dailymotion.com'):
self._code = self._dailypath.match(url.path).groups()[0]
else:
raise ValueError("unknown URL")
def embed(self):
return f"https://www.dailymotion.com/embed/video/{self._code}"
class VimeoVideo(_Video):
""" Get a video from Vimeo. """
_numcode = _re.compile('^/[0-9]+$')
def __init__(self, url):
url = _urlparse.urlparse(url)
if not url.scheme in ('http', 'https'):
raise Exception
if url.netloc in ('vimeo.com', 'www.vimeo.com'):
self._code = url.path[1:]
if not self._numcode.match(self._code):
raise ValueError("invalid video code")
else:
raise ValueError("unknown URL")
def embed(self):
return f"https://player.vimeo.com/video/{self._code}" \
"?title=0&byline=0&portrait=0"
# End of file.

View File

@ -25,8 +25,9 @@ from ._Text import *
from ._Title import *
from ._Video import *
# Smileys.
# Other resources (smileys, videos).
from ._Smileys import *
from ._Videos import *
# End of file.