television/src/discordbot/discordbot.py

119 lines
No EOL
4.1 KiB
Python

import asyncio
import os
import requests
import discord
from discord.ext import commands, tasks
from datetime import datetime
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.jobstores.base import JobLookupError
import logging
# Read env variables
bot_token = os.environ.get('DISCORDBOT_TOKEN', 'token')
live_channel_id = os.environ.get('DISCORDBOT_LIVE_CHANNEL_ID', 0)
scheduler_hostname = os.environ.get('SCHEDULER_API_HOSTNAME', 'tv.example.com')
# Discord API Intents
intents = discord.Intents.all()
intents.members = True
intents.guilds = True
intents.messages = True
intents.reactions = True
intents.presences = True
intents.message_content = True
# Discord client
bot = commands.Bot(command_prefix="!", intents=intents)
# Scheduler
scheduler = AsyncIOScheduler()
# Set up the logger
logger_discord = logging.getLogger('discord')
log_level = os.environ.get('SCHEDULER_LOG_LEVEL', 'INFO').upper()
logger_discord.setLevel(log_level)
database = {}
# Bot functions
@bot.event
async def on_ready():
# Schedule a database update to run every 5 seconds
scheduler.add_job(func=update_database, trigger='interval', seconds=5, id='update_database')
scheduler.start()
@bot.command(name='hello')
async def hello(ctx):
author_name = ctx.author.name
await ctx.channel.send(f'hi, {author_name}! >^.^<')
@bot.command(name='epg')
async def epg(ctx):
global database
await ctx.channel.send('epg:')
if database != {}:
scheduled_list = ""
live_list = ""
for key, value in database.items():
item_name = value['name']
item_start = value['start_at']
if item_start != 'now' and item_start != 'never':
scheduled_list += f'- {item_name} starts at {item_start}:00 UTC\n'
else:
live_list += f'- {item_name} is LIVE\n'
epg_list = live_list + scheduled_list
await ctx.channel.send(f'```{epg_list}```')
else:
await ctx.channel.send('Empty database!')
@bot.command(name='time')
async def time(ctx):
await ctx.channel.send(f'The time is: {datetime.now()} UTC')
# Helper functions
async def update_database():
global database
db_url = f'https://{scheduler_hostname}/database'
if requests.get(db_url).status_code == 200:
response = requests.get(db_url)
response.raise_for_status()
database = response.json()
else:
logger_discord.error('Cannot connect to the database!')
return
# Search for live streams
if database != {}:
for key, value in database.items():
stream_name = value['name']
stream_start_at = value['start_at']
if stream_start_at == 'now':
# Check if the job already exists
if scheduler.get_job('announce_live_channel') is None:
# Job doesn't exist, so add it
logger_discord.info(f'{stream_name} live stream detected!')
scheduler.add_job(func=announce_live_channel, trigger='interval', seconds=60, id='announce_live_channel', args=(stream_name,))
# Manually execute the job once immediately
scheduler.get_job('announce_live_channel').modify(next_run_time=datetime.now())
# Exit since we found one
return
else:
# Exit since we already have a announcement job
return
# Cleanup the announce job
if scheduler.get_job('announce_live_channel') is not None:
scheduler.remove_job('announce_live_channel')
logger_discord.info(f'Live stream is offline.')
if live_channel_id != 0:
update_channel = bot.get_channel(live_channel_id)
await update_channel.send('Live stream is offline.')
async def announce_live_channel(stream_name):
logger_discord.info(f'{stream_name} is live!')
if live_channel_id != 0:
live_channel = bot.get_channel(live_channel_id)
await live_channel.send(f'{stream_name} is live!')
# Run the bot with your token
asyncio.run(bot.run(bot_token))