import discord
import os
import json
from discord.ext import commands, tasks
from discord import app_commands
from discord.ui import Modal, TextInput, Button, View
from datetime import datetime, timedelta, timezone
intents = discord.Intents.default()
intents.messages = True
intents.message_content = True
intents.guilds = True
intents.members = True
bot = commands.Bot(command_prefix="!", intents=intents)
ADMIN_ROLES = [1280090992581546026, 1222928883251150940]
TOKEN = 'byebye'
class SubscriptionBot(commands.Bot):
def __init__(self):
super().__init__(command_prefix='/', intents=intents)
self.synced = False
self.subscriptions = self.load_subscriptions()
def load_subscriptions(self):
try:
with open('subscriptions.json', 'r') as f:
return json.load(f)
except FileNotFoundError:
return {}
def save_subscriptions(self):
with open('subscriptions.json', 'w') as f:
json.dump(self.subscriptions, f)
@tasks.loop(minutes=1)
async def check_expired_subscriptions(self):
now = datetime.now(timezone.utc).timestamp()
for user_id, user_subs in list(self.subscriptions.items()):
for sub in user_subs[:]:
if sub['expiration'] <= now:
guild = self.guilds[0]
member = guild.get_member(int(user_id))
role = guild.get_role(sub['role_id'])
if member and role:
await member.remove_roles(role)
user_subs.remove(sub)
user = await self.fetch_user(int(user_id))
embed = discord.Embed(
title="Подписка истекла",
description=f"Ваша подписка на роль {role.name} истекла",
color=discord.Color.red()
)
embed.set_thumbnail(url=user.avatar.url)
await user.send(embed=embed)
if not user_subs:
del self.subscriptions[user_id]
self.save_subscriptions()
bot = SubscriptionBot()
@bot.tree.command(name="sub", description="Выдать роль пользователю на определенное время")
@app_commands.describe(
user="Пользователь, которому выдается роль",
role="Роль, которую нужно выдать",
duration="Длительность подписки (например, 30d для 30 дней, 24h для 24 часов, 60m для 60 минут)"
)
async def sub(interaction: discord.Interaction, user: discord.Member, role: discord.Role, duration: str):
if any(role.id in ADMIN_ROLES for role in interaction.user.roles):
duration_units = {'d': 'days', 'h': 'hours', 'm': 'minutes'}
amount = int(duration[:-1])
unit = duration_units.get(duration[-1])
if not unit:
await interaction.response.send_message("Неверный формат длительности. Используйте 'd' для дней, 'h' для часов или 'm' для минут.", ephemeral=True)
return
expiration_time = datetime.now(timezone.utc) + timedelta(**{unit: amount})
expiration_timestamp = int(expiration_time.timestamp())
await user.add_roles(role)
user_id = str(user.id)
if user_id not in bot.subscriptions:
bot.subscriptions[user_id] = []
bot.subscriptions[user_id].append({
'role_id': role.id,
'expiration': expiration_timestamp
})
bot.save_subscriptions()
embed = discord.Embed(
title="Подписка оформлена",
description=f"Вы оформили подписку {role.name}. Она истечёт <t:{expiration_timestamp}:R>",
color=discord.Color.green()
)
embed.set_thumbnail(url=user.avatar.url)
await user.send(embed=embed)
await interaction.response.send_message(f"Подписка для {user.name} на роль {role.name} успешно оформлена.", ephemeral=True)
else:
await interaction.response.send_message("У вас нет прав для использования этой команды.", ephemeral=True)
@bot.tree.command(name="sub_list", description="Показать список ваших активных подписок")
async def sub_list(interaction: discord.Interaction):
user_id = str(interaction.user.id)
if user_id not in bot.subscriptions or not bot.subscriptions[user_id]:
await interaction.response.send_message("У вас нет активных подписок.", ephemeral=True)
return
embed = discord.Embed(
title="Ваши активные подписки",
color=discord.Color.blue()
)
embed.set_thumbnail(url=interaction.user.avatar.url)
for sub in bot.subscriptions[user_id]:
role = interaction.guild.get_role(sub['role_id'])
if role:
embed.add_field(
name=role.name,
value=f"Истекает <t:{sub['expiration']}:R>",
inline=False
)
await interaction.response.send_message(embed=embed, ephemeral=True)
@bot.event
async def on_ready():
# Первый блок on_ready
await bot.wait_until_ready()
if not bot.synced:
await bot.tree.sync()
bot.synced = True
print(f'Подписки синхронизированы!')
bot.check_expired_subscriptions.start()
bot.run(TOKEN)
Запуская код на ПК и имея небольшую базу данных, которую он сохраняет всё работает отлично, но когда я ставлю его на хостинг он выдаёт роли по команде, но не снимает их по истечению времени как должно быть, хотя в хранилще опечаток не имеется. В чём может быть проблема в коде или на хостинге и как собственно от неё избавится?