Browse Source

WIP Fix typos and other recommendations from pycharm

plugins
Zykino 2 years ago
parent
commit
a2c76bcbe1
8 changed files with 92 additions and 90 deletions
  1. +5
    -4
      prismedia/cli.py
  2. +18
    -17
      prismedia/core.py
  3. +4
    -2
      prismedia/pluginInterfaces.py
  4. +5
    -4
      prismedia/plugins/interfaces/help.py
  5. +45
    -51
      prismedia/plugins/platforms/peertube.py
  6. +2
    -2
      prismedia/plugins/platforms/youtube.py
  7. +7
    -6
      prismedia/upload.py
  8. +6
    -4
      prismedia/video.py

+ 5
- 4
prismedia/cli.py View File

@ -4,13 +4,14 @@ import video as vid
from yapsy.PluginManager import PluginManagerSingleton
def helperFunctionnality(options):
def helperFunctionality(options):
pluginManager = PluginManagerSingleton.get()
optionName = "--hearthbeat"
optionName = "--heartbeat"
if options.get(optionName):
for plugin in pluginManager.getPluginsOfCategory(pi.PluginTypes.PLATFORM):
plugin.plugin_object.hearthbeat()
plugin.plugin_object.heartbeat()
return False
else:
options.pop(optionName)
@ -46,6 +47,6 @@ def parseOptions(options):
autoOriginalDate = utils.getOption(options, "--auto-original-date", False)
if autoOriginalDate:
# TODO: Implement
raise NotImplementedError("--auto-original-date functionnality is not yet implemented.")
raise NotImplementedError("--auto-original-date functionality is not yet implemented.")
return video

+ 18
- 17
prismedia/core.py View File

