پرش به محتویات
توسعه‌دهنده aioshad
    | فیلد | مقدار |
    |---|---|
    | نام | `aioshad` |
    | نسخه | `1.0.10` |
    | نویسنده | aioshad contributors |
    | مجوز | MIT |
    | Python | 3, 3.11, 3.12, 3.13 |


    لینکی در metadata ثبت نشده است.


    # 🟦 aioshad

🚀 اولین و بزرگ‌ترین کتابخانهٔ سلف در پیام‌رسان شاد

aioshad یک کتابخانهٔ Python و asyncio برای ساخت Client / Self Account روی پیام‌رسان شاد است.

🎯 هدف پروژه این است که توسعه‌دهنده بتواند به‌جای ساختن یک Bot API جداگانه، برنامه را روی همان اکانتی که با آن وارد شاد شده است اجرا کند.

### 👤 توسعه‌دهنده **ابوالفضل سلیمانی** [GitHub](https://github.com/shanduzgil) · [Telegram](https://t.me/hacker_king_sog)

✨ ویژگی‌های اصلی

بخش قابلیت
👤 Account ورود با شماره، نگهداری Session و اجرای API روی همان اکانت
💬 Messages ارسال، ویرایش، حذف و Reply
📎 Files Upload و ارسال فایل
🖼️ Photos Upload، thumbnail و ارسال تصویر
👤 Profile تغییر نام، نام خانوادگی و Bio
⏰ TimeName نمایش ساعت/تاریخ کنار نام همان اکانت
🤖 Auto Reply پاسخ خودکار بر اساس متن دریافتی
🎯 Filters Command، Regex، Text، Private، Group، Channel، Media و ...
🧩 Filter Logic ترکیب فیلترها با &، | و ~
🔄 Dispatcher دریافت Update و اجرای Handlerها
⏱️ Scheduler اجرای Taskهای دوره‌ای
🛡️ Rate Limit محدودسازی نرخ درخواست‌ها
🌐 Network HTTP/2، Retry، Backoff و Host Failover
🔐 Session Session قابل ذخیره و رمزنگاری‌شده
🎙️ Voice Chat متدهای موجود برای Voice Chat در پروتکل پایه
🧰 Raw RPC فراخوانی متدهای Authenticated که wrapper ندارند
🧱 Typed Models مدل‌های Message، Chat و User

📦 نصب

pip install aioshad

آخرین نسخه:

pip install -U aioshad

Python موردنیاز پروژه: 3.11 یا بالاتر.


⚡ شروع سریع

ساده‌ترین حالت استفاده از کتابخانه:

import asyncio
from aioshad import Client

app = Client(
    "0937xxxxxxxx",
    session_directory="./sessions",
)

async def main():
    await app.start()

asyncio.run(main())

در اولین اجرا، فرآیند ورود انجام می‌شود و Session ذخیره خواهد شد. در اجراهای بعدی، کتابخانه از Session موجود استفاده می‌کند تا تا حد امکان از ورود مجدد جلوگیری شود.


👤 Self Account چگونه کار می‌کند؟

aioshad برای یک اکانت کاربری شاد طراحی شده است. یعنی هویت برنامه همان اکانتی است که Session آن ایجاد شده است.

شماره تلفن
Login / OTP
Session
Client
اکانت واقعی شاد

پس ساختار استفاده شبیه یک Bot API مستقل نیست؛ عملیات اصلی از طریق Session اکانت اجرا می‌شوند.


🔐 Session

بهتر است Sessionها را در یک پوشهٔ جداگانه نگهداری کنید:

app = Client(
    "0937xxxxxxxx",
    session_directory="./sessions",
)

در صورت نیاز می‌توان برای ذخیرهٔ Session از کلید رمزنگاری استفاده کرد:

app = Client(
    "0937xxxxxxxx",
    session_directory="./sessions",
    session_encryption_key="یک-راز-قوی",
)

یا در محیط سیستم:

export AIOSHAD_SESSION_KEY="یک-راز-قوی"

⚠️ نکته امنیتی

