Added and updated repositories 2025-07-11 08:27:20

This commit is contained in:
github-actions[bot]
2025-07-11 08:27:20 +00:00
parent 35e8befc45
commit e328cd957a
320 changed files with 37419 additions and 33510 deletions

View File

@@ -1,198 +1,198 @@
__version__ = (2, 0, 0)
#
# @@@@@@ @@@@@@ @@@@@@@ @@@@@@@ @@@@@@ @@@@@@@@@@ @@@@@@ @@@@@@@ @@@ @@@ @@@ @@@@@@@@ @@@@@@
# @@@@@@@@ @@@@@@@ @@@@@@@ @@@@@@@@ @@@@@@@@ @@@@@@@@@@@ @@@@@@@@ @@@@@@@@ @@@ @@@ @@@ @@@@@@@@ @@@@@@@
# @@! @@@ !@@ @@! @@! @@@ @@! @@@ @@! @@! @@! @@! @@@ @@! @@@ @@! @@@ @@! @@! !@@
# !@! @!@ !@! !@! !@! @!@ !@! @!@ !@! !@! !@! !@! @!@ !@! @!@ !@! @!@ !@! !@! !@!
# @!@!@!@! !!@@!! @!! @!@!!@! @!@ !@! @!! !!@ @!@ @!@ !@! @!@ !@! @!@ !@! @!! @!!!:! !!@@!!
# !!!@!!!! !!@!!! !!! !!@!@! !@! !!! !@! ! !@! !@! !!! !@! !!! !@! !!! !!! !!!!!: !!@!!!
# !!: !!! !:! !!: !!: :!! !!: !!! !!: !!: !!: !!! !!: !!! !!: !!! !!: !!: !:!
# :!: !:! !:! :!: :!: !:! :!: !:! :!: :!: :!: !:! :!: !:! :!: !:! :!: :!: !:!
# :: ::: :::: :: :: :: ::: ::::: :: ::: :: ::::: :: :::: :: ::::: :: :: :::: :: :::: :::: ::
# : : : :: : : : : : : : : : : : : : : :: : : : : : : :: : : : :: :: :: : :
#
# © Copyright 2024
#
# https://t.me/Den4ikSuperOstryyPer4ik
# and
# https://t.me/ToXicUse
#
# 🔒 Licensed under the GNU AGPLv3
# https://www.gnu.org/licenses/agpl-3.0.html
#
# meta developer: @AstroModules
# meta banner: https://raw.githubusercontent.com/Den4ikSuperOstryyPer4ik/Astro-modules/main/Banners/PasswordGenerator.jpg
import logging
import random
from telethon.tl.types import Message
from .. import loader, utils
from ..inline.types import InlineCall
logger = logging.getLogger(__name__)
@loader.tds
class PasswordGeneratorMod(loader.Module):
'''Random password/pincode generator'''
strings = {
"name": "RandomPasswordGenerator",
"_cfg_doc_pass_length": "set password length (in number of characters)",
"_cfg_doc_pin_code_length": "set pincode length (in number of characters)",
"_cfg_doc_simbols_in_pass": (
"Will there be additional characters in the generated password"
" (+-*!&$#?=@<>)?"
),
"what_to_generate": "🆗What should be generated?",
"new_random_pass": "🔣 new random password 🆕",
"new_random_pincode": "🔢 new random PIN-code 🆕",
"pass": "<b>🆕 Your new password in {} characters:\n<code>{}</code></b>",
"pincode": "<b>🆕 Your new pincode in {} characters:\n<code>{}</code></b>",
"menu": "💻 Menu",
"close": "🚫 Close",
}
strings_ru = {
"_cls_doc": (
"Генератор рандомного пароля/пин-кода\nНастроить генератор можно через"
" конфиг"
),
"_cfg_doc_pass_length": "выставьте длину пароля(в кол-ве символов)",
"_cfg_doc_pin_code_length": "выставьте длину Пин-Кода(в кол-ве символов)",
"_cfg_doc_simbols_in_pass": (
"Какие символы должны быть в сгенерированном пароле?"
),
"what_to_generate": "🆗 Что надо сгенерировать?",
"new_random_pass": "🔣 Новый рандомный пароль 🆕",
"new_random_pincode": "🔢 Новый рандомный PIN-код 🆕",
"pass": "<b>🆕 Ваш новый пароль в {} символов:\n<code>{}</code></b>",
"pincode": "<b>🆕 Ваш новый пин-код в {} символов:</b>\n<code>{}</code>",
"menu": "💻 Меню",
"close": "🚫 Закрыть",
}
@loader.command(ru_doc="—>конфиг этого модуля")
async def generatorcfgcmd(self, message: Message):
"""—>config for this module"""
name = self.strings("name")
await self.allmodules.commands["config"](
await utils.answer(message, f"{self.get_prefix()}config {name}")
)
def __init__(self):
self._ratelimit = []
self.config = loader.ModuleConfig(
loader.ConfigValue(
"password_length",
10,
doc=lambda: self.strings("_cfg_doc_pass_length"),
validator=loader.validators.Integer(minimum=6),
),
loader.ConfigValue(
"pincode_length",
4,
doc=lambda: self.strings("_cfg_doc_pin_code_length"),
validator=loader.validators.Integer(minimum=4),
),
loader.ConfigValue(
"symbols",
"+-*!&$?=@<>abcdefghijklnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890",
doc=lambda: self.strings("_cfg_doc_simbols_in_pass"),
),
)
@loader.command(ru_doc="—>сгенерировать случайный пароль/пин-код")
async def igeneratorcmd(self, message: Message):
"""—>generate random password/pin"""
await self.inline.form(
self.strings("what_to_generate"),
reply_markup=[
[
{
"text": self.strings("new_random_pass"),
"callback": self.new_random_pass,
}
],
[
{
"text": self.strings("new_random_pincode"),
"callback": self.new_random_pincode,
}
],
[{"text": self.strings("close"), "action": "close"}],
],
message=message,
)
async def igenerator(self, call: InlineCall):
await call.edit(
self.strings("what_to_generate"),
reply_markup=[
[
{
"text": self.strings("new_random_pass"),
"callback": self.new_random_pass,
}
],
[
{
"text": self.strings("new_random_pincode"),
"callback": self.new_random_pincode,
}
],
[{"text": self.strings("close"), "action": "close"}],
],
)
async def new_random_pass(self, call: InlineCall):
symbols = self.config["symbols"]
password_length = self.config["password_length"]
length = int(password_length)
password = ""
for _ in range(length):
password += random.choice(symbols)
await call.edit(
self.strings["pass"].format(password_length, password),
reply_markup=[
[
{
"text": self.strings("menu"),
"callback": self.igenerator
}
],
[
{
"text": self.strings("close"),
"action": "close"
}
],
],
)
async def new_random_pincode(self, call: InlineCall):
pincode_length = self.config["pincode_length"]
chars = "1234567890"
length = int(self.config["pincode_length"])
pincode = ""
for _ in range(length):
pincode += random.choice(chars)
await call.edit(
self.strings["pincode"].format(pincode_length, pincode),
reply_markup=[
[
{
"text": self.strings("menu"),
"callback": self.igenerator
}
],
[
{
"text": self.strings("close"),
"action": "close"
}
],
],
)
__version__ = (2, 0, 0)
#
# @@@@@@ @@@@@@ @@@@@@@ @@@@@@@ @@@@@@ @@@@@@@@@@ @@@@@@ @@@@@@@ @@@ @@@ @@@ @@@@@@@@ @@@@@@
# @@@@@@@@ @@@@@@@ @@@@@@@ @@@@@@@@ @@@@@@@@ @@@@@@@@@@@ @@@@@@@@ @@@@@@@@ @@@ @@@ @@@ @@@@@@@@ @@@@@@@
# @@! @@@ !@@ @@! @@! @@@ @@! @@@ @@! @@! @@! @@! @@@ @@! @@@ @@! @@@ @@! @@! !@@
# !@! @!@ !@! !@! !@! @!@ !@! @!@ !@! !@! !@! !@! @!@ !@! @!@ !@! @!@ !@! !@! !@!
# @!@!@!@! !!@@!! @!! @!@!!@! @!@ !@! @!! !!@ @!@ @!@ !@! @!@ !@! @!@ !@! @!! @!!!:! !!@@!!
# !!!@!!!! !!@!!! !!! !!@!@! !@! !!! !@! ! !@! !@! !!! !@! !!! !@! !!! !!! !!!!!: !!@!!!
# !!: !!! !:! !!: !!: :!! !!: !!! !!: !!: !!: !!! !!: !!! !!: !!! !!: !!: !:!
# :!: !:! !:! :!: :!: !:! :!: !:! :!: :!: :!: !:! :!: !:! :!: !:! :!: :!: !:!
# :: ::: :::: :: :: :: ::: ::::: :: ::: :: ::::: :: :::: :: ::::: :: :: :::: :: :::: :::: ::
# : : : :: : : : : : : : : : : : : : : :: : : : : : : :: : : : :: :: :: : :
#
# © Copyright 2024
#
# https://t.me/Den4ikSuperOstryyPer4ik
# and
# https://t.me/ToXicUse
#
# 🔒 Licensed under the GNU AGPLv3
# https://www.gnu.org/licenses/agpl-3.0.html
#
# meta developer: @AstroModules
# meta banner: https://raw.githubusercontent.com/Den4ikSuperOstryyPer4ik/Astro-modules/main/Banners/PasswordGenerator.jpg
import logging
import random
from telethon.tl.types import Message
from .. import loader, utils
from ..inline.types import InlineCall
logger = logging.getLogger(__name__)
@loader.tds
class PasswordGeneratorMod(loader.Module):
'''Random password/pincode generator'''
strings = {
"name": "RandomPasswordGenerator",
"_cfg_doc_pass_length": "set password length (in number of characters)",
"_cfg_doc_pin_code_length": "set pincode length (in number of characters)",
"_cfg_doc_simbols_in_pass": (
"Will there be additional characters in the generated password"
" (+-*!&$#?=@<>)?"
),
"what_to_generate": "🆗What should be generated?",
"new_random_pass": "🔣 new random password 🆕",
"new_random_pincode": "🔢 new random PIN-code 🆕",
"pass": "<b>🆕 Your new password in {} characters:\n<code>{}</code></b>",
"pincode": "<b>🆕 Your new pincode in {} characters:\n<code>{}</code></b>",
"menu": "💻 Menu",
"close": "🚫 Close",
}
strings_ru = {
"_cls_doc": (
"Генератор рандомного пароля/пин-кода\nНастроить генератор можно через"
" конфиг"
),
"_cfg_doc_pass_length": "выставьте длину пароля(в кол-ве символов)",
"_cfg_doc_pin_code_length": "выставьте длину Пин-Кода(в кол-ве символов)",
"_cfg_doc_simbols_in_pass": (
"Какие символы должны быть в сгенерированном пароле?"
),
"what_to_generate": "🆗 Что надо сгенерировать?",
"new_random_pass": "🔣 Новый рандомный пароль 🆕",
"new_random_pincode": "🔢 Новый рандомный PIN-код 🆕",
"pass": "<b>🆕 Ваш новый пароль в {} символов:\n<code>{}</code></b>",
"pincode": "<b>🆕 Ваш новый пин-код в {} символов:</b>\n<code>{}</code>",
"menu": "💻 Меню",
"close": "🚫 Закрыть",
}
@loader.command(ru_doc="—>конфиг этого модуля")
async def generatorcfgcmd(self, message: Message):
"""—>config for this module"""
name = self.strings("name")
await self.allmodules.commands["config"](
await utils.answer(message, f"{self.get_prefix()}config {name}")
)
def __init__(self):
self._ratelimit = []
self.config = loader.ModuleConfig(
loader.ConfigValue(
"password_length",
10,
doc=lambda: self.strings("_cfg_doc_pass_length"),
validator=loader.validators.Integer(minimum=6),
),
loader.ConfigValue(
"pincode_length",
4,
doc=lambda: self.strings("_cfg_doc_pin_code_length"),
validator=loader.validators.Integer(minimum=4),
),
loader.ConfigValue(
"symbols",
"+-*!&$?=@<>abcdefghijklnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890",
doc=lambda: self.strings("_cfg_doc_simbols_in_pass"),
),
)
@loader.command(ru_doc="—>сгенерировать случайный пароль/пин-код")
async def igeneratorcmd(self, message: Message):
"""—>generate random password/pin"""
await self.inline.form(
self.strings("what_to_generate"),
reply_markup=[
[
{
"text": self.strings("new_random_pass"),
"callback": self.new_random_pass,
}
],
[
{
"text": self.strings("new_random_pincode"),
"callback": self.new_random_pincode,
}
],
[{"text": self.strings("close"), "action": "close"}],
],
message=message,
)
async def igenerator(self, call: InlineCall):
await call.edit(
self.strings("what_to_generate"),
reply_markup=[
[
{
"text": self.strings("new_random_pass"),
"callback": self.new_random_pass,
}
],
[
{
"text": self.strings("new_random_pincode"),
"callback": self.new_random_pincode,
}
],
[{"text": self.strings("close"), "action": "close"}],
],
)
async def new_random_pass(self, call: InlineCall):
symbols = self.config["symbols"]
password_length = self.config["password_length"]
length = int(password_length)
password = ""
for _ in range(length):
password += random.choice(symbols)
await call.edit(
self.strings["pass"].format(password_length, password),
reply_markup=[
[
{
"text": self.strings("menu"),
"callback": self.igenerator
}
],
[
{
"text": self.strings("close"),
"action": "close"
}
],
],
)
async def new_random_pincode(self, call: InlineCall):
pincode_length = self.config["pincode_length"]
chars = "1234567890"
length = int(self.config["pincode_length"])
pincode = ""
for _ in range(length):
pincode += random.choice(chars)
await call.edit(
self.strings["pincode"].format(pincode_length, pincode),
reply_markup=[
[
{
"text": self.strings("menu"),
"callback": self.igenerator
}
],
[
{
"text": self.strings("close"),
"action": "close"
}
],
],
)

View File

@@ -1,400 +1,400 @@
__version__ = (1, 0, 0)
#
# @@@@@@ @@@@@@ @@@@@@@ @@@@@@@ @@@@@@ @@@@@@@@@@ @@@@@@ @@@@@@@ @@@ @@@ @@@ @@@@@@@@ @@@@@@
# @@@@@@@@ @@@@@@@ @@@@@@@ @@@@@@@@ @@@@@@@@ @@@@@@@@@@@ @@@@@@@@ @@@@@@@@ @@@ @@@ @@@ @@@@@@@@ @@@@@@@
# @@! @@@ !@@ @@! @@! @@@ @@! @@@ @@! @@! @@! @@! @@@ @@! @@@ @@! @@@ @@! @@! !@@
# !@! @!@ !@! !@! !@! @!@ !@! @!@ !@! !@! !@! !@! @!@ !@! @!@ !@! @!@ !@! !@! !@!
# @!@!@!@! !!@@!! @!! @!@!!@! @!@ !@! @!! !!@ @!@ @!@ !@! @!@ !@! @!@ !@! @!! @!!!:! !!@@!!
# !!!@!!!! !!@!!! !!! !!@!@! !@! !!! !@! ! !@! !@! !!! !@! !!! !@! !!! !!! !!!!!: !!@!!!
# !!: !!! !:! !!: !!: :!! !!: !!! !!: !!: !!: !!! !!: !!! !!: !!! !!: !!: !:!
# :!: !:! !:! :!: :!: !:! :!: !:! :!: :!: :!: !:! :!: !:! :!: !:! :!: :!: !:!
# :: ::: :::: :: :: :: ::: ::::: :: ::: :: ::::: :: :::: :: ::::: :: :: :::: :: :::: :::: ::
# : : : :: : : : : : : : : : : : : : : :: : : : : : : :: : : : :: :: :: : :
#
# © Copyright 2024
#
# https://t.me/Den4ikSuperOstryyPer4ik
# and
# https://t.me/ToXicUse
#
# 🔒 Licensed under the GNU AGPLv3
# https://www.gnu.org/licenses/agpl-3.0.html
#
# meta banner:
# meta developer: @AstroModules
# required: steampy
# meta banner: https://raw.githubusercontent.com/Den4ikSuperOstryyPer4ik/Astro-modules/main/Banners/AstroSteamNow.png
# Part of the module taken from WakaTime by @hikariatama: 38, 158, 208, 324 lines
import time
import logging
import datetime
import requests
import asyncio
from steampy.client import SteamClient
from .. import loader, utils
from ..inline.types import InlineCall
from telethon.errors.rpcerrorlist import MessageNotModifiedError
logger = logging.getLogger(__name__)
@loader.tds
class Steam(loader.Module):
'''Get now played game'''
strings = {
'name': 'SteamNow',
'_api_key': "Enter your SteamAPI Key. You can get it by following this tutorial:\n\nhttps://t.me/help_code/20", # Tutorial link
'_account_id': "Enter your Steam Account ID. More details in the tutorial: \n\nhttps://t.me/help_code/21", # Tutorial link
'no_api_key_or_id': (
'<b>❌ You did not specify your API_KEY or ACCOUNT_ID in the config.</b>\n'
'<b>🚨 Correct this for further module operation</b>'
),
'noGame': "<b>❌ The game is not running or you do not have access</b>",
'steamNow': (
'💻 <b>At the moment you are playing:</b>\n\n'
'🎮 <b>Title:</b> <code>{}</code>\n'
'🆔 <b>Game ID: {}</b>'
),
'lite_gameInfo': (
'🎮 <b>Game information:</b>\n\n'
'<b>Title: </b>{}\n'
'<b>Price: {}</b>\n'
'<b>Description:</b>\n- <i>{}</i>'
),
'steamMe': (
'<b>🎮 Your account:</b>\n\n'
'<b>Name: </b><i>{}</i> (<i>{}</i>)\n'
'<b>Online: </b><code>{}</code>\n'
'<b>Created: </b><code>{}</code>\n'
'<b>Recent games:</b>\n<i> • {}</i>'
),
'gameNotFound': '<b>🆔 There is no game with such an identifier, try again</b>',
"state": "🙂 <b>Steam widgets: {}</b>\n{}",
"error": "<b>Steam error</b>\n\n{}",
"tutorial": (
" <b>To enable the widget, send this text to any chat:"
" </b><code>{STEAMNOW}</code>"
),
"configuring": "🙂 <b>Steam widget will be ready soon...</b>",
}
strings_ru = {
'_api_key': "Введите ваш SteamAPI Key. Получить его можно по туториалу:\n\n", # Линк на тутор
'_account_id': "Введите ваш Steam Account ID. Подробнее в туториале: \n\n", # Линк на тутор
'no_api_key_or_id': (
'<b>❌ Вы не указали ваш API_KEY или ACCOUNT_ID в конфиге.</b>\n'
'<b>🚨 Исправьте это для дальнейшей работы модуля</b>'
),
'noGame': "<b>❌ Игра не запущена, или у вас нет доступа</b>",
'steamNow': (
'💻 <b>В данный момент вы играете:</b>\n\n'
'🎮 <b>Название:</b> <code>{}</code>\n'
'🆔 <b>ID Игры: {}</b>'
),
'lite_gameInfo': (
'🎮 <b>Информация об игре:</b>\n\n'
'<b>Название: </b>{}\n'
'<b>Цена: {}</b>\n'
'<b>Описание:</b>\n- <i>{}</i>'
),
'steamMe': (
'<b>🎮 Ваш аккаунт:</b>\n\n'
'<b>Имя: </b><i>{}</i> (<i>{}</i>)\n'
'<b>В сети: </b><code>{}</code>\n'
'<b>Создан: </b><code>{}</code>\n'
'<b>Последние игры:</b>\n<i> • {}</i>'
),
'gameNotFound': '<b>🆔 Игры с таким идентификатором нет, попробуйте снова</b>',
"state": "🙂 <b>Steam виджеты: {}</b>\n{}",
"error": "<b>Steam error</b>\n\n{}",
"tutorial": (
" <b>Для включения виджета отправьте данный текст в любой чат:"
" </b><code>{STEAMNOW}</code>"
),
"configuring": "🙂 <b>Steam виджет скоро будет готов...</b>",
}
def __init__(self):
self.config = loader.ModuleConfig(
loader.ConfigValue(
'API_KEY',
None,
doc=lambda: self.strings('_api_key'),
validator=loader.validators.Hidden(),
),
loader.ConfigValue(
'ACCOUNT_ID',
None,
doc=lambda: self.strings('_account_id')
),
loader.ConfigValue(
"update_interval",
300,
lambda: "Messages update interval. Not recommended < 300 seconds",
validator=loader.validators.Integer(minimum=60),
),
)
async def client_ready(self, client, db):
self.db.set(
"Steam",
"widgets",
list(map(tuple, self.db.get("Steam","widgets", [])))
)
self._task = asyncio.ensure_future(self._parse())
async def steam_requests(self, request, gameId: bool = None):
'''Function for requests to SteamAPI'''
api_key = self.config['API_KEY']
account_id = self.config['ACCOUNT_ID']
steam_client = SteamClient(api_key)
if request == 'SteamNow':
if not api_key or not account_id:
return('TokenError', None)
data = {'key': api_key, 'steamids': account_id}
response = steam_client.api_call('GET', 'ISteamUser', 'GetPlayerSummaries', 'v2', data).json()['response']
try:
gameId = response['players'][0]['gameid']
gameName = response['players'][0]['gameextrainfo']
text = self.strings('steamNow').format(gameName, gameId)
except:
text, gameId = self.strings('noGame'), None
return text, gameId #, photo
elif request == 'profileInfo':
if not api_key or not account_id:
return('TokenError', None, None, None, None, None)
url = 'http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key={}&steamids={}'
url2 = 'http://api.steampowered.com/IPlayerService/GetRecentlyPlayedGames/v0001/?key={}&steamid={}&format=json'
response = requests.get(url.format(self.config['API_KEY'], self.config['ACCOUNT_ID'])).json()['response']['players'][0]
recentGameInfo = requests.get(url2.format(self.config['API_KEY'], self.config['ACCOUNT_ID'])).json()['response']['games']
games = []
for game in recentGameInfo:
games.append(f'{game["name"]}: {game["playtime_2weeks"]}м. ({game["playtime_forever"]}м.)')
recentGames = '\n'.join(games)
return(
response['avatarfull'], # Profile photo
response['personaname'], # Name: 'ˢˡ ToxUniҨue,
response['realname'], # Realname: Tox.
datetime.datetime.fromtimestamp(response['lastlogoff']).isoformat().replace('T', ' '), # Последний раз в сети
datetime.datetime.fromtimestamp(response['timecreated']).isoformat().replace('T', ' '), # Дата создания аккаунта
recentGames
)
elif request == 'GameInfo':
if not api_key or not account_id:
return('TokenError', None)
url = f"http://store.steampowered.com/api/appdetails?appids={gameId}"
response = requests.get(url)
data = response.json()
game_data = data[str(gameId)]['data']
capsule_image = game_data.get('header_image', None)
name = game_data.get('name', None)
short_description = game_data.get('short_description', None)
price_overview = game_data.get('price_overview', None)
if price_overview:
initial_formatted_price = price_overview.get('initial_formatted', None)
final_formatted_price = price_overview.get('final_formatted', None)
else:
initial_formatted_price = None
final_formatted_price = None
final_price = f'{initial_formatted_price}' if initial_formatted_price == final_formatted_price else f'{final_formatted_price} (<u>{initial_formatted_price}</u>)'
text = self.strings('lite_gameInfo').format(name, final_price, short_description)
return capsule_image, text
async def game_info_i(
self,
call: InlineCall,
gameId: int,
message
):
_, text = await self.steam_requests('GameInfo', gameId)
if _ == 'TokenError':
return await call.edit(text=self.strings('no_api_key_or_id'))
await call.edit(text=text)
async def _parse(self, do_not_loop: bool = False):
while True:
if self.config["API_KEY"] == None or self.db.get("Steam", "state") == False:
await asyncio.sleep(5)
continue
for widget in self.db.get("Steam", "widgets", []):
now, _ = await self.steam_requests('SteamNow')
if now == 'TokenError':
await self._client.edit_message(*widget[:2], self.strings('no_api_key_or_id'))
elif now == self.strings('noGame'):
self.db.set('steam', 'inGame', None)
await self._client.edit_message(*widget[:2], self.strings('noGame'))
else:
in_game_time = self.db.get('steam', 'inGame')
if in_game_time is None:
self.db.set('steam', 'inGame', time.time())
game_time_minutes = 0
else:
game_time = time.time() - in_game_time
game_time_minutes = round(game_time / 60)
try:
await self._client.edit_message(*widget[:2], now + f'\n\n<b>🕓 В игре: {game_time_minutes} минут.</b>')
except:
return
await asyncio.sleep(int(self.config["update_interval"]))
@loader.command(
ru_doc=' - получить, во что я сейчас играю'
)
async def steamnow(self, message):
"""- get what I'm playing at"""
text, gameid = await self.steam_requests('SteamNow')
if text == self.strings('noGame'):
return await utils.answer(message, text)
elif text == 'TokenError':
return await utils.answer(message, self.strings('no_api_key_or_id'))
capsule_image, _ = await self.steam_requests('GameInfo', gameid)
await self.inline.form(
message=message,
photo=capsule_image,
text=text,
reply_markup=[
{
'text': 'Информация об игре',
'callback': self.game_info_i,
'args': (gameid, message,),
}
]
)
@loader.command(
ru_doc='- открыть аккаунт Steam'
)
async def sme(self, message):
'''- my steam account'''
photo, fullName, name, date1, date2, games = await self.steam_requests('profileInfo')
if photo == 'TokenError':
await utils.answer(message, self.strings('no_api_key_or_id'))
await utils.answer_file(
message,
photo,
caption=self.strings('steamMe').format(
fullName, name, date1, date2, games
)
)
@loader.command(
ru_doc='<id> - получить инфо об игре'
)
async def game(self, message):
'''<id> - get game info'''
args = utils.get_args_raw(message)
try:
capsule_image, text = await self.steam_requests('GameInfo', args)
if capsule_image == 'TokenError':
await utils.answer(message, self.strings('no_api_key_or_id'))
await utils.answer_file(message, capsule_image, text)
except:
await utils.answer(message, self.strings('gameNotFound'))
@loader.command(
ru_doc='- вкл/выкл виджеты SteamNow'
)
async def steamtoggle(self, message):
""" - toggle widgets updates"""
state = self.db.get('Steam', 'state')
state = True if state == False else False
self.db.set('Steam', 'state', state)
await utils.answer(
message,
self.strings("state").format(
"on" if state else "off", self.strings("tutorial") if state else ""
),
)
@loader.watcher()
async def watcher(self, message):
if (
self.db.get('Steam', 'state')
and (await self.client.get_messages(self.db.get('Steam', 'widgets')[0][0], ids=self.db.get('Steam', 'widgets')[0][1])).message == '❌ Вы не во что не играете'
):
now, _ = await self.steam_requests('SteamNow')
if now == self.strings('noGame') or now == 'TokenError':
return
await self._parse(do_not_loop=True)
try:
if "{STEAMNOW}" not in getattr(message, "text", "") or not message.out:
return
chat_id = utils.get_chat_id(message)
message_id = message.id
self.db.set(
"Steam",
"widgets",
self.db.get('steam', "widgets", []) + [(chat_id, message_id, message.text)],
)
await utils.answer(message, self.strings("configuring"))
await self._parse(do_not_loop=True)
except Exception as e:
logger.exception("Can't send widget")
await utils.answer(message, self.strings("error").format(e))
__version__ = (1, 0, 0)
#
# @@@@@@ @@@@@@ @@@@@@@ @@@@@@@ @@@@@@ @@@@@@@@@@ @@@@@@ @@@@@@@ @@@ @@@ @@@ @@@@@@@@ @@@@@@
# @@@@@@@@ @@@@@@@ @@@@@@@ @@@@@@@@ @@@@@@@@ @@@@@@@@@@@ @@@@@@@@ @@@@@@@@ @@@ @@@ @@@ @@@@@@@@ @@@@@@@
# @@! @@@ !@@ @@! @@! @@@ @@! @@@ @@! @@! @@! @@! @@@ @@! @@@ @@! @@@ @@! @@! !@@
# !@! @!@ !@! !@! !@! @!@ !@! @!@ !@! !@! !@! !@! @!@ !@! @!@ !@! @!@ !@! !@! !@!
# @!@!@!@! !!@@!! @!! @!@!!@! @!@ !@! @!! !!@ @!@ @!@ !@! @!@ !@! @!@ !@! @!! @!!!:! !!@@!!
# !!!@!!!! !!@!!! !!! !!@!@! !@! !!! !@! ! !@! !@! !!! !@! !!! !@! !!! !!! !!!!!: !!@!!!
# !!: !!! !:! !!: !!: :!! !!: !!! !!: !!: !!: !!! !!: !!! !!: !!! !!: !!: !:!
# :!: !:! !:! :!: :!: !:! :!: !:! :!: :!: :!: !:! :!: !:! :!: !:! :!: :!: !:!
# :: ::: :::: :: :: :: ::: ::::: :: ::: :: ::::: :: :::: :: ::::: :: :: :::: :: :::: :::: ::
# : : : :: : : : : : : : : : : : : : : :: : : : : : : :: : : : :: :: :: : :
#
# © Copyright 2024
#
# https://t.me/Den4ikSuperOstryyPer4ik
# and
# https://t.me/ToXicUse
#
# 🔒 Licensed under the GNU AGPLv3
# https://www.gnu.org/licenses/agpl-3.0.html
#
# meta banner:
# meta developer: @AstroModules
# required: steampy
# meta banner: https://raw.githubusercontent.com/Den4ikSuperOstryyPer4ik/Astro-modules/main/Banners/AstroSteamNow.png
# Part of the module taken from WakaTime by @hikariatama: 38, 158, 208, 324 lines
import time
import logging
import datetime
import requests
import asyncio
from steampy.client import SteamClient
from .. import loader, utils
from ..inline.types import InlineCall
from telethon.errors.rpcerrorlist import MessageNotModifiedError
logger = logging.getLogger(__name__)
@loader.tds
class Steam(loader.Module):
'''Get now played game'''
strings = {
'name': 'SteamNow',
'_api_key': "Enter your SteamAPI Key. You can get it by following this tutorial:\n\nhttps://t.me/help_code/20", # Tutorial link
'_account_id': "Enter your Steam Account ID. More details in the tutorial: \n\nhttps://t.me/help_code/21", # Tutorial link
'no_api_key_or_id': (
'<b>❌ You did not specify your API_KEY or ACCOUNT_ID in the config.</b>\n'
'<b>🚨 Correct this for further module operation</b>'
),
'noGame': "<b>❌ The game is not running or you do not have access</b>",
'steamNow': (
'💻 <b>At the moment you are playing:</b>\n\n'
'🎮 <b>Title:</b> <code>{}</code>\n'
'🆔 <b>Game ID: {}</b>'
),
'lite_gameInfo': (
'🎮 <b>Game information:</b>\n\n'
'<b>Title: </b>{}\n'
'<b>Price: {}</b>\n'
'<b>Description:</b>\n- <i>{}</i>'
),
'steamMe': (
'<b>🎮 Your account:</b>\n\n'
'<b>Name: </b><i>{}</i> (<i>{}</i>)\n'
'<b>Online: </b><code>{}</code>\n'
'<b>Created: </b><code>{}</code>\n'
'<b>Recent games:</b>\n<i> • {}</i>'
),
'gameNotFound': '<b>🆔 There is no game with such an identifier, try again</b>',
"state": "🙂 <b>Steam widgets: {}</b>\n{}",
"error": "<b>Steam error</b>\n\n{}",
"tutorial": (
" <b>To enable the widget, send this text to any chat:"
" </b><code>{STEAMNOW}</code>"
),
"configuring": "🙂 <b>Steam widget will be ready soon...</b>",
}
strings_ru = {
'_api_key': "Введите ваш SteamAPI Key. Получить его можно по туториалу:\n\n", # Линк на тутор
'_account_id': "Введите ваш Steam Account ID. Подробнее в туториале: \n\n", # Линк на тутор
'no_api_key_or_id': (
'<b>❌ Вы не указали ваш API_KEY или ACCOUNT_ID в конфиге.</b>\n'
'<b>🚨 Исправьте это для дальнейшей работы модуля</b>'
),
'noGame': "<b>❌ Игра не запущена, или у вас нет доступа</b>",
'steamNow': (
'💻 <b>В данный момент вы играете:</b>\n\n'
'🎮 <b>Название:</b> <code>{}</code>\n'
'🆔 <b>ID Игры: {}</b>'
),
'lite_gameInfo': (
'🎮 <b>Информация об игре:</b>\n\n'
'<b>Название: </b>{}\n'
'<b>Цена: {}</b>\n'
'<b>Описание:</b>\n- <i>{}</i>'
),
'steamMe': (
'<b>🎮 Ваш аккаунт:</b>\n\n'
'<b>Имя: </b><i>{}</i> (<i>{}</i>)\n'
'<b>В сети: </b><code>{}</code>\n'
'<b>Создан: </b><code>{}</code>\n'
'<b>Последние игры:</b>\n<i> • {}</i>'
),
'gameNotFound': '<b>🆔 Игры с таким идентификатором нет, попробуйте снова</b>',
"state": "🙂 <b>Steam виджеты: {}</b>\n{}",
"error": "<b>Steam error</b>\n\n{}",
"tutorial": (
" <b>Для включения виджета отправьте данный текст в любой чат:"
" </b><code>{STEAMNOW}</code>"
),
"configuring": "🙂 <b>Steam виджет скоро будет готов...</b>",
}
def __init__(self):
self.config = loader.ModuleConfig(
loader.ConfigValue(
'API_KEY',
None,
doc=lambda: self.strings('_api_key'),
validator=loader.validators.Hidden(),
),
loader.ConfigValue(
'ACCOUNT_ID',
None,
doc=lambda: self.strings('_account_id')
),
loader.ConfigValue(
"update_interval",
300,
lambda: "Messages update interval. Not recommended < 300 seconds",
validator=loader.validators.Integer(minimum=60),
),
)
async def client_ready(self, client, db):
self.db.set(
"Steam",
"widgets",
list(map(tuple, self.db.get("Steam","widgets", [])))
)
self._task = asyncio.ensure_future(self._parse())
async def steam_requests(self, request, gameId: bool = None):
'''Function for requests to SteamAPI'''
api_key = self.config['API_KEY']
account_id = self.config['ACCOUNT_ID']
steam_client = SteamClient(api_key)
if request == 'SteamNow':
if not api_key or not account_id:
return('TokenError', None)
data = {'key': api_key, 'steamids': account_id}
response = steam_client.api_call('GET', 'ISteamUser', 'GetPlayerSummaries', 'v2', data).json()['response']
try:
gameId = response['players'][0]['gameid']
gameName = response['players'][0]['gameextrainfo']
text = self.strings('steamNow').format(gameName, gameId)
except:
text, gameId = self.strings('noGame'), None
return text, gameId #, photo
elif request == 'profileInfo':
if not api_key or not account_id:
return('TokenError', None, None, None, None, None)
url = 'http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key={}&steamids={}'
url2 = 'http://api.steampowered.com/IPlayerService/GetRecentlyPlayedGames/v0001/?key={}&steamid={}&format=json'
response = requests.get(url.format(self.config['API_KEY'], self.config['ACCOUNT_ID'])).json()['response']['players'][0]
recentGameInfo = requests.get(url2.format(self.config['API_KEY'], self.config['ACCOUNT_ID'])).json()['response']['games']
games = []
for game in recentGameInfo:
games.append(f'{game["name"]}: {game["playtime_2weeks"]}м. ({game["playtime_forever"]}м.)')
recentGames = '\n'.join(games)
return(
response['avatarfull'], # Profile photo
response['personaname'], # Name: 'ˢˡ ToxUniҨue,
response['realname'], # Realname: Tox.
datetime.datetime.fromtimestamp(response['lastlogoff']).isoformat().replace('T', ' '), # Последний раз в сети
datetime.datetime.fromtimestamp(response['timecreated']).isoformat().replace('T', ' '), # Дата создания аккаунта
recentGames
)
elif request == 'GameInfo':
if not api_key or not account_id:
return('TokenError', None)
url = f"http://store.steampowered.com/api/appdetails?appids={gameId}"
response = requests.get(url)
data = response.json()
game_data = data[str(gameId)]['data']
capsule_image = game_data.get('header_image', None)
name = game_data.get('name', None)
short_description = game_data.get('short_description', None)
price_overview = game_data.get('price_overview', None)
if price_overview:
initial_formatted_price = price_overview.get('initial_formatted', None)
final_formatted_price = price_overview.get('final_formatted', None)
else:
initial_formatted_price = None
final_formatted_price = None
final_price = f'{initial_formatted_price}' if initial_formatted_price == final_formatted_price else f'{final_formatted_price} (<u>{initial_formatted_price}</u>)'
text = self.strings('lite_gameInfo').format(name, final_price, short_description)
return capsule_image, text
async def game_info_i(
self,
call: InlineCall,
gameId: int,
message
):
_, text = await self.steam_requests('GameInfo', gameId)
if _ == 'TokenError':
return await call.edit(text=self.strings('no_api_key_or_id'))
await call.edit(text=text)
async def _parse(self, do_not_loop: bool = False):
while True:
if self.config["API_KEY"] == None or self.db.get("Steam", "state") == False:
await asyncio.sleep(5)
continue
for widget in self.db.get("Steam", "widgets", []):
now, _ = await self.steam_requests('SteamNow')
if now == 'TokenError':
await self._client.edit_message(*widget[:2], self.strings('no_api_key_or_id'))
elif now == self.strings('noGame'):
self.db.set('steam', 'inGame', None)
await self._client.edit_message(*widget[:2], self.strings('noGame'))
else:
in_game_time = self.db.get('steam', 'inGame')
if in_game_time is None:
self.db.set('steam', 'inGame', time.time())
game_time_minutes = 0
else:
game_time = time.time() - in_game_time
game_time_minutes = round(game_time / 60)
try:
await self._client.edit_message(*widget[:2], now + f'\n\n<b>🕓 В игре: {game_time_minutes} минут.</b>')
except:
return
await asyncio.sleep(int(self.config["update_interval"]))
@loader.command(
ru_doc=' - получить, во что я сейчас играю'
)
async def steamnow(self, message):
"""- get what I'm playing at"""
text, gameid = await self.steam_requests('SteamNow')
if text == self.strings('noGame'):
return await utils.answer(message, text)
elif text == 'TokenError':
return await utils.answer(message, self.strings('no_api_key_or_id'))
capsule_image, _ = await self.steam_requests('GameInfo', gameid)
await self.inline.form(
message=message,
photo=capsule_image,
text=text,
reply_markup=[
{
'text': 'Информация об игре',
'callback': self.game_info_i,
'args': (gameid, message,),
}
]
)
@loader.command(
ru_doc='- открыть аккаунт Steam'
)
async def sme(self, message):
'''- my steam account'''
photo, fullName, name, date1, date2, games = await self.steam_requests('profileInfo')
if photo == 'TokenError':
await utils.answer(message, self.strings('no_api_key_or_id'))
await utils.answer_file(
message,
photo,
caption=self.strings('steamMe').format(
fullName, name, date1, date2, games
)
)
@loader.command(
ru_doc='<id> - получить инфо об игре'
)
async def game(self, message):
'''<id> - get game info'''
args = utils.get_args_raw(message)
try:
capsule_image, text = await self.steam_requests('GameInfo', args)
if capsule_image == 'TokenError':
await utils.answer(message, self.strings('no_api_key_or_id'))
await utils.answer_file(message, capsule_image, text)
except:
await utils.answer(message, self.strings('gameNotFound'))
@loader.command(
ru_doc='- вкл/выкл виджеты SteamNow'
)
async def steamtoggle(self, message):
""" - toggle widgets updates"""
state = self.db.get('Steam', 'state')
state = True if state == False else False
self.db.set('Steam', 'state', state)
await utils.answer(
message,
self.strings("state").format(
"on" if state else "off", self.strings("tutorial") if state else ""
),
)
@loader.watcher()
async def watcher(self, message):
if (
self.db.get('Steam', 'state')
and (await self.client.get_messages(self.db.get('Steam', 'widgets')[0][0], ids=self.db.get('Steam', 'widgets')[0][1])).message == '❌ Вы не во что не играете'
):
now, _ = await self.steam_requests('SteamNow')
if now == self.strings('noGame') or now == 'TokenError':
return
await self._parse(do_not_loop=True)
try:
if "{STEAMNOW}" not in getattr(message, "text", "") or not message.out:
return
chat_id = utils.get_chat_id(message)
message_id = message.id
self.db.set(
"Steam",
"widgets",
self.db.get('steam', "widgets", []) + [(chat_id, message_id, message.text)],
)
await utils.answer(message, self.strings("configuring"))
await self._parse(do_not_loop=True)
except Exception as e:
logger.exception("Can't send widget")
await utils.answer(message, self.strings("error").format(e))

