Skip to content

Commit 57e3c24

Browse files
committed
CORE
0 parents  commit 57e3c24

File tree

6 files changed

+429
-0
lines changed

6 files changed

+429
-0
lines changed

PyBot/API/Youtube.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import requests
2+
import json
3+
4+
class Youtube:
5+
def __init__(self, api_key):
6+
self.api_key = api_key
7+
self.base_url = "https://www.googleapis.com/youtube/v3/"
8+
9+
def search(self, query, max_results=10):
10+
url = f"{self.base_url}search"
11+
params = {
12+
"part": "snippet",
13+
"q": query,
14+
"key": self.api_key,
15+
"maxResults": max_results,
16+
"type": "video"
17+
}
18+
response = requests.get(url, params=params)
19+
response.raise_for_status()
20+
return response.json()
21+
22+
def get_video_info(self, video_id):
23+
url = f"{self.base_url}videos"
24+
params = {
25+
"part": "snippet,statistics",
26+
"id": video_id,
27+
"key": self.api_key
28+
}
29+
response = requests.get(url, params=params)
30+
response.raise_for_status()
31+
return response.json()
32+
33+
def get_channel_info(self, channel_id):
34+
url = f"{self.base_url}channels"
35+
params = {
36+
"part": "snippet,statistics",
37+
"id": channel_id,
38+
"key": self.api_key
39+
}
40+
response = requests.get(url, params=params)
41+
response.raise_for_status()
42+
return response.json()

PyBot/Discord/Discord.py

Whitespace-only changes.

PyBot/__init__.py

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
# __init__.py
2+
import discord
3+
from discord.ext import commands
4+
from discord import app_commands
5+
from typing import Optional, Callable, Any, List
6+
import PyBot.utils.token_utils as token_utils
7+
import PyBot.utils.embed_utils as embed_utils
8+
import PyBot.utils.webhook_utils as webhook_utils
9+
10+
token = None # Placeholder for the token, to be set later
11+
12+
class PyBot(commands.Bot):
13+
def __init__(self, command_prefix='!'):
14+
if command_prefix == "/":
15+
raise ValueError("Command prefix cannot be '/' as it is reserved for slash commands. Use a different prefix or no prefix at all. it is buggy and not recommended.")
16+
intents = discord.Intents.default()
17+
intents.message_content = True
18+
super().__init__(command_prefix=command_prefix, intents=intents)
19+
self.bot = self # For compatibility with older code
20+
21+
if not self.tree:
22+
# discord.py 2.0+ requires a CommandTree for slash commands
23+
self.tree = app_commands.CommandTree(self)
24+
self._token = None
25+
26+
# === Lifecycle Events ===
27+
async def setup_hook(self) -> None:
28+
"""Initial setup after the bot is ready."""
29+
await self.tree.sync()
30+
print("Commands synced with Discord!")
31+
if hasattr(self, 'hook') and self.hook.on_setup_hook:
32+
await self.hook.on_setup_hook()
33+
34+
async def on_ready(self):
35+
print(f'Logged in as {self.user} (ID: {self.user.id})')
36+
print('------')
37+
if hasattr(self, 'hook') and self.hook.on_ready:
38+
await self.hook.on_ready()
39+
40+
async def on_command_error(self, ctx, error):
41+
await ctx.send(f"An error occurred: {error}")
42+
if hasattr(self, 'hook') and self.hook.on_command_error:
43+
await self.hook.on_command_error(ctx, error)
44+
45+
async def on_interaction(self, interaction: discord.Interaction):
46+
"""Handle interactions, such as slash commands."""
47+
if interaction.type == discord.InteractionType.application_command:
48+
await self.tree.process_interaction(interaction)
49+
if hasattr(self, 'hook') and self.hook.on_interaction:
50+
await self.hook.on_interaction(interaction)
51+
52+
async def on_message(self, message: discord.Message):
53+
"""Handle messages sent in channels."""
54+
if message.author == self.user:
55+
return
56+
await self.process_commands(message)
57+
if hasattr(self, 'hook') and self.hook.on_message:
58+
await self.hook.on_message(message)
59+
60+
async def on_disconnect(self):
61+
"""Handle bot disconnection."""
62+
print("Bot has disconnected.")
63+
if hasattr(self, 'hook') and self.hook.on_disconnect:
64+
await self.hook.on_disconnect()
65+
66+
async def on_connect(self):
67+
"""Handle bot connection."""
68+
print("Bot has connected.")
69+
if hasattr(self, 'hook') and self.hook.on_connect:
70+
await self.hook.on_connect()
71+
72+
def run(self, new_token: Optional[str] = None):
73+
"""Run the bot with the provided token."""
74+
global token
75+
76+
# Priority: passed token > instance token > global token
77+
running_token = new_token or self._token or token
78+
79+
if running_token is None:
80+
raise ValueError("Token is not set. Please load a token before running the bot.")
81+
82+
# Update all token references
83+
self._token = running_token
84+
token = running_token
85+
86+
super().run(running_token)
87+
88+
def reboot_bot(self):
89+
"""Reboot the bot."""
90+
print("Rebooting bot...")
91+
self.loop.create_task(self.close())
92+
self.loop.run_until_complete(self.start(self._token))
93+
94+
# === Command Methods ===
95+
def add_slash_command(self, name: str, description: str, function: Callable[..., Any], options: Optional[list] = None):
96+
"""Create a slash command.
97+
98+
Args:
99+
name: The name of the command
100+
description: The description of the command
101+
function: The function to execute when the command is called
102+
options: Optional list of app_commands.Option for additional parameters
103+
"""
104+
@app_commands.command(name=name, description=description)
105+
async def slash_command(interaction: discord.Interaction):
106+
await function(interaction)
107+
108+
if options:
109+
for option in options:
110+
slash_command.add_option(option)
111+
112+
self.tree.add_command(slash_command)
113+
return slash_command
114+
115+
116+
def add_slash_group(self, name: str, description: str):
117+
"""Create a slash command group.
118+
119+
Args:
120+
name: The name of the command group
121+
description: The description of the group
122+
"""
123+
return app_commands.Group(name=name, description=description)
124+
125+
def add_custom_command(self, name, function):
126+
"""Add a custom prefix command to the bot."""
127+
self.add_command(commands.Command(function, name=name, help=function.__doc__))
128+
129+
# === Token Methods (delegated to utils) ===
130+
@staticmethod
131+
def load_token_from_string(token_string):
132+
global token
133+
token = token_utils.load_token_from_string(token_string)
134+
return token
135+
136+
@staticmethod
137+
def load_token_from_file(file_path):
138+
global token
139+
token = token_utils.load_token_from_file(file_path)
140+
return token
141+
142+
@staticmethod
143+
def load_token_from_environment(env_var):
144+
global token
145+
token = token_utils.load_token_from_environment(env_var)
146+
return token
147+
148+
@staticmethod
149+
def load_token_from_config(config_file, token_key):
150+
global token
151+
token = token_utils.load_token_from_config(config_file, token_key)
152+
return token
153+
154+
@staticmethod
155+
def load_token_from_secret(secret_name):
156+
global token
157+
token = token_utils.load_token_from_secret(secret_name)
158+
return token
159+
160+
class WebhookUtils:
161+
@staticmethod
162+
def add_webhook(url):
163+
return webhook_utils.add_webhook(url)
164+
165+
@staticmethod
166+
def send_webhook(webhook, content):
167+
return webhook_utils.send_webhook(webhook, content)
168+
169+
@staticmethod
170+
def send_embed(webhook, embed):
171+
return webhook_utils.send_embed(webhook, embed)
172+
173+
# === Embed Utility Methods ===
174+
@staticmethod
175+
def create_embed(title, description=None, color=0x000000):
176+
return embed_utils.create_embed(title, description, color)
177+
178+
@staticmethod
179+
def set_embed_title(embed, title):
180+
return embed_utils.set_embed_title(embed, title)
181+
182+
@staticmethod
183+
def set_embed_description(embed, description):
184+
return embed_utils.set_embed_description(embed, description)
185+
186+
@staticmethod
187+
def set_embed_color(embed, color):
188+
return embed_utils.set_embed_color(embed, color)
189+
190+
@staticmethod
191+
def set_embed_url(embed, url):
192+
return embed_utils.set_embed_url(embed, url)
193+
194+
@staticmethod
195+
def set_embed_timestamp(embed, timestamp=None):
196+
return embed_utils.set_embed_timestamp(embed, timestamp)
197+
198+
@staticmethod
199+
def set_embed_fields(embed, fields):
200+
return embed_utils.set_embed_fields(embed, fields)
201+
202+
@staticmethod
203+
def add_embed_field(embed, name, value, inline=True):
204+
return embed_utils.add_embed_field(embed, name, value, inline)
205+
206+
@staticmethod
207+
def set_embed_footer(embed, text, icon_url=None):
208+
return embed_utils.set_embed_footer(embed, text, icon_url)
209+
210+
@staticmethod
211+
def set_embed_footer_text(embed, text):
212+
return embed_utils.set_embed_footer_text(embed, text)
213+
214+
@staticmethod
215+
def set_embed_footer_icon(embed, icon_url):
216+
return embed_utils.set_embed_footer_icon(embed, icon_url)
217+
218+
@staticmethod
219+
def set_embed_thumbnail(embed, url):
220+
return embed_utils.set_embed_thumbnail(embed, url)
221+
222+
@staticmethod
223+
def set_embed_image(embed, url):
224+
return embed_utils.set_embed_image(embed, url)
225+
226+
@staticmethod
227+
def set_embed_author(embed, name, url=None, icon_url=None):
228+
return embed_utils.set_embed_author(embed, name, url, icon_url)
229+
230+
@staticmethod
231+
def set_embed_author_name(embed, name):
232+
return embed_utils.set_embed_author_name(embed, name)
233+
234+
@staticmethod
235+
def set_embed_author_url(embed, url):
236+
return embed_utils.set_embed_author_url(embed, url)
237+
238+
@staticmethod
239+
def set_embed_author_icon(embed, icon_url):
240+
return embed_utils.set_embed_author_icon(embed, icon_url)

PyBot/utils/embed_utils.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import discord
2+
from datetime import datetime
3+
4+
5+
def create_embed(title, description=None, color=0x000000):
6+
return discord.Embed(title=title, description=description, color=color)
7+
8+
9+
def set_embed_title(embed, title):
10+
embed.title = title
11+
return embed
12+
13+
14+
def set_embed_description(embed, description):
15+
embed.description = description
16+
return embed
17+
18+
19+
def set_embed_color(embed, color):
20+
embed.color = color
21+
return embed
22+
23+
24+
def set_embed_url(embed, url):
25+
embed.url = url
26+
return embed
27+
28+
29+
def set_embed_timestamp(embed, timestamp=None):
30+
embed.timestamp = timestamp or datetime.utcnow()
31+
return embed
32+
33+
34+
def set_embed_fields(embed, fields):
35+
for name, value, inline in fields:
36+
embed.add_field(name=name, value=value, inline=inline)
37+
return embed
38+
39+
40+
def add_embed_field(embed, name, value, inline=True):
41+
embed.add_field(name=name, value=value, inline=inline)
42+
return embed
43+
44+
45+
def set_embed_footer(embed, text, icon_url=None):
46+
embed.set_footer(text=text, icon_url=icon_url)
47+
return embed
48+
49+
50+
def set_embed_footer_text(embed, text):
51+
icon_url = embed.footer.icon_url if embed.footer else None
52+
embed.set_footer(text=text, icon_url=icon_url)
53+
return embed
54+
55+
56+
def set_embed_footer_icon(embed, icon_url):
57+
text = embed.footer.text if embed.footer else None
58+
embed.set_footer(text=text, icon_url=icon_url)
59+
return embed
60+
61+
62+
def set_embed_thumbnail(embed, url):
63+
embed.set_thumbnail(url=url)
64+
return embed
65+
66+
67+
def set_embed_image(embed, url):
68+
embed.set_image(url=url)
69+
return embed
70+
71+
72+
def set_embed_author(embed, name, url=None, icon_url=None):
73+
embed.set_author(name=name, url=url, icon_url=icon_url)
74+
return embed
75+
76+
77+
def set_embed_author_name(embed, name):
78+
author = embed.author
79+
embed.set_author(
80+
name=name,
81+
url=getattr(author, 'url', None),
82+
icon_url=getattr(author, 'icon_url', None)
83+
)
84+
return embed
85+
86+
87+
def set_embed_author_url(embed, url):
88+
author = embed.author
89+
embed.set_author(
90+
name=getattr(author, 'name', None),
91+
url=url,
92+
icon_url=getattr(author, 'icon_url', None)
93+
)
94+
return embed
95+
96+
97+
def set_embed_author_icon(embed, icon_url):
98+
author = embed.author
99+
embed.set_author(
100+
name=getattr(author, 'name', None),
101+
url=getattr(author, 'url', None),
102+
icon_url=icon_url
103+
)
104+
return embed

0 commit comments

Comments
 (0)