فایل Session را مثل یک credential حساس در نظر بگیرید. آن را داخل Git، ZIP عمومی یا کانال عمومی منتشر نکنید.


🧠 Client

کلاس اصلی کتابخانه:

from aioshad import Client

app = Client(phone_number, ...)

سازندهٔ Client

Client(
    phone_number: str,
    session_directory: str = ".",
    messenger_host: str | None = None,
    *,
    config: ClientConfig | None = None,
    session_encryption_key: str | None = None,
)

پارامترها

پارامتر توضیح
phone_number شماره اکانت
session_directory محل ذخیره Session
messenger_host Host سفارشی در صورت نیاز
config تنظیمات ClientConfig
session_encryption_key کلید رمزنگاری Session

🔌 چرخهٔ اتصال

connect()

اتصال به سرویس و آماده‌سازی Session:

await app.connect()

start()

اتصال + شروع Dispatcher و نگه‌داشتن برنامه تا زمان توقف:

await app.start()

start_in_background()

اتصال و اجرای Dispatcher بدون قفل‌کردن جریان اصلی برنامه:

await app.start_in_background()

run_until_disconnected()

روش جایگزین برای اجرای طولانی‌مدت:

await app.run_until_disconnected()

stop()

توقف Dispatcher، قابلیت‌های background، Transport و ذخیره Session:

await app.stop()

is_connected

بررسی وضعیت اتصال:

if app.is_connected:
    print("Connected")

💬 ارسال پیام

send_message()

message = await app.send_message(
    object_guid="g0...",
    text="سلام شاد!",
)

print(message.id)

Signature:

await app.send_message(
    object_guid: str,
    text: str = "",
    reply_to_message_id: str | None = None,
    file_inline: dict | None = None,
)

Reply

await app.send_message(
    "g0...",
    "پاسخ شما",
    reply_to_message_id="123456",
)

✏️ ویرایش پیام

message = await app.edit_message(
    object_guid="g0...",
    message_id="123456",
    text="متن جدید",
)

🗑️ حذف پیام

یک پیام

await app.delete_message(
    object_guid="g0...",
    message_id="123456",
)

چند پیام

await app.delete_messages(
    object_guid="g0...",
    message_ids=["123", "124", "125"],
)

delete_type دو مقدار دارد:

Global
Local

مثال:

await app.delete_message(
    "g0...",
    "123456",
    delete_type="Local",
)

📁 فایل‌ها

upload_file()

فایل را Upload می‌کند و اطلاعات فایل آپلودشده را برمی‌گرداند:

info = await app.upload_file(
    "./files/example.pdf",
)

print(info)

ورودی می‌تواند Path یا bytes باشد:

data = b"hello"

info = await app.upload_file(
    data,
    file_name="hello.txt",
    mime="txt",
)

Signature:

await app.upload_file(
    file,
    file_name=None,
    mime=None,
    chunk_size=None,
)

Upload در این نسخه فایل را ابتدا در حافظه آماده می‌کند؛ برای فایل‌های بسیار بزرگ مصرف RAM را در نظر بگیرید.


🖼️ ارسال تصویر

await app.send_photo(
    "g0...",
    "./photo.jpg",
    caption="یک تصویر",
)

پشتیبانی از ورودی str، bytes و Path وجود دارد.

Reply با عکس:

await app.send_photo(
    "g0...",
    "./photo.jpg",
    caption="پاسخ تصویری",
    reply_to_message_id="123456",
)

📄 ارسال فایل

await app.send_file(
    "g0...",
    "./document.pdf",
    caption="فایل شما",
)

همچنین می‌توان نام فایل و MIME را مشخص کرد:

await app.send_file(
    "g0...",
    b"hello world",
    file_name="hello.txt",
    mime="txt",
    caption="سلام",
)

👤 اطلاعات اکانت و کاربران

get_me()

اطلاعات اکانت لاگین‌شده:

me = await app.get_me()

print(me.guid)
print(me.name)
print(me.username)
print(me.bio)

get_user_info()

user = await app.get_user_info("u0...")
print(user.name)

مدل User

