Full support for expiring memberships

This commit is contained in:
Ben
2020-01-02 23:11:27 +00:00
parent 82a3753d0d
commit f255ad112d
7 changed files with 102 additions and 12 deletions

View File

@@ -84,7 +84,7 @@ class PenguinStringCompiler(OrderedDict):
'Y': PenguinStringCompiler.attribute_by_name('y'),
'Frame': PenguinStringCompiler.attribute_by_name('frame'),
'Member': PenguinStringCompiler.attribute_by_name('member'),
'MemberDays': PenguinStringCompiler.attribute_by_name('membership_days'),
'MemberDays': PenguinStringCompiler.attribute_by_name('membership_days_total'),
'Avatar': PenguinStringCompiler.attribute_by_name('avatar'),
'PenguinState': PenguinStringCompiler.attribute_by_name('penguin_state'),
'PartyState': PenguinStringCompiler.attribute_by_name('party_state'),

View File

@@ -148,7 +148,10 @@ class PenguinMembership(db.Model):
penguin_id = db.Column(db.ForeignKey('penguin.id', ondelete='CASCADE', onupdate='CASCADE'), primary_key=True,
nullable=False)
start = db.Column(db.DateTime, primary_key=True, nullable=False)
expires = db.Column(db.DateTime, primary_key=True, nullable=False)
expires = db.Column(db.DateTime)
start_aware = db.Column(db.Boolean, server_default=db.text("false"))
expires_aware = db.Column(db.Boolean, server_default=db.text("false"))
expired_aware = db.Column(db.Boolean, server_default=db.text("false"))
class Login(db.Model):

View File

@@ -43,7 +43,7 @@ async def handle_join_server(p, penguin_id: int, login_key: str):
await p.send_xt('lp', await p.string, p.coins, int(p.safe_chat), p.egg_timer_minutes,
penguin_standard_time, p.age, 0, p.minutes_played,
"membership_days", server_time_offset, int(p.opened_playercard),
p.membership_days_remain, server_time_offset, int(p.opened_playercard),
p.map_category, p.status_field)
spawn = random.choice(p.server.spawn_rooms)

View File

@@ -1,11 +1,14 @@
from houdini import handlers
from houdini.converters import SeparatorConverter
from houdini.handlers import XTPacket
from houdini.data.penguin import Penguin
from houdini.handlers.play.navigation import handle_join_server
from houdini.data import db
from houdini.data.penguin import Penguin, PenguinMembership
from houdini.data.mail import PenguinPostcard
from houdini.constants import ClientType
from aiocache import cached
from datetime import datetime
from datetime import datetime, timedelta
import random
import asyncio
import time
@@ -77,6 +80,78 @@ async def server_egg_timer(server):
await p.send_error_and_disconnect(910)
MemberWarningDaysToExpiry = 14
MemberWarningPostcardsVanilla = [122, 123]
MemberWarningPostcardsLegacy = [163]
MemberExpiredPostcard = 124
MemberStartPostcardVanilla = 121
MemberStartPostcardLegacy = 164
@handlers.handler(XTPacket('j', 'js'), pre_login=True, before=handle_join_server)
@handlers.allow_once
async def handle_setup_membership(p):
if not p.server.config.expire_membership or p.moderator or p.character:
p.is_member = True
p.membership_days_total = p.age
return
membership_history = PenguinMembership.query.where(PenguinMembership.penguin_id == p.id)
current_timestamp = datetime.now()
postcards = []
warning_postcards = MemberWarningPostcardsVanilla if p.is_vanilla_client else MemberWarningPostcardsLegacy
start_postcard = MemberStartPostcardVanilla if p.is_vanilla_client else MemberStartPostcardLegacy
async with db.transaction():
async for membership_record in membership_history.gino.iterate():
membership_recurring = membership_record.expires is None
membership_active = membership_recurring or membership_record.expires >= current_timestamp
if membership_record.start < current_timestamp:
if membership_active:
p.is_member = True
if not membership_recurring:
days_to_expiry = (membership_record.expires.date() - datetime.now().date()).days
p.membership_days_remain = days_to_expiry
if days_to_expiry <= MemberWarningDaysToExpiry and not membership_record.expires_aware:
postcards.append(dict(
penguin_id=p.id,
postcard_id=random.choice(warning_postcards),
send_date=membership_record.expires - timedelta(days=MemberWarningDaysToExpiry)
))
await membership_record.update(expires_aware=True).apply()
else:
if p.membership_days_remain < 0:
days_since_expiry = (membership_record.expires.date() - datetime.now().date()).days
p.membership_days_remain = min(p.membership_days_remain, days_since_expiry)
if not membership_record.expired_aware:
if p.is_vanilla_client:
postcards.append(dict(
penguin_id=p.id,
postcard_id=MemberExpiredPostcard,
send_date=membership_record.expires
))
await membership_record.update(expired_aware=True).apply()
if not membership_record.start_aware:
postcards.append(dict(
penguin_id=p.id,
postcard_id=start_postcard,
send_date=membership_record.start
))
await membership_record.update(start_aware=True).apply()
membership_end_date = current_timestamp if membership_active else membership_record.expires
p.membership_days_total += (membership_end_date - membership_record.start).days
if postcards:
await PenguinPostcard.insert().values(postcards).gino.status()
@handlers.handler(XTPacket('u', 'h'))
@handlers.cooldown(59)
async def handle_heartbeat(p):

View File

@@ -7,9 +7,9 @@ from houdini.data import penguin
class Penguin(Spheniscidae, penguin.Penguin):
__slots__ = ['x', 'y', 'frame', 'toy', 'room', 'waddle', 'table',
'data', 'muted', 'login_key', 'member', 'membership_days',
'avatar', 'walking_puffle', 'permissions', 'active_quests',
'buddy_requests', 'heartbeat', 'login_timestamp',
'data', 'muted', 'login_key', 'is_member', 'membership_days_total',
'membership_days_remain', 'avatar', 'walking_puffle', 'permissions',
'active_quests', 'legacy_buddy_requests', 'heartbeat', 'login_timestamp',
'egg_timer_minutes']
def __init__(self, *args):
@@ -25,8 +25,9 @@ class Penguin(Spheniscidae, penguin.Penguin):
self.login_key = None
self.member = 1
self.membership_days = 1
self.is_member = False
self.membership_days_total = 0
self.membership_days_remain = -1
self.avatar = None
self.walking_puffle = None
@@ -58,6 +59,10 @@ class Penguin(Spheniscidae, penguin.Penguin):
def safe_name(self):
return self.safe_nickname(self.server.config.lang)
@property
def member(self):
return int(self.is_member)
async def join_room(self, room):
await room.add_penguin(self)