Compare commits

..

20 Commits

Author SHA1 Message Date
f0ad40bfdd Merge pull request 'Переход от месива из баш скриптов к нормальному питоновскому коду' (#5) from move-to-python into master
Reviewed-on: #5
2022-11-13 12:45:15 +03:00
7961509aca Перешел на другую, актуальную библиотеку твича. 2022-11-13 12:43:03 +03:00
7cb3c36759 pep-8 2022-11-13 11:31:48 +03:00
b0c0573d34 Заменил os.system на нативные аналоги 2021-09-25 23:49:08 +03:00
c38cb73e3e Потенциальный фикс против падения на 104 строке 2021-09-25 23:18:08 +03:00
3a539f3ce8 Не создавать папки несуществующих стримеров 2021-09-25 14:54:26 +03:00
fc1331e075 fix readme 2021-09-25 14:49:14 +03:00
10c36350e7 Done TODO 2021-09-25 14:26:34 +03:00
c08670d2a2 Добавил устойчивость к несуществующим/забаненым юзерам 2021-09-25 14:25:34 +03:00
dd340b8caa Добавил цвета 2021-09-23 06:27:54 +03:00
1ed28aea26 Поправил удаление старых записей 2021-09-23 06:06:17 +03:00
36d6d1135b Больше PEP8+поправил еще чучуть 2021-09-23 04:11:36 +03:00
52335dd676 Доп опции ytdl пока не поддерживаются 2021-09-23 04:00:59 +03:00
b6f328b682 Поправил код в соответствии с PEP8, настроил логи 2021-09-23 03:59:05 +03:00
6e3cada45c Пофиксил автоудаление стримов 2021-08-05 00:45:31 +00:00
60a5341cdf Свои параметры к ytdl 2021-08-05 00:40:42 +00:00
ce76a97253 Путь, имя, частота опроса.
Увеличил частоту опроса до секунд, поправил лог, поправил путь для записи.
2021-07-31 11:41:35 +00:00
bc996a1430 DONE: автоматическое удаление старых стримов 2021-07-23 01:07:53 +00:00
5fbdee20a5 path fix 2021-07-22 23:28:56 +00:00
e776f8d4e4 Перенес TODO вверх, сделал глобальные переменные 2021-07-22 23:28:08 +00:00
5 changed files with 153 additions and 57 deletions

2
.gitignore vendored
View File

@@ -3,3 +3,5 @@ config_python.py
config_list.sh
__pycache__
.vscode
.idea
output.log

View File

@@ -1,22 +1,30 @@
# Что это?
Скрипт который проверяет и начинает запись стримов с твича (WIP)
Скрипт, который записывает стримы с твича, удаляет старые, ведет красивый лог с цветами (Alpha)
# Как юзать?
* Поставить youtube-dl, python-twitch-client
* Поставить youtube-dl, ffmpeg и другие пакеты из requirements.txt
`pip3 install python-twitch-client youtube-dl`
`apt install youtube-dl ffmpeg -y`
* Создать файл conf_python.py и добавить свой ключ (Можно получить на https://dev.twitch.tv/console), а также переменные:
`pip install -r requirements.txt`
* Создать файл conf_python.py и добавить свой ключ (Можно получить на https://dev.twitch.tv/console), а также переменные из config_python.py.template:
```
twitchid="ID" # ID ключа
twitchid = "ID" # ID ключа
streamers = ("jesusavgn", "252mart", "vi0xxx") # список стримеров в таком формате
path="/путь/до/диры/со/стримами" # путь до директории, куда писать стримы
path = "/путь/до/диры/со/стримами" # путь до директории, куда писать стримы
check_period = 5 # Частота проверки стримеров (в секундах)
max_files = 3 # Сколько хранить стримов
```
* Добавить daemon.py в crontab, ну и офк убедиться что cron.service запущен (systemd timer не подойдет ибо он убивает child процессы после завершения работы родителя)
* Запустить скрипт в screen'е или создать для него systemd.service файл (или init.d, в зависимости от системы инициализации)
`*/5 * * * * /opt/twitch-downloader/cron.sh`
# Updates
## 2022-11-13
В связи с переходом на новую библиотеку необходимо указывать 2 переменные авторизации - appid и appsecret.
twitchid это appid, а секретный ключ можно получить или перегенерировать в https://dev.twitch.tv/console

View File

@@ -1,4 +1,5 @@
twitchid="....."
appid=""
appsecret=""
streamers = ("jesusavgn", "252mart", "vi0xxx")
path="/home/losted/test"
period = 5

170
daemon.py
View File

@@ -1,23 +1,35 @@
#!/usr/bin/python3
# FIXME: не создавать папки для несуществующих стримеров
# TODO: Перезапускать скрипт при обнаружении новой версии
# TODO: Сделать нормальную конфигурацию
# TODO: Автоматически удалять старые стримы
import os
import sys
from threading import Thread
from types import resolve_bases
import config_python
import schedule
from twitch import TwitchClient
from twitchAPI.twitch import Twitch
import subprocess
import time
import logging
from logging.handlers import TimedRotatingFileHandler
from termcolor import colored
streamers = config_python.streamers
app_id = config_python.appid
app_secret = config_python.appsecret
log_format = logging.Formatter('%(asctime)s %(levelname)s:%(message)s')
log_file = 'output.log'
def which(command):
# Пиздец, почему нет нормального аналога which из bash???
'''
Мой аналог which из bash'а, который отдает true или false при наличии или отсутствии утилиты
'''
"""
Мой аналог which из bash'а, который отдает true или false
при наличии или отсутствии утилиты
"""
for dirs in os.get_exec_path():
if command in os.listdir(dirs):
# Если что-нибудь нашли, то True
@@ -25,80 +37,152 @@ def which(command):
# Если ничего не нашли во всех дирах, то выходим с False
return False
def checkTools():
'''
"""
Проверяет, установлены ли необходимые утилиты
'''
"""
tools = ('youtube-dl', 'ffmpeg')
for i in tools:
if not which(i):
print(i + " не установлен")
log.critical(i + " не установлен")
return False
return True
def startRecord(i):
'''
"""
Функция, которая запускает в отдельном потоке запись стрима - recorder(i)
'''
"""
th = Thread(target=recorder, args=(i, ))
th.start()
def recorder(i):
'''
"""
Функция, которая запускает youtube-dl, фактически записывает стрим
'''
path = config_python.path + "/"+ i
print("Записываем стрим %s\n" % i)
"""
path = config_python.path + "/" + i
log.info("Записываем стрим %s\n" % i)
# cmdline для запуска youtube-dl
# TODO: сделать возможность добавлять свои параметры
cmdline = ["youtube-dl","https://twitch.tv/"+i]
s = subprocess.call(cmdline, stdout=subprocess.DEVNULL)
print("Запись стрима %s закончена\n" % i)
if (os.path.exists(path+"/pid")):
os.system("rm "+path+"/pid")
print("lock файл удален")
cmdline = ["youtube-dl", "-q", "-o",
path+"/%(upload_date)s_%(title)s__%(timestamp)s_%(id)s.%(ext)s",
"https://twitch.tv/" + i]
subprocess.call(cmdline)
log.info("Запись стрима %s закончена\n" % i)
if os.path.exists(path + "/pid"):
os.remove(path+"/pid")
log.info("lock файл удален")
def checkAlive():
streamers = config_python.streamers
client_id = config_python.twitchid
'''
# FIXME: Распилить ну более мелкие функции
"""
1. Проверка на наличие стрима
1.1 Если нет - удалить lock файл, если он есть
1.2 Если есть - создать lock файл, запустить записывалку
'''
client = TwitchClient(client_id=client_id)
"""
for i in streamers:
# Путь до диры со стримами
path = config_python.path + "/"+ i
# Создаем путь до диры со стримером, если его нет
if not (os.path.exists(config_python.path+"/"+i)):
path = config_python.path + "/" + i
# Получаем инфо о стримере, если не получается, выходим с ошибкой
# resolved_id = client.users.translate_usernames_to_ids(i)
resolved_id = twitch_client.get_users(logins=[i])
if not resolved_id['data']:
log.error(
colored(
"Аккаунт " + i + " не найден",
'red',
)
)
break
# Создаем путь до диры со стримером, если папка не существует
if not (os.path.exists(path)):
os.makedirs(path)
# TODO: Сделать проверку на наличие стримера
user_id=client.users.translate_usernames_to_ids(i)[0]['id'] # Получить ID по нику
log.info("Создана директория " + i)
# Достаем ID стримера из инфо
user_id = resolved_id['data'][0]['id']
user_stream = twitch_client.get_streams(user_id=user_id)
# Если стрим идет, то идем дальше
if client.streams.get_stream_by_user(user_id):
if user_stream['data']:
# Если стрим идет и лок файла нет, то записываем и ставим лок
if (client.streams.get_stream_by_user(user_id).stream_type == 'live') and not (os.path.exists(config_python.path+"/"+i+"/pid")):
print(i+" стримит")
if (user_stream['data'][0]['type'] == 'live') and not (os.path.exists(config_python.path+"/"+i+"/pid")):
log.info(i + " стримит")
startRecord(i)
os.system("touch "+path+"/pid")
open(path+"/pid", 'w').close
else:
print(i+" Уже стримит")
log.info(
colored(
"Идет запись " + i,
'red',
attrs=['bold']
)
)
else:
# Если стрим не идет, то пишем об этом и убираем его из залоченных
print(i+" Не стримит")
log.info(i + " Не стримит")
# Если есть лок, то удаляем
if (os.path.exists(path+"/pid")):
os.system("rm "+path+"/pid")
if os.path.exists(path + "/pid"):
os.remove(path+"/pid")
def removeOldStreams():
# https://clck.ru/WHh32
pass
records_path = config_python.path
# По каждой папке со стримерами
for i in streamers:
try:
os.chdir(records_path+"/"+i)
# Если файлов в папке со стримами больше чем указано в конфиге
if len(os.listdir(records_path+"/"+i)) > config_python.max_files:
# Получаем список файлов
# и смотрим, превышает ли кол-во mp4 файлов заданное в конфиге
# Если превышает - удаляем старейший
oldest = min(os.listdir(records_path+"/"+i),
key=os.path.getctime)
os.unlink(oldest)
log.warning("Удален файл: " + oldest)
except Exception as e:
log.error(e)
def get_console_handler():
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setFormatter(log_format)
return console_handler
def get_file_handler():
file_handler = TimedRotatingFileHandler(log_file, when='midnight')
file_handler.setFormatter(log_format)
return file_handler
def get_logger(logger_name):
logger = logging.getLogger(logger_name)
logger.setLevel(logging.DEBUG)
logger.addHandler(get_console_handler())
logger.addHandler(get_file_handler())
logger.propagate = False
return logger
if __name__ == "__main__":
if not checkTools(): exit()
schedule.every(config_python.period).minutes.do(checkAlive)
# Проверить, установлены ли нужные утилиты
if not checkTools():
exit()
# Log config
log = get_logger("main")
log.info("Запущен")
# Проверять стримы раз в check_period
schedule.every(config_python.check_period).seconds.do(checkAlive)
# Каждый час удалять старые стримы
schedule.every(1).hours.do(removeOldStreams)
twitch_client = Twitch(app_id, app_secret)
while True:
schedule.run_pending()
time.sleep(1)

View File

@@ -1,3 +1,4 @@
youtube-dl==2021.4.17
python-twitch-client==0.7.1
twitchAPI==2.5.7.1
schedule
termcolor