User شامل این فیلدهاست:

 guid
 name
 username
 bio
 phone
 is_verified

✍️ مدیریت پروفایل

API مستقیم

await app.update_profile(
    first_name="ابوالفضل",
    last_name="سلیمانی",
    bio="Powered by aioshad",
)

ProfileManager

کتابخانه یک مدیر پروفایل آماده نیز دارد:

await app.profile.set_name("aioshad")
await app.profile.set_first_name("AioShad")
await app.profile.set_last_name("Client")
await app.profile.set_bio("Async Shad Client")

⏰ TimeName

یکی از قابلیت‌های اصلی aioshad، تغییر دوره‌ای نام همان اکانت برای نمایش ساعت/تاریخ است.

from aioshad import Client, TimeName

app = Client(
    "0937xxxxxxxx",
    session_directory="./sessions",
)

async def main():
    await app.connect()

    await app.presence.start_time_name(
        TimeName(
            format="⏰ {time}",
            timezone="Asia/Tehran",
            interval=60,
        )
    )

    await app.run_until_disconnected()

asyncio.run(main())

تنظیمات TimeName

TimeName(
    format="⏰ {time}",
    timezone="Asia/Tehran",
    interval=60,
    preserve_first_name=False,
)

Placeholderها

Placeholder مقدار
{time} ساعت 24 ساعته مثل 18:45
{time_12} ساعت 12 ساعته
{date} تاریخ YYYY-MM-DD
{day} نام روز
{timestamp} Unix timestamp

مثال:

TimeName(
    format="🕒 {time}{date}",
    timezone="Asia/Tehran",
    interval=60,
)

حداقل interval در نسخهٔ فعلی ۵ ثانیه است.

توقف TimeName

await app.presence.stop_time_name()

🤖 Auto Reply

سیستم پاسخ خودکار روی همان حساب:

app.autoreply.add(
    "سلام",
    "سلام! پیام شما دریافت شد.",
)

app.autoreply.set_default(
    "پیامت دریافت شد.",
)

await app.autoreply.enable()

غیرفعال‌سازی:

await app.autoreply.disable()

نکته

پاسخ‌دهی خودکار برای جلوگیری از پاسخ به پیام‌های ارسالی خود همان Session طراحی شده است.


🎯 Message Handler

دریافت پیام‌ها با Decorator:

from aioshad import Client, filters

app = Client("0937xxxxxxxx")

@app.on_message(filters.command("ping"))
async def ping(message):
    await message.reply("pong")

asyncio.run(app.start())

Handler می‌تواند sync یا async باشد:

@app.on_message(filters.text)
async def handler(message):
    print(message.text)

یا:

@app.on_message(filters.text)
def handler(message):
    print(message.text)

Dispatcher نتیجهٔ Awaitable را در صورت وجود await می‌کند.


🧩 تمام Filterهای موجود

ماژول اصلی:

from aioshad import filters

فیلترهای پایه

Filter کاربرد
filters.all همهٔ پیام‌ها
filters.text پیام دارای متن
filters.private چت خصوصی
filters.group گروه
filters.channel کانال
filters.reply پیام Reply شده
filters.edited پیام ویرایش‌شده
filters.media پیام‌های Media

command

@app.on_message(filters.command("start"))
async def start(message):
    await message.reply("شروع شد")

چند Command:

filters.command(["start", "help"])

Prefixهای متعدد:

filters.command(
    "start",
    prefixes=["/", "!", "."],
)

حساسیت به حروف:

filters.command(
    "PING",
    case_sensitive=True,
)

🔎 RegexFilter

@app.on_message(filters.regex(r"^hello\s+.+$"))
async def hello(message):
    await message.reply("Hello!")

با Flags:

import re

filters.regex(r"hello", flags=re.IGNORECASE)

🔤 TextFilter

فقط پیام‌هایی که متن غیرخالی دارند:

@app.on_message(filters.text)
async def text_message(message):
    print(message.text)

👤 PrivateFilter

@app.on_message(filters.private)
async def private_message(message):
    await message.reply("پیام خصوصی دریافت شد")

👥 GroupFilter

