leadguru-jobs 0.541.0__py3-none-any.whl → 0.543.0__py3-none-any.whl

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: leadguru_jobs
3
- Version: 0.541.0
3
+ Version: 0.543.0
4
4
  Summary: LGT jobs builds
5
5
  Author-email: developer@leadguru.co
6
6
  Classifier: Development Status :: 5 - Production/Stable
@@ -1,7 +1,7 @@
1
1
  lgt_jobs/__init__.py,sha256=lrhMUJ7a5YSkYswQkQe981b_w8h8NHyncwfEduXEq6Q,1992
2
2
  lgt_jobs/basejobs.py,sha256=LPEclvY6fIG17YMGy9pRK0Q58n62gkI5W1BTK6R2p-c,1234
3
3
  lgt_jobs/env.py,sha256=cRO03GGvstUjBsv3uYO-iakrOvAk_ZWUP_fnmf21iZQ,789
4
- lgt_jobs/main.py,sha256=OUfuq8INpY54pYwdL3wV8Fy_3oScdMaj5jonUakWytY,1538
4
+ lgt_jobs/main.py,sha256=cK_nkBtJHnUNDbba1WZotqPtI_6OWxiYQkAgco9OAmE,1539
5
5
  lgt_jobs/runner.py,sha256=MZ3_UvfyDSM707UI4uPDntlKKCXkIyN6h95D1i1SoQQ,2125
6
6
  lgt_jobs/simple_job.py,sha256=sta7MP-57iwRewPycmTAc9dvSbocbGjWhb1QYYj7ccA,519
7
7
  lgt_jobs/smtp.py,sha256=Svaq2ghMjGwpPA4J92wVnzrLlVbI2FcM2d4liiAbHLo,1210
@@ -30,24 +30,23 @@ lgt_jobs/lgt_common/discord_client/methods.py,sha256=C46Vq9_-dlvs0nEW6ck8QvAmE_n
30
30
  lgt_jobs/lgt_common/enums/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
31
  lgt_jobs/lgt_common/enums/slack_errors.py,sha256=5VNbBaMKya2RIR5uyr3YI8N6Xll9WexItk7uJtoJ4NQ,142
32
32
  lgt_jobs/lgt_common/pubsub/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
- lgt_jobs/lgt_common/pubsub/command.py,sha256=tr7J51NGbt6Iq5CTEUyASu3o7KqP-Q64NfKaI1WVC64,278
34
33
  lgt_jobs/lgt_common/pubsub/messages.py,sha256=rm7uKbxwDTWJqsVA8Kee-4YT58bThjCEV2Q0559Lrzg,1397
35
- lgt_jobs/lgt_common/pubsub/pubsubfactory.py,sha256=7HAg_P2sZ6DDJkDyxzc4yI-i38bDSMxySulEGlHUhxc,2441
34
+ lgt_jobs/lgt_common/pubsub/pubsubfactory.py,sha256=rfUDooYuhBQ2pE9FdDxZOpXjbrvlpiiQLCGOtnTFbSg,2204
36
35
  lgt_jobs/lgt_common/slack_client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
- lgt_jobs/lgt_common/slack_client/methods.py,sha256=-PxK8StkJ-dyACHdRRiQlRL2qaG9KEyWB7wo4eh7ifU,1506
38
- lgt_jobs/lgt_common/slack_client/slack_client.py,sha256=C1FwHQW82OS73THwPRF4_AvyDi4QbYLjbI_NDXO8Nwk,15896
39
- lgt_jobs/lgt_common/slack_client/web_client.py,sha256=oZV7oUcSXXngfMI6oXDedlQWePL9b2ClkocqbXNe1ns,6259
36
+ lgt_jobs/lgt_common/slack_client/methods.py,sha256=ctKF_1UHEmSWaRsoGEgMZicVabV7eEufZ7pjxdMAx8g,1455
37
+ lgt_jobs/lgt_common/slack_client/slack_client.py,sha256=mbwHaqixC3xCJ0KP9WepxJtwlsJwTSEWQ2O1hx0hjXE,12173
38
+ lgt_jobs/lgt_common/slack_client/web_client.py,sha256=vAfE6qrT1oTyP35chRsgeH008xtbsNGYdPqMqCdJmlE,6063
40
39
  lgt_jobs/lgt_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
- lgt_jobs/lgt_data/analytics.py,sha256=Gr-7IzrnHPN9YJlIT6-NqrzVYU39vQUMKCRMsvvM5A4,22869
42
- lgt_jobs/lgt_data/engine.py,sha256=YJYEAj1Z4_XIhPMaoB7bp8x9ponANBzw7gZRrj6c-c4,8600
43
- lgt_jobs/lgt_data/enums.py,sha256=fr5yR5WPilFgWMBtMsYkVy5vsq3bT0t553CCuKtWpXQ,2416
40
+ lgt_jobs/lgt_data/analytics.py,sha256=FJxImuuJw-m4B-eKIddytBy_B19BVsdPEHib-5gNgyo,20172
41
+ lgt_jobs/lgt_data/engine.py,sha256=Rsbz-CApAo_TVDssdjBkv8v_fVOZm_Uh1S6W4fnaEWo,7728
42
+ lgt_jobs/lgt_data/enums.py,sha256=pZz8Xv-44hhhttb01ci4YnMIj7gS1oNnhX24XnuX5UM,2160
44
43
  lgt_jobs/lgt_data/helpers.py,sha256=NDa-V5EYaJfkGoWsmQSwSe6N_jxNxs8tHRQzW1iST6k,480
