Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,10 @@ Everything you need to know, neatly organized:
- `dashboard/`: The pretty face
- `locales/`: The dictionary

[Contributing Guide →](https://zeroichi.mhankbarbar.dev/development/architecture)
[Contributing Guide →](https://zeroichi.mhankbarbar.dev/development/contributing)

---

## License

[MIT](LICENSE)
3 changes: 1 addition & 2 deletions ai/skills.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from pathlib import Path
from typing import TypedDict

import httpx
import yaml

from core.constants import SKILLS_DIR
Expand Down Expand Up @@ -92,8 +93,6 @@ def load_skill_from_file(path: Path | str) -> SkillData | None:
async def load_skill_from_url(url: str) -> SkillData | None:
"""Load a skill from a URL."""
try:
import httpx

async with httpx.AsyncClient() as client:
response = await client.get(url, timeout=10.0)
response.raise_for_status()
Expand Down
5 changes: 1 addition & 4 deletions ai/token_tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

from core.constants import DATA_DIR
from core.logger import log_debug
from core.runtime_config import runtime_config

TOKEN_FILE = DATA_DIR / "ai_tokens.json"

Expand Down Expand Up @@ -41,15 +42,11 @@ def _save(self) -> None:
@property
def _user_limit(self) -> int:
"""Daily per-user token limit."""
from core.runtime_config import runtime_config

return runtime_config.get_nested("agentic_ai", "daily_token_limit_user", default=50_000)

@property
def _chat_limit(self) -> int:
"""Daily per-chat token limit."""
from core.runtime_config import runtime_config

return runtime_config.get_nested("agentic_ai", "daily_token_limit_chat", default=200_000)

def _ensure_today(self) -> None:
Expand Down
9 changes: 0 additions & 9 deletions ai/tools/__init__.py

This file was deleted.

70 changes: 0 additions & 70 deletions ai/tools/core.py

This file was deleted.

29 changes: 0 additions & 29 deletions ai/tools/group.py

This file was deleted.

4 changes: 1 addition & 3 deletions commands/downloader/dl.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from core.command import Command, CommandContext
from core.downloader import DownloadError, FileTooLargeError, downloader
from core.i18n import t, t_error
from core.logger import log_info
from core.logger import log_info, log_warning
from core.pending_store import (
PendingDownload,
PendingPlaylist,
Expand Down Expand Up @@ -295,8 +295,6 @@ async def _show_options(self, ctx: CommandContext, info):
quoted=ctx.message.event,
)
except Exception as e:
from core.logger import log_warning

log_warning(f"Failed to send thumbnail: {e}")

return await ctx.client.reply(ctx.message, text)
Expand Down
3 changes: 1 addition & 2 deletions commands/general/stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""

import platform
import time

from core import symbols as sym
from core.command import Command, CommandContext, command_loader
Expand All @@ -26,8 +27,6 @@ async def execute(self, ctx: CommandContext) -> None:
total_cmds = len(command_loader.enabled_commands)

try:
import time

from commands.general.uptime import _start_time

elapsed = time.time() - _start_time
Expand Down
4 changes: 2 additions & 2 deletions commands/group/poll.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
Poll command - Create polls in groups.
"""

import re

from core import symbols as sym
from core.command import Command, CommandContext
from core.i18n import t
Expand All @@ -21,8 +23,6 @@ class PollCommand(Command):

async def execute(self, ctx: CommandContext) -> None:
"""Create a poll."""
import re

text = ctx.raw_args
if not text:
await ctx.client.reply(
Expand Down
5 changes: 1 addition & 4 deletions commands/group/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from core import symbols as sym
from core.command import Command, CommandContext
from core.i18n import t
from core.permissions import check_command_permissions
from core.storage import GroupData


Expand Down Expand Up @@ -40,8 +41,6 @@ async def execute(self, ctx: CommandContext) -> None:
action = ctx.args[0].lower()

if action == "set":
from core.permissions import check_command_permissions

can_execute, error = await check_command_permissions(
ctx.client, ctx.message, admin_only=True
)
Expand All @@ -63,8 +62,6 @@ async def execute(self, ctx: CommandContext) -> None:
)

elif action == "clear":
from core.permissions import check_command_permissions

can_execute, error = await check_command_permissions(
ctx.client, ctx.message, admin_only=True
)
Expand Down
63 changes: 63 additions & 0 deletions commands/owner/leave.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
"""
Leave command - Make the bot leave a group.
"""

from core.command import Command, CommandContext
from core.i18n import t_error, t_success


class LeaveCommand(Command):
name = "leave"
description = "Make the bot leave a group"
usage = "leave [group_jid]"
category = "owner"
cooldown = 5
examples = [
"leave",
"leave 123456789@g.us",
]

async def execute(self, ctx: CommandContext) -> None:
"""Handle leave command.

- Owner: can leave current group or target a specific group by JID.
- Group admin: can make the bot leave the current group.
"""
from core.runtime_config import runtime_config

is_owner = await runtime_config.is_owner_async(ctx.message.sender_jid)
is_group = ctx.message.is_group

args = ctx.args

if is_owner and args:
target_jid = args[0]
if not target_jid.endswith("@g.us"):
target_jid = f"{target_jid}@g.us"
try:
await ctx.client.leave_group(target_jid)
await ctx.client.reply(ctx.message, t_success("leave.left", group=target_jid))
except Exception as e:
await ctx.client.reply(ctx.message, t_error("leave.failed", error=str(e)))
return

if not is_group:
await ctx.client.reply(ctx.message, t_error("leave.not_group"))
return

if not is_owner:
from core.permissions import check_admin_permission

is_admin = await check_admin_permission(
ctx.client, ctx.message.chat_jid, ctx.message.sender_jid
)
if not is_admin:
await ctx.client.reply(ctx.message, t_error("leave.no_permission"))
return

group_jid = ctx.message.chat_jid
try:
await ctx.client.reply(ctx.message, t_success("leave.leaving"))
await ctx.client.leave_group(group_jid)
except Exception as e:
await ctx.client.reply(ctx.message, t_error("leave.failed", error=str(e)))
3 changes: 1 addition & 2 deletions commands/utility/lang.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
t_error,
t_success,
)
from core.permissions import check_admin_permission


class LangCommand(Command):
Expand All @@ -31,8 +32,6 @@ async def execute(self, ctx: CommandContext) -> None:
is_group = "@g.us" in chat_jid or "@lid" in chat_jid and ctx.message.is_group

if is_group:
from core.permissions import check_admin_permission

if not await check_admin_permission(ctx.client, chat_jid, ctx.message.sender_jid):
await ctx.client.reply(ctx.message, t_error("errors.admin_required", chat_jid))
return
Expand Down
2 changes: 1 addition & 1 deletion commands/utility/remind.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from core.command import Command, CommandContext
from core.i18n import t, t_error, t_info, t_success
from core.media import get_media_caption
from core.scheduler import get_scheduler
from core.utils import format_duration, parse_duration


Expand All @@ -36,7 +37,6 @@ class RemindCommand(Command):

async def execute(self, ctx: CommandContext) -> None:
"""Handle remind command."""
from core.scheduler import get_scheduler

scheduler = get_scheduler()
if not scheduler:
Expand Down
Empty file removed config/commands.py
Empty file.
Loading