A modern async Python library for interacting with Soroush Plus
Project description
SplusPy
A modern async Python library for Soroush Plus
What is SplusPy?
SplusPy is a modern, asynchronous Python library for interacting with Soroush Plus — both as a user account and a bot account.
Built from the ground up with clean architecture, it's designed to feel like Telethon or Pyrogram, but specifically for the Soroush Plus ecosystem.
Features
- No API Key Required — Built-in Soroush Plus credentials
- Fully Asynchronous — Built with Python's
asyncio - Sync Support — Use without
async/awaitviaspluspy.sync - Bot & User Support — Both account types
- Event-Driven Handlers — Powerful event system with decorators
- Filter System — Composable filters (
&,|,~) - Inline & Reply Buttons — Interactive keyboards
- Conversation API — For interactive bot flows
- FSM (Finite State Machine) — Built-in state management for bots
- Plugin System — Dynamic plugin loading
- Middleware — Pre/post processing of updates
- Scheduler — Built-in task scheduler
- Multiple Storage Backends — Memory, SQLite
- Professional Logging — Structured, namespaced loggers
- Type Hints Everywhere — Full type safety
- Clean Architecture — SOLID principles, modular design
Installation
pip install spluspy
For faster encryption:
pip install spluspy[speed]
Quick Start
Simplest Bot
from spluspy import Client
bot = Client("my_session")
@bot.on_message()
async def handler(m):
await m.reply("Hello!")
bot.run()
User Account
from spluspy import Client
client = Client("session_name")
@client.on_message()
async def handler(m):
await m.reply("Hey there!")
async def main():
await client.start(phone="+98XXXXXXXXXX")
await client.run_until_disconnected()
import asyncio
asyncio.run(main())
Sync Usage (No Async/Await)
from spluspy.sync import Client
bot = Client("session")
@bot.on_message()
def handler(m):
m.reply("Hello!")
bot.run()
Events
| Decorator | Event |
|---|---|
@bot.on_message() |
New message |
@bot.on_edited() |
Message edited |
@bot.on_callback_query() |
Inline button clicked |
@bot.on_inline_query() |
Inline query |
@bot.on_chat_action() |
Join/leave/pin |
@bot.on_user_update() |
Status change |
@bot.on_message_deleted() |
Message deleted |
@bot.on_message_read() |
Read receipt |
Filters
from spluspy import filters
@bot.on_message(filters.text) # Text only
@bot.on_message(filters.private) # Private chats
@bot.on_message(filters.group) # Groups
@bot.on_message(filters.command("start")) # /start command
@bot.on_message(filters.regex(r"\d+")) # Regex match
@bot.on_message(filters.user(123)) # Specific user
@bot.on_message(filters.text & filters.private) # Combined
@bot.on_message(filters.photo | filters.video) # Photo OR video
Message Methods
await m.reply("Hello") # Reply
await m.edit("New text") # Edit
await m.delete() # Delete
await m.forward(chat_id) # Forward
await m.copy(chat_id) # Copy (no forward header)
await m.pin() # Pin
await m.react("❤️") # React
await m.mark_read() # Mark as read
await m.download() # Download media
await m.reply_photo("photo.jpg") # Reply with photo
await m.reply_video("video.mp4") # Reply with video
await m.reply_document("file.pdf") # Reply with document
Buttons
from spluspy import Button
# Inline keyboard
keyboard = Button.build_inline(
[Button.inline("Option 1", b"opt1"), Button.inline("Option 2", b"opt2")]
)
await bot.send_message(chat_id, "Choose:", buttons=keyboard)
# Reply keyboard
kb = Button.build_reply(
[Button.text("Menu"), Button.text("Settings")]
)
await bot.send_message(chat_id, "Pick:", buttons=kb)
# Clear keyboard
await bot.send_message(chat_id, "Done", buttons=Button.clear())
FSM (State Machine)
from spluspy.fsm import State, StateMachine
from spluspy.storage import MemoryStorage
storage = MemoryStorage()
fsm = StateMachine(storage)
class Form:
name = State()
age = State()
@bot.on_message(filters.command("register"))
async def start_register(m):
ctx = fsm.context(m.sender_id)
await ctx.set_state(Form.name)
await m.reply("What is your name?")
@bot.on_message(filters.private)
async def process_form(m):
ctx = fsm.context(m.sender_id)
state = await ctx.get_state()
if state == Form.name:
await ctx.set_data(name=m.text)
await ctx.set_state(Form.age)
await m.reply("How old are you?")
elif state == Form.age:
await ctx.set_data(age=m.text)
await ctx.reset()
await m.reply(f"Registered! Name: {(await ctx.get_data()).get('name')}")
Plugin System
# plugins/hello.py
def register(client):
@client.on_message(filters.command("hello"))
async def hello_handler(m):
await m.reply("Hello from plugin!")
# main.py
from spluspy import Client
bot = Client("session")
bot.plugins.load("plugins")
bot.run()
Chat Management
await bot.ban_user(chat_id, user_id)
await bot.unban_user(chat_id, user_id)
await bot.mute_user(chat_id, user_id)
await bot.unmute_user(chat_id, user_id)
await bot.pin_message(chat_id, message)
await bot.unpin_message(chat_id, message)
await bot.join_chat(chat_id)
await bot.leave_chat(chat_id)
Project Structure
spluspy/
├── __init__.py # Public API
├── __version__.py # Version info
├── client/ # Client and conversation API
├── types/ # Domain models (Message, User, Chat, Media, etc.)
├── events/ # Event types and builders
├── filters/ # Composable message filters
├── errors/ # Custom exception hierarchy
├── session/ # Session backends (SQLite, Memory, String)
├── network/ # TCP connections and connection pool
├── storage/ # Key-value storage backends
├── plugins/ # Plugin loader
├── middleware/ # Middleware system
├── fsm/ # Finite state machine
├── scheduler/ # Task scheduler
├── utils/ # Logger, cache, helpers
└── sync/ # Synchronous client wrapper
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Run tests:
pytest - Submit a pull request
License
MIT License — see LICENSE for details.
Disclaimer
SPlusPy is an unofficial third-party library. Use it responsibly and ensure your applications comply with Soroush Plus's Terms of Service.
Made with ❤️ for the Soroush Plus community
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file spluspy-2.0.2.tar.gz.
File metadata
- Download URL: spluspy-2.0.2.tar.gz
- Upload date:
- Size: 70.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0dd183244279142b3db08156c4bdb306b81458a4a00c1250aebbab031fabcf03
|
|
| MD5 |
93928572f1b1282bc42d093d66523cf5
|
|
| BLAKE2b-256 |
6c2b505bb709714b9c6ca2ef942d7ea6f71556e2277b6d4668b5a49806c84bdd
|
File details
Details for the file spluspy-2.0.2-py3-none-any.whl.
File metadata
- Download URL: spluspy-2.0.2-py3-none-any.whl
- Upload date:
- Size: 74.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a37bca3b7c5263500050b77db6329a87ee9b22f0c972f4042a6583a1fc421584
|
|
| MD5 |
9f2e3fdd71f00370ffcd18584efac8d2
|
|
| BLAKE2b-256 |
d71360b173713d51aef41beb4bb3c79ed7393bb70fd1514036ea055a730f22b3
|