babismm 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
babismm-1.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
babismm-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,144 @@
1
+ Metadata-Version: 2.4
2
+ Name: babismm
3
+ Version: 1.0.0
4
+ Summary: A professional, robust, and highly pythonic client for SMM (Social Media Marketing) panels.
5
+ License: MIT
6
+ Classifier: Development Status :: 5 - Production/Stable
7
+ Classifier: Intended Audience :: Developers
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.7
12
+ Classifier: Programming Language :: Python :: 3.8
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
+ Requires-Python: >=3.7
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: requests>=2.25.0
22
+ Dynamic: license-file
23
+
24
+ # SMM Panel Client
25
+
26
+ A professional, robust, and highly pythonic API client for SMM (Social Media Marketing) panels.
27
+
28
+ Developed with performance, reliability, and security in mind, this package acts as a standard client compatible with any SMM panel using the Perfect Panel or similar API v2 format.
29
+
30
+ ## Features
31
+
32
+ - **Connection Pooling**: Reuses TCP connections via `requests.Session()` to make sequential requests blazing fast.
33
+ - **Context Manager Support**: Easily manage resources using the `with` statement.
34
+ - **Robust Exception Handling**: Offers descriptive custom exception classes for different error categories (network, response formatting, and API errors).
35
+ - **Flexible Order Management**: Supports standard, custom comments, package, drip-feed, and **Subscription** orders out of the box.
36
+ - **Security-First**: Excludes the API Key from default object representations (`__repr__`) to prevent accidental leaks in logs.
37
+ - **Modern User-Agent**: Configured with a modern browser User-Agent to prevent Cloudflare and WAF blockers from rejecting requests.
38
+
39
+ ---
40
+
41
+ ## Installation
42
+
43
+ You can install the package directly from PyPI:
44
+
45
+ ```bash
46
+ pip install smm-panel-client
47
+ ```
48
+
49
+ ---
50
+
51
+ ## Quick Start
52
+
53
+ ### Basic Usage
54
+
55
+ ```python
56
+ from smm import SMM, SMMError, SMMAPIError
57
+
58
+ # Initialize the client
59
+ API_URL = "https://your-smm-panel-domain.com/api/v2"
60
+ API_KEY = "your_secret_api_key"
61
+
62
+ with SMM(api_url=API_URL, api_key=API_KEY) as client:
63
+ try:
64
+ # Check balance
65
+ balance_info = client.get_balance()
66
+ print(f"Current Balance: {balance_info['balance']} {balance_info['currency']}")
67
+
68
+ # Get list of services
69
+ services = client.get_services()
70
+ print(f"Total services available: {len(services)}")
71
+
72
+ except SMMAPIError as e:
73
+ print(f"API Error occurred: {e}")
74
+ except SMMError as e:
75
+ print(f"An SMM client error occurred: {e}")
76
+ ```
77
+
78
+ ### Creating Orders
79
+
80
+ #### 1. Standard Order
81
+ ```python
82
+ order = client.add_order(
83
+ service=100, # Service ID
84
+ link="https://www.instagram.com/p/abcdefg/",
85
+ quantity=1000
86
+ )
87
+ print(f"Order placed successfully. Order ID: {order['order']}")
88
+ ```
89
+
90
+ #### 2. Subscription Order (No link/quantity required)
91
+ ```python
92
+ subscription = client.add_order(
93
+ service=205, # Subscription Service ID
94
+ username="john_doe",
95
+ min=100, # Min likes per post
96
+ max=500, # Max likes per post
97
+ posts=10, # Cover next 10 posts
98
+ delay=5 # Delay in minutes
99
+ )
100
+ print(f"Subscription active. ID: {subscription['order']}")
101
+ ```
102
+
103
+ #### 3. Drip-Feed Order
104
+ ```python
105
+ drip_feed = client.add_order(
106
+ service=120,
107
+ link="https://www.youtube.com/watch?v=xxxx",
108
+ quantity=1000,
109
+ runs=5,
110
+ interval=60 # 60 minutes between runs
111
+ )
112
+ print(f"Drip-feed order created: {drip_feed['order']}")
113
+ ```
114
+
115
+ ---
116
+
117
+ ## Error Handling
118
+
119
+ This package provides granular exceptions to handle different failure modes:
120
+
121
+ - `SMMError`: Base exception for all errors.
122
+ - `SMMNetworkError`: Raised during TCP connection failures, timeouts, or when the server responds with a non-2xx HTTP status.
123
+ - `SMMResponseError`: Raised when the response is not valid JSON (e.g. if the panel returns a Cloudflare block page or maintenance page).
124
+ - `SMMAPIError`: Raised when the HTTP response is 200 OK but contains a panel-level error message like `{"error": "Invalid API key"}`.
125
+
126
+ Example:
127
+ ```python
128
+ from smm import SMM, SMMNetworkError, SMMResponseError, SMMAPIError
129
+
130
+ try:
131
+ client.get_balance()
132
+ except SMMNetworkError as e:
133
+ print("Network issue or SMM server down.")
134
+ except SMMResponseError as e:
135
+ print(f"Invalid response from server. Status: {e.status_code}")
136
+ except SMMAPIError as e:
137
+ print(f"API rejected the request: {e}")
138
+ ```
139
+
140
+ ---
141
+
142
+ ## License
143
+
144
+ This project is licensed under the MIT License - see the LICENSE file for details.
@@ -0,0 +1,121 @@
1
+ # SMM Panel Client
2
+
3
+ A professional, robust, and highly pythonic API client for SMM (Social Media Marketing) panels.
4
+
5
+ Developed with performance, reliability, and security in mind, this package acts as a standard client compatible with any SMM panel using the Perfect Panel or similar API v2 format.
6
+
7
+ ## Features
8
+
9
+ - **Connection Pooling**: Reuses TCP connections via `requests.Session()` to make sequential requests blazing fast.
10
+ - **Context Manager Support**: Easily manage resources using the `with` statement.
11
+ - **Robust Exception Handling**: Offers descriptive custom exception classes for different error categories (network, response formatting, and API errors).
12
+ - **Flexible Order Management**: Supports standard, custom comments, package, drip-feed, and **Subscription** orders out of the box.
13
+ - **Security-First**: Excludes the API Key from default object representations (`__repr__`) to prevent accidental leaks in logs.
14
+ - **Modern User-Agent**: Configured with a modern browser User-Agent to prevent Cloudflare and WAF blockers from rejecting requests.
15
+
16
+ ---
17
+
18
+ ## Installation
19
+
20
+ You can install the package directly from PyPI:
21
+
22
+ ```bash
23
+ pip install smm-panel-client
24
+ ```
25
+
26
+ ---
27
+
28
+ ## Quick Start
29
+
30
+ ### Basic Usage
31
+
32
+ ```python
33
+ from smm import SMM, SMMError, SMMAPIError
34
+
35
+ # Initialize the client
36
+ API_URL = "https://your-smm-panel-domain.com/api/v2"
37
+ API_KEY = "your_secret_api_key"
38
+
39
+ with SMM(api_url=API_URL, api_key=API_KEY) as client:
40
+ try:
41
+ # Check balance
42
+ balance_info = client.get_balance()
43
+ print(f"Current Balance: {balance_info['balance']} {balance_info['currency']}")
44
+
45
+ # Get list of services
46
+ services = client.get_services()
47
+ print(f"Total services available: {len(services)}")
48
+
49
+ except SMMAPIError as e:
50
+ print(f"API Error occurred: {e}")
51
+ except SMMError as e:
52
+ print(f"An SMM client error occurred: {e}")
53
+ ```
54
+
55
+ ### Creating Orders
56
+
57
+ #### 1. Standard Order
58
+ ```python
59
+ order = client.add_order(
60
+ service=100, # Service ID
61
+ link="https://www.instagram.com/p/abcdefg/",
62
+ quantity=1000
63
+ )
64
+ print(f"Order placed successfully. Order ID: {order['order']}")
65
+ ```
66
+
67
+ #### 2. Subscription Order (No link/quantity required)
68
+ ```python
69
+ subscription = client.add_order(
70
+ service=205, # Subscription Service ID
71
+ username="john_doe",
72
+ min=100, # Min likes per post
73
+ max=500, # Max likes per post
74
+ posts=10, # Cover next 10 posts
75
+ delay=5 # Delay in minutes
76
+ )
77
+ print(f"Subscription active. ID: {subscription['order']}")
78
+ ```
79
+
80
+ #### 3. Drip-Feed Order
81
+ ```python
82
+ drip_feed = client.add_order(
83
+ service=120,
84
+ link="https://www.youtube.com/watch?v=xxxx",
85
+ quantity=1000,
86
+ runs=5,
87
+ interval=60 # 60 minutes between runs
88
+ )
89
+ print(f"Drip-feed order created: {drip_feed['order']}")
90
+ ```
91
+
92
+ ---
93
+
94
+ ## Error Handling
95
+
96
+ This package provides granular exceptions to handle different failure modes:
97
+
98
+ - `SMMError`: Base exception for all errors.
99
+ - `SMMNetworkError`: Raised during TCP connection failures, timeouts, or when the server responds with a non-2xx HTTP status.
100
+ - `SMMResponseError`: Raised when the response is not valid JSON (e.g. if the panel returns a Cloudflare block page or maintenance page).
101
+ - `SMMAPIError`: Raised when the HTTP response is 200 OK but contains a panel-level error message like `{"error": "Invalid API key"}`.
102
+
103
+ Example:
104
+ ```python
105
+ from smm import SMM, SMMNetworkError, SMMResponseError, SMMAPIError
106
+
107
+ try:
108
+ client.get_balance()
109
+ except SMMNetworkError as e:
110
+ print("Network issue or SMM server down.")
111
+ except SMMResponseError as e:
112
+ print(f"Invalid response from server. Status: {e.status_code}")
113
+ except SMMAPIError as e:
114
+ print(f"API rejected the request: {e}")
115
+ ```
116
+
117
+ ---
118
+
119
+ ## License
120
+
121
+ This project is licensed under the MIT License - see the LICENSE file for details.
@@ -0,0 +1,144 @@
1
+ Metadata-Version: 2.4
2
+ Name: babismm
3
+ Version: 1.0.0
4
+ Summary: A professional, robust, and highly pythonic client for SMM (Social Media Marketing) panels.
5
+ License: MIT
6
+ Classifier: Development Status :: 5 - Production/Stable
7
+ Classifier: Intended Audience :: Developers
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.7
12
+ Classifier: Programming Language :: Python :: 3.8
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
+ Requires-Python: >=3.7
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: requests>=2.25.0
22
+ Dynamic: license-file
23
+
24
+ # SMM Panel Client
25
+
26
+ A professional, robust, and highly pythonic API client for SMM (Social Media Marketing) panels.
27
+
28
+ Developed with performance, reliability, and security in mind, this package acts as a standard client compatible with any SMM panel using the Perfect Panel or similar API v2 format.
29
+
30
+ ## Features
31
+
32
+ - **Connection Pooling**: Reuses TCP connections via `requests.Session()` to make sequential requests blazing fast.
33
+ - **Context Manager Support**: Easily manage resources using the `with` statement.
34
+ - **Robust Exception Handling**: Offers descriptive custom exception classes for different error categories (network, response formatting, and API errors).
35
+ - **Flexible Order Management**: Supports standard, custom comments, package, drip-feed, and **Subscription** orders out of the box.
36
+ - **Security-First**: Excludes the API Key from default object representations (`__repr__`) to prevent accidental leaks in logs.
37
+ - **Modern User-Agent**: Configured with a modern browser User-Agent to prevent Cloudflare and WAF blockers from rejecting requests.
38
+
39
+ ---
40
+
41
+ ## Installation
42
+
43
+ You can install the package directly from PyPI:
44
+
45
+ ```bash
46
+ pip install smm-panel-client
47
+ ```
48
+
49
+ ---
50
+
51
+ ## Quick Start
52
+
53
+ ### Basic Usage
54
+
55
+ ```python
56
+ from smm import SMM, SMMError, SMMAPIError
57
+
58
+ # Initialize the client
59
+ API_URL = "https://your-smm-panel-domain.com/api/v2"
60
+ API_KEY = "your_secret_api_key"
61
+
62
+ with SMM(api_url=API_URL, api_key=API_KEY) as client:
63
+ try:
64
+ # Check balance
65
+ balance_info = client.get_balance()
66
+ print(f"Current Balance: {balance_info['balance']} {balance_info['currency']}")
67
+
68
+ # Get list of services
69
+ services = client.get_services()
70
+ print(f"Total services available: {len(services)}")
71
+
72
+ except SMMAPIError as e:
73
+ print(f"API Error occurred: {e}")
74
+ except SMMError as e:
75
+ print(f"An SMM client error occurred: {e}")
76
+ ```
77
+
78
+ ### Creating Orders
79
+
80
+ #### 1. Standard Order
81
+ ```python
82
+ order = client.add_order(
83
+ service=100, # Service ID
84
+ link="https://www.instagram.com/p/abcdefg/",
85
+ quantity=1000
86
+ )
87
+ print(f"Order placed successfully. Order ID: {order['order']}")
88
+ ```
89
+
90
+ #### 2. Subscription Order (No link/quantity required)
91
+ ```python
92
+ subscription = client.add_order(
93
+ service=205, # Subscription Service ID
94
+ username="john_doe",
95
+ min=100, # Min likes per post
96
+ max=500, # Max likes per post
97
+ posts=10, # Cover next 10 posts
98
+ delay=5 # Delay in minutes
99
+ )
100
+ print(f"Subscription active. ID: {subscription['order']}")
101
+ ```
102
+
103
+ #### 3. Drip-Feed Order
104
+ ```python
105
+ drip_feed = client.add_order(
106
+ service=120,
107
+ link="https://www.youtube.com/watch?v=xxxx",
108
+ quantity=1000,
109
+ runs=5,
110
+ interval=60 # 60 minutes between runs
111
+ )
112
+ print(f"Drip-feed order created: {drip_feed['order']}")
113
+ ```
114
+
115
+ ---
116
+
117
+ ## Error Handling
118
+
119
+ This package provides granular exceptions to handle different failure modes:
120
+
121
+ - `SMMError`: Base exception for all errors.
122
+ - `SMMNetworkError`: Raised during TCP connection failures, timeouts, or when the server responds with a non-2xx HTTP status.
123
+ - `SMMResponseError`: Raised when the response is not valid JSON (e.g. if the panel returns a Cloudflare block page or maintenance page).
124
+ - `SMMAPIError`: Raised when the HTTP response is 200 OK but contains a panel-level error message like `{"error": "Invalid API key"}`.
125
+
126
+ Example:
127
+ ```python
128
+ from smm import SMM, SMMNetworkError, SMMResponseError, SMMAPIError
129
+
130
+ try:
131
+ client.get_balance()
132
+ except SMMNetworkError as e:
133
+ print("Network issue or SMM server down.")
134
+ except SMMResponseError as e:
135
+ print(f"Invalid response from server. Status: {e.status_code}")
136
+ except SMMAPIError as e:
137
+ print(f"API rejected the request: {e}")
138
+ ```
139
+
140
+ ---
141
+
142
+ ## License
143
+
144
+ This project is licensed under the MIT License - see the LICENSE file for details.
@@ -0,0 +1,10 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ babismm.egg-info/PKG-INFO
5
+ babismm.egg-info/SOURCES.txt
6
+ babismm.egg-info/dependency_links.txt
7
+ babismm.egg-info/requires.txt
8
+ babismm.egg-info/top_level.txt
9
+ smm/__init__.py
10
+ smm/client.py
@@ -0,0 +1 @@
1
+ requests>=2.25.0
@@ -0,0 +1 @@
1
+ smm
@@ -0,0 +1,32 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "babismm"
7
+ version = "1.0.0"
8
+ description = "A professional, robust, and highly pythonic client for SMM (Social Media Marketing) panels."
9
+ readme = "README.md"
10
+ requires-python = ">=3.7"
11
+ license = { text = "MIT" }
12
+ classifiers = [
13
+ "Development Status :: 5 - Production/Stable",
14
+ "Intended Audience :: Developers",
15
+ "License :: OSI Approved :: MIT License",
16
+ "Operating System :: OS Independent",
17
+ "Programming Language :: Python :: 3",
18
+ "Programming Language :: Python :: 3.7",
19
+ "Programming Language :: Python :: 3.8",
20
+ "Programming Language :: Python :: 3.9",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Topic :: Software Development :: Libraries :: Python Modules",
25
+ ]
26
+ dependencies = [
27
+ "requests>=2.25.0",
28
+ ]
29
+
30
+ [tool.setuptools.packages.find]
31
+ where = ["."]
32
+ include = ["smm*"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,11 @@
1
+ from .client import SMM, SMMError, SMMNetworkError, SMMResponseError, SMMAPIError, smm
2
+
3
+ __version__ = "1.0.0"
4
+ __all__ = [
5
+ "SMM",
6
+ "SMMError",
7
+ "SMMNetworkError",
8
+ "SMMResponseError",
9
+ "SMMAPIError",
10
+ "smm",
11
+ ]
@@ -0,0 +1,236 @@
1
+ import requests
2
+ import json
3
+ from typing import Optional, Dict, List, Any, Union
4
+
5
+ class SMMError(Exception):
6
+ """Base exception for all SMM API client errors."""
7
+ pass
8
+
9
+ class SMMNetworkError(SMMError):
10
+ """Raised when a network-level error or non-2xx HTTP status occurs."""
11
+ def __init__(self, message: str, response: Optional[requests.Response] = None):
12
+ super().__init__(message)
13
+ self.response = response
14
+
15
+ class SMMResponseError(SMMError):
16
+ """Raised when the SMM API returns an invalid or unparsable response (e.g. HTML error pages)."""
17
+ def __init__(self, message: str, status_code: int, response_text: str):
18
+ super().__init__(message)
19
+ self.status_code = status_code
20
+ self.response_text = response_text
21
+
22
+ class SMMAPIError(SMMError):
23
+ """Raised when the API returns a successful HTTP response but contains an error message."""
24
+ pass
25
+
26
+ class SMM:
27
+ """
28
+ SMM API Client
29
+ """
30
+ def __init__(
31
+ self,
32
+ api_url: str,
33
+ api_key: str,
34
+ session: Optional[requests.Session] = None,
35
+ timeout: float = 30.0
36
+ ):
37
+ """
38
+ Initialize the SMM API Client.
39
+
40
+ Args:
41
+ api_url: The API endpoint URL (e.g., 'https://smm-panel.com/api/v2').
42
+ api_key: Your API Key.
43
+ session: Optional custom requests.Session object for connection pooling.
44
+ timeout: Default timeout for API requests in seconds.
45
+ """
46
+ self.api_url = api_url.rstrip('/')
47
+ self.api_key = api_key
48
+ self.session = session or requests.Session()
49
+ self.timeout = timeout
50
+
51
+ # Modern, professional User-Agent to avoid getting blocked by WAF/Cloudflare
52
+ self.user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
53
+
54
+ def __repr__(self) -> str:
55
+ # Prevent exposing the sensitive API Key in logs or console printouts
56
+ return f"SMM(api_url='{self.api_url}', timeout={self.timeout})"
57
+
58
+ def __enter__(self) -> 'SMM':
59
+ return self
60
+
61
+ def __exit__(self, exc_type, exc_val, exc_tb) -> None:
62
+ self.close()
63
+
64
+ def close(self) -> None:
65
+ """Close the underlying requests Session."""
66
+ if hasattr(self, 'session') and self.session:
67
+ self.session.close()
68
+
69
+ def _request(self, action: str, data: Optional[Dict[str, Any]] = None) -> Any:
70
+ """
71
+ Send a POST request to the SMM provider.
72
+ """
73
+ form_data = {
74
+ 'key': self.api_key,
75
+ 'action': action
76
+ }
77
+
78
+ if data:
79
+ for key, value in data.items():
80
+ if value is None:
81
+ continue
82
+ # Handle Boolean conversion properly (SMM panels typically expect 1 or 0, or true/false)
83
+ if isinstance(value, bool):
84
+ form_data[key] = '1' if value else '0'
85
+ else:
86
+ form_data[key] = value
87
+
88
+ headers = {
89
+ 'User-Agent': self.user_agent,
90
+ }
91
+
92
+ try:
93
+ # Let requests do the form encoding automatically.
94
+ # Timeout is explicitly set to prevent infinite hanging.
95
+ response = self.session.post(
96
+ self.api_url,
97
+ data=form_data,
98
+ headers=headers,
99
+ timeout=self.timeout
100
+ )
101
+ response.raise_for_status()
102
+
103
+ except requests.exceptions.HTTPError as e:
104
+ raise SMMNetworkError(
105
+ f"HTTP status error: {e.response.status_code} - {e.response.reason}",
106
+ response=e.response
107
+ ) from e
108
+ except requests.exceptions.RequestException as e:
109
+ raise SMMNetworkError(f"Network request failed: {e}") from e
110
+
111
+ # Safely parse JSON to avoid crash on HTML errors (e.g. Cloudflare, 502 Bad Gateway)
112
+ try:
113
+ result = response.json()
114
+ except (ValueError, TypeError) as e:
115
+ # SMM panels sometimes return text/html even for JSON on errors.
116
+ snippet = response.text[:200] if response.text else "(empty response)"
117
+ raise SMMResponseError(
118
+ f"Failed to parse JSON response. Status code: {response.status_code}. Content snippet: {snippet}",
119
+ status_code=response.status_code,
120
+ response_text=response.text
121
+ ) from e
122
+
123
+ # Handle API level error in a successful HTTP response
124
+ if isinstance(result, dict) and result.get('error'):
125
+ raise SMMAPIError(result['error'])
126
+
127
+ return result
128
+
129
+ def get_services(self) -> List[Dict[str, Any]]:
130
+ """
131
+ Retrieve list of all services.
132
+ """
133
+ return self._request('services')
134
+
135
+ def get_status(self, order_id: Union[str, int]) -> Dict[str, Any]:
136
+ """
137
+ Get status of a single order.
138
+ """
139
+ return self._request('status', {'order': order_id})
140
+
141
+ def get_multi_status(self, order_ids: List[Union[str, int]]) -> Dict[str, Any]:
142
+ """
143
+ Get status of multiple orders.
144
+ """
145
+ return self._request('status', {'orders': ','.join(map(str, order_ids))})
146
+
147
+ def create_refill(self, order_id: Union[str, int]) -> Dict[str, Any]:
148
+ """
149
+ Create refill request for a single order.
150
+ """
151
+ return self._request('refill', {'order': order_id})
152
+
153
+ def create_multi_refill(self, order_ids: List[Union[str, int]]) -> List[Any]:
154
+ """
155
+ Create refill requests for multiple orders.
156
+ """
157
+ return self._request('refill', {'orders': ','.join(map(str, order_ids))})
158
+
159
+ def get_refill_status(self, refill_id: Union[str, int]) -> Dict[str, Any]:
160
+ """
161
+ Get status of a single refill request.
162
+ """
163
+ return self._request('refill_status', {'refill': refill_id})
164
+
165
+ def get_multi_refill_status(self, refill_ids: List[Union[str, int]]) -> List[Any]:
166
+ """
167
+ Get status of multiple refill requests.
168
+ """
169
+ return self._request('refill_status', {'refills': ','.join(map(str, refill_ids))})
170
+
171
+ def cancel_orders(self, order_ids: List[Union[str, int]]) -> List[Any]:
172
+ """
173
+ Request cancellation of multiple orders.
174
+ """
175
+ return self._request('cancel', {'orders': ','.join(map(str, order_ids))})
176
+
177
+ def get_balance(self) -> Dict[str, str]:
178
+ """
179
+ Get user account balance.
180
+ """
181
+ return self._request('balance')
182
+
183
+ def add_order(
184
+ self,
185
+ service: Union[int, str],
186
+ link: Optional[str] = None,
187
+ quantity: Optional[int] = None,
188
+ comments: Optional[str] = None,
189
+ runs: Optional[int] = None,
190
+ interval: Optional[int] = None,
191
+ username: Optional[str] = None,
192
+ min: Optional[int] = None,
193
+ max: Optional[int] = None,
194
+ posts: Optional[int] = None,
195
+ delay: Optional[int] = None,
196
+ expiry: Optional[str] = None,
197
+ **kwargs: Any
198
+ ) -> Dict[str, Any]:
199
+ """
200
+ Add a new order.
201
+ Supports standard, package, drip-feed, custom comments, and subscription orders.
202
+
203
+ Args:
204
+ service: Service ID.
205
+ link: Link to target (required for standard/package/drip-feed).
206
+ quantity: Quantity (required for standard/drip-feed).
207
+ comments: Custom comments (comma/newline separated).
208
+ runs: Number of runs for drip-feed.
209
+ interval: Interval between runs in minutes for drip-feed.
210
+ username: Username for subscriptions.
211
+ min: Minimum quantity per post for subscriptions.
212
+ max: Maximum quantity per post for subscriptions.
213
+ posts: Number of posts to cover for subscriptions.
214
+ delay: Delay in minutes for subscriptions.
215
+ expiry: Expiry date for subscriptions.
216
+ **kwargs: Any additional custom parameters required by the panel.
217
+ """
218
+ params = {
219
+ 'service': service,
220
+ 'link': link,
221
+ 'quantity': quantity,
222
+ 'comments': comments,
223
+ 'runs': runs,
224
+ 'interval': interval,
225
+ 'username': username,
226
+ 'min': min,
227
+ 'max': max,
228
+ 'posts': posts,
229
+ 'delay': delay,
230
+ 'expiry': expiry,
231
+ **kwargs
232
+ }
233
+ return self._request('add', params)
234
+
235
+ # Backward compatibility alias
236
+ smm = SMM