2 Commits

Author SHA1 Message Date
bd925418fd YouTube new videos on channels monitoring 2023-01-12 13:57:41 +01:00
42a4a2e58e Internal and external spoilers are now separated 2023-01-12 11:04:52 +01:00
10 changed files with 137 additions and 40 deletions

View File

@@ -51,7 +51,8 @@
"enabled": false
},
"spoilers": {
"enabled": true
"enabled": true,
"allow_external": true
}
},
"scheduler": {
@@ -74,6 +75,11 @@
"cache_admins": {
"interval": 120,
"enabled": true
},
"channels_monitor": {
"interval": 5,
"enabled": true,
"channels": []
}
},
"locations": {

View File

@@ -31,7 +31,7 @@ from modules.commands.warnings import *
from modules.callbacks.nothing import *
from modules.callbacks.reapply import *
from modules.callbacks.rules import *
from modules.callbacks.sid import *
from modules.callbacks.spoiler import *
from modules.callbacks.sponsorship import *
from modules.callbacks.sub import *
from modules.callbacks.sus import *

View File

@@ -109,7 +109,9 @@
"spoiler_unfinished": "У вас ще є незавершений спойлер. Надішліть /cancel щоб зупинити його створення",
"spoiler_cancel": "Створення спойлера було припинено",
"spoiler_empty": "Спойлер категорії \"{0}\" без опису",
"spoiler_empty_named": "Спойлер категорії \"{0}\" без опису від **{1}**",
"spoiler_described": "Спойлер категорії \"{0}\": {1}",
"spoiler_described_named": "Спойлер категорії \"{0}\" від **{1}**: {2}",
"spoiler_description_enter": "Добре, введіть бажаний опис спойлера",
"spoiler_description_too_long": "Текст занадто довгий. Будь ласка, умісти опис у 1024 символи.",
"spoiler_using_description": "Встановлено опис спойлера: {0}\n\nЗалишилось додати вміст самого спойлера. Бот приймає текстове повідомлення, фото, відео, файл а також гіф зображення (1 шт.)",
@@ -118,6 +120,7 @@
"spoiler_incorrect_content": "Бот не підтримує такий контент. Будь ласка, надішли текст, фото, відео, файл або анімацію (гіф).",
"spoiler_incorrect_category": "Вказана категорія не є дійсною. Будь ласка, користуйся клавіатурою бота (кнопка біля 📎) для вибору категорії.",
"spoiler_in_progress": "❌ **Дія неможлива**\nПерш ніж починати нову дію, треба завершити створення спойлера або перервати його командою /cancel.",
"youtube_video": "На каналі [{0}]({1}) нове відео!\n\n**[{2}]({3})**",
"yes": "Так",
"no": "Ні",
"voice_message": [
@@ -226,8 +229,10 @@
"done": "✅ Готово",
"sponsor_apply": "Заповнити форму",
"sponsor_started": "Форму розпочато",
"spoiler_send": "Надіслати",
"spoiler_view": ереглянути"
"spoiler_view": "Переглянути",
"spoiler_preview": опередній перегляд",
"spoiler_send_chat": "Надіслати в холо-чат",
"spoiler_send_other": "Надіслати в інший чат"
},
"callback": {
"sub_accepted": "✅ Анкету {0} схвалено",
@@ -243,7 +248,8 @@
"reapply_stopped": " Перервано заповнення анкети",
"sponsor_started": " Заповнення форми розпочато",
"sponsor_accepted": "✅ Форму {0} схвалено",
"sponsor_rejected": "❌ Форму {0} відхилено"
"sponsor_rejected": "❌ Форму {0} відхилено",
"spoiler_sent": "✅ Повідомлення надіслано в холо-чат"
},
"inline": {
"forbidden": {

View File

@@ -1,10 +0,0 @@
from app import app
from pyrogram.types import CallbackQuery
from pyrogram.client import Client
from pyrogram import filters
# Callback rule ================================================================================================================
@app.on_callback_query(filters.regex("sid_[\s\S]*"))
async def callback_query_rule(app: Client, clb: CallbackQuery):
await clb.answer(url=f'https://t.me/{(await app.get_me()).username}?start={clb.data.split("_")[1]}')
# ==============================================================================================================================

View File

@@ -0,0 +1,31 @@
from app import app
from pyrogram.types import CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton
from pyrogram.client import Client
from pyrogram import filters
from modules.database import col_spoilers
from bson.objectid import ObjectId
from modules.utils import configGet, locale
# Callback sid =================================================================================================================
@app.on_callback_query(filters.regex("sid_[\s\S]*"))
async def callback_query_sid(app: Client, clb: CallbackQuery):
await clb.answer(url=f'https://t.me/{(await app.get_me()).username}?start={clb.data.split("_")[1]}')
# ==============================================================================================================================
# Callback shc =================================================================================================================
@app.on_callback_query(filters.regex("shc_[\s\S]*"))
async def callback_query_shc(app: Client, clb: CallbackQuery):
spoil = col_spoilers.find_one( {"_id": ObjectId(clb.data.split("_")[1])} )
if spoil["description"] == "":
desc = locale("spoiler_empty_named", "message", locale=clb.from_user).format(locale(spoil["category"], "message", "spoiler_categories"), clb.from_user.first_name)
else:
desc = locale("spoiler_described_named", "message", locale=clb.from_user).format(locale(spoil["category"], "message", "spoiler_categories"), clb.from_user.first_name, spoil["description"])
await app.send_message(configGet("users", "groups"), desc, reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(locale("spoiler_view", "button", locale=clb.from_user), callback_data=f'sid_{clb.data.split("_")[1]}')]]))
await app.send_message(configGet("admin", "groups"), desc, reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(locale("spoiler_view", "button", locale=clb.from_user), callback_data=f'sid_{clb.data.split("_")[1]}')]]))
await clb.answer(locale("spoiler_sent", "callback", locale=clb.from_user), show_alert=True)
# ==============================================================================================================================

