-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathobserver.py
More file actions
176 lines (138 loc) · 5.23 KB
/
observer.py
File metadata and controls
176 lines (138 loc) · 5.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
import logging
import pendulum
from mongoengine import (
Document,
StringField, IntField, ListField, DateTimeField,
ReferenceField, NULLIFY)
from mongoengine.errors import DoesNotExist
from telegram.error import BadRequest
from bot.core import BotTelegramCore
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.INFO)
logger = logging.getLogger(__name__)
class ObserverMessage(Document):
"""MongoDB Document for a observer telegram sent message
Attributes:
message_id (int): telegram send message id
subject (Subject): subject reference
observer (Observer): observer reference
datetime: now() datetime
"""
message_id = IntField(required=True)
subject = ReferenceField('Subject', required=True)
observer = ReferenceField('Observer', required=True)
datetime = DateTimeField(default=pendulum.now, required=True)
meta = {
'ordering': ['datetime'],
'indexes': [
{'fields': ['datetime'], 'expireAfterSeconds': 1*24*60*60}
]
}
def __str__(self):
return f"{self.message_id} {self.subject}"
class Observer(Document):
"""MongoDB Document for official Telegram Channel
Attributes:
username (str): telegram chat username
chat_id (str): telegram chat id
"""
username = StringField(max_length=50)
chat_id = StringField(required=True, max_length=50, unique=True)
meta = {
'allow_inheritance': True
}
def __str__(self):
return f"{self.username if self.username else ''} " \
f"{self.chat_id}".strip()
def notify(self, update_message):
"""Notify observer of update message.
Calls:
>>> self._send_update_message(update_message)
Args:
update_message (UpdateMessage): update message to be notified
"""
self._send_update_message(update_message)
def _send_update_message(self, update_message):
"""Send update message to telegram chat and creates it's respective ObserverMessage
Args:
update_message (UpdateMessage): update message to be sent
"""
telegram_message = BotTelegramCore.send_message(
f'{update_message}', chat_id=self.chat_id)
ObserverMessage(
telegram_message.message_id,
update_message.subject,
self
).save()
@classmethod
def get_official_observer(cls):
"""get official observer from official chat_id
Returns:
Observer: official observer
"""
return cls.objects.get(chat_id=BotTelegramCore.instance().chat_id)
class UserObserver(Observer):
"""MongoDB Document for user's observer
Attributes:
username (str): telegram chat username
chat_id (str): telegram chat id
messages (list of ObserverMessage): list of ObserverMessage's
"""
messages = ListField(
ReferenceField(ObserverMessage, reverse_delete_rule=NULLIFY)
)
def notify(self, update_message):
"""Notify observer of update message.
Calls:
>>> self._remove_last_message_from_subject(update_message.subject)
>>> self._send_update_message(update_message)
Args:
update_message (UpdateMessage): update message to be notified
"""
self._remove_last_message_from_subject(update_message.subject)
self._send_update_message(update_message)
def _send_update_message(self, update_message):
"""Forward official channel update message to telegram chat and creates it's respective ObserverMessage
Args:
update_message (UpdateMessage): update message to be forwarded
"""
official_observer = Observer.get_official_observer()
last_official_message = ObserverMessage\
.objects(subject=update_message.subject,
observer=official_observer)\
.order_by('-datetime').first()
telegram_message = BotTelegramCore.forward_message(
to_chat_id=self.chat_id,
from_chat_id=official_observer.chat_id,
message_id=last_official_message.message_id
)
om = ObserverMessage(
telegram_message.message_id,
update_message.subject,
self
).save()
self.messages.append(om)
self.save()
def _remove_last_message_from_subject(self, subject):
"""Delete previous forwarded official channel update message from subject on telegram chat and removes it's respective ObserverMessage
Args:
subject (Subject): subject to be filter messages
"""
self.reload()
try:
observer_messages = filter(
lambda x: (isinstance(x, ObserverMessage)
and x.subject == subject),
self.messages
)
for om in observer_messages:
BotTelegramCore.delete_message(self.chat_id, om.message_id)
for om in self.messages:
self.messages.remove(om)
om.delete()
self.save()
except DoesNotExist:
pass
except BadRequest as e:
logger.warning(f'BadRequest {e}')