@app.on_message(filters.group)
async def group_message(message):
    print(message.chat_guid)

📢 ChannelFilter

@app.on_message(filters.channel)
async def channel_message(message):
    print(message.text)

↩️ ReplyFilter

@app.on_message(filters.reply)
async def replies(message):
    print(message.reply_to_message_id)

✏️ EditedFilter

@app.on_message(filters.edited)
async def edited(message):
    print("پیام ویرایش شد:", message.text)

🆔 AuthorFilter

برای یک کاربر:

filters.author("u0...")

برای چند کاربر:

filters.author(["u0...", "u0..."])

مثال:

@app.on_message(filters.author("u0..."))
async def from_user(message):
    print(message.text)

💬 ChatFilter

filters.chat("g0...")

یا:

filters.chat(["g0...", "c0..."])

🧵 ContainsFilter

@app.on_message(filters.contains("سلام"))
async def contains(message):
    await message.reply("کلمهٔ سلام در پیام وجود داشت")

به‌صورت پیش‌فرض مقایسه Case-insensitive است.

filters.contains(
    "HELLO",
    case_sensitive=True,
)

▶️ StartsWithFilter

@app.on_message(filters.startswith("/"))
async def command_like(message):
    print(message.text)

🖼️ MediaFilter

فیلتر Media به‌صورت پیش‌فرض این نوع‌ها را بررسی می‌کند:

photo
file
video
audio
voice

مثال:

@app.on_message(filters.media)
async def media(message):
    print(message.message_type)

نوع‌های سفارشی:

filters.media("photo", "video")

🛠️ CustomFilter

می‌توان Filter دلخواه ساخت:

def long_message(message):
    return len(message.text) > 50

@app.on_message(filters.create(long_message))
async def long_text(message):
    await message.reply("پیام طولانی بود")

تابع async نیز قابل استفاده است:

async def custom(message):
    return message.text.startswith("aioshad")

@app.on_message(filters.create(custom))
async def handler(message):
    ...

🔗 ترکیب Filterها

AND — &

هر دو شرط باید برقرار باشند:

@app.on_message(filters.private & filters.text)
async def private_text(message):
    print(message.text)

مثال پیشرفته:

@app.on_message(
    filters.group & filters.contains("سلام")
)
async def group_hello(message):
    await message.reply("سلام گروه")

OR — |

حداقل یکی از شروط:

@app.on_message(
    filters.private | filters.group
)
async def chat_message(message):
    print(message.text)

NOT — ~

معکوس‌کردن یک شرط:

@app.on_message(~filters.edited)
async def normal_message(message):
    print(message.text)

ترکیب چندگانه

handler_filter = (
    (filters.private | filters.group)
    & filters.text
    & ~filters.edited
)

@app.on_message(handler_filter)
async def handler(message):
    print(message.text)

📨 کلاس Message

پیامی که به Handler داده می‌شود از نوع Message است.

فیلدهای اصلی:

id
author_guid
chat_guid
text
message_type
reply_to_message_id
is_edited
raw

Reply

await message.reply("سلام")

Reply با عکس

await message.reply_photo(
    "./image.jpg",
    caption="عکس",
)

Reply با فایل

await message.reply_file(
    "./document.pdf",
    caption="فایل",
)

Edit

await message.edit("متن جدید")

Delete

await message.delete()

یا:

await message.delete(delete_type="Local")

گرفتن Chat

chat = await message.get_chat()
print(chat.title)

گرفتن Author

user = await message.get_author()
print(user.name)

دسترسی به داده خام

value = message.get("some_key")

یا:

value = message["some_key"]

💬 کلاس Chat

Chat برای کار با یک گفت‌وگو استفاده می‌شود.

فیلدهای اصلی:

guid
title
type
username
description
members_count
voice_chat_id
raw

ارسال پیام از خود Chat

chat = await app.get_chat_info("g0...")
await chat.send_message("سلام")

ارسال عکس

await chat.send_photo("./photo.jpg")

ارسال فایل

await chat.send_file("./file.pdf")

تاریخچه

