Last active
July 8, 2022 02:08
-
-
Save KokoseiJ/23e2b8c4145757bf840613f925f61ca4 to your computer and use it in GitHub Desktop.
Automatically generate discord object parse code from their docs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
import requests | |
# Do check for: ex) "integer or string" | |
files = ["Application.md", "Audit_Log.md", "Channel.md", "Emoji.md", "Guild.md", "Guild_Scheduled_Event.md", "Guild_Template.md", "Invite.md", "Stage_Instance.md", "Sticker.md", "User.md", "Voice.md", "Webhook.md"] | |
known_types = { | |
# Type: [funcname, casting] | |
"boolean": ["boolean", None], | |
"integer": ["number", "int"], | |
"string": ["string", "char *"], | |
"array": ["!array", "char *"], | |
"default": ["!object", "char *"] | |
} | |
aliases = { | |
"snowflake": "string", | |
"iso8601 timestamp": "string", | |
"integer or string": "string", | |
"int": "integer", | |
"string (can be null only in reaction emoji objects)": "string" | |
} | |
unregistered_type = [] | |
def get_func(funcname, casting): | |
if funcname.startswith("!"): | |
funcstr = f"json_serialize_to_string(json_{funcname[1:]}_get_wrapping_value(json_object_get_{funcname[1:]}({{}}, {{}})))" | |
else: | |
funcstr = f"json_object_get_{funcname}({{}}, {{}})" | |
if casting is not None: | |
funcstr = f"({casting}) {funcstr}" | |
return funcstr | |
def get_typedata(typename): | |
typename = typename.lower().strip().rstrip() | |
if typename in aliases: | |
typename = aliases.get(typename) | |
type_ = known_types.get(typename, None) | |
if type_ is None: | |
unregistered_type.append(typename) | |
if typename.startswith("array") or typename.startswith("list"): | |
type_ = known_types.get("array") | |
else: | |
type_ = known_types.get("default") | |
return type_ | |
def format_full(s_name, s_data, baseindent=4): | |
indent = baseindent + 16 + len(s_name) | |
structstr = f"""\ | |
{s_name}_t *parse_{s_name}(JSON_Value *{s_name}_value) {{ | |
JSON_Object *{s_name} = json_object({s_name}_value); | |
*result = ({s_name}_t) @; | |
return result; | |
}} | |
""" | |
substr = f",\n{' '*indent}".join([get_func(*get_typedata(t_type)).format(s_name, f"\"{t_name}\"") for t_name, t_type in s_data.items()]) | |
print(structstr.replace("@", f"{{{substr}\n{' '*baseindent}}}")) | |
print("\n") | |
def purify_item(text): | |
rep_txt = text.replace("?", "").replace("| ", "|").replace(" |", "|") | |
pure_txt = re.sub("[\\\\]+\\*", "", rep_txt) | |
return re.sub("\\s{2,}", "", pure_txt).split("|", 3)[1:3] | |
def get_structures(text): | |
i = 0 | |
check = re.compile("#+ (.+?) Structure") | |
structures = {} | |
lines = text.split("\n") | |
while i < len(lines): | |
line = lines[i] | |
struct_match = check.match(line) | |
if struct_match: | |
struct_name = re.sub("\\s+", "_", struct_match.groups()[0].lower()) | |
#print("###", struct_name, "###") | |
struct_dict = {} | |
if ">" in lines[i+2]: | |
i += 4 | |
i += 4 | |
while True: | |
line = lines[i] | |
if not line: | |
break | |
items = purify_item(line) | |
#print(items) | |
key, val = items | |
struct_dict[key] = val | |
i += 1 | |
structures[struct_name] = struct_dict | |
i += 1 | |
return structures | |
check = [] | |
for file in files: | |
structures = get_structures(requests.get(f"https://raw.githubusercontent.com/discord/discord-api-docs/master/docs/resources/{file}").text) | |
for s_name, s_data in structures.items(): | |
if s_name in check: | |
print(f"### WARNING: {s_name} already exists") | |
check.append(s_name) | |
format_full(s_name, s_data) | |
# print("|\n".join(check)) | |
# print("#####") | |
# print("\n".join(unregistered_type)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
import requests | |
# Do check for: ex) "integer or string" | |
files = ["Application.md", "Audit_Log.md", "Channel.md", "Emoji.md", "Guild.md", "Guild_Scheduled_Event.md", "Guild_Template.md", "Invite.md", "Stage_Instance.md", "Sticker.md", "User.md", "Voice.md", "Webhook.md"] | |
known_types = { | |
# Type: [funcname, casting] | |
"boolean": ["boolean", None], | |
"integer": ["number", "int"], | |
"string": ["string", "char *"], | |
"array": ["!array", "char *"], | |
"default": ["!object", "char *"] | |
} | |
aliases = { | |
"snowflake": "string", | |
"iso8601 timestamp": "string", | |
"integer or string": "string", | |
"int": "integer", | |
"string (can be null only in reaction emoji objects)": "string" | |
} | |
unregistered_type = [] | |
def get_func(funcname, casting): | |
if funcname.startswith("!"): | |
funcstr = f"json_serialize_to_string(json_{funcname[1:]}_get_wrapping_value(json_object_get_{funcname[1:]}({{}}, {{}})))" | |
else: | |
funcstr = f"json_object_get_{funcname}({{}}, {{}})" | |
if casting is not None: | |
funcstr = f"({casting}) {funcstr}" | |
return funcstr | |
def get_typedata(typename): | |
typename = typename.lower().strip().rstrip() | |
if typename in aliases: | |
typename = aliases.get(typename) | |
type_ = known_types.get(typename, None) | |
if type_ is None: | |
unregistered_type.append(typename) | |
if typename.startswith("array") or typename.startswith("list"): | |
type_ = known_types.get("array") | |
else: | |
type_ = known_types.get("default") | |
return type_ | |
def format_full(s_name, s_data, baseindent=4): | |
indent = baseindent + 16 + len(s_name) | |
structstr = f"""\ | |
{s_name}_t *parse_{s_name}(JSON_Value *{s_name}_value) {{ | |
JSON_Object *{s_name} = json_object({s_name}_value); | |
*result = ({s_name}_t) @; | |
return result; | |
}} | |
""" | |
substr = f",\n{' '*indent}".join([get_func(*get_typedata(t_type)).format(s_name, f"\"{t_name}\"") for t_name, t_type in s_data.items()]) | |
print(structstr.replace("@", f"{{{substr}\n{' '*baseindent}}}")) | |
print("\n") | |
def format_declare_full(s_name, s_data, baseindent=4): | |
structstr = f"""\ | |
typedef struct yadl_{s_name} {{ | |
@ | |
}} {s_name}_t; | |
""" | |
substr_list = [] | |
for t_name, t_type in s_data.items(): | |
t_type = re.sub("\\[(.*?)\\]\\(.*?\\)", lambda x: x.groups()[0], t_type) | |
t_name = t_name.strip().rstrip() | |
funcname, casting = get_typedata(t_type) | |
if casting == None: | |
casting = "bool" | |
subsubstr = f"{casting}{' ' if casting[-1] != '*' else ''}{t_name};\n{' '*baseindent}" | |
substr_list.append(subsubstr) | |
if funcname.startswith("!"): | |
substr_list.append(f"/* {t_type} */\n{' '*baseindent}") | |
substr = "".join(substr_list) | |
print(structstr.replace("@", substr)) | |
def purify_item(text): | |
rep_txt = text.replace("?", "").replace("| ", "|").replace(" |", "|") | |
pure_txt = re.sub("([\\\\]+)?\\*", "", rep_txt) | |
return re.sub("\\s{2,}", "", pure_txt).split("|", 3)[1:3] | |
def get_structures(text): | |
i = 0 | |
check = re.compile("#+ (.+?) Structure") | |
structures = {} | |
lines = text.split("\n") | |
while i < len(lines): | |
line = lines[i] | |
struct_match = check.match(line) | |
if struct_match: | |
struct_name = re.sub("\\s+", "_", struct_match.groups()[0].lower()) | |
#print("###", struct_name, "###") | |
struct_dict = {} | |
if ">" in lines[i+2]: | |
i += 4 | |
i += 4 | |
while True: | |
line = lines[i] | |
if not line: | |
break | |
items = purify_item(line) | |
#print(items) | |
key, val = items | |
struct_dict[key] = val | |
i += 1 | |
structures[struct_name] = struct_dict | |
i += 1 | |
return structures | |
check = [] | |
for file in files: | |
structures = get_structures(requests.get(f"https://raw.githubusercontent.com/discord/discord-api-docs/master/docs/resources/{file}").text) | |
for s_name, s_data in structures.items(): | |
if s_name in check: | |
print(f"### WARNING: {s_name} already exists") | |
check.append(s_name) | |
format_declare_full(s_name, s_data) | |
# print("|\n".join(check)) | |
# print("#####") | |
# print("\n".join(unregistered_type)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment