diff --git a/YouTubeMDBot/__init__.py b/YouTubeMDBot/__init__.py
new file mode 100644
index 0000000..d0c79d3
--- /dev/null
+++ b/YouTubeMDBot/__init__.py
@@ -0,0 +1,23 @@
+# YouTubeMDBot
+# Copyright (C) 2019 - Javinator9889
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+from .bot import PROGRAM_ARGS
+from .bot import main
+
+from .logging_utils import LoggingHandler
+from .logging_utils import setup_logging
+
+from .decorators import send_action
+from .decorators import restricted
diff --git a/YouTubeMDBot/__main__.py b/YouTubeMDBot/__main__.py
new file mode 100644
index 0000000..8a858f1
--- /dev/null
+++ b/YouTubeMDBot/__main__.py
@@ -0,0 +1,15 @@
+# YouTubeMDBot
+# Copyright (C) 2019 - Javinator9889
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
diff --git a/YouTubeMDBot/bot.py b/YouTubeMDBot/bot.py
new file mode 100644
index 0000000..10b68d9
--- /dev/null
+++ b/YouTubeMDBot/bot.py
@@ -0,0 +1,37 @@
+# YouTubeMDBot
+# Copyright (C) 2019 - Javinator9889
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+from telegram.ext import Updater
+from telegram.ext import CommandHandler
+
+PROGRAM_ARGS = None
+
+
+def main(args: dict):
+ global PROGRAM_ARGS
+ PROGRAM_ARGS = args
+ updater = Updater(args["token"], workers=args["workers"])
+
+ dispatcher = updater.dispatcher
+ dispatcher.add_handler(CommandHandler("hello", main))
+
+ if args["use_webhook"]:
+ updater.start_webhook(listen=args["ip"],
+ port=args["port"],
+ url_path=args["token"],
+ webhook_url=args["public_url"] + '/' + args["token"])
+ else:
+ updater.start_polling(args["poll_interval"])
+ updater.idle()
diff --git a/YouTubeMDBot/commands/StartHandler.py b/YouTubeMDBot/commands/StartHandler.py
new file mode 100644
index 0000000..d209a1e
--- /dev/null
+++ b/YouTubeMDBot/commands/StartHandler.py
@@ -0,0 +1,24 @@
+# YouTubeMDBot
+# Copyright (C) 2019 - Javinator9889
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+from .. import LoggingHandler
+
+
+class StartHandler(object):
+ def __init__(self):
+ self._user_data = {}
+
+ def start(self, bot, update):
+ self._user_data[]
diff --git a/YouTubeMDBot/commands/__init__.py b/YouTubeMDBot/commands/__init__.py
new file mode 100644
index 0000000..8a858f1
--- /dev/null
+++ b/YouTubeMDBot/commands/__init__.py
@@ -0,0 +1,15 @@
+# YouTubeMDBot
+# Copyright (C) 2019 - Javinator9889
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
diff --git a/YouTubeMDBot/constants/__init__.py b/YouTubeMDBot/constants/__init__.py
new file mode 100644
index 0000000..b8d3e20
--- /dev/null
+++ b/YouTubeMDBot/constants/__init__.py
@@ -0,0 +1,17 @@
+# YouTubeMDBot
+# Copyright (C) 2019 - Javinator9889
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+from ..constants.app_constants import ydl_options
+from ..constants.app_constants import STREAM_OFFSET
diff --git a/YouTubeMDBot/constants/app_constants.py b/YouTubeMDBot/constants/app_constants.py
new file mode 100644
index 0000000..f738ade
--- /dev/null
+++ b/YouTubeMDBot/constants/app_constants.py
@@ -0,0 +1,21 @@
+# YouTubeMDBot
+# Copyright (C) 2019 - Javinator9889
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+ydl_options: dict = {
+ "format": "bestaudio[ext=m4a]",
+ "outtmpl": "-",
+ "logger": ""
+}
+STREAM_OFFSET: int = 0
diff --git a/YouTubeMDBot/decorators/__init__.py b/YouTubeMDBot/decorators/__init__.py
new file mode 100644
index 0000000..9a87cd2
--- /dev/null
+++ b/YouTubeMDBot/decorators/__init__.py
@@ -0,0 +1,17 @@
+# YouTubeMDBot
+# Copyright (C) 2019 - Javinator9889
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+from ..decorators.decorators import restricted
+from ..decorators.decorators import send_action
diff --git a/YouTubeMDBot/decorators/decorators.py b/YouTubeMDBot/decorators/decorators.py
new file mode 100644
index 0000000..5c305b4
--- /dev/null
+++ b/YouTubeMDBot/decorators/decorators.py
@@ -0,0 +1,55 @@
+# YouTubeMDBot
+# Copyright (C) 2019 - Javinator9889
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+from functools import wraps
+
+from .. import PROGRAM_ARGS
+from .. import LoggingHandler
+
+
+logging = LoggingHandler()
+
+
+def send_action(action):
+ """
+ Sends an action while processing a command.
+ :param action: the action to be performed.
+ :return: itself.
+ """
+
+ def decorator(func):
+ @wraps(func)
+ def command_func(update, context, *args, **kwargs):
+ context.bot.send_chat_action(chat_id=update.effective_message.chat_id, action=action)
+ return func(update, context, *args, **kwargs)
+ return command_func
+
+ return decorator
+
+
+def restricted(func):
+ """
+ Restricts a specific function to be accessed from non-authorized users.
+ :param func: function to be wrapped.
+ :return: itself.
+ """
+ @wraps(func)
+ def wrapped(update, context, *args, **kwargs):
+ user_id = update.effective_user.id
+ if user_id not in PROGRAM_ARGS["admin"]:
+ logging.warning("Unauthorized access denied for {}.".format(user_id))
+ return
+ return func(update, context, *args, **kwargs)
+ return wrapped
diff --git a/YouTubeMDBot/downloader/__init__.py b/YouTubeMDBot/downloader/__init__.py
new file mode 100644
index 0000000..89c3cee
--- /dev/null
+++ b/YouTubeMDBot/downloader/__init__.py
@@ -0,0 +1,16 @@
+# YouTubeMDBot
+# Copyright (C) 2019 - Javinator9889
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+from ..downloader.youtube_downloader import YouTubeDownloader
diff --git a/YouTubeMDBot/downloader/youtube_downloader.py b/YouTubeMDBot/downloader/youtube_downloader.py
new file mode 100644
index 0000000..b956952
--- /dev/null
+++ b/YouTubeMDBot/downloader/youtube_downloader.py
@@ -0,0 +1,39 @@
+# YouTubeMDBot
+# Copyright (C) 2019 - Javinator9889
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+import logging
+import youtube_dl
+
+from contextlib import redirect_stdout as save_to
+from io import BytesIO
+
+from ..constants.app_constants import ydl_options
+from ..constants.app_constants import STREAM_OFFSET
+
+
+class YouTubeDownloader(object):
+ def __init__(self, url: str,
+ logger: logging = logging.getLogger("empty-logger")):
+ self.__url: str = url
+ self.__options: dict = ydl_options
+ self.__options["logger"] = logger
+
+ def download(self, io: BytesIO = BytesIO()) -> BytesIO:
+ with save_to(io):
+ with youtube_dl.YoutubeDL(self.__options) as yt_downloader:
+ yt_downloader.download([self.__url])
+
+ io.seek(STREAM_OFFSET)
+ return io
diff --git a/YouTubeMDBot/logging_utils/__init__.py b/YouTubeMDBot/logging_utils/__init__.py
new file mode 100644
index 0000000..45c2549
--- /dev/null
+++ b/YouTubeMDBot/logging_utils/__init__.py
@@ -0,0 +1,17 @@
+# YouTubeMDBot
+# Copyright (C) 2019 - Javinator9889
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+from ..logging_utils.utils import LoggingHandler
+from ..logging_utils.utils import setup_logging
diff --git a/YouTubeMDBot/logging_utils/utils.py b/YouTubeMDBot/logging_utils/utils.py
new file mode 100644
index 0000000..309a620
--- /dev/null
+++ b/YouTubeMDBot/logging_utils/utils.py
@@ -0,0 +1,116 @@
+# YouTubeMDBot
+# Copyright (C) 2019 - Javinator9889
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+import logging
+
+
+def cleanup_old_logs(log_file: str):
+ import tarfile
+ import os
+
+ tar_log_filename = log_file + ".tar.gz"
+
+ if os.path.exists(log_file):
+ if os.path.exists(tar_log_filename):
+ os.remove(tar_log_filename)
+ with tarfile.open(tar_log_filename, "w:gz") as tar:
+ tar.add(log_file, arcname=os.path.basename(log_file))
+ tar.close()
+ os.remove(log_file)
+
+
+def setup_logging(logger_name: str, log_file: str, level=logging.DEBUG,
+ formatter: str = "%(process)d - %(asctime)s | [%(levelname)s]: %(message)s"):
+ from os import path
+ from os import makedirs
+
+ log_dir = path.dirname(path.abspath(log_file))
+ if not path.exists(log_dir):
+ makedirs(log_dir)
+
+ cleanup_old_logs(log_file)
+ new_logging = logging.getLogger(logger_name)
+ logging_formatter = logging.Formatter(formatter)
+ logging_file_handler = logging.FileHandler(log_file, mode="w")
+
+ logging_file_handler.setFormatter(logging_formatter)
+
+ new_logging.setLevel(level)
+ new_logging.addHandler(logging_file_handler)
+
+ return logging_file_handler
+
+
+class LoggingHandler(object):
+ class __LoggingHandler(object):
+ def __init__(self, logs: list):
+ self.__logs = logs
+
+ def debug(self, msg):
+ for log in self.__logs:
+ log.debug(msg)
+
+ def info(self, msg):
+ for log in self.__logs:
+ log.info(msg)
+
+ def error(self, msg):
+ for log in self.__logs:
+ log.error(msg)
+
+ def warning(self, msg):
+ for log in self.__logs:
+ log.warning(msg)
+
+ def critical(self, msg):
+ for log in self.__logs:
+ log.critical(msg)
+
+ def get_loggers(self) -> list:
+ return self.__logs
+
+ __instance = None
+
+ def __new__(cls, *args, **kwargs):
+ if not LoggingHandler.__instance:
+ logs = kwargs.get("logs")
+ if not logs or len(logs) == 0:
+ raise AttributeError("At least kwarg \"log\" (a list of the loggers) must be provided")
+ LoggingHandler.__instance = LoggingHandler.__LoggingHandler(logs)
+ return LoggingHandler.__instance
+
+ def __getattr__(self, item):
+ return getattr(self.__instance, item)
+
+ def __setattr__(self, key, value):
+ return setattr(self.__instance, key, value)
+
+ def debug(self, msg):
+ self.__instance.debug(msg)
+
+ def info(self, msg):
+ self.__instance.info(msg)
+
+ def error(self, msg):
+ self.__instance.error(msg)
+
+ def warning(self, msg):
+ self.__instance.warning(msg)
+
+ def critical(self, msg):
+ self.__instance.critical(msg)
+
+ def get_loggers(self) -> list:
+ return self.__instance.get_loggers()
diff --git a/YouTubeMDBot/metadata/MetadataIdentifier.py b/YouTubeMDBot/metadata/MetadataIdentifier.py
new file mode 100644
index 0000000..b473a23
--- /dev/null
+++ b/YouTubeMDBot/metadata/MetadataIdentifier.py
@@ -0,0 +1,20 @@
+# YouTubeMDBot
+# Copyright (C) 2019 - Javinator9889
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+import acoustid
+
+
+class MetadataIdentifier(object):
+ def __init__(self, filename: str = None, audio: str = None):
diff --git a/YouTubeMDBot/metadata/__init__.py b/YouTubeMDBot/metadata/__init__.py
new file mode 100644
index 0000000..8a858f1
--- /dev/null
+++ b/YouTubeMDBot/metadata/__init__.py
@@ -0,0 +1,15 @@
+# YouTubeMDBot
+# Copyright (C) 2019 - Javinator9889
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
diff --git a/YouTubeMDBot/requirements.txt b/YouTubeMDBot/requirements.txt
new file mode 100644
index 0000000..9c3d398
--- /dev/null
+++ b/YouTubeMDBot/requirements.txt
@@ -0,0 +1,3 @@
+youtube_dl
+pyacoustid
+python-telegram-bot