@ -6,11 +6,11 @@
# TODO: change `youtube-at` and `peertube-at` that are not easely expendable as options in my opinion
# TODO: remove `--url-only` and `--batch`
"""
prismedia - tool to upload videos to different platforms (historicaly Peertube and Youtube)
prismedia - tool to upload videos to different platforms (historically Peertube and Youtube)
Usage:
prismedia [options] --file=<file> | [<interface> [<parameters>...]]
prismedia --hearthbeat
prismedia --heartbeat
prismedia -h | --help | -V | --version
Options:
@ -22,7 +22,7 @@ Options:
WARN: tags with punctuation (!, ', ", ?, ...)
are not supported by Mastodon to be published from Peertube
-c, --category=STRING Category for the videos, see below. (default: Films)
--licence=STRING Creative Common licence tag (for exemple: CC-BY-SA) (default: proprietary)
--licence=STRING Creative Common licence tag (for example: CC-BY-SA) (default: proprietary)
-p, --privacy=STRING Choose between public, unlisted or private. (default: private)
--disable-comments Disable comments (Peertube only as YT API does not support) (default: comments are enabled)
--nsfw Set the video as No Safe For Work (Peertube only as YT API does not support) (default: video is safe)
@ -52,7 +52,7 @@ Options:
Only relevant if --playlist is set.
--progress=STRING Set the progress bar view, one of percentage, bigFile, accurate. [default: percentage]
--hearthbeat Use some credits to show some activity for you apikey so the platform know it is used and would not inactivate your keys.
--heartbeat Use some credits to show some activity for you apikey so the platform know it is used and would not inactivate your keys.
-h, --help Show this help. Note that calling `help` without the `--` calls a plugin showing a different help for the plugins.
-V, --version Show the version.
@ -118,6 +118,7 @@ import logging
VERSION = "prismedia v1.0.0-plugins-alpha"
def loadPlugins(basePluginsPath):
pluginManager = PluginManagerSingleton.get()
pluginManager.setPluginPlaces(basePluginsPath)
@ -145,8 +146,8 @@ def main():
# TODO: add the arguments’s verification (copy/adapt the Schema table)
options = docopt(__doc__, version=VERSION)
# Helper functionnalities help the user but do not upload anything
if not cli.helperFunctionnality(options):
# Helper functionalities help the user but do not upload anything
if not cli.helperFunctionality(options):
exit(os.EX_OK)
video = cli.parseOptions(options)
@ -160,15 +161,15 @@ def main():
logger.critical(utils.get_exception_string(e))
exit(os.EX_CONFIG)
list = utils.getOption(options, "--platform", [])
if list:
platforms = pluginManager.getPluginsOf(categories=pi.PluginTypes.PLATFORM, name=[list.split(",")])
listPlatforms = utils.getOption(options, "--platform", [])
if listPlatforms:
platforms = pluginManager.getPluginsOf(categories=pi.PluginTypes.PLATFORM, name=[listPlatforms.split(",")])
else:
platforms = pluginManager.getPluginsOfCategory(pi.PluginTypes.PLATFORM)
list = utils.getOption(options, "--consumer", None)
if list:
consumers = pluginManager.getPluginsOf(categories=pi.PluginTypes.CONSUMER, name=[list.split(",")])
listConsumers = utils.getOption(options, "--consumer", None)
if listConsumers:
consumers = pluginManager.getPluginsOf(categories=pi.PluginTypes.CONSUMER, name=[listConsumers.split(",")])
else:
consumers = pluginManager.getPluginsOfCategory(pi.PluginTypes.CONSUMER)
@ -178,14 +179,14 @@ def main():
for plugin in platforms:
# 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 ?
# TODO: log instead to error? critical?
print("No plugin installed name `" + plugin.name + "`.")
exit(os.EX_USAGE)
try:
video.platform[plugin.name] = vid.Platform()
if not plugin.plugin_object.prepare_options(video, options):
# A plugin found ill formed options, it should have logged the precises infos
# A plugin found ill formed options, it should have logged the precises info
print(plugin.name + " found a malformed option.")
exit(os.EX_CONFIG)
except Exception as e:
@ -195,13 +196,13 @@ def main():
for plugin in consumers:
# 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 ?
# TODO: log instead to error? critical?
print("No plugin installed name `" + plugin.name + "`.")
exit(os.EX_USAGE)
try:
if not plugin.plugin_object.prepare_options(video, options):
# A plugin found ill formed options, it should have logged the precises infos
# A plugin found ill formed options, it should have logged the precises info
print(plugin.name + " found a malformed option.")
exit(os.EX_CONFIG)
except Exception as e:
@ -209,7 +210,7 @@ def main():
exit(os.EX_CONFIG)
if video.path == "":
# TODO: log instead to error ? critical ?
# TODO: log instead to error? critical?
print("No valid path to a video file has been provided.")
exit(os.EX_USAGE)

+ 4
- 2
prismedia/pluginInterfaces.py View File

@ -1,6 +1,7 @@
from enum import Enum
from yapsy.IPlugin import IPlugin
class PluginTypes(Enum):
"""Plugin Types possibles to instantiate in this program."""
ALL = "All"
@ -8,6 +9,7 @@ class PluginTypes(Enum):
PLATFORM = "Platform"
CONSUMER = "Consumer"
class IPrismediaBasePlugin(IPlugin):
"""
Base for prismedias plugin.
@ -41,11 +43,11 @@ class IPlatformPlugin(IPrismediaBasePlugin):
Interface for the Platform plugin category.
"""
def hearthbeat(self):
def heartbeat(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)
raise NotImplementedError("`heartbeat` must be reimplemented by %s" % self)
def upload(self, video, options):
"""

+ 5
- 4
prismedia/plugins/interfaces/help.py View File

@ -2,10 +2,11 @@ import pluginInterfaces as pi
from yapsy.PluginManager import PluginManagerSingleton
class Help(pi.IInterfacePlugin):
"""
The help plugin print the usage informations of prismedias plugins.
Use it by simply caling `prismedia help <plugin_name>`.
The help plugin print the usage information of prismedias plugins.
Use it by simply calling `prismedia help <plugin_name>`.
For example `prismedia help help` bring this help.
"""
@ -20,7 +21,7 @@ class Help(pi.IInterfacePlugin):
for p in parameters:
plugin = pluginManager.getPluginByName(p, pi.PluginTypes.ALL)
if plugin is None:
# TODO: log instead to warning ? error ?
# TODO: log instead to warning? error?
print("No plugin was found with name:", p)
continue
@ -42,7 +43,7 @@ class Help(pi.IInterfacePlugin):
for plugin in pluginManager.getPluginsOfCategory(pi.PluginTypes.CONSUMER):
print("\t" + plugin.name)
# Print a line breack between each plugin help.
# Print a line break between each plugin help.
print()
return False

+ 45
- 51
prismedia/plugins/platforms/peertube.py View File

@ -12,7 +12,7 @@ import logging
import sys
import datetime
import pytz
from os.path import splitext, basename, abspath # TODO: remove me, we already import `os` or at least choose one
from os.path import splitext, basename, abspath # TODO: remove me, we already import `os` or at least choose one
from tzlocal import get_localzone
from configparser import RawConfigParser
@ -23,10 +23,11 @@ from clint.textui.progress import Bar as ProgressBar
logger = logging.getLogger('Prismedia')
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
The connections files should be set as # TODO: EXPLAIN HOW TO SETUP THE SECRET FILES
- `publish-at-peertube=DATE`: overrides the default `publish-at=DATE` for this platform. # TODO: Maybe we will use a [<plugin_name>] section on the config fire, explain that.
"""
SECRETS_FILE = 'peertube_secret'
@ -74,7 +75,7 @@ class Peertube(pi.IPlatformPlugin):
def __init__(self):
self.channelCreate = False
self.name = "peertube" # TODO: find if it is possible to get the plugin’s name from inside the plugin
self.name = "peertube" # TODO: find if it is possible to get the plugin’s name from inside the plugin
self.oauth = {}
self.secret = {}
@ -105,24 +106,20 @@ class Peertube(pi.IPlatformPlugin):
client_secret=str(self.secret.get('peertube', 'client_secret'))
)
def convert_peertube_date(self, date):
date = datetime.datetime.strptime(date, '%Y-%m-%dT%H:%M:%S')
tz = get_localzone()
tz = pytz.timezone(str(tz))
return tz.localize(date).isoformat()
def get_default_channel(self, user_info):
return user_info['videoChannels'][0]['id']
def get_channel_by_name(self, user_info, video):
for channel in user_info["videoChannels"]:
if channel['displayName'] == video.platform[self.name].channel:
return channel['id']
def create_channel(self, instance_url, video):
template = ('Peertube: Channel %s does not exist, creating it.')
logger.info(template % (video.platform[self.name].channel))
@ -139,8 +136,8 @@ class Peertube(pi.IPlatformPlugin):
}
try:
response = self.oauth.post(instance_url + "/api/v1/video-channels/",
data=data.encode('utf-8'),
headers=headers)
data=data.encode('utf-8'),
headers=headers)
except Exception as e:
logger.error("Peertube: " + utils.get_exception_string(e))
@ -151,25 +148,24 @@ class Peertube(pi.IPlatformPlugin):
return jresponse['id']
if response.status_code == 409:
logger.critical('Peertube: It seems there is a conflict with an existing channel named '
+ channel_name + '.'
' Please beware Peertube internal name is compiled from 20 firsts characters of channel name.'
' Also note that channel name are not case sensitive (no uppercase nor accent)'
' Please check your channel name and retry.')
+ channel_name + '.'
' Please beware Peertube internal name is compiled from 20 firsts characters of channel name.'
' Also note that channel name are not case sensitive (no uppercase nor accent)'
' Please check your channel name and retry.')
exit(1)
else:
logger.critical(('Peertube: Creating channel failed with an unexpected response: '
'%s') % response)
'%s') % response)
exit(1)
def get_default_playlist(user_info):
def get_default_playlist(self, user_info):
return user_info['videoChannels'][0]['id']
def get_playlist_by_name(instance_url, username, video):
def get_playlist_by_name(self, instance_url, username, video):
start = 0
user_playlists = json.loads(self.oauth.get(
instance_url + "/api/v1/accounts/"+username+"/video-playlists?start="+str(start)+"&count=100").content)
instance_url + "/api/v1/accounts/" + username + "/video-playlists?start=" + str(
start) + "&count=100").content)
total = user_playlists["total"]
data = user_playlists["data"]
# We need to iterate on pagination as peertube returns max 100 playlists (see #41)
@ -179,11 +175,11 @@ class Peertube(pi.IPlatformPlugin):
return playlist['id']
start = start + 100
user_playlists = json.loads(self.oauth.get(
instance_url + "/api/v1/accounts/"+username+"/video-playlists?start="+str(start)+"&count=100").content)
instance_url + "/api/v1/accounts/" + username + "/video-playlists?start=" + str(
start) + "&count=100").content)
data = user_playlists["data"]
def create_playlist(instance_url, video, channel):
def create_playlist(self, instance_url, video, channel):
template = ('Peertube: Playlist %s does not exist, creating it.')
logger.info(template % (str(video.playlistName)))
# We use files for form-data Content
@ -197,7 +193,7 @@ class Peertube(pi.IPlatformPlugin):
try:
response = self.oauth.post(instance_url + "/api/v1/video-playlists/",
files=files)
files=files)
except Exception as e:
logger.error("Peertube: " + utils.get_exception_string(e))
@ -208,11 +204,10 @@ class Peertube(pi.IPlatformPlugin):
return jresponse['id']
else:
logger.critical(('Peertube: Creating the playlist failed with an unexpected response: '
'%s') % response)
'%s') % response)
exit(1)
def set_playlist(instance_url, video_id, playlist_id):
def set_playlist(self, instance_url, video_id, playlist_id):
logger.info('Peertube: add video to playlist.')
data = '{"videoId":"' + str(video_id) + '"}'
@ -221,9 +216,9 @@ class Peertube(pi.IPlatformPlugin):
}
try:
response = self.oauth.post(instance_url + "/api/v1/video-playlists/"+str(playlist_id)+"/videos",
data=data,
headers=headers)
response = self.oauth.post(instance_url + "/api/v1/video-playlists/" + str(playlist_id) + "/videos",
data=data,
headers=headers)
except Exception as e:
logger.error("Peertube: " + utils.get_exception_string(e))
@ -232,19 +227,18 @@ class Peertube(pi.IPlatformPlugin):
logger.info('Peertube: Video is successfully added to the playlist.')
else:
logger.critical(('Peertube: Configuring the playlist failed with an unexpected response: '
'%s') % response)
'%s') % response)
exit(1)
def upload_video(self, video, options):
def get_userinfo(instance_url):
return json.loads(self.oauth.get(instance_url + "/api/v1/users/me").content)
def get_userinfo(base_url):
return json.loads(self.oauth.get(base_url + "/api/v1/users/me").content)
def get_file(path):
def get_file(video_path):
mimetypes.init()
return (basename(path), open(abspath(path), 'rb'),
mimetypes.types_map[splitext(path)[1]])
return (basename(video_path), open(abspath(video_path), 'rb'),
mimetypes.types_map[splitext(video_path)[1]])
path = video.path
instance_url = str(self.secret.get('peertube', 'peertube_url')).rstrip('/')
@ -257,7 +251,7 @@ class Peertube(pi.IPlatformPlugin):
# https://github.com/requests/toolbelt/issues/205
fields = [
("name", video.name),
("licence", "1"), # TODO: get licence from video object
("licence", "1"), # TODO: get licence from video object
("description", video.description),
("category", str(self.CATEGORY[video.category])),
("language", str(self.LANGUAGE[video.language])),
@ -274,7 +268,8 @@ class Peertube(pi.IPlatformPlugin):
continue
# Tag more than 30 chars crashes Peertube, so skip tags
if len(strtag) >= 30:
logger.warning("Peertube: Sorry, Peertube does not support tag with more than 30 characters, please reduce tag: " + strtag)
logger.warning(
"Peertube: Sorry, Peertube does not support tag with more than 30 characters, please reduce tag: " + strtag)
logger.warning("Peertube: Meanwhile, this tag will be skipped")
continue
# Peertube supports only 5 tags at the moment
@ -306,12 +301,13 @@ class Peertube(pi.IPlatformPlugin):
fields.append(("thumbnailfile", get_file(video.thumbnail)))
fields.append(("previewfile", get_file(video.thumbnail)))
if hasattr(video.platform[self.name], "channel"): # TODO: Should always be present
if hasattr(video.platform[self.name], "channel"): # TODO: Should always be present
channel_id = self.get_channel_by_name(user_info, video)
if not channel_id and self.channelCreate:
channel_id = self.create_channel(instance_url, video)
elif not channel_id:
logger.warning("Peertube: Channel `" + video.platform[self.name].channel + "` is unknown, using default channel.") # TODO: debate if we should have the same message and behavior than playlist : "does not exist, please set --channelCreate"
logger.warning("Peertube: Channel `" + video.platform[
self.name].channel + "` is unknown, using default channel.") # TODO: debate if we should have the same message and behavior than playlist: "does not exist, please set --channelCreate"
channel_id = self.get_default_channel(user_info)
else:
channel_id = self.get_default_channel(user_info)
@ -323,8 +319,9 @@ class Peertube(pi.IPlatformPlugin):
if not playlist_id and video.playlistCreate:
playlist_id = create_playlist(instance_url, video, channel_id)
elif not playlist_id:
logger.critical("Peertube: Playlist `" + video.playlistName + "` does not exist, please set --playlistCreate"
" if you want to create it")
logger.critical(
"Peertube: Playlist `" + video.playlistName + "` does not exist, please set --playlistCreate"
" if you want to create it")
exit(1)
encoder = MultipartEncoder(fields)
@ -338,8 +335,8 @@ class Peertube(pi.IPlatformPlugin):
'Content-Type': multipart_data.content_type
}
response = self.oauth.post(instance_url + "/api/v1/videos/upload",
data=multipart_data,
headers=headers)
data=multipart_data,
headers=headers)
if response is not None:
if response.status_code == 200:
@ -357,10 +354,9 @@ class Peertube(pi.IPlatformPlugin):
set_playlist(instance_url, video_id, playlist_id)
else:
logger.critical(('Peertube: The upload failed with an unexpected response: '
'%s') % response)
'%s') % response)
exit(1)
# upload_finished = False
# def create_callback(encoder, progress_type):
# upload_size_MB = encoder.len * (1 / (1024 * 1024))
@ -396,16 +392,14 @@ class Peertube(pi.IPlatformPlugin):
#
# return callback
def hearthbeat(self):
def heartbeat(self):
"""
If needed for your platform, use a bit of the api so the platform is aware the keys are still in use.
"""
print("Hearthbeat for peertube (nothing to do)")
print("heartbeat for peertube (nothing to do)")
pass
def upload(self, video, options):
# def run(options):
def upload(self, video, options):
logger.info('Peertube: Uploading video...')
self.upload_video(video, options)

+ 2
- 2
prismedia/plugins/platforms/youtube.py View File

@ -373,7 +373,7 @@ def resumable_upload(request, resource, method, options):
time.sleep(sleep_seconds)
def hearthbeat():
def heartbeat():
"""Use the minimums credits possibles of the API so google does not readuce to 0 the allowed credits.
This apparently happens after 90 days without any usage of credits.
For more info see the official documentations:
@ -384,7 +384,7 @@ def hearthbeat():
try:
get_playlist_by_name(youtube, "Foo")
except HttpError as e:
logger.error('Youtube: An HTTP error %d occurred on hearthbeat:\n%s' %
logger.error('Youtube: An HTTP error %d occurred on heartbeat:\n%s' %
(e.resp.status, e.content))

+ 7
- 6
prismedia/upload.py View File

@ -7,7 +7,7 @@ prismedia - tool to upload videos to Peertube and Youtube
Usage:
prismedia --file=<FILE> [options]
prismedia -f <FILE> --tags=STRING [options]
prismedia --hearthbeat
prismedia --heartbeat
prismedia -h | --help
prismedia --version
@ -52,7 +52,7 @@ Options:
Only relevant if --playlist is set.
--progress=STRING Set the progress bar view, one of percentage, bigFile (MB), accurate (KB).
--hearthbeat Use some credits to show some activity for you apikey so the platform know it is used and would not put your quota to 0 (only Youtube currently)
--heartbeat Use some credits to show some activity for you apikey so the platform know it is used and would not put your quota to 0 (only Youtube currently)
-h --help Show this help.
--version Show version.
@ -109,7 +109,6 @@ if sys.version_info[0] < 3:
import os
import datetime
import logging
logger = logging.getLogger('Prismedia')
from docopt import docopt
@ -117,6 +116,8 @@ from . import yt_upload
from . import pt_upload
from . import utils
logger = logging.getLogger('Prismedia')
try:
# noinspection PyUnresolvedReferences
from schema import Schema, And, Or, Optional, SchemaError, Hook, Use
@ -289,15 +290,15 @@ def main():
Optional('--playlist'): Or(None, str),
Optional('--playlistCreate'): bool,
Optional('--progress'): Or(None, And(str, validateProgress, error="Sorry, progress visualisation not supported")),
'--hearthbeat': bool,
'--heartbeat': bool,
'--help': bool,
'--version': bool,
# This allow to return all other options for further use: https://github.com/keleshev/schema#extra-keys
object: object
})
if options.get('--hearthbeat'):
yt_upload.hearthbeat()
if options.get('--heartbeat'):
yt_upload.heartbeat()
exit(0)
# We need to validate early options first as withNFO and logs options should be prioritized

