add 4 directories
This commit is contained in:
parent
b0eba86279
commit
0879efb8ec
18
img2toot_v3/config.ini
Executable file
18
img2toot_v3/config.ini
Executable file
|
@ -0,0 +1,18 @@
|
|||
[mastodon]
|
||||
client_id=
|
||||
client_secret=
|
||||
access_token=
|
||||
mastodon_hostname=botsin.space
|
||||
|
||||
[toot]
|
||||
status=Le curvy, c'est la vie ! 😍
|
||||
hashtag=#NSFW
|
||||
;Default visibility is the same as your configuration profil
|
||||
;but you can override it:'public', 'unlisted', 'private', 'direct'
|
||||
;visibility=public
|
||||
;visibility=private
|
||||
;visibility=unlisted
|
||||
;Default sensitive is True, but you can override it:
|
||||
;sensitive=False
|
||||
;Default spoiler text is None, but you can override it:
|
||||
;spoiler=''\00
|
117
img2toot_v3/img2toot.py
Executable file
117
img2toot_v3/img2toot.py
Executable file
|
@ -0,0 +1,117 @@
|
|||
#!/usr/bin/python3
|
||||
# coding: utf-8
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
from mastodon import Mastodon
|
||||
import os
|
||||
import random
|
||||
import sys
|
||||
import argparse
|
||||
from configparser import ConfigParser
|
||||
|
||||
__prog_name__ = 'img2toot'
|
||||
__version__ = '0.3'
|
||||
__description__ = 'Toot bot for random local NSFW image for Mastodon'
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Read arguments
|
||||
parser = argparse.ArgumentParser(prog=__prog_name__,
|
||||
description=__description__)
|
||||
parser.add_argument('--version', action='version', version=__version__)
|
||||
parser.add_argument('-d', '--dir', required=True, help="Image\'s directory")
|
||||
parser.add_argument('-c', '--config', default='config.ini',
|
||||
help="Config file (default: %(default)s)")
|
||||
args = parser.parse_args()
|
||||
config_filepath = args.config
|
||||
|
||||
# Check if config file exists
|
||||
if not os.path.isfile(config_filepath):
|
||||
print("Config file %s not found, exiting." % config_filepath)
|
||||
sys.exit(0)
|
||||
else:
|
||||
# Read config file
|
||||
conf = ConfigParser()
|
||||
conf.read(config_filepath)
|
||||
|
||||
# Need a directory
|
||||
if not args.dir:
|
||||
print("Image\'s directory argument missing")
|
||||
sys.exit(0)
|
||||
image_dir = args.dir + "/"
|
||||
|
||||
# Overwrite default settings
|
||||
if conf.has_option('toot', 'visibility'):
|
||||
toot_visibility = conf['toot']['visibility']
|
||||
else:
|
||||
toot_visibility = ''
|
||||
|
||||
if conf.has_option('toot', 'sensitive'):
|
||||
toot_sensitive = conf['toot']['sensitive']
|
||||
else:
|
||||
toot_sensitive = True
|
||||
|
||||
if conf.has_option('toot', 'spoiler'):
|
||||
toot_spoiler = conf['toot']['spoiler']
|
||||
else:
|
||||
toot_spoiler = None
|
||||
|
||||
# Log into Mastodon if enabled in settings
|
||||
mastodon_hostname = conf['mastodon']['mastodon_hostname']
|
||||
try:
|
||||
mastodonAPI = Mastodon(
|
||||
client_id=conf['mastodon']['client_id'],
|
||||
client_secret=conf['mastodon']['client_secret'],
|
||||
access_token=conf['mastodon']['access_token'],
|
||||
api_base_url='https://' + mastodon_hostname)
|
||||
masto_username = mastodonAPI.account_verify_credentials()['username']
|
||||
print ('[ OK ] Sucessfully authenticated on ' + mastodon_hostname
|
||||
+ ' as @' + masto_username)
|
||||
except BaseException as e:
|
||||
print ('[ERROR] Error while logging into Mastodon:', str(e))
|
||||
sys.exit(0)
|
||||
|
||||
#Prepare media IDs
|
||||
try:
|
||||
mfile = random.choice(os.listdir(image_dir))
|
||||
image_byte = open(image_dir + mfile, "rb").read()
|
||||
|
||||
if mfile[-3:] == "jpe":
|
||||
mime = "image/jpeg"
|
||||
elif mfile[-3:] == "jpg":
|
||||
mime = "image/jpeg"
|
||||
elif mfile[-3:] == "png":
|
||||
mime = "image/png"
|
||||
elif mfile[-3:] == "gif":
|
||||
mime = "image/gif"
|
||||
elif mfile[-3:] == "gifv":
|
||||
mime = "video/mp4"
|
||||
elif mfile[-3:] == "mp4":
|
||||
mime = "video/mp4"
|
||||
else:
|
||||
print("Incorrect media file format")
|
||||
|
||||
media_dict = mastodonAPI.media_post(image_byte, mime)
|
||||
except BaseException as e:
|
||||
print ('[ERROR] Error while reading media file : ' + str(e))
|
||||
sys.exit(0)
|
||||
|
||||
# Post the toot
|
||||
toot_status = conf['toot']['status']
|
||||
toot_status += '\n'
|
||||
toot_status += conf['toot']['hashtag']
|
||||
try:
|
||||
status = mastodonAPI.status_post(
|
||||
status=toot_status,
|
||||
in_reply_to_id=None,
|
||||
media_ids=[media_dict],
|
||||
sensitive=toot_sensitive,
|
||||
visibility=toot_visibility,
|
||||
spoiler_text=toot_spoiler
|
||||
)
|
||||
print (
|
||||
'[ OK ] Posting this on Mastodon account with media attachment : '
|
||||
+ status['url'])
|
||||
except BaseException as e:
|
||||
print ('[ERROR] Error while posting toot:' + str(e))
|
30
playlist2toot_v2/config.ini
Executable file
30
playlist2toot_v2/config.ini
Executable file
|
@ -0,0 +1,30 @@
|
|||
[mastodon]
|
||||
client_id=
|
||||
client_secret=
|
||||
access_token=
|
||||
mastodon_hostname=botsin.space
|
||||
|
||||
[toot]
|
||||
status=
|
||||
hashtag=#PouetRadio #TootRadio
|
||||
;Default visibility is the same as your configuration profil
|
||||
;but you can override it:'public', 'unlisted', 'private', 'direct'
|
||||
;visibility=public
|
||||
;visibility=private
|
||||
;visibility=unlisted
|
||||
;Default sensitive is False, but you can override it:
|
||||
;sensitive=True
|
||||
;Default spoiler text is None, but you can override it:
|
||||
;spoiler=Lorem ipsum
|
||||
|
||||
[preset]
|
||||
;Default time delay beetween 2 toot (in sec)
|
||||
delay=180
|
||||
;Use the videos duration beetween 2 toot [False, True]
|
||||
;useduration=False
|
||||
useduration=True
|
||||
;Make a thread [False, True]
|
||||
;thread=False
|
||||
thread=True
|
||||
;default thumbnail directory name
|
||||
dirthumbnail=thumbnails
|
3
playlist2toot_v2/playlist.txt
Executable file
3
playlist2toot_v2/playlist.txt
Executable file
|
@ -0,0 +1,3 @@
|
|||
commentaire1;https://www.youtube.com/watch?v=R7cPptwFZM8;#blues
|
||||
commentaire2;https://www.youtube.com/watch?v=WK2siEQsADk;#rock
|
||||
commentaire3;https://www.youtube.com/watch?v=202fjZZO-tI;#bluesrock
|
173
playlist2toot_v2/playlist2toot.py
Executable file
173
playlist2toot_v2/playlist2toot.py
Executable file
|
@ -0,0 +1,173 @@
|
|||
#!/usr/bin/python3
|
||||
# coding: utf-8
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
from mastodon import Mastodon
|
||||
import os
|
||||
import time
|
||||
import sys
|
||||
import argparse
|
||||
from configparser import ConfigParser
|
||||
import ytscraper
|
||||
|
||||
__prog_name__ = 'playlist2toot'
|
||||
__version__ = '0.2'
|
||||
__description__ = 'Toot a playlist on Mastodon'
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Read arguments
|
||||
parser = argparse.ArgumentParser(prog=__prog_name__,
|
||||
description=__description__)
|
||||
parser.add_argument('--version', action='version', version=__version__)
|
||||
parser.add_argument('-p', '--playlist', required=True,
|
||||
help="Playlist text file")
|
||||
parser.add_argument('-c', '--config', default='config.ini',
|
||||
help="Config file (default: %(default)s)")
|
||||
args = parser.parse_args()
|
||||
config_filepath = args.config
|
||||
|
||||
# Check if config file exists
|
||||
if not os.path.isfile(config_filepath):
|
||||
print("Config file %s not found, exiting." % config_filepath)
|
||||
sys.exit(0)
|
||||
else:
|
||||
# Read config file
|
||||
conf = ConfigParser()
|
||||
conf.read(config_filepath)
|
||||
|
||||
# Load the playlist file
|
||||
with open(args.playlist, "r") as fichier:
|
||||
playlist_mem = fichier.readlines()
|
||||
|
||||
# Overwrite default settings
|
||||
if conf.has_option('toot', 'status'):
|
||||
toot_status = conf['toot']['status'] + '\n'
|
||||
else:
|
||||
toot_status = ''
|
||||
|
||||
if conf.has_option('toot', 'visibility'):
|
||||
toot_visibility = conf['toot']['visibility']
|
||||
else:
|
||||
toot_visibility = ''
|
||||
|
||||
if conf.has_option('toot', 'sensitive'):
|
||||
toot_sensitive = conf['toot']['sensitive']
|
||||
else:
|
||||
toot_sensitive = False
|
||||
|
||||
if conf.has_option('toot', 'spoiler'):
|
||||
toot_spoiler = conf['toot']['spoiler']
|
||||
else:
|
||||
toot_spoiler = None
|
||||
|
||||
#used bay make a thread
|
||||
if conf.has_option('preset', 'thread'):
|
||||
toot_lastid = None
|
||||
|
||||
# Log into Mastodon if enabled in settings
|
||||
print('[ OK ] {} Let the show begin !'.format(time.strftime('%H:%M')))
|
||||
mastodon_hostname = conf['mastodon']['mastodon_hostname']
|
||||
try:
|
||||
mastodonAPI = Mastodon(
|
||||
client_id=conf['mastodon']['client_id'],
|
||||
client_secret=conf['mastodon']['client_secret'],
|
||||
access_token=conf['mastodon']['access_token'],
|
||||
api_base_url='https://' + mastodon_hostname
|
||||
)
|
||||
masto_username = mastodonAPI.account_verify_credentials()['username']
|
||||
print('[ OK ] {} Sucessfully authenticated on {} as @{}'.format(
|
||||
time.strftime('%H:%M'), mastodon_hostname, masto_username))
|
||||
except BaseException as e:
|
||||
print('[ERROR] Error while logging into Mastodon:', str(e))
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
for i in range(len(playlist_mem)):
|
||||
# Prepare the toot
|
||||
if conf.has_option('toot', 'status'):
|
||||
toot_status = conf['toot']['status'] + '\n'
|
||||
else:
|
||||
toot_status = ''
|
||||
# video commentary
|
||||
toot_status += playlist_mem[i].split(";")[0]
|
||||
toot_status += '\n'
|
||||
# video title
|
||||
video = ytscraper.scrape_url(playlist_mem[i].split(";")[1])
|
||||
toot_status += video.title
|
||||
toot_status += '\n'
|
||||
toot_status += video.yturl
|
||||
# add hashtag
|
||||
toot_status += '\n'
|
||||
toot_status += conf['toot']['hashtag']
|
||||
toot_status += ' '
|
||||
toot_status += playlist_mem[i].split(";")[2]
|
||||
|
||||
# Prepare media IDs
|
||||
try:
|
||||
paththumbnail = './' + conf['preset']['dirthumbnail']
|
||||
mfile = ytscraper.download_image(
|
||||
video.thumbnail,
|
||||
video.videoid,
|
||||
paththumbnail
|
||||
)
|
||||
image_byte = open(mfile, "rb").read()
|
||||
|
||||
if mfile[-3:] == "jpe":
|
||||
mime = "image/jpeg"
|
||||
elif mfile[-3:] == "jpg":
|
||||
mime = "image/jpeg"
|
||||
elif mfile[-3:] == "png":
|
||||
mime = "image/png"
|
||||
elif mfile[-3:] == "gif":
|
||||
mime = "image/gif"
|
||||
elif mfile[-3:] == "gifv":
|
||||
mime = "video/mp4"
|
||||
elif mfile[-3:] == "mp4":
|
||||
mime = "video/mp4"
|
||||
else:
|
||||
print("Incorrect media file format")
|
||||
|
||||
media_dict = mastodonAPI.media_post(image_byte, mime)
|
||||
except BaseException as e:
|
||||
print ('[ERROR] Error while reading media file : ' + str(e))
|
||||
sys.exit(0)
|
||||
|
||||
# Post the toot
|
||||
try:
|
||||
status = mastodonAPI.status_post(
|
||||
status=toot_status,
|
||||
in_reply_to_id=toot_lastid,
|
||||
media_ids=[media_dict],
|
||||
sensitive=toot_sensitive,
|
||||
visibility=toot_visibility,
|
||||
spoiler_text=toot_spoiler
|
||||
)
|
||||
print('[ OK ] {} Posting this on Mastodon account : {}'.format(
|
||||
time.strftime('%H:%M'), status['url']))
|
||||
except BaseException as e:
|
||||
print('[ERROR] Error while posting toot:' + str(e))
|
||||
sys.exit(0)
|
||||
|
||||
# make a thread
|
||||
if conf.getboolean('preset', 'thread'):
|
||||
toot_lastid = status['id']
|
||||
else:
|
||||
toot_lastid = None
|
||||
|
||||
# make a pause
|
||||
print('use duration = ' + conf['preset']['useduration'])
|
||||
print('delay = ' + conf['preset']['delay'])
|
||||
if conf.getboolean('preset', 'useduration'):
|
||||
preset_delay = video.durationinseconds
|
||||
else:
|
||||
print('delay = ' + conf['preset']['delay'])
|
||||
preset_delay = int(conf['preset']['delay'])
|
||||
print('preset_delay = ' + str(preset_delay), type(preset_delay))
|
||||
|
||||
if i < (len(playlist_mem) - 1):
|
||||
time.sleep(preset_delay)
|
||||
|
||||
# The End
|
||||
print('[ OK ] {} The show is over !'.format(time.strftime('%H:%M')))
|
3
playlist2toot_v2/requirements.txt
Executable file
3
playlist2toot_v2/requirements.txt
Executable file
|
@ -0,0 +1,3 @@
|
|||
Mastodon.py
|
||||
argparse
|
||||
ConfigParser
|
82
playlist2toot_v2/ytscraper.py
Executable file
82
playlist2toot_v2/ytscraper.py
Executable file
|
@ -0,0 +1,82 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from urllib.request import urlopen, urlretrieve
|
||||
import re
|
||||
import os
|
||||
from datetime import timedelta
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
"""
|
||||
based on youtube-scraper (https://github.com/narfman0/youtube-scraper)
|
||||
"""
|
||||
|
||||
|
||||
class YoutubeScrape(object):
|
||||
""" Scraper object to hold data """
|
||||
def __init__(self, soup):
|
||||
""" Initialize and scrape """
|
||||
self.soup = soup
|
||||
#self.title = self.parse_string('.watch-title')
|
||||
self.title = self.parse_string({'name': 'title'})
|
||||
self.artist = self.parse_string_o('.yt-user-info')
|
||||
self.duration = self.parse_string({'itemprop': 'duration'})
|
||||
self.durationinseconds = self.parseISO8591(self.duration)
|
||||
self.durationtime = str(timedelta(seconds=self.durationinseconds))
|
||||
self.poster = self.parse_string_o('.yt-user-info')
|
||||
self.views = self.parse_int('.watch-view-count')
|
||||
self.published = self.parse_string_o('.watch-time-text')
|
||||
self.published = re.sub(r'(Published|Uploaded) on', '',
|
||||
self.published).strip()
|
||||
#self.like = self.parse_int('#watch-like')
|
||||
#self.dislike = self.parse_int('#watch-dislike')
|
||||
self.yturl = self.parse_string({'property': "og:url"})
|
||||
self.thumbnail = self.parse_string({'property': "og:image"})
|
||||
self.videoid = self.parse_string({'itemprop': 'videoId'})
|
||||
|
||||
def parse_int(self, selector):
|
||||
""" Extract one integer element from soup """
|
||||
return int(re.sub('[^0-9]', '', self.parse_string_o(selector)))
|
||||
|
||||
def parse_string(self, selector):
|
||||
""" Extract one particular element from soup """
|
||||
return self.soup.find_all(attrs=selector)[0]['content']
|
||||
|
||||
def parse_string_o(self, selector):
|
||||
""" Extract one particular element from soup """
|
||||
return self.soup.select(selector)[0].get_text().strip()
|
||||
|
||||
def parseISO8591(self, duration):
|
||||
""" Parse ISO 8591 formated duration """
|
||||
regex = re.compile(r'PT((\d{1,3})H)?((\d{1,3})M)?((\d{1,2})S)?')
|
||||
if duration:
|
||||
duration = regex.findall(duration)
|
||||
if len(duration) > 0:
|
||||
_, hours, _, minutes, _, seconds = duration[0]
|
||||
duration = [seconds, minutes, hours]
|
||||
duration = [int(v) if len(v) > 0 else 0 for v in duration]
|
||||
duration = sum([60**p*v for p, v in enumerate(duration)])
|
||||
else:
|
||||
duration = 30
|
||||
else:
|
||||
duration = 30
|
||||
return duration
|
||||
|
||||
|
||||
def scrape_html(html):
|
||||
""" Return meta information about a video """
|
||||
soup = BeautifulSoup(html, "html.parser")
|
||||
return YoutubeScrape(soup)
|
||||
|
||||
|
||||
def scrape_url(url):
|
||||
""" Scrape a given url for youtube information """
|
||||
html = urlopen(url)
|
||||
return YoutubeScrape(BeautifulSoup(html, "html.parser"))
|
||||
|
||||
|
||||
def download_image(urlthumbnail, videoid, path):
|
||||
"""Download the thumbnail"""
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
local_filename, headers = urlretrieve(urlthumbnail,
|
||||
path + '/maxresdefault-' + videoid + '.jpg')
|
||||
return local_filename
|
18
tootytvideo_v1/config.ini
Executable file
18
tootytvideo_v1/config.ini
Executable file
|
@ -0,0 +1,18 @@
|
|||
[mastodon]
|
||||
client_id=
|
||||
client_secret=
|
||||
access_token=
|
||||
mastodon_hostname=botsin.space
|
||||
|
||||
[toot]
|
||||
status=
|
||||
hashtag=#PouetRadio #TootRadio
|
||||
;Default visibility is the same as your configuration profil
|
||||
;but you can override it:'public', 'unlisted', 'private', 'direct'
|
||||
;visibility=public
|
||||
;visibility=private
|
||||
;visibility=unlisted
|
||||
;Default sensitive is False, but you can override it:
|
||||
;sensitive=True
|
||||
;Default spoiler text is None, but you can override it:
|
||||
;spoiler=Lorem ipsum
|
156
tootytvideo_v1/tootytvideo.py
Executable file
156
tootytvideo_v1/tootytvideo.py
Executable file
|
@ -0,0 +1,156 @@
|
|||
#!/usr/bin/python3
|
||||
# coding: utf-8
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
from mastodon import Mastodon
|
||||
import os
|
||||
import time
|
||||
import sys
|
||||
import argparse
|
||||
from configparser import ConfigParser
|
||||
import ytscraper
|
||||
|
||||
__prog_name__ = 'tootytvideo'
|
||||
__version__ = '0.1'
|
||||
__description__ = 'Toot a youtube video on Mastodon'
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Read arguments
|
||||
parser = argparse.ArgumentParser(prog=__prog_name__,
|
||||
description=__description__)
|
||||
parser.add_argument('--version', action='version', version=__version__)
|
||||
parser.add_argument('-c', '--config', default='config.ini',
|
||||
help="Config file (default: %(default)s)")
|
||||
args = parser.parse_args()
|
||||
config_filepath = args.config
|
||||
|
||||
# Check if config file exists
|
||||
if not os.path.isfile(config_filepath):
|
||||
print("Config file %s not found, exiting." % config_filepath)
|
||||
sys.exit(0)
|
||||
else:
|
||||
# Read config file
|
||||
conf = ConfigParser()
|
||||
conf.read(config_filepath)
|
||||
|
||||
# Overwrite default settings
|
||||
if conf.has_option('toot', 'status'):
|
||||
toot_status = conf['toot']['status'] + '\n'
|
||||
else:
|
||||
toot_status = ''
|
||||
|
||||
if conf.has_option('toot', 'visibility'):
|
||||
toot_visibility = conf['toot']['visibility']
|
||||
else:
|
||||
toot_visibility = ''
|
||||
|
||||
if conf.has_option('toot', 'sensitive'):
|
||||
toot_sensitive = conf['toot']['sensitive']
|
||||
else:
|
||||
toot_sensitive = False
|
||||
|
||||
if conf.has_option('toot', 'spoiler'):
|
||||
toot_spoiler = conf['toot']['spoiler']
|
||||
else:
|
||||
toot_spoiler = None
|
||||
|
||||
# Log into Mastodon if enabled in settings
|
||||
print('[ OK ] {} Login'.format(time.strftime('%H:%M')))
|
||||
mastodon_hostname = conf['mastodon']['mastodon_hostname']
|
||||
try:
|
||||
mastodonAPI = Mastodon(
|
||||
client_id=conf['mastodon']['client_id'],
|
||||
client_secret=conf['mastodon']['client_secret'],
|
||||
access_token=conf['mastodon']['access_token'],
|
||||
api_base_url='https://' + mastodon_hostname
|
||||
)
|
||||
masto_username = mastodonAPI.account_verify_credentials()['username']
|
||||
print('[ OK ] {} Sucessfully authenticated on {} as @{}'.format(
|
||||
time.strftime('%H:%M'), mastodon_hostname, masto_username))
|
||||
except BaseException as e:
|
||||
print('[ERROR] Error while logging into Mastodon:', str(e))
|
||||
sys.exit(0)
|
||||
# Run
|
||||
resp = True
|
||||
|
||||
while resp:
|
||||
print('+- New toot -+')
|
||||
yturl = input('Youtube URL : ')
|
||||
comment = input('Add a comment : ')
|
||||
hashtag = input('Add hastag : ')
|
||||
|
||||
# Prepare the toot
|
||||
if conf.has_option('toot', 'status'):
|
||||
toot_status = conf['toot']['status'] + '\n'
|
||||
else:
|
||||
toot_status = ''
|
||||
# video commentary
|
||||
toot_status += comment
|
||||
toot_status += '\n'
|
||||
# video title
|
||||
video = ytscraper.scrape_url(yturl)
|
||||
toot_status += video.title
|
||||
toot_status += '\n'
|
||||
toot_status += video.yturl
|
||||
# add hashtag
|
||||
toot_status += '\n'
|
||||
toot_status += conf['toot']['hashtag']
|
||||
toot_status += ' '
|
||||
toot_status += hashtag
|
||||
|
||||
# Prepare media IDs
|
||||
try:
|
||||
mfile = ytscraper.download_image(
|
||||
video.thumbnail,
|
||||
video.videoid,
|
||||
'.'
|
||||
)
|
||||
image_byte = open(mfile, "rb").read()
|
||||
|
||||
if mfile[-3:] == "jpe":
|
||||
mime = "image/jpeg"
|
||||
elif mfile[-3:] == "jpg":
|
||||
mime = "image/jpeg"
|
||||
elif mfile[-3:] == "png":
|
||||
mime = "image/png"
|
||||
elif mfile[-3:] == "gif":
|
||||
mime = "image/gif"
|
||||
elif mfile[-3:] == "gifv":
|
||||
mime = "video/mp4"
|
||||
elif mfile[-3:] == "mp4":
|
||||
mime = "video/mp4"
|
||||
else:
|
||||
print("Incorrect media file format")
|
||||
|
||||
media_dict = mastodonAPI.media_post(image_byte, mime)
|
||||
except BaseException as e:
|
||||
print ('[ERROR] Error while reading media file : ' + str(e))
|
||||
sys.exit(0)
|
||||
|
||||
# Post the toot
|
||||
try:
|
||||
status = mastodonAPI.status_post(
|
||||
status=toot_status,
|
||||
in_reply_to_id=None,
|
||||
media_ids=[media_dict],
|
||||
sensitive=toot_sensitive,
|
||||
visibility=toot_visibility,
|
||||
spoiler_text=toot_spoiler
|
||||
)
|
||||
print('[ OK ] {} Posting this on Mastodon account : {}'.format(
|
||||
time.strftime('%H:%M'), status['url']))
|
||||
except BaseException as e:
|
||||
print('[ERROR] Error while posting toot:' + str(e))
|
||||
sys.exit(0)
|
||||
|
||||
# make a pause
|
||||
r = input('Continue (y/n)? ')
|
||||
if r.lower() == 'y':
|
||||
resp = True
|
||||
else:
|
||||
resp = False
|
||||
|
||||
# The End
|
||||
print('[ OK ] {} The show is over !'.format(time.strftime('%H:%M')))
|
82
tootytvideo_v1/ytscraper.py
Executable file
82
tootytvideo_v1/ytscraper.py
Executable file
|
@ -0,0 +1,82 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from urllib.request import urlopen, urlretrieve
|
||||
import re
|
||||
import os
|
||||
from datetime import timedelta
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
"""
|
||||
based on youtube-scraper (https://github.com/narfman0/youtube-scraper)
|
||||
"""
|
||||
|
||||
|
||||
class YoutubeScrape(object):
|
||||
""" Scraper object to hold data """
|
||||
def __init__(self, soup):
|
||||
""" Initialize and scrape """
|
||||
self.soup = soup
|
||||
#self.title = self.parse_string('.watch-title')
|
||||
self.title = self.parse_string({'name': 'title'})
|
||||
self.artist = self.parse_string_o('.yt-user-info')
|
||||
self.duration = self.parse_string({'itemprop': 'duration'})
|
||||
self.durationinseconds = self.parseISO8591(self.duration)
|
||||
self.durationtime = str(timedelta(seconds=self.durationinseconds))
|
||||
self.poster = self.parse_string_o('.yt-user-info')
|
||||
self.views = self.parse_int('.watch-view-count')
|
||||
self.published = self.parse_string_o('.watch-time-text')
|
||||
self.published = re.sub(r'(Published|Uploaded) on', '',
|
||||
self.published).strip()
|
||||
#self.like = self.parse_int('#watch-like')
|
||||
#self.dislike = self.parse_int('#watch-dislike')
|
||||
self.yturl = self.parse_string({'property': "og:url"})
|
||||
self.thumbnail = self.parse_string({'property': "og:image"})
|
||||
self.videoid = self.parse_string({'itemprop': 'videoId'})
|
||||
|
||||
def parse_int(self, selector):
|
||||
""" Extract one integer element from soup """
|
||||
return int(re.sub('[^0-9]', '', self.parse_string_o(selector)))
|
||||
|
||||
def parse_string(self, selector):
|
||||
""" Extract one particular element from soup """
|
||||
return self.soup.find_all(attrs=selector)[0]['content']
|
||||
|
||||
def parse_string_o(self, selector):
|
||||
""" Extract one particular element from soup """
|
||||
return self.soup.select(selector)[0].get_text().strip()
|
||||
|
||||
def parseISO8591(self, duration):
|
||||
""" Parse ISO 8591 formated duration """
|
||||
regex = re.compile(r'PT((\d{1,3})H)?((\d{1,3})M)?((\d{1,2})S)?')
|
||||
if duration:
|
||||
duration = regex.findall(duration)
|
||||
if len(duration) > 0:
|
||||
_, hours, _, minutes, _, seconds = duration[0]
|
||||
duration = [seconds, minutes, hours]
|
||||
duration = [int(v) if len(v) > 0 else 0 for v in duration]
|
||||
duration = sum([60**p*v for p, v in enumerate(duration)])
|
||||
else:
|
||||
duration = 30
|
||||
else:
|
||||
duration = 30
|
||||
return duration
|
||||
|
||||
|
||||
def scrape_html(html):
|
||||
""" Return meta information about a video """
|
||||
soup = BeautifulSoup(html, "html.parser")
|
||||
return YoutubeScrape(soup)
|
||||
|
||||
|
||||
def scrape_url(url):
|
||||
""" Scrape a given url for youtube information """
|
||||
html = urlopen(url)
|
||||
return YoutubeScrape(BeautifulSoup(html, "html.parser"))
|
||||
|
||||
|
||||
def download_image(urlthumbnail, videoid, path):
|
||||
"""Download the thumbnail"""
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
local_filename, headers = urlretrieve(urlthumbnail,
|
||||
path + '/maxresdefault-' + videoid + '.jpg')
|
||||
return local_filename
|
18
txt2toot/config.ini
Executable file
18
txt2toot/config.ini
Executable file
|
@ -0,0 +1,18 @@
|
|||
[mastodon]
|
||||
client_id=
|
||||
client_secret=
|
||||
access_token=
|
||||
mastodon_hostname=botsin.space
|
||||
|
||||
[toot]
|
||||
status=le beau texte :
|
||||
hashtag=#txtbot
|
||||
;Default visibility is the same as your configuration profil
|
||||
;but you can override it:'public', 'unlisted', 'private', 'direct'
|
||||
;visibility=public
|
||||
;visibility=private
|
||||
;visibility=unlisted
|
||||
;Default sensitive is False, but you can override it:
|
||||
;sensitive=True
|
||||
;Default spoiler text is None, but you can override it:
|
||||
;spoiler=Lorem ipsum
|
1
txt2toot/txt/Documen561ezft 2 sans titre
Executable file
1
txt2toot/txt/Documen561ezft 2 sans titre
Executable file
|
@ -0,0 +1 @@
|
|||
Quibus ita sceleste patratis Paulus cruore perfusus reversusque ad principis castra multos coopertos paene catenis adduxit in squalorem deiectos atque maestitiam, quorum adventu intendebantur eculei uncosque parabat carnifex et tormenta. et ex is proscripti sunt plures actique in exilium alii, non nullos gladii consumpsere poenales. nec enim quisquam facile meminit sub Constantio, ubi susurro tenus haec movebantur, quemquam absolutum.
|
1
txt2toot/txt/qzefqefe515zefdcs
Executable file
1
txt2toot/txt/qzefqefe515zefdcs
Executable file
|
@ -0,0 +1 @@
|
|||
Dum haec in oriente aguntur, Arelate hiemem agens Constantius post theatralis ludos atque circenses ambitioso editos apparatu diem sextum idus Octobres, qui imperii eius annum tricensimum terminabat, insolentiae pondera gravius librans, siquid dubium deferebatur aut falsum, pro liquido accipiens et conperto, inter alia excarnificatum Gerontium Magnentianae comitem partis exulari maerore multavit.
|
5
txt2toot/txt/sgrgsrg.txt
Executable file
5
txt2toot/txt/sgrgsrg.txt
Executable file
|
@ -0,0 +1,5 @@
|
|||
Et quoniam apud eos ut in capite mundi morborum
|
||||
Cognitis enim pilatorum caesorumque funeribus nemo
|
||||
Tu autem, Fanni, quod mihi tantum tribui dicis
|
||||
Coactique aliquotiens nostri pedites ad eos
|
||||
Huic Arabia est conserta, ex alio latere Nabataeis
|
1
txt2toot/txt/zefbdfberb.txt
Executable file
1
txt2toot/txt/zefbdfberb.txt
Executable file
|
@ -0,0 +1 @@
|
|||
Abusus enim multitudine hominum, quam tranquillis in rebus diutius rexit, ex agrestibus habitaculis urbes construxit multis opibus firmas et viribus, quarum ad praesens pleraeque licet Graecis nominibus appellentur, quae isdem ad arbitrium inposita sunt conditoris, primigenia tamen nomina non amittunt, quae eis Assyria lingua institutores veteres indiderunt.
|
117
txt2toot/txt2toot.py
Executable file
117
txt2toot/txt2toot.py
Executable file
|
@ -0,0 +1,117 @@
|
|||
#!/usr/bin/python3
|
||||
# coding: utf-8
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
from mastodon import Mastodon
|
||||
import os
|
||||
import random
|
||||
import sys
|
||||
import argparse
|
||||
from configparser import ConfigParser
|
||||
|
||||
__prog_name__ = 'txt2toot'
|
||||
__version__ = '0.1'
|
||||
__description__ = 'Toot a random text file on Mastodon'
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Read arguments
|
||||
parser = argparse.ArgumentParser(prog=__prog_name__,
|
||||
description=__description__)
|
||||
parser.add_argument('--version', action='version', version=__version__)
|
||||
parser.add_argument('-d', '--dir', required=True,
|
||||
help="Text file\'s directory")
|
||||
parser.add_argument('-c', '--config', default='config.ini',
|
||||
help="Config file (default: %(default)s)")
|
||||
args = parser.parse_args()
|
||||
config_filepath = args.config
|
||||
|
||||
# Check if config file exists
|
||||
if not os.path.isfile(config_filepath):
|
||||
print("Config file %s not found, exiting." % config_filepath)
|
||||
sys.exit(0)
|
||||
else:
|
||||
# Read config file
|
||||
conf = ConfigParser()
|
||||
conf.read(config_filepath)
|
||||
|
||||
# Need a directory
|
||||
if not args.dir:
|
||||
print("Image\'s directory argument missing")
|
||||
sys.exit(0)
|
||||
txt_dir = args.dir + "/"
|
||||
|
||||
# Overwrite default settings
|
||||
if conf.has_option('toot', 'status'):
|
||||
toot_status = conf['toot']['status'] + '\n'
|
||||
else:
|
||||
toot_status = ''
|
||||
|
||||
if conf.has_option('toot', 'visibility'):
|
||||
toot_visibility = conf['toot']['visibility']
|
||||
else:
|
||||
toot_visibility = ''
|
||||
|
||||
if conf.has_option('toot', 'sensitive'):
|
||||
toot_sensitive = conf['toot']['sensitive']
|
||||
else:
|
||||
toot_sensitive = False
|
||||
|
||||
if conf.has_option('toot', 'spoiler'):
|
||||
toot_spoiler = conf['toot']['spoiler']
|
||||
else:
|
||||
toot_spoiler = None
|
||||
|
||||
# Log into Mastodon if enabled in settings
|
||||
mastodon_hostname = conf['mastodon']['mastodon_hostname']
|
||||
try:
|
||||
mastodonAPI = Mastodon(
|
||||
client_id=conf['mastodon']['client_id'],
|
||||
client_secret=conf['mastodon']['client_secret'],
|
||||
access_token=conf['mastodon']['access_token'],
|
||||
api_base_url='https://' + mastodon_hostname
|
||||
)
|
||||
masto_username = mastodonAPI.account_verify_credentials()['username']
|
||||
print ('[ OK ] Sucessfully authenticated on ' + mastodon_hostname
|
||||
+ ' as @' + masto_username)
|
||||
except BaseException as e:
|
||||
print ('[ERROR] Error while logging into Mastodon:', str(e))
|
||||
sys.exit(0)
|
||||
|
||||
#Prepare media IDs
|
||||
try:
|
||||
mfile = random.choice(os.listdir(txt_dir))
|
||||
txt_byte = open(txt_dir + mfile, "r").read()
|
||||
|
||||
print(type(txt_byte))
|
||||
|
||||
#TODO : améliorer avec prise en compte hashtag+txt
|
||||
|
||||
txt_len = len(toot_status) + len(conf['toot']['hashtag'])
|
||||
print(type(txt_len))
|
||||
txt_maxlen = 500 - txt_len
|
||||
toot_status += txt_byte[:txt_maxlen]
|
||||
|
||||
except BaseException as e:
|
||||
print ('[ERROR] Error while reading text file : ' + str(e))
|
||||
sys.exit(0)
|
||||
|
||||
# Post the toot
|
||||
toot_status += '\n'
|
||||
toot_status += conf['toot']['hashtag']
|
||||
try:
|
||||
status = mastodonAPI.status_post(
|
||||
status=toot_status,
|
||||
in_reply_to_id=None,
|
||||
media_ids=None,
|
||||
sensitive=toot_sensitive,
|
||||
visibility=toot_visibility,
|
||||
spoiler_text=toot_spoiler
|
||||
)
|
||||
print (
|
||||
'[ OK ] Posting this on Mastodon account with media attachment : '
|
||||
+ status['url'])
|
||||
except BaseException as e:
|
||||
print ('[ERROR] Error while posting toot:' + str(e))
|
||||
sys.exit(0)
|
Loading…
Reference in New Issue
Block a user