Restrict betting system to Dota 2 only
This commit is contained in:
parent
dd3c993146
commit
2e3bd9bd99
5 changed files with 38 additions and 73 deletions
12
config.py
12
config.py
|
|
@ -35,13 +35,7 @@ ODDS_API_KEY = os.getenv("ODDS_API_KEY", "")
|
||||||
ODDS_API_BASE = "https://api.the-odds-api.com/v4"
|
ODDS_API_BASE = "https://api.the-odds-api.com/v4"
|
||||||
BET_MAX_AMOUNT = 3.0
|
BET_MAX_AMOUNT = 3.0
|
||||||
ODDS_SPORTS = {
|
ODDS_SPORTS = {
|
||||||
"epl": "soccer_epl",
|
"dota2": "esports_dota2",
|
||||||
"ucl": "soccer_uefa_champs_league",
|
|
||||||
"laliga": "soccer_spain_la_liga",
|
|
||||||
"bundesliga": "soccer_germany_bundesliga",
|
|
||||||
"seriea": "soccer_italy_serie_a",
|
|
||||||
"ligue1": "soccer_france_ligue_one",
|
|
||||||
"europa": "soccer_uefa_europa_league",
|
|
||||||
}
|
}
|
||||||
ODDS_CACHE_TTL = 86400 # 24 часа — экономим запросы (500/мес бесплатно)
|
ODDS_CACHE_TTL = 86400 # 24 часа — экономим запросы (500/мес бесплатно)
|
||||||
|
|
||||||
|
|
@ -219,8 +213,8 @@ def get_hint_text(templates_str: str) -> str:
|
||||||
"• /talk [текст] — ИИ базарит на фене.\n"
|
"• /talk [текст] — ИИ базарит на фене.\n"
|
||||||
"• /penis_casino [ставка] — казино на размер.\n"
|
"• /penis_casino [ставка] — казино на размер.\n"
|
||||||
"• /gadanie [тема] — гадание на фене с мемом.\n"
|
"• /gadanie [тема] — гадание на фене с мемом.\n"
|
||||||
"• /matches [epl|ucl|laliga|bundesliga|seriea|ligue1|europa] — матчи для ставок.\n"
|
"• /matches — матчи для ставок.\n"
|
||||||
"• /bet [лига] [номер] [исход] [ставка] — поставить см.\n"
|
"• /bet [номер] [исход] [ставка] — поставить.\n"
|
||||||
"• /mybets — мои активные ставки.\n"
|
"• /mybets — мои активные ставки.\n"
|
||||||
"• /bet_history — история ставок за месяц + статистика.\n"
|
"• /bet_history — история ставок за месяц + статистика.\n"
|
||||||
"• /sports_debug — диагностика API матчей.\n"
|
"• /sports_debug — диагностика API матчей.\n"
|
||||||
|
|
|
||||||
|
|
@ -248,21 +248,14 @@ def format_matches(matches: list[dict], sport_alias: str, sport_label: str) -> s
|
||||||
|
|
||||||
lines.append(f"{i}️⃣ {m['home']} vs {m['away']}{start_str}\n{odds_str}\n")
|
lines.append(f"{i}️⃣ {m['home']} vs {m['away']}{start_str}\n{odds_str}\n")
|
||||||
|
|
||||||
lines.append(f"Ставка: /bet {sport_alias} [номер] [исход] [ставка]")
|
lines.append("Ставка: /bet [номер] [исход] [ставка]")
|
||||||
lines.append(f"Коротко после /matches {sport_alias}: /bet [номер] [исход] [ставка]")
|
lines.append("Исход: 1/2. Можно писать ещё название команды или коэффициент.")
|
||||||
lines.append("Исход: 1/2, для ничьи X. Можно писать ещё название команды или коэффициент.")
|
|
||||||
return "\n".join(lines)
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
def _get_sport_label(key: str) -> str:
|
def _get_sport_label(key: str) -> str:
|
||||||
labels = {
|
labels = {
|
||||||
"epl": "⚽ EPL",
|
"dota2": "🎮 Dota 2",
|
||||||
"ucl": "⚽ Champions League",
|
|
||||||
"laliga": "⚽ La Liga",
|
|
||||||
"bundesliga": "⚽ Bundesliga",
|
|
||||||
"seriea": "⚽ Serie A",
|
|
||||||
"ligue1": "⚽ Ligue 1",
|
|
||||||
"europa": "⚽ Europa League",
|
|
||||||
}
|
}
|
||||||
return labels.get(key, key)
|
return labels.get(key, key)
|
||||||
|
|
||||||
|
|
|
||||||
55
main.py
55
main.py
|
|
@ -1461,37 +1461,17 @@ async def handle_gadanie_cmd(message: Message):
|
||||||
async def handle_matches_cmd(message: Message):
|
async def handle_matches_cmd(message: Message):
|
||||||
raw_text = message.text or ""
|
raw_text = message.text or ""
|
||||||
parts = raw_text.split(maxsplit=1)
|
parts = raw_text.split(maxsplit=1)
|
||||||
sport_alias = parts[1].strip().lower() if len(parts) > 1 else None
|
sport_alias = parts[1].strip().lower() if len(parts) > 1 else "dota2"
|
||||||
|
|
||||||
# Если лига не указана — показать список
|
|
||||||
if not sport_alias:
|
|
||||||
labels = {
|
|
||||||
"epl": "⚽ EPL (Англия)",
|
|
||||||
"ucl": "⚽ Champions League",
|
|
||||||
"laliga": "⚽ La Liga (Испания)",
|
|
||||||
"bundesliga": "⚽ Bundesliga (Германия)",
|
|
||||||
"seriea": "⚽ Serie A (Италия)",
|
|
||||||
"ligue1": "⚽ Ligue 1 (Франция)",
|
|
||||||
"europa": "⚽ Europa League",
|
|
||||||
}
|
|
||||||
lines = ["🏆 Доступные лиги для ставок:\n"]
|
|
||||||
for alias, name in labels.items():
|
|
||||||
lines.append(f" {name} → /matches {alias}")
|
|
||||||
lines.append("\nПример: /matches epl")
|
|
||||||
await message.reply("\n".join(lines), parse_mode=None)
|
|
||||||
return
|
|
||||||
|
|
||||||
if sport_alias not in config.ODDS_SPORTS:
|
if sport_alias not in config.ODDS_SPORTS:
|
||||||
if message.from_user:
|
if message.from_user:
|
||||||
clear_user_sport_context(message.from_user.id)
|
clear_user_sport_context(message.from_user.id)
|
||||||
available = " / ".join(config.ODDS_SPORTS.keys())
|
await message.reply("Неизвестная лига. Доступно: dota2", parse_mode=None)
|
||||||
await message.reply(f"Неизвестная лига. Доступно: {available}", parse_mode=None)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if message.from_user:
|
if message.from_user:
|
||||||
if sport_alias in config.ODDS_SPORTS:
|
|
||||||
remember_user_sport_context(message.from_user.id, sport_alias)
|
remember_user_sport_context(message.from_user.id, sport_alias)
|
||||||
else:
|
|
||||||
clear_user_sport_context(message.from_user.id)
|
|
||||||
await message.bot.send_chat_action(chat_id=message.chat.id, action="typing")
|
await message.bot.send_chat_action(chat_id=message.chat.id, action="typing")
|
||||||
result = await get_formatted_matches(sport_alias)
|
result = await get_formatted_matches(sport_alias)
|
||||||
await message.reply(result, parse_mode=None)
|
await message.reply(result, parse_mode=None)
|
||||||
|
|
@ -1504,41 +1484,34 @@ async def handle_bet_cmd(message: Message):
|
||||||
parts = raw_text.split()
|
parts = raw_text.split()
|
||||||
if len(parts) < 4:
|
if len(parts) < 4:
|
||||||
await message.reply(
|
await message.reply(
|
||||||
"Формат: /bet [спорт] [номер] [исход] [ставка]\n"
|
"Формат: /bet [номер] [исход] [ставка]\n"
|
||||||
"Коротко после /matches cs|dota|football: /bet [номер] [исход] [ставка]\n"
|
"Или: /bet dota2 [номер] [исход] [ставка]\n"
|
||||||
"Исход: 1/2, для ничьи X, можно ещё название команды или коэффициент.\n"
|
"Исход: 1/2. Можно писать ещё название команды или коэффициент.\n"
|
||||||
"Пример: /bet cs 1 1 0.5",
|
"Пример: /bet 1 1 0.5",
|
||||||
parse_mode=None,
|
parse_mode=None,
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
sport_alias: str | None
|
sport_alias: str
|
||||||
if parts[1].lower() in config.ODDS_SPORTS:
|
if parts[1].lower() == "dota2":
|
||||||
if len(parts) < 5:
|
if len(parts) < 5:
|
||||||
await message.reply(
|
await message.reply(
|
||||||
"Формат: /bet [спорт] [номер] [исход] [ставка]\nПример: /bet cs 1 1 0.5",
|
"Формат: /bet dota2 [номер] [исход] [ставка]\nПример: /bet dota2 1 1 0.5",
|
||||||
parse_mode=None,
|
parse_mode=None,
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
sport_alias = parts[1].lower()
|
sport_alias = "dota2"
|
||||||
index_token = parts[2]
|
index_token = parts[2]
|
||||||
selection = " ".join(parts[3:-1]).strip()
|
selection = " ".join(parts[3:-1]).strip()
|
||||||
amount_token = parts[-1]
|
amount_token = parts[-1]
|
||||||
else:
|
else:
|
||||||
sport_alias = get_user_sport_context(message.from_user.id)
|
sport_alias = "dota2"
|
||||||
if not sport_alias:
|
|
||||||
await message.reply(
|
|
||||||
"Сначала открой /matches с нужной лигой (epl, ucl, laliga...).\n"
|
|
||||||
"Либо пиши полный формат: /bet [спорт] [номер] [исход] [ставка]",
|
|
||||||
parse_mode=None,
|
|
||||||
)
|
|
||||||
return
|
|
||||||
index_token = parts[1]
|
index_token = parts[1]
|
||||||
selection = " ".join(parts[2:-1]).strip()
|
selection = " ".join(parts[2:-1]).strip()
|
||||||
amount_token = parts[-1]
|
amount_token = parts[-1]
|
||||||
|
|
||||||
if not selection:
|
if not selection:
|
||||||
await message.reply("Нужен исход: 1, 2, X, название команды или коэффициент.", parse_mode=None)
|
await message.reply("Нужен исход: 1, 2, название команды или коэффициент.", parse_mode=None)
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -174,13 +174,7 @@ async def get_profile(user: dict = Depends(get_current_user)) -> ProfileResponse
|
||||||
async def get_leagues() -> list[LeagueInfo]:
|
async def get_leagues() -> list[LeagueInfo]:
|
||||||
"""Список доступных лиг для ставок."""
|
"""Список доступных лиг для ставок."""
|
||||||
labels = {
|
labels = {
|
||||||
"epl": "⚽ EPL (Англия)",
|
"dota2": "🎮 Dota 2",
|
||||||
"ucl": "⚽ Champions League",
|
|
||||||
"laliga": "⚽ La Liga (Испания)",
|
|
||||||
"bundesliga": "⚽ Bundesliga (Германия)",
|
|
||||||
"seriea": "⚽ Serie A (Италия)",
|
|
||||||
"ligue1": "⚽ Ligue 1 (Франция)",
|
|
||||||
"europa": "⚽ Europa League",
|
|
||||||
}
|
}
|
||||||
return [
|
return [
|
||||||
LeagueInfo(alias=alias, name=labels.get(alias, alias), sport_key=key)
|
LeagueInfo(alias=alias, name=labels.get(alias, alias), sport_key=key)
|
||||||
|
|
|
||||||
|
|
@ -295,13 +295,17 @@ async function showBetHistory() {
|
||||||
|
|
||||||
async function renderBetting(data) {
|
async function renderBetting(data) {
|
||||||
if (data?.league) {
|
if (data?.league) {
|
||||||
return renderMatches(data.league, data.leagueName);
|
return renderMatches(data.league, data.leagueName, data.isOnlyLeague);
|
||||||
}
|
}
|
||||||
|
|
||||||
container.innerHTML = `<div class="section-header">⚽ Ставки на матчи</div>${skeleton(2)}`;
|
container.innerHTML = `<div class="section-header">⚽ Ставки на матчи</div>${skeleton(2)}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const leagues = await API.getLeagues();
|
const leagues = await API.getLeagues();
|
||||||
|
if (leagues.length === 1) {
|
||||||
|
return renderMatches(leagues[0].alias, leagues[0].name, true);
|
||||||
|
}
|
||||||
|
|
||||||
container.innerHTML = `
|
container.innerHTML = `
|
||||||
<div class="section-header">⚽ Выбери лигу</div>
|
<div class="section-header">⚽ Выбери лигу</div>
|
||||||
<div class="league-list" id="league-list"></div>
|
<div class="league-list" id="league-list"></div>
|
||||||
|
|
@ -317,7 +321,7 @@ async function renderBetting(data) {
|
||||||
`);
|
`);
|
||||||
item.addEventListener('click', () => {
|
item.addEventListener('click', () => {
|
||||||
haptic();
|
haptic();
|
||||||
navigate('betting', { league: l.alias, leagueName: l.name });
|
navigate('betting', { league: l.alias, leagueName: l.name, isOnlyLeague: false });
|
||||||
});
|
});
|
||||||
list.appendChild(item);
|
list.appendChild(item);
|
||||||
});
|
});
|
||||||
|
|
@ -326,15 +330,22 @@ async function renderBetting(data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function renderMatches(league, leagueName) {
|
async function renderMatches(league, leagueName, isOnlyLeague = false) {
|
||||||
|
const headerText = isOnlyLeague ? '🎮 Dota 2 Матчи' : leagueName;
|
||||||
|
const backTarget = isOnlyLeague ? 'home' : 'betting';
|
||||||
|
const instructionsHtml = isOnlyLeague
|
||||||
|
? `<div style="font-size:13px;color:var(--text-secondary);margin-bottom:12px">Ставки на актуальные матчи Dota 2. Выберите исход и укажите сумму ставки в сантиметрах.</div>`
|
||||||
|
: '';
|
||||||
|
|
||||||
container.innerHTML = `
|
container.innerHTML = `
|
||||||
<div style="display:flex;align-items:center;gap:8px;margin-bottom:16px">
|
<div style="display:flex;align-items:center;gap:8px;margin-bottom:16px">
|
||||||
<button class="btn btn-secondary btn-sm" id="back-btn" style="width:auto;padding:8px 12px">← Назад</button>
|
<button class="btn btn-secondary btn-sm" id="back-btn" style="width:auto;padding:8px 12px">← Назад</button>
|
||||||
<div class="section-header" style="margin:0">${leagueName}</div>
|
<div class="section-header" style="margin:0">${headerText}</div>
|
||||||
</div>
|
</div>
|
||||||
|
${instructionsHtml}
|
||||||
${skeleton(3)}
|
${skeleton(3)}
|
||||||
`;
|
`;
|
||||||
document.getElementById('back-btn').onclick = () => navigate('betting');
|
document.getElementById('back-btn').onclick = () => navigate(backTarget);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const matches = await API.getMatches(league);
|
const matches = await API.getMatches(league);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue