From 8f7732a07f0ab6306c77d56e600a3cb11f74efa8 Mon Sep 17 00:00:00 2001 From: "Thomas \"Cakeisalie5\" Touhey" Date: Sun, 29 Jul 2018 21:55:18 +0200 Subject: [PATCH] Modified the way videos work in textoutpc. --- textoutpc/__init__.py | 5 ++- textoutpc/_options.py | 45 ++++++++++++++++---- textoutpc/_translate.py | 7 ++-- textoutpc/builtin/_Video.py | 61 ++++----------------------- textoutpc/builtin/_Videos.py | 79 +++++++++++++++++++++++++++++++++++ textoutpc/builtin/__init__.py | 3 +- 6 files changed, 132 insertions(+), 68 deletions(-) create mode 100644 textoutpc/builtin/_Videos.py diff --git a/textoutpc/__init__.py b/textoutpc/__init__.py index 850caff..7f9515d 100755 --- a/textoutpc/__init__.py +++ b/textoutpc/__init__.py @@ -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" diff --git a/textoutpc/_options.py b/textoutpc/_options.py index 51cf83f..c777e2c 100755 --- a/textoutpc/_options.py +++ b/textoutpc/_options.py @@ -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. diff --git a/textoutpc/_translate.py b/textoutpc/_translate.py index 423c771..72f422a 100755 --- a/textoutpc/_translate.py +++ b/textoutpc/_translate.py @@ -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. diff --git a/textoutpc/builtin/_Video.py b/textoutpc/builtin/_Video.py index 94c199e..4601f53 100755 --- a/textoutpc/builtin/_Video.py +++ b/textoutpc/builtin/_Video.py @@ -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 '

{}

'.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 += ''.format(self._id) - elif self._type == "dailymotion": - code += ''.format(self._code) - elif self._type == "vimeo": - code += ''.format(self._code) + code += ''.format(self._video.embed()) return code + '' diff --git a/textoutpc/builtin/_Videos.py b/textoutpc/builtin/_Videos.py new file mode 100644 index 0000000..efe13d0 --- /dev/null +++ b/textoutpc/builtin/_Videos.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +#****************************************************************************** +# Copyright (C) 2018 Thomas "Cakeisalie5" Touhey +# 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. diff --git a/textoutpc/builtin/__init__.py b/textoutpc/builtin/__init__.py index 9feec19..22dca02 100755 --- a/textoutpc/builtin/__init__.py +++ b/textoutpc/builtin/__init__.py @@ -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.