Modified the way videos work in textoutpc.
This commit is contained in:
parent
1f80dd6772
commit
8f7732a07f
|
@ -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"
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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>'
|
||||
|
||||
|
|
|
@ -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.
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue