@ -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 connec tions 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- %d T % 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 ( instanc e_url) :
return json . loads ( self . oauth . get ( instanc e_url + " /api/v1/users/me " ) . content )
def get_userinfo ( bas e_url) :
return json . loads ( self . oauth . get ( bas e_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 ( " Hearth beat for peertube (nothing to do)" )
print ( " heart beat 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 )