leadguru-jobs 0.638.0__py3-none-any.whl → 0.640.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.
- {leadguru_jobs-0.638.0.dist-info → leadguru_jobs-0.640.0.dist-info}/METADATA +1 -1
- leadguru_jobs-0.640.0.dist-info/RECORD +109 -0
- lgt_jobs/jobs/bot_stats_update.py +2 -10
- lgt_jobs/jobs/chat_history.py +3 -6
- lgt_jobs/jobs/connect_sources.py +4 -1
- lgt_jobs/jobs/inbox_leads.py +6 -2
- lgt_jobs/jobs/load_slack_people.py +2 -1
- lgt_jobs/jobs/send_slack_message.py +1 -1
- lgt_jobs/jobs/update_slack_profile.py +2 -1
- lgt_jobs/jobs/workspace_connect.py +3 -1
- lgt_jobs/lgt_data/model.py +0 -1136
- lgt_jobs/lgt_data/models/base.py +29 -0
- lgt_jobs/lgt_data/models/boards/__init__.py +0 -0
- lgt_jobs/lgt_data/models/boards/board.py +39 -0
- lgt_jobs/lgt_data/models/boards/status.py +14 -0
- lgt_jobs/lgt_data/models/bots/__init__.py +0 -0
- lgt_jobs/lgt_data/models/bots/base_bot.py +44 -0
- lgt_jobs/lgt_data/models/bots/bot_info.py +33 -0
- lgt_jobs/lgt_data/models/bots/dedicated_bot.py +90 -0
- lgt_jobs/lgt_data/models/chat/__init__.py +0 -0
- lgt_jobs/lgt_data/models/chat/file.py +8 -0
- lgt_jobs/lgt_data/models/chat/grouped_messages.py +17 -0
- lgt_jobs/lgt_data/models/chat/message.py +85 -0
- lgt_jobs/lgt_data/models/{message_request.py → chat/request.py} +2 -1
- lgt_jobs/lgt_data/models/chat/scheduled_message.py +14 -0
- lgt_jobs/lgt_data/models/contacts/__init__.py +0 -0
- lgt_jobs/lgt_data/models/contacts/contact.py +22 -0
- lgt_jobs/lgt_data/models/external/__init__.py +0 -0
- lgt_jobs/lgt_data/models/external/cloud/__init__.py +0 -0
- lgt_jobs/lgt_data/models/external/cloud/file.py +18 -0
- lgt_jobs/lgt_data/models/external/discord/__init__.py +0 -0
- lgt_jobs/lgt_data/models/external/discord/user.py +45 -0
- lgt_jobs/lgt_data/models/external/slack/__init__.py +0 -0
- lgt_jobs/lgt_data/models/external/slack/timezone.py +8 -0
- lgt_jobs/lgt_data/models/external/slack/user.py +43 -0
- lgt_jobs/lgt_data/models/external/user_workspace.py +32 -0
- lgt_jobs/lgt_data/models/leads/__init__.py +0 -0
- lgt_jobs/lgt_data/models/leads/config.py +13 -0
- lgt_jobs/lgt_data/models/leads/extended_lead.py +46 -0
- lgt_jobs/lgt_data/models/leads/lead.py +48 -0
- lgt_jobs/lgt_data/models/leads/message.py +51 -0
- lgt_jobs/lgt_data/models/notifications/__init__.py +0 -0
- lgt_jobs/lgt_data/models/notifications/notification.py +248 -0
- lgt_jobs/lgt_data/models/notifications/notification_settings.py +52 -0
- lgt_jobs/lgt_data/models/people/__init__.py +0 -0
- lgt_jobs/lgt_data/models/people/people.py +75 -0
- lgt_jobs/lgt_data/models/people/profile.py +13 -0
- lgt_jobs/lgt_data/models/post/__init__.py +0 -0
- lgt_jobs/lgt_data/models/post/message.py +18 -0
- lgt_jobs/lgt_data/models/post/post.py +15 -0
- lgt_jobs/lgt_data/models/templates/__init__.py +0 -0
- lgt_jobs/lgt_data/models/templates/template.py +12 -0
- lgt_jobs/lgt_data/models/user/__init__.py +0 -0
- lgt_jobs/lgt_data/models/user/feature.py +10 -0
- lgt_jobs/lgt_data/models/user/general_settings.py +9 -0
- lgt_jobs/lgt_data/models/user/reset_password.py +7 -0
- lgt_jobs/lgt_data/models/user/subscription.py +22 -0
- lgt_jobs/lgt_data/models/user/user.py +95 -0
- lgt_jobs/lgt_data/models/user/user_follow_ups.py +20 -0
- lgt_jobs/lgt_data/models/user/user_page.py +19 -0
- lgt_jobs/lgt_data/models/user/verification.py +12 -0
- lgt_jobs/lgt_data/models/user_leads/__init__.py +0 -0
- lgt_jobs/lgt_data/models/user_leads/extended_user_lead.py +41 -0
- lgt_jobs/lgt_data/models/user_leads/user_lead.py +33 -0
- lgt_jobs/lgt_data/mongo_repository.py +225 -45
- lgt_jobs/lgt_data/repositories/__init__.py +0 -0
- lgt_jobs/lgt_data/repositories/post/__init__.py +0 -0
- lgt_jobs/lgt_data/repositories/post/posts.py +28 -0
- lgt_jobs/runner.py +2 -2
- lgt_jobs/simple_job.py +1 -1
- leadguru_jobs-0.638.0.dist-info/RECORD +0 -55
- lgt_jobs/lgt_common/lgt_logging.py +0 -15
- {leadguru_jobs-0.638.0.dist-info → leadguru_jobs-0.640.0.dist-info}/WHEEL +0 -0
- {leadguru_jobs-0.638.0.dist-info → leadguru_jobs-0.640.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,95 @@
|
|
1
|
+
import copy
|
2
|
+
from datetime import UTC, datetime
|
3
|
+
from typing import List, Optional
|
4
|
+
|
5
|
+
from bson import ObjectId
|
6
|
+
|
7
|
+
from lgt_jobs.lgt_data.enums import UserRole
|
8
|
+
from lgt_jobs.lgt_data.models.base import BaseModel
|
9
|
+
from lgt_jobs.lgt_data.models.external.discord.user import DiscordUser
|
10
|
+
from lgt_jobs.lgt_data.models.external.slack.user import SlackUser
|
11
|
+
from lgt_jobs.lgt_data.models.notifications.notification_settings import NotificationSettings
|
12
|
+
from lgt_jobs.lgt_data.models.people.profile import Profile
|
13
|
+
from lgt_jobs.lgt_data.models.user.general_settings import GeneralSettings
|
14
|
+
|
15
|
+
|
16
|
+
class UserModel(BaseModel):
|
17
|
+
def __init__(self):
|
18
|
+
super().__init__()
|
19
|
+
self.email: Optional[str] = None
|
20
|
+
self.password: Optional[str] = None
|
21
|
+
self.roles: List[str] = []
|
22
|
+
self.user_name: str = ''
|
23
|
+
self.company: str = ''
|
24
|
+
self.company_size: Optional[int] = None
|
25
|
+
self.company_industries: Optional[List[str]] = None
|
26
|
+
self.company_technologies: Optional[List[str]] = None
|
27
|
+
self.company_locations: Optional[List[str]] = None
|
28
|
+
self.company_web_site: str = ''
|
29
|
+
self.company_description: str = ''
|
30
|
+
self.position: str = ''
|
31
|
+
self.leads_limit: Optional[int] = None
|
32
|
+
self.leads_proceeded: Optional[int] = None
|
33
|
+
self.leads_filtered: Optional[int] = None
|
34
|
+
self.leads_limit_updated_at: Optional[int] = None
|
35
|
+
self.paid_lead_price: int = 1
|
36
|
+
self.state: int = 0
|
37
|
+
self.credits_exceeded_at: Optional[datetime] = None
|
38
|
+
self.unanswered_leads_period = None
|
39
|
+
self.inactive = None
|
40
|
+
self.slack_users: List[SlackUser] = []
|
41
|
+
self.discord_users: List[DiscordUser] = []
|
42
|
+
self.verified: bool = False
|
43
|
+
self.subscription_id: ObjectId | None = None
|
44
|
+
self.subscription_expired_at: datetime | None = None
|
45
|
+
self.balance: str | None = None
|
46
|
+
self.subscription_name: str | None = None
|
47
|
+
self.subscription_expiration_notified = False
|
48
|
+
self.subscription_expiration_warning_notified = False
|
49
|
+
self.notification_settings: NotificationSettings | None = None
|
50
|
+
self.general_settings: GeneralSettings | None = None
|
51
|
+
|
52
|
+
@classmethod
|
53
|
+
def from_dic(cls, dic: dict):
|
54
|
+
if not dic:
|
55
|
+
return None
|
56
|
+
|
57
|
+
model: UserModel = cls()
|
58
|
+
for k, v in dic.items():
|
59
|
+
setattr(model, k, v)
|
60
|
+
|
61
|
+
if '_id' in dic:
|
62
|
+
setattr(model, 'id', dic['_id'])
|
63
|
+
|
64
|
+
model.slack_profile = Profile.from_dic(dic.get('slack_profile'))
|
65
|
+
model.slack_users = [SlackUser.from_dic(user) for user in dic.get('slack_users', [])]
|
66
|
+
model.discord_users = [DiscordUser.from_dic(user) for user in dic.get('discord_users', [])]
|
67
|
+
model.notification_settings = NotificationSettings.from_dic(dic.get('notification_settings'))
|
68
|
+
model.general_settings = GeneralSettings.from_dic(dic.get('general_settings'))
|
69
|
+
return model
|
70
|
+
|
71
|
+
def to_dic(self):
|
72
|
+
result = copy.deepcopy(self.__dict__)
|
73
|
+
|
74
|
+
if result.get('slack_profile'):
|
75
|
+
result['slack_profile'] = result.get('slack_profile').__dict__
|
76
|
+
if result.get('notification_settings'):
|
77
|
+
result['notification_settings'] = NotificationSettings.to_dic(result.get('notification_settings'))
|
78
|
+
if result.get('general_settings'):
|
79
|
+
result['general_settings'] = GeneralSettings.to_dic(result.get('general_settings'))
|
80
|
+
|
81
|
+
return result
|
82
|
+
|
83
|
+
@property
|
84
|
+
def is_admin(self):
|
85
|
+
return UserRole.ADMIN in self.roles
|
86
|
+
|
87
|
+
@property
|
88
|
+
def subscription_expired(self):
|
89
|
+
return self.subscription_expired_at.replace(tzinfo=UTC) < datetime.now(UTC)
|
90
|
+
|
91
|
+
def get_slack_user(self, slack_email: str) -> SlackUser:
|
92
|
+
return next(filter(lambda x: slack_email == x.email, self.slack_users), None)
|
93
|
+
|
94
|
+
def get_discord_user(self, login: str) -> DiscordUser:
|
95
|
+
return next(filter(lambda x: login == x.login, self.discord_users), None)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
from lgt_jobs.lgt_data.models.base import DictionaryModel
|
2
|
+
from lgt_jobs.lgt_data.models.leads.extended_lead import ExtendedLeadModel
|
3
|
+
from lgt_jobs.lgt_data.models.notifications.notification_settings import NotificationSettings
|
4
|
+
|
5
|
+
|
6
|
+
class UserFollowUps(DictionaryModel):
|
7
|
+
actual_follow_ups: list[ExtendedLeadModel] = []
|
8
|
+
overdue_follow_ups: list[ExtendedLeadModel] = []
|
9
|
+
email: str | None = None
|
10
|
+
notification_settings: NotificationSettings | None = None
|
11
|
+
|
12
|
+
@classmethod
|
13
|
+
def from_dic(cls, dic: dict):
|
14
|
+
if not dic:
|
15
|
+
return None
|
16
|
+
model: UserFollowUps | None = super().from_dic(dic)
|
17
|
+
model.actual_follow_ups = [ExtendedLeadModel.from_dic(lead) for lead in dic.get('actual_follow_ups', [])]
|
18
|
+
model.overdue_follow_ups = [ExtendedLeadModel.from_dic(lead) for lead in dic.get('overdue_follow_ups', [])]
|
19
|
+
model.notification_settings = NotificationSettings.from_dic(dic.get('notification_settings'))
|
20
|
+
return model
|
@@ -0,0 +1,19 @@
|
|
1
|
+
from typing import List
|
2
|
+
|
3
|
+
from lgt_jobs.lgt_data.models.user.user import UserModel
|
4
|
+
|
5
|
+
|
6
|
+
class UsersPage:
|
7
|
+
users: List[UserModel]
|
8
|
+
count: int = 0
|
9
|
+
|
10
|
+
def __init__(self, users: List[UserModel], count: int):
|
11
|
+
self.users = users
|
12
|
+
self.count = count
|
13
|
+
|
14
|
+
@staticmethod
|
15
|
+
def from_dic(dic: dict):
|
16
|
+
users = [UserModel.from_dic(doc) for doc in dic.get('page', [])]
|
17
|
+
count = dic.get('count', 0)
|
18
|
+
return UsersPage(users=users, count=count)
|
19
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
from datetime import datetime, UTC
|
2
|
+
|
3
|
+
from lgt_jobs.lgt_data.models.base import DictionaryModel
|
4
|
+
|
5
|
+
|
6
|
+
class UserVerificationModel(DictionaryModel):
|
7
|
+
pass
|
8
|
+
|
9
|
+
def __init__(self):
|
10
|
+
super().__init__()
|
11
|
+
self.email = None
|
12
|
+
self.created_at = datetime.now(UTC)
|
File without changes
|
@@ -0,0 +1,41 @@
|
|
1
|
+
from typing import List
|
2
|
+
|
3
|
+
from lgt_jobs.lgt_data.models.bots.bot_info import BotInfo
|
4
|
+
from lgt_jobs.lgt_data.models.leads.lead import LeadModel
|
5
|
+
from lgt_jobs.lgt_data.models.people.people import SlackMemberInformation
|
6
|
+
from lgt_jobs.lgt_data.models.user_leads.user_lead import UserLeadModel
|
7
|
+
|
8
|
+
|
9
|
+
class ExtendedUserLeadModel(UserLeadModel):
|
10
|
+
pass
|
11
|
+
|
12
|
+
def __init__(self):
|
13
|
+
super().__init__()
|
14
|
+
self.contact: SlackMemberInformation | None = None
|
15
|
+
self.previous_publications = []
|
16
|
+
self.bots: List[BotInfo] = []
|
17
|
+
self.user_email: str | None = None
|
18
|
+
|
19
|
+
@classmethod
|
20
|
+
def from_dic(cls, dic: dict):
|
21
|
+
if not dic:
|
22
|
+
return None
|
23
|
+
|
24
|
+
result: ExtendedUserLeadModel | None = super().from_dic(dic)
|
25
|
+
if not result:
|
26
|
+
return None
|
27
|
+
|
28
|
+
result.contact = SlackMemberInformation.from_dic(dic.get('contact'))
|
29
|
+
result.previous_publications = [LeadModel.from_dic(lead) for lead in dic.get('previous_publications', [])]
|
30
|
+
return result
|
31
|
+
|
32
|
+
def to_dic(self):
|
33
|
+
result = super().to_dic()
|
34
|
+
result["contact"] = self.contact.to_dic()
|
35
|
+
return result
|
36
|
+
|
37
|
+
def to_csv(self, board_name: str) -> List[str]:
|
38
|
+
return [self.message.source, self.contact.real_name, self.contact.title, self.contact.email,
|
39
|
+
self.notes, board_name, self.status,
|
40
|
+
self.followup_date.strftime("%d.%m.%Y %H:%M") if self.followup_date else "",
|
41
|
+
self.message.message.replace('\n', ' ').strip()]
|
@@ -0,0 +1,33 @@
|
|
1
|
+
from datetime import datetime, UTC
|
2
|
+
|
3
|
+
from bson import ObjectId
|
4
|
+
|
5
|
+
from lgt_jobs.lgt_data.models.leads.lead import LeadModel
|
6
|
+
|
7
|
+
|
8
|
+
class UserLeadModel(LeadModel):
|
9
|
+
pass
|
10
|
+
|
11
|
+
def __init__(self):
|
12
|
+
super().__init__()
|
13
|
+
self.order: int = 0
|
14
|
+
self.followup_date: datetime | None = None
|
15
|
+
self.user_id: ObjectId | None = None
|
16
|
+
self.chat_viewed_at: datetime | None = None
|
17
|
+
self.board_id: ObjectId | None = None
|
18
|
+
|
19
|
+
@classmethod
|
20
|
+
def from_dic(cls, dic: dict):
|
21
|
+
if not dic:
|
22
|
+
return None
|
23
|
+
|
24
|
+
result: UserLeadModel | None = super().from_dic(dic)
|
25
|
+
if not result:
|
26
|
+
return None
|
27
|
+
|
28
|
+
if result.followup_date:
|
29
|
+
result.followup_date.replace(tzinfo=UTC)
|
30
|
+
|
31
|
+
result.chat_viewed_at = dic.get('chat_viewed_at')
|
32
|
+
return result
|
33
|
+
|
@@ -6,14 +6,30 @@ from dateutil import tz
|
|
6
6
|
from pymongo import MongoClient, UpdateOne
|
7
7
|
from bson.objectid import ObjectId
|
8
8
|
from lgt_jobs.lgt_data.enums import SourceType
|
9
|
-
from lgt_jobs.lgt_data.model import (LeadModel, BaseModel, UserModel, UserResetPasswordModel, BoardModel, BoardedStatus,
|
10
|
-
DedicatedBotModel, SlackMemberInformation, UserTemplateModel,
|
11
|
-
ExtendedUserLeadModel, UserLeadModel, ExtendedLeadModel, UserContact, ChatMessage,
|
12
|
-
GroupedMessagesModel, UserVerificationModel, UsersPage, Subscription,
|
13
|
-
ScheduledMessage)
|
14
9
|
from datetime import datetime, UTC, timedelta
|
15
10
|
from collections import OrderedDict
|
16
|
-
|
11
|
+
|
12
|
+
from lgt_jobs.lgt_data.models.base import BaseModel
|
13
|
+
from lgt_jobs.lgt_data.models.boards.board import BoardModel
|
14
|
+
from lgt_jobs.lgt_data.models.boards.status import BoardedStatus
|
15
|
+
from lgt_jobs.lgt_data.models.bots.dedicated_bot import DedicatedBotModel
|
16
|
+
from lgt_jobs.lgt_data.models.chat.grouped_messages import GroupedMessagesModel
|
17
|
+
from lgt_jobs.lgt_data.models.chat.message import ChatMessage
|
18
|
+
from lgt_jobs.lgt_data.models.chat.scheduled_message import ScheduledMessage
|
19
|
+
from lgt_jobs.lgt_data.models.chat.request import MessageRequest
|
20
|
+
from lgt_jobs.lgt_data.models.contacts.contact import UserContact
|
21
|
+
from lgt_jobs.lgt_data.models.leads.extended_lead import ExtendedLeadModel
|
22
|
+
from lgt_jobs.lgt_data.models.leads.lead import LeadModel
|
23
|
+
from lgt_jobs.lgt_data.models.people.people import SlackMemberInformation
|
24
|
+
from lgt_jobs.lgt_data.models.templates.template import UserTemplateModel
|
25
|
+
from lgt_jobs.lgt_data.models.user.reset_password import UserResetPasswordModel
|
26
|
+
from lgt_jobs.lgt_data.models.user.subscription import Subscription
|
27
|
+
from lgt_jobs.lgt_data.models.user.user import UserModel
|
28
|
+
from lgt_jobs.lgt_data.models.user.user_follow_ups import UserFollowUps
|
29
|
+
from lgt_jobs.lgt_data.models.user.user_page import UsersPage
|
30
|
+
from lgt_jobs.lgt_data.models.user.verification import UserVerificationModel
|
31
|
+
from lgt_jobs.lgt_data.models.user_leads.extended_user_lead import ExtendedUserLeadModel
|
32
|
+
from lgt_jobs.lgt_data.models.user_leads.user_lead import UserLeadModel
|
17
33
|
|
18
34
|
client = MongoClient(os.environ.get('MONGO_CONNECTION_STRING', 'mongodb://127.0.0.1:27017/'))
|
19
35
|
|
@@ -73,6 +89,10 @@ class UserMongoRepository(BaseMongoRepository):
|
|
73
89
|
connected_slack_email = kwargs.get('connected_slack_email')
|
74
90
|
soon_subscription_expiration = kwargs.get('soon_subscription_expiration')
|
75
91
|
has_new_message = kwargs.get('has_new_message')
|
92
|
+
has_new_message_request = kwargs.get('has_new_message_request')
|
93
|
+
has_deactivated_sources = kwargs.get('has_deactivated_sources')
|
94
|
+
has_new_replies = kwargs.get('has_new_replies')
|
95
|
+
has_new_reactions = kwargs.get('has_new_reactions')
|
76
96
|
min_days = kwargs.get('min_days_soon_subscription_expiration', 3)
|
77
97
|
|
78
98
|
if subscription_expired:
|
@@ -87,6 +107,22 @@ class UserMongoRepository(BaseMongoRepository):
|
|
87
107
|
pipeline['notification_settings.incoming_messages.enabled'] = True
|
88
108
|
pipeline['notification_settings.incoming_messages.need_to_notify'] = True
|
89
109
|
|
110
|
+
if has_new_message_request:
|
111
|
+
pipeline['notification_settings.inbox.enabled'] = True
|
112
|
+
pipeline['notification_settings.inbox.need_to_notify'] = True
|
113
|
+
|
114
|
+
if has_deactivated_sources:
|
115
|
+
pipeline['notification_settings.source_deactivation.enabled'] = True
|
116
|
+
pipeline['notification_settings.source_deactivation.need_to_notify'] = True
|
117
|
+
|
118
|
+
if has_new_replies:
|
119
|
+
pipeline['notification_settings.bulk_replies.enabled'] = True
|
120
|
+
pipeline['notification_settings.bulk_replies.need_to_notify'] = True
|
121
|
+
|
122
|
+
if has_new_reactions:
|
123
|
+
pipeline['notification_settings.bulk_reactions.enabled'] = True
|
124
|
+
pipeline['notification_settings.bulk_reactions.need_to_notify'] = True
|
125
|
+
|
90
126
|
if connected_slack_email:
|
91
127
|
pipeline['slack_users.email'] = connected_slack_email
|
92
128
|
|
@@ -106,7 +142,7 @@ class UserMongoRepository(BaseMongoRepository):
|
|
106
142
|
search = kwargs.get('search')
|
107
143
|
sort_field = kwargs.get('sort_field', 'email')
|
108
144
|
sort_direction = kwargs.get('sort_direction', 'ASCENDING')
|
109
|
-
sort_direction
|
145
|
+
sort_direction = pymongo.ASCENDING if sort_direction == 'ASCENDING' else pymongo.DESCENDING
|
110
146
|
if not include_inactive:
|
111
147
|
match_pipeline['inactive'] = False
|
112
148
|
if email:
|
@@ -176,6 +212,81 @@ class UserLeadMongoRepository(BaseMongoRepository):
|
|
176
212
|
collection_name = 'user_leads'
|
177
213
|
model = ExtendedUserLeadModel
|
178
214
|
|
215
|
+
def get_leads_with_follow_ups(self):
|
216
|
+
now = datetime.now(UTC)
|
217
|
+
this_day = datetime(now.year, now.month, now.day, 21, 00, 00, tzinfo=UTC)
|
218
|
+
after_week = this_day + timedelta(7)
|
219
|
+
pipeline = [
|
220
|
+
{'$match': {'archived': False, 'followup_date': {'$ne': None}}},
|
221
|
+
{
|
222
|
+
'$lookup': {
|
223
|
+
'from': 'users',
|
224
|
+
'localField': 'user_id',
|
225
|
+
'foreignField': '_id',
|
226
|
+
'as': 'user'
|
227
|
+
}
|
228
|
+
},
|
229
|
+
{
|
230
|
+
'$lookup': {
|
231
|
+
'from': 'slack_contact',
|
232
|
+
'localField': 'message.sender_id',
|
233
|
+
'foreignField': 'sender_id',
|
234
|
+
'as': 'contact'
|
235
|
+
}
|
236
|
+
},
|
237
|
+
{'$addFields': {'contact': {'$first': '$contact'}, 'user': {'$first': '$user'}}},
|
238
|
+
{
|
239
|
+
'$project': {
|
240
|
+
'user_id': 1,
|
241
|
+
'user_email': '$user.email',
|
242
|
+
'notification_settings': '$user.notification_settings',
|
243
|
+
'followup_to': {
|
244
|
+
'$cond': {
|
245
|
+
'if': {'$eq': ['$user.notification_settings.follow_ups.type', 'once_a_day']},
|
246
|
+
'then': this_day,
|
247
|
+
'else': after_week
|
248
|
+
}
|
249
|
+
},
|
250
|
+
'followup_date': 1,
|
251
|
+
'contact': 1,
|
252
|
+
'message.sender_id': 1,
|
253
|
+
'message.source': 1
|
254
|
+
}
|
255
|
+
},
|
256
|
+
{'$group': {'_id': '$user_id', 'leads': {'$push': '$$ROOT'}}},
|
257
|
+
{
|
258
|
+
'$addFields': {
|
259
|
+
'actual_follow_ups': {
|
260
|
+
'$filter': {
|
261
|
+
'input': '$leads',
|
262
|
+
'as': 'lead',
|
263
|
+
'cond': {
|
264
|
+
'$and': [
|
265
|
+
{'$gte': ['$$lead.followup_date', now]},
|
266
|
+
{'$lte': ['$$lead.followup_date', '$$lead.followup_to']}
|
267
|
+
]
|
268
|
+
}
|
269
|
+
}
|
270
|
+
},
|
271
|
+
'overdue_follow_ups': {
|
272
|
+
'$filter': {
|
273
|
+
'input': '$leads',
|
274
|
+
'as': 'lead',
|
275
|
+
'cond': {'$lt': ['$$lead.followup_date', now]}
|
276
|
+
}
|
277
|
+
}
|
278
|
+
}
|
279
|
+
},
|
280
|
+
{
|
281
|
+
'$addFields': {
|
282
|
+
'email': {'$first': '$leads.user_email'},
|
283
|
+
'notification_settings': {'$first': '$leads.notification_settings'}}
|
284
|
+
},
|
285
|
+
{'$match': {'actual_follow_ups': {'$ne': []}}},
|
286
|
+
{'$unset': ['leads']}
|
287
|
+
]
|
288
|
+
return [UserFollowUps.from_dic(doc) for doc in list(self.collection().aggregate(pipeline))]
|
289
|
+
|
179
290
|
def update_source(self, source_id: str, source_data: dict):
|
180
291
|
self.collection().update_many({'message.source.source_id': source_id},
|
181
292
|
{'$set': {'message.source': source_data}})
|
@@ -222,22 +333,22 @@ class UserLeadMongoRepository(BaseMongoRepository):
|
|
222
333
|
archived = kwargs.get('archived')
|
223
334
|
from_date = kwargs.get('from_date')
|
224
335
|
to_date = kwargs.get('to_date')
|
225
|
-
has_followup = kwargs.get('has_followup'
|
226
|
-
followup_to = kwargs.get('followup_to_date'
|
227
|
-
followup_from = kwargs.get('followup_from_date'
|
228
|
-
created_to = kwargs.get('created_to_date'
|
229
|
-
created_from = kwargs.get('created_from_date'
|
230
|
-
sender_ids = kwargs.get('sender_ids'
|
231
|
-
text = kwargs.get('text'
|
232
|
-
stop_words = kwargs.get('stop_words'
|
233
|
-
tags = kwargs.get('tags'
|
234
|
-
configs = kwargs.get('config'
|
235
|
-
bots_names = kwargs.get('bots_names'
|
236
|
-
locations = kwargs.get('locations'
|
237
|
-
with_chat = kwargs.get('with_chat'
|
238
|
-
leads_ids = kwargs.get('leads_ids'
|
239
|
-
exclude_leads = kwargs.get('exclude_leads'
|
240
|
-
exclude_senders = kwargs.get('exclude_senders'
|
336
|
+
has_followup = kwargs.get('has_followup')
|
337
|
+
followup_to = kwargs.get('followup_to_date')
|
338
|
+
followup_from = kwargs.get('followup_from_date')
|
339
|
+
created_to = kwargs.get('created_to_date')
|
340
|
+
created_from = kwargs.get('created_from_date')
|
341
|
+
sender_ids = kwargs.get('sender_ids')
|
342
|
+
text = kwargs.get('text')
|
343
|
+
stop_words = kwargs.get('stop_words')
|
344
|
+
tags = kwargs.get('tags')
|
345
|
+
configs = kwargs.get('config')
|
346
|
+
bots_names = kwargs.get('bots_names')
|
347
|
+
locations = kwargs.get('locations')
|
348
|
+
with_chat = kwargs.get('with_chat')
|
349
|
+
leads_ids = kwargs.get('leads_ids')
|
350
|
+
exclude_leads = kwargs.get('exclude_leads')
|
351
|
+
exclude_senders = kwargs.get('exclude_senders')
|
241
352
|
deleted = kwargs.get('deleted', False)
|
242
353
|
|
243
354
|
pipeline['message.profile.display_name'] = {
|
@@ -549,18 +660,17 @@ class LeadMongoRepository(BaseMongoRepository):
|
|
549
660
|
from_date: datetime = kwargs.get('from_date')
|
550
661
|
to_date: datetime = kwargs.get('to_date')
|
551
662
|
|
552
|
-
country = kwargs.get('country'
|
553
|
-
user_id = kwargs.get('user_id'
|
554
|
-
tags = kwargs.get('tags'
|
555
|
-
text = kwargs.get('text'
|
556
|
-
stop_words = kwargs.get('stop_words'
|
557
|
-
exclude_leads = kwargs.get('exclude_leads'
|
558
|
-
exclude_senders = kwargs.get('exclude_senders'
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
locations = kwargs.get('locations', None)
|
663
|
+
country = kwargs.get('country')
|
664
|
+
user_id = kwargs.get('user_id')
|
665
|
+
tags = kwargs.get('tags')
|
666
|
+
text = kwargs.get('text')
|
667
|
+
stop_words = kwargs.get('stop_words')
|
668
|
+
exclude_leads = kwargs.get('exclude_leads')
|
669
|
+
exclude_senders = kwargs.get('exclude_senders')
|
670
|
+
sender_ids = kwargs.get('sender_ids')
|
671
|
+
configs = kwargs.get('config')
|
672
|
+
bots_names = kwargs.get('bots_names')
|
673
|
+
locations = kwargs.get('locations')
|
564
674
|
publication_text = kwargs.get('publication_text')
|
565
675
|
|
566
676
|
pipeline['message.profile.display_name'] = {
|
@@ -610,13 +720,6 @@ class LeadMongoRepository(BaseMongoRepository):
|
|
610
720
|
if exclude_senders:
|
611
721
|
pipeline['message.sender_id'] = {'$nin': exclude_senders}
|
612
722
|
|
613
|
-
if excluded_channels:
|
614
|
-
pipeline['$and'] = []
|
615
|
-
for ws, channels in excluded_channels.items():
|
616
|
-
if channels is not None:
|
617
|
-
pipeline['$and'].append(
|
618
|
-
{'$or': [{'message.name': {'$ne': ws}}, {'message.channel_id': {'$nin': channels}}]})
|
619
|
-
|
620
723
|
if sender_ids:
|
621
724
|
pipeline['message.sender_id'] = {'$in': sender_ids}
|
622
725
|
|
@@ -848,6 +951,9 @@ class DedicatedBotRepository(BaseMongoRepository):
|
|
848
951
|
kwargs["only_valid"] = only_valid
|
849
952
|
pipeline = self.__create_bots_filter(**kwargs)
|
850
953
|
docs = self.collection().find(pipeline)
|
954
|
+
sort_by = kwargs.get('sort_by')
|
955
|
+
if sort_by:
|
956
|
+
docs = docs.sort({sort_by: 1})
|
851
957
|
return [DedicatedBotModel.from_dic(doc) for doc in docs]
|
852
958
|
|
853
959
|
def get_source_ids_for_user(self, **kwargs):
|
@@ -864,7 +970,7 @@ class DedicatedBotRepository(BaseMongoRepository):
|
|
864
970
|
|
865
971
|
@staticmethod
|
866
972
|
def __create_bots_filter(**kwargs):
|
867
|
-
pipeline = {}
|
973
|
+
pipeline: dict = {}
|
868
974
|
name = kwargs.get('name')
|
869
975
|
source_type = kwargs.get('source_type', None)
|
870
976
|
user_name = kwargs.get('user_name')
|
@@ -876,6 +982,8 @@ class DedicatedBotRepository(BaseMongoRepository):
|
|
876
982
|
source_id = kwargs.get('source_id')
|
877
983
|
server_id = kwargs.get('server_id')
|
878
984
|
active_server_id = kwargs.get('active_server_id')
|
985
|
+
invalid_creds = kwargs.get('invalid_creds')
|
986
|
+
sort_by = kwargs.get('sort_by')
|
879
987
|
|
880
988
|
if bot_id:
|
881
989
|
pipeline["_id"] = to_object_id(bot_id)
|
@@ -904,12 +1012,18 @@ class DedicatedBotRepository(BaseMongoRepository):
|
|
904
1012
|
if only_valid:
|
905
1013
|
pipeline['invalid_creds'] = False
|
906
1014
|
|
1015
|
+
if invalid_creds is not None:
|
1016
|
+
pipeline['invalid_creds'] = invalid_creds
|
1017
|
+
|
907
1018
|
if not include_deleted:
|
908
1019
|
pipeline['deleted'] = False
|
909
1020
|
|
910
1021
|
if not include_paused and source_type == SourceType.DISCORD:
|
911
1022
|
pipeline['paused'] = False
|
912
1023
|
|
1024
|
+
if sort_by:
|
1025
|
+
pipeline['sort_by'] = {'$exists': True}
|
1026
|
+
|
913
1027
|
return pipeline
|
914
1028
|
|
915
1029
|
|
@@ -1144,15 +1258,59 @@ class ChatRepository(BaseMongoRepository):
|
|
1144
1258
|
|
1145
1259
|
if from_date:
|
1146
1260
|
start = datetime(from_date.year, from_date.month, from_date.day, tzinfo=tz.tzutc())
|
1147
|
-
pipeline['
|
1261
|
+
pipeline['created_at']['$gte'] = start
|
1148
1262
|
|
1149
1263
|
if to_date:
|
1150
1264
|
end = datetime(to_date.year, to_date.month, to_date.day, 23, 59, 59, tzinfo=tz.tzutc())
|
1151
|
-
pipeline['
|
1265
|
+
pipeline['created_at']['$lte'] = end
|
1152
1266
|
|
1153
1267
|
return [ChatMessage.from_dic(msg)
|
1154
1268
|
for msg in self.collection().find(pipeline).sort("id", pymongo.ASCENDING)]
|
1155
1269
|
|
1270
|
+
def get_aggregated_list(self, **kwargs):
|
1271
|
+
match_pipeline = {}
|
1272
|
+
user_id = kwargs.get('user_id')
|
1273
|
+
from_date = kwargs.get('from_date')
|
1274
|
+
to_date = kwargs.get('to_date')
|
1275
|
+
sort_by = kwargs.get('sort_by', 'id')
|
1276
|
+
viewed = kwargs.get('viewed')
|
1277
|
+
|
1278
|
+
if user_id:
|
1279
|
+
match_pipeline['user_id'] = to_object_id(user_id)
|
1280
|
+
|
1281
|
+
if from_date or to_date:
|
1282
|
+
match_pipeline['created_at'] = {}
|
1283
|
+
|
1284
|
+
if viewed is not None:
|
1285
|
+
match_pipeline['viewed'] = viewed
|
1286
|
+
|
1287
|
+
if from_date:
|
1288
|
+
start = datetime(from_date.year, from_date.month, from_date.day, tzinfo=tz.tzutc())
|
1289
|
+
match_pipeline['created_at']['$gte'] = start
|
1290
|
+
|
1291
|
+
if to_date:
|
1292
|
+
end = datetime(to_date.year, to_date.month, to_date.day, 23, 59, 59, tzinfo=tz.tzutc())
|
1293
|
+
match_pipeline['created_at']['$lte'] = end
|
1294
|
+
|
1295
|
+
pipeline = [
|
1296
|
+
{'$match': match_pipeline},
|
1297
|
+
{
|
1298
|
+
'$lookup': {
|
1299
|
+
'from': 'slack_contact',
|
1300
|
+
'localField': 'sender_id',
|
1301
|
+
'foreignField': 'sender_id',
|
1302
|
+
'as': 'user'
|
1303
|
+
}
|
1304
|
+
},
|
1305
|
+
{
|
1306
|
+
'$addFields': {'user': {'$first': '$user'}}
|
1307
|
+
},
|
1308
|
+
{
|
1309
|
+
'$sort': {sort_by: 1}
|
1310
|
+
}]
|
1311
|
+
|
1312
|
+
return self.collection().aggregate(pipeline)
|
1313
|
+
|
1156
1314
|
def get_grouped_messages(self, **kwargs):
|
1157
1315
|
match_pipeline = {}
|
1158
1316
|
pipeline = [
|
@@ -1202,6 +1360,28 @@ class MessageRequestsRepository(BaseMongoRepository):
|
|
1202
1360
|
self.collection().update_one({'user_id': to_object_id(user_id), 'sender_id': sender_id},
|
1203
1361
|
{'$set': message_request.to_dic()}, upsert=True)
|
1204
1362
|
|
1363
|
+
def get_many(self, user_id: str, viewed: bool = False):
|
1364
|
+
pipeline = [
|
1365
|
+
{
|
1366
|
+
'$match': {'user_id': to_object_id(user_id), 'viewed': viewed}
|
1367
|
+
},
|
1368
|
+
{
|
1369
|
+
'$lookup': {
|
1370
|
+
'from': 'slack_contact',
|
1371
|
+
'localField': 'sender_id',
|
1372
|
+
'foreignField': 'sender_id',
|
1373
|
+
'as': 'user'
|
1374
|
+
}
|
1375
|
+
},
|
1376
|
+
{
|
1377
|
+
'$addFields': {'user': {'$first': '$user'}}
|
1378
|
+
},
|
1379
|
+
{
|
1380
|
+
'$sort': {'created_at': 1}
|
1381
|
+
}
|
1382
|
+
]
|
1383
|
+
return self.collection().aggregate(pipeline)
|
1384
|
+
|
1205
1385
|
def find(self, user_id: str, sender_id: str):
|
1206
1386
|
return self.collection().find_one({'user_id': to_object_id(user_id), 'sender_id': sender_id})
|
1207
1387
|
|
File without changes
|
File without changes
|
@@ -0,0 +1,28 @@
|
|
1
|
+
from bson import ObjectId
|
2
|
+
|
3
|
+
from lgt_jobs.lgt_data.models.post.post import Post
|
4
|
+
from lgt_jobs.lgt_data.mongo_repository import BaseMongoRepository
|
5
|
+
|
6
|
+
|
7
|
+
class PostsRepository(BaseMongoRepository):
|
8
|
+
collection_name = 'posts'
|
9
|
+
|
10
|
+
def get_users_posts(self, ids: list[str]) -> dict[ObjectId, list[Post]]:
|
11
|
+
pipeline = [
|
12
|
+
{
|
13
|
+
'$lookup': {
|
14
|
+
'from': 'posted_messages',
|
15
|
+
'as': 'messages',
|
16
|
+
'let': {'id': '$_id'},
|
17
|
+
'pipeline': [
|
18
|
+
{'$match': {'$expr': {'$and': [{'$in': ['$id', ids]}, {'$eq': ['$$id', '$post_id']}]}}}
|
19
|
+
]}},
|
20
|
+
{
|
21
|
+
'$match': {'messages': {'$ne': []}}
|
22
|
+
},
|
23
|
+
{
|
24
|
+
'$group': {'_id': '$user_id', 'posts': {'$push': '$$ROOT'}}
|
25
|
+
}]
|
26
|
+
docs = self.collection().aggregate(pipeline)
|
27
|
+
posts_map = {doc['_id']: [Post.from_dic(post) for post in doc['posts']] for doc in docs}
|
28
|
+
return posts_map
|
lgt_jobs/runner.py
CHANGED
@@ -2,8 +2,8 @@ import json
|
|
2
2
|
from datetime import datetime, UTC
|
3
3
|
from lgt_jobs.lgt_common.pubsub.messages import publish_message2_pubsub
|
4
4
|
from lgt_jobs.lgt_data.engine import DelayedJob
|
5
|
-
from .basejobs import InvalidJobTypeException, BaseBackgroundJobData, BaseBackgroundJob
|
6
|
-
from .env import background_jobs_topic
|
5
|
+
from lgt_jobs.basejobs import InvalidJobTypeException, BaseBackgroundJobData, BaseBackgroundJob
|
6
|
+
from lgt_jobs.env import background_jobs_topic
|
7
7
|
|
8
8
|
|
9
9
|
def datetime_converter(o):
|
lgt_jobs/simple_job.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
from abc import ABC
|
2
2
|
from typing import Optional
|
3
3
|
from pydantic import BaseModel
|
4
|
-
from .basejobs import BaseBackgroundJobData, BaseBackgroundJob
|
4
|
+
from lgt_jobs.basejobs import BaseBackgroundJobData, BaseBackgroundJob
|
5
5
|
|
6
6
|
|
7
7
|
class SimpleTestJobData(BaseBackgroundJobData, BaseModel):
|