Skip to content

Commit

Permalink
feat(warlord): Website management section
Browse files Browse the repository at this point in the history
  • Loading branch information
Nickelza committed Nov 22, 2023
1 parent cbd15b6 commit 2a86467
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 5 deletions.
23 changes: 23 additions & 0 deletions resources/phrases.py
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,7 @@ def surround_with_arrows(text: str) -> str:
NOTIFICATION_CATEGORY_LOCATION = 'Location'
NOTIFICATION_CATEGORY_PREDICTION = 'Prediction'
NOTIFICATION_CATEGORY_DEVIL_FRUIT = 'Devil Fruit'
NOTIFICATION_CATEGORY_WARLORD = 'Warlord'

# Notification - Crew Leave
CREW_LEAVE_NOTIFICATION = '{} has left the Crew'
Expand Down Expand Up @@ -957,6 +958,28 @@ def surround_with_arrows(text: str) -> str:
+ BOUNTY_LOAN_EXPIRED_ACTION_BORROWER
BOUNTY_LOAN_EXPIRED_NOTIFICATION_DESCRIPTION = 'If to be notified when your loan expires'
BOUNTY_LOAN_EXPIRED_NOTIFICATION_KEY = 'Bounty loan expired'
# Notification - Warlord appointment
WARLORD_APPOINTMENT_NOTIFICATION = \
'Congratulations, you have been appointed as a Warlord!' \
'\n\n*Epithet*: {}' \
'\n*Duration*: {}' \
'\n*Reason*: {}' \
'\n\n*Privileges*' \
f'\n{Env.PIRATE_KING_TRANSACTION_TAX_DISCOUNT.get_int()}% off tax on gifts and loans' \
'\n• Immunity from Crew disbandment \\(if Captain\\) and Devil Fruit revocation for not ' \
f'appearing in the latest {Env.CREW_MAINTAIN_MIN_LATEST_LEADERBOARD_APPEARANCE.get_int()} leaderboards' \
'\n• View inferior ranks status \\(Emperor and below\\)' \
f'\n• Custom Bounty Poster {Env.BOUNTY_POSTER_LIMIT_WARLORD.get_int()} times a day' \
f'\n• View New World users in logs' \
f'\n\n_You will appear in the weekly leaderboard exclusively with Warlord rank' \
f' \\(only for the global leaderboard\\)_'
WARLORD_APPOINTMENT_NOTIFICATION_DESCRIPTION = 'If to be notified when you are appointed as a Warlord'
WARLORD_APPOINTMENT_NOTIFICATION_KEY = 'Warlord appointment'
# Notification - Warlord revocation
WARLORD_REVOCATION_NOTIFICATION = 'Your Warlord status has been revoked' \
'\n\n*Reason*: {}'
WARLORD_REVOCATION_NOTIFICATION_DESCRIPTION = 'If to be notified when your Warlord status is revoked'
WARLORD_REVOCATION_NOTIFICATION_KEY = 'Warlord revocation'

# List
LIST_OVERVIEW = 'Select' + ' {} *{}* from the list below\n{}' # In the chunk to avoid IDE recognizing it as SQL
Expand Down
19 changes: 18 additions & 1 deletion src/chat/tgrest/tgrest_chat_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@

