FEAT: Added Twitch module (can't check if it's working yet due to a sync issue)
FIX: Added the needed changes to the code for the new module
This commit is contained in:
parent
49a7588699
commit
bd318a7815
@ -6,12 +6,18 @@ load_dotenv()
|
|||||||
config = {
|
config = {
|
||||||
'DISCORD_TOKEN': os.getenv('DISCORD_TOKEN'),
|
'DISCORD_TOKEN': os.getenv('DISCORD_TOKEN'),
|
||||||
'GUILD_ID': int(os.getenv('DISCORD_GUILD_ID')),
|
'GUILD_ID': int(os.getenv('DISCORD_GUILD_ID')),
|
||||||
|
'DISCORD_CHANNEL_ID': int(os.getenv('DISCORD_CHANNEL_ID')),
|
||||||
|
'TWITCH_CLIENT_ID': os.getenv('TWITCH_CLIENT_ID'),
|
||||||
|
'TWITCH_CLIENT_SECRET': os.getenv('TWITCH_CLIENT_SECRET'),
|
||||||
'modules': {
|
'modules': {
|
||||||
'currency': {
|
'currency': {
|
||||||
'enabled': True
|
'enabled': True
|
||||||
},
|
},
|
||||||
'xp': {
|
'xp': {
|
||||||
'enabled': True
|
'enabled': True
|
||||||
|
},
|
||||||
|
'twitch': {
|
||||||
|
'enabled': True
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
13
main.py
13
main.py
@ -3,9 +3,11 @@ from config import config
|
|||||||
|
|
||||||
TOKEN = config['DISCORD_TOKEN']
|
TOKEN = config['DISCORD_TOKEN']
|
||||||
GUILD_ID = config['GUILD_ID']
|
GUILD_ID = config['GUILD_ID']
|
||||||
|
DISCORD_CHANNEL_ID = config['DISCORD_CHANNEL_ID']
|
||||||
|
|
||||||
intents = discord.Intents.default()
|
intents = discord.Intents.default()
|
||||||
intents.messages = True
|
intents.messages = True
|
||||||
|
guild = discord.Object(id=GUILD_ID)
|
||||||
|
|
||||||
|
|
||||||
class Selena(discord.Client):
|
class Selena(discord.Client):
|
||||||
@ -25,11 +27,14 @@ class Selena(discord.Client):
|
|||||||
xp = XP(self)
|
xp = XP(self)
|
||||||
xp.setup(self.tree)
|
xp.setup(self.tree)
|
||||||
|
|
||||||
|
if config['modules']['twitch']['enabled']:
|
||||||
|
from modules.social.twitch import Twitch
|
||||||
|
twitch = Twitch(self)
|
||||||
|
twitch.setup(self.tree)
|
||||||
|
|
||||||
async def setup_hook(self):
|
async def setup_hook(self):
|
||||||
self.tree.copy_global_to(guild=discord.Object(id=GUILD_ID))
|
self.tree.copy_global_to(guild=guild)
|
||||||
await self.tree.sync(guild=discord.Object(id=GUILD_ID))
|
await self.tree.sync(guild=guild)
|
||||||
# Force sync for all commands
|
|
||||||
await self.tree.sync()
|
|
||||||
|
|
||||||
|
|
||||||
bot = Selena()
|
bot = Selena()
|
||||||
|
127
modules/social/twitch.py
Normal file
127
modules/social/twitch.py
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
import discord
|
||||||
|
from discord import app_commands
|
||||||
|
import sqlite3
|
||||||
|
import aiohttp
|
||||||
|
import asyncio
|
||||||
|
from config import config
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
|
|
||||||
|
class Twitch:
|
||||||
|
def __init__(self, bot):
|
||||||
|
self.bot = bot
|
||||||
|
self.db_path = 'data/selena.db'
|
||||||
|
self.client_id = config['TWITCH_CLIENT_ID']
|
||||||
|
self.client_secret = config['TWITCH_CLIENT_SECRET']
|
||||||
|
self._init_db()
|
||||||
|
self.live_channels = set()
|
||||||
|
self.token = None
|
||||||
|
self.token_expiry = datetime.utcnow()
|
||||||
|
|
||||||
|
def _init_db(self):
|
||||||
|
with sqlite3.connect(self.db_path) as conn:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute('''
|
||||||
|
CREATE TABLE IF NOT EXISTS twitch_channels (
|
||||||
|
channel_name TEXT PRIMARY KEY
|
||||||
|
)
|
||||||
|
''')
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
async def fetch_twitch_token(self):
|
||||||
|
if self.token and datetime.utcnow() < self.token_expiry:
|
||||||
|
return self.token
|
||||||
|
|
||||||
|
async with aiohttp.ClientSession() as session:
|
||||||
|
async with session.post('https://id.twitch.tv/oauth2/token', params={
|
||||||
|
'client_id': self.client_id,
|
||||||
|
'client_secret': self.client_secret,
|
||||||
|
'grant_type': 'client_credentials'
|
||||||
|
}) as response:
|
||||||
|
data = await response.json()
|
||||||
|
self.token = data['access_token']
|
||||||
|
self.token_expiry = datetime.utcnow() + timedelta(seconds=data['expires_in'])
|
||||||
|
return self.token
|
||||||
|
|
||||||
|
async def fetch_twitch_channel(self, channel_name):
|
||||||
|
token = await self.fetch_titch_token()
|
||||||
|
async with aiohttp.ClientSession() as session:
|
||||||
|
async with session.get('https://api.twitch.tv/helix/users', headers={
|
||||||
|
'Client-ID': self.client_id,
|
||||||
|
'Authorization': f'Bearer {token}'
|
||||||
|
}, params={'login': channel_name}) as response:
|
||||||
|
data = await response.json()
|
||||||
|
if data['data']:
|
||||||
|
return data['data'][0]
|
||||||
|
return None
|
||||||
|
|
||||||
|
async def fetch_stream_status(self, user_id):
|
||||||
|
token = await self.fetch_twitch_token()
|
||||||
|
async with aiohttp.ClientSession() as session:
|
||||||
|
async with session.get('https://api.twitch.tv/helix/streams', headers={
|
||||||
|
'Client-ID': self.client_id,
|
||||||
|
'Authorization': f'Bearer {token}'
|
||||||
|
}, params={'user_id': user_id}) as response:
|
||||||
|
data = await response.json()
|
||||||
|
if data['data']:
|
||||||
|
return data['data'][0]
|
||||||
|
return None
|
||||||
|
|
||||||
|
async def check_live_status(self):
|
||||||
|
with sqlite3.connect(self.db_path) as conn:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute('SELECT channel_name FROM twitch_channels')
|
||||||
|
channels = cursor.fetchall()
|
||||||
|
|
||||||
|
for (channel_name,) in channels:
|
||||||
|
channel = await self.fetch_twitch_channel(channel_name)
|
||||||
|
if channel:
|
||||||
|
stream = await self.fetch_stream_status(channel['id'])
|
||||||
|
if stream and channel_name not in self.live_channels:
|
||||||
|
self.live_channels.add(channel_name)
|
||||||
|
discord_channel = self.bot.get_channel(config['DISCORD_CHANNEL_ID'])
|
||||||
|
await discord_channel.send(f'{channel_name} is now live on Twitch!')
|
||||||
|
elif not stream and channel_name in self.live_channels:
|
||||||
|
self.live_channels.remove(channel_name)
|
||||||
|
|
||||||
|
@app_commands.command(name='add_twitch_channel', description='Follow a new Twitch channel')
|
||||||
|
async def add_twitch_channel(self, interaction: discord.Interaction, channel_name: str):
|
||||||
|
with sqlite3.connect(self.db_path) as conn:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute('INSERT OR IGNORE INTO twitch_channels (channel_name) VALUES (?)', (channel_name,))
|
||||||
|
conn.commit()
|
||||||
|
await interaction.response.send_message(f'Added {channel_name} to the followed Twitch channels.')
|
||||||
|
|
||||||
|
@app_commands.command(name='remove_twitch_channel', description='Unfollow a Twitch channel')
|
||||||
|
async def remove_twitch_channel(self, interaction: discord.Interaction, channel_name: str):
|
||||||
|
with sqlite3.connect(self.db_path) as conn:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute('DELETE FROM twitch_channels WHERE channel_name = ?', (channel_name,))
|
||||||
|
conn.commit()
|
||||||
|
await interaction.response.send_message(f'Removed {channel_name} from the followed Twitch channels.')
|
||||||
|
|
||||||
|
@app_commands.command(name='check_twitch_channel', description='Check if a Twitch channel is live')
|
||||||
|
async def check_twitch_channel(self, interaction: discord.Interaction, channel_name: str):
|
||||||
|
channel = await self.fetch_twitch_channel(channel_name)
|
||||||
|
if channel:
|
||||||
|
stream = await self.fetch_stream_status(channel['id'])
|
||||||
|
if stream:
|
||||||
|
await interaction.response.send_message(f'{channel_name} is currently live on Twitch!')
|
||||||
|
else:
|
||||||
|
await interaction.response.send_message(f'{channel_name} is not live on Twitch.')
|
||||||
|
else:
|
||||||
|
await interaction.response.send_message(f'Could not find Twitch channel: {channel_name}')
|
||||||
|
|
||||||
|
async def start_checking_live_status(self):
|
||||||
|
while True:
|
||||||
|
await self.check_live_status()
|
||||||
|
await asyncio.sleep(60)
|
||||||
|
|
||||||
|
def setup(self, tree):
|
||||||
|
tree.add_command(self.add_twitch_channel)
|
||||||
|
tree.add_command(self.remove_twitch_channel)
|
||||||
|
tree.add_command(self.check_twitch_channel)
|
||||||
|
|
||||||
|
|
||||||
|
def setup(bot):
|
||||||
|
bot.tree.add_cog(Twitch(bot))
|
Loading…
x
Reference in New Issue
Block a user