messages = await chat.get_chat_history(limit=50)

پیام‌ها

messages = await chat.get_messages(limit=50)

حذف پیام

await chat.delete_message("123456")

یا:

await chat.delete_messages(["123", "124"])

📚 مدیریت Chatها

get_chats()

result = await app.get_chats()
print(result)

get_chat_info()

chat = await app.get_chat_info("g0...")

get_chat_info_by_username()

chat = await app.get_chat_info_by_username("username")

🕘 تاریخچه و پیام‌ها

get_messages()

result = await app.get_messages(
    "g0...",
    limit=50,
)

پارامترهای صفحه‌بندی:

await app.get_messages(
    "g0...",
    limit=50,
    sort="FromMax",
    max_id="1000",
    min_id="900",
)

get_chat_history()

این متد خروجی را به فهرست Message تبدیل می‌کند:

messages = await app.get_chat_history(
    "g0...",
    limit=50,
)

for message in messages:
    print(message.id, message.text)

🔄 Updateها

get_chats_updates()

updates = await app.get_chats_updates(state=0)

get_messages_updates()

updates = await app.get_messages_updates(
    "g0...",
    state=0,
)

Dispatcher داخلی نیز از updateهای چت برای دریافت پیام‌ها استفاده می‌کند.


📡 Dispatcher

Dispatcher مسئول دریافت Update و اجرای Handlerهاست.

ویژگی‌های اصلی:

  • Polling دوره‌ای
  • اجرای Filter قبل از Handler
  • اجرای هم‌زمان Handlerها
  • ثبت و حذف Handler
  • جلوگیری از پردازش تکراری Messageهای دیده‌شده
  • کنترل خطاهای متوالی
  • توقف تمیز

حذف Handler

@app.on_message(filters.text)
async def my_handler(message):
    ...

app.remove_handler(my_handler)

remove_handler() تعداد Handlerهای حذف‌شده را برمی‌گرداند.


⏱️ Scheduler

برای اجرای Taskهای دوره‌ای:

async def job():
    print("task running")

app.scheduler.every(60, job)

حداقل interval برابر ۵ ثانیه است.

توقف تمام Taskها:

await app.scheduler.cancel_all()

🛡️ Rate Limiting

aioshad در Transport از محدودسازی نرخ درخواست استفاده می‌کند.

تنظیم پیش‌فرض:

5 requests / second

قابل تنظیم از طریق ClientConfig:

from aioshad import Client, ClientConfig

config = ClientConfig(
    max_requests_per_second=3,
)

app = Client(
    "0937xxxxxxxx",
    config=config,
)

⚙️ ClientConfig

کلاس تنظیمات:

from aioshad import ClientConfig

مقادیر اصلی نسخهٔ فعلی:

گزینه مقدار پیش‌فرض
timeout 30.0
poll_interval 1.5
error_backoff 3.0
max_consecutive_errors 10
max_requests_per_second 5.0
retry_attempts 3
upload_chunk_size 131072
app_version 4.4.26
platform Web
package web.shad.ir
language fa

مثال:

config = ClientConfig(
    timeout=45,
    poll_interval=2,
    retry_attempts=5,
    max_requests_per_second=4,
)

🌐 Network و Host

کتابخانه Transport خود را دارد و برای ارتباط شبکه‌ای از HTTP/2 استفاده می‌کند.

قابلیت‌های لایهٔ شبکه:

  • Timeout
  • Retry
  • Backoff
  • Rate Limit
  • Host Failover
  • Upload Chunk

Hostهای پیش‌فرض پروژه:

shadmessenger60.iranlms.ir
shadmessenger145.iranlms.ir
shadmessenger40.iranlms.ir
shadmessenger23.iranlms.ir
shadmessenger57.iranlms.ir

برای انتخاب Host دستی:

app.set_messenger_host(
    "example-host"
)

Hostهای واقعی سرویس ممکن است تغییر کنند. این فهرست مربوط به مقادیری است که در نسخهٔ فعلی پروژه تعریف شده‌اند.


🎙️ Voice Chat

متدهای زیر در Client وجود دارند:

await app.create_voice_chat("g0...")

await app.join_voice_chat(
    "g0...",
    voice_chat_id="...",
    sdp_offer_data="...",
)

await app.leave_voice_chat(
    "g0...",
    voice_chat_id="...",
)

await app.get_voice_chat_participants(
    "g0...",
    voice_chat_id="...",
)

await app.discard_voice_chat(
    "g0...",
    voice_chat_id="...",
)

await app.set_voice_chat_state(
    "g0...",
    voice_chat_id="...",
    activity="Speaking",
)

Chat نیز wrapperهای مربوط به Join/Leave/Participants را ارائه می‌کند.

جزئیات SDP و رفتار نهایی Voice Chat به پروتکل/endpoint فعال شاد وابسته است.


🚫 Block / Unblock

برای مسدود یا آزادکردن کاربر:

await app.block_user("u0...")

و:

await app.unblock_user("u0...")

این دو متد در Client به یک RPC احراز‌شدهٔ مربوط به Block متصل هستند.


🧰 Raw RPC

اگر یک متد Authenticated در wrapperهای سطح‌بالای aioshad وجود نداشته باشد، می‌توانید از invoke() استفاده کنید:

result = await app.invoke(
    "METHOD_NAME",
    key="value",
)

مثال با داده‌های متعدد:

result = await app.invoke(
    "METHOD_NAME",
    object_guid="g0...",
    limit=50,
)

این API عمداً generic است تا برای متدهای جدید پروتکل لازم نباشد هستهٔ Client تغییر کند.

نام Method و پارامترهای RPC باید مطابق endpoint و payload واقعی سرویس باشد؛ aioshad برای RPCهای ناشناخته payload حدسی تولید نمی‌کند.


🧱 API کامل Client — Reference

تمام متدهای عمومی Client در نسخهٔ فعلی:

متد خروجی کاربرد
connect() Client اتصال/احراز هویت
start() None شروع کامل Client
start_in_background() None شروع بدون idle داخلی
run_until_disconnected() None اجرای طولانی‌مدت
stop() None توقف تمیز
on_message() Handler ثبت Message Handler
remove_handler() int حذف Handler
send_message() Message ارسال پیام
edit_message() Message ویرایش پیام
delete_messages() dict حذف چند پیام
delete_message() dict حذف یک پیام
upload_file() dict Upload فایل
send_photo() Message ارسال عکس
send_file() Message ارسال فایل
get_user_info() User اطلاعات کاربر
get_me() User اطلاعات حساب فعلی
update_profile() bool تغییر پروفایل
get_chats() dict دریافت Chatها
get_messages() dict دریافت پیام‌ها
get_chats_updates() dict دریافت updateهای چت
get_messages_updates() dict دریافت updateهای پیام
get_chat_history() list[Message] تاریخچهٔ Chat
register_device() dict ثبت/بررسی Device
get_chat_info() Chat اطلاعات Chat
get_chat_info_by_username() Chat Chat با Username
join_voice_chat() dict Join Voice Chat
leave_voice_chat() dict Leave Voice Chat
get_voice_chat_participants() dict Participants
create_voice_chat() dict ساخت Voice Chat
discard_voice_chat() dict حذف/Discard Voice Chat
set_voice_chat_state() dict تغییر وضعیت Voice Chat
invoke() dict RPC خام
block_user() dict Block
unblock_user() dict Unblock
set_messenger_host() None تعیین Host

🧩 API کلاس Message — Reference

متدهای عمومی Message:

edit()
delete()
reply()
reply_photo()
reply_file()
get_chat()
get_author()
get()
__getitem__()

مثال کامل:

@app.on_message(filters.command("demo"))
async def demo(message):
    await message.edit("پیام ویرایش شد")
    await message.reply("Reply")
    chat = await message.get_chat()
    user = await message.get_author()
    print(chat.title)
    print(user.name)

💬 API کلاس Chat — Reference

متدهای عمومی Chat:

send_message()
send_photo()
send_file()
get_chat_history()
get_messages()
delete_messages()
delete_message()
join_voice_chat()
leave_voice_chat()
get_voice_chat_participants()
get()
__getitem__()