from src.chat.tgrest.screens.screen_prediction import manage as manage_screen_prediction
from src.chat.tgrest.screens.screen_send_private_message import manage as manage_screen_send_private_message
from src.model.enums.Notification import ImpelDownNotificationRestrictionPlaced, DevilFruitAwardedNotification
from src.model.enums.Notification import ImpelDownNotificationRestrictionPlaced, DevilFruitAwardedNotification, \
WarlordAppointmentNotification, WarlordRevocationNotification
from src.model.enums.Notification import ImpelDownNotificationRestrictionRemoved
from src.model.enums.devil_fruit.DevilFruitSource import DevilFruitSource
from src.model.error.CustomException import DevilFruitValidationException
Expand All @@ -15,6 +16,8 @@
from src.model.tgrest.TgRestObjectType import TgRestObjectType
from src.model.tgrest.TgRestPrediction import TgRestPrediction
from src.model.tgrest.TgRestPrivateMessage import TgRestPrivateMessage
from src.model.tgrest.TgRestWarlordAppointment import TgRestWarlordAppointment
from src.model.tgrest.TgRestWarlordRevocation import TgRestWarlordRevocation
from src.service.devil_fruit_service import give_devil_fruit_to_user
from src.service.message_service import full_message_send, escape_valid_markdown_chars
from src.service.notification_service import send_notification
Expand Down Expand Up @@ -85,6 +88,20 @@ async def manage(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
notification = DevilFruitAwardedNotification(tg_rest_dfa.devil_fruit, tg_rest_dfa.reason)
await send_notification(context, tg_rest_dfa.user, notification)

case TgRestObjectType.WARLORD_APPOINTMENT:
tg_rest_wa = TgRestWarlordAppointment(**tg_rest_dict)

# Send notification
notification = WarlordAppointmentNotification(tg_rest_wa.warlord, tg_rest_wa.days)
await send_notification(context, tg_rest_wa.user, notification)

case TgRestObjectType.WARLORD_REVOCATION:
tg_rest_wr = TgRestWarlordRevocation(**tg_rest_dict)

# Send notification
notification = WarlordRevocationNotification(tg_rest_wr.warlord)
await send_notification(context, tg_rest_wr.user, notification)

case _:
raise TgRestException("Unknown object type")
await full_message_send(context, "Request received", update=update, quote=True)
Expand Down
4 changes: 3 additions & 1 deletion src/model/Warlord.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ class Warlord(BaseModel):
reason = CharField(max_length=999, null=True)
date = DateTimeField(default=datetime.datetime.now)
end_date = DateTimeField()
original_end_date = DateTimeField() # In case it was ended early
revoke_reason = CharField(max_length=999, null=True)

class Meta:
db_table = 'warlord'
Expand Down Expand Up @@ -56,7 +58,7 @@ def get_active_user_ids() -> list[int]:
@staticmethod
def get_latest_active_by_user(user: User) -> 'Warlord':
"""
Get latest active warlord by user
Get the latest active warlord by user
:param user: The user
:return: The warlord
"""
Expand Down
57 changes: 54 additions & 3 deletions src/model/enums/Notification.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@
from src.model.PredictionOption import PredictionOption
from src.model.PredictionOptionUser import PredictionOptionUser
from src.model.User import User
from src.model.Warlord import Warlord
from src.model.enums.Emoji import Emoji
from src.model.enums.ReservedKeyboardKeys import ReservedKeyboardKeys
from src.model.enums.Screen import Screen
from src.model.enums.impel_down.ImpelDownBountyAction import ImpelDownBountyAction
from src.model.enums.impel_down.ImpelDownSentenceType import ImpelDownSentenceType
from src.model.game.GameType import GameType
from src.model.pojo.Keyboard import Keyboard
from src.service.date_service import default_datetime_format
from src.service.date_service import default_datetime_format, convert_days_to_duration
from src.service.date_service import get_remaining_duration
from src.service.message_service import get_image_preview, escape_valid_markdown_chars, mention_markdown_user, \
get_message_url
Expand All @@ -36,6 +37,7 @@ class NotificationCategory(IntEnum):
BOUNTY_GIFT = 7
DEVIL_FRUIT = 8
BOUNTY_LOAN = 9
WARLORD = 10


NOTIFICATION_CATEGORY_DESCRIPTIONS = {
Expand All @@ -47,7 +49,8 @@ class NotificationCategory(IntEnum):
NotificationCategory.DELETED_MESSAGE: phrases.NOTIFICATION_CATEGORY_DELETED_MESSAGE,
NotificationCategory.BOUNTY_GIFT: phrases.NOTIFICATION_CATEGORY_BOUNTY_GIFT,
NotificationCategory.DEVIL_FRUIT: phrases.NOTIFICATION_CATEGORY_DEVIL_FRUIT,
NotificationCategory.BOUNTY_LOAN: phrases.NOTIFICATION_CATEGORY_BOUNTY_LOAN
NotificationCategory.BOUNTY_LOAN: phrases.NOTIFICATION_CATEGORY_BOUNTY_LOAN,
NotificationCategory.WARLORD: phrases.NOTIFICATION_CATEGORY_WARLORD
}


Expand Down Expand Up @@ -75,6 +78,8 @@ class NotificationType(IntEnum):
BOUNTY_LOAN_PAYMENT = 19
BOUNTY_LOAN_FORGIVEN = 20
BOUNTY_LOAN_EXPIRED = 21
WARLORD_APPOINTMENT = 22
WARLORD_REVOCATION = 23


class Notification:
Expand Down Expand Up @@ -720,14 +725,60 @@ def build(self) -> str:
loaner.get_markdown_mention())


class WarlordAppointmentNotification(Notification):
"""Class for warlord appointment notifications."""

def __init__(self, warlord: Warlord = None, days: int = None):
"""
Constructor
:param warlord: The warlord
"""

self.warlord = warlord
self.days = days

super().__init__(NotificationCategory.WARLORD, NotificationType.WARLORD_APPOINTMENT,
phrases.WARLORD_APPOINTMENT_NOTIFICATION,
phrases.WARLORD_APPOINTMENT_NOTIFICATION_DESCRIPTION,
phrases.WARLORD_APPOINTMENT_NOTIFICATION_KEY)

