AS2 support

This commit is contained in:
rsakeys 2020-04-06 18:46:56 +01:00
parent 55ac7e3ff8
commit b78b6ab0d1

View File

@ -1,5 +1,3 @@
from datetime import datetime
from houdini import handlers from houdini import handlers
from houdini.constants import ClientType from houdini.constants import ClientType
from houdini.data.item import Item from houdini.data.item import Item
@ -10,6 +8,8 @@ from houdini.data.redemption import PenguinRedemptionBook, PenguinRedemptionCode
RedemptionAwardLocation, RedemptionAwardPuffle, RedemptionAwardPuffleItem, RedemptionCode RedemptionAwardLocation, RedemptionAwardPuffle, RedemptionAwardPuffleItem, RedemptionCode
from houdini.handlers import XTPacket from houdini.handlers import XTPacket
from houdini.handlers.games.ninja.card import ninja_rank_up
import random import random
from datetime import datetime from datetime import datetime
@ -31,12 +31,82 @@ async def handle_join_redemption_server_vanilla(p, credentials: str, confirmatio
int(p.is_member)) int(p.is_member))
@handlers.handler(XTPacket('rsc', ext='red'), pre_login=True) @handlers.handler(XTPacket('rjs', ext='red'), pre_login=True, client=ClientType.Legacy)
@handlers.allow_once
async def handle_join_redemption_server_legacy(p, penguin_id: int, login_key: str, lang: str):
if login_key != p.login_key:
return await p.close()
tr = p.server.redis.multi_exec()
tr.setex(f'{p.username}.lkey', p.server.config.auth_ttl, login_key)
await tr.execute()
await p.send_xt('rjs', '', 1)
@handlers.handler(XTPacket('rsc', ext='red'), pre_login=True, client=ClientType.Legacy)
@handlers.depends_on_packet(XTPacket('rjs', ext='red')) @handlers.depends_on_packet(XTPacket('rjs', ext='red'))
async def handle_code(p, redemption_code: str): async def handle_code_legacy(p, redemption_code: str):
query = RedemptionCode.distinct(RedemptionCode.id) \
.load(cards=RedemptionAwardCard.distinct(RedemptionAwardCard.card_id),
items=RedemptionAwardItem.distinct(RedemptionAwardItem.item_id),
flooring=RedemptionAwardFlooring.distinct(RedemptionAwardFlooring.flooring_id),
furniture=RedemptionAwardFurniture.distinct(RedemptionAwardFurniture.furniture_id),
igloos=RedemptionAwardIgloo.distinct(RedemptionAwardIgloo.igloo_id),
locations=RedemptionAwardLocation.distinct(RedemptionAwardLocation.location_id),
puffles=RedemptionAwardPuffle.distinct(RedemptionAwardPuffle.puffle_id),
puffle_items=RedemptionAwardPuffleItem.distinct(RedemptionAwardPuffleItem.puffle_item_id)
) \
.query.where(RedemptionCode.code == redemption_code)
codes = await query.gino.all()
awards = []
if not codes:
return await p.send_error(720)
code = codes[0]
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 == 'GOLDEN':
return await p.send_xt('rsc', 'GOLDEN', p.ninja_rank, p.fire_ninja_rank, p.water_ninja_rank,
int(p.fire_ninja_rank > 0), int(p.water_ninja_rank > 0))
if code.type == 'CARD':
for award in code.cards:
await p.add_card(p.server.cards[award.card_id])
else:
if code.items:
for award in code.items:
awards.append(str(award.item_id))
await p.add_inventory(p.server.items[award.item_id], notify=False)
await PenguinRedemptionCode.create(penguin_id=p.id, code_id=code.id)
await p.update(coins=p.coins + code.coins).apply()
return await p.send_xt('rsc', code.type, ','.join(map(str, awards)), code.coins)
@handlers.handler(XTPacket('rsc', ext='red'), pre_login=True, client=ClientType.Vanilla)
@handlers.depends_on_packet(XTPacket('rjs', ext='red'))
async def handle_code_vanilla(p, redemption_code: str):
query = RedemptionCode.distinct(RedemptionCode.id)\ query = RedemptionCode.distinct(RedemptionCode.id)\
.load(cards=RedemptionAwardCard.distinct(RedemptionAwardCard.card_id), .load(cards=RedemptionAwardCard.distinct(RedemptionAwardCard.card_id),
items=RedemptionAwardItem.distinct(RedemptionAwardItem.item_id), items=RedemptionAwardItem.distinct(RedemptionAwardItem.item_id),
flooring = RedemptionAwardFlooring.distinct(RedemptionAwardFlooring.flooring_id),
furniture=RedemptionAwardFurniture.distinct(RedemptionAwardFurniture.furniture_id), furniture=RedemptionAwardFurniture.distinct(RedemptionAwardFurniture.furniture_id),
igloos=RedemptionAwardIgloo.distinct(RedemptionAwardIgloo.igloo_id), igloos=RedemptionAwardIgloo.distinct(RedemptionAwardIgloo.igloo_id),
locations=RedemptionAwardLocation.distinct(RedemptionAwardLocation.location_id), locations=RedemptionAwardLocation.distinct(RedemptionAwardLocation.location_id),
@ -44,35 +114,37 @@ async def handle_code(p, redemption_code: str):
puffle_items=RedemptionAwardPuffleItem.distinct(RedemptionAwardPuffleItem.puffle_item_id) puffle_items=RedemptionAwardPuffleItem.distinct(RedemptionAwardPuffleItem.puffle_item_id)
)\ )\
.query.where(RedemptionCode.code == redemption_code) .query.where(RedemptionCode.code == redemption_code)
code = await query.gino.all() codes = await query.gino.all()
awards = [] awards = []
if code[0] is None: if not codes:
return await p.send_error(720) return await p.send_error(720)
if code[0].uses is not None: code = codes[0]
redeemed_count = await db.select([db.func.count(PenguinRedemptionCode.code_id)]).where(
PenguinRedemptionCode.code_id == code[0].id).gino.scalar()
if redeemed_count >= code[0].uses: 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) return await p.send_error(721)
penguin_redeemed = await PenguinRedemptionCode.query.where((PenguinRedemptionCode.code_id == code[0].id) & penguin_redeemed = await PenguinRedemptionCode.query.where((PenguinRedemptionCode.code_id == code.id) &
(PenguinRedemptionCode.penguin_id == p.id)).gino.scalar() (PenguinRedemptionCode.penguin_id == p.id)).gino.scalar()
if penguin_redeemed: if penguin_redeemed:
return await p.send_error(721) return await p.send_error(721)
if code[0].expires is not None and code[0].expires < datetime.now(): if code.expires is not None and code.expires < datetime.now():
return await p.send_error(726) return await p.send_error(726)
if code[0].type == 'CATALOG': if code.type == 'CATALOG':
num_redeemed_codes = await PenguinRedemptionCode.join(RedemptionCode).count().where( num_redeemed_codes = await PenguinRedemptionCode.join(RedemptionCode).count().where(
(PenguinRedemptionCode.penguin_id == p.id) & (RedemptionCode.type == 'CATALOG') (PenguinRedemptionCode.penguin_id == p.id) & (RedemptionCode.type == 'CATALOG')
).gino.scalar() ).gino.scalar()
owned_ids = ','.join((str(item) for item in p.server.items.treasure if item in p.inventory)) owned_ids = ','.join((str(item) for item in p.server.items.treasure if item in p.inventory))
return await p.send_xt('rsc', 'treasurebook', 3, owned_ids, num_redeemed_codes) return await p.send_xt('rsc', 'treasurebook', 3, owned_ids, num_redeemed_codes)
if code[0].type == 'INNOCENT': if code.type == 'INNOCENT':
innocent_redeemed_items = { item for item in p.server.items.innocent if item.id in p.inventory } innocent_redeemed_items = { item for item in p.server.items.innocent if item.id in p.inventory }
innocent_redeemed_furniture = { item for item in p.server.furniture.innocent if item.id in p.furniture } innocent_redeemed_furniture = { item for item in p.server.furniture.innocent if item.id in p.furniture }
innocent_redeemed = innocent_redeemed_items.union(innocent_redeemed_furniture) innocent_redeemed = innocent_redeemed_items.union(innocent_redeemed_furniture)
@ -99,82 +171,174 @@ async def handle_code(p, redemption_code: str):
return await p.send_xt('rsc', 'INNOCENT', ','.join(map(str, awards)), return await p.send_xt('rsc', 'INNOCENT', ','.join(map(str, awards)),
len(innocent_redeemed) + len(choices), len(innocent_redeemed) + len(choices),
len(innocent_items)) len(innocent_items))
if code[0].type == 'GOLDEN':
if code.type == 'GOLDEN':
return await p.send_xt('rsc', 'GOLDEN', p.ninja_rank, p.fire_ninja_rank, p.water_ninja_rank, 0, return await p.send_xt('rsc', 'GOLDEN', p.ninja_rank, p.fire_ninja_rank, p.water_ninja_rank, 0,
int(p.fire_ninja_rank > 0), int(p.water_ninja_rank > 0), 0) int(p.fire_ninja_rank > 0), int(p.water_ninja_rank > 0), 0)
if code[0].type == 'CARD': if code.type == 'CARD':
for award in code[0].cards: for award in code.cards:
awards.append(str(award.card_id)) awards.append(str(award.card_id))
await p.add_card(p.server.cards[award.card_id]) await p.add_card(p.server.cards[award.card_id])
else: else:
if code[0].items: if code.items:
for award in code[0].items: for award in code.items:
awards.append(str(award.item_id)) awards.append(str(award.item_id))
await p.add_inventory(p.server.items[award.item_id], notify=False) await p.add_inventory(p.server.items[award.item_id], notify=False)
if code[0].furniture: if code.furniture:
for award in code[0].furniture: for award in code.furniture:
awards.append('f'+str(award.furniture_id)) awards.append('f'+str(award.furniture_id))
await p.add_furniture(p.server.furniture[award.furniture_id], notify=False) await p.add_furniture(p.server.furniture[award.furniture_id], notify=False)
if code[0].igloos: if code.igloos:
for award in code[0].igloos: for award in code.igloos:
awards.append('g'+str(award.igloo_id)) awards.append('g'+str(award.igloo_id))
await p.add_igloo(p.server.igloos[award.igloo_id], notify=False) await p.add_igloo(p.server.igloos[award.igloo_id], notify=False)
if code[0].locations: if code.locations:
for award in code[0].locations: for award in code.locations:
awards.append('loc'+str(award.location_id)) awards.append('loc'+str(award.location_id))
await p.add_location(p.server.locations[award.location_id], notify=False) await p.add_location(p.server.locations[award.location_id], notify=False)
if code[0].flooring: if code.flooring:
for award in code[0].flooring: for award in code.flooring:
awards.append('flr'+str(award.flooring_id)) awards.append('flr'+str(award.flooring_id))
await p.add_flooring(p.server.flooring[award.flooring_id], notify=False) await p.add_flooring(p.server.flooring[award.flooring_id], notify=False)
if code[0].puffles: if code.puffles:
for award in code[0].puffles: for award in code[0].puffles:
awards.append('p'+str(award.puffle_id)) awards.append('p'+str(award.puffle_id))
if code[0].puffle_items: if code.puffle_items:
for award in code[0].puffle_items: for award in code.puffle_items:
awards.append('pi'+str(award.puffle_item_id)) awards.append('pi'+str(award.puffle_item_id))
await p.add_puffle_item(p.server.puffle_items[award.puffle_item_id], notify=False) await p.add_puffle_item(p.server.puffle_items[award.puffle_item_id], notify=False)
await PenguinRedemptionCode.create(penguin_id=p.id, code_id=code[0].id) await PenguinRedemptionCode.create(penguin_id=p.id, code_id=code.id)
await p.update(coins=p.coins + code[0].coins).apply() await p.update(coins=p.coins + code.coins).apply()
coins = "" if code[0].coins == 0 else code[0].coins coins = "" if code.coins == 0 else code.coins
return await p.send_xt('rsc', code[0].type, ','.join(map(str, awards)), coins) return await p.send_xt('rsc', code.type, ','.join(map(str, awards)), coins)
@handlers.handler(XTPacket('rsgc', ext='red'), pre_login=True) @handlers.handler(XTPacket('rsgc', ext='red'), pre_login=True)
@handlers.depends_on_packet(XTPacket('rsc', ext='red')) @handlers.depends_on_packet(XTPacket('rsc', ext='red'))
async def handle_golden_choice(p, redemption_code: str, choice: int): async def handle_golden_choice(p, redemption_code: str, choice: int):
query = RedemptionCode.distinct(RedemptionCode.id)\ query = RedemptionCode.distinct(RedemptionCode.id)\
.load(cards=RedemptionAwardCard.distinct(RedemptionAwardCard.card_id)
)\
.query.where(RedemptionCode.code == redemption_code)
codes = await query.gino.all()
if not codes:
return await p.close()
code = codes[0]
if len(code.cards) < 6:
return await p.close()
penguin_redeemed = await PenguinRedemptionCode.query.where((PenguinRedemptionCode.code_id == code.id) & (PenguinRedemptionCode.penguin_id == p.id)).gino.scalar()
if penguin_redeemed:
return await p.close()
card_ids = [card.card_id for card in code.cards]
if choice == 1:
await ninja_rank_up(p)
await p.send_xt('rsgc', ','.join(map(str, card_ids[:4])) + '|' + str(p.ninja_rank))
elif choice == 2:
await p.send_xt('rsgc', ','.join(map(str, card_ids[:4])) + '|' + ','.join(map(str, card_ids[-2:])))
for card in code.cards:
await p.add_card(p.server.cards[card.card_id])
if code.uses is None:
await PenguinRedemptionCode.create(penguin_id=p.id, code_id=code.id)
@handlers.handler(XTPacket('rscrt', ext='red'), pre_login=True)
@handlers.depends_on_packet(XTPacket('rsc', ext='red'))
async def handle_send_cart(p, redemption_code: str, choice: str, super_exclusive: int):
query = RedemptionCode.distinct(RedemptionCode.id) \
.load(cards=RedemptionAwardCard.distinct(RedemptionAwardCard.card_id), .load(cards=RedemptionAwardCard.distinct(RedemptionAwardCard.card_id),
items=RedemptionAwardItem.distinct(RedemptionAwardItem.item_id), items=RedemptionAwardItem.distinct(RedemptionAwardItem.item_id),
flooring=RedemptionAwardFlooring.distinct(RedemptionAwardFlooring.flooring_id),
furniture=RedemptionAwardFurniture.distinct(RedemptionAwardFurniture.furniture_id), furniture=RedemptionAwardFurniture.distinct(RedemptionAwardFurniture.furniture_id),
igloos=RedemptionAwardIgloo.distinct(RedemptionAwardIgloo.igloo_id), igloos=RedemptionAwardIgloo.distinct(RedemptionAwardIgloo.igloo_id),
locations=RedemptionAwardLocation.distinct(RedemptionAwardLocation.location_id), locations=RedemptionAwardLocation.distinct(RedemptionAwardLocation.location_id),
puffles=RedemptionAwardPuffle.distinct(RedemptionAwardPuffle.puffle_id), puffles=RedemptionAwardPuffle.distinct(RedemptionAwardPuffle.puffle_id),
puffle_items=RedemptionAwardPuffleItem.distinct(RedemptionAwardPuffleItem.puffle_item_id) puffle_items=RedemptionAwardPuffleItem.distinct(RedemptionAwardPuffleItem.puffle_item_id)
)\ ) \
.query.where(RedemptionCode.code == redemption_code) .query.where(RedemptionCode.code == redemption_code)
code = await query.gino.all() codes = await query.gino.all()
code = codes[0]
if len(code[0].cards) < 6: coins = 0
if choice is None:
return await p.close() return await p.close()
penguin_redeemed = await PenguinRedemptionCode.query.where((PenguinRedemptionCode.code_id == code[0].id) & (PenguinRedemptionCode.penguin_id == p.id)).gino.scalar() choices = choice.split(',')
print(choices)
for choice in choices:
if choice[:2] == 'c0':
coins += 500
if penguin_redeemed: elif choice[:1] != 'p':
if int(choice) not in p.server.items:
return await p.close()
else:
print('Adding', int(choice))
await p.add_inventory(p.server.items[int(choice)], notify=False)
# if int(choice) not in p.server.items.treasure:
# return await p.close()
# else:
# await p.add_inventory(p.server.items[choice], notify=False)
while 'c0' in choices:
choices.remove('c0')
if code.uses is None:
await PenguinRedemptionCode.create(penguin_id=p.id, code_id=code.id)
if coins == 0:
coins = ''
else:
await p.update(coins=p.coins + coins).apply()
await p.send_xt('rscrt', ','.join(choices), coins)
@handlers.handler(XTPacket('rsp', ext='red'), pre_login=True)
@handlers.depends_on_packet(XTPacket('rsc', ext='red'))
async def handle_redeem_puffle(p, name: str, id: int):
if name is None or id is None:
return await p.close() return await p.close()
if id not in p.server.puffles:
return await p.close()
if not 16 > len(name) >= 3:
await p.send_xt('rsp', 0)
if len(p.puffles) >= 75:
return await p.send_error(440)
await p.add_puffle_item(p.server.puffle_items[3], quantity=5, cost=0)
await p.add_puffle_item(p.server.puffle_items[79], cost=0)
await p.add_puffle_item(p.server.puffle_items[p.server.puffles[puffle_id].favourite_toy])
puffle = await p.puffles.insert(puffle_id=id, name=name)
await p.add_inbox(p.server.postcards[111], details=puffle.name)
await p.send_xt('rsp', 1)
# change book ids to correct order? 1, 2, 4