👤 API کلاس User

User یک مدل داده‌ای سبک است و فیلدهای زیر را ارائه می‌کند:

guid
name
username
bio
phone
is_verified

⏰ API قابلیت‌ها

ProfileManager

set_name()
set_first_name()
set_last_name()
set_bio()

PresenceManager

start_time_name()
stop_time_name()
close()

AutoResponder

add()
set_default()
enable()
disable()

Scheduler

every()
cancel_all()

🧩 API Filter — Reference کامل

کلاس‌های موجود:

Filter
AndFilter
OrFilter
InvertFilter
CustomFilter
CommandFilter
RegexFilter
TextFilter
PrivateFilter
GroupFilter
ChannelFilter
ReplyFilter
EditedFilter
AuthorFilter
ChatFilter
AllFilter
ContainsFilter
StartsWithFilter
MediaFilter

Aliasهای راحت نیز وجود دارند:

command
regex
author
chat
create
text
private
group
channel
reply
edited
all
contains
startswith
media

🧯 مدیریت خطاها

استثناهای اصلی کتابخانه:

from aioshad import (
    AioShadError,
    AuthenticationError,
    InvalidSessionError,
    RPCError,
    RateLimitError,
    UnsupportedMethodError,
)

ساختار کلی:

AioShadError
├── AuthenticationError
│   └── InvalidSessionError
├── RateLimitError
├── UnsupportedMethodError
└── RPCError

نمونه:

from aioshad import AuthenticationError, RPCError

try:
    await app.connect()
except AuthenticationError:
    print("خطای احراز هویت")
except RPCError as exc:
    print("RPC error:", exc)

🧪 یک نمونه پروژهٔ کامل

import asyncio

from aioshad import Client, TimeName, filters

app = Client(
    "0937xxxxxxxx",
    session_directory="./sessions",
)


@app.on_message(filters.command("ping"))
async def ping(message):
    await message.reply("pong 🏓")


@app.on_message(filters.private & filters.text)
async def private_text(message):
    print("Private:", message.text)


@app.on_message(filters.media)
async def media(message):
    print("Media:", message.message_type)


async def main():
    await app.connect()

    # تغییر نام بر اساس زمان
    await app.presence.start_time_name(
        TimeName(
            format="⏰ {time}",
            timezone="Asia/Tehran",
            interval=60,
        )
    )

    # پاسخ خودکار
    app.autoreply.add("سلام", "سلام! 👋")
    await app.autoreply.enable()

    await app.run_until_disconnected()


try:
    asyncio.run(main())
except KeyboardInterrupt:
    pass

🗂️ ساختار پروژه

ساختار نسخهٔ فعلی:

aioshad/
├── aioshad/
│   ├── __init__.py
│   ├── client.py
│   ├── config.py
│   ├── crypto.py
│   ├── dispatcher.py
│   ├── errors.py
│   ├── features.py
│   ├── filters.py
│   ├── methods.py
│   ├── network.py
│   ├── rate_limit.py
│   ├── session.py
│   ├── py.typed
│   └── types/
│       ├── __init__.py
│       ├── chat.py
│       ├── message.py
│       └── user.py
├── examples/
│   ├── selfbot.py
│   └── time_name.py
├── tests/
│   └── test_core.py
├── pyproject.toml
├── setup.py
├── requirements.txt
├── MANIFEST.in
├── CHANGELOG.md
├── LICENSE
└── README.md

🧠 معماری داخلی

                    ┌─────────────────┐
                    │     Client      │
                    └────────┬────────┘
        ┌────────────────────┼────────────────────┐
        │                    │                    │
        ▼                    ▼                    ▼
   Dispatcher             Methods             Features
        │                    │            ┌──────┼──────┐
        │                    │            │      │      │
        ▼                    ▼            ▼      ▼      ▼
     Filters             Transport     Profile TimeName AutoReply
                    ┌────────┼────────┐
                    ▼        ▼        ▼
                  HTTP/2   Retry   Rate Limit
                           Shad

