mirror of
https://github.com/solero/houdini.git
synced 2024-11-08 20:28:20 +00:00
Redemption join handlers
This commit is contained in:
parent
98c2062633
commit
c1bd04fe3a
41
houdini.sql
41
houdini.sql
@ -1168,6 +1168,7 @@ CREATE TABLE redemption_code (
|
||||
type VARCHAR(8) NOT NULL DEFAULT 'BLANKET',
|
||||
coins INT NOT NULL DEFAULT 0,
|
||||
expires TIMESTAMP DEFAULT NULL,
|
||||
uses INT DEFAULT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
@ -1180,6 +1181,7 @@ COMMENT ON COLUMN redemption_code.code IS 'Redemption code';
|
||||
COMMENT ON COLUMN redemption_code.type IS 'Code type';
|
||||
COMMENT ON COLUMN redemption_code.coins IS 'Code coins amount';
|
||||
COMMENT ON COLUMN redemption_code.expires IS 'Expiry date';
|
||||
COMMENT ON COLUMN redemption_code.uses IS 'Number of uses';
|
||||
|
||||
DROP TABLE IF EXISTS redemption_book;
|
||||
CREATE TABLE redemption_book (
|
||||
@ -1212,24 +1214,39 @@ COMMENT ON COLUMN redemption_book_word.line IS 'Line number of page';
|
||||
COMMENT ON COLUMN redemption_book_word.word_number IS 'The nth word on the line';
|
||||
COMMENT ON COLUMN redemption_book_word.answer IS 'The correct word';
|
||||
|
||||
DROP TABLE IF EXISTS penguin_redemption;
|
||||
CREATE TABLE penguin_redemption (
|
||||
DROP TABLE IF EXISTS penguin_redemption_code;
|
||||
CREATE TABLE penguin_redemption_code (
|
||||
penguin_id INT NOT NULL,
|
||||
code_id INT DEFAULT NULL,
|
||||
book_id INT DEFAULT NULL,
|
||||
code_id INT NOT NULL,
|
||||
PRIMARY KEY (penguin_id, code_id),
|
||||
CONSTRAINT penguin_redemption_ibfk_1 FOREIGN KEY (penguin_id) REFERENCES penguin (id) ON DELETE RESTRICT ON UPDATE CASCADE,
|
||||
CONSTRAINT penguin_redemption_ibfk_2 FOREIGN KEY (code_id) REFERENCES redemption_code (id) ON DELETE RESTRICT ON UPDATE CASCADE,
|
||||
CONSTRAINT penguin_redemption_ibfk_3 FOREIGN KEY (book_id) REFERENCES redemption_book (id) ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
CONSTRAINT penguin_redemption_code_ibfk_1 FOREIGN KEY (penguin_id) REFERENCES penguin (id) ON DELETE RESTRICT ON UPDATE CASCADE,
|
||||
CONSTRAINT penguin_redemption_code_ibfk_2 FOREIGN KEY (code_id) REFERENCES redemption_code (id) ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX penguin_redemption_code_id ON penguin_redemption (code_id);
|
||||
CREATE INDEX penguin_redemption_book_id ON penguin_redemption (book_id);
|
||||
CREATE INDEX penguin_redemption_code_code_id ON penguin_redemption_code (code_id);
|
||||
|
||||
COMMENT ON TABLE penguin_redemption IS 'Redeemed codes';
|
||||
COMMENT ON TABLE penguin_redemption_code IS 'Redeemed codes';
|
||||
|
||||
COMMENT ON COLUMN penguin_redemption_code.penguin_id IS 'Unique penguin ID';
|
||||
COMMENT ON COLUMN penguin_redemption_code.code_id IS 'Unique code ID';
|
||||
|
||||
|
||||
DROP TABLE IF EXISTS penguin_redemption_book;
|
||||
CREATE TABLE penguin_redemption_book (
|
||||
penguin_id INT NOT NULL,
|
||||
book_id INT NOT NULL,
|
||||
PRIMARY KEY (penguin_id, book_id),
|
||||
CONSTRAINT penguin_redemption_book_ibfk_1 FOREIGN KEY (penguin_id) REFERENCES penguin (id) ON DELETE RESTRICT ON UPDATE CASCADE,
|
||||
CONSTRAINT penguin_redemption_book_ibfk_2 FOREIGN KEY (book_id) REFERENCES redemption_book (id) ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX penguin_redemption_book_book_id ON penguin_redemption_book (book_id);
|
||||
|
||||
COMMENT ON TABLE penguin_redemption_book IS 'Redeemed book codes';
|
||||
|
||||
COMMENT ON COLUMN penguin_redemption_book.penguin_id IS 'Unique penguin ID';
|
||||
COMMENT ON COLUMN penguin_redemption_book.book_id IS 'Unique book ID';
|
||||
|
||||
COMMENT ON COLUMN penguin_redemption.penguin_id IS 'Unique penguin ID';
|
||||
COMMENT ON COLUMN penguin_redemption.code_id IS 'Unique code ID';
|
||||
|
||||
DROP TABLE IF EXISTS redemption_award_card;
|
||||
CREATE TABLE redemption_award_card (
|
||||
|
@ -1,6 +1,101 @@
|
||||
from houdini.data import db
|
||||
|
||||
|
||||
class RedemptionCode(db.Model):
|
||||
__tablename__ = 'redemption_code'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True,
|
||||
server_default=db.text("nextval('\"redemption_code_id_seq\"'::regclass)"))
|
||||
code = db.Column(db.String(16), nullable=False, unique=True)
|
||||
type = db.Column(db.String(8), nullable=False, server_default=db.text("'BLANKET'::character varying"))
|
||||
coins = db.Column(db.Integer, nullable=False, server_default=db.text("0"))
|
||||
expires = db.Column(db.DateTime)
|
||||
uses = db.Column(db.Integer)
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self._cards = set()
|
||||
self._flooring = set()
|
||||
self._furniture = set()
|
||||
self._igloos = set()
|
||||
self._items = set()
|
||||
self._locations = set()
|
||||
self._puffles = set()
|
||||
self._puffle_items = set()
|
||||
|
||||
@property
|
||||
def cards(self):
|
||||
return self._cards
|
||||
|
||||
@cards.setter
|
||||
def cards(self, child):
|
||||
if isinstance(child, RedemptionAwardCard):
|
||||
self._cards.add(child)
|
||||
|
||||
@property
|
||||
def flooring(self):
|
||||
return self._flooring
|
||||
|
||||
@flooring.setter
|
||||
def flooring(self, child):
|
||||
if isinstance(child, RedemptionAwardFlooring):
|
||||
self._flooring.add(child)
|
||||
|
||||
@property
|
||||
def furniture(self):
|
||||
return self._furniture
|
||||
|
||||
@furniture.setter
|
||||
def furniture(self, child):
|
||||
if isinstance(child, RedemptionAwardFurniture):
|
||||
self._furniture.add(child)
|
||||
|
||||
@property
|
||||
def igloos(self):
|
||||
return self._igloos
|
||||
|
||||
@igloos.setter
|
||||
def igloos(self, child):
|
||||
if isinstance(child, RedemptionAwardIgloo):
|
||||
self._igloos.add(child)
|
||||
|
||||
@property
|
||||
def items(self):
|
||||
return self._items
|
||||
|
||||
@items.setter
|
||||
def items(self, child):
|
||||
if isinstance(child, RedemptionAwardItem):
|
||||
self._items.add(child)
|
||||
|
||||
@property
|
||||
def locations(self):
|
||||
return self._locations
|
||||
|
||||
@locations.setter
|
||||
def locations(self, child):
|
||||
if isinstance(child, RedemptionAwardLocation):
|
||||
self._locations.add(child)
|
||||
|
||||
@property
|
||||
def puffles(self):
|
||||
return self._puffles
|
||||
|
||||
@puffles.setter
|
||||
def puffles(self, child):
|
||||
if isinstance(child, RedemptionAwardPuffle):
|
||||
self._puffles.add(child)
|
||||
|
||||
@property
|
||||
def puffle_items(self):
|
||||
return self._puffle_items
|
||||
|
||||
@puffle_items.setter
|
||||
def puffle_items(self, child):
|
||||
if isinstance(child, RedemptionAwardPuffleItem):
|
||||
self._puffle_items.add(child)
|
||||
|
||||
|
||||
class RedemptionBook(db.Model):
|
||||
__tablename__ = 'redemption_book'
|
||||
|
||||
@ -19,17 +114,6 @@ class RedemptionBookWord(db.Model):
|
||||
answer = db.Column(db.String(20), nullable=False)
|
||||
|
||||
|
||||
class RedemptionCode(db.Model):
|
||||
__tablename__ = 'redemption_code'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True,
|
||||
server_default=db.text("nextval('\"redemption_code_id_seq\"'::regclass)"))
|
||||
code = db.Column(db.String(16), nullable=False, unique=True)
|
||||
type = db.Column(db.String(8), nullable=False, server_default=db.text("'BLANKET'::character varying"))
|
||||
coins = db.Column(db.Integer, nullable=False, server_default=db.text("0"))
|
||||
expires = db.Column(db.DateTime)
|
||||
|
||||
|
||||
class RedemptionAwardCard(db.Model):
|
||||
__tablename__ = 'redemption_award_card'
|
||||
code_id = db.Column(db.ForeignKey('redemption_code.id', ondelete='CASCADE', onupdate='CASCADE'), primary_key=True,
|
||||
@ -56,8 +140,8 @@ class RedemptionAwardFurniture(db.Model):
|
||||
|
||||
class RedemptionAwardIgloo(db.Model):
|
||||
__tablename__ = 'redemption_award_igloo'
|
||||
code_id = db.Column('CodeID', db.ForeignKey('redemption_code.id', ondelete='CASCADE', onupdate='CASCADE'),
|
||||
primary_key=True,nullable=False)
|
||||
code_id = db.Column(db.ForeignKey('redemption_code.id', ondelete='CASCADE', onupdate='CASCADE'),
|
||||
primary_key=True, nullable=False)
|
||||
igloo_id = db.Column(db.ForeignKey('igloo.id', ondelete='CASCADE', onupdate='CASCADE'), primary_key=True,
|
||||
nullable=False)
|
||||
|
||||
@ -94,11 +178,19 @@ class RedemptionAwardPuffleItem(db.Model):
|
||||
primary_key=True, nullable=False)
|
||||
|
||||
|
||||
class PenguinRedemption(db.Model):
|
||||
__tablename__ = 'penguin_redemption'
|
||||
class PenguinRedemptionCode(db.Model):
|
||||
__tablename__ = 'penguin_redemption_code'
|
||||
|
||||
penguin_id = db.Column(db.ForeignKey('penguin.id', ondelete='CASCADE', onupdate='CASCADE'), primary_key=True,
|
||||
nullable=False)
|
||||
code_id = db.Column(db.ForeignKey('redemption_code.id', ondelete='CASCADE', onupdate='CASCADE'), primary_key=True,
|
||||
nullable=False, index=True)
|
||||
book_id = db.Column(db.ForeignKey('redemption_book.id', ondelete='CASCADE', onupdate='CASCADE'), index=True)
|
||||
|
||||
|
||||
class PenguinRedemptionBook(db.Model):
|
||||
__tablename__ = 'penguin_redemption_book'
|
||||
|
||||
penguin_id = db.Column(db.ForeignKey('penguin.id', ondelete='CASCADE', onupdate='CASCADE'), primary_key=True,
|
||||
nullable=False)
|
||||
book_id = db.Column(db.ForeignKey('redemption_book.id', ondelete='CASCADE', onupdate='CASCADE'), primary_key=True,
|
||||
nullable=False, index=True)
|
||||
|
@ -0,0 +1,68 @@
|
||||
from houdini import handlers
|
||||
from houdini.handlers import XTPacket
|
||||
from houdini.constants import ClientType
|
||||
|
||||
from houdini.data import db
|
||||
from houdini.data.redemption import RedemptionCode, RedemptionAwardCard, RedemptionAwardFlooring, \
|
||||
RedemptionAwardFurniture, RedemptionAwardIgloo, RedemptionAwardItem, RedemptionAwardLocation,\
|
||||
RedemptionAwardPuffle, RedemptionAwardPuffleItem, PenguinRedemptionBook, PenguinRedemptionCode
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
@handlers.handler(XTPacket('rjs', ext='red'), pre_login=True, client=ClientType.Vanilla)
|
||||
@handlers.allow_once
|
||||
async def handle_join_redemption_server_vanilla(p, credentials: str, confirmation_hash: str, lang: str):
|
||||
pid, _, username, login_key, rdnk, approved, rejected = credentials.split('|')
|
||||
|
||||
if login_key != p.login_key:
|
||||
return await p.close()
|
||||
|
||||
tr = p.server.redis.multi_exec()
|
||||
tr.setex(f'{username}.lkey', p.server.config.auth_ttl, login_key)
|
||||
tr.setex(f'{username}.ckey', p.server.config.auth_ttl, confirmation_hash)
|
||||
await tr.execute()
|
||||
|
||||
redeemed_books = await PenguinRedemptionBook.query.where(PenguinRedemptionBook.penguin_id == p.id).gino.all()
|
||||
await p.send_xt('rjs', ','.join(str(redeemed_book.book_id) for redeemed_book in redeemed_books), 'houdini',
|
||||
int(p.is_member))
|
||||
|
||||
|
||||
@handlers.handler(XTPacket('rsc', ext='red'), pre_login=True)
|
||||
@handlers.depends_on_packet(XTPacket('rjs', ext='red'))
|
||||
async def handle_code(p, redemption_code: str):
|
||||
query = RedemptionCode.load(cards=RedemptionAwardCard,
|
||||
flooring=RedemptionAwardFlooring,
|
||||
furniture=RedemptionAwardFurniture,
|
||||
igloos=RedemptionAwardIgloo,
|
||||
items=RedemptionAwardItem,
|
||||
locations=RedemptionAwardLocation,
|
||||
puffles=RedemptionAwardPuffle,
|
||||
puffle_items=RedemptionAwardPuffleItem)\
|
||||
.query.where(RedemptionCode.code == redemption_code)
|
||||
code = await query.gino.first()
|
||||
|
||||
if code is None:
|
||||
return await p.send_error(720)
|
||||
|
||||
if code.uses is not None:
|
||||
redeemed_count = await db.select([db.func.count(PenguinRedemptionCode.code_id)]).where(
|
||||
PenguinRedemptionCode.code_id == code.id).gino.scalar()
|
||||
|
||||
if redeemed_count >= code.uses:
|
||||
return await p.send_error(721)
|
||||
|
||||
penguin_redeemed = await PenguinRedemptionCode.query.where((PenguinRedemptionCode.code_id == code.id) &
|
||||
(PenguinRedemptionCode.penguin_id == p.id)).gino.scalar()
|
||||
if penguin_redeemed:
|
||||
return await p.send_error(721)
|
||||
|
||||
if code.expires is not None and code.expires < datetime.now():
|
||||
return await p.send_error(726)
|
||||
|
||||
if code.type == 'CATALOG':
|
||||
owned_ids = ','.join((item.item_id for item in code.items if item.item_id in p.inventory))
|
||||
return await p.send_xt('rsc', 'treasurebook', 3, owned_ids, 0)
|
||||
|
||||
await p.send_xt('rsc', code.type, '', code.coins)
|
||||
|
Loading…
Reference in New Issue
Block a user