45
- lgt_jobs/lgt_data/model.py,sha256=ZXJHbsQ-BgH09o9siw5yqKNWqQSymsOQ5HH8nKFeACQ,29312
46
- lgt_jobs/lgt_data/mongo_repository.py,sha256=nX9oh7-Em1amfljkvgbyA4hjaxdOb27ocZM132YmZWQ,49479
44
+ lgt_jobs/lgt_data/model.py,sha256=DDfoWeH6rLWKoZsFJ2tI5Yagj1WlOa0PIJp-GqBIVSA,28112
45
+ lgt_jobs/lgt_data/mongo_repository.py,sha256=6Cv5L90jUPgzTbv5vCjsGSOkeCdzVJf0pTRYHujBnUU,44855
47
46
  lgt_jobs/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
47
  lgt_jobs/services/web_client.py,sha256=GLWsJkIC8rv6xLFaLwcMm4EwBlVDu0njORwkZqBJaE4,2086
49
48
  lgt_jobs/templates/new_message.html,sha256=BD_E90akmQ1Wf07wtZAjeK_7DUKRmja5HFHVo_AKI24,6994
50
- leadguru_jobs-0.541.0.dist-info/METADATA,sha256=Q5__VkynO0HZNbyMvhgTzXWlxMQdAoC7uuENThf3t6I,1319
51
- leadguru_jobs-0.541.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
52
- leadguru_jobs-0.541.0.dist-info/top_level.txt,sha256=rIuw1DqwbnZyeoarBSC-bYeGOhv9mZBs7_afl9q4_JI,9
53
- leadguru_jobs-0.541.0.dist-info/RECORD,,
49
+ leadguru_jobs-0.543.0.dist-info/METADATA,sha256=BSC1hi76_fPJxmBt6C__Sd9VpnWH9vfbEV8VWq6d1IU,1319
50
+ leadguru_jobs-0.543.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
51
+ leadguru_jobs-0.543.0.dist-info/top_level.txt,sha256=rIuw1DqwbnZyeoarBSC-bYeGOhv9mZBs7_afl9q4_JI,9
52
+ leadguru_jobs-0.543.0.dist-info/RECORD,,
@@ -30,10 +30,6 @@ class PubSubFactory:
30
30
  topic_path = self.get_topic_path(topic_name)
31
31
  self.publisher.api.delete_topic(topic=topic_path)
32
32
 
33
- def delete_subscriber(self, subscriber_name: str, topic_name: str):
34
- subscription_path = self.get_subscription_path(subscriber_name, topic_name)
35
- self.subscriber.api.delete_subscription(subscription=subscription_path)
36
-
37
33
  def create_subscription_if_doesnt_exist(self, subscriber_name, topic_name,
38
34
  ack_deadline_seconds=60) -> pubsub_v1.types.pubsub_gapic_types.Subscription:
39
35
  subscription_path = self.get_subscription_path(subscriber_name, topic_name)
@@ -6,7 +6,6 @@ class SlackMethods:
6
6
  users_list = 'users.list'
7
7
  users_info = 'users.info'
8
8
  users_get_presence = 'users.getPresence'
9
- list_users = "users.list"
10
9
 
11
10
  conversations_join = 'conversations.join'
12
11
  conversations_leave = 'conversations.leave'
@@ -19,7 +18,6 @@ class SlackMethods:
19
18
  chat_delete = 'chat.delete'
20
19
  chat_update = 'chat.update'
21
20
  chat_post_message = 'chat.postMessage'
22
- chat_schedule_message = "chat.scheduleMessage"
23
21
  chat_attachments = "chat.unfurlLink"
24
22
 
25
23
  rtm_connect = 'rtm.connect'
@@ -30,6 +28,7 @@ class SlackMethods:
30
28
  alternative_invite_by_email = 'users.inviteRequests.create'
31
29
 
32
30
  upload_file = 'files.upload'
31
+ files_info = 'files.info'
33
32
  download_file = 'files.download'
34
33
  delete_file = 'files.delete'
35
34
  share_files = 'files.share'
@@ -1,13 +1,10 @@
1
1
  import requests
2
- import aiohttp
3
- import asyncio
4
- import websockets
5
2
  import json
6
3
  import io
7
4
  from urllib import parse
8
5
  from requests import Response
9
6
  from websockets.client import WebSocketClientProtocol
10
- from .methods import SlackMethods
7
+ from lgt_jobs.lgt_common.slack_client.methods import SlackMethods
11
8
 
12
9
 
13
10
  class SlackClient:
@@ -25,34 +22,6 @@ class SlackClient:
25
22
  else:
26
23
  self.cookies = cookies
27
24
 
28
- def join_channels(self, channels):
29
- loop = asyncio.new_event_loop()
30
- asyncio.set_event_loop(loop)
31
- tasks = asyncio.gather(*[self.join_channel_async(channel) for channel in channels])
32
- results = loop.run_until_complete(tasks)
33
- loop.close()
34
- return results
35
-
36
- def leave_channels(self, channels):
37
- loop = asyncio.new_event_loop()
38
- asyncio.set_event_loop(loop)
39
- tasks = asyncio.gather(*[self.leave_channel_async(channel) for channel in channels])
40
- results = loop.run_until_complete(tasks)
41
- loop.close()
42
- return results
43
-
44
- async def join_channel_async(self, channel):
45
- async with aiohttp.ClientSession() as session:
46
- url = f'{self.base_url}{SlackMethods.conversations_join}?{self.__channel_payload(channel)}'
47
- async with session.post(url=url, cookies=self.cookies) as response:
48
- return await response.json()
49
-
50
- async def leave_channel_async(self, channel):
51
- async with aiohttp.ClientSession() as session:
52
- url = f'{self.base_url}{SlackMethods.conversations_leave}?{self.__channel_payload(channel)}'
53
- async with session.post(url=url, cookies=self.cookies) as response:
54
- return await response.json()
55
-
56
25
  def upload_file(self, file, file_name):
57
26
  payload = {"content": file, "filename": file_name}
