leadguru-jobs 0.559.0__py3-none-any.whl → 0.561.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.559.0
3
+ Version: 0.561.0
4
4
  Summary: LGT jobs builds
5
5
  Author-email: developer@leadguru.co
6
6
  Classifier: Development Status :: 5 - Production/Stable
@@ -1,4 +1,4 @@
1
- lgt_jobs/__init__.py,sha256=kmM5J3qBJd-fOZa2I4gkh36IytrgN6_18gWwwpR3n6Y,2156
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
4
  lgt_jobs/main.py,sha256=cK_nkBtJHnUNDbba1WZotqPtI_6OWxiYQkAgco9OAmE,1539
@@ -13,12 +13,11 @@ lgt_jobs/assets/images/mail.png,sha256=eORzQcAMkFr7DjgtABVhJ_zFuXgO7OXv78lLF4b39
13
13
  lgt_jobs/jobs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
14
  lgt_jobs/jobs/analytics.py,sha256=IIsWt4A1qUw3w-S-8W16uKY1FRVWfXXA41_mu4uCNiM,979
15
15
  lgt_jobs/jobs/bot_stats_update.py,sha256=R6mf5FxhWbyx92AYXlj0FZVjz2Tgz86mBvLHrsQ9AFE,7502
16
- lgt_jobs/jobs/chat_history.py,sha256=tZ4XyOGdy1k6r4uotxSSKbXjTR_oRK6Ym0YthFYBtl8,6200
17
- lgt_jobs/jobs/connect_sources.py,sha256=CD15PKYrloepfr8fqUP0XkmvXb9VZDXfLNhYiiYeQ3U,3668
16
+ lgt_jobs/jobs/chat_history.py,sha256=QZdSWlk_DrDJt5yrNApYHiUEWQMYcKyuXaP_PlzkjYw,6303
18
17
  lgt_jobs/jobs/inbox_leads.py,sha256=EYxdQPseNBY5ON7BK3LpnXDCgQpzHTPLRJCZmZiAAHA,5582
19
18
  lgt_jobs/jobs/mass_message.py,sha256=1mFcBlL2MhzLbj5yrd_NyJc7TXDWCcROAzGDnr0miMU,2035
20
19
  lgt_jobs/jobs/send_code.py,sha256=dIlLPkG3GgGKIEqGiElyzrtdrnJNTL1Ak2V0xnE-WIQ,824
21
- lgt_jobs/jobs/send_slack_message.py,sha256=IuRqDGcDrz2EAZzF6nrLXO0aSA4mETB_tGOEbcMhjHE,2562
20
+ lgt_jobs/jobs/send_slack_message.py,sha256=WdXXh7QpjJKSvDU93YT9QKzoGRNBpPCJgiIxPs5gp1s,2782
22
21
  lgt_jobs/jobs/update_slack_profile.py,sha256=0fUHBd2gEBne52sTfxwji2Wu-oYDM5dLGsL-rHq5kwM,2765
23
22
  lgt_jobs/jobs/user_balance_update.py,sha256=HxeEmDdloK9EcoEj1ybYTgxIkB0IQNLnss_kk3rLI1Q,2404
24
23
  lgt_jobs/jobs/workspace_connect.py,sha256=qgjIRzAQRbJBx--eYsTtYgOUh2-p3N_-LIltfbJrYYo,7102
@@ -35,19 +34,19 @@ lgt_jobs/lgt_common/pubsub/messages.py,sha256=rm7uKbxwDTWJqsVA8Kee-4YT58bThjCEV2
35
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
36
  lgt_jobs/lgt_common/slack_client/methods.py,sha256=ctKF_1UHEmSWaRsoGEgMZicVabV7eEufZ7pjxdMAx8g,1455
