forked from summertriangle-dev/sparklebox
-
Notifications
You must be signed in to change notification settings - Fork 2
/
webutil.py
126 lines (100 loc) · 4.03 KB
/
webutil.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import tornado.escape
import hashlib
import base64
import os
import starlight
import enums
import struct
import hmac
def tlable_make_assr(text):
salt = os.getenv("TLABLE_SALT").encode("utf8")
return base64.b64encode(hmac.new(salt, text.encode("utf8"), hashlib.sha224).digest()).decode("utf8")
def tlable(text, write=1):
text = text.replace("\n", " ")
if write:
return """<span class="tlable" data-summertriangle-assr="{1}">{0}</span>""".format(
tornado.escape.xhtml_escape(text), tlable_make_assr(text))
else:
return """<span class="tlable">{0}</span>""".format(
tornado.escape.xhtml_escape(text))
def icon(css_class):
return """<div class="icon icon_{0}"></div>""".format(css_class)
def icon_ex(card_id, is_lowbw=0, collapsible=0, classes=""):
rec = starlight.data.card(card_id)
if not rec:
btext = "(?) bug:{0}".format(card_id)
ish = """<div class="profile {1}">
<div class="icon icon_unknown"></div>
<div class="profile_text {0}"><b>Mysterious Kashikoi Person</b><br>{btext}</div>
</div>""".format("hides_under_mobile" if collapsible else "", classes, btext=btext)
return """<a class="noline">{ish}</a>""".format(ish=ish)
else:
if not is_lowbw:
link = "/char/{rec.chara_id}#c_{rec.id}_head".format(rec=rec)
else:
link = "/card/{rec.id}".format(rec=rec)
btext = "({0}) {1}".format(enums.rarity(rec.rarity), tlable(rec.title, write=0) if rec.title_flag else "")
ish = """<div class="profile {4}">
<div class="icon icon_{rec.id} msprites {1}_sm {2}_sm"></div>
<div class="profile_text {3}"><b>{0}</b><br>{btext}</div>
</div>""".format(tornado.escape.xhtml_escape(rec.chara.name),#chara.conventional
enums.stat_dot(rec.best_stat),
enums.skill_class(rec.skill.skill_type) if rec.skill else "none",
"hides_under_mobile" if collapsible else "",
classes,
rec=rec, btext=btext)
return """<a href="{link}" class="noline">{ish}</a>""".format(rec=rec, ish=ish, link=link)
def audio(object_id, use, index):
a = (object_id << 40) | ((use & 0xFF) << 24) | ((index & 0xFF) << 16) | 0x11AB
# make everything 8 bytes long for reasons
a &= 0xFFFFFFFFFFFFFFFF
a ^= 0x1042FC1040200700
basename = hex(a)[2:]
return "va2/{0}.mp3".format(basename)
SHORT_MAX_ENCODABLE_ATTR = 3
SHORT_MAX_ENCODABLE_UNIQ = 8191
def encode_card_id_short(id_):
attr_part = id_ // 100000
if attr_part > SHORT_MAX_ENCODABLE_ATTR:
return encode_card_id_long(id_)
uniq_part = id_ % 100000
if uniq_part > SHORT_MAX_ENCODABLE_UNIQ:
return encode_card_id_long(id_)
pack = (0b1000000000000000 |
attr_part << 13 |
uniq_part )
return struct.pack(">H", pack)
def encode_card_id_long(id_):
if id_ >= 2 ** 31:
raise ValueError("unencodable id")
return struct.pack(">I", id_)
def encode_cardlist(ids):
return base64.urlsafe_b64encode(b"".join(encode_card_id_short(x) for x in ids)).decode("ascii")
def encode_card_structs(cards):
return encode_cardlist(card.id for card in cards)
def decode_card_id_short(the_id):
packv, = struct.unpack(">H", the_id)
return (((packv >> 13) & 0b11) * 100000) + (packv & 8191)
def decode_card_id_long(the_id):
return struct.unpack(">I", the_id)[0]
def decode_cardlist(id_b):
lastgroup = len(id_b) % 4
if lastgroup == 2:
id_b += "=="
else:
id_b += "="
bytea = base64.urlsafe_b64decode(id_b.encode("ascii"))
result = []
while bytea:
if bytea[0] & 0x80:
if len(bytea) < 2:
raise ValueError("malformed card list")
result.append(decode_card_id_short(bytea[:2]))
advance = 2
else:
if len(bytea) < 4:
raise ValueError("malformed card list")
result.append(decode_card_id_long(bytea[:4]))
advance = 4
bytea = bytea[advance:]
return result