+ 6
- 4
prismedia/video.py View File

@ -1,5 +1,6 @@
from os.path import dirname, splitext, basename, isfile, normpath, expanduser
class Platform(object):
"""
Store data representing a Platform.
@ -13,6 +14,7 @@ class Platform(object):
def __repr__(self):
return str(self.__dict__)
# TODO: Add container for `with-*` and a `isValid` method to check that all `with-*` options are present
# TODO: We need some list (using enum?) for the commons licences, language, privacy, categories options
class Video(object):
@ -59,13 +61,13 @@ class Video(object):
elif isfile(path):
self._path = path
else:
# TODO: log instead to debug ? info ?
# TODO: log instead to debug? info?
print("The path `" + value + "` does not point to a video")
self._path = ""
@property
def thumbnail(self):
if not self._thumbnail is None:
if self._thumbnail is not None:
return self._thumbnail
else:
result = None
@ -89,7 +91,7 @@ class Video(object):
elif isfile(video_directory + video_file + ".jpeg"):
result = video_directory + video_file + ".jpeg"
# TODO: move to caller. Logging the output is its resporsability
# TODO: move to caller. Logging the output is its responsibility
# Display some info after research
# if not result:
# logger.debug("No thumbnail has been found, continuing")
@ -104,7 +106,7 @@ class Video(object):
@property
def name(self):
if not self._name is None:
if self._name is not None:
return self._name
else:
return splitext(basename(self.path))[0]

Loading…
Cancel
Save