From fe37d0be74a01f3a278471e94e8005a4aea1e461 Mon Sep 17 00:00:00 2001 From: Zykino Date: Sun, 11 Apr 2021 22:22:13 +0200 Subject: [PATCH] WIP Implements the core flow --- prismedia/cli.py | 40 ++++------ prismedia/core.py | 98 ++++++++++++------------- prismedia/pluginInterfaces.py | 38 +++++----- prismedia/plugins/interfaces/help.py | 9 ++- prismedia/plugins/platforms/peertube.py | 6 +- prismedia/utils.py | 8 ++ prismedia/video.py | 2 +- 7 files changed, 103 insertions(+), 98 deletions(-) diff --git a/prismedia/cli.py b/prismedia/cli.py index 797b23c..d40ab26 100644 --- a/prismedia/cli.py +++ b/prismedia/cli.py @@ -1,4 +1,5 @@ import pluginInterfaces as pi +import utils import video as vid from yapsy.PluginManager import PluginManagerSingleton @@ -20,37 +21,28 @@ def helperFunctionnality(options): def parseOptions(options): video = vid.Video() - video.path = _getOption(options, "--file", video.path) - video.thumbnail = _getOption(options, "--thumbnail", video.thumbnail) - video.name = _getOption(options, "--name", video.name) - video.description = _getOption(options, "--description", video.description) - video.playlistName = _getOption(options, "--playlist", video.playlistName) - video.privacy = _getOption(options, "--privacy", video.privacy) - video.category = _getOption(options, "--category", video.category) - video.tags = _getOption(options, "--tag", video.tags) - video.language = _getOption(options, "--language", video.language) - video.originalDate = _getOption(options, "--original-date", video.originalDate) + video.path = utils.getOption(options, "--file", video.path) + video.thumbnail = utils.getOption(options, "--thumbnail", video.thumbnail) + video.name = utils.getOption(options, "--name", video.name) + video.description = utils.getOption(options, "--description", video.description) + video.playlistName = utils.getOption(options, "--playlist", video.playlistName) + video.privacy = utils.getOption(options, "--privacy", video.privacy) + video.category = utils.getOption(options, "--category", video.category) + video.tags = utils.getOption(options, "--tag", video.tags) + video.language = utils.getOption(options, "--language", video.language) + video.originalDate = utils.getOption(options, "--original-date", video.originalDate) # TODO: set as an object: { "all": date1, "platformX": date2, …}? # Maybe the publishAt by platform is better placed in `self.platform` # And so publishAt would only contains the global date. - video.publishAt = _getOption(options, "--publish-at", video.publishAt) + video.publishAt = utils.getOption(options, "--publish-at", video.publishAt) # TODO: Add a list of licences - video.licence = _getOption(options, "--licence", video.licence) - video.disableComments = _getOption(options, "--disable-comments", video.disableComments) - video.nsfw = _getOption(options, "--nsfw", video.nsfw) + video.licence = utils.getOption(options, "--licence", video.licence) + video.disableComments = utils.getOption(options, "--disable-comments", video.disableComments) + video.nsfw = utils.getOption(options, "--nsfw", video.nsfw) - autoOriginalDate = _getOption(options, "--auto-original-date", False) + autoOriginalDate = utils.getOption(options, "--auto-original-date", False) if autoOriginalDate: # TODO: Implement raise NotImplementedError("--auto-original-date functionnality is not yet implemented.") return video - - -def _getOption(options, optionName, defaultValue = None): - value = options.get(optionName) - options.pop(optionName) - - if value is None: - return defaultValue - return value diff --git a/prismedia/core.py b/prismedia/core.py index fe68d07..c82909c 100644 --- a/prismedia/core.py +++ b/prismedia/core.py @@ -60,7 +60,6 @@ Plugins options: Interface plugin to use to provide the video to upload. Select the interface you want to use. If `--file` is provided instead the interface will be the command line. --platform=STRING Platforms plugins to use. Usually one platform plugin upload to one platform website (comma separated list) (default: all) --consumer=STRING Consumers plugins to use. They are executed after an upload has been done (comma separated list) (default: all) - --list-plugins List all the plugins currently installed by category. Logging options: --log=STRING Log level, between debug, info, warning, error, critical. Ignored if --quiet is set (default to info) @@ -124,7 +123,7 @@ def loadPlugins(basePluginsPath): # Define the various categories corresponding to the different # kinds of plugins you have defined pluginManager.setCategoriesFilter({ - pi.PluginTypes.DEFAULT : pi.IPlugin, + pi.PluginTypes.ALL : pi.IPrismediaBasePlugin, pi.PluginTypes.INTERFACE : pi.IInterfacePlugin, pi.PluginTypes.PLATFORM : pi.IPlatformPlugin, pi.PluginTypes.CONSUMER : pi.IConsumerPlugin, @@ -143,58 +142,55 @@ def main(): # Helper functionnalities help the user but do not upload anything if not cli.helperFunctionnality(options): - exit(0) # TODO: Magic exit code + exit(os.EX_OK) video = cli.parseOptions(options) - videos = [video] if options[""]: interface = pluginManager.getPluginByName(options[""], pi.PluginTypes.INTERFACE) - if not interface.plugin_object.prepareOptions(videos, options): - exit(0) # TODO: Magic exit code - - # TODO: Loop through videos and platforms - for v in videos: - if v.path == "": + if not interface.plugin_object.prepareOptions(video, options): + # The plugin asked to stop execution. + exit(os.EX_OK) + + if options["--platform"]: + platforms = pluginManager.getPluginsOf(categories=pi.PluginTypes.PLATFORM, name=[options["--platform"].split(",")]) + else: + platforms = pluginManager.getPluginsOfCategory(pi.PluginTypes.PLATFORM) + + if options["--consumer"]: + consumers = pluginManager.getPluginsOf(categories=pi.PluginTypes.CONSUMER, name=[options["--consumer"].split(",")]) + else: + consumers = pluginManager.getPluginsOfCategory(pi.PluginTypes.CONSUMER) + + # Let each plugin check its options before starting any upload + for plugin in [*platforms, *consumers]: + print("DEBUG:", plugin.name) + # TODO: Check this is needed or not: in case of no plugin or wrong name maybe the list is empty instead of there being a None value + if plugin is None: # TODO: log instead to error ? critical ? - print("No valid path to a video file has been provided.") - continue - - print(options) - - print() - print("# Plugins") - #def test_loadPlugins(arg): - # Loop round the plugins and print their names. - print("debug") - print(pluginManager.getAllPlugins()) - - print("all plugins") - for plugin in pluginManager.getAllPlugins(): - print(plugin.name) - # plugin.plugin_object.print_name() - - print() - print("# Video") - v = vid.Video() - v.name = "vidéo" - print(v.__dict__) - print(v.thumbnail) - -# def startInterface(): -# interface = loadPlugins() -# -# options = interface["default"].run() # Do I need this to extract basic cli? like an option "--interface=xxx" -# if options.get('--interface'): -# if interface[options.get('--interface')]: -# options = interface[options.get('--interface')].run(options) -# else: -# options = interface["cli"].run(options) -# options = interface["nfo"].run(options) -# -# def uploadToPlatforms(options): -# platforms = loadPlugins("platform") -# for platform in options.get('--platform'): -# platforms[platform].run(options) - -# TODO: REMOVE ME + print("No plugin installed name `" + plugin.name + "`.") + exit(os.EX_USAGE) + + if not plugin.plugin_object.prepareOptions(video, options): + # A plugin found ill formed options, it should have logged the precises infos + print(plugin.name + " found a malformed option.") + exit(os.EX_CONFIG) + + if video.path == "": + # TODO: log instead to error ? critical ? + print("No valid path to a video file has been provided.") + exit(os.EX_USAGE) + + print("All options validated, starting uploads onto platforms") + + for platform in platforms: + print("Uploading to: " + platform.name) + platform.plugin_object.upload(video) + + print("All uploads have been done, calling consumers plugins") + + for consumer in consumers: + print("Calling consumer: " + platform.name) + consumer.plugin_object.finished(video) + + main() diff --git a/prismedia/pluginInterfaces.py b/prismedia/pluginInterfaces.py index b22458c..ec90d44 100644 --- a/prismedia/pluginInterfaces.py +++ b/prismedia/pluginInterfaces.py @@ -3,50 +3,51 @@ from yapsy.IPlugin import IPlugin class PluginTypes(Enum): """Plugin Types possibles to instantiate in this program.""" - DEFAULT = "Default" + ALL = "All" INTERFACE = "Interface" PLATFORM = "Platform" CONSUMER = "Consumer" -### -# Interface -### -# TODO: The interface is not thought out yet -class IInterfacePlugin(IPlugin): +class IPrismediaBasePlugin(IPlugin): """ - Interface for the Interface plugin category. + Base for prismedia’s plugin. """ - def prepareOptions(self, videos, options): + def prepareOptions(self, video, options): """ Return a falsy value to exit the program. - - `videos`: list of videos to be uploaded + - `video`: video object to be uploaded - `options`: a dictionary of options to be used by Prismedia and other plugins """ raise NotImplementedError("`getOptions` must be reimplemented by %s" % self) +### +# Interface +### +class IInterfacePlugin(IPrismediaBasePlugin): + """ + Interface for the Interface plugin category. + """ + + # TODO: Add callback for communicating upload’s progress to the user + + ### # Platform ### -class IPlatformPlugin(IPlugin): +class IPlatformPlugin(IPrismediaBasePlugin): """ Interface for the Platform plugin category. """ - # def dryrun(self, video, options): - # """ - # Simulate an upload but without really uploading anything. - # """ - # raise NotImplementedError("`dryrun` must be reimplemented by %s" % self) - def hearthbeat(self): """ If needed for your platform, use a bit of the api so the platform is aware the keys are still in use. """ raise NotImplementedError("`hearthbeat` must be reimplemented by %s" % self) - def upload(self, video, options): + def upload(self, video): """ The upload function """ @@ -56,8 +57,7 @@ class IPlatformPlugin(IPlugin): ### # Consumer ### -# TODO: The interface is not thought out yet -class IConsumerPlugin(IPlugin): +class IConsumerPlugin(IPrismediaBasePlugin): """ Interface for the Consumer plugin category. """ diff --git a/prismedia/plugins/interfaces/help.py b/prismedia/plugins/interfaces/help.py index dbd9625..a8452a0 100644 --- a/prismedia/plugins/interfaces/help.py +++ b/prismedia/plugins/interfaces/help.py @@ -9,7 +9,7 @@ class Help(pi.IInterfacePlugin): For example `prismedia help help` bring this help. """ - def prepareOptions(self, videos, options): + def prepareOptions(self, video, options): pluginManager = PluginManagerSingleton.get() if options[""]: @@ -18,7 +18,12 @@ class Help(pi.IInterfacePlugin): parameters = ["help"] for p in parameters: - plugin = pluginManager.getPluginByName(p, pi.PluginTypes.DEFAULT) + plugin = pluginManager.getPluginByName(p, pi.PluginTypes.ALL) + if plugin is None: + # TODO: log instead to warning ? error ? + print("No plugin was found with name:", p) + continue + print(plugin.name + "\t" + plugin.description) print("Usage:", plugin.plugin_object.__doc__) diff --git a/prismedia/plugins/platforms/peertube.py b/prismedia/plugins/platforms/peertube.py index 89d6ce0..8f337fb 100644 --- a/prismedia/plugins/platforms/peertube.py +++ b/prismedia/plugins/platforms/peertube.py @@ -68,9 +68,13 @@ class Peertube(pi.IPlatformPlugin): """ Plugin to upload to the Peertube platform. The connetions files should be set as # TODO: EXPLAIN HOW TO SETUP THE SECRET FILES - You can provide the option `publish-at-peertube=DATE` in a configuraiton file to override the default `publish-at=DATE` for this platform. + - `publish-at-peertube=DATE`: overrides the default `publish-at=DATE` for this platform. # TODO: Maybe we will use a [] section on the config fire, explain that. """ + def prepareOptions(self, video, options): + # TODO: get the `publish-at-peertube=DATE` option + return True + def get_authenticated_service(secret): peertube_url = str(secret.get('peertube', 'peertube_url')).rstrip("/") diff --git a/prismedia/utils.py b/prismedia/utils.py index d8f66ee..3f91394 100644 --- a/prismedia/utils.py +++ b/prismedia/utils.py @@ -223,3 +223,11 @@ def cleanString(toclean): cleaned = re.sub('[^A-Za-z0-9]+', '', toclean) return cleaned + +def getOption(options, optionName, defaultValue = None): + value = options.get(optionName) + options.pop(optionName) + + if value is None: + return defaultValue + return value diff --git a/prismedia/video.py b/prismedia/video.py index 2a7091d..03fcd06 100644 --- a/prismedia/video.py +++ b/prismedia/video.py @@ -40,7 +40,7 @@ class Video(object): self._path = value else: # TODO: log instead to debug ? info ? - print("The path `" + value + "` does not contain a valid video") + print("The path `" + value + "` does not point to a video") self.path = "" @property