[wip4] Room preview generation improvements + Room checking with user email

This commit is contained in:
Andrea Carulli 2024-01-18 18:03:32 +01:00
parent 6fe87b6ea1
commit aa54032492
11 changed files with 201 additions and 73 deletions

View File

@ -1,5 +1,5 @@
from email.mime.text import MIMEText
from sanic import response, redirect, Blueprint, exceptions from sanic import response, redirect, Blueprint, exceptions
from room import unconfirm_room_by_order
from config import * from config import *
from utils import * from utils import *
from ext import * from ext import *
@ -12,7 +12,7 @@ import json
bp = Blueprint("admin", url_prefix="/manage/admin") bp = Blueprint("admin", url_prefix="/manage/admin")
def credentialsCheck(request, order:Order): def credentials_check(request, order:Order):
if not order: if not order:
raise exceptions.Forbidden("You have been logged out. Please access the link in your E-Mail to login again!") raise exceptions.Forbidden("You have been logged out. Please access the link in your E-Mail to login again!")
if EXTRA_PRINTS: if EXTRA_PRINTS:
@ -22,15 +22,15 @@ def credentialsCheck(request, order:Order):
@bp.get('/cache/clear') @bp.get('/cache/clear')
async def clearCache(request, order:Order): async def clear_cache(request, order:Order):
credentialsCheck(request, order) credentials_check(request, order)
await request.app.ctx.om.fill_cache() await request.app.ctx.om.fill_cache()
return redirect(f'/manage/admin') return redirect(f'/manage/admin')
@bp.get('/loginas/<code>') @bp.get('/loginas/<code>')
async def loginAs(request, code, order:Order): async def login_as(request, code, order:Order):
credentialsCheck(request, order) credentials_check(request, order)
dOrder = await getOrderByCode(request, code, throwException=True) dOrder = await get_order_by_code(request, code, throwException=True)
if(dOrder.isAdmin()): if(dOrder.isAdmin()):
raise exceptions.Forbidden("You can't login as another admin!") raise exceptions.Forbidden("You can't login as another admin!")
@ -44,26 +44,18 @@ async def loginAs(request, code, order:Order):
return r return r
@bp.get('/room/unconfirm/<code>') @bp.get('/room/unconfirm/<code>')
async def unconfirmRoom(request, code, order:Order): async def unconfirm_room(request, code, order:Order):
credentialsCheck(request, order) credentials_check(request, order)
dOrder = await getOrderByCode(request, code, throwException=True) dOrder = await get_order_by_code(request, code, throwException=True)
unconfirm_room_by_order(dOrder, True, request)
if(not dOrder.room_confirmed):
raise exceptions.BadRequest("Room is not confirmed!")
ppl = getPeopleInRoomByRoomId(request, code)
for p in ppl:
await p.edit_answer('room_confirmed', "False")
await p.send_answers()
return redirect(f'/manage/nosecount') return redirect(f'/manage/nosecount')
@bp.get('/room/delete/<code>') @bp.get('/room/delete/<code>')
async def deleteRoom(request, code, order:Order): async def delete_room(request, code, order:Order):
credentialsCheck(request, order) credentials_check(request, order)
dOrder = await getOrderByCode(request, code, throwException=True) dOrder = await get_order_by_code(request, code, throwException=True)
ppl = getPeopleInRoomByRoomId(request, code) ppl = get_people_in_room_by_code(request, code)
for p in ppl: for p in ppl:
await p.edit_answer('room_id', None) await p.edit_answer('room_id', None)
await p.edit_answer('room_confirmed', "False") await p.edit_answer('room_confirmed', "False")
@ -79,9 +71,9 @@ async def deleteRoom(request, code, order:Order):
return redirect(f'/manage/nosecount') return redirect(f'/manage/nosecount')
@bp.post('/room/rename/<code>') @bp.post('/room/rename/<code>')
async def renameRoom(request, code, order:Order): async def rename_room(request, code, order:Order):
credentialsCheck(request, order) credentials_check(request, order)
dOrder = await getOrderByCode(request, code, throwException=True) dOrder = await get_order_by_code(request, code, throwException=True)
name = request.form.get('name') name = request.form.get('name')
if len(name) > 64 or len(name) < 4: if len(name) > 64 or len(name) < 4:

8
ext.py
View File

@ -65,7 +65,7 @@ class Order:
self.has_card = True self.has_card = True
if p['item'] == ITEMS_ID_MAP['sponsorship_item']: if p['item'] == ITEMS_ID_MAP['sponsorship_item']:
sponsorshipType = keyFromValue(ITEM_VARIATIONS_MAP['sponsorship_item'], p['variation']) sponsorshipType = key_from_value(ITEM_VARIATIONS_MAP['sponsorship_item'], p['variation'])
self.sponsorship = sponsorshipType[0].replace ('sponsorship_item_', '') if len(sponsorshipType) > 0 else None self.sponsorship = sponsorshipType[0].replace ('sponsorship_item_', '') if len(sponsorshipType) > 0 else None
if p['attendee_name']: if p['attendee_name']:
@ -79,7 +79,7 @@ class Order:
self.has_late = True self.has_late = True
if p['item'] == ITEMS_ID_MAP['bed_in_room']: if p['item'] == ITEMS_ID_MAP['bed_in_room']:
roomTypeLst = keyFromValue(ITEM_VARIATIONS_MAP['bed_in_room'], p['variation']) roomTypeLst = key_from_value(ITEM_VARIATIONS_MAP['bed_in_room'], p['variation'])
roomTypeId = roomTypeLst[0] if len(roomTypeLst) > 0 else None roomTypeId = roomTypeLst[0] if len(roomTypeLst) > 0 else None
self.bed_in_room = p['variation'] self.bed_in_room = p['variation']
self.room_person_no = ROOM_CAPACITY_MAP[roomTypeId] if roomTypeId in ROOM_CAPACITY_MAP else None self.room_person_no = ROOM_CAPACITY_MAP[roomTypeId] if roomTypeId in ROOM_CAPACITY_MAP else None
@ -270,8 +270,8 @@ class OrderManager:
self.order_list.remove(code) self.order_list.remove(code)
async def fill_cache(self): async def fill_cache(self):
await loadItems() await load_items()
await loadQuestions() await load_questions()
self.empty() self.empty()
p = 0 p = 0

6
messages.py Normal file
View File

@ -0,0 +1,6 @@
ROOM_ERROR_MESSAGES = {
'room_id_mismatch': "There's a member in your room that is actually in another room, too. Please contact us as soon as possible in order to fix this issue.",
'unpaid': "Somebody in your room has not paid for their reservation, yet.",
'type_mismatch': "A member in your room has a ticket for a different type of room capacity. This happens when users swap their room types with others, without abandoning the room.",
'daily': "Some member in your room has a Daily ticket. These tickets do not include a hotel reservation"
}

BIN
res/font/NotoSans-Bold.ttf Normal file

Binary file not shown.

1
res/icons/share.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18,16.08C17.24,16.08 16.56,16.38 16.04,16.85L8.91,12.7C8.96,12.47 9,12.24 9,12C9,11.76 8.96,11.53 8.91,11.3L15.96,7.19C16.5,7.69 17.21,8 18,8A3,3 0 0,0 21,5A3,3 0 0,0 18,2A3,3 0 0,0 15,5C15,5.24 15.04,5.47 15.09,5.7L8.04,9.81C7.5,9.31 6.79,9 6,9A3,3 0 0,0 3,12A3,3 0 0,0 6,15C6.79,15 7.5,14.69 8.04,14.19L15.16,18.34C15.11,18.55 15.08,18.77 15.08,19C15.08,20.61 16.39,21.91 18,21.91C19.61,21.91 20.92,20.61 20.92,19A2.92,2.92 0 0,0 18,16.08Z" /></svg>

After

Width:  |  Height:  |  Size: 521 B

152
room.py
View File