def build(self) -> str:
return self.text.format(escape_valid_markdown_chars(self.warlord.epithet),
convert_days_to_duration(self.days),
escape_valid_markdown_chars(self.warlord.reason))


class WarlordRevocationNotification(Notification):
"""Class for warlord revocation notifications."""

def __init__(self, warlord: Warlord = None):
"""
Constructor
:param warlord: The warlord
"""

self.warlord = warlord

super().__init__(NotificationCategory.WARLORD, NotificationType.WARLORD_REVOCATION,
phrases.WARLORD_REVOCATION_NOTIFICATION,
phrases.WARLORD_REVOCATION_NOTIFICATION_DESCRIPTION,
phrases.WARLORD_REVOCATION_NOTIFICATION_KEY)

def build(self) -> str:
return self.text.format(escape_valid_markdown_chars(self.warlord.revoke_reason))


NOTIFICATIONS = [CrewLeaveNotification(), LocationUpdateNotification(), CrewDisbandNotification(),
CrewDisbandWarningNotification(), GameTurnNotification(), CrewMemberRemoveNotification(),
ImpelDownNotificationRestrictionPlaced(), ImpelDownNotificationRestrictionRemoved(),
PredictionResultNotification(), PredictionBetInvalidNotification(), DeletedMessageArrestNotification(),
DeletedMessageMuteNotification(), DeletedMessageLocationNotification(),
BountyGiftReceivedNotification(), DevilFruitAwardedNotification(), DevilFruitExpiredNotification(),
DevilFruitRevokeNotification(), DevilFruitRevokeWarningNotification(), BountyLoanPaymentNotification(),
BountyLoanForgivenNotification(), BountyLoanExpiredNotification()]
BountyLoanForgivenNotification(), BountyLoanExpiredNotification(), WarlordAppointmentNotification(),
WarlordRevocationNotification()]


def get_notifications_by_category(notification_category: NotificationCategory) -> list[Notification]:
Expand Down
2 changes: 2 additions & 0 deletions src/model/tgrest/TgRestObjectType.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ class TgRestObjectType(StrEnum):
PRIVATE_MESSAGE = 'private_message'
IMPEL_DOWN_NOTIFICATION = 'impel_down_notification'
DEVIL_FRUIT_AWARD = 'devil_fruit_award'
WARLORD_APPOINTMENT = 'warlord_appointment'
WARLORD_REVOCATION = 'warlord_revocation'
26 changes: 26 additions & 0 deletions src/model/tgrest/TgRestWarlordAppointment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from src.model.User import User
from src.model.Warlord import Warlord
from src.model.tgrest.TgRest import TgRest
from src.model.tgrest.TgRestObjectType import TgRestObjectType


class TgRestWarlordAppointment(TgRest):
"""
TgRestWarlordAppointment class is used to create a Telegram REST API request.
"""

def __init__(self, bot_id: str, object_type: TgRestObjectType, user_id: int, warlord_id: int, days: int):
"""
Constructor
:param user_id: The user id
:param warlord_id: The warlord id
:param days: The number of days the user will be a warlord. Technically not necessary since it can be calculated
from the end date, but it's easier to just pass it in.
"""

super().__init__(bot_id, object_type)

self.user: User = User.get_by_id(user_id)
self.warlord: Warlord = Warlord.get_by_id(warlord_id)
self.days: int = days
23 changes: 23 additions & 0 deletions src/model/tgrest/TgRestWarlordRevocation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from src.model.User import User
from src.model.Warlord import Warlord
from src.model.tgrest.TgRest import TgRest
from src.model.tgrest.TgRestObjectType import TgRestObjectType


class TgRestWarlordRevocation(TgRest):
"""
TgRestWarlordRevocation class is used to create a Telegram REST API request.
"""

def __init__(self, bot_id: str, object_type: TgRestObjectType, user_id: int, warlord_id: int):
"""
Constructor
:param user_id: The user id
:param warlord_id: The warlord id
"""

super().__init__(bot_id, object_type)

self.user: User = User.get_by_id(user_id)
self.warlord: Warlord = Warlord.get_by_id(warlord_id)
9 changes: 9 additions & 0 deletions src/service/date_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,15 @@ def convert_seconds_to_duration(seconds: int) -> str:
return result


def convert_days_to_duration(days: int) -> str:
"""
Converts days to days, hours, minutes, seconds
:param days: Days to convert
:return: Days, hours e.g. 1 day 2 hours 5 minutes
"""
return convert_seconds_to_duration(days * 86400)


def cron_datetime_difference(cron_expression: str, start_datetime: datetime = None) -> str:
"""
Get the difference between the next run time and the current datetime
Expand Down

0 comments on commit 2a86467

Please sign in to comment.