View File

@@ -28,13 +28,14 @@ db = db_client.get_database(name=db_config["name"])
collections = db.list_collection_names()
for collection in ["tmp", "users", "context", "spoilers", "messages", "warnings", "applications", "sponsorships"]:
for collection in ["tmp", "users", "context", "youtube", "spoilers", "messages", "warnings", "applications", "sponsorships"]:
if not collection in collections:
db.create_collection(collection)
col_tmp = db.get_collection("tmp")
col_users = db.get_collection("users")
col_context = db.get_collection("context")
col_youtube = db.get_collection("youtube")
col_spoilers = db.get_collection("spoilers")
col_messages = db.get_collection("messages")
col_warnings = db.get_collection("warnings")

View File

@@ -146,7 +146,37 @@ async def any_stage(app: Client, msg: Message):
ready = True
if ready is True:
await msg.reply_text(locale("spoiler_ready", "message", locale=msg.from_user), reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(locale("spoiler_send", "button", locale=msg.from_user), switch_inline_query=f"spoiler:{spoiler['_id'].__str__()}")]]))
if configGet("allow_external", "features", "spoilers") is True:
await msg.reply_text(
locale("spoiler_ready", "message", locale=msg.from_user),
reply_markup=InlineKeyboardMarkup(
[
[
InlineKeyboardButton(locale("spoiler_preview", "button", locale=msg.from_user), callback_data=f"sid_{spoiler['_id'].__str__()}")
],
[
InlineKeyboardButton(locale("spoiler_send_chat", "button", locale=msg.from_user), callback_data=f"shc_{spoiler['_id'].__str__()}")
],
[
InlineKeyboardButton(locale("spoiler_send_other", "button", locale=msg.from_user), switch_inline_query=f"spoiler:{spoiler['_id'].__str__()}")
]
]
)
)
else:
await msg.reply_text(
locale("spoiler_ready", "message", locale=msg.from_user),
reply_markup=InlineKeyboardMarkup(
[
[
InlineKeyboardButton(locale("spoiler_preview", "button", locale=msg.from_user), callback_data=f"sid_{spoiler['_id'].__str__()}")
],
[
InlineKeyboardButton(locale("spoiler_send_chat", "button", locale=msg.from_user), callback_data=f"shc_{spoiler['_id'].__str__()}")
]
]
)
)
else:
await msg.reply_text(locale("spoiler_incorrect_content", "message", locale=msg.from_user))

View File