@ -1,3 +1,6 @@
from email.mime.text import MIMEText
from messages import ROOM_ERROR_MESSAGES
import smtplib
from sanic.response import html, redirect, text from sanic.response import html, redirect, text
from sanic import Blueprint, exceptions from sanic import Blueprint, exceptions
from random import choice from random import choice
@ -207,8 +210,8 @@ async def approve_roomreq(request, code, order: Order):
await order.edit_answer('pending_roommates', (','.join([x for x in order.pending_roommates if x != pending_member.code]) or None)) await order.edit_answer('pending_roommates', (','.join([x for x in order.pending_roommates if x != pending_member.code]) or None))
await pending_member.send_answers() await pending_member.send_answers()
await order.send_answers() await order.send_answers(order.code)
remove_room_preview()
return redirect('/manage/welcome') return redirect('/manage/welcome')
@bp.route("/leave") @bp.route("/leave")
@ -232,7 +235,7 @@ async def leave_room(request, order: Order):
await room_owner.send_answers() await room_owner.send_answers()
await order.send_answers() await order.send_answers()
remove_room_preview (order.room_id)
return redirect('/manage/welcome') return redirect('/manage/welcome')
@bp.route("/reject/<code>") @bp.route("/reject/<code>")
@ -288,7 +291,7 @@ async def rename_room(request, order: Order):
await order.edit_answer("room_name", name) await order.edit_answer("room_name", name)
await order.send_answers() await order.send_answers()
remove_room_preview (order.code) remove_room_preview(order.code)
return redirect('/manage/welcome') return redirect('/manage/welcome')
@bp.route("/confirm") @bp.route("/confirm")
@ -357,6 +360,78 @@ async def confirm_room(request, order: Order, quotas: Quotas):
return redirect('/manage/welcome') return redirect('/manage/welcome')
async def unconfirm_room_by_order(order, throw=True, request=None):
if not order.room_confirmed and throw:
raise exceptions.BadRequest("Room is not confirmed!")
ppl = get_people_in_room_by_code(request, order.code)
for p in ppl:
await p.edit_answer('room_confirmed', "False")
await p.send_answers()
async def validate_room(request, order):
check, room_errors, member_orders = await check_room(request, order)
if check == True: return
try:
# Build message
issues_str = ""
for err in room_errors:
if err in ROOM_ERROR_MESSAGES:
issues_str += f" - {ROOM_ERROR_MESSAGES['err']}"
memberMessages = []
for member in member_orders:
msg = MIMEText(f"Hello {member.name}!\n\nWe had to unconfirm your room {order.room_name} due to th{'ese issues' if len(room_errors) > 1 else 'is issue'}:\n{issues_str}\n\nPlease contact your room's owner or contact our support for further informations at https://furizon.net/contact/.\nThank you")
msg['Subject'] = '[Furizon] Your room cannot be confirmed'
msg['From'] = 'Furizon <no-reply@furizon.net>'
msg['To'] = f"{member.name} <{member.email}>"
memberMessages.append(msg)
if (len(memberMessages) == 0): return
s = smtplib.SMTP_SSL(SMTP_HOST)
s.login(SMTP_USER, SMTP_PASSWORD)
for message in memberMessages:
s.sendmail(message['From'], message['to'], message.as_string())
s.quit()
except Exception as ex:
if EXTRA_PRINTS: print(ex)
async def check_room(request, order):
room_errors = []
room_members = []
if not order or not order.room_id or order.room_id != order.code: return False, room_errors, room_members
# This is not needed anymore you buy tickets already
#if quotas.get_left(len(order.room_members)) == 0:
# raise exceptions.BadRequest("There are no more rooms of this size to reserve.")
bed_in_room = order.bed_in_room # Variation id of the ticket for that kind of room
for m in order.room_members:
if m == order.code:
res = order
else:
res = await request.app.ctx.om.get_order(code=m)
# Room user in another room
if res.room_id != order.code:
room_errors.append('room_id_mismatch')
if res.status != 'paid':
room_errors.append('unpaid')
if res.bed_in_room != bed_in_room:
room_errors.append('type_mismatch')
if res.daily:
room_errors.append('daily')
room_members.append(res)
if len(room_members) != order.room_person_no and order.room_person_no != None:
room_errors.append('capacity_mismatch')
return len(room_errors) == 0, room_errors, room_members
async def get_room (request, code): async def get_room (request, code):
order_data = await request.app.ctx.om.get_order(code=code) order_data = await request.app.ctx.om.get_order(code=code)
if not order_data or not order_data.room_owner: return None if not order_data or not order_data.room_owner: return None
@ -369,6 +444,7 @@ async def get_room (request, code):
return {'name': order_data.room_name, return {'name': order_data.room_name,
'confirmed': order_data.room_confirmed, 'confirmed': order_data.room_confirmed,
'capacity': order_data.room_person_no, 'capacity': order_data.room_person_no,
'free_spots': order_data.room_person_no - len(members_map),
'members': members_map} 'members': members_map}
async def get_room_with_order (request, code): async def get_room_with_order (request, code):
@ -382,35 +458,67 @@ def remove_room_preview(code):
except Exception as ex: except Exception as ex:
if (EXTRA_PRINTS): print(ex) if (EXTRA_PRINTS): print(ex)
def draw_profile (source, member, position, font, size=(170, 170), border_width=5):
idraw = ImageDraw.Draw(source)
source_size = source.size
main_fill = (187, 198, 206)
propic_x = position[0]
propic_y = (source_size[1] // 2) - (size[1] // 2)
border_loc = (propic_x, propic_y, propic_x + size[0] + border_width * 2, propic_y + size[1] + border_width *2)
profile_location = (propic_x + border_width, propic_y + border_width)
propic_name_y = propic_y + size[1] + border_width + 20
border_color = SPONSORSHIP_COLOR_MAP[member['sponsorship']] if member['sponsorship'] in SPONSORSHIP_COLOR_MAP.keys() else (84, 110, 122)
# Draw border
idraw.rounded_rectangle(border_loc, border_width, border_color)
# Draw profile picture
with Image.open(f'res/propic/{member['propic'] or 'default.png'}') as to_add:
source.paste(to_add.resize (size), profile_location)
name_len = idraw.textlength(str(member['name']), font)
calc_size = 0
if name_len > size[0]:
calc_size = size[0] * 20 / name_len if name_len > size[0] else 20
font = ImageFont.truetype(font.path, calc_size)
name_len = idraw.textlength(str(member['name']), font)
name_loc = (position[0] + ((size[0] / 2) - name_len / 2), propic_name_y + (calc_size/2))
name_color = SPONSORSHIP_COLOR_MAP[member['sponsorship']] if member['sponsorship'] in SPONSORSHIP_COLOR_MAP.keys() else main_fill
idraw.text(name_loc, str(member['name']), font=font, fill=name_color)
async def generate_room_preview(request, code, room_data): async def generate_room_preview(request, code, room_data):
font_path = f'res/font/pt-serif-caption-latin-400-normal.ttf' font_path = f'res/font/NotoSans-Bold.ttf'
main_fill = (16, 149, 193) main_fill = (187, 198, 206)
propic_size = (170, 170)
logo_size = (200, 43)
border_width = 5
propic_gap = 50
propic_width = propic_size[0] + (border_width * 2)
propic_total_width = propic_width + propic_gap
jobs.append(code) jobs.append(code)
try: try:
room_data = await get_room(request, code) if not room_data else room_data room_data = await get_room(request, code) if not room_data else room_data
width = 230 * int(room_data['capacity']) + 130 if not room_data: return
width = max([(propic_width + propic_gap) * int(room_data['capacity']) + propic_gap, 670])
height = int(width * 0.525)
font = ImageFont.truetype(font_path, 20) font = ImageFont.truetype(font_path, 20)
with Image.new('RGB', (width, 270), (17, 25, 31)) as to_save:
i_draw = ImageDraw.Draw(to_save) # Recalculate gap
propic_gap = (width - (propic_width * int(room_data['capacity']))) // (int(room_data['capacity']) + 1)
propic_total_width = propic_width + propic_gap
# Define output image
with Image.new('RGB', (width, height), (17, 25, 31)) as source:
# Draw logo
with (Image.open('res/furizon.png') as logo, logo.resize(logo_size).convert('RGBA') as resized_logo):
source.paste(resized_logo, ((source.size[0] // 2) - (logo_size[0] // 2), 10), resized_logo)
i_draw = ImageDraw.Draw(source)
# Draw room's name # Draw room's name
room_name_len = i_draw.textlength(room_data['name'], font) room_name_len = i_draw.textlength(room_data['name'], font)
i_draw.text((((width / 2) - room_name_len / 2), 10), room_data['name'], font=font, fill=main_fill) i_draw.text((((width / 2) - room_name_len / 2), 55), room_data['name'], font=font, fill=main_fill)
# Draw members # Draw members
for m in range (room_data['capacity']): for m in range (room_data['capacity']):
member = room_data['members'][m] if m < len(room_data['members']) else { 'name': 'Empty', 'propic': '../new.png', 'sponsorship': None } member = room_data['members'][m] if m < len(room_data['members']) else { 'name': 'Empty', 'propic': '../new.png', 'sponsorship': None }
font = ImageFont.truetype(font_path, 20) font = ImageFont.truetype(font_path, 20)
with Image.open(f'res/propic/{member['propic'] or 'default.png'}') as to_add: draw_profile(source, member, (propic_gap + (propic_total_width * m), 63), font, propic_size, border_width)
to_save.paste(to_add.resize ((180, 180)), (90 + (230 * m), 45)) source.save(f'res/rooms/{code}.jpg', 'JPEG', quality=60)
name_len = i_draw.textlength(str(member['name']), font)
calc_size = 0
if name_len > 180:
calc_size = 180 * 20 / name_len if name_len > 180 else 20
font = ImageFont.truetype(font_path, calc_size)
name_len = i_draw.textlength(str(member['name']), font)
name_loc = ((90 + (230 * m)) + (90 - name_len / 2), 235 + (calc_size/2))
name_color = SPONSORSHIP_COLOR_MAP[member['sponsorship']] if member['sponsorship'] in SPONSORSHIP_COLOR_MAP.keys() else main_fill
i_draw.text(name_loc, str(member['name']), font=font, fill=name_color)
to_save.save(f'res/rooms/{code}.jpg', 'JPEG')
except Exception as err: except Exception as err:
if EXTRA_PRINTS: print(err) if EXTRA_PRINTS: print(err)
finally: finally:

View File

@ -1,5 +1,13 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}Furizon 2024 Nosecount{% endblock %} {% block title %}Furizon 2024 Nosecount{% endblock %}
{% block head %}
<meta property="og:title" content="Nose count - Furizon" />
<meta property="og:image:type" content="image/jpeg" />
<meta property="og:image:alt" content="Furizon logo" />
<meta property="og:image" content="https://reg.furizon.net/res/furizon.png" />
<meta property="og:image:secure_url" content="https://reg.furizon.net/res/furizon.png" />
<meta property="og:description" content="Explore this year's rooms, find your friends and plan your meet-ups."/>
{% endblock %}
{% block main %} {% block main %}
<main class="container"> <main class="container">
{% if order and order.isAdmin() %} {% if order and order.isAdmin() %}

View File

@ -1,5 +1,13 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}Furizon 2024 Sponsorcount{% endblock %} {% block title %}Furizon 2024 Sponsorcount{% endblock %}
{% block head %}
<meta property="og:title" content="Sponsor count - Furizon" />
<meta property="og:image:type" content="image/jpeg" />
<meta property="og:image:alt" content="Furizon logo" />
<meta property="og:image" content="https://reg.furizon.net/res/furizon.png" />
<meta property="og:image:secure_url" content="https://reg.furizon.net/res/furizon.png" />
<meta property="og:description" content="Thanks to all the amazing furs who decided to support us this year ❤️"/>
{% endblock %}
{% block main %} {% block main %}
<main class="container"> <main class="container">
<header> <header>

View File

@ -2,9 +2,14 @@
{% block title %}{{room_data['name']}}{% endblock %} {% block title %}{{room_data['name']}}{% endblock %}
{% block head %} {% block head %}
<!--Open Graph tags here--> <!--Open Graph tags here-->
<meta property="og:title" content="{{room_data['name']}}" /> <meta property="og:title" content="View room - Furizon" />
<meta property="og:image:type" content="image/jpeg" /> <meta property="og:image:type" content="image/jpeg" />
<meta property="og:image:alt" content="View of a room" /> <meta property="og:image:alt" content="View of a room" />
<meta property="og:image" content="http://localhost:8188/{{preview}}" />
<meta property="og:image:secure_url" content="http://localhost:8188/{{preview}}" />
<meta property="og:image:width" content="{{230 * room_data['capacity'] + 130}}"/>
<meta property="og:image:height" content="270"/>
<meta property="og:description" content="Room {{room_data['name']}} has {{'been confirmed.' if room_data['confirmed'] else ('been filled.' if room_data['free_spots'] == 0 else (room_data['free_spots'] | string) + ' free spots out of ' + (room_data['capacity'] | string )) }}"/>
{% endblock %} {% endblock %}
{% block main %} {% block main %}
<main class="container"> <main class="container">
@ -12,7 +17,7 @@
<picture> <picture>
<source srcset="/res/furizon.png" media="(prefers-color-scheme:dark)"> <source srcset="/res/furizon.png" media="(prefers-color-scheme:dark)">
<img src="/res/furizon-light.png" style="height:4rem;text-align:center;" <img src="/res/furizon-light.png" style="height:4rem;text-align:center;"
onload="window.location.href='/manage/nosecount';"> >
</picture> </picture>
</header> </header>
</main> </main>

View File

@ -23,7 +23,7 @@ QUESTION_TYPES = { #https://docs.pretix.eu/en/latest/api/resources/questions.htm
TYPE_OF_QUESTIONS = {} # maps questionId -> type TYPE_OF_QUESTIONS = {} # maps questionId -> type
async def loadQuestions(): async def load_questions():
global TYPE_OF_QUESTIONS global TYPE_OF_QUESTIONS
TYPE_OF_QUESTIONS.clear() TYPE_OF_QUESTIONS.clear()
async with httpx.AsyncClient() as client: async with httpx.AsyncClient() as client:
@ -38,7 +38,7 @@ async def loadQuestions():
for q in data['results']: for q in data['results']:
TYPE_OF_QUESTIONS[q['id']] = q['type'] TYPE_OF_QUESTIONS[q['id']] = q['type']
async def loadItems(): async def load_items():
global ITEMS_ID_MAP global ITEMS_ID_MAP
global ITEM_VARIATIONS_MAP global ITEM_VARIATIONS_MAP
global CATEGORIES_LIST_MAP global CATEGORIES_LIST_MAP
@ -54,14 +54,14 @@ async def loadItems():
data = res.json() data = res.json()
for q in data['results']: for q in data['results']:
# Map item id # Map item id
itemName = checkAndGetName ('item', q) itemName = check_and_get_name ('item', q)
if itemName and itemName in ITEMS_ID_MAP: if itemName and itemName in ITEMS_ID_MAP:
ITEMS_ID_MAP[itemName] = q['id'] ITEMS_ID_MAP[itemName] = q['id']
# If item has variations, map them, too # If item has variations, map them, too
if itemName in ITEM_VARIATIONS_MAP and VARIATIONS_TAG in q: if itemName in ITEM_VARIATIONS_MAP and VARIATIONS_TAG in q:
isBedInRoom = itemName == 'bed_in_room' isBedInRoom = itemName == 'bed_in_room'
for v in q[VARIATIONS_TAG]: for v in q[VARIATIONS_TAG]:
variationName = checkAndGetName('variation', v) variationName = check_and_get_name('variation', v)
if variationName and variationName in ITEM_VARIATIONS_MAP[itemName]: if variationName and variationName in ITEM_VARIATIONS_MAP[itemName]:
ITEM_VARIATIONS_MAP[itemName][variationName] = v['id'] ITEM_VARIATIONS_MAP[itemName][variationName] = v['id']
if isBedInRoom and variationName in ITEM_VARIATIONS_MAP['bed_in_room']: if isBedInRoom and variationName in ITEM_VARIATIONS_MAP['bed_in_room']:
@ -70,7 +70,7 @@ async def loadItems():
roomName = v['value'][list(v['value'].keys())[0]] roomName = v['value'][list(v['value'].keys())[0]]
ROOM_TYPE_NAMES[v['id']] = roomName ROOM_TYPE_NAMES[v['id']] = roomName
# Adds itself to the category list # Adds itself to the category list
categoryName = checkAndGetCategory ('item', q) categoryName = check_and_get_category ('item', q)
if not categoryName: continue if not categoryName: continue
CATEGORIES_LIST_MAP[categoryName].append(q['id']) CATEGORIES_LIST_MAP[categoryName].append(q['id'])
if (EXTRA_PRINTS): if (EXTRA_PRINTS):
@ -84,38 +84,38 @@ async def loadItems():
print (ROOM_TYPE_NAMES) print (ROOM_TYPE_NAMES)
# Tries to get an item name from metadata. Prints a warning if an item has no metadata # Tries to get an item name from metadata. Prints a warning if an item has no metadata
def checkAndGetName(type, q): def check_and_get_name(type, q):
itemName = extractMetadataName(q) itemName = extract_metadata_name(q)
if not itemName and EXTRA_PRINTS: if not itemName and EXTRA_PRINTS:
print (type + ' ' + q['id'] + ' has not been mapped.') print (type + ' ' + q['id'] + ' has not been mapped.')
return itemName return itemName
def checkAndGetCategory (type, q): def check_and_get_category (type, q):
categoryName = extractCategory (q) categoryName = extract_category (q)
if not categoryName and EXTRA_PRINTS: if not categoryName and EXTRA_PRINTS:
print (type + ' ' + q['id'] + ' has no category set.') print (type + ' ' + q['id'] + ' has no category set.')
return categoryName return categoryName
# Checks if the item has specified metadata name # Checks if the item has specified metadata name
def internalNameCheck (toExtract, name): def internal_name_check (toExtract, name):
return toExtract and name and METADATA_TAG in toExtract and toExtract[METADATA_TAG][METADATA_NAME] == str(name) return toExtract and name and METADATA_TAG in toExtract and toExtract[METADATA_TAG][METADATA_NAME] == str(name)
# Returns the item_name metadata from the item or None if not defined # Returns the item_name metadata from the item or None if not defined
def extractMetadataName (toExtract): def extract_metadata_name (toExtract):
return extractData(toExtract, [METADATA_TAG, METADATA_NAME]) return extract_data(toExtract, [METADATA_TAG, METADATA_NAME])
# Returns the category_name metadata from the item or None if not defined # Returns the category_name metadata from the item or None if not defined
def extractCategory (toExtract): def extract_category (toExtract):
return extractData(toExtract, [METADATA_TAG, METADATA_CATEGORY]) return extract_data(toExtract, [METADATA_TAG, METADATA_CATEGORY])
def extractData (dataFrom, tags): def extract_data (dataFrom, tags):
data = dataFrom data = dataFrom
for t in tags: for t in tags:
if t not in data: return None if t not in data: return None
data = data[t] data = data[t]
return data return data
def keyFromValue(dict, value): def key_from_value(dict, value):
return [k for k,v in dict.items() if v == value] return [k for k,v in dict.items() if v == value]
def sizeof_fmt(num, suffix="B"): def sizeof_fmt(num, suffix="B"):
@ -125,7 +125,7 @@ def sizeof_fmt(num, suffix="B"):
num /= 1000.0 num /= 1000.0
return f"{num:.1f}Yi{suffix}" return f"{num:.1f}Yi{suffix}"
async def getOrderByCode(request, code, throwException=False): async def get_order_by_code(request, code, throwException=False):
res = await request.app.ctx.om.get_order(code=code) res = await request.app.ctx.om.get_order(code=code)
if not throwException: if not throwException:
return res return res
@ -133,10 +133,10 @@ async def getOrderByCode(request, code, throwException=False):
raise exceptions.BadRequest(f"[getOrderByCode] Code {code} not found!") raise exceptions.BadRequest(f"[getOrderByCode] Code {code} not found!")
return res return res
def getPeopleInRoomByRoomId(request, roomId): def get_people_in_room_by_code(request, code):
c = request.app.ctx.om.cache c = request.app.ctx.om.cache
ret = [] ret = []
for person in c.values(): for person in c.values():
if person.room_id == roomId: if person.room_id == code:
ret.append(person) ret.append(person)
return ret return ret