View File

@@ -1,345 +1,345 @@
__version__ = (1, 4, 2)
#
# @@@@@@ @@@@@@ @@@@@@@ @@@@@@@ @@@@@@ @@@@@@@@@@ @@@@@@ @@@@@@@ @@@ @@@ @@@ @@@@@@@@ @@@@@@
# @@@@@@@@ @@@@@@@ @@@@@@@ @@@@@@@@ @@@@@@@@ @@@@@@@@@@@ @@@@@@@@ @@@@@@@@ @@@ @@@ @@@ @@@@@@@@ @@@@@@@
# @@! @@@ !@@ @@! @@! @@@ @@! @@@ @@! @@! @@! @@! @@@ @@! @@@ @@! @@@ @@! @@! !@@
# !@! @!@ !@! !@! !@! @!@ !@! @!@ !@! !@! !@! !@! @!@ !@! @!@ !@! @!@ !@! !@! !@!
# @!@!@!@! !!@@!! @!! @!@!!@! @!@ !@! @!! !!@ @!@ @!@ !@! @!@ !@! @!@ !@! @!! @!!!:! !!@@!!
# !!!@!!!! !!@!!! !!! !!@!@! !@! !!! !@! ! !@! !@! !!! !@! !!! !@! !!! !!! !!!!!: !!@!!!
# !!: !!! !:! !!: !!: :!! !!: !!! !!: !!: !!: !!! !!: !!! !!: !!! !!: !!: !:!
# :!: !:! !:! :!: :!: !:! :!: !:! :!: :!: :!: !:! :!: !:! :!: !:! :!: :!: !:!
# :: ::: :::: :: :: :: ::: ::::: :: ::: :: ::::: :: :::: :: ::::: :: :: :::: :: :::: :::: ::
# : : : :: : : : : : : : : : : : : : : :: : : : : : : :: : : : :: :: :: : :
#
# © Copyright 2024
#
# https://t.me/Den4ikSuperOstryyPer4ik
# and
# https://t.me/ToXicUse
#
# 🔒 Licensed under the GNU AGPLv3
# https://www.gnu.org/licenses/agpl-3.0.html
#
# meta developer: @AstroModules
import datetime
import logging
import time
from telethon import types
from telethon.tl.functions.account import UpdateProfileRequest
from telethon.tl.functions.users import GetFullUserRequest
from .. import loader, utils
from ..inline.types import InlineCall
logger = logging.getLogger(__name__)
@loader.tds
class TxAFKMod(loader.Module):
'''Афк модуль от AstroModules с изменением био и имени'''
async def client_ready(self, client, db):
self._db = db
self._me = await client.get_me()
strings = {
"name": "TxAFK",
"lname": "| afk.",
"lname0": " ",
"bt_off_afk": "⚠️ АФК режим отключен",
"bt_on_afk": "💤 АФК режим снова активен",
"_cfg_cst_btn": "Ссылка на чат которая будет отоброжаться вместе с уведомлением. (Чтобы вообще убрать напишите None)",
"standart_bio_text": "Кастомное описание профиля",
"feedback_bot__text": "Юзер вашего фидбэк бота (если имеется)",
"button__text": "Добавить инлайн кнопку отключения АФК режима?",
"custom_text__afk_text": "Кастомный текст афк. Используй {time} для вывода последнего времени нахождения в сети",
}
def __init__(self):
self.config = loader.ModuleConfig(
loader.ConfigValue(
"feedback_bot",
"None",
doc=lambda: self.strings("feedback_bot__text"),
),
loader.ConfigValue(
"custom_text__afk",
"None",
doc=lambda: self.strings("custom_text__afk_text"),
),
loader.ConfigValue(
"standart_bio",
"None",
doc=lambda: self.strings("standart_bio_text"),
),
loader.ConfigValue(
"custom_button",
[
"🦄 AstroModules 🦄",
"https://t.me/AstroModulesChat",
],
lambda: self.strings("_cfg_cst_btn"),
validator=loader.validators.Union(
loader.validators.Series(fixed_len=2),
loader.validators.NoneType(),
),
),
loader.ConfigValue(
"ignore_chats",
[],
lambda: "Чаты, в которых при упоминании TxAFК не будет срабатывать",
validator=loader.validators.Series(
validator=loader.validators.Union(
loader.validators.TelegramID(),
loader.validators.RegExp("[0-9]"),
),
),
),
loader.ConfigValue(
"button",
True,
doc=lambda: self.strings("button__text"),
validator=loader.validators.Boolean(),
)
)
async def txcfgcmd(self, message):
"""- открыть конфиг модуля"""
await self.allmodules.commands["config"](
await utils.answer(message, f"{self.get_prefix()}config TxAFK")
)
async def goafkcmd(self, message):
"""- войти в AFK режим"""
try:
user_id = (
(
(
await self._client.get_entity(
args if not args.isdigit() else int(args)
)
).id
)
if args
else reply.sender_id
)
except Exception:
user_id = self._tg_id
user = await self._client(GetFullUserRequest(user_id))
self._db.set(__name__, "afk", True)
self._db.set(__name__, "gone", time.time())
self._db.set(__name__, "ratelimit", [])
a_afk_bio_nofb = "В афк."
lastname = self.strings("lname")
if self.config['feedback_bot'] == None:
await message.client(UpdateProfileRequest(about=a_afk_bio_nofb, last_name=lastname))
else:
a_afk_bio = 'На данный момент в АФК. Связь только через '
feedback = self.config['feedback_bot']
aaa = a_afk_bio + feedback
await message.client(UpdateProfileRequest(about=aaa))
await self.allmodules.log("goafk")
await utils.answer(message, '<emoji document_id=5215519585150706301>👍</emoji> <b>АФК режим включен!</b>')
await message.client(UpdateProfileRequest(last_name=lastname))
async def ungoafkcmd(self, message):
"""- выйти из режима AFK"""
msg = await utils.answer(message, '<emoji document_id=5213107179329953547>⏰</emoji> <b>Отключаю режим АФК...</b>')
sbio = self.config['standart_bio']
lastname0 = self.strings('lname0')
self._db.set(__name__, "afk", False)
self._db.set(__name__, "gone", None)
self._db.set(__name__, "ratelimit", [])
await self.allmodules.log("unafk")
if sbio == None:
await message.client(UpdateProfileRequest(about='', last_name=lastname0))
else:
await message.client(UpdateProfileRequest(about=sbio, last_name=lastname0))
time.sleep(1)
await utils.answer(msg, '<emoji document_id=5220108512893344933>🆘</emoji> <b>Режим AFK отключен!</b>')
def _afk_custom_text(self) -> str:
now = datetime.datetime.now().replace(microsecond=0)
gone = datetime.datetime.fromtimestamp(
self._db.get(__name__, "gone")
).replace(microsecond=0)
time = now - gone
return (
"<b> </b>\n"
+ self.config["custom_text__afk"].format(
time=time,
)
)
async def watcher(self, message):
if not isinstance(message, types.Message):
return
if utils.get_chat_id(message) in self.config['ignore_chats']:
return
if message.mentioned or getattr(message.to_id, "user_id", None) == self._me.id:
afk_state = self.get_afk()
if not afk_state:
return
logger.debug("tagged!")
ratelimit = self._db.get(__name__, "ratelimit", [])
if utils.get_chat_id(message) in ratelimit:
return
else:
self._db.setdefault(__name__, {}).setdefault("ratelimit", []).append(
utils.get_chat_id(message)
)
self._db.save()
user = await utils.get_user(message)
if user.is_self or user.bot or user.verified:
logger.debug("User is self, bot or verified.")
return
if self.get_afk() is False:
return
now = datetime.datetime.now().replace(microsecond=0)
gone = datetime.datetime.fromtimestamp(
self._db.get(__name__, "gone")
).replace(microsecond=0)
time = now - gone
if self.config['custom_button'] == None:
if self.config["button"] == False:
if self.config["custom_text__afk"] == None:
await self.inline.form(message=message, text=f"<b>🔅 Я сейчас нахожусь в АФК.</b>\n\nПоследний раз был в сети <code>{time}</code> назад.")
else:
await self.inline.form(message=message, text=self._afk_custom_text())
elif self.config['button'] == True:
if self.config["custom_text__afk"] == None:
await self.inline.form(
message=message,
text=f"<b>🔅 Я сейчас нахожусь в АФК.</b>\n\nПоследний раз был в сети <code>{time}</code> назад.",
reply_markup=[
[
{
"text": "🚫 Выйти с афк 🚫",
"callback": self.button_cancel,
}
]
]
)
else:
await self.inline.form(
message=message,
text=self._afk_custom_text(),
reply_markup=[
[
{
"text": "🚫 Выйти с афк 🚫",
"callback": self.button_cancel,
}
]
]
)
else:
if self.config["button"] == False:
if self.config["custom_text__afk"] == None:
await self.inline.form(message=message, text=f"<b>🔅 Я сейчас нахожусь в АФК.</b>\n\nПоследний раз был в сети <code>{time}</code> назад.", reply_markup=[{"text": self.config['custom_button'][0], "url": self.config['custom_button'][1]}])
else:
await self.inline.form(message=message, text=self._afk_custom_text(), reply_markup=[{"text": self.config['custom_button'][0], "url": self.config['custom_button'][1]}])
elif self.config['button'] == True:
if self.config["custom_text__afk"] == None:
await self.inline.form(
message=message,
text=f"<b>🔅 Я сейчас нахожусь в АФК.</b>\n\nПоследний раз был в сети <code>{time}</code> назад.",
reply_markup=[
[
{
"text": self.config['custom_button'][0],
"url": self.config['custom_button'][1],
}
],
[
{
"text": "🚫 Выйти с афк 🚫",
"callback": self.button_cancel,
}
]
]
)
else:
await self.inline.form(
message=message,
text=self._afk_custom_text(),
reply_markup=[
[
{
"text": self.config['custom_button'][0],
"url": self.config['custom_button'][1],
}
],
[
{
"text": "🚫 Выйти с афк 🚫",
"callback": self.button_cancel,
}
]
]
)
async def button_cancel(self, call: InlineCall):
self._db.set(__name__, "afk", False)
self._db.set(__name__, "gone", None)
self._db.set(__name__, "ratelimit", [])
await self.allmodules.log("unafk")
if self.config['standart_bio'] == None:
lastname = self.strings("lname0")
about = self.strings("lname0")
await self._client(UpdateProfileRequest(about=about, last_name=lastname))
else:
aboutt = self.config['standart_bio']
lastname = self.strings("lname0")
await self._client(UpdateProfileRequest(about=aboutt, last_name=lastname))
await call.edit(
self.strings["bt_off_afk"],
reply_markup=[
{
"text": "🔰 Войти в афк 🔰",
"callback": self.button_cancel_on,
}
]
)
async def button_cancel_on(self, call: InlineCall):
self._db.set(__name__, "afk", True)
self._db.set(__name__, "gone", time.time())
self._db.set(__name__, "ratelimit", [])
a_afk_bio_nofb = "В афк."
lastname = self.strings("lname")
if self.config['feedback_bot'] == None:
await self._client(UpdateProfileRequest(about=a_afk_bio_nofb, last_name=lastname))
else:
a_afk_bio = 'На данный момент в АФК. Связь только через '
feedback = self.config['feedback_bot']
aaa = a_afk_bio + feedback
await self._client(UpdateProfileRequest(about=aaa))
await call.edit(
self.strings["bt_on_afk"],
reply_markup=[
{
"text": "🚫 Выйти с афк 🚫",
"callback": self.button_cancel,
}
]
)
def get_afk(self):
return self._db.get(__name__, "afk", False)
__version__ = (1, 4, 2)
#
# @@@@@@ @@@@@@ @@@@@@@ @@@@@@@ @@@@@@ @@@@@@@@@@ @@@@@@ @@@@@@@ @@@ @@@ @@@ @@@@@@@@ @@@@@@
# @@@@@@@@ @@@@@@@ @@@@@@@ @@@@@@@@ @@@@@@@@ @@@@@@@@@@@ @@@@@@@@ @@@@@@@@ @@@ @@@ @@@ @@@@@@@@ @@@@@@@
# @@! @@@ !@@ @@! @@! @@@ @@! @@@ @@! @@! @@! @@! @@@ @@! @@@ @@! @@@ @@! @@! !@@
# !@! @!@ !@! !@! !@! @!@ !@! @!@ !@! !@! !@! !@! @!@ !@! @!@ !@! @!@ !@! !@! !@!
# @!@!@!@! !!@@!! @!! @!@!!@! @!@ !@! @!! !!@ @!@ @!@ !@! @!@ !@! @!@ !@! @!! @!!!:! !!@@!!
# !!!@!!!! !!@!!! !!! !!@!@! !@! !!! !@! ! !@! !@! !!! !@! !!! !@! !!! !!! !!!!!: !!@!!!
# !!: !!! !:! !!: !!: :!! !!: !!! !!: !!: !!: !!! !!: !!! !!: !!! !!: !!: !:!
# :!: !:! !:! :!: :!: !:! :!: !:! :!: :!: :!: !:! :!: !:! :!: !:! :!: :!: !:!
# :: ::: :::: :: :: :: ::: ::::: :: ::: :: ::::: :: :::: :: ::::: :: :: :::: :: :::: :::: ::
# : : : :: : : : : : : : : : : : : : : :: : : : : : : :: : : : :: :: :: : :
#
# © Copyright 2024
#
# https://t.me/Den4ikSuperOstryyPer4ik
# and
# https://t.me/ToXicUse
#
# 🔒 Licensed under the GNU AGPLv3
# https://www.gnu.org/licenses/agpl-3.0.html
#
# meta developer: @AstroModules
import datetime
import logging
import time
from telethon import types
from telethon.tl.functions.account import UpdateProfileRequest
from telethon.tl.functions.users import GetFullUserRequest
from .. import loader, utils
from ..inline.types import InlineCall
logger = logging.getLogger(__name__)
@loader.tds
class TxAFKMod(loader.Module):
'''Афк модуль от AstroModules с изменением био и имени'''
async def client_ready(self, client, db):
self._db = db
self._me = await client.get_me()
strings = {
"name": "TxAFK",
"lname": "| afk.",
"lname0": " ",
"bt_off_afk": "⚠️ АФК режим отключен",
"bt_on_afk": "💤 АФК режим снова активен",
"_cfg_cst_btn": "Ссылка на чат которая будет отоброжаться вместе с уведомлением. (Чтобы вообще убрать напишите None)",
"standart_bio_text": "Кастомное описание профиля",
"feedback_bot__text": "Юзер вашего фидбэк бота (если имеется)",
"button__text": "Добавить инлайн кнопку отключения АФК режима?",
"custom_text__afk_text": "Кастомный текст афк. Используй {time} для вывода последнего времени нахождения в сети",
}
def __init__(self):
self.config = loader.ModuleConfig(
loader.ConfigValue(
"feedback_bot",
"None",
doc=lambda: self.strings("feedback_bot__text"),
),
loader.ConfigValue(
"custom_text__afk",
"None",
doc=lambda: self.strings("custom_text__afk_text"),
),
loader.ConfigValue(
"standart_bio",
"None",
doc=lambda: self.strings("standart_bio_text"),
),
loader.ConfigValue(
"custom_button",
[
"🦄 AstroModules 🦄",
"https://t.me/AstroModulesChat",
],
lambda: self.strings("_cfg_cst_btn"),
validator=loader.validators.Union(
loader.validators.Series(fixed_len=2),
loader.validators.NoneType(),
),
),
loader.ConfigValue(
"ignore_chats",
[],
lambda: "Чаты, в которых при упоминании TxAFК не будет срабатывать",
validator=loader.validators.Series(
validator=loader.validators.Union(
loader.validators.TelegramID(),
loader.validators.RegExp("[0-9]"),
),
),
),
loader.ConfigValue(
"button",
True,
doc=lambda: self.strings("button__text"),
validator=loader.validators.Boolean(),
)
)
async def txcfgcmd(self, message):
"""- открыть конфиг модуля"""
await self.allmodules.commands["config"](
await utils.answer(message, f"{self.get_prefix()}config TxAFK")
)
async def goafkcmd(self, message):
"""- войти в AFK режим"""
try:
user_id = (
(
(
await self._client.get_entity(
args if not args.isdigit() else int(args)
)
).id
)
if args
else reply.sender_id
)
except Exception:
user_id = self._tg_id
user = await self._client(GetFullUserRequest(user_id))
self._db.set(__name__, "afk", True)
self._db.set(__name__, "gone", time.time())
self._db.set(__name__, "ratelimit", [])
a_afk_bio_nofb = "В афк."
lastname = self.strings("lname")
if self.config['feedback_bot'] == None:
await message.client(UpdateProfileRequest(about=a_afk_bio_nofb, last_name=lastname))
else:
a_afk_bio = 'На данный момент в АФК. Связь только через '
feedback = self.config['feedback_bot']
aaa = a_afk_bio + feedback
await message.client(UpdateProfileRequest(about=aaa))
await self.allmodules.log("goafk")
await utils.answer(message, '<emoji document_id=5215519585150706301>👍</emoji> <b>АФК режим включен!</b>')
await message.client(UpdateProfileRequest(last_name=lastname))
async def ungoafkcmd(self, message):
"""- выйти из режима AFK"""
msg = await utils.answer(message, '<emoji document_id=5213107179329953547>⏰</emoji> <b>Отключаю режим АФК...</b>')
sbio = self.config['standart_bio']
lastname0 = self.strings('lname0')
self._db.set(__name__, "afk", False)
self._db.set(__name__, "gone", None)
self._db.set(__name__, "ratelimit", [])
await self.allmodules.log("unafk")
if sbio == None:
await message.client(UpdateProfileRequest(about='', last_name=lastname0))
else:
await message.client(UpdateProfileRequest(about=sbio, last_name=lastname0))
time.sleep(1)
await utils.answer(msg, '<emoji document_id=5220108512893344933>🆘</emoji> <b>Режим AFK отключен!</b>')
def _afk_custom_text(self) -> str:
now = datetime.datetime.now().replace(microsecond=0)
gone = datetime.datetime.fromtimestamp(
self._db.get(__name__, "gone")
).replace(microsecond=0)
time = now - gone
return (
"<b> </b>\n"
+ self.config["custom_text__afk"].format(
time=time,
)
)
async def watcher(self, message):
if not isinstance(message, types.Message):
return
if utils.get_chat_id(message) in self.config['ignore_chats']:
return
if message.mentioned or getattr(message.to_id, "user_id", None) == self._me.id:
afk_state = self.get_afk()
if not afk_state:
return
logger.debug("tagged!")
ratelimit = self._db.get(__name__, "ratelimit", [])
if utils.get_chat_id(message) in ratelimit:
return
else:
self._db.setdefault(__name__, {}).setdefault("ratelimit", []).append(
utils.get_chat_id(message)
)
self._db.save()
user = await utils.get_user(message)
if user.is_self or user.bot or user.verified:
logger.debug("User is self, bot or verified.")
return
if self.get_afk() is False:
return
now = datetime.datetime.now().replace(microsecond=0)
gone = datetime.datetime.fromtimestamp(
self._db.get(__name__, "gone")
).replace(microsecond=0)
time = now - gone
if self.config['custom_button'] == None:
if self.config["button"] == False:
if self.config["custom_text__afk"] == None:
await self.inline.form(message=message, text=f"<b>🔅 Я сейчас нахожусь в АФК.</b>\n\nПоследний раз был в сети <code>{time}</code> назад.")
else:
await self.inline.form(message=message, text=self._afk_custom_text())
elif self.config['button'] == True:
if self.config["custom_text__afk"] == None:
await self.inline.form(
message=message,
text=f"<b>🔅 Я сейчас нахожусь в АФК.</b>\n\nПоследний раз был в сети <code>{time}</code> назад.",
reply_markup=[
[
{
"text": "🚫 Выйти с афк 🚫",
"callback": self.button_cancel,
}
]
]
)
else:
await self.inline.form(
message=message,
text=self._afk_custom_text(),
reply_markup=[
[
{
"text": "🚫 Выйти с афк 🚫",
"callback": self.button_cancel,
}
]
]
)
else:
if self.config["button"] == False:
if self.config["custom_text__afk"] == None:
await self.inline.form(message=message, text=f"<b>🔅 Я сейчас нахожусь в АФК.</b>\n\nПоследний раз был в сети <code>{time}</code> назад.", reply_markup=[{"text": self.config['custom_button'][0], "url": self.config['custom_button'][1]}])
else:
await self.inline.form(message=message, text=self._afk_custom_text(), reply_markup=[{"text": self.config['custom_button'][0], "url": self.config['custom_button'][1]}])
elif self.config['button'] == True:
if self.config["custom_text__afk"] == None:
await self.inline.form(
message=message,
text=f"<b>🔅 Я сейчас нахожусь в АФК.</b>\n\nПоследний раз был в сети <code>{time}</code> назад.",
reply_markup=[
[
{
"text": self.config['custom_button'][0],
"url": self.config['custom_button'][1],
}
],
[
{
"text": "🚫 Выйти с афк 🚫",
"callback": self.button_cancel,
}
]
]
)
else:
await self.inline.form(
message=message,
text=self._afk_custom_text(),
reply_markup=[
[
{
"text": self.config['custom_button'][0],
"url": self.config['custom_button'][1],
}
],
[
{
"text": "🚫 Выйти с афк 🚫",
"callback": self.button_cancel,
}
]
]
)
async def button_cancel(self, call: InlineCall):
self._db.set(__name__, "afk", False)
self._db.set(__name__, "gone", None)
self._db.set(__name__, "ratelimit", [])
await self.allmodules.log("unafk")
if self.config['standart_bio'] == None:
lastname = self.strings("lname0")
about = self.strings("lname0")
await self._client(UpdateProfileRequest(about=about, last_name=lastname))
else:
aboutt = self.config['standart_bio']
lastname = self.strings("lname0")
await self._client(UpdateProfileRequest(about=aboutt, last_name=lastname))
await call.edit(
self.strings["bt_off_afk"],
reply_markup=[
{
"text": "🔰 Войти в афк 🔰",
"callback": self.button_cancel_on,
}
]
)
async def button_cancel_on(self, call: InlineCall):
self._db.set(__name__, "afk", True)
self._db.set(__name__, "gone", time.time())
self._db.set(__name__, "ratelimit", [])
a_afk_bio_nofb = "В афк."
lastname = self.strings("lname")
if self.config['feedback_bot'] == None:
await self._client(UpdateProfileRequest(about=a_afk_bio_nofb, last_name=lastname))
else:
a_afk_bio = 'На данный момент в АФК. Связь только через '
feedback = self.config['feedback_bot']
aaa = a_afk_bio + feedback
await self._client(UpdateProfileRequest(about=aaa))
await call.edit(
self.strings["bt_on_afk"],
reply_markup=[
{
"text": "🚫 Выйти с афк 🚫",
"callback": self.button_cancel,
}
]
)
def get_afk(self):
return self._db.get(__name__, "afk", False)

