-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreminderManagement.py
613 lines (517 loc) · 33.9 KB
/
reminderManagement.py
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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
from enum import Enum
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, ReplyKeyboardMarkup
from chain.dfuse import DfuseConnection, ResponseSuccessful
from constants import dfuse_api_key, time_span_for_notification, \
alert_message_time_election_is_coming, eden_portal_url, telegram_admins_id, ReminderGroup, \
time_span_for_notification_time_is_up, alert_message_time_round_end_is_coming, eden_portal_url_action, \
telegram_bot_name
from constants.rawActionWeb import RawActionWeb
from database import Election, Database, ExtendedParticipant, ExtendedRoom
from database.room import Room
from groupManagement import RoomArray
from log import Log
from datetime import datetime, timedelta
from chain.eden import EdenData, Response, ResponseError
from database.participant import Participant
from database.reminder import Reminder, ReminderSent, ReminderSendStatus
from datetime import datetime
from debugMode.modeDemo import ModeDemo
from dateTimeManagement import DateTimeManagement
from text.textManagement import GroupCommunicationTextManagement
from transmission import SessionType, Communication
import gettext
from transmissionCustom import ADD_AT_SIGN_IF_NOT_EXISTS
_ = gettext.gettext
__ = gettext.ngettext
class ReminderManagementException(Exception):
pass
LOG = Log(className="RemindersManagement")
class ReminderManagement:
def __init__(self, election: Election, database: Database, edenData: EdenData, communication: Communication, modeDemo: ModeDemo = None):
assert isinstance(election, Election), "election is not instance of Election"
assert isinstance(database, Database), "database is not instance of Database"
assert isinstance(edenData, EdenData), "edenData is not instance of EdenData"
assert isinstance(communication, Communication), "communication is not instance of Communication"
assert isinstance(modeDemo, (ModeDemo, type(None))), "modeDemo is not instance of ModeDemo or None"
self.database: Database = database
self.edenData = edenData
self.communication = communication
self.dateTimeManagement = DateTimeManagement(edenData=edenData)
self.participants = []
self.datetime = self.setExecutionTime(modeDemo=modeDemo)
# basic workflow
self.election: Election = election
# if self.database.electionGroupsCreated(election= self.election, round= 999) #TODO: check in the future
# self.createRemindersIfNotExists(election=self.election)
def createRemindersTimeIsUpIfNotExists(self, election: Election, round: int, roundEnd: datetime):
"""Create round end reminders if not exists"""
try:
LOG.info("Create reminders (time is up) in election if not exists")
session = self.database.createCsesion(expireOnCommit=False)
for item in alert_message_time_round_end_is_coming:
if len(item) != 3:
raise ReminderManagementException("alert_message_time_round_end_is_coming is not in correct size")
if isinstance(item[0], int) is False:
LOG.exception("alert_message_time_round_end_is_coming tuple[0]: "
"element is not int")
raise ReminderManagementException("alert_message_time_round_end_is_coming tuple[0]: "
"element is not int")
if isinstance(item[1], Enum) is False:
LOG.exception("alert_message_time_round_end_is_coming tuple[1]: "
"element is not ReminderGroup")
raise ReminderManagementException("alert_message_time_round_end_is_coming tuple[1]: "
"element is not ReminderGroup")
if isinstance(item[2], str) is False:
LOG.exception("alert_message_time_round_end_is_coming tuple[2]: "
"element is not str")
raise ReminderManagementException("alert_message_time_round_end_is_coming tuple[2]: "
"element is not str")
reminder = Reminder(electionID=election.electionID,
round=round,
reminderGroup=item[1],
dateTimeBefore=roundEnd - timedelta(minutes=item[0]))
self.database.createReminder(reminder=reminder, csession=session)
self.database.removeCcession(session=session)
LOG.debug("Reminders created")
except Exception as e:
self.database.rollbackCcession(session=session)
self.database.removeCcession(session=session)
LOG.exception("Exception thrown when called createRemindersIFNotExists; Description: " + str(e))
def setExecutionTime(self, modeDemo: ModeDemo = None) -> datetime:
"""Set execution time; if modeDemo is defined then use datetime from modeDemo.blockHeight
otherwise
use time of the node as main time of server"""
if modeDemo is None:
# in live mode time of blockchain is also time of server
blockchainTime: datetime = self.dateTimeManagement.getTime()
return blockchainTime
else:
# in demo mode time of block is also time of server
blockchainTime: datetime = modeDemo.getCurrentBlockTimestamp()
return blockchainTime
def sendReminderTimeIsUpIfNeeded(self, election: Election, roundEnd: datetime, modeDemo: ModeDemo = None):
"""Send reminder if time is up"""
try:
LOG.info("Send reminder if time is up")
self.communication.updateKnownUserData(botName=telegram_bot_name)
executionTime: datetime = self.setExecutionTime(modeDemo=modeDemo)
reminders: list = self.database.getReminders(election=election, reminderGroup1=ReminderGroup.IN_ELECTION)
if reminders is not None:
for reminder in reminders:
reminderRound: int = reminder.round
LOG.info("Reminder (time is up): " + str(reminder))
LOG.debug("Reminder (time is up) time: " + str(reminder.dateTimeBefore) +
"; Execution time: " + str(executionTime) +
"; Reminder time span: " + str(reminder.dateTimeBefore + timedelta(
minutes=time_span_for_notification_time_is_up)) +
" ..."
)
if reminder.dateTimeBefore <= executionTime <= reminder.dateTimeBefore + timedelta(
minutes=time_span_for_notification_time_is_up):
LOG.info("... send reminder to election id: " + str(reminder.electionID) +
" and dateTimeBefore: " + str(reminder.dateTimeBefore) +
" and round: " + str(reminder.round))
# get text of reminder
minutesToElectionInMinutes = (roundEnd - executionTime).total_seconds() / 60
closestReminder: tuple[int, ReminderGroup, str] = self.theNearestDateTime(
alert_message_time_round_end_is_coming,
minutesToElectionInMinutes)
roomsAndParticipants: list[list(Room, Participant)] = self.getMembersFromDatabaseInElection(
election=election,
reminder=reminder)
if roomsAndParticipants is None or len(roomsAndParticipants) == 0:
LOG.warning("All participant got reminder - do nothing")
return
votes: Response = self.edenData.getVotes(
height=modeDemo.currentBlockHeight if modeDemo is not None else None)
if isinstance(votes, ResponseError):
LOG.error("Error when called getVotes: " + votes.error)
raise ReminderManagementException("Error when called getVotes: " + votes.error)
if len(roomsAndParticipants) == 0:
LOG.critical("No rooms and participants")
return
# extendedRoom = ExtendedRoom.fromRoom(room= )
roomArray: RoomArray = RoomArray()
currentRoom: ExtendedRoom = None
self.communication.updateKnownUserData(botName=telegram_bot_name)
for room, participant in roomsAndParticipants:
LOG.debug("Group: " + str(room) + "; Participant: " + str(participant))
# only first time
if currentRoom is None:
currentRoom = ExtendedRoom.fromRoom(room=room)
roomArray.setRoom(room=currentRoom)
# if current room is not the same as previous, add it to the array
if currentRoom.roomID != room.roomID:
currentRoom = ExtendedRoom.fromRoom(room=room)
roomArray.setRoom(room=currentRoom)
# create extended participant - because of 'votefor' variable
extendedParticipant: ExtendedParticipant = \
ExtendedParticipant.fromParticipant(participant=participant,
index=0 # index does not matter here
)
# send to participant
# check if participant has voted
candidate = [y['candidate'] for x, y in votes.data.items() if
x == extendedParticipant.accountName and y is not None]
# set vote
extendedParticipant.voteFor = candidate[0] if len(candidate) > 0 else None
# add participant to current room
currentRoom.addMember(member=extendedParticipant)
self.sendAndSyncWithDatabaseRoundIsAlmostFinish(member=extendedParticipant,
reminder=reminder,
modeDemo=modeDemo,
election=election,
closestReminderConst=closestReminder
)
# send message to the group
self.sendToTheGroupTimeIsUp(reminderRound=reminderRound,
election=election,
closestReminderConst=closestReminder,
roomArray=roomArray,
modeDemo=modeDemo)
except Exception as e:
LOG.exception("Exception thrown when called sendReminderTimeIsUpIfNeeded; Description: " + str(e))
def sendReminderIfNeeded(self, election: Election, modeDemo: ModeDemo = None):
"""Send reminder if needed"""
try:
LOG.info("Send reminders if needed")
executionTime: datetime = self.setExecutionTime(modeDemo=modeDemo)
LOG.debug("Working time: " + str(executionTime))
reminders: list[Reminder] = self.database.getReminders(election=election,
reminderGroup1=ReminderGroup.ATTENDED,
reminderGroup2=ReminderGroup.NOT_ATTENDED)
remindersBoth: list[Reminder] = self.database.getReminders(election=election,
reminderGroup1=ReminderGroup.BOTH)
if reminders is None and remindersBoth is not None:
reminders = remindersBoth
elif reminders is not None and remindersBoth is None:
# do nothing
Log.info("reminders is not None and remindersBoth is None")
elif reminders is not None and remindersBoth is not None:
reminders = reminders + remindersBoth
if reminders is not None:
for item in reminders:
if isinstance(item, Reminder):
reminder: Reminder = item
LOG.info("Reminder: " + str(reminder))
LOG.debug("Reminder time: " + str(reminder.dateTimeBefore) +
"; Execution time: " + str(executionTime) +
"; Reminder time span: " + str(reminder.dateTimeBefore + timedelta(
minutes=time_span_for_notification)) +
" ..."
)
if reminder.dateTimeBefore <= executionTime <= reminder.dateTimeBefore + timedelta(
minutes=time_span_for_notification):
LOG.info("... send reminder to election id: " + str(reminder.electionID) +
" and dateTimeBefore: " + str(reminder.dateTimeBefore))
dummyElection: Election = self.database.getDummyElection(election=election)
if dummyElection is None:
LOG.error("HUGE PROBLEM: Dummy election is not found. Reminders will not be sent")
return
members: list[(Room, Participant)] = self.getMembersFromDatabase(election=dummyElection)
reminderSentList: list[ReminderSent] = self.database.getAllParticipantsReminderSentRecord(
reminder=reminder)
self.communication.updateKnownUserData(botName=telegram_bot_name)
for room, member in members:
if member.telegramID is None or len(member.telegramID) < 3:
LOG.debug("Member " + str(member) + " has no known telegramID, skip sending")
continue
isSent: bool = self.sendAndSyncWithDatabaseElectionIsComing(member=member,
election=election,
reminder=reminder,
reminderSentList=reminderSentList)
if isSent:
LOG.info("Reminder (for user: " + member.accountName + " sent to telegramID: "
+ member.telegramID)
else:
LOG.debug("... reminder is not needed!")
else:
LOG.error("Reminders are not set in the database. Something went wrong.")
except Exception as e:
LOG.exception("Exception thrown when called sendReminderIfNeeded; Description: " + str(e))
def getMembersFromChain(self, height: int = None):
"""Get participants from chain"""
try:
LOG.info("Get members from chain")
response: Response = self.edenData.getMembers(height=height)
if isinstance(response, ResponseError):
raise Exception("Response from chain is not instance of Response; Description: " + str(response))
else:
return response.data
except Exception as e:
LOG.exception(str(e))
raise ReminderManagementException \
("Exception thrown when called getMembersFromChain; Description: " + str(e))
def getMembersFromDatabase(self, election: Election):
"""Get participants from database"""
try:
LOG.info("Get members from database")
roomsAndParticipants = self.database.getMembers(election=election)
if roomsAndParticipants is not None:
return roomsAndParticipants
else:
raise Exception("Participants are not set in the database. Something went wrong.")
return None
except Exception as e:
LOG.exception(str(e))
raise ReminderManagementException(
"Exception thrown when called getMembersFromDatabase; Description: " + str(e))
def getMembersFromDatabaseInElection(self, election: Election, reminder: Reminder):
"""Get participants from database in election process"""
"""Returns list of rooms[0] and participants[1]"""
try:
assert isinstance(election, Election), "election is not instance of Election"
assert isinstance(reminder, Reminder), "reminder is not instance of Reminder"
# round is in the reminder object
LOG.info("Get participants from database in election process")
groupsAndParticipants = self.database.getMembersInElectionRoundNotYetSend(election=election,
reminder=reminder)
return groupsAndParticipants
except Exception as e:
LOG.exception(str(e))
raise ReminderManagementException(
"Exception thrown when called getMembersFromDatabase; Description: " + str(e))
def theNearestDateTime(self, alerts: list[[int, ReminderGroup, str]], minutes: int) -> tuple[
int, ReminderGroup, str]:
"""Get the nearest date time"""
try:
#LOG.info("Get nearest date time")
nearest = min(alerts, key=lambda x: abs(x[0] - minutes))
return nearest
except Exception as e:
LOG.exception(str(e))
raise ReminderManagementException("Exception thrown when called nearestDateTime; Description: " + str(e))
def getTextForUpcomingElection(self, member: Participant, electionDateTime: datetime, reminder: Reminder,
currentTime: datetime) -> str:
try:
LOG.info("Getting text for election: " + str(electionDateTime))
assert isinstance(electionDateTime, datetime), "electionDateTime is not instance of datetime"
assert isinstance(currentTime, datetime), "currentTime is not instance of datetime"
assert isinstance(reminder, Reminder), "reminder is not instance of Reminder"
assert isinstance(member, Participant), "member is not instance of Participant"
# get timedifference in text format from constants
minutesToElectionInMinutes = (electionDateTime - currentTime).total_seconds() / 60
nearestDatetimeToElectionInMinutes: tuple[int, ReminderGroup, str] = \
self.theNearestDateTime(alert_message_time_election_is_coming, minutesToElectionInMinutes)
nearestDateTimeText = nearestDatetimeToElectionInMinutes[2]
#LOG.debug("Nearest datetime to election: " + str(nearestDatetimeToElectionInMinutes) +
# " minutes with text '" + nearestDateTimeText + "'")
if member.participationStatus and \
(nearestDatetimeToElectionInMinutes[1] == ReminderGroup.BOTH or
nearestDatetimeToElectionInMinutes[1] == ReminderGroup.ATTENDED):
LOG.debug("Member (" + str(member) + ") is going to participate and reminder is for 'attended members'")
return _("Hey! \n"
"I am here to remind you that Eden election is starting %s.") % \
(nearestDateTimeText)
elif member.participationStatus is False and \
(nearestDatetimeToElectionInMinutes[1] is ReminderGroup.BOTH or \
nearestDatetimeToElectionInMinutes[1] is ReminderGroup.NOT_ATTENDED):
LOG.debug("Member (" + str(member) + ") is not going to participate and reminder "
"is for 'not attended members'")
return _("Hey! \n"
"I am here to remind you that Eden election is starting %s.\n"
"You are not registered to attend this election, so you will not be able to participate.\n\n"
"You can change your attendance status by pressing the button below text:.") % \
(nearestDateTimeText)
else:
LOG.debug("Do not send reminder to member (" + str(member) + ").")
return ""
except Exception as e:
LOG.exception("Exception in getTextForUpcomingElection: " + str(e))
raise ReminderManagementException("Exception in getTextForUpcomingElection: " + str(e))
def sendToTheGroupTimeIsUp(self,
election: Election,
reminderRound: int,
closestReminderConst: tuple[int, ReminderGroup, str],
roomArray: RoomArray,
modeDemo: ModeDemo = None):
"""Send reminder that the round is almost finished - in group"""
try:
assert isinstance(election, Election), "election is not instance of Election"
assert isinstance(reminderRound, int), "reminderRound is not instance of int"
assert isinstance(closestReminderConst, tuple), "closestReminderConst is not instance of tuple"
assert isinstance(roomArray, RoomArray), "roomArray is not instance of RoomArray"
assert isinstance(modeDemo, ModeDemo), "modeDemo is not instance of ModeDemo"
gctm: GroupCommunicationTextManagement = GroupCommunicationTextManagement()
timeIsUpButtons: tuple[str] = gctm.timeIsAlmostUpButtons()
# prepare replay markup
replyMarkup: InlineKeyboardMarkup = InlineKeyboardMarkup(
[
[ # First row - link to the portal
InlineKeyboardButton( # Opens a web URL
timeIsUpButtons[0],
url=eden_portal_url_action
)
]
]
)
LOG.info("Send reminder that the round is almost finished - in group")
rooms: list[ExtendedRoom] = roomArray.getRoomArray()
self.communication.updateKnownUserData(botName=telegram_bot_name)
for room in rooms:
try:
# prepare and sent message to the group
text: str = gctm.timeIsAlmostUpGroup(timeLeftInMinutes=closestReminderConst[0]-1, # -1 because it is increased because of lag
round=reminderRound,
extendedRoom=room,
)
if room.roomTelegramID is None:
LOG.error("ReminderManagement.sendToTheGroupTimeIsUp; Room telegram ID is None")
raise ReminderManagementException(
"ReminderManagement.sendToTheGroupTimeIsUp;Room telegram ID is None")
sendResponse = self.communication.sendMessage(sessionType=SessionType.BOT,
chatId=int(room.roomTelegramID),
text=text,
inlineReplyMarkup=replyMarkup)
if sendResponse is not None:
LOG.debug("sendToTheGroupTimeIsUp; Message was sent to the group: " + str(room.roomTelegramID))
else:
LOG.error(
"sendToTheGroupTimeIsUp; Message was not sent to the group: " + str(room.roomTelegramID))
except:
LOG.exception("Exception thrown when called sendToTheGroupTimeIsUp; Description: ")
except Exception as e:
LOG.exception(str(e))
raise ReminderManagementException("Exception thrown when called sendToTheGroup; Description: " + str(e))
def sendAndSyncWithDatabaseRoundIsAlmostFinish(self, member: ExtendedParticipant, election: Election,
reminder: Reminder,
closestReminderConst: tuple[int, ReminderGroup, str],
modeDemo: ModeDemo = None) -> bool:
"""Send reminder and write to database"""
###I have participants without reminderSent record, send the message to them, write to database
try:
assert isinstance(member, ExtendedParticipant), "member is not instance of ExtendedParticipant"
assert isinstance(election, Election), "election is not instance of Election"
assert len(closestReminderConst) == 3, "closestReminderConst is not correct size"
assert isinstance(closestReminderConst[0], int), "closestReminderConst[0] is not instance of int"
assert isinstance(closestReminderConst[1],
ReminderGroup), "closestReminderConst[1] is not instance of ReminderGroup"
assert isinstance(closestReminderConst[2], str), "closestReminderConst[2] is not instance of str"
LOG.debug("Member: " + str(member))
LOG.debug("Election id: " + str(election.electionID))
LOG.debug("Reminder: " + str(reminder))
#
# Create inline keyboard markup
#
gctm: GroupCommunicationTextManagement = GroupCommunicationTextManagement()
timeIsUpButtons: tuple[str] = gctm.timeIsAlmostUpButtons()
if len(timeIsUpButtons) != 2:
LOG.exception("timeIsUpButtons is not tuple with 2 items")
raise ReminderManagementException("timeIsUpButtons is not tuple with 2 items")
replyMarkup: InlineKeyboardMarkup = InlineKeyboardMarkup(
[
[ # First row - link to the portal
InlineKeyboardButton( # Opens a web URL
timeIsUpButtons[0],
url=eden_portal_url_action
),
# Second row - link to the blocks
InlineKeyboardButton( # Opens a web URL
timeIsUpButtons[1],
url=RawActionWeb().electVote(round=reminder.round,
voter=member.accountName,
candidate=None)
),
]
]
)
#
# Send message to the user
#
# prepare and send notification to the user
text: str = gctm.timeIsAlmostUpPrivate(timeLeftInMinutes=closestReminderConst[0]-1, # -1 because it is increased because of lag
round=reminder.round,
voteFor=member.voteFor)
sendResponse: bool = False
try:
# LIVE MODE
cSession = self.database.createCsesion(expireOnCommit=False)
LOG.trace("Live mode is enabled, sending message to: " + member.telegramID)
member.telegramID = ADD_AT_SIGN_IF_NOT_EXISTS(member.telegramID)
sendResponse = self.communication.sendMessage(sessionType=SessionType.BOT,
chatId=member.telegramID,
text=text,
inlineReplyMarkup=replyMarkup)
# Save the record to the database
response = self.database.createOrUpdateReminderSentRecord(reminder=reminder,
accountName=member.accountName,
sendStatus=ReminderSendStatus.SEND if sendResponse is True
else ReminderSendStatus.ERROR,
cSession=cSession)
if response is True:
self.database.commitCcession(session=cSession)
else:
self.database.rollbackCcession(session=cSession)
LOG.info("LiveMode; Is message sent successfully to " + member.telegramID + ": " + str(sendResponse)
+ ". Saving to the database under electionID: " + str(election.electionID))
self.database.removeCcession(session=cSession)
except Exception as e:
LOG.exception("Exception in sendAndSyncWithDatabaseElectionIsComing. Description: " + str(e))
self.database.rollbackCcession(session=cSession)
self.database.removeCcession(session=cSession)
return sendResponse
except Exception as e:
LOG.exception("Exception thrown when called sendAndSyncWithDatabaseElectionIsComing; Description: " + str(e))
def sendAndSyncWithDatabaseElectionIsComing(self, member: Participant, election: Election, reminder: Reminder,
reminderSentList: list[ReminderSent]) -> bool:
"""Send reminder and write to database"""
try:
assert isinstance(member, Participant), "member is not instance of Participant"
assert isinstance(election, Election), "election is not instance of Election"
assert isinstance(reminder, Reminder), "reminder is not instance of Reminder"
assert isinstance(reminderSentList, list), "reminderSentList is not instance of list"
LOG.trace("Send and sync with database: election is coming; "
"Member: " + str(member) +
", Election: " + str(election) +
", Reminder: " + str(reminder))
foundReminders: list[ReminderSent] = [x for x in reminderSentList if x.accountName == member.accountName]
# if participant is found in reminderSentList + status is sent then skip
if len(foundReminders) > 0:
LOG.debug("Participant is found in reminderSentList + status is 'SEND'")
LOG.info("Reminder already sent to telegramID: " + str(member.telegramID))
return
# prepare and send notification to the user
text: str = self.getTextForUpcomingElection(member=member,
electionDateTime=election.date,
reminder=reminder,
currentTime=self.datetime)
if text is None or len(text) < 1:
LOG.debug("Text is empty, skip sending")
return False
replyMarkup: InlineKeyboardMarkup = InlineKeyboardMarkup(
[
[ # First row
InlineKeyboardButton( # Opens a web URL
"Change the status",
url=eden_portal_url
),
]
]
) if member.participationStatus is False else None
sendResponse: bool = False
try:
cSession = self.database.createCsesion(expireOnCommit=False)
LOG.trace("Live mode is enabled, sending message to: " + member.telegramID)
member.telegramID = ADD_AT_SIGN_IF_NOT_EXISTS(member.telegramID)
sendResponse = self.communication.sendMessage(sessionType=SessionType.BOT,
chatId=member.telegramID,
text=text,
inlineReplyMarkup=replyMarkup)
LOG.info("LiveMode; Is message sent successfully to " + member.telegramID + ": " + str(sendResponse)
+ ". Saving to the database under electionID: " + str(election.electionID))
response: bool = self.database.createOrUpdateReminderSentRecord(reminder=reminder, accountName=member.accountName,
sendStatus=ReminderSendStatus.SEND if sendResponse is True
else ReminderSendStatus.ERROR,
cSession=cSession)
if response is True:
self.database.commitCcession(session=cSession)
else:
self.database.rollbackCcession(session=cSession)
self.database.removeCcession(session=cSession)
except Exception as e:
LOG.exception("Exception in sendAndSyncWithDatabaseElectionIsComing. Description: " + str(e))
self.database.rollbackCcession(session=cSession)
self.database.removeCcession(session=cSession)
return sendResponse
except Exception as e:
LOG.exception("Exception thrown when called sendAndSyncWithDatabaseElectionIsComing; Description: " + str(e))