Files
AE_script/AF_script_test_4.py

829 lines
26 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import telebot
import logging
import logging.config
from dotenv import load_dotenv
import os
from pprint import pprint
from synology_drive_api.drive import SynologyDrive
import pandas as pd
from transliterate import translit
import requests
from time import sleep
import datetime
import sys
PLACEHOLDER = sys.platform == "win32"
# XXX
if PLACEHOLDER:
from random import random, choices
def send_job_dumb(data):
if random() < 0.8:
uid = "".join(choices("abcdefghijklmnopqrstuvwxyz_", k=8))
return {"uid": uid, "outname": data["outfile_name"]}
class fake_resp:
def __init__(self, state="queured", *kargs, **kwargs):
self.state = state
self.status_code == 200
def json(self):
return {"state": self.state}
def fake_get():
if random < 0.8:
return fake_resp()
elif random < 0.8:
return fake_resp("finished")
else:
return fake_resp("error")
LOG_CONFIG = {
"version": 1,
"handlers": {
"telegram": {
"class": "telegram_handler.TelegramHandler",
"level": "INFO",
"token": TOKEN,
"chat_id": GROUP_CHAT,
"formatter": "telegram",
},
"console": {
"class": "logging.StreamHandler",
"level": "DEBUG",
"formatter": "simple",
"stream": "ext://sys.stdout",
},
"file": {
"class": "logging.FileHandler",
"level": "DEBUG",
"formatter": "simple",
"encoding": "utf-8",
"filename": "AF_script.log",
},
},
# ,'telegram'
"loggers": {__name__: {"handlers": ["console", "file"], "level": "DEBUG"}},
"formatters": {
"telegram": {
"class": "telegram_handler.HtmlFormatter",
"format": "%(levelname)s %(message)s",
"use_emoji": "True",
},
"simple": {
"class": "logging.Formatter",
"format": "%(asctime)s %(levelname)-8s %(funcName)12s() - %(message)s",
"datefmt": "%d.%m.%Y %H:%M:%S",
},
},
}
logging.config.dictConfig(LOG_CONFIG)
logger = logging.getLogger(__name__)
# logger.handlers[2].formatter.use_emoji=True
bot = telebot.TeleBot(TOKEN)
telebot.logger.addHandler(logger.handlers[1])
@bot.message_handler(commands=["help", "start"])
def send_welcome(message):
bot.send_chat_action(message.chat.id, "typing")
if message.from_user.username:
user = f" {message.from_user.username}"
else:
user = "!"
sleep(1)
bot.reply_to(
message,
f"Привет{user}\n Я помогу тебе сделать Анонсы!\n Вот список команд которые я могу выполнить:\n /ибаш - наибашу обработку и рендер!\n /харе - оанавливает нах!",
)
logger.debug(load_dotenv(dotenv_path="/mnt/aescript/.env",verbose=True))
NAS_USER = os.getenv("NAS_USER")
NASS_PASS = os.getenv("NASS_PASS")
NAS_IP = os.getenv("NAS_IP")
NAS_PORT = os.getenv("NAS_PORT")
NAS_FILE = os.getenv("NAS_FILE")
TOKEN = os.getenv("TOKEN")
GROUP_CHAT = os.getenv("GROUP_CHAT")
def load_osheet(message):
logger.debug("Get data")
synd = SynologyDrive(
NAS_USER, NAS_PASS, NAS_IP, NAS_PORT, https=True, dsm_version="7"
)
try:
logger.debug(synd.login()) # Проверка что ссеия установлена.
try:
logger.debug("Try to download sheet")
bio = synd.download_synology_office_file(NAS_FILE)
logger.debug("Download Success")
return bio
except:
logger.exception("Download fails")
bot.send_message(
message.chat.id,
f"<b>Не удалось скачать таблицу</b>",
parse_mode=["html"],
)
except:
logger.exception("Login error")
bot.send_message(
message.chat.id, f"<b>Не удалось авторизоватся</b>", parse_mode=["html"]
)
def get_start(osheet):
logger.debug("Read Start page")
try:
sheet = pd.read_excel(osheet, sheet_name="Start", header=1)
sheet = sheet[sheet["STATE"] == False] # Проверка "первая"
logger.debug("Parsing OK")
return sheet
except:
logger.exception("error while read excel sheet")
def get_packs(osheet):
logger.debug("Read SPORT page")
try:
sheet = pd.read_excel(osheet, sheet_name="SPORT", header=0, index_col="SPORT")
logger.debug("Parsing OK")
return sheet[sheet.index.notna()]
except:
logger.exception("error while read excel sheet")
raise
def get_logos(osheet):
logger.debug("Read TEAMS page")
try:
sheet = pd.read_excel(osheet, sheet_name="TEAMS", header=0, index_col=[0, 1])
logger.debug("Parsing OK")
return sheet
except:
logger.exception("error while read excel sheet")
def get_sport_logo(sport, pack, message):
logger.info(f"Get {sport} pack")
bot.send_message(
message.chat.id, f"Ищем оформления для {sport}", parse_mode=["html"]
)
try:
d = pack.loc[sport]["LINK"]
logger.debug(d)
if pd.isna(d):
logger.warning(f'There is no LINK for sport "{sport}"')
return ""
return d
except:
logger.exception("Couldn't get " + sport + " pack")
return ""
def get_team_logo(team, sport, logos, message):
logger.info(f"Get {team}/{sport} logo")
bot.send_message(
message.chat.id, f"Поиск логотипа {sport}-<b>{team}</b>", parse_mode=["html"]
)
logger.debug(team, sport)
logger.info(logos)
bot.send_message(message.chat.id, logos)
try:
d = logos.loc[team, sport]["LINK"][0] ##проверить!!!
logger.debug(d)
return d
except KeyError as inst:
logger.warning(f"There is no LINK for {team}/{sport}")
return ""
except Exception:
logger.exception(f"Error while get {sport} pack")
return ""
def make_data_dict(ds):
dd = {}
dd["date"] = ds["DATA"]
dd["time"] = ds["TIME"]
dd["channel"] = ds["CHANEL"]
dd["sport"] = ds["SPORT"]
dd["league"] = ds["LEAGUE"]
dd["team_a"] = ds["TEAM A"]
dd["team_b"] = ds["TEAM B"]
dd["index"] = ds.name
return dd
def make_job_dicts(dd, pack, logos, message):
# def make_name(ds,pack,logos):
logger.debug("Start make name")
fn = ""
data = {}
empty_sport = pack.iloc[0].name
# Дата и Время
if isinstance(dd["date"], str):
fn += f"{dd['date'][6:]}{dd['date'][3:5]}{dd['date'][0:2]}"
elif isinstance(dd["date"], datetime.date):
fn += f"{dd['date'].year}{dd['date'].month:02}{dd['date'].day:02}"
# Вид спорта и оформление
if dd["sport"] != empty_sport:
fn += f"_{dd['sport']}"
data["sport"] = dd["sport"]
data["pack"] = unc2uri(get_sport_logo(dd["sport"], pack, message))
else:
data["sport"] = ""
data["pack"] = ""
# Лига
if dd["league"][-1] == ".":
logger.debug("dot in league name!")
fn += f'_{dd["league"][:-1]}'
data["league"] = dd["league"][:-1]
else:
data["league"] = dd["league"]
fn += f'_{dd["league"]}'
# Команды А и Б
if pd.isna(dd["team_a"]):
logger.info("No Team A present")
bot.send_message(message.chat.id, f"Нет команды А", parse_mode=["html"])
data["team_a"] = ""
data["team_a_logo"] = ""
data["team_a_logo_res"] = ""
else:
name = dd["team_a"].split("#")
fn += f"_{name[0]}"
data["team_a_logo_res"] = name[2:]
data["team_a"] = name[0]
data["team_a_logo"] = unc2uri(
get_team_logo(dd["team_a"], dd["sport"], logos, message)
)
if pd.isna(dd["team_b"]):
logger.info("No Team B present")
bot.send_message(message.chat.id, f"Нет команды Б", parse_mode=["html"])
data["team_b"] = ""
data["team_b_logo"] = ""
data["team_b_logo_res"] = ""
else:
name = dd["team_b"].split("#")
fn += f"_{name[0]}"
data["team_b_logo_res"] = name[2:]
data["team_b"] = name[0]
data["team_b_logo"] = unc2uri(
get_team_logo(dd["team_b"], dd["sport"], logos, message)
)
# CHANEL -> START/TRIUMPH
if pd.isna(dd["channel"]):
logger.debug("No Channel is set")
pass
else:
logger.debug("Channel is set " + dd["channel"])
fn += f"_{dd['channel']}"
fn = translit(fn, reversed=True)
fn = fn.replace(" ", "-")
fn = fn.replace("'", "")
data["outfile_name"] = fn
if isinstance(dd["time"], str):
t = dd["time"].split(":")
# data['time']=':'.join(t[0:2])
data["time_h"] = t[0]
data["time_m"] = t[1]
elif isinstance(dd["time"], datetime.time):
data["time_h"] = str(dd["time"].hour)
data["time_m"] = str(dd["time"].minute)
logger.debug("time " + data["time_h"] + ":" + data["time_m"])
if isinstance(dd["date"], str):
d = dd["date"].split(".")
d = f"{int(d[0])} {['','января','февраля','марта','апреля','мая','июня','июля','августа','сентября','октября','ноября','декабря'][int(d[1])]}"
elif isinstance(dd["date"], datetime.date):
d = f"{dd['date'].day} {['','января','февраля','марта','апреля','мая','июня','июля','августа','сентября','октября','ноября','декабря'][dd['date'].month]}"
data["data"] = d
logger.debug(data)
logger.debug(data["outfile_name"])
logger.debug(fn)
logger.debug("End make name")
watch_list = []
watch_list.append(send_job(data, message))
if True:
data["data"] = "сегодня"
data["outfile_name"] = fn + "_Today"
watch_list.append(send_job(data, message))
data["data"] = "завтра"
data["outfile_name"] = fn + "_Tomorrow"
watch_list.append(send_job(data, message))
pprint(watch_list)
return list(filter(None, watch_list))
def send_job(data, message):
payload = {}
payload["template"] = {
"src": "file:///c:/users/virtVmix-2/Downloads/PackShot_Sborka_eng.aepx",
"composition": "pack",
"outputModule": "Start_h264",
"outputExt": "mp4",
}
payload["actions"] = {
"postrender": [
{
"module": "@nexrender/action-encode",
"preset": "mp4",
"output": "encoded.mp4",
},
{
"module": "@nexrender/action-copy",
"input": "encoded.mp4",
"output": f"//10.10.35.3/edit/Auto_Anons/{data['outfile_name']}.mp4",
},
]
}
payload["assets"] = []
# ДАТА из файла и "сегодня"/"завтра"
# Размер и положение текста "Сегодня"
if data["data"] == "сегодня":
fontSize = "105"
anchorPoint = [0, 5]
payload["assets"].append(
{
"layerName": "DATA",
"property": "Source Text.fontSize",
"type": "data",
"value": fontSize,
}
)
logger.info(f'For "{data['data']}" font set to {fontSize}')
bot.send_message(
message.chat.id,
f'Для "<i>{data['data']}</i>" размер шрифта установлен <b>{fontSize}</b>',
parse_mode=["html"],
)
payload["assets"].append(
{
"layerName": "DATA",
"property": "transform.anchorPoint",
"type": "data",
"value": anchorPoint,
}
)
logger.info(f'Shifting the "{data['data']}" by {anchorPoint} pixels')
bot.send_message(
message.chat.id,
f'<b>Сдвигаем</b> "<i>{data['data']}</i>" на <b>{anchorPoint}</b> пикселей',
parse_mode=["html"],
)
# Размер и положение текста "Завтра"
elif data["data"] == "завтра":
fontSize = "115"
anchorPoint = [0, 25]
payload["assets"].append(
{
"layerName": "DATA",
"property": "Source Text.fontSize",
"type": "data",
"value": fontSize,
}
)
logger.info(f'For "{data['data']}" font set to {fontSize}')
bot.send_message(
message.chat.id,
f'Для "<i>{data['data']}</i>" размер шрифта установлен <b>{fontSize}</b>',
parse_mode=["html"],
)
payload["assets"].append(
{
"layerName": "DATA",
"property": "transform.anchorPoint",
"type": "data",
"value": anchorPoint,
}
)
logger.info(f'Shifting the "{data['data']}" by {anchorPoint} pixels')
bot.send_message(
message.chat.id,
f'<b>Сдвигаем</b> "<i>{data['data']}</i>" на <b>{anchorPoint}</b> пикселей',
parse_mode=["html"],
)
# Размер и положение текста "Даты"
payload["assets"].append(
{
"type": "data",
"layerName": "DATA",
"property": "Source Text",
"value": data["data"],
}
)
if len(data["data"]) < 6:
fontSize = "120"
anchorPoint = [0, 20]
payload["assets"].append(
{
"layerName": "DATA",
"property": "Source Text.fontSize",
"type": "data",
"value": fontSize,
}
)
logger.info(f'For "{data['data']}" font set to {fontSize}')
bot.send_message(
message.chat.id,
f'Для "<i>{data['data']}</i>" размер шрифта установлен <b>{fontSize}</b>',
parse_mode=["html"],
)
payload["assets"].append(
{
"layerName": "DATA",
"property": "transform.anchorPoint",
"type": "data",
"value": anchorPoint,
}
)
logger.info(f'Shifting the "{data['data']}" by {anchorPoint} pixels')
bot.send_message(
message.chat.id,
f'<b>Сдвигаем</b> "<i>{data['data']}</i>" на <b>{anchorPoint}</b> пикселей',
parse_mode=["html"],
)
# Время
if len(data["time_h"]) < 2:
anchorPoint = [60, 0]
payload["assets"].append(
{
"layerName": "TIME_H",
"property": "transform.anchorPoint",
"type": "data",
"value": anchorPoint,
}
)
payload["assets"].append(
{
"layerName": "TIME_M",
"property": "transform.anchorPoint",
"type": "data",
"value": anchorPoint,
}
)
payload["assets"].append(
{
"layerName": "TIME",
"property": "transform.anchorPoint",
"type": "data",
"value": anchorPoint,
}
)
logger.info(
f'Shifting the "{data['time_h']}:{data['time_m']}" by {anchorPoint} pixels'
)
bot.send_message(
message.chat.id,
f'<b>Сдвигаем</b> "<i>{data['time_h']}:{data['time_m']}</i>" на <b>{anchorPoint}</b> пикседей',
parse_mode=["html"],
)
elif len(data["time_h"]) == 2 and int(data["time_h"]) < 20:
anchorPoint = [20, 0]
payload["assets"].append(
{
"layerName": "TIME_H",
"property": "transform.anchorPoint",
"type": "data",
"value": anchorPoint,
}
)
payload["assets"].append(
{
"layerName": "TIME_M",
"property": "transform.anchorPoint",
"type": "data",
"value": anchorPoint,
}
)
payload["assets"].append(
{
"layerName": "TIME",
"property": "transform.anchorPoint",
"type": "data",
"value": anchorPoint,
}
)
logger.info(
f'Shifting the "{data['time_h']}:{data['time_m']}" by {anchorPoint} pixels'
)
bot.send_message(
message.chat.id,
f'<b>Сдвигаем</b> "<i>{data['time_h']}:{data['time_m']}</i>" на <b>{anchorPoint}</b> пикседей',
parse_mode=["html"],
)
payload["assets"].append(
{
"type": "data",
"layerName": "TIME_H",
"property": "Source Text",
"value": data["time_h"],
}
)
payload["assets"].append(
{
"type": "data",
"layerName": "TIME_M",
"property": "Source Text",
"value": data["time_m"],
}
)
# Лига
payload["assets"].append(
{
"type": "data",
"layerName": "LEAGUE",
"property": "Source Text",
"value": data["league"],
}
)
# Размер текста "Лиги"
if len(data["league"]) > 16:
fontSize = "73"
payload["assets"].append(
{
"layerName": "LEAGUE",
"property": "Source Text.fontSize",
"type": "data",
"value": fontSize,
}
)
logger.info(f'For "{data['league']}" font set to {fontSize}')
bot.send_message(
message.chat.id,
f'Для "<i>{data['league']}</i>" размер шрифта установлен <b>{fontSize}</b>',
parse_mode=["html"],
)
# Спорт
if data["sport"]:
payload["assets"].append(
{
"type": "data",
"layerName": "SPORT",
"property": "Source Text",
"value": data["sport"],
}
)
# Команда А
if data["team_a"]:
payload["assets"].append(
{
"type": "data",
"layerName": "TEAM_A",
"property": "Source Text",
"value": data["team_a"],
}
)
# Команда Б
if data["team_b"]:
payload["assets"].append(
{
"type": "data",
"layerName": "TEAM_B",
"property": "Source Text",
"value": data["team_b"],
}
)
# Логотип А
if data["team_a_logo"]:
payload["assets"].append(
{"src": data["team_a_logo"], "type": "image", "layerName": "TEAM_A_LOGO"}
)
if data["team_a_logo_res"]:
payload["assets"].append(
{
"property": "scale",
"type": "data",
"expression": "if (width > height) {max_size = width;} else {max_size = height;} var real_size = "
+ data["team_a_logo_res"][0]
+ "/max_size*100;[real_size,real_size]",
"layerName": "TEAM_A_LOGO",
}
)
logger.info(
f"{data['team_a']} logo was resized to {data['team_a_logo_res'][0]}"
)
bot.send_message(
message.chat.id,
f"<b>{data['team_a']}</b> маштабирован под <b>{data['team_a_logo_res'][0]}</b> пикселей",
parse_mode=["html"],
)
# Логотип Б
if data["team_b_logo"]:
payload["assets"].append(
{"src": data["team_b_logo"], "type": "image", "layerName": "TEAM_B_LOGO"}
)
if data["team_b_logo_res"]:
payload["assets"].append(
{
"property": "scale",
"type": "data",
"expression": "if (width > height) {max_size = width;} else {max_size = height;} var real_size = "
+ data["team_b_logo_res"][0]
+ "/max_size*100;[real_size,real_size]",
"layerName": "TEAM_B_LOGO",
}
)
logger.info(
f"{data['team_b']} logo was resized to {data['team_b_logo_res'][0]}"
)
bot.send_message(
message.chat.id,
f"<b>{data['team_b']}</b> маштабирован под <b>{data['team_b_logo_res'][0]}</b> пикселей",
parse_mode=["html"],
)
# Верхнее оформлени
if data["pack"]:
payload["assets"].append(
{"src": data["pack"], "type": "video", "layerName": "TOP"}
)
url = "http://10.10.2.20:3000/api/v1/jobs"
r = requests.post(url, json=payload)
if r.status_code == 200:
res = r.json()
# pprint(res)
uid = res["uid"]
return {"uid": uid, "outname": data["outfile_name"]}
def unc2uri(unc):
logger.debug("Start")
from urllib.parse import urlparse
from pathlib import PureWindowsPath
try:
print(unc)
p = urlparse(unc)
if len(p.scheme) > 2 or not unc:
return unc
else:
p = PureWindowsPath(unc)
return p.as_uri()
except:
logger.exception("erro wile prasing url")
# XXX
if PLACEHOLDER:
send_job = send_job_dumb
logger.info("Start!") # Начинаем
@bot.message_handler(commands=["чёкак", "status"])
def status(message):
logger.info(f"Staus requested by {message.from_user.username}")
r = requests.get("http://10.10.2.20:3000/api/v1/jobs")
if r.status_code == 200:
jobs = r.json()
s = [{"uid": i["uid"], "state": i["state"]} for i in jobs]
queued = 0
if s:
for job in s:
if job["state"] in ("queued"):
queued += 1
t = requests.get(f"http://10.10.2.20:3000/api/v1/jobs/{job['uid']}")
# bot.send_message(message.chat.id,f'{job['uid']} - {t.json()['state']}')
pprint(t)
logger.info(f"{queued} queud")
bot.send_message(message.chat.id, f"В очереди {queued}")
else:
logger.info(f"no queued jobs")
bot.send_message(message.chat.id, "Нет задач в очереди")
@bot.message_handler(commands=["харе", "stop"])
def stop(message):
r = requests.get("http://10.10.2.20:3000/api/v1/jobs")
if r.status_code == 200:
jobs = r.json()
s = [{"uid": i["uid"], "state": i["state"]} for i in jobs]
queued = 0
if s:
for job in s:
if job["state"] in ("queued", "picked"):
requests.delete(f"http://10.10.2.20:3000/api/v1/jobs/{job['uid']}")
queued += 1
else:
requests.delete(f"http://10.10.2.20:3000/api/v1/jobs/{job['uid']}")
logger.info(f"Cancelled {queued} jobs by {message.from_user.username}")
bot.send_message(message.chat.id, f"Отменяно {queued}")
else:
logger.info(
f"{message.from_user.username} requested job cancel but No jobs to cancel"
)
bot.send_message(message.chat.id, "Нет задач для отмены")
@bot.message_handler(commands=["ибаш", "ibash"])
def ibash(message):
logger.info(f"Starting jobs for {message.from_user.username}")
bot.send_chat_action(message.chat.id, "typing")
if message.from_user.username:
user = message.from_user.username
else:
user = "!"
bot.send_message(
message.chat.id,
f"Ну что ж {user}, давай попробуем \n<b>НАИБАШИТЬ!!!</b>",
parse_mode=["html"],
)
bot.send_chat_action(message.chat.id, "upload_document")
osheet = load_osheet(message)
start = get_start(osheet)
pack = get_packs(osheet)
logos = get_logos(osheet)
# Удаляем прошлые задания которые закончились или с оштбкой
r = requests.get("http://10.10.2.20:3000/api/v1/jobs")
if r.status_code == 200:
jobs = r.json()
s = [{"uid": i["uid"], "state": i["state"]} for i in jobs]
for job in s:
if job["state"] in ("finished", "error"):
requests.delete(f"http://10.10.2.20:3000/api/v1/jobs/{job['uid']}")
bot.send_chat_action(message.chat.id, "record_video")
watch_list = []
for i, row in start.iterrows():
dd = make_data_dict(row)
watch_list += make_job_dicts(dd, pack, logos, message)
logger.info(f"Queued {len(watch_list)} jobs")
bot.send_message(message.chat.id, f"В очереди {len(watch_list)} задач")
while watch_list:
bot.send_chat_action(message.chat.id, "record_video")
sleep(25)
for job in watch_list:
# XXX
if PLACEHOLDER:
r = fake_get()
else:
r = requests.get(f"http://10.10.2.20:3000/api/v1/jobs/{job['uid']}")
logger.debug(r.text)
if r.status_code == 200 and r.json()["state"] == "finished":
watch_list.remove(job)
logger.info(
f"{job['outname']}, {r.json()['state']}, {len(watch_list)} to go"
)
bot.send_message(
message.chat.id,
f"<b>{job['outname']}</b>, <i>готов</i>, {len(watch_list)} осталось выполнить",
parse_mode=["html"],
)
logger.debug(f"{job['uid']} - {r.json()['state']}")
elif r.status_code == 200 and r.json()["state"] == "error":
watch_list.remove(job)
logger.warning(f"{job}, {r.json()['state']}, {len(watch_list)} to go")
bot.send_message(
message.chat.id,
f"!!!{job}, {r.json()['state']}, {len(watch_list)} осталось выполнить",
parse_mode=["html"],
)
# print('.',end="")
bot.send_message("Пойду спать :)")
bot.infinity_polling()
logger.info("End!") # Заканчиваем