simotel-connect 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.
- simotel_connect-1.0.0/PKG-INFO +356 -0
- simotel_connect-1.0.0/README.md +333 -0
- simotel_connect-1.0.0/pyproject.toml +40 -0
- simotel_connect-1.0.0/setup.cfg +4 -0
- simotel_connect-1.0.0/setup.py +19 -0
- simotel_connect-1.0.0/simotel_connect/__init__.py +52 -0
- simotel_connect-1.0.0/simotel_connect/apps.py +11 -0
- simotel_connect-1.0.0/simotel_connect/client.py +260 -0
- simotel_connect-1.0.0/simotel_connect/config.py +160 -0
- simotel_connect-1.0.0/simotel_connect/exceptions.py +38 -0
- simotel_connect-1.0.0/simotel_connect/managers/__init__.py +1 -0
- simotel_connect-1.0.0/simotel_connect/managers/autodialer/__init__.py +32 -0
- simotel_connect-1.0.0/simotel_connect/managers/autodialer/announcements.py +55 -0
- simotel_connect-1.0.0/simotel_connect/managers/autodialer/campaigns.py +54 -0
- simotel_connect-1.0.0/simotel_connect/managers/autodialer/contacts.py +67 -0
- simotel_connect-1.0.0/simotel_connect/managers/autodialer/groups.py +61 -0
- simotel_connect-1.0.0/simotel_connect/managers/autodialer/reports.py +46 -0
- simotel_connect-1.0.0/simotel_connect/managers/autodialer/trunks.py +25 -0
- simotel_connect-1.0.0/simotel_connect/managers/base.py +67 -0
- simotel_connect-1.0.0/simotel_connect/managers/call/__init__.py +43 -0
- simotel_connect-1.0.0/simotel_connect/managers/call/originate.py +68 -0
- simotel_connect-1.0.0/simotel_connect/managers/pbx/__init__.py +42 -0
- simotel_connect-1.0.0/simotel_connect/managers/pbx/announcements.py +62 -0
- simotel_connect-1.0.0/simotel_connect/managers/pbx/blacklists.py +58 -0
- simotel_connect-1.0.0/simotel_connect/managers/pbx/faxes.py +47 -0
- simotel_connect-1.0.0/simotel_connect/managers/pbx/musiconholds.py +21 -0
- simotel_connect-1.0.0/simotel_connect/managers/pbx/queues.py +216 -0
- simotel_connect-1.0.0/simotel_connect/managers/pbx/trunks.py +75 -0
- simotel_connect-1.0.0/simotel_connect/managers/pbx/users.py +128 -0
- simotel_connect-1.0.0/simotel_connect/managers/pbx/whitelists.py +51 -0
- simotel_connect-1.0.0/simotel_connect/managers/reports/__init__.py +1 -0
- simotel_connect-1.0.0/simotel_connect/managers/reports/reports.py +177 -0
- simotel_connect-1.0.0/simotel_connect/managers/setting/__init__.py +1 -0
- simotel_connect-1.0.0/simotel_connect/managers/setting/ping.py +33 -0
- simotel_connect-1.0.0/simotel_connect/managers/voicemails/__init__.py +1 -0
- simotel_connect-1.0.0/simotel_connect/managers/voicemails/voicemails.py +73 -0
- simotel_connect-1.0.0/simotel_connect/response.py +39 -0
- simotel_connect-1.0.0/simotel_connect/simotel.py +171 -0
- simotel_connect-1.0.0/simotel_connect/tests/__init__.py +1 -0
- simotel_connect-1.0.0/simotel_connect/tests/conftest.py +58 -0
- simotel_connect-1.0.0/simotel_connect/tests/settings.py +22 -0
- simotel_connect-1.0.0/simotel_connect/tests/test_client.py +105 -0
- simotel_connect-1.0.0/simotel_connect/tests/test_managers.py +180 -0
- simotel_connect-1.0.0/simotel_connect.egg-info/PKG-INFO +356 -0
- simotel_connect-1.0.0/simotel_connect.egg-info/SOURCES.txt +46 -0
- simotel_connect-1.0.0/simotel_connect.egg-info/dependency_links.txt +1 -0
- simotel_connect-1.0.0/simotel_connect.egg-info/requires.txt +10 -0
- simotel_connect-1.0.0/simotel_connect.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: simotel-connect
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A professional Django/Python client for the Simotel PBX API
|
|
5
|
+
License: MIT
|
|
6
|
+
Keywords: simotel,pbx,voip,django,api,asterisk
|
|
7
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
8
|
+
Classifier: Intended Audience :: Developers
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Framework :: Django
|
|
12
|
+
Classifier: Topic :: Communications :: Telephony
|
|
13
|
+
Requires-Python: >=3.8
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
Requires-Dist: requests>=2.28.0
|
|
16
|
+
Provides-Extra: django
|
|
17
|
+
Requires-Dist: django>=3.2; extra == "django"
|
|
18
|
+
Provides-Extra: dev
|
|
19
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
20
|
+
Requires-Dist: pytest-django; extra == "dev"
|
|
21
|
+
Requires-Dist: responses>=0.23; extra == "dev"
|
|
22
|
+
Requires-Dist: django>=3.2; extra == "dev"
|
|
23
|
+
|
|
24
|
+
# 📞 Simotel Connect (کتابخانه پایتون و جنگو برای سیموتل)
|
|
25
|
+
|
|
26
|
+
[](https://pypi.org/project/simotel-connect/)
|
|
27
|
+
[](https://www.djangoproject.com/)
|
|
28
|
+
[](https://opensource.org/licenses/MIT)
|
|
29
|
+
|
|
30
|
+
یک پکیج پایتونی و ماژول Reusable Django حرفهای، مقیاسپذیر و تمیز برای ارتباط با وبسرویس **مرکز تلفن سیموتل (Simotel PBX API v4)**.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 🌟 ویژگیها
|
|
35
|
+
|
|
36
|
+
- 🔐 **پشتیبانی کامل از احراز هویت دوگانه سیموتل** (`X-APIKEY` به همراه HTTP Basic Auth)
|
|
37
|
+
- ⚙️ **سیستم کانفیگ انعطافپذیر و سه لایه** (Django `settings.py` > متغیرهای محیطی `.env` > ورودی مستقیم سازنده)
|
|
38
|
+
- 🏗️ **طراحی ماژولار با الگوهای Facade و Manager**: تمام متدها دستهبندیشده و خوانا
|
|
39
|
+
- 🔄 **مکانیزم Retry و Connection Pooling خودکار** با Session پایدار
|
|
40
|
+
- 🛡️ **مدیریت خطای جامع (Exception Handling)** با خطاهای اختصاصی
|
|
41
|
+
- 📊 **پوشش کامل بیش از ۸۰ اندپوینت سیموتل**:
|
|
42
|
+
- مدیریت کاربران و داخلیها (`users`)
|
|
43
|
+
- ترانکها (`trunks`)
|
|
44
|
+
- صفها و اپراتورها به صورت تک و گروهی (`queues`, `agents`)
|
|
45
|
+
- لیست سیاه و سفید (`blacklists`, `whitelists`)
|
|
46
|
+
- فایلهای صوتی و اعلامیهها (`announcements`)
|
|
47
|
+
- موسیقی انتظار (`musiconholds`)
|
|
48
|
+
- ارسال، دریافت و دانلود فکس (`faxes`)
|
|
49
|
+
- برقراری تماس خودکار (Click-to-Call / `originate`)
|
|
50
|
+
- صندوقهای صوتی و دانلود پیام (`voicemails`)
|
|
51
|
+
- گزارشات کامل CDR، صف، اپراتور، نظرسنجی و دانلود فایل صوتی مکالمه تک و دو کاناله (`reports`)
|
|
52
|
+
- ماژول تماس انبوه و کمپینها (`autodialer`)
|
|
53
|
+
- بررسی وضعیت اتصال (`ping`)
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 📦 نصب
|
|
58
|
+
|
|
59
|
+
نصب در محیط پروژه:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
pip install simotel-connect
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
یا برای توسعه به صورت Editable:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
git clone https://github.com/yourusername/simotel-django-app.git
|
|
69
|
+
cd simotel-django-app
|
|
70
|
+
pip install -e ".[dev]"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## ⚙️ راهاندازی و کانفیگ
|
|
76
|
+
|
|
77
|
+
### روش ۱: از طریق Django `settings.py` (توصیهشده برای پروژههای جنگو)
|
|
78
|
+
|
|
79
|
+
در فایل `settings.py` پروژه جنگو:
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
# settings.py
|
|
83
|
+
|
|
84
|
+
INSTALLED_APPS = [
|
|
85
|
+
...,
|
|
86
|
+
"simotel_connect",
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
SIMOTEL = {
|
|
90
|
+
"HOST": "192.168.1.10", # آدرس IP یا دامنه سرور سیموتل
|
|
91
|
+
"API_KEY": "YOUR_SIMOTEL_API_KEY", # از مسیر Maintenance > API Accounts
|
|
92
|
+
"USERNAME": "admin", # نام کاربری پنل سیموتل
|
|
93
|
+
"PASSWORD": "your_password", # رمز عبور سیموتل
|
|
94
|
+
"PORT": 80, # اختیاری (پیشفرض 80)
|
|
95
|
+
"SCHEME": "http", # اختیاری (پیشفرض http)
|
|
96
|
+
"TIMEOUT": 30, # اختیاری (پیشفرض 30 ثانیه)
|
|
97
|
+
"VERIFY_SSL": True, # اختیاری
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
سپس در هر کجای پروژه (Views, Celery Tasks, Services):
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
from simotel_connect import Simotel
|
|
105
|
+
|
|
106
|
+
# به صورت خودکار مقادیر را از settings.py میخواند
|
|
107
|
+
sm = Simotel()
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
### روش ۲: از طریق متغیرهای محیطی (`.env`)
|
|
113
|
+
|
|
114
|
+
```env
|
|
115
|
+
SIMOTEL_HOST=192.168.1.10
|
|
116
|
+
SIMOTEL_API_KEY=YOUR_SIMOTEL_API_KEY
|
|
117
|
+
SIMOTEL_USERNAME=admin
|
|
118
|
+
SIMOTEL_PASSWORD=your_password
|
|
119
|
+
SIMOTEL_TIMEOUT=30
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
from simotel_connect import Simotel
|
|
124
|
+
|
|
125
|
+
sm = Simotel()
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
### روش ۳: مقداردهی مستقیم (بدون جنگو یا چند سروری)
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
from simotel_connect import Simotel
|
|
134
|
+
|
|
135
|
+
sm = Simotel(
|
|
136
|
+
host="192.168.1.10",
|
|
137
|
+
api_key="YOUR_SIMOTEL_API_KEY",
|
|
138
|
+
username="admin",
|
|
139
|
+
password="your_password",
|
|
140
|
+
timeout=15,
|
|
141
|
+
)
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## 🚀 راهنمای کاربردی و مثالها
|
|
147
|
+
|
|
148
|
+
### ۱. تست وضعیت اتصال (Health Check)
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
response = sm.setting.ping()
|
|
152
|
+
if response.success:
|
|
153
|
+
print("اتصال به سیموتل برقرار است:", response.message)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
### ۲. برقراری تماس (Click-to-Call / Originate)
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
# تماس بین یک داخلی و شماره موبایل
|
|
162
|
+
resp = sm.call.originate(
|
|
163
|
+
src_type="internal",
|
|
164
|
+
src_number="1001",
|
|
165
|
+
dst_type="trunk",
|
|
166
|
+
dst_number="09121234567",
|
|
167
|
+
caller_id="1001"
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
# تماس بین دو داخلی
|
|
171
|
+
resp = sm.call.originate(
|
|
172
|
+
src_type="internal",
|
|
173
|
+
src_number="1001",
|
|
174
|
+
dst_type="internal",
|
|
175
|
+
dst_number="1002"
|
|
176
|
+
)
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
### ۳. مدیریت کاربران و داخلیها (Users)
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
# افزودن داخلی جدید
|
|
185
|
+
sm.pbx.users.add(
|
|
186
|
+
extension="1001",
|
|
187
|
+
name="علی رضایی",
|
|
188
|
+
password="StrongPassword123",
|
|
189
|
+
email="ali@example.com",
|
|
190
|
+
mobile="09121234567"
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
# جستجوی کاربران
|
|
194
|
+
users = sm.pbx.users.search(extension="1001")
|
|
195
|
+
print(users.data)
|
|
196
|
+
|
|
197
|
+
# ویرایش کاربر
|
|
198
|
+
sm.pbx.users.update(extension="1001", name="علی رضایی (پشتیبانی)")
|
|
199
|
+
|
|
200
|
+
# حذف کاربر
|
|
201
|
+
sm.pbx.users.remove(extension="1001")
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
### ۴. مدیریت صفها و اپراتورها (Queues)
|
|
207
|
+
|
|
208
|
+
```python
|
|
209
|
+
# ایجاد صف جدید
|
|
210
|
+
sm.pbx.queues.add(name="2000", strategy="leastrecent", timeout=30)
|
|
211
|
+
|
|
212
|
+
# افزودن اپراتور به صف
|
|
213
|
+
sm.pbx.queues.add_agent(queue="2000", agent="1001", penalty=0)
|
|
214
|
+
|
|
215
|
+
# شروع استراحت اپراتور (Pause)
|
|
216
|
+
sm.pbx.queues.pause_agent(queue="2000", agent="1001", reason="استراحت ناهار")
|
|
217
|
+
|
|
218
|
+
# پایان استراحت اپراتور (Resume)
|
|
219
|
+
sm.pbx.queues.resume_agent(queue="2000", agent="1001")
|
|
220
|
+
|
|
221
|
+
# افزودن دستهای اپراتورها
|
|
222
|
+
sm.pbx.queues.batch_add_agent(queue="2000", agents=["1001", "1002", "1003"])
|
|
223
|
+
|
|
224
|
+
# توقف دستهای اپراتورها
|
|
225
|
+
sm.pbx.queues.batch_pause_agent(queue="2000", agents=["1001", "1002"])
|
|
226
|
+
|
|
227
|
+
# خروج اپراتور از صف
|
|
228
|
+
sm.pbx.queues.remove_agent(queue="2000", agent="1001")
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
### ۵. گزارشات و دانلود صوت مکالمات (Reports)
|
|
234
|
+
|
|
235
|
+
```python
|
|
236
|
+
# گزارش CDR تماسها در بازه زمانی
|
|
237
|
+
cdr = sm.reports.cdr_search(
|
|
238
|
+
from_date="2024-01-01 08:00:00",
|
|
239
|
+
to_date="2024-01-31 18:00:00",
|
|
240
|
+
limit=50
|
|
241
|
+
)
|
|
242
|
+
for call in cdr.data:
|
|
243
|
+
print(call)
|
|
244
|
+
|
|
245
|
+
# گزارش صفها
|
|
246
|
+
queue_report = sm.reports.queue_search(queue="2000")
|
|
247
|
+
|
|
248
|
+
# گزارش عملکرد اپراتورها
|
|
249
|
+
agent_report = sm.reports.agent_search(agent="1001")
|
|
250
|
+
|
|
251
|
+
# دانلود فایل صوتی مکالمه ضبطشده
|
|
252
|
+
audio_bytes = sm.reports.download_audio(call_id="unique_call_id_123")
|
|
253
|
+
with open("recorded_call.wav", "wb") as f:
|
|
254
|
+
f.write(audio_bytes)
|
|
255
|
+
|
|
256
|
+
# دانلود مکالمه دو کاناله (کانال اپراتور و مشتری مجزا)
|
|
257
|
+
dual_audio = sm.reports.download_audio_dual_channel(call_id="unique_call_id_123")
|
|
258
|
+
with open("dual_call.wav", "wb") as f:
|
|
259
|
+
f.write(dual_audio)
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
### ۶. لیست سیاه و سفید (Blacklist & Whitelist)
|
|
265
|
+
|
|
266
|
+
```python
|
|
267
|
+
# مسدود کردن شماره مزاحم
|
|
268
|
+
sm.pbx.blacklists.add(number="09999999999", description="مزاحم تلفنی")
|
|
269
|
+
|
|
270
|
+
# رفع مسدودیت
|
|
271
|
+
sm.pbx.blacklists.remove(number="09999999999")
|
|
272
|
+
|
|
273
|
+
# افزودن به لیست سفید (مشتری VIP)
|
|
274
|
+
sm.pbx.whitelists.add(number="09120000000", description="مدیرعامل")
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
### ۷. تماس خودکار و کمپینها (Autodialer)
|
|
280
|
+
|
|
281
|
+
```python
|
|
282
|
+
# آپلود فایل صوتی کمپین
|
|
283
|
+
sm.autodialer.announcements.upload(
|
|
284
|
+
file_path="/path/to/promo.wav",
|
|
285
|
+
name="جشنواره_نوروزی"
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
# ایجاد گروه مخاطبین
|
|
289
|
+
sm.autodialer.groups.add(name="مشتریان_ویژه")
|
|
290
|
+
|
|
291
|
+
# افزودن مخاطب به گروه
|
|
292
|
+
sm.autodialer.contacts.add(
|
|
293
|
+
number="09121234567",
|
|
294
|
+
name="محمد محمدی",
|
|
295
|
+
group="مشتریان_ویژه"
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
# ایجاد کمپین تماس انبوه
|
|
299
|
+
sm.autodialer.campaigns.add(
|
|
300
|
+
name="کمپین عیدانه",
|
|
301
|
+
announcement="جشنواره_نوروزی",
|
|
302
|
+
group="مشتریان_ویژه",
|
|
303
|
+
trunk="main_trunk"
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
# مشاهده گزارشات کمپین
|
|
307
|
+
reports = sm.autodialer.reports.search(campaign="کمپین عیدانه")
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
## ⚠️ مدیریت خطاها (Exception Handling)
|
|
313
|
+
|
|
314
|
+
تمام خطاهای پکیج از `SimotelError` ارثبری دارند:
|
|
315
|
+
|
|
316
|
+
```python
|
|
317
|
+
from simotel_connect import (
|
|
318
|
+
Simotel,
|
|
319
|
+
SimotelError,
|
|
320
|
+
SimotelAuthError,
|
|
321
|
+
SimotelAPIError,
|
|
322
|
+
SimotelConnectionError,
|
|
323
|
+
SimotelTimeoutError,
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
sm = Simotel()
|
|
327
|
+
|
|
328
|
+
try:
|
|
329
|
+
sm.call.originate(src_type="internal", src_number="1001", dst_type="internal", dst_number="1002")
|
|
330
|
+
except SimotelAuthError:
|
|
331
|
+
print("خطا در نام کاربری، رمز عبور یا API Key سیموتل")
|
|
332
|
+
except SimotelAPIError as e:
|
|
333
|
+
print(f"سیموتل با پیام خطا پاسخ داد: {e.args[0]}")
|
|
334
|
+
print(f"اطلاعات خطا: {e.data}")
|
|
335
|
+
except SimotelConnectionError:
|
|
336
|
+
print("ارتباط با سرور سیموتل برقرار نشد (بررسی شبکه یا IP)")
|
|
337
|
+
except SimotelTimeoutError:
|
|
338
|
+
print("درخواست با تایماوت مواجه شد")
|
|
339
|
+
except SimotelError as e:
|
|
340
|
+
print(f"خطای نامشخص سیموتل: {e}")
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
## 🧪 اجرای تستها
|
|
346
|
+
|
|
347
|
+
```bash
|
|
348
|
+
pip install -e ".[dev]"
|
|
349
|
+
pytest simotel_connect/tests/ -v
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
## 📄 لایسنس
|
|
355
|
+
|
|
356
|
+
این پروژه تحت مجوز **MIT** منتشر شده است.
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
# 📞 Simotel Connect (کتابخانه پایتون و جنگو برای سیموتل)
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/simotel-connect/)
|
|
4
|
+
[](https://www.djangoproject.com/)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
|
|
7
|
+
یک پکیج پایتونی و ماژول Reusable Django حرفهای، مقیاسپذیر و تمیز برای ارتباط با وبسرویس **مرکز تلفن سیموتل (Simotel PBX API v4)**.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 🌟 ویژگیها
|
|
12
|
+
|
|
13
|
+
- 🔐 **پشتیبانی کامل از احراز هویت دوگانه سیموتل** (`X-APIKEY` به همراه HTTP Basic Auth)
|
|
14
|
+
- ⚙️ **سیستم کانفیگ انعطافپذیر و سه لایه** (Django `settings.py` > متغیرهای محیطی `.env` > ورودی مستقیم سازنده)
|
|
15
|
+
- 🏗️ **طراحی ماژولار با الگوهای Facade و Manager**: تمام متدها دستهبندیشده و خوانا
|
|
16
|
+
- 🔄 **مکانیزم Retry و Connection Pooling خودکار** با Session پایدار
|
|
17
|
+
- 🛡️ **مدیریت خطای جامع (Exception Handling)** با خطاهای اختصاصی
|
|
18
|
+
- 📊 **پوشش کامل بیش از ۸۰ اندپوینت سیموتل**:
|
|
19
|
+
- مدیریت کاربران و داخلیها (`users`)
|
|
20
|
+
- ترانکها (`trunks`)
|
|
21
|
+
- صفها و اپراتورها به صورت تک و گروهی (`queues`, `agents`)
|
|
22
|
+
- لیست سیاه و سفید (`blacklists`, `whitelists`)
|
|
23
|
+
- فایلهای صوتی و اعلامیهها (`announcements`)
|
|
24
|
+
- موسیقی انتظار (`musiconholds`)
|
|
25
|
+
- ارسال، دریافت و دانلود فکس (`faxes`)
|
|
26
|
+
- برقراری تماس خودکار (Click-to-Call / `originate`)
|
|
27
|
+
- صندوقهای صوتی و دانلود پیام (`voicemails`)
|
|
28
|
+
- گزارشات کامل CDR، صف، اپراتور، نظرسنجی و دانلود فایل صوتی مکالمه تک و دو کاناله (`reports`)
|
|
29
|
+
- ماژول تماس انبوه و کمپینها (`autodialer`)
|
|
30
|
+
- بررسی وضعیت اتصال (`ping`)
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 📦 نصب
|
|
35
|
+
|
|
36
|
+
نصب در محیط پروژه:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install simotel-connect
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
یا برای توسعه به صورت Editable:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
git clone https://github.com/yourusername/simotel-django-app.git
|
|
46
|
+
cd simotel-django-app
|
|
47
|
+
pip install -e ".[dev]"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## ⚙️ راهاندازی و کانفیگ
|
|
53
|
+
|
|
54
|
+
### روش ۱: از طریق Django `settings.py` (توصیهشده برای پروژههای جنگو)
|
|
55
|
+
|
|
56
|
+
در فایل `settings.py` پروژه جنگو:
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
# settings.py
|
|
60
|
+
|
|
61
|
+
INSTALLED_APPS = [
|
|
62
|
+
...,
|
|
63
|
+
"simotel_connect",
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
SIMOTEL = {
|
|
67
|
+
"HOST": "192.168.1.10", # آدرس IP یا دامنه سرور سیموتل
|
|
68
|
+
"API_KEY": "YOUR_SIMOTEL_API_KEY", # از مسیر Maintenance > API Accounts
|
|
69
|
+
"USERNAME": "admin", # نام کاربری پنل سیموتل
|
|
70
|
+
"PASSWORD": "your_password", # رمز عبور سیموتل
|
|
71
|
+
"PORT": 80, # اختیاری (پیشفرض 80)
|
|
72
|
+
"SCHEME": "http", # اختیاری (پیشفرض http)
|
|
73
|
+
"TIMEOUT": 30, # اختیاری (پیشفرض 30 ثانیه)
|
|
74
|
+
"VERIFY_SSL": True, # اختیاری
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
سپس در هر کجای پروژه (Views, Celery Tasks, Services):
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
from simotel_connect import Simotel
|
|
82
|
+
|
|
83
|
+
# به صورت خودکار مقادیر را از settings.py میخواند
|
|
84
|
+
sm = Simotel()
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
### روش ۲: از طریق متغیرهای محیطی (`.env`)
|
|
90
|
+
|
|
91
|
+
```env
|
|
92
|
+
SIMOTEL_HOST=192.168.1.10
|
|
93
|
+
SIMOTEL_API_KEY=YOUR_SIMOTEL_API_KEY
|
|
94
|
+
SIMOTEL_USERNAME=admin
|
|
95
|
+
SIMOTEL_PASSWORD=your_password
|
|
96
|
+
SIMOTEL_TIMEOUT=30
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
from simotel_connect import Simotel
|
|
101
|
+
|
|
102
|
+
sm = Simotel()
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
### روش ۳: مقداردهی مستقیم (بدون جنگو یا چند سروری)
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
from simotel_connect import Simotel
|
|
111
|
+
|
|
112
|
+
sm = Simotel(
|
|
113
|
+
host="192.168.1.10",
|
|
114
|
+
api_key="YOUR_SIMOTEL_API_KEY",
|
|
115
|
+
username="admin",
|
|
116
|
+
password="your_password",
|
|
117
|
+
timeout=15,
|
|
118
|
+
)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 🚀 راهنمای کاربردی و مثالها
|
|
124
|
+
|
|
125
|
+
### ۱. تست وضعیت اتصال (Health Check)
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
response = sm.setting.ping()
|
|
129
|
+
if response.success:
|
|
130
|
+
print("اتصال به سیموتل برقرار است:", response.message)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
### ۲. برقراری تماس (Click-to-Call / Originate)
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
# تماس بین یک داخلی و شماره موبایل
|
|
139
|
+
resp = sm.call.originate(
|
|
140
|
+
src_type="internal",
|
|
141
|
+
src_number="1001",
|
|
142
|
+
dst_type="trunk",
|
|
143
|
+
dst_number="09121234567",
|
|
144
|
+
caller_id="1001"
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
# تماس بین دو داخلی
|
|
148
|
+
resp = sm.call.originate(
|
|
149
|
+
src_type="internal",
|
|
150
|
+
src_number="1001",
|
|
151
|
+
dst_type="internal",
|
|
152
|
+
dst_number="1002"
|
|
153
|
+
)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
### ۳. مدیریت کاربران و داخلیها (Users)
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
# افزودن داخلی جدید
|
|
162
|
+
sm.pbx.users.add(
|
|
163
|
+
extension="1001",
|
|
164
|
+
name="علی رضایی",
|
|
165
|
+
password="StrongPassword123",
|
|
166
|
+
email="ali@example.com",
|
|
167
|
+
mobile="09121234567"
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
# جستجوی کاربران
|
|
171
|
+
users = sm.pbx.users.search(extension="1001")
|
|
172
|
+
print(users.data)
|
|
173
|
+
|
|
174
|
+
# ویرایش کاربر
|
|
175
|
+
sm.pbx.users.update(extension="1001", name="علی رضایی (پشتیبانی)")
|
|
176
|
+
|
|
177
|
+
# حذف کاربر
|
|
178
|
+
sm.pbx.users.remove(extension="1001")
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
### ۴. مدیریت صفها و اپراتورها (Queues)
|
|
184
|
+
|
|
185
|
+
```python
|
|
186
|
+
# ایجاد صف جدید
|
|
187
|
+
sm.pbx.queues.add(name="2000", strategy="leastrecent", timeout=30)
|
|
188
|
+
|
|
189
|
+
# افزودن اپراتور به صف
|
|
190
|
+
sm.pbx.queues.add_agent(queue="2000", agent="1001", penalty=0)
|
|
191
|
+
|
|
192
|
+
# شروع استراحت اپراتور (Pause)
|
|
193
|
+
sm.pbx.queues.pause_agent(queue="2000", agent="1001", reason="استراحت ناهار")
|
|
194
|
+
|
|
195
|
+
# پایان استراحت اپراتور (Resume)
|
|
196
|
+
sm.pbx.queues.resume_agent(queue="2000", agent="1001")
|
|
197
|
+
|
|
198
|
+
# افزودن دستهای اپراتورها
|
|
199
|
+
sm.pbx.queues.batch_add_agent(queue="2000", agents=["1001", "1002", "1003"])
|
|
200
|
+
|
|
201
|
+
# توقف دستهای اپراتورها
|
|
202
|
+
sm.pbx.queues.batch_pause_agent(queue="2000", agents=["1001", "1002"])
|
|
203
|
+
|
|
204
|
+
# خروج اپراتور از صف
|
|
205
|
+
sm.pbx.queues.remove_agent(queue="2000", agent="1001")
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
### ۵. گزارشات و دانلود صوت مکالمات (Reports)
|
|
211
|
+
|
|
212
|
+
```python
|
|
213
|
+
# گزارش CDR تماسها در بازه زمانی
|
|
214
|
+
cdr = sm.reports.cdr_search(
|
|
215
|
+
from_date="2024-01-01 08:00:00",
|
|
216
|
+
to_date="2024-01-31 18:00:00",
|
|
217
|
+
limit=50
|
|
218
|
+
)
|
|
219
|
+
for call in cdr.data:
|
|
220
|
+
print(call)
|
|
221
|
+
|
|
222
|
+
# گزارش صفها
|
|
223
|
+
queue_report = sm.reports.queue_search(queue="2000")
|
|
224
|
+
|
|
225
|
+
# گزارش عملکرد اپراتورها
|
|
226
|
+
agent_report = sm.reports.agent_search(agent="1001")
|
|
227
|
+
|
|
228
|
+
# دانلود فایل صوتی مکالمه ضبطشده
|
|
229
|
+
audio_bytes = sm.reports.download_audio(call_id="unique_call_id_123")
|
|
230
|
+
with open("recorded_call.wav", "wb") as f:
|
|
231
|
+
f.write(audio_bytes)
|
|
232
|
+
|
|
233
|
+
# دانلود مکالمه دو کاناله (کانال اپراتور و مشتری مجزا)
|
|
234
|
+
dual_audio = sm.reports.download_audio_dual_channel(call_id="unique_call_id_123")
|
|
235
|
+
with open("dual_call.wav", "wb") as f:
|
|
236
|
+
f.write(dual_audio)
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
### ۶. لیست سیاه و سفید (Blacklist & Whitelist)
|
|
242
|
+
|
|
243
|
+
```python
|
|
244
|
+
# مسدود کردن شماره مزاحم
|
|
245
|
+
sm.pbx.blacklists.add(number="09999999999", description="مزاحم تلفنی")
|
|
246
|
+
|
|
247
|
+
# رفع مسدودیت
|
|
248
|
+
sm.pbx.blacklists.remove(number="09999999999")
|
|
249
|
+
|
|
250
|
+
# افزودن به لیست سفید (مشتری VIP)
|
|
251
|
+
sm.pbx.whitelists.add(number="09120000000", description="مدیرعامل")
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
### ۷. تماس خودکار و کمپینها (Autodialer)
|
|
257
|
+
|
|
258
|
+
```python
|
|
259
|
+
# آپلود فایل صوتی کمپین
|
|
260
|
+
sm.autodialer.announcements.upload(
|
|
261
|
+
file_path="/path/to/promo.wav",
|
|
262
|
+
name="جشنواره_نوروزی"
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
# ایجاد گروه مخاطبین
|
|
266
|
+
sm.autodialer.groups.add(name="مشتریان_ویژه")
|
|
267
|
+
|
|
268
|
+
# افزودن مخاطب به گروه
|
|
269
|
+
sm.autodialer.contacts.add(
|
|
270
|
+
number="09121234567",
|
|
271
|
+
name="محمد محمدی",
|
|
272
|
+
group="مشتریان_ویژه"
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
# ایجاد کمپین تماس انبوه
|
|
276
|
+
sm.autodialer.campaigns.add(
|
|
277
|
+
name="کمپین عیدانه",
|
|
278
|
+
announcement="جشنواره_نوروزی",
|
|
279
|
+
group="مشتریان_ویژه",
|
|
280
|
+
trunk="main_trunk"
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
# مشاهده گزارشات کمپین
|
|
284
|
+
reports = sm.autodialer.reports.search(campaign="کمپین عیدانه")
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## ⚠️ مدیریت خطاها (Exception Handling)
|
|
290
|
+
|
|
291
|
+
تمام خطاهای پکیج از `SimotelError` ارثبری دارند:
|
|
292
|
+
|
|
293
|
+
```python
|
|
294
|
+
from simotel_connect import (
|
|
295
|
+
Simotel,
|
|
296
|
+
SimotelError,
|
|
297
|
+
SimotelAuthError,
|
|
298
|
+
SimotelAPIError,
|
|
299
|
+
SimotelConnectionError,
|
|
300
|
+
SimotelTimeoutError,
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
sm = Simotel()
|
|
304
|
+
|
|
305
|
+
try:
|
|
306
|
+
sm.call.originate(src_type="internal", src_number="1001", dst_type="internal", dst_number="1002")
|
|
307
|
+
except SimotelAuthError:
|
|
308
|
+
print("خطا در نام کاربری، رمز عبور یا API Key سیموتل")
|
|
309
|
+
except SimotelAPIError as e:
|
|
310
|
+
print(f"سیموتل با پیام خطا پاسخ داد: {e.args[0]}")
|
|
311
|
+
print(f"اطلاعات خطا: {e.data}")
|
|
312
|
+
except SimotelConnectionError:
|
|
313
|
+
print("ارتباط با سرور سیموتل برقرار نشد (بررسی شبکه یا IP)")
|
|
314
|
+
except SimotelTimeoutError:
|
|
315
|
+
print("درخواست با تایماوت مواجه شد")
|
|
316
|
+
except SimotelError as e:
|
|
317
|
+
print(f"خطای نامشخص سیموتل: {e}")
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
## 🧪 اجرای تستها
|
|
323
|
+
|
|
324
|
+
```bash
|
|
325
|
+
pip install -e ".[dev]"
|
|
326
|
+
pytest simotel_connect/tests/ -v
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## 📄 لایسنس
|
|
332
|
+
|
|
333
|
+
این پروژه تحت مجوز **MIT** منتشر شده است.
|