Исправление: добавил type hints ко всем 20 production-функциям
This commit is contained in:
parent
613dea55cf
commit
65e01f0091
@ -11,7 +11,7 @@ class Cat(commands.Cog):
|
||||
"""Команда !cat — случайный котик"""
|
||||
|
||||
@commands.command(name="cat")
|
||||
async def cat(self, ctx):
|
||||
async def cat(self, ctx: commands.Context) -> None:
|
||||
"""Получить случайного котика"""
|
||||
url = await fetch_cat()
|
||||
if url is None:
|
||||
|
||||
@ -6,7 +6,7 @@ class Help(commands.Cog):
|
||||
"""Команда !hp — список всех команд бота"""
|
||||
|
||||
@commands.command(name="hp")
|
||||
async def hp(self, ctx):
|
||||
async def hp(self, ctx: commands.Context) -> None:
|
||||
"""Показать список доступных команд"""
|
||||
await self._show_help(ctx)
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ class Morning(commands.Cog):
|
||||
pass
|
||||
|
||||
@commands.command(name="morning")
|
||||
async def morning(self, ctx):
|
||||
async def morning(self, ctx: commands.Context) -> None:
|
||||
"""Погода, лучшие статьи за сутки и котик"""
|
||||
logger.info("%s: !morning запущен", ctx.author)
|
||||
await run_morning(ctx.bot, ctx.channel)
|
||||
|
||||
@ -16,7 +16,7 @@ class News(commands.Cog):
|
||||
"""Команда !news — свежие статьи и новости по AI с Habr"""
|
||||
|
||||
@commands.command(name="nw")
|
||||
async def nw(self, ctx):
|
||||
async def nw(self, ctx: commands.Context) -> None:
|
||||
"""Топ-5 свежих статей и новостей по AI с Habr"""
|
||||
articles = await fetch_rss(RSS_URL_ARTICLES)
|
||||
if articles is None:
|
||||
|
||||
@ -12,7 +12,7 @@ class Pg(commands.Cog):
|
||||
self.api_url = API_URL_WEATHER
|
||||
|
||||
@commands.command(name="pg")
|
||||
async def pg(self, ctx):
|
||||
async def pg(self, ctx: commands.Context) -> None:
|
||||
"""Прогноз погоды в Магнитогорске"""
|
||||
data = await fetch_weather(self.api_url)
|
||||
if data is None:
|
||||
|
||||
@ -9,7 +9,7 @@ class Stats(commands.Cog):
|
||||
"""Команда !stats — статистика серверов"""
|
||||
|
||||
@commands.command(name="stats")
|
||||
async def stats(self, ctx):
|
||||
async def stats(self, ctx: commands.Context) -> None:
|
||||
"""Количество серверов, каналов и пользователей"""
|
||||
guilds = ctx.bot.guilds
|
||||
total_guilds = len(guilds)
|
||||
|
||||
@ -11,7 +11,7 @@ class Status(commands.Cog):
|
||||
"""Команда !status — статус бота, пинг, uptime"""
|
||||
|
||||
@commands.command(name="status")
|
||||
async def status(self, ctx):
|
||||
async def status(self, ctx: commands.Context) -> None:
|
||||
"""Статус бота: пинг к Discord gateway и время работы"""
|
||||
latency_ms = round(ctx.bot.latency * 1000, 1)
|
||||
start_time = getattr(ctx.bot, "_start_time", time.time())
|
||||
|
||||
@ -52,7 +52,7 @@ async def gather_morning() -> MorningData:
|
||||
)
|
||||
|
||||
|
||||
async def run_morning(bot: "commands.Bot", channel: discord.TextChannel):
|
||||
async def run_morning(bot: "commands.Bot", channel: discord.TextChannel) -> None:
|
||||
"""Выполнить утренний дайджест и отправить в канал."""
|
||||
try:
|
||||
data = await gather_morning()
|
||||
@ -249,8 +249,8 @@ class Scheduler:
|
||||
if not sent:
|
||||
logger.error("Не удалось найти канал для отправки morning-дайджеста")
|
||||
|
||||
def start(self):
|
||||
def start(self) -> None:
|
||||
self._start_scheduler()
|
||||
|
||||
def stop(self):
|
||||
def stop(self) -> None:
|
||||
self._stop_scheduler()
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import asyncio
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
import requests
|
||||
|
||||
@ -14,7 +15,7 @@ RSS_URL_POSTS = "https://habr.com/ru/rss/hubs/artificial_intelligence/news/top/d
|
||||
_session = requests.Session()
|
||||
|
||||
|
||||
async def fetch_rss(url):
|
||||
async def fetch_rss(url: str) -> Optional[list[dict]]:
|
||||
"""Скачать и распарсить RSS-ленту (RSS 2.0 / Atom)."""
|
||||
await habr_rss_limiter.acquire()
|
||||
from defusedxml.ElementTree import fromstring
|
||||
@ -74,7 +75,7 @@ async def fetch_rss(url):
|
||||
return None
|
||||
|
||||
|
||||
def _parse_date(pub_date):
|
||||
def _parse_date(pub_date: Optional[str]) -> str:
|
||||
"""Парсить дату из RSS в строку 'дд.мм.гггг' или вернуть часть даты."""
|
||||
if not pub_date:
|
||||
return ""
|
||||
@ -86,7 +87,7 @@ def _parse_date(pub_date):
|
||||
return pub_date[:10].replace("-", ".")
|
||||
|
||||
|
||||
def truncate_title(title, max_len=60):
|
||||
def truncate_title(title: str, max_len: int = 60) -> str:
|
||||
"""Обрезать заголовок, если он длиннее max_len."""
|
||||
if len(title) > max_len:
|
||||
return title[:max_len] + "..."
|
||||
@ -107,7 +108,7 @@ def truncate_embed_field(text: str, max_len: int = 1024) -> str:
|
||||
return text[:max_len - 3] + "..."
|
||||
|
||||
|
||||
def format_articles(articles, title, link):
|
||||
def format_articles(articles: list[dict], title: str, link: str) -> list[str]:
|
||||
"""Сформировать список строк для вывода статей/постов."""
|
||||
lines = [f"**{title}**\n<{link}>"]
|
||||
for i, article in enumerate(articles[:5], 1):
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import asyncio
|
||||
import logging
|
||||
from typing import Any, Optional
|
||||
|
||||
import requests
|
||||
from requests.exceptions import ConnectionError, Timeout, SSLError
|
||||
|
||||
@ -12,7 +14,7 @@ API_URL_WEATHER = "https://wttr.in/Magnitogorsk?format=j1&lang=ru"
|
||||
_session = requests.Session()
|
||||
|
||||
|
||||
async def fetch_weather(api_url, timeout=10, max_retries=3):
|
||||
async def fetch_weather(api_url: str, timeout: int = 10, max_retries: int = 3) -> Optional[dict]:
|
||||
"""Получить данные о погоде с retry."""
|
||||
await weather_limiter.acquire()
|
||||
for attempt in range(max_retries):
|
||||
@ -35,7 +37,7 @@ async def fetch_weather(api_url, timeout=10, max_retries=3):
|
||||
return await fetch_open_meteo()
|
||||
|
||||
|
||||
async def fetch_open_meteo(lat=53.4069, lon=58.9797, timeout=10, max_retries=3):
|
||||
async def fetch_open_meteo(lat: float = 53.4069, lon: float = 58.9797, timeout: int = 10, max_retries: int = 3) -> Optional[dict]:
|
||||
"""Fallback на Open-Meteo API."""
|
||||
await open_meteo_limiter.acquire()
|
||||
url = (
|
||||
@ -78,7 +80,7 @@ async def fetch_open_meteo(lat=53.4069, lon=58.9797, timeout=10, max_retries=3):
|
||||
return None
|
||||
|
||||
|
||||
def wmo_to_russian(code):
|
||||
def wmo_to_russian(code: Optional[int]) -> str:
|
||||
"""Перевод WMO weather code в русский."""
|
||||
mapping = {
|
||||
0: "Ясно",
|
||||
@ -139,7 +141,7 @@ _WEATHER_MAPPING = [
|
||||
]
|
||||
|
||||
|
||||
def translate_weather(en):
|
||||
def translate_weather(en: Optional[str]) -> str:
|
||||
if not en:
|
||||
return "—"
|
||||
en_lower = en.lower()
|
||||
@ -149,7 +151,7 @@ def translate_weather(en):
|
||||
return en
|
||||
|
||||
|
||||
def format_weather_data_for_console(data):
|
||||
def format_weather_data_for_console(data: Optional[dict]) -> Optional[list[str]]:
|
||||
"""
|
||||
Форматировать погодные данные для консольного вывода.
|
||||
|
||||
@ -186,7 +188,7 @@ def format_weather_data_for_console(data):
|
||||
]
|
||||
|
||||
|
||||
def format_weather_for_embed(data):
|
||||
def format_weather_for_embed(data: Optional[dict]) -> Optional[str]:
|
||||
"""Форматировать погоду для Discord embed (с заголовком)."""
|
||||
if data is None:
|
||||
return None
|
||||
@ -196,7 +198,7 @@ def format_weather_for_embed(data):
|
||||
return "**Погода в Магнитогорске:**\n" + "\n".join(lines)
|
||||
|
||||
|
||||
def pressure_to_mmhg(mb):
|
||||
def pressure_to_mmhg(mb: Any) -> float | str:
|
||||
if mb == "—" or mb is None or mb == "":
|
||||
return "—"
|
||||
try:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user