View File

@@ -1,34 +1,35 @@
komarumod
RandomPasswordGenerator
gamecheat
convertio
mindtalk
dialogs_manager
inline_bot_manager
RandomTrack
iOSAppsForAndroid
video_to_voice
вахуи_пон
RandomStatuses
TwinkManager
brawl_stats
astroafk
YandexMusic
astroweather
wordly
RandomUser
summer
пон_вахуи
pcmanager
shazam
achievements
Steam
minesweeper
dl_yt_previews
TxAFK
akinator
Compliments
commands_logger
Emotions
AntiMat
demotivator
komarumod
RandomPasswordGenerator
gamecheat
convertio
mindtalk
dialogs_manager
inline_bot_manager
RandomTrack
iOSAppsForAndroid
video_to_voice
вахуи_пон
RandomStatuses
TwinkManager
brawl_stats
astroafk
YandexMusic
astroweather
wordly
RandomUser
summer
пон_вахуи
pcmanager
shazam
achievements
Steam
minesweeper
dl_yt_previews
TxAFK
akinator
Compliments
commands_logger
Emotions
AntiMat
demotivator
ymlive

View File

@@ -67,7 +67,7 @@ class PCManagerMod(loader.Module):
async def pcoff(self, message: Message):
"""- выключить компьютер"""
bot = self.config["bot_username"]
call = await self.lib.message_g('🛑 Shutdown',
call = await self.lib.message_g('/off',
bot,
mark_read=True,
delete=True
@@ -78,7 +78,7 @@ class PCManagerMod(loader.Module):
async def pcreboot(self, message: Message):
"""- перезагрузить компьютер"""
bot = self.config["bot_username"]
call = await self.lib.message_g('🔄 Reboot',
call = await self.lib.message_g('/reboot',
bot,
mark_read=True,
delete=True
@@ -89,7 +89,7 @@ class PCManagerMod(loader.Module):
async def pcinfo(self, message: Message):
"""- просмотреть характеристики системы"""
bot = self.config["bot_username"]
call = await self.lib.message_q('💻 System Info',
call = await self.lib.message_q('/info',
bot,
mark_read=True,
delete=True
@@ -100,7 +100,7 @@ class PCManagerMod(loader.Module):
async def pcip(self, message: Message):
"""- просмотреть информацию об айпи адресе"""
bot = self.config["bot_username"]
call = await self.lib.message_q('🌐 IP Info',
call = await self.lib.message_q('/ip',
bot,
mark_read=True,
delete=True
@@ -108,10 +108,10 @@ class PCManagerMod(loader.Module):
await utils.answer(message, f'<emoji document_id=5787544344906959608></emoji> <b>[PC_Manager]</b> <emoji document_id=5787544344906959608></emoji>\n\n{call.text}')
@loader.command()
async def pcscrin(self, message: Message):
async def pcscreen(self, message: Message):
"""- сделать скриншот экрана"""
bot = self.config['bot_username']
call = await self.lib.message_g('/screenshot',
call = await self.lib.message_q('/screenshot',
bot,
mark_read=True,
delete=True
@@ -121,29 +121,19 @@ class PCManagerMod(loader.Module):
@loader.command()
async def pcweb(self, message: Message):
"""<ссылка> - открыть ссылку в браузере"""
"""<ссылка> - открыть ссылку в браузере
🔑 Дополнительно:"""
bot = self.config['bot_username']
args = utils.get_args_raw(message)
call = await self.lib.message_q(f'/browse {args}',
call = await self.lib.message_q(f'/web {args}',
bot,
mark_read=True,
delete=True
)
await utils.answer(message, f'<emoji document_id=5787544344906959608></emoji> <b>[PC_Manager]</b> <emoji document_id=5787544344906959608></emoji>\n\n{call.text}\n\nСсылка: {args}')
@loader.command()
async def pcwebscrin(self, message: Message):
"""- сделать снимок с веб-камеры
🔑 Дополнительно:"""
bot = self.config['bot_username']
call = await self.lib.message_g('/photo',
bot,
mark_read=True,
delete=True
)
await utils.answer(message, '<emoji document_id=5787544344906959608></emoji> <b>[PC_Manager]</b> <emoji document_id=5787544344906959608></emoji>\n\nОтправка снимка...')
await message.respond(call)
@loader.command()
async def pcalert(self, message: Message):
@@ -217,20 +207,15 @@ class PCManagerMod(loader.Module):
],
[
{
"text": "⬆️",
"text": "0%",
"callback": self.set_volume,
"args": ("up",)
},
"args": (0,)
},
{
"text": "100%",
"callback": self.set_volume,
"args": (100,)
},
{
"text": "⬇️",
"callback": self.set_volume,
"args": ("down",)
},
],
[
{
@@ -288,4 +273,4 @@ class PCManagerMod(loader.Module):
await self.client.send_message(f'{bot}', '/key__next')
return await call.answer("Успешно!", show_alert=False)
# Tx...
# Tx...

View File

@@ -1,87 +1,87 @@
__version__ = (1, 0, 0)
#
# @@@@@@ @@@@@@ @@@@@@@ @@@@@@@ @@@@@@ @@@@@@@@@@ @@@@@@ @@@@@@@ @@@ @@@ @@@ @@@@@@@@ @@@@@@
# @@@@@@@@ @@@@@@@ @@@@@@@ @@@@@@@@ @@@@@@@@ @@@@@@@@@@@ @@@@@@@@ @@@@@@@@ @@@ @@@ @@@ @@@@@@@@ @@@@@@@
# @@! @@@ !@@ @@! @@! @@@ @@! @@@ @@! @@! @@! @@! @@@ @@! @@@ @@! @@@ @@! @@! !@@
# !@! @!@ !@! !@! !@! @!@ !@! @!@ !@! !@! !@! !@! @!@ !@! @!@ !@! @!@ !@! !@! !@!
# @!@!@!@! !!@@!! @!! @!@!!@! @!@ !@! @!! !!@ @!@ @!@ !@! @!@ !@! @!@ !@! @!! @!!!:! !!@@!!
# !!!@!!!! !!@!!! !!! !!@!@! !@! !!! !@! ! !@! !@! !!! !@! !!! !@! !!! !!! !!!!!: !!@!!!
# !!: !!! !:! !!: !!: :!! !!: !!! !!: !!: !!: !!! !!: !!! !!: !!! !!: !!: !:!
# :!: !:! !:! :!: :!: !:! :!: !:! :!: :!: :!: !:! :!: !:! :!: !:! :!: :!: !:!
# :: ::: :::: :: :: :: ::: ::::: :: ::: :: ::::: :: :::: :: ::::: :: :: :::: :: :::: :::: ::
# : : : :: : : : : : : : : : : : : : : :: : : : : : : :: : : : :: :: :: : :
#
# © Copyright 2024
#
# https://t.me/Den4ikSuperOstryyPer4ik
# and
# https://t.me/ToXicUse
#
# 🔒 Licensed under the GNU AGPLv3
# https://www.gnu.org/licenses/agpl-3.0.html
#
# meta developer: @AstroModules
# meta banner: https://raw.githubusercontent.com/Den4ikSuperOstryyPer4ik/Astro-modules/main/Banners/AstroShazam.png
# The code snippet is adapted from VoiceMod code by D4n1l3k300
# requires: ShazamAPI
import io
from ShazamAPI import Shazam
from .. import loader, utils
@loader.tds
class ShazamMod(loader.Module):
"""Use <reply to voice> to search for a song using audio."""
strings = {
"name": 'Shazam',
"Downloading": "<emoji document_id=5443127283898405358>📥</emoji> <b>Downloading...</b>",
"Searching": "<emoji document_id=5447410659077661506>🔎</emoji> <b>Searching...</b>",
"no_reply": "<emoji document_id=5294339927318739359>🎙</emoji> <b>Please reply to an audio message.</b>",
"not_found": "<emoji document_id=5210952531676504517>🚫</emoji> <b>Song not found.</b>",
"track_info": (
"<emoji document_id=5325547803936572038>✨</emoji> <b>Song found</b>\n"
'<emoji document_id=5460795800101594035>📝</emoji> <b>Name</b> "<code>{}</code>"'
)
}
strings_ru = {
"Downloading": "<emoji document_id=5443127283898405358>📥</emoji> <b>Загрузка..</b>",
"Searching": "<emoji document_id=5447410659077661506>🔎</emoji> <b>Поиск..</b>",
"no_reply": "<emoji document_id=5294339927318739359>🎙</emoji> <b>Oтветьте на аудио сообщение</b>",
"not_found": "<emoji document_id=5210952531676504517>🚫</emoji> <b>Не удалось найти песню</b>",
"track_info": (
"<emoji document_id=5325547803936572038>✨</emoji> <b>Песня найдена</b>\n"
'<emoji document_id=5460795800101594035>📝</emoji> <b>Название:</b> "<code>{}</code>"'
)
}
async def fetch_audio(self, message):
reply = await message.get_reply_message()
if reply and reply.file and reply.file.mime_type.startswith("audio"):
await utils.answer(message, self.strings['Downloading'])
audio_data = io.BytesIO(await reply.download_media(bytes))
await utils.answer(message, self.strings['Searching'])
return audio_data, reply
await utils.answer(message, self.strings['no_reply'])
return None, None
@loader.command(ru_doc='<reply to audio> - распознать трек')
async def sh(self, message):
"""<reply to audio> - recognize track"""
audio_data, reply = await self.fetch_audio(message)
if not audio_data:
return
try:
shazam = Shazam(audio_data.read())
recog = next(shazam.recognizeSong())[1]["track"]
await self.client.send_file(
message.peer_id,
file=recog["images"]["background"],
caption=self.strings['track_info'].format(recog["share"]["subject"]),
reply_to=reply.id,
)
await message.delete()
except Exception:
await utils.answer(message, self.strings['not_found'])
__version__ = (1, 0, 0)
#
# @@@@@@ @@@@@@ @@@@@@@ @@@@@@@ @@@@@@ @@@@@@@@@@ @@@@@@ @@@@@@@ @@@ @@@ @@@ @@@@@@@@ @@@@@@
# @@@@@@@@ @@@@@@@ @@@@@@@ @@@@@@@@ @@@@@@@@ @@@@@@@@@@@ @@@@@@@@ @@@@@@@@ @@@ @@@ @@@ @@@@@@@@ @@@@@@@
# @@! @@@ !@@ @@! @@! @@@ @@! @@@ @@! @@! @@! @@! @@@ @@! @@@ @@! @@@ @@! @@! !@@
# !@! @!@ !@! !@! !@! @!@ !@! @!@ !@! !@! !@! !@! @!@ !@! @!@ !@! @!@ !@! !@! !@!
# @!@!@!@! !!@@!! @!! @!@!!@! @!@ !@! @!! !!@ @!@ @!@ !@! @!@ !@! @!@ !@! @!! @!!!:! !!@@!!
# !!!@!!!! !!@!!! !!! !!@!@! !@! !!! !@! ! !@! !@! !!! !@! !!! !@! !!! !!! !!!!!: !!@!!!
# !!: !!! !:! !!: !!: :!! !!: !!! !!: !!: !!: !!! !!: !!! !!: !!! !!: !!: !:!
# :!: !:! !:! :!: :!: !:! :!: !:! :!: :!: :!: !:! :!: !:! :!: !:! :!: :!: !:!
# :: ::: :::: :: :: :: ::: ::::: :: ::: :: ::::: :: :::: :: ::::: :: :: :::: :: :::: :::: ::
# : : : :: : : : : : : : : : : : : : : :: : : : : : : :: : : : :: :: :: : :
#
# © Copyright 2024
#
# https://t.me/Den4ikSuperOstryyPer4ik
# and
# https://t.me/ToXicUse
#
# 🔒 Licensed under the GNU AGPLv3
# https://www.gnu.org/licenses/agpl-3.0.html
#
# meta developer: @AstroModules
# meta banner: https://raw.githubusercontent.com/Den4ikSuperOstryyPer4ik/Astro-modules/main/Banners/AstroShazam.png
# The code snippet is adapted from VoiceMod code by D4n1l3k300
# requires: ShazamAPI
import io
from ShazamAPI import Shazam
from .. import loader, utils
@loader.tds
class ShazamMod(loader.Module):
"""Use <reply to voice> to search for a song using audio."""
strings = {
"name": 'Shazam',
"Downloading": "<emoji document_id=5443127283898405358>📥</emoji> <b>Downloading...</b>",
"Searching": "<emoji document_id=5447410659077661506>🔎</emoji> <b>Searching...</b>",
"no_reply": "<emoji document_id=5294339927318739359>🎙</emoji> <b>Please reply to an audio message.</b>",
"not_found": "<emoji document_id=5210952531676504517>🚫</emoji> <b>Song not found.</b>",
"track_info": (
"<emoji document_id=5325547803936572038>✨</emoji> <b>Song found</b>\n"
'<emoji document_id=5460795800101594035>📝</emoji> <b>Name</b> "<code>{}</code>"'
)
}
strings_ru = {
"Downloading": "<emoji document_id=5443127283898405358>📥</emoji> <b>Загрузка..</b>",
"Searching": "<emoji document_id=5447410659077661506>🔎</emoji> <b>Поиск..</b>",
"no_reply": "<emoji document_id=5294339927318739359>🎙</emoji> <b>Oтветьте на аудио сообщение</b>",
"not_found": "<emoji document_id=5210952531676504517>🚫</emoji> <b>Не удалось найти песню</b>",
"track_info": (
"<emoji document_id=5325547803936572038>✨</emoji> <b>Песня найдена</b>\n"
'<emoji document_id=5460795800101594035>📝</emoji> <b>Название:</b> "<code>{}</code>"'
)
}
async def fetch_audio(self, message):
reply = await message.get_reply_message()
if reply and reply.file and reply.file.mime_type.startswith("audio"):
await utils.answer(message, self.strings['Downloading'])
audio_data = io.BytesIO(await reply.download_media(bytes))
await utils.answer(message, self.strings['Searching'])
return audio_data, reply
await utils.answer(message, self.strings['no_reply'])
return None, None
@loader.command(ru_doc='<reply to audio> - распознать трек')
async def sh(self, message):
"""<reply to audio> - recognize track"""
audio_data, reply = await self.fetch_audio(message)
if not audio_data:
return
try:
shazam = Shazam(audio_data.read())
recog = next(shazam.recognizeSong())[1]["track"]
await self.client.send_file(
message.peer_id,
file=recog["images"]["background"],
caption=self.strings['track_info'].format(recog["share"]["subject"]),
reply_to=reply.id,
)
await message.delete()
except Exception:
await utils.answer(message, self.strings['not_found'])