-
Notifications
You must be signed in to change notification settings - Fork 0
/
mudxml.py
340 lines (269 loc) · 13.6 KB
/
mudxml.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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
import os
import json
import sys
import xml.etree.ElementTree as ET
from xml.dom import minidom
def iterate_children(element, depth=0):
# Create a dictionary to hold the element's information
element_dict = {
'tag': element.tag,
'attributes': element.attrib,
'text': element.text,
'children': [],
'depth': depth
}
# Recursively iterate over each child element, increasing the depth
for child in element:
child_dict = iterate_children(child, depth + 1)
element_dict['children'].append(child_dict)
return element_dict
def reconstruct_element(element_dict):
# Create a new element with the tag and attributes from the dictionary
element = ET.Element(element_dict['tag'], element_dict['attributes'])
# Set the element's text content
if element_dict['text']:
element.text = element_dict['text']
# Recursively reconstruct each child element and add it to the current element
for child_dict in element_dict['children']:
child_element = reconstruct_element(child_dict)
element.append(child_element)
# Add a newline after every closed bracket
if element_dict['children']:
element.tail = '\n' + ' ' * element_dict['depth']
return element
def reconstruct():
# Load the dictionary from the JSON file
with open('log.json', 'r') as f:
root_dict = json.load(f)
# Reconstruct the root element from the dictionary
root = reconstruct_element(root_dict)
# Create an ElementTree from the root element
tree = ET.ElementTree(root)
# Convert the ElementTree to a string
xml_string = ET.tostring(root, encoding='unicode')
# Parse the XML string with minidom and format it with toprettyxml
pretty_xml = minidom.parseString(xml_string).toprettyxml(indent=' ')
# Write the formatted XML to a file
with open('reconstructed.xml', 'w') as f:
f.write(pretty_xml)
def add_to_order(text, depth):
for i in range(depth):
text = ' ' + text
Order.append(text)
def write_script_code(file, element_dict):
file.write("-- Script Code:\n")
for script_child in element_dict['children']:
if script_child['tag'] == 'script' and script_child['text'] is not None:
file.write(script_child['text'])
break
def write_json(child, element_dict, parent_dir='', package_dir='', depth=0, filename=''):
# Create the .json file
json_path = os.path.join('MudletPackage', package_dir, parent_dir, filename + '.json')
with open(json_path, 'w', encoding='utf-8') as file:
# Write the other tags to the JSON file
# json.dump({k: v for k, v in element_dict.items() if k != 'children'}, file)
# Create an empty dictionary
new_dict = {}
# Iterate over each key-value pair in element_dict
for key, value in element_dict.items():
if key == 'children':
child_values = []
for tag in value:
if tag['tag'] == 'script':
continue
child_values.append(tag)
new_dict[key] = child_values
else:
new_dict[key] = value
# Write the new dictionary to the file
json.dump(new_dict, file)
add_to_order(child['text'], depth)
def process_trigger(child, element_dict, file):
file.write(f"-- Trigger: {child['text']} \n")
pattern_types = ["substring", "regex", "start of line", "exact", "lua function", "line spacer", "colour trigger", "prompt"]
isColorizerTrigger = False
# TODO: probably some more processing here
for attribute in element_dict['attributes']:
if element_dict['attributes'][attribute] == 'yes':
if attribute == 'isColorizerTrigger':
isColorizerTrigger = True
file.write(f"-- Attribute: {attribute}\n")
file.write("\n")
for script_child in element_dict['children']:
if isColorizerTrigger:
if script_child["tag"] == "mFgColor" and script_child['text'] is not None:
file.write(f"-- mFgColor: {script_child['text']}\n")
if script_child["tag"] == "mBgColor" and script_child['text'] is not None:
file.write(f"-- mBgColour: {script_child['text']}\n")
if script_child["tag"] == "regexCodeList" and script_child['children']:
index = 0
pattern_list = []
pattern_types_list = []
file.write(f"\n-- Trigger Patterns:\n")
for triggerPattern in script_child['children']:
if triggerPattern['tag'] == 'string' and triggerPattern['text'] is not None:
pattern_list.append(triggerPattern['text'])
if script_child["tag"] == "regexCodePropertyList" and script_child['children']:
for triggerPatternType in script_child['children']:
if triggerPatternType['tag'] == 'integer' and triggerPatternType['text'] is not None:
pattern_types_list.append(pattern_types[int(triggerPatternType['text'])])
for pattern in pattern_list:
file.write(f"-- {index} ({pattern_types_list[index]}): {pattern}\n")
index += 1
file.write("\n")
write_script_code(file, element_dict)
def process_timer(child, element_dict, file):
file.write(f"-- Timer: {child['text']}\n")
for attribute in element_dict['attributes']:
if element_dict['attributes'][attribute] == 'yes':
file.write(f"-- Attribute: {attribute}\n")
file.write("\n")
for script_child in element_dict['children']:
if script_child["tag"] == "command" and script_child['text'] is not None:
file.write(f"-- Command: {script_child['text']}\n")
elif script_child["tag"] == "time" and script_child['text'] is not None:
file.write(f"-- Time: {script_child['text']}\n")
file.write("\n")
write_script_code(file, element_dict)
def process_alias(child, element_dict, file):
file.write(f"-- Alias: {child['text']}\n")
for attribute in element_dict['attributes']:
if element_dict['attributes'][attribute] == 'yes':
file.write(f"-- Attribute: {attribute}\n")
file.write("\n")
for script_child in element_dict['children']:
if script_child["tag"] == "command" and script_child['text'] is not None:
file.write(f"-- Command: {script_child['text']}\n")
elif script_child["tag"] == "regex" and script_child['text'] is not None:
file.write(f"-- Pattern: {script_child['text']}\n")
file.write("\n")
write_script_code(file, element_dict)
def process_script(child, element_dict, file):
file.write(f"-- Script: {child['text']}\n")
for attribute in element_dict['attributes']:
if element_dict['attributes'][attribute] == 'yes':
file.write(f"-- Attribute: {attribute}\n")
for script_child in element_dict['children']:
if script_child['tag'] == 'eventHandlerList' and script_child['children']:
file.write(f"-- {child['text']}() called on the following events:\n")
for eventHandler in script_child['children']:
if eventHandler['tag'] == 'string' and eventHandler['text'] is not None:
file.write(f"-- {eventHandler['text']}\n")
file.write("\n")
write_script_code(file, element_dict)
def process_key(child, element_dict, file):
file.write(f"-- Key: {child['text']}\n")
for attribute in element_dict['attributes']:
if element_dict['attributes'][attribute] == 'yes':
file.write(f"-- Attribute: {attribute}\n")
for script_child in element_dict['children']:
if script_child["tag"] == "command" and script_child['text'] is not None:
file.write(f"-- Command: {script_child['text']}\n")
elif script_child["tag"] == "keyCode" and script_child['text'] is not None:
file.write(f"-- keyCode: {script_child['text']}\n")
elif script_child["tag"] == "keyModifier" and script_child['text'] is not None:
file.write(f"-- keyModifier: {script_child['text']}\n")
file.write("\n")
write_script_code(file, element_dict)
def build_filestructure(element_dict, parent_dir='', package_dir='', depth=0):
# If the element is a HostPackage, create a .json file for it
if element_dict['tag'] == 'HostPackage':
os.makedirs('MudletPackage', exist_ok=True)
json_path = os.path.join('MudletPackage', 'HostPackage.json')
with open(json_path, 'w') as file:
# Write the tags and children to the JSON file
json.dump({**element_dict['attributes'], 'children': element_dict['children']}, file)
element = ET.Element(element_dict['tag'], element_dict['attributes'])
# Set the element's text content
if element_dict['text']:
element.text = element_dict['text']
# If the element is a TriggerGroup (or AliasGroup, ScriptGroup, KeyGroup),
# and it has a name, create a new directory for it
group_types = ['TriggerGroup', 'TimerGroup', 'AliasGroup', 'ScriptGroup', 'KeyGroup']
if element_dict['tag'] in group_types:
for child in element_dict['children']:
if child['tag'] == 'name':
# Determine the correct package directory based on the group type
package_dir = element_dict['tag'].replace('Group', 'Package')
# Replace forward slashes in the directory name
dir_name = f"{child['text'].replace('/', '_S_').replace('*', '_A_').replace('?', '_Q_').replace('<', '_LT_').replace('>', '_GT_').replace('|', '_P_').replace('"', '_DQ_').rstrip('.')}"
# Create the new directory
new_dir = os.path.join('MudletPackage', package_dir, parent_dir, dir_name)
os.makedirs(new_dir, exist_ok=True)
add_to_order(child['text'], depth)
# Update the parent directory for the next level of recursion
parent_dir = os.path.join(parent_dir, dir_name)
break
# If the element is a Trigger, Alias, Script, or Key, create a .lua file for it
element_types = ['Trigger', 'Timer', 'Alias', 'Script', 'Key']
if element_dict['tag'] in element_types:
for child in element_dict['children']:
if child['tag'] == 'name':
# Replace forward slashes in the filename
filename = f"{child['text'].replace('/', '_S_').replace('*', '_A_').replace('?', '_Q_').replace('<', '_LT_').replace('>', '_GT_').replace('|', '_P_').replace('"', '_DQ_').rstrip('.')}"
write_json(child, element_dict, parent_dir, package_dir, depth, filename)
file_path = os.path.join('MudletPackage', package_dir, parent_dir, filename + '.lua')
with open(file_path, 'w', encoding='utf-8') as file:
if element_dict['tag'] == 'Trigger':
process_trigger(child, element_dict, file)
elif element_dict['tag'] == 'Timer':
process_timer(child, element_dict, file)
elif element_dict['tag'] == 'Alias':
process_alias(child, element_dict, file)
elif element_dict['tag'] == 'Script':
process_script(child, element_dict, file)
elif element_dict['tag'] == 'Key':
process_key(child, element_dict, file)
# Recursively reconstruct each child element and add it to the current element
for child_dict in element_dict['children']:
child_element = build_filestructure(child_dict, parent_dir, package_dir, depth + 1)
element.append(child_element)
return element
def check_xml_header(filename):
try:
tree = ET.parse(filename)
root = tree.getroot()
# Check the root tag
if root.tag != 'MudletPackage':
print(f"Unexpected root tag: {root.tag}, expecting MudletPackage")
return False
# Check the first child tag
if len(root) > 0 and root[0].tag != 'HostPackage':
print(f"Unexpected first child tag: {root[0].tag}, expecting HostPackage")
print(f"Is this just a script export? For now, only full package exports are supported.")
return False
return True
except ET.ParseError:
print(f"Failed to parse {filename}")
return False
Order = []
def main(filename):
# check if this is a Mudlet package
print("Processing Mudlet Package...")
if not check_xml_header(filename):
sys.exit()
tree = ET.parse(filename)
root = tree.getroot()
# Start iterating from the root
root_dict = iterate_children(root)
# Write the dictionary to a file in JSON format
with open('log.json', 'w') as f:
json.dump(root_dict, f, indent=4)
build_filestructure(root_dict, '')
with open('order.txt', 'w') as f:
for item in Order:
f.write("%s\n" % item)
print("Mudlet Package processed successfully! See folder MudletPackage")
sys.exit()
if __name__ == "__main__":
# Check if a filename was provided as a command-line argument
if len(sys.argv) > 1:
filename = sys.argv[1]
# Check if the file exists
if not os.path.exists(filename):
print(f"File {filename} does not exist.")
sys.exit()
main(filename)
else:
print("Usage: python mudxml.py <filename>")
print("where <filename> is the name of the Mudlet XML package file to be processed.")