django-unicom 0.1.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.
- django_unicom-0.1.0/MANIFEST.in +6 -0
- django_unicom-0.1.0/PKG-INFO +129 -0
- django_unicom-0.1.0/README.md +104 -0
- django_unicom-0.1.0/django_unicom.egg-info/PKG-INFO +129 -0
- django_unicom-0.1.0/django_unicom.egg-info/SOURCES.txt +32 -0
- django_unicom-0.1.0/django_unicom.egg-info/dependency_links.txt +1 -0
- django_unicom-0.1.0/django_unicom.egg-info/requires.txt +5 -0
- django_unicom-0.1.0/django_unicom.egg-info/top_level.txt +2 -0
- django_unicom-0.1.0/pyproject.toml +3 -0
- django_unicom-0.1.0/setup.cfg +4 -0
- django_unicom-0.1.0/setup.py +28 -0
- django_unicom-0.1.0/unicom/__init__.py +0 -0
- django_unicom-0.1.0/unicom/admin.py +53 -0
- django_unicom-0.1.0/unicom/apps.py +10 -0
- django_unicom-0.1.0/unicom/management/__init__.py +0 -0
- django_unicom-0.1.0/unicom/management/commands/__init__.py +0 -0
- django_unicom-0.1.0/unicom/management/commands/mail_inbox_listen.py +55 -0
- django_unicom-0.1.0/unicom/migrations/0001_initial.py +103 -0
- django_unicom-0.1.0/unicom/migrations/__init__.py +0 -0
- django_unicom-0.1.0/unicom/models/__init__.py +6 -0
- django_unicom-0.1.0/unicom/models/account.py +32 -0
- django_unicom-0.1.0/unicom/models/account_chat.py +12 -0
- django_unicom-0.1.0/unicom/models/bot.py +71 -0
- django_unicom-0.1.0/unicom/models/chat.py +13 -0
- django_unicom-0.1.0/unicom/models/constants.py +1 -0
- django_unicom-0.1.0/unicom/models/message.py +73 -0
- django_unicom-0.1.0/unicom/models/update.py +15 -0
- django_unicom-0.1.0/unicom/signals.py +39 -0
- django_unicom-0.1.0/unicom/templates/admin/unicom/chat_history.html +228 -0
- django_unicom-0.1.0/unicom/urls.py +8 -0
- django_unicom-0.1.0/unicom/views/__init__.py +0 -0
- django_unicom-0.1.0/unicom/views/chat_history_view.py +31 -0
- django_unicom-0.1.0/unicom/views/telegram_webhook.py +57 -0
- django_unicom-0.1.0/unicom/views/whatsapp_webhook.py +54 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: django-unicom
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Unified communication layer for Django (Telegram, WhatsApp, Email)
|
|
5
|
+
Home-page: https://github.com/meena-erian/unicom
|
|
6
|
+
Author: Meena (Menas) Erian
|
|
7
|
+
Author-email: hi@menas.pro
|
|
8
|
+
Classifier: Framework :: Django
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
Requires-Dist: Django>=3.2
|
|
13
|
+
Provides-Extra: dev
|
|
14
|
+
Requires-Dist: pytest; extra == "dev"
|
|
15
|
+
Requires-Dist: pytest-django; extra == "dev"
|
|
16
|
+
Dynamic: author
|
|
17
|
+
Dynamic: author-email
|
|
18
|
+
Dynamic: classifier
|
|
19
|
+
Dynamic: description
|
|
20
|
+
Dynamic: description-content-type
|
|
21
|
+
Dynamic: home-page
|
|
22
|
+
Dynamic: provides-extra
|
|
23
|
+
Dynamic: requires-dist
|
|
24
|
+
Dynamic: summary
|
|
25
|
+
|
|
26
|
+
# Django Unicom
|
|
27
|
+
|
|
28
|
+
**Unified communication layer for Django** — easily integrate Telegram bots, WhatsApp, and Email with a consistent API across all platforms.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 🚀 Quick Start
|
|
33
|
+
|
|
34
|
+
1. **Install the package:**
|
|
35
|
+
```bash
|
|
36
|
+
pip install django-unicom
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
2. **Add `unicom` to your Django settings:**
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
INSTALLED_APPS = [
|
|
43
|
+
...
|
|
44
|
+
'unicom',
|
|
45
|
+
]
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
3. **Include `unicom` URLs in your project’s `urls.py`:**
|
|
49
|
+
|
|
50
|
+
> This is required so that webhook URLs can be constructed correctly.
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from django.urls import path, include
|
|
54
|
+
|
|
55
|
+
urlpatterns = [
|
|
56
|
+
...
|
|
57
|
+
path('unicom/', include('unicom.urls')),
|
|
58
|
+
]
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
4. **Define your public origin:**
|
|
62
|
+
In your Django `settings.py`:
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
DJANGO_PUBLIC_ORIGIN = "https://yourdomain.com"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Or via environment variable:
|
|
69
|
+
|
|
70
|
+
```env
|
|
71
|
+
DJANGO_PUBLIC_ORIGIN=https://yourdomain.com
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
That’s it! Unicom can now register and manage public-facing webhooks (e.g., for Telegram bots) based on your defined base URL.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 🧑💻 Contributing
|
|
79
|
+
|
|
80
|
+
We ❤️ contributors!
|
|
81
|
+
|
|
82
|
+
### Requirements:
|
|
83
|
+
|
|
84
|
+
* Docker & Docker Compose installed
|
|
85
|
+
|
|
86
|
+
### Getting Started:
|
|
87
|
+
|
|
88
|
+
1. Clone the repo:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
git clone https://github.com/meena-erian/unicom.git
|
|
92
|
+
cd unicom
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
2. Create a `db.env` file in the root:
|
|
96
|
+
|
|
97
|
+
```env
|
|
98
|
+
POSTGRES_DB=unicom_test
|
|
99
|
+
POSTGRES_USER=unicom
|
|
100
|
+
POSTGRES_PASSWORD=unicom
|
|
101
|
+
DJANGO_PUBLIC_ORIGIN=https://yourdomain.com
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
3. Start the dev environment:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
docker-compose up --build
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
4. Run tests:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
docker-compose exec app pytest
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
or just
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
pytest
|
|
120
|
+
```
|
|
121
|
+
Note: To run ```test_telegram_live``` tests you need to create ```telegram_credentials.py``` in the tests folder and define in it ```TELEGRAM_API_TOKEN``` and ```TELEGRAM_SECRET_TOKEN```
|
|
122
|
+
|
|
123
|
+
No need to modify `settings.py` — everything is pre-wired to read from `db.env`.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## 📄 License
|
|
128
|
+
|
|
129
|
+
MIT License © Meena (Menas) Erian
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Django Unicom
|
|
2
|
+
|
|
3
|
+
**Unified communication layer for Django** — easily integrate Telegram bots, WhatsApp, and Email with a consistent API across all platforms.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🚀 Quick Start
|
|
8
|
+
|
|
9
|
+
1. **Install the package:**
|
|
10
|
+
```bash
|
|
11
|
+
pip install django-unicom
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
2. **Add `unicom` to your Django settings:**
|
|
15
|
+
|
|
16
|
+
```python
|
|
17
|
+
INSTALLED_APPS = [
|
|
18
|
+
...
|
|
19
|
+
'unicom',
|
|
20
|
+
]
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
3. **Include `unicom` URLs in your project’s `urls.py`:**
|
|
24
|
+
|
|
25
|
+
> This is required so that webhook URLs can be constructed correctly.
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from django.urls import path, include
|
|
29
|
+
|
|
30
|
+
urlpatterns = [
|
|
31
|
+
...
|
|
32
|
+
path('unicom/', include('unicom.urls')),
|
|
33
|
+
]
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
4. **Define your public origin:**
|
|
37
|
+
In your Django `settings.py`:
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
DJANGO_PUBLIC_ORIGIN = "https://yourdomain.com"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Or via environment variable:
|
|
44
|
+
|
|
45
|
+
```env
|
|
46
|
+
DJANGO_PUBLIC_ORIGIN=https://yourdomain.com
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
That’s it! Unicom can now register and manage public-facing webhooks (e.g., for Telegram bots) based on your defined base URL.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## 🧑💻 Contributing
|
|
54
|
+
|
|
55
|
+
We ❤️ contributors!
|
|
56
|
+
|
|
57
|
+
### Requirements:
|
|
58
|
+
|
|
59
|
+
* Docker & Docker Compose installed
|
|
60
|
+
|
|
61
|
+
### Getting Started:
|
|
62
|
+
|
|
63
|
+
1. Clone the repo:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
git clone https://github.com/meena-erian/unicom.git
|
|
67
|
+
cd unicom
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
2. Create a `db.env` file in the root:
|
|
71
|
+
|
|
72
|
+
```env
|
|
73
|
+
POSTGRES_DB=unicom_test
|
|
74
|
+
POSTGRES_USER=unicom
|
|
75
|
+
POSTGRES_PASSWORD=unicom
|
|
76
|
+
DJANGO_PUBLIC_ORIGIN=https://yourdomain.com
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
3. Start the dev environment:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
docker-compose up --build
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
4. Run tests:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
docker-compose exec app pytest
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
or just
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
pytest
|
|
95
|
+
```
|
|
96
|
+
Note: To run ```test_telegram_live``` tests you need to create ```telegram_credentials.py``` in the tests folder and define in it ```TELEGRAM_API_TOKEN``` and ```TELEGRAM_SECRET_TOKEN```
|
|
97
|
+
|
|
98
|
+
No need to modify `settings.py` — everything is pre-wired to read from `db.env`.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 📄 License
|
|
103
|
+
|
|
104
|
+
MIT License © Meena (Menas) Erian
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: django-unicom
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Unified communication layer for Django (Telegram, WhatsApp, Email)
|
|
5
|
+
Home-page: https://github.com/meena-erian/unicom
|
|
6
|
+
Author: Meena (Menas) Erian
|
|
7
|
+
Author-email: hi@menas.pro
|
|
8
|
+
Classifier: Framework :: Django
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
Requires-Dist: Django>=3.2
|
|
13
|
+
Provides-Extra: dev
|
|
14
|
+
Requires-Dist: pytest; extra == "dev"
|
|
15
|
+
Requires-Dist: pytest-django; extra == "dev"
|
|
16
|
+
Dynamic: author
|
|
17
|
+
Dynamic: author-email
|
|
18
|
+
Dynamic: classifier
|
|
19
|
+
Dynamic: description
|
|
20
|
+
Dynamic: description-content-type
|
|
21
|
+
Dynamic: home-page
|
|
22
|
+
Dynamic: provides-extra
|
|
23
|
+
Dynamic: requires-dist
|
|
24
|
+
Dynamic: summary
|
|
25
|
+
|
|
26
|
+
# Django Unicom
|
|
27
|
+
|
|
28
|
+
**Unified communication layer for Django** — easily integrate Telegram bots, WhatsApp, and Email with a consistent API across all platforms.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 🚀 Quick Start
|
|
33
|
+
|
|
34
|
+
1. **Install the package:**
|
|
35
|
+
```bash
|
|
36
|
+
pip install django-unicom
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
2. **Add `unicom` to your Django settings:**
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
INSTALLED_APPS = [
|
|
43
|
+
...
|
|
44
|
+
'unicom',
|
|
45
|
+
]
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
3. **Include `unicom` URLs in your project’s `urls.py`:**
|
|
49
|
+
|
|
50
|
+
> This is required so that webhook URLs can be constructed correctly.
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from django.urls import path, include
|
|
54
|
+
|
|
55
|
+
urlpatterns = [
|
|
56
|
+
...
|
|
57
|
+
path('unicom/', include('unicom.urls')),
|
|
58
|
+
]
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
4. **Define your public origin:**
|
|
62
|
+
In your Django `settings.py`:
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
DJANGO_PUBLIC_ORIGIN = "https://yourdomain.com"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Or via environment variable:
|
|
69
|
+
|
|
70
|
+
```env
|
|
71
|
+
DJANGO_PUBLIC_ORIGIN=https://yourdomain.com
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
That’s it! Unicom can now register and manage public-facing webhooks (e.g., for Telegram bots) based on your defined base URL.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 🧑💻 Contributing
|
|
79
|
+
|
|
80
|
+
We ❤️ contributors!
|
|
81
|
+
|
|
82
|
+
### Requirements:
|
|
83
|
+
|
|
84
|
+
* Docker & Docker Compose installed
|
|
85
|
+
|
|
86
|
+
### Getting Started:
|
|
87
|
+
|
|
88
|
+
1. Clone the repo:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
git clone https://github.com/meena-erian/unicom.git
|
|
92
|
+
cd unicom
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
2. Create a `db.env` file in the root:
|
|
96
|
+
|
|
97
|
+
```env
|
|
98
|
+
POSTGRES_DB=unicom_test
|
|
99
|
+
POSTGRES_USER=unicom
|
|
100
|
+
POSTGRES_PASSWORD=unicom
|
|
101
|
+
DJANGO_PUBLIC_ORIGIN=https://yourdomain.com
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
3. Start the dev environment:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
docker-compose up --build
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
4. Run tests:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
docker-compose exec app pytest
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
or just
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
pytest
|
|
120
|
+
```
|
|
121
|
+
Note: To run ```test_telegram_live``` tests you need to create ```telegram_credentials.py``` in the tests folder and define in it ```TELEGRAM_API_TOKEN``` and ```TELEGRAM_SECRET_TOKEN```
|
|
122
|
+
|
|
123
|
+
No need to modify `settings.py` — everything is pre-wired to read from `db.env`.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## 📄 License
|
|
128
|
+
|
|
129
|
+
MIT License © Meena (Menas) Erian
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
MANIFEST.in
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
setup.py
|
|
5
|
+
django_unicom.egg-info/PKG-INFO
|
|
6
|
+
django_unicom.egg-info/SOURCES.txt
|
|
7
|
+
django_unicom.egg-info/dependency_links.txt
|
|
8
|
+
django_unicom.egg-info/requires.txt
|
|
9
|
+
django_unicom.egg-info/top_level.txt
|
|
10
|
+
unicom/__init__.py
|
|
11
|
+
unicom/admin.py
|
|
12
|
+
unicom/apps.py
|
|
13
|
+
unicom/signals.py
|
|
14
|
+
unicom/urls.py
|
|
15
|
+
unicom/management/__init__.py
|
|
16
|
+
unicom/management/commands/__init__.py
|
|
17
|
+
unicom/management/commands/mail_inbox_listen.py
|
|
18
|
+
unicom/migrations/0001_initial.py
|
|
19
|
+
unicom/migrations/__init__.py
|
|
20
|
+
unicom/models/__init__.py
|
|
21
|
+
unicom/models/account.py
|
|
22
|
+
unicom/models/account_chat.py
|
|
23
|
+
unicom/models/bot.py
|
|
24
|
+
unicom/models/chat.py
|
|
25
|
+
unicom/models/constants.py
|
|
26
|
+
unicom/models/message.py
|
|
27
|
+
unicom/models/update.py
|
|
28
|
+
unicom/templates/admin/unicom/chat_history.html
|
|
29
|
+
unicom/views/__init__.py
|
|
30
|
+
unicom/views/chat_history_view.py
|
|
31
|
+
unicom/views/telegram_webhook.py
|
|
32
|
+
unicom/views/whatsapp_webhook.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
setup(
|
|
4
|
+
name='django-unicom',
|
|
5
|
+
version='0.1.0',
|
|
6
|
+
description='Unified communication layer for Django (Telegram, WhatsApp, Email)',
|
|
7
|
+
long_description=open('README.md').read(),
|
|
8
|
+
long_description_content_type='text/markdown',
|
|
9
|
+
author='Meena (Menas) Erian',
|
|
10
|
+
author_email='hi@menas.pro',
|
|
11
|
+
url='https://github.com/meena-erian/unicom',
|
|
12
|
+
packages=find_packages(exclude=['tests*']),
|
|
13
|
+
include_package_data=True,
|
|
14
|
+
install_requires=[
|
|
15
|
+
'Django>=3.2',
|
|
16
|
+
],
|
|
17
|
+
extras_require={
|
|
18
|
+
'dev': [
|
|
19
|
+
'pytest',
|
|
20
|
+
'pytest-django',
|
|
21
|
+
],
|
|
22
|
+
},
|
|
23
|
+
classifiers=[
|
|
24
|
+
'Framework :: Django',
|
|
25
|
+
'Programming Language :: Python :: 3',
|
|
26
|
+
'License :: OSI Approved :: MIT License',
|
|
27
|
+
],
|
|
28
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from django.contrib import admin
|
|
2
|
+
from unicom.models import Message, Update, Chat, Account, AccountChat, Bot
|
|
3
|
+
from django.utils.html import format_html
|
|
4
|
+
from unicom.views.chat_history_view import chat_history_view
|
|
5
|
+
from django.urls import path
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ChatAdmin(admin.ModelAdmin):
|
|
9
|
+
list_filter = ('platform', 'is_private')
|
|
10
|
+
list_display = ('id', 'name', 'view_chat_link')
|
|
11
|
+
search_fields = ('id', 'name')
|
|
12
|
+
|
|
13
|
+
def view_chat_link(self, obj):
|
|
14
|
+
return format_html('<a href="{}" target="_blank">View Chat</a>', self.url_for_chat(obj.id))
|
|
15
|
+
|
|
16
|
+
def url_for_chat(self, id):
|
|
17
|
+
return f"{id}/messages/"
|
|
18
|
+
|
|
19
|
+
def get_urls(self):
|
|
20
|
+
urls = super().get_urls()
|
|
21
|
+
custom_urls = [
|
|
22
|
+
path('<path:chat_id>/messages/', self.admin_site.admin_view(chat_history_view), name='chat-detail')
|
|
23
|
+
]
|
|
24
|
+
return custom_urls + urls
|
|
25
|
+
|
|
26
|
+
view_chat_link.short_description = 'View Chat'
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class AccountChatAdmin(admin.ModelAdmin):
|
|
30
|
+
list_filter = ('account__platform', )
|
|
31
|
+
search_fields = ('account__name', 'chat__name')
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class AccountAdmin(admin.ModelAdmin):
|
|
35
|
+
list_filter = ('platform', )
|
|
36
|
+
search_fields = ('name', )
|
|
37
|
+
|
|
38
|
+
class BotAdmin(admin.ModelAdmin):
|
|
39
|
+
list_filter = ('platform', )
|
|
40
|
+
search_fields = ('name', )
|
|
41
|
+
list_display = ('id', 'name', 'platform', 'active', 'confirmed_webhook_url', 'error')
|
|
42
|
+
|
|
43
|
+
def get_readonly_fields(self, request, obj=None):
|
|
44
|
+
if obj:
|
|
45
|
+
return ['active', 'confirmed_webhook_url', 'error']
|
|
46
|
+
return super().get_readonly_fields(request, obj)
|
|
47
|
+
|
|
48
|
+
admin.site.register(Bot)
|
|
49
|
+
admin.site.register(Message)
|
|
50
|
+
admin.site.register(Update)
|
|
51
|
+
admin.site.register(Chat, ChatAdmin)
|
|
52
|
+
admin.site.register(Account, AccountAdmin)
|
|
53
|
+
admin.site.register(AccountChat, AccountChatAdmin)
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# import time
|
|
2
|
+
# import logging
|
|
3
|
+
# from imapclient import IMAPClient, SEEN
|
|
4
|
+
# from django.core.management.base import BaseCommand
|
|
5
|
+
# from django.conf import settings
|
|
6
|
+
|
|
7
|
+
# from robopower.services.email.save_email_message import save_email_message
|
|
8
|
+
|
|
9
|
+
# logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
# class Command(BaseCommand):
|
|
12
|
+
# help = "Listen to an IMAP account via IDLE and hand off new emails."
|
|
13
|
+
|
|
14
|
+
# def handle(self, *args, **options):
|
|
15
|
+
# while True:
|
|
16
|
+
# try:
|
|
17
|
+
# with IMAPClient(settings.IMAP_HOST, port=settings.IMAP_PORT, ssl=settings.IMAP_USE_SSL) as server:
|
|
18
|
+
# print(f"Logging in to {settings.IMAP_HOST}:{settings.IMAP_PORT} as {settings.IMAP_USER} with pwd {settings.IMAP_PASSWORD}")
|
|
19
|
+
# server.login(settings.IMAP_USER, settings.IMAP_PASSWORD)
|
|
20
|
+
# server.select_folder('INBOX')
|
|
21
|
+
# self.stdout.write("✅ Connected to IMAP, entering IDLE…")
|
|
22
|
+
|
|
23
|
+
# while True:
|
|
24
|
+
# try:
|
|
25
|
+
# server.idle() # enter IDLE
|
|
26
|
+
# responses = server.idle_check(timeout=300) # wake up at least every 5m
|
|
27
|
+
# except (ConnectionResetError, OSError) as e:
|
|
28
|
+
# logger.warning("IMAP idle connection lost: %s", e)
|
|
29
|
+
# break # break inner loop to reconnect
|
|
30
|
+
# finally:
|
|
31
|
+
# # if idle() succeeded we need to terminate it
|
|
32
|
+
# # (noop if connection already gone)
|
|
33
|
+
# try:
|
|
34
|
+
# server.idle_done()
|
|
35
|
+
# except Exception:
|
|
36
|
+
# pass
|
|
37
|
+
|
|
38
|
+
# if not responses:
|
|
39
|
+
# continue
|
|
40
|
+
|
|
41
|
+
# # process all new unseen messages
|
|
42
|
+
# uids = server.search(['UNSEEN'])
|
|
43
|
+
# for uid in uids:
|
|
44
|
+
# try:
|
|
45
|
+
# resp = server.fetch(uid, ['BODY.PEEK[]'])
|
|
46
|
+
# raw = resp[uid][b'BODY[]']
|
|
47
|
+
# msg = save_email_message(raw)
|
|
48
|
+
# self.stdout.write(f"💾 Saved email {msg.id} (uid={uid})")
|
|
49
|
+
# server.add_flags(uid, [SEEN])
|
|
50
|
+
# except Exception as exc:
|
|
51
|
+
# logger.exception("Failed to process UID %s: %s", uid, exc)
|
|
52
|
+
|
|
53
|
+
# except Exception as e:
|
|
54
|
+
# logger.exception("Fatal IMAP error, reconnecting in 30s…")
|
|
55
|
+
# time.sleep(30)
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Generated by Django 4.2.20 on 2025-05-20 11:04
|
|
2
|
+
|
|
3
|
+
from django.conf import settings
|
|
4
|
+
import django.contrib.postgres.fields
|
|
5
|
+
import django.core.validators
|
|
6
|
+
from django.db import migrations, models
|
|
7
|
+
import django.db.models.deletion
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Migration(migrations.Migration):
|
|
11
|
+
|
|
12
|
+
initial = True
|
|
13
|
+
|
|
14
|
+
dependencies = [
|
|
15
|
+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
operations = [
|
|
19
|
+
migrations.CreateModel(
|
|
20
|
+
name='Account',
|
|
21
|
+
fields=[
|
|
22
|
+
('id', models.CharField(max_length=500, primary_key=True, serialize=False)),
|
|
23
|
+
('platform', models.CharField(choices=[('Telegram', 'Telegram'), ('WhatsApp', 'WhatsApp'), ('Internal', 'Internal'), ('Email', 'Email')], max_length=100)),
|
|
24
|
+
('is_bot', models.BooleanField(default=False)),
|
|
25
|
+
('name', models.CharField(blank=True, max_length=100, null=True)),
|
|
26
|
+
('raw', models.JSONField()),
|
|
27
|
+
],
|
|
28
|
+
),
|
|
29
|
+
migrations.CreateModel(
|
|
30
|
+
name='Bot',
|
|
31
|
+
fields=[
|
|
32
|
+
('id', models.BigAutoField(primary_key=True, serialize=False)),
|
|
33
|
+
('name', models.CharField(max_length=100)),
|
|
34
|
+
('platform', models.CharField(choices=[('Telegram', 'Telegram'), ('WhatsApp', 'WhatsApp'), ('Internal', 'Internal'), ('Email', 'Email')], max_length=100)),
|
|
35
|
+
('config', models.JSONField()),
|
|
36
|
+
('active', models.BooleanField(default=False, editable=False)),
|
|
37
|
+
('confirmed_webhook_url', models.CharField(blank=True, editable=False, max_length=500, null=True)),
|
|
38
|
+
('error', models.CharField(blank=True, editable=False, max_length=500, null=True)),
|
|
39
|
+
],
|
|
40
|
+
),
|
|
41
|
+
migrations.CreateModel(
|
|
42
|
+
name='Chat',
|
|
43
|
+
fields=[
|
|
44
|
+
('id', models.CharField(max_length=500, primary_key=True, serialize=False)),
|
|
45
|
+
('platform', models.CharField(choices=[('Telegram', 'Telegram'), ('WhatsApp', 'WhatsApp'), ('Internal', 'Internal'), ('Email', 'Email')], max_length=100)),
|
|
46
|
+
('is_private', models.BooleanField(default=True)),
|
|
47
|
+
('name', models.CharField(blank=True, max_length=100, null=True)),
|
|
48
|
+
],
|
|
49
|
+
),
|
|
50
|
+
migrations.CreateModel(
|
|
51
|
+
name='Message',
|
|
52
|
+
fields=[
|
|
53
|
+
('id', models.CharField(max_length=500, primary_key=True, serialize=False)),
|
|
54
|
+
('platform', models.CharField(choices=[('Telegram', 'Telegram'), ('WhatsApp', 'WhatsApp'), ('Internal', 'Internal'), ('Email', 'Email')], max_length=100)),
|
|
55
|
+
('is_bot', models.BooleanField(default=False)),
|
|
56
|
+
('sender_name', models.CharField(max_length=100)),
|
|
57
|
+
('subject', models.CharField(blank=True, help_text='Subject of the message (only for email messages)', max_length=512, null=True)),
|
|
58
|
+
('text', models.TextField()),
|
|
59
|
+
('html', models.TextField(blank=True, help_text='Full HTML body (only for email messages)', null=True)),
|
|
60
|
+
('to', django.contrib.postgres.fields.ArrayField(base_field=models.EmailField(max_length=254, validators=[django.core.validators.EmailValidator()]), blank=True, default=list, help_text='List of To: addresses', size=None)),
|
|
61
|
+
('cc', django.contrib.postgres.fields.ArrayField(base_field=models.EmailField(max_length=254, validators=[django.core.validators.EmailValidator()]), blank=True, default=list, help_text='List of Cc: addresses', size=None)),
|
|
62
|
+
('bcc', django.contrib.postgres.fields.ArrayField(base_field=models.EmailField(max_length=254, validators=[django.core.validators.EmailValidator()]), blank=True, default=list, help_text='List of Bcc: addresses', size=None)),
|
|
63
|
+
('media', models.FileField(blank=True, null=True, upload_to='media/')),
|
|
64
|
+
('timestamp', models.DateTimeField()),
|
|
65
|
+
('time_sent', models.DateTimeField(blank=True, null=True)),
|
|
66
|
+
('time_delivered', models.DateTimeField(blank=True, null=True)),
|
|
67
|
+
('time_seen', models.DateTimeField(blank=True, null=True)),
|
|
68
|
+
('sent', models.BooleanField(default=False)),
|
|
69
|
+
('delivered', models.BooleanField(default=False)),
|
|
70
|
+
('seen', models.BooleanField(default=False)),
|
|
71
|
+
('raw', models.JSONField()),
|
|
72
|
+
('media_type', models.CharField(choices=[('text', 'Text'), ('html', 'HTML'), ('image', 'Image'), ('audio', 'Audio')], default='text', max_length=10)),
|
|
73
|
+
('chat', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='messages', to='unicom.chat')),
|
|
74
|
+
('reply_to_message', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='replies', to='unicom.message')),
|
|
75
|
+
('sender', models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, to='unicom.account')),
|
|
76
|
+
('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.RESTRICT, to=settings.AUTH_USER_MODEL)),
|
|
77
|
+
],
|
|
78
|
+
options={
|
|
79
|
+
'ordering': ['-timestamp'],
|
|
80
|
+
},
|
|
81
|
+
),
|
|
82
|
+
migrations.CreateModel(
|
|
83
|
+
name='Update',
|
|
84
|
+
fields=[
|
|
85
|
+
('platform', models.CharField(choices=[('Telegram', 'Telegram'), ('WhatsApp', 'WhatsApp'), ('Internal', 'Internal'), ('Email', 'Email')], max_length=100)),
|
|
86
|
+
('id', models.CharField(max_length=100, primary_key=True, serialize=False)),
|
|
87
|
+
('payload', models.JSONField()),
|
|
88
|
+
('bot', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='unicom.bot')),
|
|
89
|
+
('message', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='unicom.message')),
|
|
90
|
+
],
|
|
91
|
+
),
|
|
92
|
+
migrations.CreateModel(
|
|
93
|
+
name='AccountChat',
|
|
94
|
+
fields=[
|
|
95
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
96
|
+
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='unicom.account')),
|
|
97
|
+
('chat', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='unicom.chat')),
|
|
98
|
+
],
|
|
99
|
+
options={
|
|
100
|
+
'unique_together': {('account', 'chat')},
|
|
101
|
+
},
|
|
102
|
+
),
|
|
103
|
+
]
|
|
File without changes
|