mirror of
https://github.com/solero/houdini.git
synced 2024-11-24 14:37:22 +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',
|
type VARCHAR(8) NOT NULL DEFAULT 'BLANKET',
|
||||||
coins INT NOT NULL DEFAULT 0,
|
coins INT NOT NULL DEFAULT 0,
|
||||||
expires TIMESTAMP DEFAULT NULL,
|
expires TIMESTAMP DEFAULT NULL,
|
||||||
|
uses INT DEFAULT NULL,
|
||||||
PRIMARY KEY (id)
|
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.type IS 'Code type';
|
||||||
COMMENT ON COLUMN redemption_code.coins IS 'Code coins amount';
|
COMMENT ON COLUMN redemption_code.coins IS 'Code coins amount';
|
||||||
COMMENT ON COLUMN redemption_code.expires IS 'Expiry date';
|
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;
|
DROP TABLE IF EXISTS redemption_book;
|
||||||
CREATE TABLE 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.word_number IS 'The nth word on the line';
|
||||||
COMMENT ON COLUMN redemption_book_word.answer IS 'The correct word';
|
COMMENT ON COLUMN redemption_book_word.answer IS 'The correct word';
|
||||||
|
|
||||||
DROP TABLE IF EXISTS penguin_redemption;
|
DROP TABLE IF EXISTS penguin_redemption_code;
|
||||||
CREATE TABLE penguin_redemption (
|
CREATE TABLE penguin_redemption_code (
|
||||||
penguin_id INT NOT NULL,
|
penguin_id INT NOT NULL,
|
||||||
code_id INT DEFAULT NULL,
|
code_id INT NOT NULL,
|
||||||
book_id INT DEFAULT NULL,
|
|
||||||
PRIMARY KEY (penguin_id, code_id),
|
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_code_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_code_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
|
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE INDEX penguin_redemption_code_id ON penguin_redemption (code_id);
|
CREATE INDEX penguin_redemption_code_code_id ON penguin_redemption_code (code_id);
|
||||||
CREATE INDEX penguin_redemption_book_id ON penguin_redemption (book_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;
|
DROP TABLE IF EXISTS redemption_award_card;
|
||||||
CREATE TABLE redemption_award_card (
|
CREATE TABLE redemption_award_card (
|
||||||
|
@ -1,6 +1,101 @@
|
|||||||
from houdini.data import db
|
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):
|
class RedemptionBook(db.Model):
|
||||||
__tablename__ = 'redemption_book'
|
__tablename__ = 'redemption_book'
|
||||||
|
|
||||||
@ -19,17 +114,6 @@ class RedemptionBookWord(db.Model):
|
|||||||
answer = db.Column(db.String(20), nullable=False)
|
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):
|
class RedemptionAwardCard(db.Model):
|
||||||
__tablename__ = 'redemption_award_card'
|
__tablename__ = 'redemption_award_card'
|
||||||
code_id = db.Column(db.ForeignKey('redemption_code.id', ondelete='CASCADE', onupdate='CASCADE'), primary_key=True,
|
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):
|
class RedemptionAwardIgloo(db.Model):
|
||||||
__tablename__ = 'redemption_award_igloo'
|
__tablename__ = 'redemption_award_igloo'
|
||||||
code_id = db.Column('CodeID', db.ForeignKey('redemption_code.id', ondelete='CASCADE', onupdate='CASCADE'),
|
code_id = db.Column(db.ForeignKey('redemption_code.id', ondelete='CASCADE', onupdate='CASCADE'),
|
||||||
primary_key=True,nullable=False)
|
primary_key=True, nullable=False)
|
||||||
igloo_id = db.Column(db.ForeignKey('igloo.id', ondelete='CASCADE', onupdate='CASCADE'), primary_key=True,
|
igloo_id = db.Column(db.ForeignKey('igloo.id', ondelete='CASCADE', onupdate='CASCADE'), primary_key=True,
|
||||||
nullable=False)
|
nullable=False)
|
||||||
|
|
||||||
@ -94,11 +178,19 @@ class RedemptionAwardPuffleItem(db.Model):
|
|||||||
primary_key=True, nullable=False)
|
primary_key=True, nullable=False)
|
||||||
|
|
||||||
|
|
||||||
class PenguinRedemption(db.Model):
|
class PenguinRedemptionCode(db.Model):
|
||||||
__tablename__ = 'penguin_redemption'
|
__tablename__ = 'penguin_redemption_code'
|
||||||
|
|
||||||
penguin_id = db.Column(db.ForeignKey('penguin.id', ondelete='CASCADE', onupdate='CASCADE'), primary_key=True,
|
penguin_id = db.Column(db.ForeignKey('penguin.id', ondelete='CASCADE', onupdate='CASCADE'), primary_key=True,
|
||||||
nullable=False)
|
nullable=False)
|
||||||
code_id = db.Column(db.ForeignKey('redemption_code.id', ondelete='CASCADE', onupdate='CASCADE'), primary_key=True,
|
code_id = db.Column(db.ForeignKey('redemption_code.id', ondelete='CASCADE', onupdate='CASCADE'), primary_key=True,
|
||||||
nullable=False, index=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