reformat w/ black
This commit is contained in:
parent
0394c10616
commit
604a1378b7
3 changed files with 581 additions and 166 deletions
570
delojza.py
570
delojza.py
|
@ -64,40 +64,66 @@ class DelojzaDB:
|
||||||
return [res[0] for res in results.fetchall()]
|
return [res[0] for res in results.fetchall()]
|
||||||
|
|
||||||
def get_chat(self, id):
|
def get_chat(self, id):
|
||||||
return self.db.execute("SELECT id, protected FROM chats WHERE id == ?", (id,)).fetchone()
|
return self.db.execute(
|
||||||
|
"SELECT id, protected FROM chats WHERE id == ?", (id,)
|
||||||
|
).fetchone()
|
||||||
|
|
||||||
def set_chat_protected(self, id, protected):
|
def set_chat_protected(self, id, protected):
|
||||||
chat_in_db = self.get_chat(id)
|
chat_in_db = self.get_chat(id)
|
||||||
if chat_in_db:
|
if chat_in_db:
|
||||||
self.db.execute("UPDATE chats SET protected = ? WHERE id = ?", (protected, id))
|
self.db.execute(
|
||||||
|
"UPDATE chats SET protected = ? WHERE id = ?", (protected, id)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.db.execute("INSERT INTO chats (id, protected) VALUES (?, ?)", (id, protected))
|
self.db.execute(
|
||||||
|
"INSERT INTO chats (id, protected) VALUES (?, ?)", (id, protected)
|
||||||
|
)
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
|
|
||||||
def get_tag(self, tag):
|
def get_tag(self, tag):
|
||||||
return self.db.execute("SELECT id, tag, protected FROM tags WHERE tag == ?", (tag,)).fetchone()
|
return self.db.execute(
|
||||||
|
"SELECT id, tag, protected FROM tags WHERE tag == ?", (tag,)
|
||||||
|
).fetchone()
|
||||||
|
|
||||||
def set_tag_protected(self, tag, protected):
|
def set_tag_protected(self, tag, protected):
|
||||||
tag_in_db = self.get_tag(tag)
|
tag_in_db = self.get_tag(tag)
|
||||||
if tag_in_db:
|
if tag_in_db:
|
||||||
self.db.execute("UPDATE tags SET protected = ? WHERE tag = ?", (protected, tag))
|
self.db.execute(
|
||||||
|
"UPDATE tags SET protected = ? WHERE tag = ?", (protected, tag)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.db.execute("INSERT INTO tags (tag, protected) VALUES (?, ?)", (tag, protected))
|
self.db.execute(
|
||||||
|
"INSERT INTO tags (tag, protected) VALUES (?, ?)", (tag, protected)
|
||||||
|
)
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
|
|
||||||
|
|
||||||
class DelojzaBot:
|
class DelojzaBot:
|
||||||
def __init__(self, tg_api_key, out_dir, redirects=None, tmp_dir=None, db_path=None, protected_password=None,
|
def __init__(
|
||||||
acoustid_key=None, tumblr_name=None, tumblr_keys=None, markov=None):
|
self,
|
||||||
|
tg_api_key,
|
||||||
|
out_dir,
|
||||||
|
redirects=None,
|
||||||
|
tmp_dir=None,
|
||||||
|
db_path=None,
|
||||||
|
protected_password=None,
|
||||||
|
acoustid_key=None,
|
||||||
|
tumblr_name=None,
|
||||||
|
tumblr_keys=None,
|
||||||
|
markov=None,
|
||||||
|
):
|
||||||
self._setup_logging(os.path.dirname(os.path.realpath(__file__)))
|
self._setup_logging(os.path.dirname(os.path.realpath(__file__)))
|
||||||
|
|
||||||
self.db = DelojzaDB(db_path or os.path.join(os.path.dirname(os.path.realpath(__file__)), "delojza.db"))
|
self.db = DelojzaDB(
|
||||||
|
db_path
|
||||||
|
or os.path.join(os.path.dirname(os.path.realpath(__file__)), "delojza.db")
|
||||||
|
)
|
||||||
|
|
||||||
self.out_dir = os.path.abspath(out_dir)
|
self.out_dir = os.path.abspath(out_dir)
|
||||||
self.out_dir = self.out_dir[:-1] if self.out_dir[-1] == "/" else self.out_dir
|
self.out_dir = self.out_dir[:-1] if self.out_dir[-1] == "/" else self.out_dir
|
||||||
self.logger.debug('OUT_DIR: ' + out_dir)
|
self.logger.debug("OUT_DIR: " + out_dir)
|
||||||
self.tmp_dir = tmp_dir if tmp_dir else tempfile.gettempdir()
|
self.tmp_dir = tmp_dir if tmp_dir else tempfile.gettempdir()
|
||||||
self.logger.debug('TMP_DIR: ' + tmp_dir)
|
self.logger.debug("TMP_DIR: " + tmp_dir)
|
||||||
self.markov = markov
|
self.markov = markov
|
||||||
|
|
||||||
self.redirects = {}
|
self.redirects = {}
|
||||||
|
@ -146,7 +172,9 @@ class DelojzaBot:
|
||||||
dfh = logging.FileHandler(log_path + "/delojza.log")
|
dfh = logging.FileHandler(log_path + "/delojza.log")
|
||||||
dfh.setLevel(logging.DEBUG)
|
dfh.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
formatter = logging.Formatter('%(asctime)s - %(name)s [%(levelname)s] %(message)s')
|
formatter = logging.Formatter(
|
||||||
|
"%(asctime)s - %(name)s [%(levelname)s] %(message)s"
|
||||||
|
)
|
||||||
|
|
||||||
ch.setFormatter(formatter)
|
ch.setFormatter(formatter)
|
||||||
dfh.setFormatter(formatter)
|
dfh.setFormatter(formatter)
|
||||||
|
@ -156,15 +184,16 @@ class DelojzaBot:
|
||||||
|
|
||||||
def _log_msg(self, update):
|
def _log_msg(self, update):
|
||||||
from_user = update.message.from_user
|
from_user = update.message.from_user
|
||||||
self.logger.debug(f"Received from {from_user.username or (from_user.first_name + from_user.last_name)}"
|
self.logger.debug(
|
||||||
f" ({update.message.chat.id}): " + (update.message.text or "<NONE>"))
|
f"Received from {from_user.username or (from_user.first_name + from_user.last_name)}"
|
||||||
|
f" ({update.message.chat.id}): " + (update.message.text or "<NONE>")
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def ytdl_can(url):
|
def ytdl_can(url):
|
||||||
ies = youtube_dl.extractor.gen_extractors()
|
ies = youtube_dl.extractor.gen_extractors()
|
||||||
for ie in ies:
|
for ie in ies:
|
||||||
if ie.suitable(url) and ie.IE_NAME != 'generic' \
|
if ie.suitable(url) and ie.IE_NAME != "generic" and "/channel/" not in url:
|
||||||
and '/channel/' not in url:
|
|
||||||
# Site has dedicated extractor
|
# Site has dedicated extractor
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
@ -174,14 +203,21 @@ class DelojzaBot:
|
||||||
def sanitize(filepath):
|
def sanitize(filepath):
|
||||||
if filepath is None:
|
if filepath is None:
|
||||||
return None
|
return None
|
||||||
filepath = unicodedata.normalize('NFKD', filepath).encode('ascii', 'ignore').decode('ascii')
|
filepath = (
|
||||||
return re.sub(r'[^\w.()\[\]{}#-]', '_', filepath)
|
unicodedata.normalize("NFKD", filepath)
|
||||||
|
.encode("ascii", "ignore")
|
||||||
|
.decode("ascii")
|
||||||
|
)
|
||||||
|
return re.sub(r"[^\w.()\[\]{}#-]", "_", filepath)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_tags(filepath):
|
def _get_tags(filepath):
|
||||||
try:
|
try:
|
||||||
audio = EasyID3(filepath)
|
audio = EasyID3(filepath)
|
||||||
return audio["artist"][0] if audio["artist"] else None, audio["title"][0] if audio["title"] else None
|
return (
|
||||||
|
audio["artist"][0] if audio["artist"] else None,
|
||||||
|
audio["title"][0] if audio["title"] else None,
|
||||||
|
)
|
||||||
except mutagen.id3.ID3NoHeaderError:
|
except mutagen.id3.ID3NoHeaderError:
|
||||||
return None, None
|
return None, None
|
||||||
|
|
||||||
|
@ -213,12 +249,16 @@ class DelojzaBot:
|
||||||
if self.acoustid_key:
|
if self.acoustid_key:
|
||||||
try:
|
try:
|
||||||
self.logger.debug("Requesting AcoustID for {}".format(filepath))
|
self.logger.debug("Requesting AcoustID for {}".format(filepath))
|
||||||
results = sorted(acoustid.match(self.acoustid_key, filepath), key=itemgetter(0), reverse=True)
|
results = sorted(
|
||||||
|
acoustid.match(self.acoustid_key, filepath),
|
||||||
|
key=itemgetter(0),
|
||||||
|
reverse=True,
|
||||||
|
)
|
||||||
if len(results) > 0:
|
if len(results) > 0:
|
||||||
score, rid, aid_title, aid_artist = results[0]
|
score, rid, aid_title, aid_artist = results[0]
|
||||||
if score > .4:
|
if score > 0.4:
|
||||||
title = aid_title
|
title = aid_title
|
||||||
artist = re.sub(r' *; +', ' & ', aid_artist)
|
artist = re.sub(r" *; +", " & ", aid_artist)
|
||||||
best_acoustid_score = score
|
best_acoustid_score = score
|
||||||
source = "AcoustID ({}%)".format(round(score * 100))
|
source = "AcoustID ({}%)".format(round(score * 100))
|
||||||
except acoustid.NoBackendError:
|
except acoustid.NoBackendError:
|
||||||
|
@ -226,30 +266,32 @@ class DelojzaBot:
|
||||||
except acoustid.FingerprintGenerationError:
|
except acoustid.FingerprintGenerationError:
|
||||||
self.logger.warning("fingerprint could not be calculated")
|
self.logger.warning("fingerprint could not be calculated")
|
||||||
except acoustid.WebServiceError as exc:
|
except acoustid.WebServiceError as exc:
|
||||||
self.logger.warning("web service request failed: {}".format(exc.message))
|
self.logger.warning(
|
||||||
|
"web service request failed: {}".format(exc.message)
|
||||||
|
)
|
||||||
|
|
||||||
if best_acoustid_score < .8:
|
if best_acoustid_score < 0.8:
|
||||||
if 'track' in info:
|
if "track" in info:
|
||||||
title = info['track']
|
title = info["track"]
|
||||||
if 'artist' in info:
|
if "artist" in info:
|
||||||
artist = info['artist']
|
artist = info["artist"]
|
||||||
|
|
||||||
if 'track' in info or 'artist' in info:
|
if "track" in info or "artist" in info:
|
||||||
source = "supplied metadata"
|
source = "supplied metadata"
|
||||||
|
|
||||||
if title is None and artist is None and '-' in info.get("title", ""):
|
if title is None and artist is None and "-" in info.get("title", ""):
|
||||||
split = info['title'].split("-")
|
split = info["title"].split("-")
|
||||||
artist = split[0]
|
artist = split[0]
|
||||||
title = split[1]
|
title = split[1]
|
||||||
source = "fallback (artist - title)"
|
source = "fallback (artist - title)"
|
||||||
|
|
||||||
if title is None and 'title' in info:
|
if title is None and "title" in info:
|
||||||
title = info['title']
|
title = info["title"]
|
||||||
source = "full title fallback"
|
source = "full title fallback"
|
||||||
|
|
||||||
if 'soundcloud' in info.get("extractor", "") and artist is None:
|
if "soundcloud" in info.get("extractor", "") and artist is None:
|
||||||
artist = info['uploader']
|
artist = info["uploader"]
|
||||||
source = "soundcloud \"fallback\""
|
source = 'soundcloud "fallback"'
|
||||||
|
|
||||||
artist = artist.strip() if artist else None
|
artist = artist.strip() if artist else None
|
||||||
title = title.strip() if title else None
|
title = title.strip() if title else None
|
||||||
|
@ -258,14 +300,18 @@ class DelojzaBot:
|
||||||
message.reply_text("Tried tagging, found nothing :(")
|
message.reply_text("Tried tagging, found nothing :(")
|
||||||
return
|
return
|
||||||
|
|
||||||
message.reply_text("Tagging as \"{}\" by \"{}\"\nvia {}".format(title, artist, source))
|
message.reply_text(
|
||||||
self.logger.info("Tagging {} w/ {} - {} [{}]...".format(filepath, title, artist, source))
|
'Tagging as "{}" by "{}"\nvia {}'.format(title, artist, source)
|
||||||
|
)
|
||||||
|
self.logger.info(
|
||||||
|
"Tagging {} w/ {} - {} [{}]...".format(filepath, title, artist, source)
|
||||||
|
)
|
||||||
self._tag_file(filepath, artist, title)
|
self._tag_file(filepath, artist, title)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_percent_filled(directory):
|
def _get_percent_filled(directory):
|
||||||
output = subprocess.check_output(["df", directory])
|
output = subprocess.check_output(["df", directory])
|
||||||
percents_re = re.search(r"[0-9]+%", output.decode('utf-8'))
|
percents_re = re.search(r"[0-9]+%", output.decode("utf-8"))
|
||||||
if not percents_re:
|
if not percents_re:
|
||||||
raise RuntimeError
|
raise RuntimeError
|
||||||
return int(percents_re.group(0)[:-1])
|
return int(percents_re.group(0)[:-1])
|
||||||
|
@ -273,18 +319,22 @@ class DelojzaBot:
|
||||||
# noinspection PyUnusedLocal
|
# noinspection PyUnusedLocal
|
||||||
def download_ytdl(self, urls, out_path, date, message, audio=False, filetitle=None):
|
def download_ytdl(self, urls, out_path, date, message, audio=False, filetitle=None):
|
||||||
ytdl = {
|
ytdl = {
|
||||||
'noplaylist': True,
|
"noplaylist": True,
|
||||||
'restrictfilenames': True,
|
"restrictfilenames": True,
|
||||||
'outtmpl': os.path.join(self.tmp_dir, '{}__%(title)s__%(id)s.%(ext)s'.format(datestr(date)))
|
"outtmpl": os.path.join(
|
||||||
|
self.tmp_dir, "{}__%(title)s__%(id)s.%(ext)s".format(datestr(date))
|
||||||
|
),
|
||||||
}
|
}
|
||||||
if audio:
|
if audio:
|
||||||
ytdl['format'] = 'bestaudio/best'
|
ytdl["format"] = "bestaudio/best"
|
||||||
ytdl['postprocessors'] = [{
|
ytdl["postprocessors"] = [
|
||||||
'key': 'FFmpegExtractAudio',
|
{
|
||||||
'preferredcodec': 'mp3',
|
"key": "FFmpegExtractAudio",
|
||||||
'preferredquality': '256'
|
"preferredcodec": "mp3",
|
||||||
}]
|
"preferredquality": "256",
|
||||||
ytdl['postprocessor_args'] = ['-ar', '44100']
|
}
|
||||||
|
]
|
||||||
|
ytdl["postprocessor_args"] = ["-ar", "44100"]
|
||||||
filenames = []
|
filenames = []
|
||||||
with youtube_dl.YoutubeDL(ytdl) as ytdl:
|
with youtube_dl.YoutubeDL(ytdl) as ytdl:
|
||||||
attempts = 0
|
attempts = 0
|
||||||
|
@ -294,7 +344,7 @@ class DelojzaBot:
|
||||||
break
|
break
|
||||||
except DownloadError as exc:
|
except DownloadError as exc:
|
||||||
attempts += 1
|
attempts += 1
|
||||||
if '403' in str(exc) and attempts < 5:
|
if "403" in str(exc) and attempts < 5:
|
||||||
self.logger.warning("Received a 403!")
|
self.logger.warning("Received a 403!")
|
||||||
sleep(1.357)
|
sleep(1.357)
|
||||||
if self.markov:
|
if self.markov:
|
||||||
|
@ -303,7 +353,7 @@ class DelojzaBot:
|
||||||
raise exc
|
raise exc
|
||||||
for info in [ytdl.extract_info(url, download=False) for url in urls]:
|
for info in [ytdl.extract_info(url, download=False) for url in urls]:
|
||||||
filename = ytdl.prepare_filename(info)
|
filename = ytdl.prepare_filename(info)
|
||||||
globbeds = glob(os.path.splitext(filename)[0] + '.*')
|
globbeds = glob(os.path.splitext(filename)[0] + ".*")
|
||||||
for globbed in globbeds:
|
for globbed in globbeds:
|
||||||
if globbed.endswith("mp3"):
|
if globbed.endswith("mp3"):
|
||||||
self._autotag_file(globbed, message, info=info)
|
self._autotag_file(globbed, message, info=info)
|
||||||
|
@ -315,24 +365,34 @@ class DelojzaBot:
|
||||||
def download_raw(self, urls, out_path, date, message, audio=False, filetitle=None):
|
def download_raw(self, urls, out_path, date, message, audio=False, filetitle=None):
|
||||||
filenames = []
|
filenames = []
|
||||||
for url in urls:
|
for url in urls:
|
||||||
local_filename = os.path.join(out_path, "{}__{}".format(datestr(date),
|
local_filename = os.path.join(
|
||||||
self.sanitize(filetitle or url.split('/')[-1])))
|
out_path,
|
||||||
|
"{}__{}".format(
|
||||||
|
datestr(date), self.sanitize(filetitle or url.split("/")[-1])
|
||||||
|
),
|
||||||
|
)
|
||||||
final_filename = local_filename
|
final_filename = local_filename
|
||||||
is_mp3 = local_filename.endswith("mp3")
|
is_mp3 = local_filename.endswith("mp3")
|
||||||
|
|
||||||
r = requests.get(url, stream=True)
|
r = requests.get(url, stream=True)
|
||||||
with open(local_filename, 'wb') as f:
|
with open(local_filename, "wb") as f:
|
||||||
for chunk in r.iter_content(chunk_size=1024):
|
for chunk in r.iter_content(chunk_size=1024):
|
||||||
if chunk:
|
if chunk:
|
||||||
f.write(chunk)
|
f.write(chunk)
|
||||||
|
|
||||||
if not re.match(r'.*\..{3,5}$', os.path.split(local_filename)[-1]):
|
if not re.match(r".*\..{3,5}$", os.path.split(local_filename)[-1]):
|
||||||
kind = filetype.guess(local_filename)
|
kind = filetype.guess(local_filename)
|
||||||
if kind is None:
|
if kind is None:
|
||||||
self.logger.error("File has no extension and could not be determined!")
|
self.logger.error(
|
||||||
|
"File has no extension and could not be determined!"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.logger.info('Moving file without extension... %s?' % kind.extension)
|
self.logger.info(
|
||||||
final_filename = shutil.move(local_filename, local_filename + '.' + kind.extension)
|
"Moving file without extension... %s?" % kind.extension
|
||||||
|
)
|
||||||
|
final_filename = shutil.move(
|
||||||
|
local_filename, local_filename + "." + kind.extension
|
||||||
|
)
|
||||||
is_mp3 = kind.extension == "mp3"
|
is_mp3 = kind.extension == "mp3"
|
||||||
|
|
||||||
filenames.append(final_filename)
|
filenames.append(final_filename)
|
||||||
|
@ -340,7 +400,7 @@ class DelojzaBot:
|
||||||
if audio and is_mp3:
|
if audio and is_mp3:
|
||||||
try:
|
try:
|
||||||
id3 = mutagen.id3.ID3(final_filename)
|
id3 = mutagen.id3.ID3(final_filename)
|
||||||
untagged = 'TIT2' not in id3
|
untagged = "TIT2" not in id3
|
||||||
except mutagen.id3.ID3NoHeaderError:
|
except mutagen.id3.ID3NoHeaderError:
|
||||||
untagged = True
|
untagged = True
|
||||||
if untagged:
|
if untagged:
|
||||||
|
@ -350,10 +410,18 @@ class DelojzaBot:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def extract_hashtags(message):
|
def extract_hashtags(message):
|
||||||
hashtags = list(map(message.parse_entity,
|
hashtags = list(
|
||||||
list(filter(lambda e: e.type == 'hashtag', message.entities))))
|
map(
|
||||||
hashtags += list(map(message.parse_caption_entity,
|
message.parse_entity,
|
||||||
list(filter(lambda e: e.type == 'hashtag', message.caption_entities))))
|
list(filter(lambda e: e.type == "hashtag", message.entities)),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
hashtags += list(
|
||||||
|
map(
|
||||||
|
message.parse_caption_entity,
|
||||||
|
list(filter(lambda e: e.type == "hashtag", message.caption_entities)),
|
||||||
|
)
|
||||||
|
)
|
||||||
if len(hashtags) > 0:
|
if len(hashtags) > 0:
|
||||||
hashtags = [hashtag[1:].upper() for hashtag in hashtags]
|
hashtags = [hashtag[1:].upper() for hashtag in hashtags]
|
||||||
for i, hashtag in enumerate(hashtags):
|
for i, hashtag in enumerate(hashtags):
|
||||||
|
@ -370,24 +438,30 @@ class DelojzaBot:
|
||||||
return hashtags
|
return hashtags
|
||||||
|
|
||||||
def handle_text(self, message, hashtags):
|
def handle_text(self, message, hashtags):
|
||||||
if len(hashtags) == 0 or hashtags[0] not in ('TEXT', 'TXT'):
|
if len(hashtags) == 0 or hashtags[0] not in ("TEXT", "TXT"):
|
||||||
return
|
return
|
||||||
|
|
||||||
info_line = self.sanitize("-".join(re.sub(r'#[\w]+', '', message.text).strip().split()[:7]))
|
info_line = self.sanitize(
|
||||||
|
"-".join(re.sub(r"#[\w]+", "", message.text).strip().split()[:7])
|
||||||
|
)
|
||||||
if len(info_line) > 64:
|
if len(info_line) > 64:
|
||||||
info_line = info_line[:64]
|
info_line = info_line[:64]
|
||||||
|
|
||||||
filename = '{}__{}.txt'.format(datestr(message.date), info_line)
|
filename = "{}__{}.txt".format(datestr(message.date), info_line)
|
||||||
out_dir = self.redirects.get(hashtags[0], self.out_dir)
|
out_dir = self.redirects.get(hashtags[0], self.out_dir)
|
||||||
out_path = os.path.join(out_dir, *hashtags[1:] or ['TEXT'])
|
out_path = os.path.join(out_dir, *hashtags[1:] or ["TEXT"])
|
||||||
file_path = os.path.join(out_path, filename)
|
file_path = os.path.join(out_path, filename)
|
||||||
|
|
||||||
mkdir_p(out_path)
|
mkdir_p(out_path)
|
||||||
|
|
||||||
with open(file_path, 'w') as out_file:
|
with open(file_path, "w") as out_file:
|
||||||
out_file.write(message.text)
|
out_file.write(message.text)
|
||||||
|
|
||||||
message.reply_text("Saved text to \"{}\"...".format(os.path.join(*hashtags[1:] or ['TEXT'], filename)))
|
message.reply_text(
|
||||||
|
'Saved text to "{}"...'.format(
|
||||||
|
os.path.join(*hashtags[1:] or ["TEXT"], filename)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# noinspection PyBroadException
|
# noinspection PyBroadException
|
||||||
def handle(self, urls, message, hashtags, download_fn, filetitle=None):
|
def handle(self, urls, message, hashtags, download_fn, filetitle=None):
|
||||||
|
@ -405,67 +479,104 @@ class DelojzaBot:
|
||||||
else:
|
else:
|
||||||
out_dir = self.out_dir
|
out_dir = self.out_dir
|
||||||
|
|
||||||
if any(hashtag in self.db.get_protected_tags() for hashtag in original_hashtags):
|
if any(
|
||||||
|
hashtag in self.db.get_protected_tags() for hashtag in original_hashtags
|
||||||
|
):
|
||||||
if message.chat.id not in self.db.get_protected_chats():
|
if message.chat.id not in self.db.get_protected_chats():
|
||||||
self.logger.info("Redirecting {} in chat {} due to protected hashtags: {}..."
|
self.logger.info(
|
||||||
.format(urls, message.chat.title, hashtags))
|
"Redirecting {} in chat {} due to protected hashtags: {}...".format(
|
||||||
|
urls, message.chat.title, hashtags
|
||||||
|
)
|
||||||
|
)
|
||||||
hashtags.insert(0, "PUBLIC")
|
hashtags.insert(0, "PUBLIC")
|
||||||
|
|
||||||
for i in range(len(hashtags)):
|
for i in range(len(hashtags)):
|
||||||
current_path = hashtags[:i + 1]
|
current_path = hashtags[: i + 1]
|
||||||
if not os.path.isdir(os.path.join(out_dir, *current_path)):
|
if not os.path.isdir(os.path.join(out_dir, *current_path)):
|
||||||
test_path = current_path
|
test_path = current_path
|
||||||
test_path[-1] = "_" + test_path[-1]
|
test_path[-1] = "_" + test_path[-1]
|
||||||
if os.path.isdir(os.path.join(out_dir, *test_path)):
|
if os.path.isdir(os.path.join(out_dir, *test_path)):
|
||||||
self.logger.debug(f"Rerouting {current_path[-1]} to _{test_path[-1]}")
|
self.logger.debug(
|
||||||
|
f"Rerouting {current_path[-1]} to _{test_path[-1]}"
|
||||||
|
)
|
||||||
hashtags[i] = test_path[-1]
|
hashtags[i] = test_path[-1]
|
||||||
|
|
||||||
self.last_hashtags[message.chat.id] = None
|
self.last_hashtags[message.chat.id] = None
|
||||||
|
|
||||||
self.logger.info("Downloading %s into '%s' (%s)" % (urls, "/".join(original_hashtags), out_dir))
|
self.logger.info(
|
||||||
|
"Downloading %s into '%s' (%s)"
|
||||||
|
% (urls, "/".join(original_hashtags), out_dir)
|
||||||
|
)
|
||||||
|
|
||||||
out_path = os.path.join(out_dir, *hashtags)
|
out_path = os.path.join(out_dir, *hashtags)
|
||||||
mkdir_p(out_path)
|
mkdir_p(out_path)
|
||||||
|
|
||||||
reply = 'Downloading to "{}"...'.format("/".join(original_hashtags))
|
reply = 'Downloading to "{}"...'.format("/".join(original_hashtags))
|
||||||
|
|
||||||
audio = any([any([tag in hashtag for tag in ('AUDIO', 'RADIO')]) for hashtag in original_hashtags])
|
audio = any(
|
||||||
|
[
|
||||||
|
any([tag in hashtag for tag in ("AUDIO", "RADIO")])
|
||||||
|
for hashtag in original_hashtags
|
||||||
|
]
|
||||||
|
)
|
||||||
if audio and download_fn != self.download_raw:
|
if audio and download_fn != self.download_raw:
|
||||||
reply += ' (And also guessing you want to extract the audio)'
|
reply += " (And also guessing you want to extract the audio)"
|
||||||
message.reply_text(reply)
|
message.reply_text(reply)
|
||||||
|
|
||||||
filenames = download_fn(urls, out_path, message.date, message, audio=audio, filetitle=filetitle)
|
filenames = download_fn(
|
||||||
|
urls, out_path, message.date, message, audio=audio, filetitle=filetitle
|
||||||
|
)
|
||||||
|
|
||||||
cmd_hashtag = original_hashtags[0]
|
cmd_hashtag = original_hashtags[0]
|
||||||
|
|
||||||
tumblr_ids = []
|
tumblr_ids = []
|
||||||
if cmd_hashtag in ('TUMBLR', 'TUMBLR_NOW') and self.tumblr_client:
|
if cmd_hashtag in ("TUMBLR", "TUMBLR_NOW") and self.tumblr_client:
|
||||||
now = cmd_hashtag == 'TUMBLR_NOW'
|
now = cmd_hashtag == "TUMBLR_NOW"
|
||||||
reply = '(btw, {})'.format("***FIRING TO TUMBLR RIGHT AWAY***" if now else "queueing to tumblr")
|
reply = "(btw, {})".format(
|
||||||
|
"***FIRING TO TUMBLR RIGHT AWAY***" if now else "queueing to tumblr"
|
||||||
|
)
|
||||||
message.reply_text(reply, parse_mode=telegram.ParseMode.MARKDOWN)
|
message.reply_text(reply, parse_mode=telegram.ParseMode.MARKDOWN)
|
||||||
for filename in filenames:
|
for filename in filenames:
|
||||||
if filename.endswith(".mp4"):
|
if filename.endswith(".mp4"):
|
||||||
try:
|
try:
|
||||||
output_filename = filename[:-len(".mp4")] + ".gif"
|
output_filename = filename[: -len(".mp4")] + ".gif"
|
||||||
subprocess.check_output(['ffmpeg', '-i', filename, output_filename])
|
subprocess.check_output(
|
||||||
|
["ffmpeg", "-i", filename, output_filename]
|
||||||
|
)
|
||||||
filename = output_filename
|
filename = output_filename
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
message.reply_text("Conversion to gif failed, sorry! Check log...")
|
message.reply_text(
|
||||||
|
"Conversion to gif failed, sorry! Check log..."
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
response = self.tumblr_client.create_photo(self.tumblr_name, data=filename,
|
response = self.tumblr_client.create_photo(
|
||||||
state="published" if now else "queue")
|
self.tumblr_name,
|
||||||
if 'id' in response:
|
data=filename,
|
||||||
tumblr_ids.append(response['id'])
|
state="published" if now else "queue",
|
||||||
|
)
|
||||||
|
if "id" in response:
|
||||||
|
tumblr_ids.append(response["id"])
|
||||||
else:
|
else:
|
||||||
self.logger.warning("Did not receive 'id' in tumblr response: \n" + pprint.pformat(response))
|
self.logger.warning(
|
||||||
message.reply_text('Something weird happened with the tumblrs, check it!')
|
"Did not receive 'id' in tumblr response: \n"
|
||||||
|
+ pprint.pformat(response)
|
||||||
|
)
|
||||||
|
message.reply_text(
|
||||||
|
"Something weird happened with the tumblrs, check it!"
|
||||||
|
)
|
||||||
|
|
||||||
self.last_downloaded[message.chat.id] = filenames, original_hashtags, tumblr_ids
|
self.last_downloaded[message.chat.id] = (
|
||||||
|
filenames,
|
||||||
|
original_hashtags,
|
||||||
|
tumblr_ids,
|
||||||
|
)
|
||||||
return True
|
return True
|
||||||
except:
|
except:
|
||||||
exc_type, exc_value, __ = sys.exc_info()
|
exc_type, exc_value, __ = sys.exc_info()
|
||||||
if "Timed out" not in str(exc_value):
|
if "Timed out" not in str(exc_value):
|
||||||
message.reply_text("Something is FUCKED: [{}] {}".format(exc_type, exc_value))
|
message.reply_text(
|
||||||
|
"Something is FUCKED: [{}] {}".format(exc_type, exc_value)
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def handle_tg_message(self, message, bot, hashtag):
|
def handle_tg_message(self, message, bot, hashtag):
|
||||||
|
@ -488,13 +599,19 @@ class DelojzaBot:
|
||||||
|
|
||||||
if file is not None:
|
if file is not None:
|
||||||
url = bot.getFile(file).file_path
|
url = bot.getFile(file).file_path
|
||||||
return self.handle([url], message, hashtag, self.download_raw, filetitle=filetitle)
|
return self.handle(
|
||||||
|
[url], message, hashtag, self.download_raw, filetitle=filetitle
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def handle_urls(self, message, hashtags):
|
def handle_urls(self, message, hashtags):
|
||||||
urls = list(map(lambda e: message.parse_entity(e),
|
urls = list(
|
||||||
filter(lambda e: e.type == 'url', message.entities)))
|
map(
|
||||||
|
lambda e: message.parse_entity(e),
|
||||||
|
filter(lambda e: e.type == "url", message.entities),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
ytdl_res = False
|
ytdl_res = False
|
||||||
ytdl_urls = [url for url in urls if self.ytdl_can(url)]
|
ytdl_urls = [url for url in urls if self.ytdl_can(url)]
|
||||||
|
@ -504,8 +621,11 @@ class DelojzaBot:
|
||||||
raw_res = False
|
raw_res = False
|
||||||
normal_urls = [url for url in urls if not self.ytdl_can(url)]
|
normal_urls = [url for url in urls if not self.ytdl_can(url)]
|
||||||
if len(normal_urls) > 0:
|
if len(normal_urls) > 0:
|
||||||
file_urls = [url for url in normal_urls if
|
file_urls = [
|
||||||
"text" not in requests.head(url).headers.get("Content-Type", "text")]
|
url
|
||||||
|
for url in normal_urls
|
||||||
|
if "text" not in requests.head(url).headers.get("Content-Type", "text")
|
||||||
|
]
|
||||||
if len(file_urls) > 0:
|
if len(file_urls) > 0:
|
||||||
raw_res = self.handle(file_urls, message, hashtags, self.download_raw)
|
raw_res = self.handle(file_urls, message, hashtags, self.download_raw)
|
||||||
|
|
||||||
|
@ -515,64 +635,109 @@ class DelojzaBot:
|
||||||
self._log_msg(update)
|
self._log_msg(update)
|
||||||
hashtags = self._get_hashtags(update.message)
|
hashtags = self._get_hashtags(update.message)
|
||||||
if hashtags:
|
if hashtags:
|
||||||
url_res = self.handle_urls(update.message, self._get_hashtags(update.message))
|
url_res = self.handle_urls(
|
||||||
|
update.message, self._get_hashtags(update.message)
|
||||||
|
)
|
||||||
if url_res:
|
if url_res:
|
||||||
return
|
return
|
||||||
|
|
||||||
msg_res = self.handle_tg_message(update.message, bot, self._get_hashtags(update.message))
|
msg_res = self.handle_tg_message(
|
||||||
|
update.message, bot, self._get_hashtags(update.message)
|
||||||
|
)
|
||||||
if msg_res:
|
if msg_res:
|
||||||
return
|
return
|
||||||
|
|
||||||
hashtags = self.extract_hashtags(update.message)
|
hashtags = self.extract_hashtags(update.message)
|
||||||
if len(hashtags) > 0:
|
if len(hashtags) > 0:
|
||||||
self.handle_text(update.message.reply_to_message or update.message, hashtags)
|
self.handle_text(
|
||||||
|
update.message.reply_to_message or update.message, hashtags
|
||||||
|
)
|
||||||
|
|
||||||
if update.message.reply_to_message:
|
if update.message.reply_to_message:
|
||||||
self.handle_tg_message(update.message.reply_to_message, bot, hashtags)
|
self.handle_tg_message(update.message.reply_to_message, bot, hashtags)
|
||||||
self.handle_urls(update.message.reply_to_message, hashtags)
|
self.handle_urls(update.message.reply_to_message, hashtags)
|
||||||
else:
|
else:
|
||||||
self.last_hashtags[update.message.chat.id] = update.message.from_user, datetime.now(), hashtags
|
self.last_hashtags[update.message.chat.id] = (
|
||||||
|
update.message.from_user,
|
||||||
|
datetime.now(),
|
||||||
|
hashtags,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
if self.markov and update.message.text:
|
if self.markov and update.message.text:
|
||||||
self.markov.add_to_corpus(update.message.text)
|
self.markov.add_to_corpus(update.message.text)
|
||||||
|
|
||||||
def _get_tag_dirs(self):
|
def _get_tag_dirs(self):
|
||||||
return list(filter(lambda x: x.upper() == x,
|
return (
|
||||||
filter(lambda directory: os.path.isdir(os.path.join(self.out_dir, directory)),
|
list(
|
||||||
os.listdir(self.out_dir)))) + list(self.redirects.keys())
|
filter(
|
||||||
|
lambda x: x.upper() == x,
|
||||||
|
filter(
|
||||||
|
lambda directory: os.path.isdir(
|
||||||
|
os.path.join(self.out_dir, directory)
|
||||||
|
),
|
||||||
|
os.listdir(self.out_dir),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
+ list(self.redirects.keys())
|
||||||
|
)
|
||||||
|
|
||||||
def tg_stats(self, _, update):
|
def tg_stats(self, _, update):
|
||||||
self._log_msg(update)
|
self._log_msg(update)
|
||||||
self.db.initialize()
|
self.db.initialize()
|
||||||
if update.message.chat.id not in self.db.get_protected_chats():
|
if update.message.chat.id not in self.db.get_protected_chats():
|
||||||
update.message.reply_text((self.markov.make_sentence() + "!") if self.markov and random() > .7 else "nope.")
|
update.message.reply_text(
|
||||||
|
(self.markov.make_sentence() + "!")
|
||||||
|
if self.markov and random() > 0.7
|
||||||
|
else "nope."
|
||||||
|
)
|
||||||
return
|
return
|
||||||
tag_dirs = self._get_tag_dirs()
|
tag_dirs = self._get_tag_dirs()
|
||||||
reply = "Total number of tags: {}\n\n".format(len(tag_dirs))
|
reply = "Total number of tags: {}\n\n".format(len(tag_dirs))
|
||||||
counts = [(directory, os.listdir(os.path.join(self.out_dir, directory))) for directory in
|
counts = [
|
||||||
tag_dirs] # TODO REDIRECTS
|
(directory, os.listdir(os.path.join(self.out_dir, directory)))
|
||||||
|
for directory in tag_dirs
|
||||||
|
] # TODO REDIRECTS
|
||||||
counts.sort(key=itemgetter(0))
|
counts.sort(key=itemgetter(0))
|
||||||
counts.sort(key=lambda x: len(x[1]), reverse=True)
|
counts.sort(key=lambda x: len(x[1]), reverse=True)
|
||||||
for directory, files in counts:
|
for directory, files in counts:
|
||||||
if len(files) == 1:
|
if len(files) == 1:
|
||||||
break
|
break
|
||||||
abs_paths = [os.path.join(self.out_dir, directory, file) for file in files] # TODO REDIRECTS
|
abs_paths = [
|
||||||
|
os.path.join(self.out_dir, directory, file) for file in files
|
||||||
|
] # TODO REDIRECTS
|
||||||
abs_files = list(filter(os.path.isfile, abs_paths))
|
abs_files = list(filter(os.path.isfile, abs_paths))
|
||||||
# mimes = [magic.from_file(path, mime=True).split("/")[0] for path in abs_files]
|
# mimes = [magic.from_file(path, mime=True).split("/")[0] for path in abs_files]
|
||||||
# mime_counts = [(mime, mimes.count(mime)) for mime in set(mimes)]
|
# mime_counts = [(mime, mimes.count(mime)) for mime in set(mimes)]
|
||||||
exts = [ext[1:] for ext in [os.path.splitext(path)[1] for path in abs_files] if len(ext) > 0]
|
exts = [
|
||||||
|
ext[1:]
|
||||||
|
for ext in [os.path.splitext(path)[1] for path in abs_files]
|
||||||
|
if len(ext) > 0
|
||||||
|
]
|
||||||
ext_counts = [(ext, exts.count(ext)) for ext in set(exts)]
|
ext_counts = [(ext, exts.count(ext)) for ext in set(exts)]
|
||||||
dir_cnt = len(abs_paths) - len(abs_files)
|
dir_cnt = len(abs_paths) - len(abs_files)
|
||||||
type_counts = ext_counts + ([("directorie", dir_cnt)] if dir_cnt > 0 else [])
|
type_counts = ext_counts + (
|
||||||
details = ", ".join(["{} {}s".format(cnt, mime) for mime, cnt in
|
[("directorie", dir_cnt)] if dir_cnt > 0 else []
|
||||||
sorted(type_counts, key=itemgetter(1), reverse=True)])
|
)
|
||||||
|
details = ", ".join(
|
||||||
|
[
|
||||||
|
"{} {}s".format(cnt, mime)
|
||||||
|
for mime, cnt in sorted(
|
||||||
|
type_counts, key=itemgetter(1), reverse=True
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
if len(type_counts) == 1:
|
if len(type_counts) == 1:
|
||||||
reply += "<b>{}:</b> {}\n".format(directory, details)
|
reply += "<b>{}:</b> {}\n".format(directory, details)
|
||||||
else:
|
else:
|
||||||
reply += "<b>{}:</b> {} files ({})\n".format(directory, len(files), details)
|
reply += "<b>{}:</b> {} files ({})\n".format(
|
||||||
|
directory, len(files), details
|
||||||
|
)
|
||||||
orphans = list(filter(lambda cnt: len(cnt[1]) <= 1, counts))
|
orphans = list(filter(lambda cnt: len(cnt[1]) <= 1, counts))
|
||||||
if len(orphans) > 0:
|
if len(orphans) > 0:
|
||||||
reply += "\nFollowing tags are orphans: " + ", ".join(map(itemgetter(0), orphans))
|
reply += "\nFollowing tags are orphans: " + ", ".join(
|
||||||
|
map(itemgetter(0), orphans)
|
||||||
|
)
|
||||||
update.message.reply_text(reply, parse_mode=telegram.ParseMode.HTML)
|
update.message.reply_text(reply, parse_mode=telegram.ParseMode.HTML)
|
||||||
|
|
||||||
def _get_orphan_tags(self):
|
def _get_orphan_tags(self):
|
||||||
|
@ -589,20 +754,30 @@ class DelojzaBot:
|
||||||
self._log_msg(update)
|
self._log_msg(update)
|
||||||
self.db.initialize()
|
self.db.initialize()
|
||||||
if update.message.chat.id not in self.db.get_protected_chats():
|
if update.message.chat.id not in self.db.get_protected_chats():
|
||||||
update.message.reply_text((self.markov.make_sentence() + "!") if self.markov and random() > .7 else "nope.")
|
update.message.reply_text(
|
||||||
|
(self.markov.make_sentence() + "!")
|
||||||
|
if self.markov and random() > 0.7
|
||||||
|
else "nope."
|
||||||
|
)
|
||||||
return
|
return
|
||||||
orphans = self._get_orphan_tags()
|
orphans = self._get_orphan_tags()
|
||||||
if len(orphans) == 0:
|
if len(orphans) == 0:
|
||||||
update.message.reply_text("Good job, no orphan tags!")
|
update.message.reply_text("Good job, no orphan tags!")
|
||||||
else:
|
else:
|
||||||
update.message.reply_text("The following tags only contain a single file:\n" +
|
update.message.reply_text(
|
||||||
", ".join(map(itemgetter(0), orphans)))
|
"The following tags only contain a single file:\n"
|
||||||
|
+ ", ".join(map(itemgetter(0), orphans))
|
||||||
|
)
|
||||||
|
|
||||||
def tg_orphan_full(self, _, update):
|
def tg_orphan_full(self, _, update):
|
||||||
self._log_msg(update)
|
self._log_msg(update)
|
||||||
self.db.initialize()
|
self.db.initialize()
|
||||||
if update.message.chat.id not in self.db.get_protected_chats():
|
if update.message.chat.id not in self.db.get_protected_chats():
|
||||||
update.message.reply_text((self.markov.make_sentence() + "!") if self.markov and random() > .7 else "nope.")
|
update.message.reply_text(
|
||||||
|
(self.markov.make_sentence() + "!")
|
||||||
|
if self.markov and random() > 0.7
|
||||||
|
else "nope."
|
||||||
|
)
|
||||||
return
|
return
|
||||||
orphans = self._get_orphan_tags()
|
orphans = self._get_orphan_tags()
|
||||||
if len(orphans) == 0:
|
if len(orphans) == 0:
|
||||||
|
@ -625,7 +800,7 @@ class DelojzaBot:
|
||||||
out_dir = self.redirects.get(hashtags[0], self.out_dir)
|
out_dir = self.redirects.get(hashtags[0], self.out_dir)
|
||||||
mp3s = [filename for filename in files if filename.endswith("mp3")]
|
mp3s = [filename for filename in files if filename.endswith("mp3")]
|
||||||
if len(mp3s) > 0:
|
if len(mp3s) > 0:
|
||||||
arg_raw = re.sub(r'^/[@\w]+ ?', '', update.message.text).strip()
|
arg_raw = re.sub(r"^/[@\w]+ ?", "", update.message.text).strip()
|
||||||
artist, title = None, None
|
artist, title = None, None
|
||||||
|
|
||||||
reverse = len(arg_raw) == 0
|
reverse = len(arg_raw) == 0
|
||||||
|
@ -643,10 +818,16 @@ class DelojzaBot:
|
||||||
title, artist = orig_artist, orig_title
|
title, artist = orig_artist, orig_title
|
||||||
|
|
||||||
self._tag_file(mp3, artist, title)
|
self._tag_file(mp3, artist, title)
|
||||||
update.message.reply_text("Tagging \"{}\" as \"{}\" by \"{}\"!"
|
update.message.reply_text(
|
||||||
.format(mp3[len(out_dir) + 1:], title, artist))
|
'Tagging "{}" as "{}" by "{}"!'.format(
|
||||||
|
mp3[len(out_dir) + 1 :], title, artist
|
||||||
|
)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
update.message.reply_text((self.markov.make_sentence() if self.markov and random() > .7 else "") + "???")
|
update.message.reply_text(
|
||||||
|
(self.markov.make_sentence() if self.markov and random() > 0.7 else "")
|
||||||
|
+ "???"
|
||||||
|
)
|
||||||
|
|
||||||
def tg_delete(self, _, update):
|
def tg_delete(self, _, update):
|
||||||
self._log_msg(update)
|
self._log_msg(update)
|
||||||
|
@ -654,19 +835,28 @@ class DelojzaBot:
|
||||||
files, hashtags, tumblr_ids = self.last_downloaded[update.message.chat.id]
|
files, hashtags, tumblr_ids = self.last_downloaded[update.message.chat.id]
|
||||||
out_dir = self.redirects.get(hashtags[0], self.out_dir)
|
out_dir = self.redirects.get(hashtags[0], self.out_dir)
|
||||||
for file in files:
|
for file in files:
|
||||||
update.message.reply_text("Removing \"{}\"!".format(file[len(out_dir) + 1:]))
|
update.message.reply_text(
|
||||||
|
'Removing "{}"!'.format(file[len(out_dir) + 1 :])
|
||||||
|
)
|
||||||
os.remove(file)
|
os.remove(file)
|
||||||
parent_dir = os.path.dirname(file)
|
parent_dir = os.path.dirname(file)
|
||||||
while True:
|
while True:
|
||||||
if len(os.listdir(parent_dir)) == 0:
|
if len(os.listdir(parent_dir)) == 0:
|
||||||
update.message.reply_text("Removing directory \"{}\" as it's empty..."
|
update.message.reply_text(
|
||||||
.format(parent_dir[len(out_dir) + 1:]))
|
'Removing directory "{}" as it\'s empty...'.format(
|
||||||
|
parent_dir[len(out_dir) + 1 :]
|
||||||
|
)
|
||||||
|
)
|
||||||
os.rmdir(parent_dir)
|
os.rmdir(parent_dir)
|
||||||
if parent_dir == out_dir:
|
if parent_dir == out_dir:
|
||||||
break
|
break
|
||||||
parent_dir = os.path.dirname(parent_dir)
|
parent_dir = os.path.dirname(parent_dir)
|
||||||
if len(tumblr_ids) > 0:
|
if len(tumblr_ids) > 0:
|
||||||
plural = "s (all {} of them)".format(len(tumblr_ids)) if len(tumblr_ids) > 1 else ""
|
plural = (
|
||||||
|
"s (all {} of them)".format(len(tumblr_ids))
|
||||||
|
if len(tumblr_ids) > 1
|
||||||
|
else ""
|
||||||
|
)
|
||||||
update.message.reply_text("Also deleting tumblr post{}!".format(plural))
|
update.message.reply_text("Also deleting tumblr post{}!".format(plural))
|
||||||
for tumblr_id in tumblr_ids:
|
for tumblr_id in tumblr_ids:
|
||||||
if self.tumblr_client:
|
if self.tumblr_client:
|
||||||
|
@ -681,13 +871,16 @@ class DelojzaBot:
|
||||||
|
|
||||||
msg_split = update.message.text.split(" ")
|
msg_split = update.message.text.split(" ")
|
||||||
if len(msg_split) != 3:
|
if len(msg_split) != 3:
|
||||||
update.message.reply_text((self.markov.make_sentence() if self.markov and random() > .7 else "") + "???")
|
update.message.reply_text(
|
||||||
|
(self.markov.make_sentence() if self.markov and random() > 0.7 else "")
|
||||||
|
+ "???"
|
||||||
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
chat_in_db = self.db.get_chat(update.message.chat.id)
|
chat_in_db = self.db.get_chat(update.message.chat.id)
|
||||||
|
|
||||||
cmd = msg_split[1]
|
cmd = msg_split[1]
|
||||||
if cmd == 'tag':
|
if cmd == "tag":
|
||||||
if chat_in_db and chat_in_db[1]:
|
if chat_in_db and chat_in_db[1]:
|
||||||
tag = msg_split[2].upper()
|
tag = msg_split[2].upper()
|
||||||
tag_in_db = self.db.get_tag(tag)
|
tag_in_db = self.db.get_tag(tag)
|
||||||
|
@ -698,10 +891,18 @@ class DelojzaBot:
|
||||||
end_protected = True
|
end_protected = True
|
||||||
|
|
||||||
self.db.set_tag_protected(tag, end_protected)
|
self.db.set_tag_protected(tag, end_protected)
|
||||||
update.message.reply_text(f"got it, will {'NOT ' if not end_protected else ''}protect tag {tag}!")
|
update.message.reply_text(
|
||||||
|
f"got it, will {'NOT ' if not end_protected else ''}protect tag {tag}!"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
update.message.reply_text((self.markov.make_sentence() if self.markov and random() > .7 else "hublubl"))
|
update.message.reply_text(
|
||||||
elif cmd == 'chat':
|
(
|
||||||
|
self.markov.make_sentence()
|
||||||
|
if self.markov and random() > 0.7
|
||||||
|
else "hublubl"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif cmd == "chat":
|
||||||
password = msg_split[2]
|
password = msg_split[2]
|
||||||
if password == self.protected_password:
|
if password == self.protected_password:
|
||||||
if chat_in_db:
|
if chat_in_db:
|
||||||
|
@ -711,37 +912,63 @@ class DelojzaBot:
|
||||||
end_protected = True
|
end_protected = True
|
||||||
|
|
||||||
self.db.set_chat_protected(update.message.chat.id, end_protected)
|
self.db.set_chat_protected(update.message.chat.id, end_protected)
|
||||||
update.message.reply_text(f"got it, will {'NOT ' if not end_protected else ''}protect this chat!")
|
update.message.reply_text(
|
||||||
|
f"got it, will {'NOT ' if not end_protected else ''}protect this chat!"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
update.message.reply_text((self.markov.make_sentence() if self.markov and random() > .7 else "hublubl"))
|
update.message.reply_text(
|
||||||
|
(
|
||||||
|
self.markov.make_sentence()
|
||||||
|
if self.markov and random() > 0.7
|
||||||
|
else "hublubl"
|
||||||
|
)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
update.message.reply_text((self.markov.make_sentence() if self.markov and random() > .7 else "") + "???")
|
update.message.reply_text(
|
||||||
|
(self.markov.make_sentence() if self.markov and random() > 0.7 else "")
|
||||||
|
+ "???"
|
||||||
|
)
|
||||||
|
|
||||||
def tg_queue(self, _, update):
|
def tg_queue(self, _, update):
|
||||||
if self.tumblr_client:
|
if self.tumblr_client:
|
||||||
blog_info = self.tumblr_client.blog_info(self.tumblr_name)
|
blog_info = self.tumblr_client.blog_info(self.tumblr_name)
|
||||||
update.message.reply_text("Currently queued tumblr posts: " + str(blog_info['blog'].get('queue', "???")))
|
update.message.reply_text(
|
||||||
|
"Currently queued tumblr posts: "
|
||||||
|
+ str(blog_info["blog"].get("queue", "???"))
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
update.message.reply_text((self.markov.make_sentence() if self.markov and random() > .7 else "") + "???")
|
update.message.reply_text(
|
||||||
|
(self.markov.make_sentence() if self.markov and random() > 0.7 else "")
|
||||||
|
+ "???"
|
||||||
|
)
|
||||||
|
|
||||||
# noinspection PyMethodMayBeStatic
|
# noinspection PyMethodMayBeStatic
|
||||||
def tg_version(self, _, update):
|
def tg_version(self, _, update):
|
||||||
self._log_msg(update)
|
self._log_msg(update)
|
||||||
delojza_date = datetime.fromtimestamp(os.path.getmtime(os.path.realpath(__file__))) \
|
delojza_date = datetime.fromtimestamp(
|
||||||
.strftime('%Y/%m/%d - %H:%M:%S')
|
os.path.getmtime(os.path.realpath(__file__))
|
||||||
update.message.reply_text("delojza modified date: {}\nyoutube-dl version: {}"
|
).strftime("%Y/%m/%d - %H:%M:%S")
|
||||||
.format(delojza_date, YTDL_VERSION))
|
update.message.reply_text(
|
||||||
|
"delojza modified date: {}\nyoutube-dl version: {}".format(
|
||||||
|
delojza_date, YTDL_VERSION
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def tg_start(self, _, update):
|
def tg_start(self, _, update):
|
||||||
self._log_msg(update)
|
self._log_msg(update)
|
||||||
update.message.reply_text(self.markov.make_sentence() if self.markov else "HELLO")
|
update.message.reply_text(
|
||||||
|
self.markov.make_sentence() if self.markov else "HELLO"
|
||||||
|
)
|
||||||
|
|
||||||
def tg_error(self, bot, update, error):
|
def tg_error(self, bot, update, error):
|
||||||
self.logger.error(error)
|
self.logger.error(error)
|
||||||
if "Timed out" in str(error):
|
if "Timed out" in str(error):
|
||||||
if update is not None:
|
if update is not None:
|
||||||
default = "Mmmm, I like it..."
|
default = "Mmmm, I like it..."
|
||||||
update.message.reply_text((self.markov.make_sentence(tries=100) if self.markov else default) or default)
|
update.message.reply_text(
|
||||||
|
(self.markov.make_sentence(tries=100) if self.markov else default)
|
||||||
|
or default
|
||||||
|
)
|
||||||
self.tg_handle(bot, update)
|
self.tg_handle(bot, update)
|
||||||
else:
|
else:
|
||||||
if update is not None:
|
if update is not None:
|
||||||
|
@ -755,7 +982,7 @@ class DelojzaBot:
|
||||||
|
|
||||||
class MarkovBlabberer:
|
class MarkovBlabberer:
|
||||||
def __init__(self, filepath):
|
def __init__(self, filepath):
|
||||||
self.logger = logging.getLogger('markov')
|
self.logger = logging.getLogger("markov")
|
||||||
self.filepath = filepath
|
self.filepath = filepath
|
||||||
|
|
||||||
with open(filepath) as f:
|
with open(filepath) as f:
|
||||||
|
@ -770,21 +997,28 @@ class MarkovBlabberer:
|
||||||
text = text.lower()
|
text = text.lower()
|
||||||
new_sentence = markovify.NewlineText(text)
|
new_sentence = markovify.NewlineText(text)
|
||||||
self.markov = markovify.combine([self.markov, new_sentence])
|
self.markov = markovify.combine([self.markov, new_sentence])
|
||||||
with open(self.filepath, 'a') as f:
|
with open(self.filepath, "a") as f:
|
||||||
f.write(text + '\n')
|
f.write(text + "\n")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
logging.basicConfig(
|
||||||
|
level=logging.INFO,
|
||||||
|
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
||||||
|
)
|
||||||
|
|
||||||
_DIR_ = os.path.dirname(os.path.realpath(__file__))
|
_DIR_ = os.path.dirname(os.path.realpath(__file__))
|
||||||
CONFIG_PATHS = ['/etc/delojza/delojza.ini',
|
CONFIG_PATHS = [
|
||||||
os.path.join(os.getenv("HOME") or "", ".config/delojza/delojza.ini"),
|
"/etc/delojza/delojza.ini",
|
||||||
os.path.join(_DIR_, "delojza.ini")]
|
os.path.join(os.getenv("HOME") or "", ".config/delojza/delojza.ini"),
|
||||||
|
os.path.join(_DIR_, "delojza.ini"),
|
||||||
|
]
|
||||||
|
|
||||||
config = ConfigParser()
|
config = ConfigParser()
|
||||||
try:
|
try:
|
||||||
CONF_FILE = next(conf_path for conf_path in CONFIG_PATHS if os.path.isfile(conf_path))
|
CONF_FILE = next(
|
||||||
|
conf_path for conf_path in CONFIG_PATHS if os.path.isfile(conf_path)
|
||||||
|
)
|
||||||
config.read(CONF_FILE)
|
config.read(CONF_FILE)
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
logging.error("No config file found, stopping.")
|
logging.error("No config file found, stopping.")
|
||||||
|
@ -793,24 +1027,30 @@ if __name__ == '__main__':
|
||||||
try:
|
try:
|
||||||
markov = MarkovBlabberer("initial.txt")
|
markov = MarkovBlabberer("initial.txt")
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
logging.warning("Didn't find `initial.txt`, continuing without markov blabbering!")
|
logging.warning(
|
||||||
|
"Didn't find `initial.txt`, continuing without markov blabbering!"
|
||||||
|
)
|
||||||
markov = None
|
markov = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
redirects = config.items('redirects')
|
redirects = config.items("redirects")
|
||||||
except NoSectionError:
|
except NoSectionError:
|
||||||
redirects = {}
|
redirects = {}
|
||||||
|
|
||||||
delojza = DelojzaBot(config.get('delojza', 'tg_api_key'),
|
delojza = DelojzaBot(
|
||||||
config.get('delojza', 'OUT_DIR', fallback=os.path.join(_DIR_, "out")),
|
config.get("delojza", "tg_api_key"),
|
||||||
tmp_dir=config.get('delojza', 'tmp_dir', fallback=tempfile.gettempdir()),
|
config.get("delojza", "OUT_DIR", fallback=os.path.join(_DIR_, "out")),
|
||||||
redirects=redirects,
|
tmp_dir=config.get("delojza", "tmp_dir", fallback=tempfile.gettempdir()),
|
||||||
protected_password=config.get('delojza', 'protected_password', fallback=None),
|
redirects=redirects,
|
||||||
acoustid_key=config.get('delojza', 'acoustid_api_key', fallback=None),
|
protected_password=config.get("delojza", "protected_password", fallback=None),
|
||||||
tumblr_name=config.get('tumblr', 'blog_name', fallback=None),
|
acoustid_key=config.get("delojza", "acoustid_api_key", fallback=None),
|
||||||
tumblr_keys=(config.get('tumblr', 'consumer_key', fallback=None),
|
tumblr_name=config.get("tumblr", "blog_name", fallback=None),
|
||||||
config.get('tumblr', 'consumer_secret', fallback=None),
|
tumblr_keys=(
|
||||||
config.get('tumblr', 'oauth_key', fallback=None),
|
config.get("tumblr", "consumer_key", fallback=None),
|
||||||
config.get('tumblr', 'oauth_secret', fallback=None)),
|
config.get("tumblr", "consumer_secret", fallback=None),
|
||||||
markov=markov)
|
config.get("tumblr", "oauth_key", fallback=None),
|
||||||
|
config.get("tumblr", "oauth_secret", fallback=None),
|
||||||
|
),
|
||||||
|
markov=markov,
|
||||||
|
)
|
||||||
delojza.run_idle()
|
delojza.run_idle()
|
||||||
|
|
176
poetry.lock
generated
176
poetry.lock
generated
|
@ -6,6 +6,33 @@ category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "black"
|
||||||
|
version = "21.9b0"
|
||||||
|
description = "The uncompromising code formatter."
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6.2"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
click = ">=7.1.2"
|
||||||
|
mypy-extensions = ">=0.4.3"
|
||||||
|
pathspec = ">=0.9.0,<1"
|
||||||
|
platformdirs = ">=2"
|
||||||
|
regex = ">=2020.1.8"
|
||||||
|
tomli = ">=0.2.6,<2.0.0"
|
||||||
|
typing-extensions = [
|
||||||
|
{version = ">=3.10.0.0", markers = "python_version < \"3.10\""},
|
||||||
|
{version = "!=3.10.0.1", markers = "python_version >= \"3.10\""},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
colorama = ["colorama (>=0.4.3)"]
|
||||||
|
d = ["aiohttp (>=3.6.0)", "aiohttp-cors (>=0.4.0)"]
|
||||||
|
jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
|
||||||
|
python2 = ["typed-ast (>=1.4.2)"]
|
||||||
|
uvloop = ["uvloop (>=0.15.2)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "certifi"
|
name = "certifi"
|
||||||
version = "2021.5.30"
|
version = "2021.5.30"
|
||||||
|
@ -36,6 +63,25 @@ python-versions = ">=3.5.0"
|
||||||
[package.extras]
|
[package.extras]
|
||||||
unicode_backport = ["unicodedata2"]
|
unicode_backport = ["unicodedata2"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "click"
|
||||||
|
version = "8.0.1"
|
||||||
|
description = "Composable command line interface toolkit"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colorama"
|
||||||
|
version = "0.4.4"
|
||||||
|
description = "Cross-platform colored terminal text."
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cryptography"
|
name = "cryptography"
|
||||||
version = "3.4.8"
|
version = "3.4.8"
|
||||||
|
@ -98,6 +144,14 @@ category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.5, <4"
|
python-versions = ">=3.5, <4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mypy-extensions"
|
||||||
|
version = "0.4.3"
|
||||||
|
description = "Experimental type system extensions for programs checked with the mypy typechecker."
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oauthlib"
|
name = "oauthlib"
|
||||||
version = "3.1.1"
|
version = "3.1.1"
|
||||||
|
@ -111,6 +165,26 @@ rsa = ["cryptography (>=3.0.0,<4)"]
|
||||||
signals = ["blinker (>=1.4.0)"]
|
signals = ["blinker (>=1.4.0)"]
|
||||||
signedtoken = ["cryptography (>=3.0.0,<4)", "pyjwt (>=2.0.0,<3)"]
|
signedtoken = ["cryptography (>=3.0.0,<4)", "pyjwt (>=2.0.0,<3)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pathspec"
|
||||||
|
version = "0.9.0"
|
||||||
|
description = "Utility library for gitignore style pattern matching of file paths."
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "platformdirs"
|
||||||
|
version = "2.3.0"
|
||||||
|
description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"]
|
||||||
|
test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyacoustid"
|
name = "pyacoustid"
|
||||||
version = "1.2.2"
|
version = "1.2.2"
|
||||||
|
@ -160,6 +234,14 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||||
future = "*"
|
future = "*"
|
||||||
requests-oauthlib = "*"
|
requests-oauthlib = "*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "2021.8.28"
|
||||||
|
description = "Alternative regular expression module, to replace re."
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "requests"
|
name = "requests"
|
||||||
version = "2.26.0"
|
version = "2.26.0"
|
||||||
|
@ -193,6 +275,22 @@ requests = ">=2.0.0"
|
||||||
[package.extras]
|
[package.extras]
|
||||||
rsa = ["oauthlib[signedtoken] (>=3.0.0)"]
|
rsa = ["oauthlib[signedtoken] (>=3.0.0)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tomli"
|
||||||
|
version = "1.2.1"
|
||||||
|
description = "A lil' TOML parser"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typing-extensions"
|
||||||
|
version = "3.10.0.2"
|
||||||
|
description = "Backported and Experimental Type Hints for Python 3.5+"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unidecode"
|
name = "unidecode"
|
||||||
version = "1.3.1"
|
version = "1.3.1"
|
||||||
|
@ -225,12 +323,16 @@ python-versions = "*"
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "1.1"
|
lock-version = "1.1"
|
||||||
python-versions = "^3.8"
|
python-versions = "^3.8"
|
||||||
content-hash = "01568add6ada6b27a0123da237bc38f136148cd1dad83399c994fb9991c906e7"
|
content-hash = "c6e54519de2d7d86694444f2c26f29af31da90a5df5dcd06c619d8d2dc7d2fd7"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
audioread = [
|
audioread = [
|
||||||
{file = "audioread-2.1.9.tar.gz", hash = "sha256:a3480e42056c8e80a8192a54f6729a280ef66d27782ee11cbd63e9d4d1523089"},
|
{file = "audioread-2.1.9.tar.gz", hash = "sha256:a3480e42056c8e80a8192a54f6729a280ef66d27782ee11cbd63e9d4d1523089"},
|
||||||
]
|
]
|
||||||
|
black = [
|
||||||
|
{file = "black-21.9b0-py3-none-any.whl", hash = "sha256:380f1b5da05e5a1429225676655dddb96f5ae8c75bdf91e53d798871b902a115"},
|
||||||
|
{file = "black-21.9b0.tar.gz", hash = "sha256:7de4cfc7eb6b710de325712d40125689101d21d25283eed7e9998722cf10eb91"},
|
||||||
|
]
|
||||||
certifi = [
|
certifi = [
|
||||||
{file = "certifi-2021.5.30-py2.py3-none-any.whl", hash = "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8"},
|
{file = "certifi-2021.5.30-py2.py3-none-any.whl", hash = "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8"},
|
||||||
{file = "certifi-2021.5.30.tar.gz", hash = "sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee"},
|
{file = "certifi-2021.5.30.tar.gz", hash = "sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee"},
|
||||||
|
@ -286,6 +388,14 @@ charset-normalizer = [
|
||||||
{file = "charset-normalizer-2.0.4.tar.gz", hash = "sha256:f23667ebe1084be45f6ae0538e4a5a865206544097e4e8bbcacf42cd02a348f3"},
|
{file = "charset-normalizer-2.0.4.tar.gz", hash = "sha256:f23667ebe1084be45f6ae0538e4a5a865206544097e4e8bbcacf42cd02a348f3"},
|
||||||
{file = "charset_normalizer-2.0.4-py3-none-any.whl", hash = "sha256:0c8911edd15d19223366a194a513099a302055a962bca2cec0f54b8b63175d8b"},
|
{file = "charset_normalizer-2.0.4-py3-none-any.whl", hash = "sha256:0c8911edd15d19223366a194a513099a302055a962bca2cec0f54b8b63175d8b"},
|
||||||
]
|
]
|
||||||
|
click = [
|
||||||
|
{file = "click-8.0.1-py3-none-any.whl", hash = "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"},
|
||||||
|
{file = "click-8.0.1.tar.gz", hash = "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a"},
|
||||||
|
]
|
||||||
|
colorama = [
|
||||||
|
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
|
||||||
|
{file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
|
||||||
|
]
|
||||||
cryptography = [
|
cryptography = [
|
||||||
{file = "cryptography-3.4.8-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:a00cf305f07b26c351d8d4e1af84ad7501eca8a342dedf24a7acb0e7b7406e14"},
|
{file = "cryptography-3.4.8-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:a00cf305f07b26c351d8d4e1af84ad7501eca8a342dedf24a7acb0e7b7406e14"},
|
||||||
{file = "cryptography-3.4.8-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:f44d141b8c4ea5eb4dbc9b3ad992d45580c1d22bf5e24363f2fbf50c2d7ae8a7"},
|
{file = "cryptography-3.4.8-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:f44d141b8c4ea5eb4dbc9b3ad992d45580c1d22bf5e24363f2fbf50c2d7ae8a7"},
|
||||||
|
@ -323,10 +433,22 @@ mutagen = [
|
||||||
{file = "mutagen-1.45.1-py3-none-any.whl", hash = "sha256:9c9f243fcec7f410f138cb12c21c84c64fde4195481a30c9bfb05b5f003adfed"},
|
{file = "mutagen-1.45.1-py3-none-any.whl", hash = "sha256:9c9f243fcec7f410f138cb12c21c84c64fde4195481a30c9bfb05b5f003adfed"},
|
||||||
{file = "mutagen-1.45.1.tar.gz", hash = "sha256:6397602efb3c2d7baebd2166ed85731ae1c1d475abca22090b7141ff5034b3e1"},
|
{file = "mutagen-1.45.1.tar.gz", hash = "sha256:6397602efb3c2d7baebd2166ed85731ae1c1d475abca22090b7141ff5034b3e1"},
|
||||||
]
|
]
|
||||||
|
mypy-extensions = [
|
||||||
|
{file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
|
||||||
|
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
|
||||||
|
]
|
||||||
oauthlib = [
|
oauthlib = [
|
||||||
{file = "oauthlib-3.1.1-py2.py3-none-any.whl", hash = "sha256:42bf6354c2ed8c6acb54d971fce6f88193d97297e18602a3a886603f9d7730cc"},
|
{file = "oauthlib-3.1.1-py2.py3-none-any.whl", hash = "sha256:42bf6354c2ed8c6acb54d971fce6f88193d97297e18602a3a886603f9d7730cc"},
|
||||||
{file = "oauthlib-3.1.1.tar.gz", hash = "sha256:8f0215fcc533dd8dd1bee6f4c412d4f0cd7297307d43ac61666389e3bc3198a3"},
|
{file = "oauthlib-3.1.1.tar.gz", hash = "sha256:8f0215fcc533dd8dd1bee6f4c412d4f0cd7297307d43ac61666389e3bc3198a3"},
|
||||||
]
|
]
|
||||||
|
pathspec = [
|
||||||
|
{file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"},
|
||||||
|
{file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"},
|
||||||
|
]
|
||||||
|
platformdirs = [
|
||||||
|
{file = "platformdirs-2.3.0-py3-none-any.whl", hash = "sha256:8003ac87717ae2c7ee1ea5a84a1a61e87f3fbd16eb5aadba194ea30a9019f648"},
|
||||||
|
{file = "platformdirs-2.3.0.tar.gz", hash = "sha256:15b056538719b1c94bdaccb29e5f81879c7f7f0f4a153f46086d155dffcd4f0f"},
|
||||||
|
]
|
||||||
pyacoustid = [
|
pyacoustid = [
|
||||||
{file = "pyacoustid-1.2.2.tar.gz", hash = "sha256:c279d9c30a7f481f1420fc37db65833b5f9816cd364dc2acaa93a11c482d4141"},
|
{file = "pyacoustid-1.2.2.tar.gz", hash = "sha256:c279d9c30a7f481f1420fc37db65833b5f9816cd364dc2acaa93a11c482d4141"},
|
||||||
]
|
]
|
||||||
|
@ -342,6 +464,49 @@ pytumblr = [
|
||||||
{file = "PyTumblr-0.1.0-py2.py3-none-any.whl", hash = "sha256:a3774d3978bcff2db98f36a2e5d17bb8496ac21157b1b518089adad86d0dca72"},
|
{file = "PyTumblr-0.1.0-py2.py3-none-any.whl", hash = "sha256:a3774d3978bcff2db98f36a2e5d17bb8496ac21157b1b518089adad86d0dca72"},
|
||||||
{file = "PyTumblr-0.1.0.tar.gz", hash = "sha256:eaa4d98217df7ab6392fa5d8801f4a2bdcba35bf0fd49328aa3c98e3b231b6f2"},
|
{file = "PyTumblr-0.1.0.tar.gz", hash = "sha256:eaa4d98217df7ab6392fa5d8801f4a2bdcba35bf0fd49328aa3c98e3b231b6f2"},
|
||||||
]
|
]
|
||||||
|
regex = [
|
||||||
|
{file = "regex-2021.8.28-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9d05ad5367c90814099000442b2125535e9d77581855b9bee8780f1b41f2b1a2"},
|
||||||
|
{file = "regex-2021.8.28-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3bf1bc02bc421047bfec3343729c4bbbea42605bcfd6d6bfe2c07ade8b12d2a"},
|
||||||
|
{file = "regex-2021.8.28-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f6a808044faae658f546dd5f525e921de9fa409de7a5570865467f03a626fc0"},
|
||||||
|
{file = "regex-2021.8.28-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a617593aeacc7a691cc4af4a4410031654f2909053bd8c8e7db837f179a630eb"},
|
||||||
|
{file = "regex-2021.8.28-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:79aef6b5cd41feff359acaf98e040844613ff5298d0d19c455b3d9ae0bc8c35a"},
|
||||||
|
{file = "regex-2021.8.28-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0fc1f8f06977c2d4f5e3d3f0d4a08089be783973fc6b6e278bde01f0544ff308"},
|
||||||
|
{file = "regex-2021.8.28-cp310-cp310-win32.whl", hash = "sha256:6eebf512aa90751d5ef6a7c2ac9d60113f32e86e5687326a50d7686e309f66ed"},
|
||||||
|
{file = "regex-2021.8.28-cp310-cp310-win_amd64.whl", hash = "sha256:ac88856a8cbccfc14f1b2d0b829af354cc1743cb375e7f04251ae73b2af6adf8"},
|
||||||
|
{file = "regex-2021.8.28-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c206587c83e795d417ed3adc8453a791f6d36b67c81416676cad053b4104152c"},
|
||||||
|
{file = "regex-2021.8.28-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8690ed94481f219a7a967c118abaf71ccc440f69acd583cab721b90eeedb77c"},
|
||||||
|
{file = "regex-2021.8.28-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:328a1fad67445550b982caa2a2a850da5989fd6595e858f02d04636e7f8b0b13"},
|
||||||
|
{file = "regex-2021.8.28-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c7cb4c512d2d3b0870e00fbbac2f291d4b4bf2634d59a31176a87afe2777c6f0"},
|
||||||
|
{file = "regex-2021.8.28-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66256b6391c057305e5ae9209941ef63c33a476b73772ca967d4a2df70520ec1"},
|
||||||
|
{file = "regex-2021.8.28-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8e44769068d33e0ea6ccdf4b84d80c5afffe5207aa4d1881a629cf0ef3ec398f"},
|
||||||
|
{file = "regex-2021.8.28-cp36-cp36m-win32.whl", hash = "sha256:08d74bfaa4c7731b8dac0a992c63673a2782758f7cfad34cf9c1b9184f911354"},
|
||||||
|
{file = "regex-2021.8.28-cp36-cp36m-win_amd64.whl", hash = "sha256:abb48494d88e8a82601af905143e0de838c776c1241d92021e9256d5515b3645"},
|
||||||
|
{file = "regex-2021.8.28-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b4c220a1fe0d2c622493b0a1fd48f8f991998fb447d3cd368033a4b86cf1127a"},
|
||||||
|
{file = "regex-2021.8.28-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4a332404baa6665b54e5d283b4262f41f2103c255897084ec8f5487ce7b9e8e"},
|
||||||
|
{file = "regex-2021.8.28-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c61dcc1cf9fd165127a2853e2c31eb4fb961a4f26b394ac9fe5669c7a6592892"},
|
||||||
|
{file = "regex-2021.8.28-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ee329d0387b5b41a5dddbb6243a21cb7896587a651bebb957e2d2bb8b63c0791"},
|
||||||
|
{file = "regex-2021.8.28-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f60667673ff9c249709160529ab39667d1ae9fd38634e006bec95611f632e759"},
|
||||||
|
{file = "regex-2021.8.28-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b844fb09bd9936ed158ff9df0ab601e2045b316b17aa8b931857365ea8586906"},
|
||||||
|
{file = "regex-2021.8.28-cp37-cp37m-win32.whl", hash = "sha256:4cde065ab33bcaab774d84096fae266d9301d1a2f5519d7bd58fc55274afbf7a"},
|
||||||
|
{file = "regex-2021.8.28-cp37-cp37m-win_amd64.whl", hash = "sha256:1413b5022ed6ac0d504ba425ef02549a57d0f4276de58e3ab7e82437892704fc"},
|
||||||
|
{file = "regex-2021.8.28-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ed4b50355b066796dacdd1cf538f2ce57275d001838f9b132fab80b75e8c84dd"},
|
||||||
|
{file = "regex-2021.8.28-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28fc475f560d8f67cc8767b94db4c9440210f6958495aeae70fac8faec631797"},
|
||||||
|
{file = "regex-2021.8.28-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdc178caebd0f338d57ae445ef8e9b737ddf8fbc3ea187603f65aec5b041248f"},
|
||||||
|
{file = "regex-2021.8.28-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:999ad08220467b6ad4bd3dd34e65329dd5d0df9b31e47106105e407954965256"},
|
||||||
|
{file = "regex-2021.8.28-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:808ee5834e06f57978da3e003ad9d6292de69d2bf6263662a1a8ae30788e080b"},
|
||||||
|
{file = "regex-2021.8.28-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d5111d4c843d80202e62b4fdbb4920db1dcee4f9366d6b03294f45ed7b18b42e"},
|
||||||
|
{file = "regex-2021.8.28-cp38-cp38-win32.whl", hash = "sha256:473858730ef6d6ff7f7d5f19452184cd0caa062a20047f6d6f3e135a4648865d"},
|
||||||
|
{file = "regex-2021.8.28-cp38-cp38-win_amd64.whl", hash = "sha256:31a99a4796bf5aefc8351e98507b09e1b09115574f7c9dbb9cf2111f7220d2e2"},
|
||||||
|
{file = "regex-2021.8.28-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:04f6b9749e335bb0d2f68c707f23bb1773c3fb6ecd10edf0f04df12a8920d468"},
|
||||||
|
{file = "regex-2021.8.28-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b006628fe43aa69259ec04ca258d88ed19b64791693df59c422b607b6ece8bb"},
|
||||||
|
{file = "regex-2021.8.28-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:121f4b3185feaade3f85f70294aef3f777199e9b5c0c0245c774ae884b110a2d"},
|
||||||
|
{file = "regex-2021.8.28-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a577a21de2ef8059b58f79ff76a4da81c45a75fe0bfb09bc8b7bb4293fa18983"},
|
||||||
|
{file = "regex-2021.8.28-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1743345e30917e8c574f273f51679c294effba6ad372db1967852f12c76759d8"},
|
||||||
|
{file = "regex-2021.8.28-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e1e8406b895aba6caa63d9fd1b6b1700d7e4825f78ccb1e5260551d168db38ed"},
|
||||||
|
{file = "regex-2021.8.28-cp39-cp39-win32.whl", hash = "sha256:ed283ab3a01d8b53de3a05bfdf4473ae24e43caee7dcb5584e86f3f3e5ab4374"},
|
||||||
|
{file = "regex-2021.8.28-cp39-cp39-win_amd64.whl", hash = "sha256:610b690b406653c84b7cb6091facb3033500ee81089867ee7d59e675f9ca2b73"},
|
||||||
|
{file = "regex-2021.8.28.tar.gz", hash = "sha256:f585cbbeecb35f35609edccb95efd95a3e35824cd7752b586503f7e6087303f1"},
|
||||||
|
]
|
||||||
requests = [
|
requests = [
|
||||||
{file = "requests-2.26.0-py2.py3-none-any.whl", hash = "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24"},
|
{file = "requests-2.26.0-py2.py3-none-any.whl", hash = "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24"},
|
||||||
{file = "requests-2.26.0.tar.gz", hash = "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"},
|
{file = "requests-2.26.0.tar.gz", hash = "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"},
|
||||||
|
@ -351,6 +516,15 @@ requests-oauthlib = [
|
||||||
{file = "requests_oauthlib-1.3.0-py2.py3-none-any.whl", hash = "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d"},
|
{file = "requests_oauthlib-1.3.0-py2.py3-none-any.whl", hash = "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d"},
|
||||||
{file = "requests_oauthlib-1.3.0-py3.7.egg", hash = "sha256:fa6c47b933f01060936d87ae9327fead68768b69c6c9ea2109c48be30f2d4dbc"},
|
{file = "requests_oauthlib-1.3.0-py3.7.egg", hash = "sha256:fa6c47b933f01060936d87ae9327fead68768b69c6c9ea2109c48be30f2d4dbc"},
|
||||||
]
|
]
|
||||||
|
tomli = [
|
||||||
|
{file = "tomli-1.2.1-py3-none-any.whl", hash = "sha256:8dd0e9524d6f386271a36b41dbf6c57d8e32fd96fd22b6584679dc569d20899f"},
|
||||||
|
{file = "tomli-1.2.1.tar.gz", hash = "sha256:a5b75cb6f3968abb47af1b40c1819dc519ea82bcc065776a866e8d74c5ca9442"},
|
||||||
|
]
|
||||||
|
typing-extensions = [
|
||||||
|
{file = "typing_extensions-3.10.0.2-py2-none-any.whl", hash = "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7"},
|
||||||
|
{file = "typing_extensions-3.10.0.2-py3-none-any.whl", hash = "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34"},
|
||||||
|
{file = "typing_extensions-3.10.0.2.tar.gz", hash = "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e"},
|
||||||
|
]
|
||||||
unidecode = [
|
unidecode = [
|
||||||
{file = "Unidecode-1.3.1-py3-none-any.whl", hash = "sha256:5f58926b9125b499f8ab6816828e737578fa3e31fa24d351a3ab7f4b7c064ab0"},
|
{file = "Unidecode-1.3.1-py3-none-any.whl", hash = "sha256:5f58926b9125b499f8ab6816828e737578fa3e31fa24d351a3ab7f4b7c064ab0"},
|
||||||
{file = "Unidecode-1.3.1.tar.gz", hash = "sha256:6efac090bf8f29970afc90caf4daae87b172709b786cb1b4da2d0c0624431ecc"},
|
{file = "Unidecode-1.3.1.tar.gz", hash = "sha256:6efac090bf8f29970afc90caf4daae87b172709b786cb1b4da2d0c0624431ecc"},
|
||||||
|
|
|
@ -17,6 +17,7 @@ PyTumblr = "^0.1.0"
|
||||||
markovify = "^0.9.3"
|
markovify = "^0.9.3"
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
|
black = {version = "^21.9b0", allow-prereleases = true}
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["poetry-core>=1.0.0"]
|
requires = ["poetry-core>=1.0.0"]
|
||||||
|
|
Loading…
Reference in a new issue