Added and updated repositories 2026-04-15 01:53:05

This commit is contained in:
github-actions[bot]
2026-04-15 01:53:05 +00:00
parent 3a193cfb2f
commit 4ca7279309
4 changed files with 54 additions and 72 deletions

View File

@@ -100,18 +100,6 @@ class MInstaller:
return "dependency", [] return "dependency", []
async def pip(self, dependencies: List[str]) -> bool:
virtualenv = hasattr(sys, 'real_prefix') or sys.prefix != getattr(sys, 'base_prefix', sys.prefix)
flags = ["--user"] if loader.USER_INSTALL and not virtualenv else []
process = await asyncio.create_subprocess_exec(
sys.executable, "-m", "pip", "install", "-U", "-q",
"--disable-pip-version-check", "--no-warn-script-location",
*flags, *dependencies
)
return await process.wait() == 0
async def load(self, plugin: 'loader.Module', code: str, origin: str, step: int) -> Union[str, List[str]]: async def load(self, plugin: 'loader.Module', code: str, origin: str, step: int) -> Union[str, List[str]]:
if step == 0: if step == 0:
try: try:
@@ -121,7 +109,7 @@ class MInstaller:
)) ))
if dependencies: if dependencies:
if not await self.pip(dependencies): if not await plugin.install_requirements(dependencies):
return dependencies return dependencies
importlib.invalidate_caches() importlib.invalidate_caches()
return "retry" return "retry"
@@ -171,7 +159,7 @@ class MInstaller:
alternative = {"sklearn": "scikit-learn", "pil": "Pillow", "herokutl": "Heroku-TL-New"}.get(exception.name.lower(), exception.name) alternative = {"sklearn": "scikit-learn", "pil": "Pillow", "herokutl": "Heroku-TL-New"}.get(exception.name.lower(), exception.name)
dependencies = [alternative] dependencies = [alternative]
if not alternative or not await self.pip(dependencies): if not alternative or not await plugin.install_requirements(dependencies):
return dependencies return dependencies
importlib.invalidate_caches() importlib.invalidate_caches()
@@ -872,7 +860,7 @@ class FHeta(loader.Module):
return { return {
"title": self.strings["prompt"], "title": self.strings["prompt"],
"description": self.strings["hint"], "description": self.strings["hint"],
"message": f"{self.ui.emoji('error')} <b>{self.strings['prompt']}</b>", "message": f"{self.ui.emoji('error')} <b>{self.strings['noquery'].format(prefix=f'<code>@{self.inline.bot_username} ')}</code></b>",
"thumb": "https://raw.githubusercontent.com/Fixyres/FModules/refs/heads/main/assets/FHeta/magnifying_glass.png" "thumb": "https://raw.githubusercontent.com/Fixyres/FModules/refs/heads/main/assets/FHeta/magnifying_glass.png"
} }
@@ -890,7 +878,7 @@ class FHeta(loader.Module):
return { return {
"title": self.strings["retry"], "title": self.strings["retry"],
"description": self.strings["hint"], "description": self.strings["hint"],
"message": f"{self.ui.emoji('error')} <b>{self.strings['notfound'].format(query=utils.escape_html(query))}</b>", "message": f"{self.ui.emoji('error')} <b>{self.strings['notfound'].format(query=f'<code>{utils.escape_html(query)}</code>')}</b>",
"thumb": "https://raw.githubusercontent.com/Fixyres/FModules/refs/heads/main/assets/FHeta/try_other_query.png" "thumb": "https://raw.githubusercontent.com/Fixyres/FModules/refs/heads/main/assets/FHeta/try_other_query.png"
} }
@@ -941,18 +929,18 @@ class FHeta(loader.Module):
query = utils.get_args_raw(message) query = utils.get_args_raw(message)
if not query: if not query:
return await utils.answer(message, f"{self.ui.emoji('error')} <b>{self.strings['noquery'].format(prefix=self.get_prefix())}</b>") return await utils.answer(message, f"{self.ui.emoji('error')} <b>{self.strings['noquery'].format(prefix=f'<code>{self.get_prefix()}')}</code></b>")
if len(query) > 168: if len(query) > 168:
return await utils.answer(message, f"{self.ui.emoji('warn')} <b>{self.strings['toolong']}</b>") return await utils.answer(message, f"{self.ui.emoji('warn')} <b>{self.strings['toolong']}</b>")
message = await utils.answer(message, f"{self.ui.emoji('search')} <b>{self.strings['search'].format(query=utils.escape_html(query))}</b>") message = await utils.answer(message, f"{self.ui.emoji('search')} <b>{self.strings['search'].format(query=f'<code>{utils.escape_html(query)}</code>')}</b>")
modules = await self.api.fetch("search", query=query, inline="false", token=self.token, user_id=self.identifier, ood=str(self.config["only_official_developers"]).lower()) modules = await self.api.fetch("search", query=query, inline="false", token=self.token, user_id=self.identifier, ood=str(self.config["only_official_developers"]).lower())
if not modules or not isinstance(modules, list): if not modules or not isinstance(modules, list):
return await utils.answer(message, f"{self.ui.emoji('error')} <b>{self.strings['notfound'].format(query=utils.escape_html(query))}</b>") return await utils.answer(message, f"{self.ui.emoji('error')} <b>{self.strings['notfound'].format(query=f'<code>{utils.escape_html(query)}</code>')}</b>")
data = modules[0] data = modules[0]
buttons = self.ui.buttons(data.get("install", ""), data, 0, modules, query) buttons = self.ui.buttons(data.get("install", ""), data, 0, modules, query)
form = await self.inline.form("", message, reply_markup=buttons, silent=True) form = await self.inline.form("", message, reply_markup=buttons, silent=True)

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

View File

@@ -1,9 +1,8 @@
#Midga3 #Midga3
#Placeholder system is the best #Placeholder system is the best
# meta banner: https://github.com/Midga3/heroku-modules/blob/main/new_module.jpg?raw=true
# meta developer: @midga3_modules # meta developer: @midga3_modules
__version__ = (1, 0, 0) __version__ = (1, 1, 2)
import logging import logging
import aiohttp import aiohttp
@@ -17,13 +16,20 @@ class PingEmoji(loader.Module):
strings = { strings = {
"name": "PingEmoji" "name": "PingEmoji"
} }
def __init__(self):
self.config = loader.ModuleConfig(
loader.ConfigValue(
"emoji",
"<tg-emoji emoji-id=5276307163529092252>🔴</tg-emoji>",
"Ping Emoji",
)
)
async def client_ready(self, client, db): async def client_ready(self, client, db):
self._client = client self._client = client
utils.register_placeholder("ping_emoji", self.get_emoji) utils.register_placeholder("ping_emoji", self.get_emoji)
async def get_emoji(self, data): async def get_emoji(self, data):
if data['ping'] > 300: if data['ping'] > 300:
return "<tg-emoji emoji-id=5276307163529092252>🔴</tg-emoji>" return self.config['emoji']
else: else:
return "" return ""

View File