38
- lgt_jobs/lgt_common/slack_client/slack_client.py,sha256=fxSTaU696yfe5tFWnuW6LuH4EUkgB2kdqDxQ96GYMJY,13799
39
- lgt_jobs/lgt_common/slack_client/web_client.py,sha256=JrkEepL6EhEtX3Psv_sd25bcRB2P23LoGnFHcczQpnc,4778
37
+ lgt_jobs/lgt_common/slack_client/slack_client.py,sha256=icHapSOszFYnSofJ-eWl4lUWSOqng6S9XSRFfMx87Rg,13836
38
+ lgt_jobs/lgt_common/slack_client/web_client.py,sha256=hiexBYtCnwz0oZvU6GnlQkD3aDqt9v5CvfPWMbz3Z50,6311
40
39
  lgt_jobs/lgt_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
40
  lgt_jobs/lgt_data/analytics.py,sha256=TFUffL8Dn-vIJ3ZaCVN-cj1Qnjb8F9GJyuk6Fo7mR1s,21645
42
41
  lgt_jobs/lgt_data/engine.py,sha256=Rsbz-CApAo_TVDssdjBkv8v_fVOZm_Uh1S6W4fnaEWo,7728
43
42
  lgt_jobs/lgt_data/enums.py,sha256=GZn6wm-kOd3veEOo1qlOR8QYje4vKaGV0na9jGt9388,2160
44
43
  lgt_jobs/lgt_data/helpers.py,sha256=NDa-V5EYaJfkGoWsmQSwSe6N_jxNxs8tHRQzW1iST6k,480
45
- lgt_jobs/lgt_data/model.py,sha256=BtVpJC_TRXUOklpzwRiDywyuKCCV2GGXtjsRYcPibDc,28454
46
- lgt_jobs/lgt_data/mongo_repository.py,sha256=wdhslZTfTU-3Ad4Gm8NVl9HZFM5aK_vgG47EqNQBARk,45179
44
+ lgt_jobs/lgt_data/model.py,sha256=DDfoWeH6rLWKoZsFJ2tI5Yagj1WlOa0PIJp-GqBIVSA,28112
45
+ lgt_jobs/lgt_data/mongo_repository.py,sha256=qqbt-oJ-RHmICLARgWvHuyPwVeKFkUqJZ2MA1bfIlXs,44762
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.559.0.dist-info/METADATA,sha256=A_vZrWjKQsHxV06Ou4NsbjAhA24uX3QqaknlN0NcKkk,1319
51
- leadguru_jobs-0.559.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
52
- leadguru_jobs-0.559.0.dist-info/top_level.txt,sha256=rIuw1DqwbnZyeoarBSC-bYeGOhv9mZBs7_afl9q4_JI,9
53
- leadguru_jobs-0.559.0.dist-info/RECORD,,
49
+ leadguru_jobs-0.561.0.dist-info/METADATA,sha256=-bP6WNVz3lmRi9b290wt67FhtcWHWcskt_G98oSboBA,1319
50
+ leadguru_jobs-0.561.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
51
+ leadguru_jobs-0.561.0.dist-info/top_level.txt,sha256=rIuw1DqwbnZyeoarBSC-bYeGOhv9mZBs7_afl9q4_JI,9
52
+ leadguru_jobs-0.561.0.dist-info/RECORD,,
lgt_jobs/__init__.py CHANGED
@@ -3,7 +3,6 @@ name = "lgt_jobs"
3
3
  from .jobs.user_balance_update import UpdateUserBalanceJob, UpdateUserBalanceJobData
4
4
  from .jobs.send_slack_message import SendSlackMessageJob, SendSlackMessageJobData
5
5
  from .jobs.analytics import (TrackAnalyticsJob, TrackAnalyticsJobData)
6
- from .jobs.connect_sources import (ConnectSourceJobData, ConnectSourceJob)
7
6
  from .jobs.bot_stats_update import (BotStatsUpdateJob, BotStatsUpdateJobData)
8
7
  from .jobs.chat_history import (LoadChatHistoryJob, LoadChatHistoryJobData)
9
8
  from .jobs.update_slack_profile import (UpdateExternalUserProfileJob, UpdateExternalUserProfileJobData)
@@ -23,7 +22,6 @@ jobs_map = {
23
22
  "SendSlackMessageJob": SendSlackMessageJob,
24
23
  "UpdateUserBalanceJob": UpdateUserBalanceJob,
25
24
  "SendMassMessageSlackChannelJob": SendMassMessageSlackChannelJob,
26
- "ConnectSourceJob": ConnectSourceJob
27
25
  }
