From ee7cf637ba128ff882ea447ee9865263e6489f3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Ml=C3=A1dek?= Date: Sat, 28 Mar 2020 13:55:12 +0100 Subject: [PATCH] requirements.in -> poetry, modularization first phase, remove docker --- docker/delojza/Dockerfile | 9 - docker/docker-compose.yml | 24 --- src/delojza.py | 158 ++------------- src/lib/__init__.py | 0 src/lib/db.py | 42 ++++ src/lib/markov.py | 25 +++ src/lib/tagging.py | 25 +++ src/lib/util.py | 43 +++++ src/poetry.lock | 393 ++++++++++++++++++++++++++++++++++++++ src/pyproject.toml | 24 +++ src/requirements.in | 9 - src/requirements.txt | 28 --- 12 files changed, 570 insertions(+), 210 deletions(-) delete mode 100644 docker/delojza/Dockerfile delete mode 100644 docker/docker-compose.yml create mode 100644 src/lib/__init__.py create mode 100644 src/lib/db.py create mode 100644 src/lib/markov.py create mode 100644 src/lib/tagging.py create mode 100644 src/lib/util.py create mode 100644 src/poetry.lock create mode 100644 src/pyproject.toml delete mode 100644 src/requirements.in delete mode 100644 src/requirements.txt diff --git a/docker/delojza/Dockerfile b/docker/delojza/Dockerfile deleted file mode 100644 index c91bf0d..0000000 --- a/docker/delojza/Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -FROM python:3.7 - -RUN apt-get update && apt-get -y install ffmpeg - -COPY ./src /app - -RUN cd /app && pip install -r requirements.txt - -CMD /app/run.sh diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml deleted file mode 100644 index dc870bf..0000000 --- a/docker/docker-compose.yml +++ /dev/null @@ -1,24 +0,0 @@ -version: '3' - -#volumes: -# postgres_ksx-radio: {} - -services: -# ksx-postgres: -# restart: always -# image: postgres:11 -# ports: -# - "5532:5432" -# volumes: -# - postgres_ksx-radio:/var/lib/postgresql/data -# - ../src/db_versions:/docker-entrypoint-initdb.d -# environment: -# - POSTGRES_USER=ksx -# - POSTGRES_PASSWORD=ksx -# - POSTGRES_DB=ksx-radio - - delojza: - restart: always - build: - context: ../. - dockerfile: ./docker/delojza/Dockerfile diff --git a/src/delojza.py b/src/delojza.py index f13a1c8..458a9ed 100755 --- a/src/delojza.py +++ b/src/delojza.py @@ -1,16 +1,13 @@ #!/usr/bin/env python3 -import errno import logging import os import pprint import re import shutil -import sqlite3 import subprocess import sys import tempfile -import unicodedata from configparser import ConfigParser, NoSectionError from datetime import datetime, timedelta from glob import glob @@ -20,73 +17,20 @@ from time import sleep import acoustid import filetype -import markovify import mutagen.id3 import pytumblr import requests import telegram import youtube_dl -from mutagen.easyid3 import EasyID3 +from lib.db import DelojzaDB +from lib.markov import MarkovBlabberer +from lib.tagging import tag_file, get_tags +from lib.util import mkdir_p, sanitize, ytdl_can from telegram.ext import Updater, CommandHandler, MessageHandler -from unidecode import unidecode from youtube_dl import DownloadError from youtube_dl.version import __version__ as YTDL_VERSION -def mkdir_p(path): - try: - os.makedirs(path) - except OSError as exc: - if exc.errno == errno.EEXIST and os.path.isdir(path): - pass - else: - raise - - -def datestr(date): - return date.strftime("%Y-%m-%d@%H%M") - - -class DelojzaDB: - def __init__(self, db_path): - self.db_path = db_path - self.db = None - - def initialize(self): - if self.db is None: - self.db = sqlite3.connect(self.db_path) - - def get_protected_tags(self): - results = self.db.execute("SELECT tag FROM tags WHERE protected == 1") - return [res[0] for res in results.fetchall()] - - def get_protected_chats(self): - results = self.db.execute("SELECT id FROM chats WHERE protected == 1") - return [res[0] for res in results.fetchall()] - - def get_chat(self, id): - return self.db.execute("SELECT id, protected FROM chats WHERE id == ?", (id,)).fetchone() - - def set_chat_protected(self, id, protected): - chat_in_db = self.get_chat(id) - if chat_in_db: - self.db.execute("UPDATE chats SET protected = ? WHERE id = ?", (protected, id)) - else: - self.db.execute("INSERT INTO chats (id, protected) VALUES (?, ?)", (id, protected)) - self.db.commit() - - def get_tag(self, tag): - return self.db.execute("SELECT id, tag, protected FROM tags WHERE tag == ?", (tag,)).fetchone() - - def set_tag_protected(self, tag, protected): - tag_in_db = self.get_tag(tag) - if tag_in_db: - self.db.execute("UPDATE tags SET protected = ? WHERE tag = ?", (protected, tag)) - else: - self.db.execute("INSERT INTO tags (tag, protected) VALUES (?, ?)", (tag, protected)) - self.db.commit() - - class DelojzaBot: def __init__(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): @@ -161,45 +105,8 @@ class DelojzaBot: f" ({update.message.chat.id}): " + (update.message.text or "")) @staticmethod - def ytdl_can(url): - ies = youtube_dl.extractor.gen_extractors() - for ie in ies: - if ie.suitable(url) and ie.IE_NAME != 'generic' \ - and '/channel/' not in url: - # Site has dedicated extractor - return True - return False - - # https://github.com/django/django/blob/master/django/utils/text.py#L393 - @staticmethod - def sanitize(filepath): - if filepath is None: - return None - filepath = unicodedata.normalize('NFKD', filepath).encode('ascii', 'ignore').decode('ascii') - return re.sub(r'[^\w.()\[\]{}#-]', '_', filepath) - - @staticmethod - def _get_tags(filepath): - try: - audio = EasyID3(filepath) - return audio["artist"][0] if audio["artist"] else None, audio["title"][0] if audio["title"] else None - except mutagen.id3.ID3NoHeaderError: - return None, None - - @staticmethod - def _tag_file(filepath, artist, title): - try: - id3 = mutagen.id3.ID3(filepath) - except mutagen.id3.ID3NoHeaderError: - mutafile = mutagen.File(filepath) - mutafile.add_tags() - mutafile.save() - id3 = mutagen.id3.ID3(filepath) - id3.add(mutagen.id3.TIT2(encoding=3, text=title)) - if artist: - id3.add(mutagen.id3.TOPE(encoding=3, text=artist)) - id3.add(mutagen.id3.TPE1(encoding=3, text=artist)) - id3.save() + def datestr(date: datetime): + return date.strftime("%Y-%m-%d@%H%M") def _autotag_file(self, filepath, message, info=None): if info is None: @@ -261,22 +168,14 @@ class DelojzaBot: message.reply_text("Tagging as \"{}\" by \"{}\"\nvia {}".format(title, artist, source)) self.logger.info("Tagging {} w/ {} - {} [{}]...".format(filepath, title, artist, source)) - self._tag_file(filepath, artist, title) - - @staticmethod - def _get_percent_filled(directory): - output = subprocess.check_output(["df", directory]) - percents_re = re.search(r"[0-9]+%", output.decode('utf-8')) - if not percents_re: - raise RuntimeError - return int(percents_re.group(0)[:-1]) + tag_file(filepath, artist, title) # noinspection PyUnusedLocal def download_ytdl(self, urls, out_path, date, message, audio=False, filetitle=None): ytdl = { 'noplaylist': 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(self.datestr(date))) } if audio: ytdl['format'] = 'bestaudio/best' @@ -316,8 +215,8 @@ class DelojzaBot: def download_raw(self, urls, out_path, date, message, audio=False, filetitle=None): filenames = [] for url in urls: - local_filename = os.path.join(out_path, "{}__{}".format(datestr(date), - self.sanitize(filetitle or url.split('/')[-1]))) + local_filename = os.path.join(out_path, "{}__{}".format(self.datestr(date), + sanitize(filetitle or url.split('/')[-1]))) final_filename = local_filename is_mp3 = local_filename.endswith("mp3") @@ -374,11 +273,11 @@ class DelojzaBot: if len(hashtags) == 0 or hashtags[0] not in ('TEXT', 'TXT'): return - info_line = self.sanitize("-".join(re.sub(r'#[\w]+', '', message.text).strip().split()[:7])) + info_line = sanitize("-".join(re.sub(r'#[\w]+', '', message.text).strip().split()[:7])) if len(info_line) > 64: info_line = info_line[:64] - filename = '{}__{}.txt'.format(datestr(message.date), info_line) + filename = '{}__{}.txt'.format(self.datestr(message.date), info_line) out_dir = self.redirects.get(hashtags[0], self.out_dir) out_path = os.path.join(out_dir, *hashtags[1:] or ['TEXT']) file_path = os.path.join(out_path, filename) @@ -488,7 +387,7 @@ class DelojzaBot: file = message.voice.file_id if file is not None: - if self.markov and random.random() > .66: + if self.markov and random() > .66: sentence = self.markov.make_sentence() if sentence: message.reply_text(sentence) @@ -501,18 +400,18 @@ class DelojzaBot: urls = list(map(lambda e: message.parse_entity(e), filter(lambda e: e.type == 'url', message.entities))) - if len(urls) > 0 and self.markov and random.random() > .66: + if len(urls) > 0 and self.markov and random() > .66: sentence = self.markov.make_sentence() if sentence: message.reply_text(sentence) ytdl_res = False - ytdl_urls = [url for url in urls if self.ytdl_can(url)] + ytdl_urls = [url for url in urls if ytdl_can(url)] if len(ytdl_urls) > 0: ytdl_res = self.handle(ytdl_urls, message, hashtags, self.download_ytdl) 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 ytdl_can(url)] if len(normal_urls) > 0: file_urls = [url for url in normal_urls if "text" not in requests.head(url).headers.get("Content-Type", "text")] @@ -649,10 +548,10 @@ class DelojzaBot: for mp3 in mp3s: if reverse: - orig_artist, orig_title = self._get_tags(mp3) + orig_artist, orig_title = get_tags(mp3) title, artist = orig_artist, orig_title - self._tag_file(mp3, artist, title) + tag_file(mp3, artist, title) update.message.reply_text("Tagging \"{}\" as \"{}\" by \"{}\"!" .format(mp3[len(out_dir) + 1:], title, artist)) else: @@ -763,27 +662,6 @@ class DelojzaBot: self.updater.idle() -class MarkovBlabberer: - def __init__(self, filepath): - self.logger = logging.getLogger('markov') - self.filepath = filepath - - with open(filepath) as f: - text = f.read() - self.markov = markovify.NewlineText(unidecode(text.lower())) - self.logger.info("Sentence of the day: " + self.make_sentence()) - - def make_sentence(self, tries=100): - return self.markov.make_sentence(tries=tries) or "???" - - def add_to_corpus(self, text): - text = text.lower() - new_sentence = markovify.NewlineText(text) - self.markov = markovify.combine([self.markov, new_sentence]) - with open(self.filepath, 'a') as f: - f.write(text + '\n') - - if __name__ == '__main__': logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') diff --git a/src/lib/__init__.py b/src/lib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/lib/db.py b/src/lib/db.py new file mode 100644 index 0000000..0e048d9 --- /dev/null +++ b/src/lib/db.py @@ -0,0 +1,42 @@ +import sqlite3 +from typing import List + + +class DelojzaDB: + def __init__(self, db_path): + self.db_path = db_path + self.db = None + + def initialize(self) -> None: + if self.db is None: + self.db = sqlite3.connect(self.db_path) + + def get_protected_tags(self) -> List[str]: + results = self.db.execute("SELECT tag FROM tags WHERE protected == 1") + return [res[0] for res in results.fetchall()] + + def get_protected_chats(self) -> List[str]: + results = self.db.execute("SELECT id FROM chats WHERE protected == 1") + return [res[0] for res in results.fetchall()] + + def get_chat(self, id): + return self.db.execute("SELECT id, protected FROM chats WHERE id == ?", (id,)).fetchone() + + def set_chat_protected(self, id, protected): + chat_in_db = self.get_chat(id) + if chat_in_db: + self.db.execute("UPDATE chats SET protected = ? WHERE id = ?", (protected, id)) + else: + self.db.execute("INSERT INTO chats (id, protected) VALUES (?, ?)", (id, protected)) + self.db.commit() + + def get_tag(self, tag): + return self.db.execute("SELECT id, tag, protected FROM tags WHERE tag == ?", (tag,)).fetchone() + + def set_tag_protected(self, tag, protected): + tag_in_db = self.get_tag(tag) + if tag_in_db: + self.db.execute("UPDATE tags SET protected = ? WHERE tag = ?", (protected, tag)) + else: + self.db.execute("INSERT INTO tags (tag, protected) VALUES (?, ?)", (tag, protected)) + self.db.commit() diff --git a/src/lib/markov.py b/src/lib/markov.py new file mode 100644 index 0000000..2920397 --- /dev/null +++ b/src/lib/markov.py @@ -0,0 +1,25 @@ +import logging + +import markovify +from unidecode import unidecode + + +class MarkovBlabberer: + def __init__(self, filepath): + self.logger = logging.getLogger('markov') + self.filepath = filepath + + with open(filepath) as f: + text = f.read() + self.markov = markovify.NewlineText(unidecode(text.lower())) + self.logger.info("Sentence of the day: " + self.make_sentence()) + + def make_sentence(self, tries=100): + return self.markov.make_sentence(tries=tries) or "???" + + def add_to_corpus(self, text): + text = text.lower() + new_sentence = markovify.NewlineText(text) + self.markov = markovify.combine([self.markov, new_sentence]) + with open(self.filepath, 'a') as f: + f.write(text + '\n') diff --git a/src/lib/tagging.py b/src/lib/tagging.py new file mode 100644 index 0000000..accb04c --- /dev/null +++ b/src/lib/tagging.py @@ -0,0 +1,25 @@ +import mutagen.id3 +from mutagen.easyid3 import EasyID3 + + +def get_tags(filepath): + try: + audio = EasyID3(filepath) + return audio["artist"][0] if audio["artist"] else None, audio["title"][0] if audio["title"] else None + except mutagen.id3.ID3NoHeaderError: + return None, None + + +def tag_file(filepath, artist, title): + try: + id3 = mutagen.id3.ID3(filepath) + except mutagen.id3.ID3NoHeaderError: + mutafile = mutagen.File(filepath) + mutafile.add_tags() + mutafile.save() + id3 = mutagen.id3.ID3(filepath) + id3.add(mutagen.id3.TIT2(encoding=3, text=title)) + if artist: + id3.add(mutagen.id3.TOPE(encoding=3, text=artist)) + id3.add(mutagen.id3.TPE1(encoding=3, text=artist)) + id3.save() diff --git a/src/lib/util.py b/src/lib/util.py new file mode 100644 index 0000000..7e7cadd --- /dev/null +++ b/src/lib/util.py @@ -0,0 +1,43 @@ +import errno +import os +import re +import subprocess +import unicodedata + +import youtube_dl + + +def ytdl_can(url: str): + ies = youtube_dl.extractor.gen_extractors() + for ie in ies: + if ie.suitable(url) and ie.IE_NAME != 'generic' \ + and '/channel/' not in url: + # Site has dedicated extractor + return True + return False + + +def mkdir_p(path: str): + try: + os.makedirs(path) + except OSError as exc: + if exc.errno == errno.EEXIST and os.path.isdir(path): + pass + else: + raise + + +def _get_percent_filled(directory: str): + output = subprocess.check_output(["df", directory]) + percents_re = re.search(r"[0-9]+%", output.decode('utf-8')) + if not percents_re: + raise RuntimeError + return int(percents_re.group(0)[:-1]) + + +# https://github.com/django/django/blob/master/django/utils/text.py#L393 +def sanitize(filepath: str): + if filepath is None: + return None + filepath = unicodedata.normalize('NFKD', filepath).encode('ascii', 'ignore').decode('ascii') + return re.sub(r'[^\w.()\[\]{}#-]', '_', filepath) diff --git a/src/poetry.lock b/src/poetry.lock new file mode 100644 index 0000000..c199348 --- /dev/null +++ b/src/poetry.lock @@ -0,0 +1,393 @@ +[[package]] +category = "main" +description = "multi-library, cross-platform audio decoding" +name = "audioread" +optional = false +python-versions = "*" +version = "2.1.8" + +[[package]] +category = "main" +description = "Python package for providing Mozilla's CA Bundle." +name = "certifi" +optional = false +python-versions = "*" +version = "2019.11.28" + +[[package]] +category = "main" +description = "Foreign Function Interface for Python calling C code." +name = "cffi" +optional = false +python-versions = "*" +version = "1.14.0" + +[package.dependencies] +pycparser = "*" + +[[package]] +category = "main" +description = "Universal encoding detector for Python 2 and 3" +name = "chardet" +optional = false +python-versions = "*" +version = "3.0.4" + +[[package]] +category = "main" +description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +name = "cryptography" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" +version = "2.8" + +[package.dependencies] +cffi = ">=1.8,<1.11.3 || >1.11.3" +six = ">=1.4.1" + +[package.extras] +docs = ["sphinx (>=1.6.5,<1.8.0 || >1.8.0)", "sphinx-rtd-theme"] +docstest = ["doc8", "pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"] +idna = ["idna (>=2.1)"] +pep8test = ["flake8", "flake8-import-order", "pep8-naming"] +test = ["pytest (>=3.6.0,<3.9.0 || >3.9.0,<3.9.1 || >3.9.1,<3.9.2 || >3.9.2)", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,<3.79.2 || >3.79.2)"] + +[[package]] +category = "main" +description = "Decorators for Humans" +name = "decorator" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*" +version = "4.4.2" + +[[package]] +category = "main" +description = "Infer file type and MIME type of any file/buffer. No external dependencies." +name = "filetype" +optional = false +python-versions = "*" +version = "1.0.6" + +[[package]] +category = "main" +description = "Clean single-source support for Python 3 and 2" +name = "future" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +version = "0.18.2" + +[[package]] +category = "main" +description = "Internationalized Domain Names in Applications (IDNA)" +name = "idna" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.9" + +[[package]] +category = "main" +description = "A simple, extensible Markov chain generator. Uses include generating random semi-plausible sentences based on an existing text." +name = "markovify" +optional = false +python-versions = "*" +version = "0.8.0" + +[package.dependencies] +unidecode = "*" + +[[package]] +category = "main" +description = "read and write audio tags for many formats" +name = "mutagen" +optional = false +python-versions = ">=3.5, <4" +version = "1.44.0" + +[[package]] +category = "main" +description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" +name = "oauthlib" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "3.1.0" + +[package.extras] +rsa = ["cryptography"] +signals = ["blinker"] +signedtoken = ["cryptography", "pyjwt (>=1.0.0)"] + +[[package]] +category = "main" +description = "bindings for Chromaprint acoustic fingerprinting and the Acoustid API" +name = "pyacoustid" +optional = false +python-versions = "*" +version = "1.1.7" + +[package.dependencies] +audioread = "*" +requests = "*" + +[[package]] +category = "main" +description = "C parser in Python" +name = "pycparser" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.20" + +[[package]] +category = "main" +description = "We have made you a wrapper you can't refuse" +name = "python-telegram-bot" +optional = false +python-versions = "*" +version = "12.4.2" + +[package.dependencies] +certifi = "*" +cryptography = "*" +decorator = ">=4.4.0" +future = ">=0.16.0" +tornado = ">=5.1" + +[package.extras] +json = ["ujson"] +socks = ["pysocks"] + +[[package]] +category = "main" +description = "A Python API v2 wrapper for Tumblr" +name = "pytumblr" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "0.1.0" + +[package.dependencies] +future = "*" +requests-oauthlib = "*" + +[[package]] +category = "main" +description = "Python HTTP for Humans." +name = "requests" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "2.23.0" + +[package.dependencies] +certifi = ">=2017.4.17" +chardet = ">=3.0.2,<4" +idna = ">=2.5,<3" +urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26" + +[package.extras] +security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] +socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] + +[[package]] +category = "main" +description = "OAuthlib authentication support for Requests." +name = "requests-oauthlib" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "1.3.0" + +[package.dependencies] +oauthlib = ">=3.0.0" +requests = ">=2.0.0" + +[package.extras] +rsa = ["oauthlib (>=3.0.0)"] + +[[package]] +category = "main" +description = "Python 2 and 3 compatibility utilities" +name = "six" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +version = "1.14.0" + +[[package]] +category = "main" +description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." +name = "tornado" +optional = false +python-versions = ">= 3.5" +version = "6.0.4" + +[[package]] +category = "main" +description = "ASCII transliterations of Unicode text" +name = "unidecode" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "1.1.1" + +[[package]] +category = "main" +description = "HTTP library with thread-safe connection pooling, file post, and more." +name = "urllib3" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" +version = "1.25.8" + +[package.extras] +brotli = ["brotlipy (>=0.6.0)"] +secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] +socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"] + +[[package]] +category = "main" +description = "YouTube video downloader" +name = "youtube-dl" +optional = false +python-versions = "*" +version = "2020.3.24" + +[metadata] +content-hash = "dd08867932866aa57fdeebf8d02ff9c14739cd099e039ca310222679905ab4e4" +python-versions = "^3.8" + +[metadata.files] +audioread = [ + {file = "audioread-2.1.8.tar.gz", hash = "sha256:073904fabc842881e07bd3e4a5776623535562f70b1655b635d22886168dd168"}, +] +certifi = [ + {file = "certifi-2019.11.28-py2.py3-none-any.whl", hash = "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3"}, + {file = "certifi-2019.11.28.tar.gz", hash = "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"}, +] +cffi = [ + {file = "cffi-1.14.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1cae98a7054b5c9391eb3249b86e0e99ab1e02bb0cc0575da191aedadbdf4384"}, + {file = "cffi-1.14.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:cf16e3cf6c0a5fdd9bc10c21687e19d29ad1fe863372b5543deaec1039581a30"}, + {file = "cffi-1.14.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:f2b0fa0c01d8a0c7483afd9f31d7ecf2d71760ca24499c8697aeb5ca37dc090c"}, + {file = "cffi-1.14.0-cp27-cp27m-win32.whl", hash = "sha256:99f748a7e71ff382613b4e1acc0ac83bf7ad167fb3802e35e90d9763daba4d78"}, + {file = "cffi-1.14.0-cp27-cp27m-win_amd64.whl", hash = "sha256:c420917b188a5582a56d8b93bdd8e0f6eca08c84ff623a4c16e809152cd35793"}, + {file = "cffi-1.14.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:399aed636c7d3749bbed55bc907c3288cb43c65c4389964ad5ff849b6370603e"}, + {file = "cffi-1.14.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:cab50b8c2250b46fe738c77dbd25ce017d5e6fb35d3407606e7a4180656a5a6a"}, + {file = "cffi-1.14.0-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:001bf3242a1bb04d985d63e138230802c6c8d4db3668fb545fb5005ddf5bb5ff"}, + {file = "cffi-1.14.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:e56c744aa6ff427a607763346e4170629caf7e48ead6921745986db3692f987f"}, + {file = "cffi-1.14.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:b8c78301cefcf5fd914aad35d3c04c2b21ce8629b5e4f4e45ae6812e461910fa"}, + {file = "cffi-1.14.0-cp35-cp35m-win32.whl", hash = "sha256:8c0ffc886aea5df6a1762d0019e9cb05f825d0eec1f520c51be9d198701daee5"}, + {file = "cffi-1.14.0-cp35-cp35m-win_amd64.whl", hash = "sha256:8a6c688fefb4e1cd56feb6c511984a6c4f7ec7d2a1ff31a10254f3c817054ae4"}, + {file = "cffi-1.14.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:95cd16d3dee553f882540c1ffe331d085c9e629499ceadfbda4d4fde635f4b7d"}, + {file = "cffi-1.14.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:66e41db66b47d0d8672d8ed2708ba91b2f2524ece3dee48b5dfb36be8c2f21dc"}, + {file = "cffi-1.14.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:028a579fc9aed3af38f4892bdcc7390508adabc30c6af4a6e4f611b0c680e6ac"}, + {file = "cffi-1.14.0-cp36-cp36m-win32.whl", hash = "sha256:cef128cb4d5e0b3493f058f10ce32365972c554572ff821e175dbc6f8ff6924f"}, + {file = "cffi-1.14.0-cp36-cp36m-win_amd64.whl", hash = "sha256:337d448e5a725bba2d8293c48d9353fc68d0e9e4088d62a9571def317797522b"}, + {file = "cffi-1.14.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e577934fc5f8779c554639376beeaa5657d54349096ef24abe8c74c5d9c117c3"}, + {file = "cffi-1.14.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:62ae9af2d069ea2698bf536dcfe1e4eed9090211dbaafeeedf5cb6c41b352f66"}, + {file = "cffi-1.14.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:14491a910663bf9f13ddf2bc8f60562d6bc5315c1f09c704937ef17293fb85b0"}, + {file = "cffi-1.14.0-cp37-cp37m-win32.whl", hash = "sha256:c43866529f2f06fe0edc6246eb4faa34f03fe88b64a0a9a942561c8e22f4b71f"}, + {file = "cffi-1.14.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2089ed025da3919d2e75a4d963d008330c96751127dd6f73c8dc0c65041b4c26"}, + {file = "cffi-1.14.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3b911c2dbd4f423b4c4fcca138cadde747abdb20d196c4a48708b8a2d32b16dd"}, + {file = "cffi-1.14.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:7e63cbcf2429a8dbfe48dcc2322d5f2220b77b2e17b7ba023d6166d84655da55"}, + {file = "cffi-1.14.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:3d311bcc4a41408cf5854f06ef2c5cab88f9fded37a3b95936c9879c1640d4c2"}, + {file = "cffi-1.14.0-cp38-cp38-win32.whl", hash = "sha256:675686925a9fb403edba0114db74e741d8181683dcf216be697d208857e04ca8"}, + {file = "cffi-1.14.0-cp38-cp38-win_amd64.whl", hash = "sha256:00789914be39dffba161cfc5be31b55775de5ba2235fe49aa28c148236c4e06b"}, + {file = "cffi-1.14.0.tar.gz", hash = "sha256:2d384f4a127a15ba701207f7639d94106693b6cd64173d6c8988e2c25f3ac2b6"}, +] +chardet = [ + {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, + {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, +] +cryptography = [ + {file = "cryptography-2.8-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:fb81c17e0ebe3358486cd8cc3ad78adbae58af12fc2bf2bc0bb84e8090fa5ce8"}, + {file = "cryptography-2.8-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:44ff04138935882fef7c686878e1c8fd80a723161ad6a98da31e14b7553170c2"}, + {file = "cryptography-2.8-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:369d2346db5934345787451504853ad9d342d7f721ae82d098083e1f49a582ad"}, + {file = "cryptography-2.8-cp27-cp27m-win32.whl", hash = "sha256:df6b4dca2e11865e6cfbfb708e800efb18370f5a46fd601d3755bc7f85b3a8a2"}, + {file = "cryptography-2.8-cp27-cp27m-win_amd64.whl", hash = "sha256:7f09806ed4fbea8f51585231ba742b58cbcfbfe823ea197d8c89a5e433c7e912"}, + {file = "cryptography-2.8-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:58363dbd966afb4f89b3b11dfb8ff200058fbc3b947507675c19ceb46104b48d"}, + {file = "cryptography-2.8-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:6ec280fb24d27e3d97aa731e16207d58bd8ae94ef6eab97249a2afe4ba643d42"}, + {file = "cryptography-2.8-cp34-abi3-macosx_10_6_intel.whl", hash = "sha256:b43f53f29816ba1db8525f006fa6f49292e9b029554b3eb56a189a70f2a40879"}, + {file = "cryptography-2.8-cp34-abi3-manylinux1_x86_64.whl", hash = "sha256:7270a6c29199adc1297776937a05b59720e8a782531f1f122f2eb8467f9aab4d"}, + {file = "cryptography-2.8-cp34-abi3-manylinux2010_x86_64.whl", hash = "sha256:de96157ec73458a7f14e3d26f17f8128c959084931e8997b9e655a39c8fde9f9"}, + {file = "cryptography-2.8-cp34-cp34m-win32.whl", hash = "sha256:02079a6addc7b5140ba0825f542c0869ff4df9a69c360e339ecead5baefa843c"}, + {file = "cryptography-2.8-cp34-cp34m-win_amd64.whl", hash = "sha256:b0de590a8b0979649ebeef8bb9f54394d3a41f66c5584fff4220901739b6b2f0"}, + {file = "cryptography-2.8-cp35-cp35m-win32.whl", hash = "sha256:ecadccc7ba52193963c0475ac9f6fa28ac01e01349a2ca48509667ef41ffd2cf"}, + {file = "cryptography-2.8-cp35-cp35m-win_amd64.whl", hash = "sha256:90df0cc93e1f8d2fba8365fb59a858f51a11a394d64dbf3ef844f783844cc793"}, + {file = "cryptography-2.8-cp36-cp36m-win32.whl", hash = "sha256:1df22371fbf2004c6f64e927668734070a8953362cd8370ddd336774d6743595"}, + {file = "cryptography-2.8-cp36-cp36m-win_amd64.whl", hash = "sha256:a518c153a2b5ed6b8cc03f7ae79d5ffad7315ad4569b2d5333a13c38d64bd8d7"}, + {file = "cryptography-2.8-cp37-cp37m-win32.whl", hash = "sha256:4b1030728872c59687badcca1e225a9103440e467c17d6d1730ab3d2d64bfeff"}, + {file = "cryptography-2.8-cp37-cp37m-win_amd64.whl", hash = "sha256:d31402aad60ed889c7e57934a03477b572a03af7794fa8fb1780f21ea8f6551f"}, + {file = "cryptography-2.8-cp38-cp38-win32.whl", hash = "sha256:73fd30c57fa2d0a1d7a49c561c40c2f79c7d6c374cc7750e9ac7c99176f6428e"}, + {file = "cryptography-2.8-cp38-cp38-win_amd64.whl", hash = "sha256:971221ed40f058f5662a604bd1ae6e4521d84e6cad0b7b170564cc34169c8f13"}, + {file = "cryptography-2.8.tar.gz", hash = "sha256:3cda1f0ed8747339bbdf71b9f38ca74c7b592f24f65cdb3ab3765e4b02871651"}, +] +decorator = [ + {file = "decorator-4.4.2-py2.py3-none-any.whl", hash = "sha256:41fa54c2a0cc4ba648be4fd43cff00aedf5b9465c9bf18d64325bc225f08f760"}, + {file = "decorator-4.4.2.tar.gz", hash = "sha256:e3a62f0520172440ca0dcc823749319382e377f37f140a0b99ef45fecb84bfe7"}, +] +filetype = [ + {file = "filetype-1.0.6-py2.py3-none-any.whl", hash = "sha256:fd6d0ec56820acccf8c9fb6c3ba7e04a302f6ff6c70bcc09daf4842ae9e2ac30"}, + {file = "filetype-1.0.6.tar.gz", hash = "sha256:99d2b923921cadbe6e451249091ca7156b4beaee6e741bd711a582d4dd2f2881"}, +] +future = [ + {file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"}, +] +idna = [ + {file = "idna-2.9-py2.py3-none-any.whl", hash = "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"}, + {file = "idna-2.9.tar.gz", hash = "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb"}, +] +markovify = [ + {file = "markovify-0.8.0.tar.gz", hash = "sha256:c533a2e1aba8148bb98031b7159e8bf1a276c61db53d2e882ecb74fa5603a4f4"}, +] +mutagen = [ + {file = "mutagen-1.44.0-py3-none-any.whl", hash = "sha256:1cfc9f40cc0c89f051e3f3dbd5d9057a193c98433cf6c95e02d7f5a395615c01"}, + {file = "mutagen-1.44.0.tar.gz", hash = "sha256:56065d8a9ca0bc64610a4d0f37e2bd4453381dde3226b8835ee656faa3287be4"}, +] +oauthlib = [ + {file = "oauthlib-3.1.0-py2.py3-none-any.whl", hash = "sha256:df884cd6cbe20e32633f1db1072e9356f53638e4361bef4e8b03c9127c9328ea"}, + {file = "oauthlib-3.1.0.tar.gz", hash = "sha256:bee41cc35fcca6e988463cacc3bcb8a96224f470ca547e697b604cc697b2f889"}, +] +pyacoustid = [ + {file = "pyacoustid-1.1.7.tar.gz", hash = "sha256:07394a8ae84625a0a6fef2d891d19687ff59cd955caaf48097da2826043356fd"}, +] +pycparser = [ + {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"}, + {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, +] +python-telegram-bot = [ + {file = "python-telegram-bot-12.4.2.tar.gz", hash = "sha256:0a97cbca638f949582b4ee326170d2f8d7f4bf559a4e511132bb2203623e04ad"}, + {file = "python_telegram_bot-12.4.2-py2.py3-none-any.whl", hash = "sha256:d3cffd020af4094d07c11783f875e5c682072ba7f5bc21ce89ff0222f4e6d742"}, +] +pytumblr = [ + {file = "PyTumblr-0.1.0-py2.py3-none-any.whl", hash = "sha256:a3774d3978bcff2db98f36a2e5d17bb8496ac21157b1b518089adad86d0dca72"}, + {file = "PyTumblr-0.1.0.tar.gz", hash = "sha256:eaa4d98217df7ab6392fa5d8801f4a2bdcba35bf0fd49328aa3c98e3b231b6f2"}, +] +requests = [ + {file = "requests-2.23.0-py2.py3-none-any.whl", hash = "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee"}, + {file = "requests-2.23.0.tar.gz", hash = "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6"}, +] +requests-oauthlib = [ + {file = "requests-oauthlib-1.3.0.tar.gz", hash = "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a"}, + {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"}, +] +six = [ + {file = "six-1.14.0-py2.py3-none-any.whl", hash = "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"}, + {file = "six-1.14.0.tar.gz", hash = "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a"}, +] +tornado = [ + {file = "tornado-6.0.4-cp35-cp35m-win32.whl", hash = "sha256:5217e601700f24e966ddab689f90b7ea4bd91ff3357c3600fa1045e26d68e55d"}, + {file = "tornado-6.0.4-cp35-cp35m-win_amd64.whl", hash = "sha256:c98232a3ac391f5faea6821b53db8db461157baa788f5d6222a193e9456e1740"}, + {file = "tornado-6.0.4-cp36-cp36m-win32.whl", hash = "sha256:5f6a07e62e799be5d2330e68d808c8ac41d4a259b9cea61da4101b83cb5dc673"}, + {file = "tornado-6.0.4-cp36-cp36m-win_amd64.whl", hash = "sha256:c952975c8ba74f546ae6de2e226ab3cc3cc11ae47baf607459a6728585bb542a"}, + {file = "tornado-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:2c027eb2a393d964b22b5c154d1a23a5f8727db6fda837118a776b29e2b8ebc6"}, + {file = "tornado-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:5618f72e947533832cbc3dec54e1dffc1747a5cb17d1fd91577ed14fa0dc081b"}, + {file = "tornado-6.0.4-cp38-cp38-win32.whl", hash = "sha256:22aed82c2ea340c3771e3babc5ef220272f6fd06b5108a53b4976d0d722bcd52"}, + {file = "tornado-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:c58d56003daf1b616336781b26d184023ea4af13ae143d9dda65e31e534940b9"}, + {file = "tornado-6.0.4.tar.gz", hash = "sha256:0fe2d45ba43b00a41cd73f8be321a44936dc1aba233dee979f17a042b83eb6dc"}, +] +unidecode = [ + {file = "Unidecode-1.1.1-py2.py3-none-any.whl", hash = "sha256:1d7a042116536098d05d599ef2b8616759f02985c85b4fef50c78a5aaf10822a"}, + {file = "Unidecode-1.1.1.tar.gz", hash = "sha256:2b6aab710c2a1647e928e36d69c21e76b453cd455f4e2621000e54b2a9b8cce8"}, +] +urllib3 = [ + {file = "urllib3-1.25.8-py2.py3-none-any.whl", hash = "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc"}, + {file = "urllib3-1.25.8.tar.gz", hash = "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc"}, +] +youtube-dl = [ + {file = "youtube_dl-2020.3.24-py2.py3-none-any.whl", hash = "sha256:c0be39ea9bca72fa02a0d2d043c5e9bd8ea8e0fe79705e891161d6fcd29da59e"}, + {file = "youtube_dl-2020.3.24.tar.gz", hash = "sha256:4b03efe439f7cae26eba909821d1df00a9a4eb82741cb2e8b78fe29702bd4633"}, +] diff --git a/src/pyproject.toml b/src/pyproject.toml new file mode 100644 index 0000000..07f8755 --- /dev/null +++ b/src/pyproject.toml @@ -0,0 +1,24 @@ +[tool.poetry] +name = "delojza" +version = "0.1.0" +description = "" +authors = ["Tomáš Mládek "] +license = "MIT" + +[tool.poetry.dependencies] +python = "^3.8" +python-telegram-bot = "^12.4.2" +youtube-dl = "^2020" +requests = "^2.23.0" +filetype = "^1.0.6" +mutagen = "^1.44.0" +pyacoustid = "^1.1.7" +pytumblr = "^0.1.0" +markovify = "^0.8.0" +unidecode = "^1.1.1" + +[tool.poetry.dev-dependencies] + +[build-system] +requires = ["poetry>=0.12"] +build-backend = "poetry.masonry.api" diff --git a/src/requirements.in b/src/requirements.in deleted file mode 100644 index dd3aeea..0000000 --- a/src/requirements.in +++ /dev/null @@ -1,9 +0,0 @@ -python-telegram-bot -youtube-dl -requests -filetype -mutagen -pyacoustid -pytumblr -markovify -unidecode \ No newline at end of file diff --git a/src/requirements.txt b/src/requirements.txt deleted file mode 100644 index 3a4ec2e..0000000 --- a/src/requirements.txt +++ /dev/null @@ -1,28 +0,0 @@ -# -# This file is autogenerated by pip-compile -# To update, run: -# -# pip-compile -# -asn1crypto==0.24.0 # via cryptography -audioread==2.1.8 # via pyacoustid -certifi==2019.3.9 # via python-telegram-bot, requests -cffi==1.12.3 # via cryptography -chardet==3.0.4 # via requests -cryptography==2.7 # via python-telegram-bot -filetype==1.0.5 -future==0.17.1 # via python-telegram-bot, pytumblr -idna==2.8 # via requests -markovify==0.7.1 -mutagen==1.42.0 -oauthlib==3.0.1 # via requests-oauthlib -pyacoustid==1.1.7 -pycparser==2.19 # via cffi -python-telegram-bot==11.1.0 -pytumblr==0.0.8 -requests-oauthlib==1.2.0 # via pytumblr -requests==2.22.0 -six==1.12.0 # via cryptography -unidecode==1.0.23 -urllib3==1.25.3 # via requests -youtube-dl==2019.5.20