58
27
  return requests.post(f"{self.base_url}{SlackMethods.upload_file}", data=payload,
@@ -78,6 +47,10 @@ class SlackClient:
78
47
  return requests.post(f"{self.base_url}{SlackMethods.share_files}", data=payload,
79
48
  headers=self.headers, cookies=self.cookies).json()
80
49
 
50
+ def get_file_info(self, file_id: str):
51
+ return requests.get(url=f"{self.base_url}{SlackMethods.files_info}",
52
+ cookies=self.cookies, headers=self.headers, params={'file': file_id}).json()
53
+
81
54
  def get_profile(self, user_id: str = None):
82
55
  url = f'{self.base_url}{SlackMethods.profile_get}'
83
56
  payload = {}
@@ -165,10 +138,6 @@ class SlackClient:
165
138
  url = f'{self.base_url}{SlackMethods.conversations_replies}?{self.__ts_payload(channel, id)}'
166
139
  return requests.get(url=url, cookies=self.cookies).json()
167
140
 
168
- def get_presense(self, user: str = None):
169
- url = f'{self.base_url}{SlackMethods.users_get_presence}?{self.__presense_payload(user)}'
170
- return requests.get(url=url, cookies=self.cookies).json()
171
-
172
141
  def post_message(self, channel: str, text: str):
173
142
  import uuid
174
143
  payload = {
@@ -179,21 +148,6 @@ class SlackClient:
179
148
  url = f'{self.base_url}{SlackMethods.chat_post_message}'
180
149
  return requests.post(url=url, cookies=self.cookies, headers=self.headers, data=payload).json()
181
150
 
182
- def post_message_schedule(self, channel: str, text: str, post_at: int):
183
- url = (f'{self.base_url}{SlackMethods.chat_schedule_message}?'
184
- f'{self.__post_scheduled_message_payload(channel, text, post_at)}')
185
- return requests.post(url=url, cookies=self.cookies).json()
186
-
187
- def users_list(self, cursor=None, limit: int = 1000):
188
- url = f'{self.base_url}{SlackMethods.users_list}?{self.__token_payload()}'
189
- if cursor:
190
- url += f'&cursor={cursor}'
191
-
192
- if limit:
193
- url += f'&limit={limit}'
194
-
195
- return requests.get(url=url, cookies=self.cookies).json()
196
-
197
151
  def user_info(self, user: str):
198
152
  url = f'{self.base_url}{SlackMethods.users_info}?{self.__user_info_payload(user)}'
199
153
  return requests.get(url=url, cookies=self.cookies).json()
@@ -202,19 +156,6 @@ class SlackClient:
202
156
  url = f'{self.base_url}{SlackMethods.reactions_get}?{self.__get_reactions_payload(channel, id)}'
203
157
  return requests.get(url=url, cookies=self.cookies).json()
204
158
 
205
- def get_attachments(self, channel: str, msg_id: str, url: str):
206
- payload = {
207
- 'token': self.token,
208
- 'channel': channel,
209
- 'client_msg_id': msg_id,
210
- 'url': url
211
- }
212
- url = f'{self.base_url}{SlackMethods.chat_attachments}'
213
- response = requests.post(url=url, cookies=self.cookies, data=payload)
214
- if response.status_code != 200:
215
- return
216
- return response.json().get('attachments')
217
-
218
159
  def check_email(self, email: str, user_agent: str) -> bool:
219
160
  payload = {'email': email}
220
161
  headers = {'User-Agent': user_agent}
@@ -270,23 +211,6 @@ class SlackClient:
270
211
  return requests.post(f"{self.base_url}/{SlackMethods.auth_test}", headers=headers,
271
212
  cookies=self.cookies)
272
213
 
273
- def rtm_connect(self, callback):
274
- loop = asyncio.new_event_loop()
275
- loop.run_until_complete(self.__consumer(callback))
276
- loop.run_forever()
277
-
278
- async def __consumer(self, callback):
279
- url = f'{self.base_url}{SlackMethods.rtm_connect}?{self.__token_payload()}'
280
- response = requests.get(url=url, cookies=self.cookies).json()
281
- web_socket_url = response['url']
282
- async with websockets.connect(uri=web_socket_url) as websocket:
283
- self.socket = websocket
284
- async for message in websocket:
285
- await callback(json.loads(message))
286
-
287
- def __token_payload(self):
288
- return parse.urlencode({'token': self.token})
289
-
290
214
  def __user_info_payload(self, user):
291
215
  payload = {
292
216
  'token': self.token,
@@ -294,15 +218,6 @@ class SlackClient:
294
218
  }
295
219
  return parse.urlencode(payload)
296
220
 
297
- def __post_scheduled_message_payload(self, channel, text, post_at):
298
- payload = {
299
- 'token': self.token,
300
- 'channel': channel,
301
- 'text': text,
302
- 'post_at': post_at
303
- }
304
- return parse.urlencode(payload)
305
-
306
221
  def __update_message_payload(self, channel, id, text, file_ids):
307
222
  payload = {
308
223
  'parse': 'none',
@@ -345,13 +260,6 @@ class SlackClient:
345
260
  }
346
261
  return parse.urlencode(payload)
347
262
 
348
- def __update_profile_payload(self, profile):
349
- payload = {
350
- 'token': self.token,
351
- 'profile': profile
352
- }
353
- return parse.urlencode(payload)
354
-
355
263
  def __channel_payload(self, channel, id=None):
356
264
  payload = {
357
265
  'token': self.token,
@@ -365,15 +273,6 @@ class SlackClient:
365
273
 
366
274
  return parse.urlencode(payload)
367
275
 
368
- def __presense_payload(self, user: str = None):
369
- payload = {
370
- 'token': self.token,
371
- }
372
-
373
- if user:
374
- payload["user"] = user
375
- return parse.urlencode(payload)
376
-
377
276
  def __ts_payload(self, channel: str, id: str):
378
277
  payload = {
379
278
  'token': self.token,
@@ -76,7 +76,6 @@ class SlackFilesClient:
76
76
  blob = bucket.blob(blob_path)
77
77
  blob.upload_from_string(res.content, content_type=mimetype)
78
78
 
79
- blob = bucket.get_blob(blob_path)
80
79
  # valid for 3 days
81
80
  return blob.generate_signed_url(timedelta(3))
82
81
 
@@ -106,9 +105,6 @@ class SlackWebClient:
106
105
  def post_message(self, to, text):
107
106
  return self.client.post_message(to, text)
108
107
 
109
- def user_list(self):
110
- return self.client.users_list()
111
-
112
108
  def channels_list(self):
113
109
  return self.client.get_conversations_list()
114
110
 
@@ -118,12 +114,6 @@ class SlackWebClient:
118
114
  def update_profile(self, profile):
119
115
  return self.client.update_profile(profile)
120
116
 
121
- def channel_join(self, channels):
122
- return self.client.join_channels(channels)
123
-
124
- def channel_leave(self, channels):
125
- return self.client.leave_channels(channels)
126
-
127
117
  def get_reactions(self, channel, id):
128
118
  return self.client.get_reactions(channel, id)
129
119
 
@@ -165,3 +155,6 @@ class SlackWebClient:
165
155
 
166
156
  def get_team_info(self):
167
157
  return self.client.get_team_info()
158
+
159
+ def get_file_info(self, file_id: str):
160
+ return self.client.get_file_info(file_id)
@@ -513,52 +513,6 @@ def get_bots_aggregated_analytics(from_date: datetime = None,
513
513
  return received_messages_dic, filtered_messages_dic
514
514
 
515
515
 
516
- def get_channel_aggregated_analytics(from_date: datetime = None, to_date: datetime = None,
517
- bot_id: Optional[str | ObjectId] = None):
518
- pipeline = [
519
- {
520
- '$match': {
521
- 'extra_ids': {"$in": [str(bot_id)]}
522
- }
523
- },
524
- {
525
- "$group": {
526
- '_id': {
527
- '$arrayElemAt': [
528
- '$attributes', 0
529
- ]
530
- },
531
- 'count': {"$sum": 1}
532
- }
533
- },
534
- {
535
- '$limit': 1000
536
- }
537
- ]
538
-
539
- if from_date:
540
- beginning_of_the_day = datetime(from_date.year, from_date.month, from_date.day, 0, 0, 0, 0)
541
- pipeline.insert(0, {"$match": {"created_at": {"$gte": beginning_of_the_day}}})
542
-
543
- if to_date:
544
- end_of_the_day = datetime(to_date.year, to_date.month, to_date.day, 23, 59, 59, 999)
545
- pipeline.insert(0, {"$match": {"created_at": {"$lte": end_of_the_day}}})
546
-
547
- received_messages = list(db[f'received_messages'].aggregate(pipeline))
548
- filtered_messages = list(db[f'filtered_messages'].aggregate(pipeline))
549
-
550
- received_messages_dic = OrderedDict()
551
- filtered_messages_dic = OrderedDict()
552
-
553
- for item in received_messages:
554
- received_messages_dic[item["_id"]] = item["count"]
555
-
556
- for item in filtered_messages:
557
- filtered_messages_dic[item["_id"]] = item["count"]
558
-
559
- return received_messages_dic, filtered_messages_dic
560
-
561
-
562
516
  def get_users_aggregated_analytics(event_type: str = 'user-lead-extended',
563
517
  from_date: datetime = None,
564
518
  to_date: datetime = None,
@@ -645,51 +599,6 @@ def get_events_leads(email, event, from_date, to_date=None):
645
599
  return list(db[event].find(pipeline))
646
600
 
647
601
 
648
- def get_leads_aggregation(email, event, from_date, to_date=None):
649
- pipeline = get_event_pipeline(email, from_date, to_date)
650
- return list(db[event].aggregate(pipeline))
651
-
652
-
653
- def get_event_pipeline(email, from_date, to_date=None):
654
- pipeline = [
655
- {
656
- "$match": {
657
- 'name': email,
658
- 'created_at': {'$gte': from_date}
659
- }
660
- },
661
- {
662
- '$group': {
663
- '_id': {
664
- '$dateFromParts': {
665
- 'day': {
666
- '$dayOfMonth': '$created_at'
667
- },
668
- 'month': {
669
- '$month': '$created_at'
670
- },
671
- 'year': {
672
- '$year': '$created_at'
673
- }
674
- }
675
- },
676
- 'count': {
677
- '$sum': 1
678
- }
679
- }
680
- },
681
- {
682
- "$sort": {"_id": 1}
683
- }
684
- ]
685
-
686
- if to_date:
687
- end = datetime(to_date.year, to_date.month, to_date.day, 23, 59, 59, tzinfo=tz.tzutc())
688
- pipeline[0]["$match"]["created_at"]['$lte'] = end
689
-
690
- return pipeline
691
-
692
-
693
602
  def get_total_analytic_followup_up_date(from_date, to_date=None):
694
603
  beginning_of_the_day = datetime(from_date.year, from_date.month, from_date.day, 0, 0, 0, 0)
695
604
  end_of_the_day = datetime(to_date.year, to_date.month, to_date.day, 23, 59, 59, 999)
@@ -5,7 +5,7 @@ from datetime import datetime, UTC
5
5
  from bson import ObjectId
6
6
  from mongoengine import connect, Document, DateTimeField, StringField, IntField, ObjectIdField, ListField
7
7
  from typing import Dict, Tuple, Optional
8
- from .mongo_repository import to_object_id, UserMongoRepository
8
+ from .mongo_repository import to_object_id
9
9
 
10
10
  connect(host=os.environ.get('MONGO_CONNECTION_STRING', 'mongodb://127.0.0.1:27017/'), db="lgt_admin", alias="lgt_admin")
11
11
 
@@ -73,29 +73,6 @@ class UserTrackAction(Document):
73
73
  metadata=metadata
74
74
  ).save()
75
75
 
76
- @staticmethod
77
- def get_ws_monitoring_logs(email: str, action_subtype: str, from_date: datetime, to_date: datetime,
78
- source_id=None) -> list[UserTrackAction]:
79
-
80
- pipeline = {'action': {'$regex': f"^monitoring.*{action_subtype}$"}}
81
-
82
- if email:
83
- user = UserMongoRepository().get_by_email(email)
84
- pipeline['user_id'] = to_object_id(user.id)
85
-
86
- if from_date:
87
- start = datetime(from_date.year, from_date.month, from_date.day)
88
- pipeline['created_at__gte'] = start
89
-
90
- if to_date:
91
- end = datetime(to_date.year, to_date.month, to_date.day, 23, 59, 59)
92
- pipeline['created_at__lte'] = end
93
-
94
- if source_id:
95
- pipeline['metadata'] = {'$regex': f"^{source_id}:"}
96
-
97
- return list(UserTrackAction.objects(**pipeline))
98
-
99
76
  @staticmethod
100
77
  def get_global_user_actions(user_id: str = None, from_date: datetime = None,
101
78
  to_date: datetime = None, actions: list = None) -> \
@@ -1,12 +1,6 @@
1
1
  from enum import Enum, IntFlag
2
2
 
3
3
 
4
- class DedicatedBotState(IntFlag):
5
- Operational = 0
6
- Stopped = 1
7
- ScheduledForDeletion = 2
8
-
9
-
10
4
  class UserAccountState(IntFlag):
11
5
  Operational = 0
12
6
  Suspended = 1
@@ -33,13 +27,6 @@ class SourceType(str, Enum):
33
27
  DISCORD = 'discord'
34
28
 
35
29
 
36
- class BotUpdateEventType(str, Enum):
37
- NotDefined = 'NotDefined'
38
- BotAdded = 'BotAdded'
39
- BotDeleted = 'BotDeleted'
40
- BotUpdated = 'BotUpdated'
41
-
42
-
43
30
  class UserAction(str, Enum):
44
31
  PAUSE_SOURCE = 'monitoring.pause.source'
45
32
  UNPAUSE_SOURCE = 'monitoring.unpause.source'
@@ -3,7 +3,7 @@ import copy
3
3
  import json
4
4
  from abc import ABC
5
5
  from datetime import datetime, UTC
6
- from typing import Optional, List, Dict
6
+ from typing import Optional, List
7
7
  from .enums import UserRole, SourceType, FeaturesEnum, FeatureOptions
8
8
  from bson import ObjectId
9
9
 
@@ -290,6 +290,8 @@ class UserModel(BaseModel):
290
290
  self.subscription_expired_at: datetime | None = None
291
291
  self.balance: str | None = None
292
292
  self.subscription_name: str | None = None
293
+ self.subscription_expiration_notified = False
294
+ self.subscription_expiration_warning_notified = False
293
295
 
294
296
  @classmethod
295
297
  def from_dic(cls, dic: dict):
@@ -540,37 +542,6 @@ class BotInfo:
540
542
  return result
541
543
 
542
544
 
543
- class SlackReplyModel(BaseModel):
544
- def __init__(self):
545
- super().__init__()
546
- self.type = None
547
- self.user = None
548
- self.username = None
549
- self.text = None
550
- self.thread_ts = None
551
- self.parent_user_id = None
552
- self.ts = None
553
- self.files = []
554
- self.attachments = []
555
-
556
- @classmethod
557
- def from_slack_response(cls, dic: dict):
558
- if not dic:
559
- return None
560
-
561
- model = cls()
562
- for k, v in dic.items():
563
- setattr(model, k, v)
564
-
565
- js_ticks = int(model.ts.split('.')[0] + model.ts.split('.')[1][3:])
566
- model.created_at = datetime.fromtimestamp(js_ticks / 1000.0)
567
-
568
- if model.files:
569
- model.files = [{"url_private_download": file.get("url_private_download")} for file in model.files]
570
-
571
- return model
572
-
573
-
574
545
  class ChatMessage:
575
546
  bot_id: ObjectId
576
547
  user_id: ObjectId
@@ -657,16 +628,6 @@ class UserLeadModel(LeadModel):
657
628
  result.chat_viewed_at = dic.get('chat_viewed_at')
658
629
  return result
659
630
 
660
- @staticmethod
661
- def from_route(lead: LeadModel):
662
- model_dict = lead.to_dic()
663
- result = UserLeadModel.from_dic(model_dict)
664
- result.order = 0
665
-
666
- result.message = MessageModel.from_dic(model_dict['message'])
667
- result.chat_viewed_at = None
668
- return result
669
-
670
631
 
671
632
  class ExtendedUserLeadModel(UserLeadModel):
672
633
  pass
@@ -892,8 +853,7 @@ class ExtendedSlackMemberInformation(SlackMemberInformation):
892
853
  return model
893
854
 
894
855
  @staticmethod
895
- def to_lead(contact: ExtendedSlackMemberInformation, linkedin_contacts: Dict[str, LinkedinContact] = None) \
896
- -> ExtendedUserLeadModel:
856
+ def to_lead(contact: ExtendedSlackMemberInformation) -> ExtendedUserLeadModel:
897
857
  lead = ExtendedUserLeadModel()
898
858
  lead.id = str(contact.id)
899
859
  lead.created_at = contact.created_at
@@ -936,13 +896,6 @@ class UserTemplateModel(BaseModel):
936
896
  user_id: Optional[ObjectId]
937
897
 
938
898
 
939
- class LinkedinContact(BaseModel):
940
- full_name: str
941
- slack_user: str
942
- title: str
943
- urls: List[dict]
944
-
945
-
946
899
  class CloudFileModel(BaseModel):
947
900
  blob_path: str
948
901
  public_url: str
@@ -7,7 +7,7 @@ from pymongo import MongoClient, UpdateOne
7
7
  from bson.objectid import ObjectId
8
8
  from lgt_jobs.lgt_data.enums import SourceType
9
9
  from lgt_jobs.lgt_data.model import (LeadModel, BaseModel, UserModel, UserResetPasswordModel, BoardModel, BoardedStatus,
10
- DedicatedBotModel, SlackMemberInformation, UserTemplateModel, LinkedinContact,
10
+ DedicatedBotModel, SlackMemberInformation, UserTemplateModel,
11
11
  ExtendedUserLeadModel, UserLeadModel, ExtendedLeadModel, UserContact, ChatMessage,
12
12
  GroupedMessagesModel, UserVerificationModel, UsersPage, Subscription)
13
13
  from datetime import datetime, UTC, timedelta
@@ -153,10 +153,6 @@ class UserLeadMongoRepository(BaseMongoRepository):
153
153
  collection_name = 'user_leads'
154
154
  model = ExtendedUserLeadModel
155
155
 
156
- def get_count(self, user_id, **kwargs):
157
- pipeline = self.__create_leads_filter(user_id, **kwargs)
158
- return self.collection().count_documents(pipeline)
159
-
160
156
  def get_many(self, ids: list, user_id):
161
157
  docs = self.collection().find({"id": {'$in': ids}, 'user_id': to_object_id(user_id)})
162
158
  leads = [ExtendedUserLeadModel.from_dic(lead) for lead in docs]
@@ -292,54 +288,6 @@ class UserLeadMongoRepository(BaseMongoRepository):
292
288
  pipeline["message.dedicated_slack_options.bot_id"] = {"$in": dedicated_bots_ids}
293
289
  return pipeline
294
290
 
295
- def get_unanswered_leads_ids(self, user_id: str, from_date=None):
296
- pipeline = [
297
- {
298
- '$match':
299
- {
300
- 'user_id': to_object_id(user_id)
301
- }
302
- },
303
- {
304
- '$match':
305
- {
306
- 'chat_history': {'$exists': True, '$not': {'$size': 0}}
307
- }
308
- },
309
- {
310
- '$project':
311
- {
312
- 'id': 1,
313
- 'sender_id': "$message.sender_id",
314
- 'last_message': {'$arrayElemAt': ['$chat_history', 0]}
315
- }
316
- },
317
- {
318
- '$addFields':
319
- {
320
- 'is_user_message': {'$ne': ['$sender_id', '$last_message.user']}
321
- }
322
- },
323
- {
324
- '$match':
325
- {
326
- '$and':
327
- [
328
- {'last_message.text': {'$regex': '\\?'}},
329
- {'is_user_message': False}
330
- ]
331
- }
332
- }
333
- ]
334
-
335
- if from_date:
336
- beginning_of_the_day = datetime(from_date.year, from_date.month, from_date.day, 0, 0, 0, 0)
337
- pipeline.insert(0, {"$match": {"created_at": {"$gte": beginning_of_the_day}}})
338
-
339
- data = list(self.collection().aggregate(pipeline))
340
- leads_ids = [item['id'] for item in data]
341
- return leads_ids
342
-
343
291
  def get_daily_analytics_by_workspace(self, user_configs: list,
344
292
  dedicated_only: bool | None,
345
293
  from_date: datetime,
@@ -405,10 +353,6 @@ class UserLeadMongoRepository(BaseMongoRepository):
405
353
 
406
354
  return saved_messages_dic
407
355
 
408
- def get_leads_after(self, action_after: datetime) -> [ExtendedUserLeadModel]:
409
- leads = self.collection().find({'last_action_at': {'$gte': action_after}})
410
- return [ExtendedUserLeadModel.from_dic(lead) for lead in leads]
411
-
412
356
  def add_lead(self, user_id, lead: UserLeadModel) -> None:
413
357
  if not lead.created_at:
414
358
  lead.created_at = datetime.now(UTC)
@@ -429,11 +373,6 @@ class UserLeadMongoRepository(BaseMongoRepository):
429
373
 
430
374
  return ExtendedUserLeadModel.from_dic(self.collection().find_one(pipeline))
431
375
 
432
- def update_same_leads(self, user_id, sender_id: str, **kwargs):
433
- pipeline = {'user_id': to_object_id(user_id), 'message.sender_id': sender_id}
434
- update_dict = {k: v for k, v in kwargs.items() if v is not None}
435
- self.collection().update_many(pipeline, {'$set': update_dict})
436
-
437
376
  def update_leads_order(self, user_id, lead_ids: [str]):
438
377
  pipeline = {'user_id': to_object_id(user_id), 'id': {'$in': lead_ids}}
439
378
  docs = list(self.collection().find(pipeline))
@@ -559,10 +498,6 @@ class LeadMongoRepository(BaseMongoRepository):
559
498
  update_dict = {k: v for k, v in kwargs.items() if v is not None}
560
499
  self.collection().update_one({'id': _id}, {'$set': update_dict}, upsert=False)
561
500
 
562
- def get_count(self, **kwargs):
563
- pipeline = self.__create_leads_filter(**kwargs)
564
- return self.collection().count_documents(pipeline)
565
-
566
501
  def get_list(self, skip, limit, **kwargs):
567
502
  pipeline = self.__create_leads_filter(**kwargs)
568
503
 
@@ -684,10 +619,6 @@ class SpamLeadsMongoRepository(LeadMongoRepository):
684
619
  lead.contact = next(filter(lambda x: x.sender_id == lead.message.sender_id, contacts), None)
685
620
  return leads
686
621
 
687
- def get_count(self, **kwargs):
688
- pipeline = self.__create_leads_filter(**kwargs)
689
- return self.collection().count_documents(pipeline)
690
-
691
622
  def __create_leads_filter(self, **kwargs):
692
623
  pipeline = {"user_id": {'$exists': False}}
693
624
  text = kwargs.get('text', None)
@@ -883,14 +814,6 @@ class DedicatedBotRepository(BaseMongoRepository):
883
814
 
884
815
  collection_name = 'dedicated_bots'
885
816
 
886
- def get_by_user_and_source_id(self, user_id: str, source_id: str) -> Optional[DedicatedBotModel]:
887
- doc = self.collection().find_one({"user_id": ObjectId(f"{user_id}"), "source.source_id": source_id})
888
- return DedicatedBotModel.from_dic(doc)
889
-
890
- def get_by_user_and_active_server_id(self, user_id: str, active_server_id: str) -> Optional[DedicatedBotModel]:
891
- doc = self.collection().find_one({"user_id": ObjectId(f"{user_id}"), "active_servers.id": active_server_id})
892
- return DedicatedBotModel.from_dic(doc)
893
-
894
817
  def add_or_update(self, bot: DedicatedBotModel):
895
818
  bot_dict = bot.to_dic()
896
819
  if '_id' in bot_dict:
@@ -923,25 +846,6 @@ class DedicatedBotRepository(BaseMongoRepository):
923
846
  pipeline = self.__create_bots_filter(**kwargs)
924
847
  return DedicatedBotModel.from_dic(self.collection().find_one(pipeline))
925
848
 
926
- def get_user_bots(self, user_id: str, only_valid: bool = False,
927
- include_deleted: bool = False, include_paused: bool = False, **kwargs) -> List[DedicatedBotModel]:
928
- pipeline = {'user_id': to_object_id(user_id)}
929
- user_name = kwargs.get('user_name')
930
-
931
- if user_name:
932
- pipeline['user_name'] = user_name
933
-
934
- if not include_deleted:
935
- pipeline['deleted'] = False
936
-
937
- if not include_paused:
938
- pipeline['paused'] = False
939
-
940
- if only_valid:
941
- pipeline['invalid_creds'] = False
942
-
943
- return [DedicatedBotModel.from_dic(doc) for doc in self.collection().find(pipeline)]
944
-
945
849
  def delete(self, _id: str):
946
850
  self.collection().update_one({'_id': to_object_id(f"{_id}")}, {"$set": {"deleted": True}})
947
851
 
@@ -1025,26 +929,6 @@ class SlackContactUserRepository(BaseMongoRepository):
1025
929
  pipeline = {"sender_id": user_id}
1026
930
  return SlackMemberInformation.from_dic(self.collection().find_one(pipeline))
1027
931
 
1028
- def get_count_in_workspaces(self):
1029
- pipeline = [
1030
- {
1031
- '$match': {
1032
- 'user': {
1033
- '$ne': 'USLACKBOT'
1034
- }
1035
- }
1036
- }, {
1037
- '$group': {
1038
- '_id': '$workspace',
1039
- 'count': {
1040
- '$sum': 1
1041
- }
1042
- }
1043
- }
1044
- ]
1045
- docs = list(self.collection().aggregate(pipeline))
1046
- return {doc['_id']: doc['count'] for doc in docs}
1047
-
1048
932
 
1049
933
  class UserTemplatesRepository(BaseMongoRepository):
1050
934
  collection_name = "user_templates"
@@ -1071,15 +955,6 @@ class UserTemplatesRepository(BaseMongoRepository):
1071
955
  return self.collection().find_one_and_delete({'_id': to_object_id(id)})
1072
956
 
1073
957
 
1074
- class LinkedinContactRepository(BaseMongoRepository):
1075
- collection_name = "linkedin_contact"
1076
- model = LinkedinContact
1077
-
1078
- def find(self, **kwargs):
1079
- docs = self.collection().find({**kwargs})
1080
- return [LinkedinContact.from_dic(doc) for doc in docs]
1081
-
1082
-
1083
958
  class UserContactsRepository(BaseMongoRepository):
1084
959
  collection_name = 'user_contacts'
1085
960
 
lgt_jobs/main.py CHANGED
@@ -40,7 +40,7 @@ if __name__ == '__main__':
40
40
  client.setup_logging()
41
41
  factory = PubSubFactory(project_id)
42
42
  factory.create_topic_if_doesnt_exist(background_jobs_topic)
43
- factory.create_subscription_if_doesnt_exist(background_jobs_subscriber, background_jobs_topic,600)
43
+ factory.create_subscription_if_doesnt_exist(background_jobs_subscriber, background_jobs_topic, 600)
44
44
  bot_subscription_path = factory.get_subscription_path(background_jobs_subscriber, background_jobs_topic)
45
45
  factory.subscriber.subscribe(bot_subscription_path, callback=run_background_job_with_lock)
46
46
  while True:
@@ -1,14 +0,0 @@
1
- import enum
2
- from typing import Optional
3
- from pydantic import BaseModel, Extra
4
-
5
-
6
- class TelegramCommandType(enum.Enum):
7
- AUTH_VERIFICATION_CODE = 1
8
- HARD_RESET = 1
9
-
10
-
11
- class TelegramCommand(BaseModel, extra=Extra.ignore):
12
- bot_id: str
13
- type: int
14
- data: Optional[str]