28
26
  __all__ = [
29
27
  # Jobs
@@ -37,7 +35,6 @@ __all__ = [
37
35
  SendSlackMessageJob,
38
36
  UpdateUserBalanceJob,
39
37
  SendMassMessageSlackChannelJob,
40
- ConnectSourceJob,
41
38
 
42
39
  # module classes
43
40
  BackgroundJobRunner,
@@ -53,7 +50,6 @@ __all__ = [
53
50
  SendSlackMessageJobData,
54
51
  UpdateUserBalanceJobData,
55
52
  SendMassMessageSlackChannelJobData,
56
- ConnectSourceJobData,
57
53
  # mapping
58
54
  jobs_map
59
55
  ]
@@ -100,8 +100,9 @@ class LoadChatHistoryJob(BaseBackgroundJob, ABC):
100
100
  if not messages:
101
101
  return None
102
102
 
103
- messages = [SlackMessageConvertService.from_slack_response(bot.user_name, m, contact.sender_id,
104
- bot.id, user.id) for m in messages]
103
+ messages = [SlackMessageConvertService.from_slack_response(user.email, "slack_files",
104
+ bot.token, m, contact.sender_id, bot.id,
105
+ user.id, bot.cookies) for m in messages]
105
106
  new_messages = self._get_new_messages(contact, bot, messages)
106
107
  chat_history = [message.to_dic() for message in new_messages]
107
108
  self.chat_repo.upsert_messages(chat_history)
@@ -54,7 +54,9 @@ class SendSlackMessageJob(BaseBackgroundJob, ABC):
54
54
  message = resp.get('message') if 'message' in resp \
55
55
  else slack_client.conversation_replies(channel_id, resp['file_msg_ts'])['messages'][0]
56
56
 
57
- message_model: ChatMessage = SlackMessageConvertService.from_slack_response(bot.user_name, message,
58
- data.sender_id, bot.id, user.id)
57
+ message_model: ChatMessage = SlackMessageConvertService.from_slack_response(user.email, "slack_files",
58
+ bot.token, message, data.sender_id,
59
+ bot.id, user.id,
60
+ slack_client.client.cookies)
59
61
  message_model.viewed = True
60
62
  ChatRepository().upsert_messages([message_model.to_dic()])
@@ -54,13 +54,14 @@ class SlackClient:
54
54
 
55
55
  def users_list(self, cursor=None, limit: int = 1000):
56
56
  url = f'{self.base_url}{SlackMethods.users_list}'
57
+ payload = {}
57
58
  if cursor:
58
- url += f'&cursor={cursor}'
59
+ payload['cursor'] = cursor
59
60
 
60
61
  if limit:
61
- url += f'&limit={limit}'
62
+ payload['limit'] = limit
62
63
 
63
- return requests.get(url=url, cookies=self.cookies, headers=self.headers).json()
64
+ return requests.get(url=url, cookies=self.cookies, headers=self.headers, params=payload).json()
64
65
 
65
66
  def upload_file(self, file, file_name):
66
67
  payload = {"content": file, "filename": file_name}
@@ -1,13 +1,28 @@
1
+ import requests
1
2
  from google.cloud import storage
2
3
  from datetime import datetime, timedelta
3
- from lgt_jobs.lgt_data.model import ChatMessage, LeadGuruFile
4
- from lgt_jobs.lgt_common.slack_client.slack_client import SlackClient
5
- from lgt_jobs.lgt_data.mongo_repository import to_object_id
4
+ from lgt_jobs.lgt_data.model import ChatMessage
5
+ from .slack_client import SlackClient
6
+ from ...lgt_data.mongo_repository import to_object_id
7
+
8
+
9
+ def get_file_url(blob_path):
10
+ storage_client = storage.Client()
11
+ bucket = storage_client.get_bucket(SlackFilesClient.bucket_name)
12
+ blob = bucket.get_blob(blob_path)
13
+ if not blob:
14
+ return None
15
+ # valid for 3 days
16
+ return blob.generate_signed_url(timedelta(3))
6
17
 
7
18
 
8
19
  class SlackMessageConvertService:
9
20
  @staticmethod
10
- def from_slack_response(bot_name, dic, sender_id, bot_id, user_id) -> ChatMessage:
21
+ def from_slack_response(user_email, bot_name, bot_token, dic, sender_id, bot_id, user_id, cookies=None):
22
+
23
+ """
24
+ :rtype: SlackHistoryMessageModel
25
+ """
11
26
  result = ChatMessage()
12
27
  result.sender_id = sender_id
13
28
  result.bot_id = bot_id
@@ -17,15 +32,24 @@ class SlackMessageConvertService:
17
32
  result.attachments = dic.get('attachments', [])
18
33
  result.files = []
19
34
  result.user_id = to_object_id(user_id)
35
+
20
36
  if 'files' in dic:
21
37
  for file in dic.get('files'):
22
- if file.get('mode') != "tombstone" and file.get('url_private_download'):
23
- leadguru_file = LeadGuruFile()
24
- leadguru_file.id = file['id']
25
- leadguru_file.content_type = file['mimetype']
26
- leadguru_file.file_name = file['name']
27
- leadguru_file.blob_path = f'slack_files/{bot_name}/slack_files/{file["id"]}'
28
- result.files.append(leadguru_file)
38
+ if file.get('mode', '') == "tombstone" or not file.get('url_private_download'):
39
+ continue
40
+ new_file = ChatMessage.SlackFileModel()
41
+ new_file.id = file.get('id')
42
+ new_file.name = file.get('name')
43
+ new_file.title = file.get('title')
44
+ new_file.filetype = file.get('filetype')
45
+ new_file.size = file.get('size')
46
+ new_file.mimetype = file.get('mimetype')
47
+
48
+ url_private_download = file.get('url_private_download')
49
+ new_file.download_url = SlackFilesClient.get_file_url(user_email, bot_name, bot_token,
50
+ new_file.id, url_private_download,
51
+ new_file.mimetype, cookies)
52
+ result.files.append(new_file)
29
53
 
30
54
  js_ticks = int(result.id.split('.')[0] + result.id.split('.')[1][3:])
31
55
  result.created_at = datetime.fromtimestamp(js_ticks / 1000.0)
@@ -35,12 +59,23 @@ class SlackMessageConvertService:
35
59
  class SlackFilesClient:
36
60
  bucket_name = 'lgt_service_file'
37
61
 
38
- def get_file_url(self, blob_path):
62
+ # Consider to cache these file somewhere in the super-fast cache solution
63
+ @staticmethod
64
+ def get_file_url(user_email, bot_name, bot_token, file_id, url_private_download, mimetype, cookies=None):
39
65
  storage_client = storage.Client()
40
- bucket = storage_client.get_bucket(self.bucket_name)
66
+ bucket = storage_client.get_bucket(SlackFilesClient.bucket_name)
67
+ blob_path = f'slack_files/{user_email}/{bot_name}/{file_id}'
41
68
  blob = bucket.get_blob(blob_path)
69
+
42
70
  if not blob:
43
- return None
71
+ res = requests.get(url_private_download, headers={'Authorization': f'Bearer {bot_token}'}, cookies=cookies)
72
+ if res.status_code != 200:
73
+ raise Exception(
74
+ f'Failed to download file: {url_private_download} from slack due to response: '
75
+ f'Code: {res.status_code} Error: {res.content}')
76
+ blob = bucket.blob(blob_path)
77
+ blob.upload_from_string(res.content, content_type=mimetype)
78
+
44
79
  # valid for 3 days
45
80
  return blob.generate_signed_url(timedelta(3))
46
81
 
@@ -103,10 +138,10 @@ class SlackWebClient:
103
138
  def confirm_email(self, email: str, user_agent: str, locale: str = 'en-US') -> bool:
104
139
  return self.client.confirm_email(email, user_agent, locale)
105
140
 
106
- def confirm_code(self, email: str, code: str, user_agent: str):
141
+ def confirm_code(self, email: str, code: str, user_agent: str, ) -> requests.Response:
107
142
  return self.client.confirm_code(email, code, user_agent)
108
143
 
109
- def find_workspaces(self, user_agent: str):
144
+ def find_workspaces(self, user_agent: str, ) -> requests.Response:
110
145
  return self.client.find_workspaces(user_agent)
111
146
 
112
147
  def conversation_replies(self, channel: str, id: str) -> dict:
@@ -322,10 +322,6 @@ class UserModel(BaseModel):
322
322
  def is_admin(self):
323
323
  return UserRole.ADMIN in self.roles
324
324
 
325
- @property
326
- def subscription_expired(self):
327
- return self.subscription_expired_at.replace(tzinfo=UTC) < datetime.now(UTC)
328
-
329
325
  def get_slack_user(self, slack_email: str):
330
326
  return next(filter(lambda x: slack_email == x.email, self.slack_users), None)
331
327
 
@@ -583,7 +579,9 @@ class ChatMessage:
583
579
 
584
580
  def to_dic(self):
585
581
  result = copy.deepcopy(self.__dict__)
586
- result['files'] = [x.to_dic() for x in result.get('files', [])]
582
+ if self.files and 'files' in result:
583
+ result['files'] = [x.to_dic() if isinstance(x, ChatMessage.SlackFileModel) else x for x in self.files]
584
+
587
585
  return result
588
586
 
589
587
  @classmethod
@@ -871,8 +869,7 @@ class ExtendedSlackMemberInformation(SlackMemberInformation):
871
869
  if not hasattr(contact, "display_name"):
872
870
  contact.display_name = contact.name
873
871
 
874
- lead.linkedin_urls = [
875
- f"https://www.linkedin.com/search/results/all/?keywords={contact.real_name}&origin=GLOBAL_SEARCH_HEADER&sid=u%40F"]
872
+ lead.linkedin_urls = [f"https://www.linkedin.com/search/results/all/?keywords={contact.real_name}&origin=GLOBAL_SEARCH_HEADER&sid=u%40F"]
876
873
  lead.message = MessageModel()
877
874
  lead.message.message = contact.real_name
878
875
  if contact.title:
@@ -974,19 +971,3 @@ class Subscription(BaseModel):
974
971
  model: Subscription | None = super().from_dic(dic)
975
972
  model.features = [Feature.from_dic(feature) for feature in dic.get('features', [])]
976
973
  return model
977
-
978
-
979
- class LeadGuruFile(DictionaryModel):
980
- id: str = None
981
- blob_path: str
982
- content_type: str
983
- file_name: str = None
984
-
985
-
986
- class ScheduledMessage(BaseModel):
987
- post_at: datetime
988
- bot_id: ObjectId
989
- user_id: ObjectId
990
- sender_id: str
991
- text: str | None
992
- files: list
@@ -9,8 +9,7 @@ from lgt_jobs.lgt_data.enums import SourceType
9
9
  from lgt_jobs.lgt_data.model import (LeadModel, BaseModel, UserModel, UserResetPasswordModel, BoardModel, BoardedStatus,
10
10
  DedicatedBotModel, SlackMemberInformation, UserTemplateModel,
11
11
  ExtendedUserLeadModel, UserLeadModel, ExtendedLeadModel, UserContact, ChatMessage,
12
- GroupedMessagesModel, UserVerificationModel, UsersPage, Subscription,
13
- ScheduledMessage)
12
+ GroupedMessagesModel, UserVerificationModel, UsersPage, Subscription)
14
13
  from datetime import datetime, UTC, timedelta
15
14
  from collections import OrderedDict
16
15
 
@@ -1208,15 +1207,3 @@ class SubscriptionsRepository(BaseMongoRepository):
1208
1207
  pipeline['expired'] = expired
1209
1208
 
1210
1209
  return Subscription.from_dic(self.collection().find_one(pipeline))
1211
-
1212
-
1213
- class ScheduledMessagesRepository(BaseMongoRepository):
1214
- pass
1215
-
1216
- collection_name = 'scheduled_messages'
1217
-
1218
- def find_all(self, only_actual: bool = True):
1219
- pipeline = {}
1220
- if only_actual:
1221
- pipeline['post_at'] = {'$lte': datetime.now(UTC)}
1222
- return [ScheduledMessage.from_dic(doc) for doc in self.collection().find(pipeline)]
@@ -1,82 +0,0 @@
1
- from abc import ABC
2
- from typing import List
3
- import logging as log
4
- from lgt_jobs.basejobs import BaseBackgroundJob, BaseBackgroundJobData
5
- from lgt_jobs.jobs.bot_stats_update import BotStatsUpdateJob, BotStatsUpdateJobData
6
- from lgt_jobs.runner import BackgroundJobRunner
7
- from lgt_jobs.lgt_data.engine import UserTrackAction
8
- from lgt_jobs.lgt_data.enums import SourceType, UserAction, StatusConnection
9
- from lgt_jobs.lgt_data.model import BaseModel, DedicatedBotModel, Server, Source, SlackUser
10
- from lgt_jobs.lgt_data.mongo_repository import DedicatedBotRepository, UserMongoRepository
11
-
12
-
13
- class ConnectSourceJobData(BaseBackgroundJobData, BaseModel):
14
- slack_email: str
15
- sources_ids: List[str]
16
- action_user_email: str
17
- user_email: str
18
-
19
-
20
- class ConnectSourceJob(BaseBackgroundJob, ABC):
21
- @property
22
- def job_data_type(self) -> type:
23
- return ConnectSourceJobData
24
-
25
- def exec(self, data: ConnectSourceJobData):
26
- users_repository = UserMongoRepository()
27
- bots_repository = DedicatedBotRepository()
28
- action_user = users_repository.get_by_email(data.action_user_email)
29
- user = users_repository.get_by_email(data.user_email)
30
- if not action_user:
31
- log.info(f'Unable to find user with email: {data.action_user_email}')
32
- return
33
-
34
- slack_user: SlackUser = action_user.get_slack_user(data.slack_email)
35
- if not slack_user:
36
- log.info(f"You have no credentials for {data.slack_email}. Try to login to Slack.")
37
- bots = []
38
- for ws in slack_user.workspaces:
39
- if ws.id in data.sources_ids:
40
- active_bot = bots_repository.get_one(user_id=action_user.id, active_server_id=ws.id)
41
- bot = bots_repository.get_one(user_id=action_user.id, server_id=ws.id, include_deleted=True,
42
- user_name=data.slack_email)
43
- if active_bot:
44
- continue
45
- if not bot:
46
- bot = DedicatedBotModel()
47
- bot.servers = [Server()]
48
-
49
- bot.user_name = slack_user.email
50
- bot.slack_url = ws.url
51
- bot.user_id = action_user.id
52
- bot.created_by = user.email
53
- bot.registration_link = ws.url
54
- bot.token = ws.token
55
- bot.cookies = slack_user.cookies
56
- bot.deleted = False
57
- bot.paused = False
58
- bot.invalid_creds = False
59
- bot.banned = False
60
- bot.two_factor_required = ws.two_factor_required
61
- source = Source()
62
-
63
- for server in bot.servers:
64
- server.id = ws.id
65
- server.name = ws.domain
66
- server.deleted = False
67
- server.active = True
68
- server.icon = ws.icon
69
-
70
- source.source_id = ws.id
71
- source.source_name = ws.domain
72
- bot.type = source.source_type = SourceType.SLACK
73
- bot.icon = ws.icon
74
- bot.source = source
75
- bots_repository.add_or_update(bot)
76
- UserTrackAction.track(action_user.id, UserAction.START_SOURCE, ws.id)
77
- bot = bots_repository.get_one(user_id=action_user.id, server_id=ws.id, user_name=slack_user.email)
78
- bots.append(bot)
79
- BackgroundJobRunner.submit(BotStatsUpdateJob, BotStatsUpdateJobData(bot_id=str(bot.id)))
80
- slack_user.status = StatusConnection.COMPLETE
81
- users_repository.set(action_user.id, slack_users=[user.to_dic() for user in action_user.slack_users])
82
- return bots