@@ -26,7 +26,7 @@ from typing import Optional, Dict, Any
from collections import OrderedDict from collections import OrderedDict
from .. import loader, utils, validators from .. import loader, utils, validators
from herokutl.tl.functions.users import GetFullUserRequest from telethon.tl.functions.users import GetFullUserRequest
from herokutl.tl.functions.payments import GetStarsStatusRequest from herokutl.tl.functions.payments import GetStarsStatusRequest
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -118,21 +118,23 @@ class PlaceholdersMod(loader.Module):
) )
self.cache = LRUCache(max_size=100, ttl=300) self.cache = LRUCache(max_size=100, ttl=300)
async def client_ready(self): async def client_ready(self, client, db):
self._client = client
self.session = aiohttp.ClientSession() self.session = aiohttp.ClientSession()
self.me = await self._client.get_me() self.me = await client.get_me()
self.full_me = await self._client(GetFullUserRequest(self.me)) self.full_me = await client(GetFullUserRequest(self.me))
try: try:
stars_status = await self._client(GetStarsStatusRequest(entity="me")) stars_status = await self._client(GetStarsStatusRequest(entity='me'))
self.stars_balance = stars_status.balance self.stars_balance = stars_status.balance
except Exception: except:
self.stars_balance = 0 self.stars_balance = 0
self.tz = timezone(timedelta(hours=self.config["timezone"])) self.tz = timezone(timedelta(hours=self.config["timezone"]))
self.weekdays_ru = ["Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота", "Воскресенье"] self.weekdays_ru = ["Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота", "Воскресенье"]
# Регистрация плейсхолдеров
self._register_placeholders() self._register_placeholders()
def _register_placeholders(self): def _register_placeholders(self):
@@ -199,30 +201,18 @@ class PlaceholdersMod(loader.Module):
utils.register_placeholder(name, func, desc) utils.register_placeholder(name, func, desc)
async def get_premium_check(self): async def get_premium_check(self):
if not getattr(self.me, "premium", False): if not self.me.premium:
return "Нет Premium" return "Нет Premium"
# premium_until отсутствует в публичном MTProto API herokutl/Telethon — until = self.full_me.full_user.premium_until
# пробуем достать его, но не падаем если поля нет if not until or until < time.time():
until = None return "Премиум закончился"
try:
until = getattr(self.full_me.full_user, "premium_until", None)
# Иногда это datetime, иногда unix timestamp (int)
if isinstance(until, datetime):
until = until.timestamp()
except Exception:
until = None
if not until:
return "✅ Premium активен"
if until < time.time():
return "⚠️ Премиум истёк"
end_date = datetime.fromtimestamp(until, tz=self.tz) end_date = datetime.fromtimestamp(until, tz=self.tz)
days_left = (end_date.date() - datetime.now(self.tz).date()).days days_left = (end_date.date() - datetime.now(self.tz).date()).days
formatted = end_date.strftime("%d.%m.%Y") formatted = end_date.strftime("%d.%m.%Y")
return f"✅ до {formatted} (ещё {days_left} дн.)" return f"{formatted} (Осталось {days_left} дней)"
async def get_username(self): async def get_username(self):
return f"@{self.me.username}" if self.me.username else "Нет" return f"@{self.me.username}" if self.me.username else "Нет"
@@ -245,8 +235,10 @@ class PlaceholdersMod(loader.Module):
async def get_dc_id(self): async def get_dc_id(self):
return str(self.me.dc_id if hasattr(self.me, "dc_id") else "Неизвестно") return str(self.me.dc_id if hasattr(self.me, "dc_id") else "Неизвестно")
async def get_stars(self): async def get_stars(self):
return f"{self.stars_balance:,}".replace(",", " ") if self.stars_balance else "0" result = await self.client(GetStarsStatusRequest("me"))
stars = result.balance.amount if result and result.balance else 0
return f"{stars:,}".replace(",", " ") if stars else "0"
async def get_usd_to_rub(self): async def get_usd_to_rub(self):
cache_key = "usd_rub" cache_key = "usd_rub"
@@ -261,7 +253,7 @@ class PlaceholdersMod(loader.Module):
result = f"1 USD ≈ {rate:.2f} RUB" result = f"1 USD ≈ {rate:.2f} RUB"
self.cache.set(cache_key, result) self.cache.set(cache_key, result)
return result return result
except Exception: except:
try: try:
async with self.session.get("https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@latest/v1/currencies/usd.json") as resp: async with self.session.get("https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@latest/v1/currencies/usd.json") as resp:
data = await resp.json() data = await resp.json()
@@ -269,7 +261,7 @@ class PlaceholdersMod(loader.Module):
result = f"1 USD ≈ {rate:.2f} RUB" result = f"1 USD ≈ {rate:.2f} RUB"
self.cache.set(cache_key, result) self.cache.set(cache_key, result)
return result return result
except Exception: except:
return "Курс USD недоступен" return "Курс USD недоступен"
async def get_rub_to_usd(self): async def get_rub_to_usd(self):
@@ -278,7 +270,7 @@ class PlaceholdersMod(loader.Module):
try: try:
rate = float(usd_rub.split("")[1].strip().split()[0]) rate = float(usd_rub.split("")[1].strip().split()[0])
return f"1 RUB ≈ {1/rate:.4f} USD" return f"1 RUB ≈ {1/rate:.4f} USD"
except Exception: except:
pass pass
return "Курс RUB недоступен" return "Курс RUB недоступен"
@@ -301,7 +293,7 @@ class PlaceholdersMod(loader.Module):
result = f"1 TON ≈ {rate:.2f} RUB" result = f"1 TON ≈ {rate:.2f} RUB"
self.cache.set(cache_key, result) self.cache.set(cache_key, result)
return result return result
except Exception: except:
return "Курс TON недоступен" return "Курс TON недоступен"
async def get_rub_to_ton(self): async def get_rub_to_ton(self):
@@ -310,7 +302,7 @@ class PlaceholdersMod(loader.Module):
try: try:
rate = float(ton_rub.split("")[1].strip().split()[0]) rate = float(ton_rub.split("")[1].strip().split()[0])
return f"1 RUB ≈ {1/rate:.6f} TON" return f"1 RUB ≈ {1/rate:.6f} TON"
except Exception: except:
pass pass
return "Курс недоступен" return "Курс недоступен"
@@ -327,7 +319,7 @@ class PlaceholdersMod(loader.Module):
result = f"1 BTC ≈ {rate:,.0f} RUB" result = f"1 BTC ≈ {rate:,.0f} RUB"
self.cache.set(cache_key, result) self.cache.set(cache_key, result)
return result return result
except Exception: except:
return "Курс BTC недоступен" return "Курс BTC недоступен"
async def get_eth_to_rub(self): async def get_eth_to_rub(self):
@@ -343,7 +335,7 @@ class PlaceholdersMod(loader.Module):
result = f"1 ETH ≈ {rate:,.0f} RUB" result = f"1 ETH ≈ {rate:,.0f} RUB"
self.cache.set(cache_key, result) self.cache.set(cache_key, result)
return result return result
except Exception: except:
return "Курс ETH недоступен" return "Курс ETH недоступен"
async def get_stars_to_rub(self): async def get_stars_to_rub(self):
@@ -373,7 +365,7 @@ class PlaceholdersMod(loader.Module):
sent_gb = net.bytes_sent // (1024**3) sent_gb = net.bytes_sent // (1024**3)
recv_gb = net.bytes_recv // (1024**3) recv_gb = net.bytes_recv // (1024**3)
return f"{sent_gb} GB │ ↓ {recv_gb} GB" return f"{sent_gb} GB │ ↓ {recv_gb} GB"
except Exception: except:
return "↑ 0 GB │ ↓ 0 GB" return "↑ 0 GB │ ↓ 0 GB"
async def get_speedtest(self): async def get_speedtest(self):
@@ -405,7 +397,7 @@ class PlaceholdersMod(loader.Module):
result = f"{speed_mbps:.1f} Mbps" result = f"{speed_mbps:.1f} Mbps"
self.cache.set(cache_key, result) self.cache.set(cache_key, result)
return result return result
except Exception: except:
continue continue
return "Тест скорости недоступен" return "Тест скорости недоступен"
@@ -426,7 +418,7 @@ class PlaceholdersMod(loader.Module):
used_gb = usage.used // (1024**3) used_gb = usage.used // (1024**3)
total_gb = usage.total // (1024**3) total_gb = usage.total // (1024**3)
return f"{used_gb} GB / {total_gb} GB ({percent:.1f}%)" return f"{used_gb} GB / {total_gb} GB ({percent:.1f}%)"
except Exception: except:
return "Диск недоступен" return "Диск недоступен"
async def get_local_ip(self): async def get_local_ip(self):
@@ -436,7 +428,7 @@ class PlaceholdersMod(loader.Module):
ip = s.getsockname()[0] ip = s.getsockname()[0]
s.close() s.close()
return ip return ip
except Exception: except:
return "Неизвестно" return "Неизвестно"
async def get_user_hostname(self): async def get_user_hostname(self):
@@ -507,7 +499,7 @@ class PlaceholdersMod(loader.Module):
} }
self.cache.set(cache_key, weather_data) self.cache.set(cache_key, weather_data)
return weather_data return weather_data
except Exception: except:
pass pass
default = { default = {
@@ -595,7 +587,7 @@ class PlaceholdersMod(loader.Module):
result = f"🎵 {stats['playcount']} скробблов" result = f"🎵 {stats['playcount']} скробблов"
self.cache.set(cache_key, result) self.cache.set(cache_key, result)
return result return result
except Exception: except:
pass pass
return "Статистика недоступна" return "Статистика недоступна"
@@ -637,14 +629,10 @@ class PlaceholdersMod(loader.Module):
} }
self.cache.set(cache_key, result) self.cache.set(cache_key, result)
return result return result
except Exception: except:
pass pass
return None return None
async def on_unload(self): async def on_unload(self):
utils.unregister_placeholders(self.__class__.__name__) await self.session.close()
try:
await self.session.close()
except Exception:
pass