📋 وابستگی‌ها

پروژه به‌صورت رسمی این وابستگی‌ها را تعریف می‌کند:

httpx >= 0.27.0
h2 >= 4.0.0
cryptography >= 42.0.0
Pillow >= 10.0.0

🧪 تست

برای اجرای تست‌های پروژه:

pytest

تست‌های موجود روی بخش‌های هسته مانند Session، Modelها، Filterها، Rate Limiter و Config متمرکزند.

تست زندهٔ شبکه به‌صورت پیش‌فرض نیازمند یک اکانت معتبر و سرویس فعال است.


⚠️ محدودیت‌ها و نکات سازگاری

aioshad مستقیماً به پروتکل و endpointهای شاد وابسته است. در نتیجه ممکن است با تغییر سمت سرویس، بعضی متدها نیاز به به‌روزرسانی داشته باشند.

چند نکتهٔ مهم:

  • APIهای داخلی شاد ممکن است تغییر کنند.
  • Hostهای سرویس ممکن است جابه‌جا یا غیرفعال شوند.
  • رفتار Voice Chat به endpoint و payload فعال وابسته است.
  • invoke() برای RPCهای جدید یا wrapperنشده وجود دارد.
  • قابلیت‌های ادعاشده در این README بر اساس API موجود در نسخهٔ فعلی پروژه مستند شده‌اند؛ قابلیت‌هایی که در سورس وجود ندارند عمداً به‌عنوان API رسمی این نسخه معرفی نشده‌اند.

🔒 امنیت

برای استفادهٔ امن:

✅ Session را خصوصی نگه دارید
✅ Token/Key را در کد عمومی نگذارید
✅ پوشهٔ sessions را به Git اضافه نکنید
✅ از Session اکانت دیگران استفاده نکنید
✅ Rate Limit را جدی بگیرید

پیشنهاد برای .gitignore:

sessions/
*.session
.env

📜 مجوز

این پروژه با مجوز MIT ارائه شده است.


👨‍💻 سازنده

ابوالفضل سلیمانی

توسعه‌دهندهٔ پروژهٔ aioshad.

🔗 GitHub:

https://github.com/shanduzgil

📢 Telegram:

https://t.me/hacker_king_sog


⭐ پشتیبانی و توسعه

برای توسعهٔ پروژه، Issue و Pull Request را از طریق GitHub ارسال کنید:

https://github.com/shanduzgil


### 🟦 aioshad **Async Python Client / Self Account for Shad** ساخته‌شده با ❤️ توسط **ابوالفضل سلیمانی**

Lifecycle (1.0.5)

import asyncio
from aioshad import Client

app = Client(
    phone_number="0937xxxxxxxx",
    session_directory="./sessions",
)

async def main():
    await app.start()

if __name__ == "__main__":
    asyncio.run(main())

برای اجرای background:

await app.start_in_background()
# application work
await app.stop()

connect() اتصال را آماده می‌کند؛ start() چرخهٔ کامل اجرا را شروع می‌کند؛ run_until_disconnected() برای اجرای طولانی‌مدت است؛ و stop() باید shutdown را کامل کند.

Changelog

v1.0.10

  • 🎉 Stable release
  • 🐛 TimeName: preserve_first_name=True works correctly
  • 🐛 TimeName: stop_time_name() restores the original first name
  • 🐛 TimeName: added time_full (HH:MM:SS) format variable
  • 🐛 TimeName: interval minimum enforced at 60s (shad rate limit)
  • 🐛 TimeName: automatic retry with backoff on TOO_REQUESTS
  • 🐛 Scheduler.every: works as a decorator: @scheduler.every(30)
  • 🐛 filters.media: instance (no () needed)
  • 🐛 filters.command(prefixes="/"): works without commands
  • 🐛 Clearer TypeError for filter classes without ()
  • 🐛 Add missing import re (methods.py, features.py)
  • 🐛 Replace deprecated asyncio.iscoroutinefunction
  • 🔇 Reduce httpx log verbosity
    [aioshad در PyPI](https://pypi.org/project/aioshad/)