@@ -22,34 +22,36 @@ async def inline_answer(client: Client, inline_query: InlineQuery):
results = []
if inline_query.query.startswith("spoiler:"):
if configGet("allow_external", "features", "spoilers") is True:
try:
if inline_query.query.startswith("spoiler:"):
try:
spoil = col_spoilers.find_one( {"_id": ObjectId(inline_query.query.removeprefix("spoiler:"))} )
spoil = col_spoilers.find_one( {"_id": ObjectId(inline_query.query.removeprefix("spoiler:"))} )
if spoil is not None:
if spoil is not None:
desc = locale("spoiler_empty", "message", locale=inline_query.from_user).format(locale(spoil["category"], "message", "spoiler_categories")) if spoil["description"] == "" else locale("spoiler_described", "message", locale=inline_query.from_user).format(locale(spoil["category"], "message", "spoiler_categories"), spoil["description"])
desc = locale("spoiler_empty", "message", locale=inline_query.from_user).format(locale(spoil["category"], "message", "spoiler_categories")) if spoil["description"] == "" else locale("spoiler_described", "message", locale=inline_query.from_user).format(locale(spoil["category"], "message", "spoiler_categories"), spoil["description"])
results = [
InlineQueryResultArticle(
title=locale("title", "inline", "spoiler", locale=inline_query.from_user),
description=locale("description", "inline", "spoiler", locale=inline_query.from_user),
input_message_content=InputTextMessageContent(desc, disable_web_page_preview=True),
reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(locale("spoiler_view", "button", locale=inline_query.from_user), callback_data=f'sid_{inline_query.query.removeprefix("spoiler:")}')]])
)
]
results = [
InlineQueryResultArticle(
title=locale("title", "inline", "spoiler", locale=inline_query.from_user),
description=locale("description", "inline", "spoiler", locale=inline_query.from_user),
input_message_content=InputTextMessageContent(desc, disable_web_page_preview=True),
reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(locale("spoiler_view", "button", locale=inline_query.from_user), callback_data=f'sid_{inline_query.query.removeprefix("spoiler:")}')]])
)
]
except InvalidId:
results = []
except InvalidId:
results = []
await inline_query.answer(
results=results
)
await inline_query.answer(
results=results
)
return
return
if inline_query.chat_type in [ChatType.CHANNEL]:
await inline_query.answer(

View File

@@ -1,7 +1,9 @@
"""Automatically register commands and execute
some scheduled tasks is the main idea of this module"""
from asyncio import sleep
from os import listdir, makedirs, path, sep
from traceback import format_exc
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from datetime import datetime, timedelta
from ujson import dumps
@@ -12,7 +14,9 @@ from pyrogram.enums.chat_members_filter import ChatMembersFilter
from classes.holo_user import HoloUser
from modules.utils import configGet, jsonSave, locale, logWrite
from dateutil.relativedelta import relativedelta
from modules.database import col_applications, col_sponsorships
from modules.database import col_applications, col_sponsorships, col_youtube
from xmltodict import parse
from requests import get
scheduler = AsyncIOScheduler()
@@ -233,4 +237,30 @@ async def commands_register():
if configGet("debug") is True:
print(commands, flush=True)
logWrite(f"Complete commands registration:\n{dumps(commands_raw, indent=4, ensure_ascii=False, encode_html_chars=False)}", debug=True)
logWrite(f"Complete commands registration:\n{dumps(commands_raw, indent=4, ensure_ascii=False, encode_html_chars=False)}", debug=True)
if configGet("enabled", "scheduler", "channels_monitor"):
@scheduler.scheduled_job(trigger="interval", minutes=configGet("interval", "scheduler", "channels_monitor"))
async def channels_monitor():
for channel in configGet("channels", "scheduler", "channels_monitor"):
if configGet("debug") is True:
logWrite(f'Processing videos of {channel["name"]} ({channel["id"]})', debug=True)
try:
req = get(f'https://www.youtube.com/feeds/videos.xml?channel_id={channel["id"]}')
parsed = parse(req.content)
if "feed" not in parsed:
continue
if "entry" not in parsed["feed"]:
continue
for entry in parsed["feed"]["entry"]:
if "yt:videoId" not in entry:
continue
if col_youtube.find_one( {"channel": channel["id"], "video": entry["yt:videoId"]} ) is None:
col_youtube.insert_one( {"channel": channel["id"], "video": entry["yt:videoId"], "date": datetime.fromisoformat(entry["published"])} )
await app.send_message(configGet("users", "groups"), locale("youtube_video", "message").format(channel["name"], channel["link"], entry["title"], entry["link"]["@href"]), disable_web_page_preview=False)
await sleep(2)
except Exception as exp:
logWrite(f'Could not get last videos of {channel["name"]} ({channel["id"]}) due to {exp}: {format_exc()}')
if configGet("debug") is True:
logWrite("Admin group caching performed", debug=True)

View File

@@ -8,4 +8,5 @@ tgcrypto==1.2.5
python_dateutil==2.8.2
starlette~=0.22.0
ujson~=5.7.0
ftfy~=6.1.1
ftfy~=6.1.1
xmltodict~=0.13.0