Add multi file input for processing and organising of logs
This commit is contained in:
parent
71f2800c4e
commit
320462d73d
2 changed files with 458 additions and 196 deletions
12
README.md
12
README.md
|
@ -70,3 +70,15 @@ Attention ! Il laisse quelques fichiers dans le dossier courant. Gardez les logs
|
|||
|
||||
Auteur : Zatalyz. Tout est sous licence CC0, c'est de l'assemblage de bons conseils et de tests, rien de transcendant. Plus de détail dans chaque script.
|
||||
|
||||
|
||||
## Python version
|
||||
The script uses basic python3 with no additional 3rd part libraries. The main file is main.py and the only other file it uses is tk_tooltip.py.
|
||||
To just run the GUI, run:
|
||||
`python3 main.py`
|
||||
|
||||
###
|
||||
If you want to create a binary for distribution, it seems that pyinstaller is the easiest way.
|
||||
Just run:
|
||||
|
||||
`pip3 install pyinstaller`
|
||||
`pyinstaller --onefile --noconsole --clean --log-level=WARN --strip main.py tk_tooltip.py`
|
||||
|
|
642
main.py
642
main.py
|
@ -1,5 +1,5 @@
|
|||
import tkinter as tk
|
||||
import tkinter.ttk as ttk
|
||||
from tkinter import ttk
|
||||
from tkinter import filedialog
|
||||
from tk_tooltip import CreateToolTip
|
||||
import re
|
||||
|
@ -62,207 +62,457 @@ system_info_categories = [
|
|||
("R2_INVITE", "Ring invitation"),
|
||||
]
|
||||
|
||||
def get_input_filepath():
|
||||
global input_filepath
|
||||
filepath = filedialog.askopenfilename(
|
||||
filetypes=[("Text Files", "*.txt"), ("All Files", "*.*")],
|
||||
initialdir='/'.join(ent_input.get().split('/')[:-1 if '.' in ent_input.get() else len(ent_input.get())])
|
||||
)
|
||||
if not filepath:
|
||||
return
|
||||
input_filepath = filepath
|
||||
ent_input.delete(0, tk.END)
|
||||
ent_input.insert(0, input_filepath)
|
||||
|
||||
class GUI:
|
||||
color_regex = re.compile('@\{[A-F0-9]{4}\}')
|
||||
|
||||
def get_output_filepath():
|
||||
global output_filepath
|
||||
filepath = filedialog.askdirectory(
|
||||
initialdir=ent_output.get()
|
||||
)
|
||||
if not filepath:
|
||||
return
|
||||
output_filepath = filepath
|
||||
ent_output.delete(0, tk.END)
|
||||
ent_output.insert(0, output_filepath)
|
||||
def __init__(self):
|
||||
self.originalfolderlog = ''
|
||||
self.keep_color = False
|
||||
self.keep_channel = False
|
||||
self.keep_lang_flag = False
|
||||
self.keep_original_part = False
|
||||
self.keep_translated_part = False
|
||||
self.keep_timestamp = False
|
||||
self.replace_charname = False
|
||||
|
||||
self.window = tk.Tk()
|
||||
self.window.title("Ryzom Log Cleaner")
|
||||
|
||||
def toggle_channel(index):
|
||||
def tgl_chan():
|
||||
if chan_toggle[index]:
|
||||
btn_chan_toggle[index].config(relief="raised", bg="#ffcccb")
|
||||
chan_toggle[index] = False
|
||||
if channel_names[index] == "SYSTEM":
|
||||
frm_btn_sys.grid_remove()
|
||||
self.window.columnconfigure(0, weight=1)
|
||||
#self.window.rowconfigure([0,1], minsize=50)
|
||||
|
||||
self.ntb_file_selection = ttk.Notebook(self.window)
|
||||
|
||||
### Single file tab
|
||||
self.frm_single_file = tk.Frame(self.window)
|
||||
self.frm_single_file.columnconfigure(0, weight=1)
|
||||
btn_input = tk.Button(self.frm_single_file, text="Input file", command=self.get_input_filepath)
|
||||
self.ent_input = tk.Entry(self.frm_single_file, text="Input path")
|
||||
# ent_input.insert(0, "~/log.txt")
|
||||
btn_output = tk.Button(self.frm_single_file, text="Output file", command=self.get_output_filepath)
|
||||
self.ent_output = tk.Entry(self.frm_single_file, text="Output path")
|
||||
# ent_output.insert(0, "~/cleaned/")
|
||||
self.frm_charname = tk.Frame(self.frm_single_file)
|
||||
lbl_charname = tk.Label(self.frm_charname, text="Char name:")
|
||||
self.ent_charname = tk.Entry(self.frm_charname, text="Charname")
|
||||
self.ent_charname.insert(0, "Select input file to auto-fill")
|
||||
|
||||
btn_input.grid(row=0, column=1, sticky='ew')
|
||||
self.ent_input.grid(row=0, column=0, sticky='ew')
|
||||
btn_output.grid(row=1, column=1, sticky='ew')
|
||||
self.ent_output.grid(row=1, column=0, sticky='ew')
|
||||
|
||||
self.frm_charname.grid(row=2, column=0, columnspan=2, sticky='ew')
|
||||
self.frm_charname.columnconfigure(1, weight=1)
|
||||
|
||||
lbl_charname.grid(row=0, column=0)
|
||||
self.ent_charname.grid(row=0, column=1, sticky='ew')
|
||||
|
||||
|
||||
### Multi file tab
|
||||
self.frm_multi_file = tk.Frame(self.window)
|
||||
self.frm_multi_file.columnconfigure(0, weight=1)
|
||||
btn_input_multi = tk.Button(self.frm_multi_file, text="Input files", command=self.get_input_filepaths)
|
||||
self.ent_input_multi = tk.Entry(self.frm_multi_file, text="Input paths")
|
||||
# ent_input.insert(0, "~/log.txt")
|
||||
btn_output_multi = tk.Button(self.frm_multi_file, text="Output directory", command=self.get_output_directory)
|
||||
self.ent_output_multi = tk.Entry(self.frm_multi_file, text="Output paths")
|
||||
# ent_output.insert(0, "~/cleaned/")
|
||||
self.frm_charname_multi = tk.Frame(self.frm_multi_file)
|
||||
lbl_charname_multi = tk.Label(self.frm_charname_multi, text="Char name (detected from file name of each file if empty):")
|
||||
self.ent_charname_multi = tk.Entry(self.frm_charname_multi, text="Charname Multi")
|
||||
|
||||
btn_input_multi.grid(row=0, column=1, sticky='ew')
|
||||
self.ent_input_multi.grid(row=0, column=0, sticky='ew')
|
||||
btn_output_multi.grid(row=1, column=1, sticky='ew')
|
||||
self.ent_output_multi.grid(row=1, column=0, sticky='ew')
|
||||
|
||||
self.frm_charname_multi.grid(row=2, column=0, columnspan=2, sticky='ew')
|
||||
self.frm_charname_multi.columnconfigure(1, weight=1)
|
||||
|
||||
lbl_charname_multi.grid(row=0, column=0)
|
||||
self.ent_charname_multi.grid(row=0, column=1, sticky='ew')
|
||||
|
||||
|
||||
### Organise logs tab
|
||||
self.frm_organise_logs = tk.Frame(self.window)
|
||||
self.frm_organise_logs.columnconfigure(0, weight=1)
|
||||
btn_input_orgalogs = tk.Button(self.frm_organise_logs, text="Input directory", command=self.get_input_dir_orgalogs)
|
||||
self.ent_input_orgalogs = tk.Entry(self.frm_organise_logs, text="Input dir")
|
||||
# ent_input.insert(0, "~/log.txt")
|
||||
btn_output_orgalogs = tk.Button(self.frm_organise_logs, text="(Empty) Output directory", command=self.get_output_dir_orgalogs)
|
||||
self.ent_output_orgalogs = tk.Entry(self.frm_organise_logs, text="Output dir")
|
||||
# ent_output.insert(0, "~/cleaned/")
|
||||
self.frm_charname_orgalogs = tk.Frame(self.frm_organise_logs)
|
||||
lbl_charname_orgalogs = tk.Label(self.frm_charname_orgalogs, text="Char name (detected from file name of each file if empty):")
|
||||
self.ent_charname_orgalogs = tk.Entry(self.frm_charname_orgalogs, text="Charname Orgalogs")
|
||||
|
||||
btn_input_orgalogs.grid(row=0, column=1, sticky='ew')
|
||||
self.ent_input_orgalogs.grid(row=0, column=0, sticky='ew')
|
||||
btn_output_orgalogs.grid(row=1, column=1, sticky='ew')
|
||||
self.ent_output_orgalogs.grid(row=1, column=0, sticky='ew')
|
||||
|
||||
self.frm_charname_orgalogs.grid(row=2, column=0, columnspan=2, sticky='ew')
|
||||
self.frm_charname_orgalogs.columnconfigure(1, weight=1)
|
||||
|
||||
lbl_charname_orgalogs.grid(row=0, column=0)
|
||||
self.ent_charname_orgalogs.grid(row=0, column=1, sticky='ew')
|
||||
|
||||
self.btn_organise = tk.Button(self.frm_organise_logs, text="Organise!", command=self.organise_logs)
|
||||
self.btn_organise.grid(row=10, column=0, columnspan=2, sticky='ew')
|
||||
|
||||
|
||||
|
||||
### Setup tab notebook
|
||||
self.ntb_file_selection.add(self.frm_single_file, text="Single file input/output")
|
||||
self.ntb_file_selection.add(self.frm_multi_file, text="Multi file input/output")
|
||||
self.ntb_file_selection.add(self.frm_organise_logs, text="Organise logs")
|
||||
self.ntb_file_selection.grid(row=0, column=0, columnspan=2, sticky='ew', ipady='2.5')
|
||||
def on_tab_change(event):
|
||||
tab = event.widget.tab('current')['text']
|
||||
if tab == "Single file input/output":
|
||||
self.btn_process.config(command=self.process_file)
|
||||
self.frm_process_settings.grid(in_=self.frm_single_file)
|
||||
elif tab == "Multi file input/output":
|
||||
self.btn_process.config(command=self.process_files)
|
||||
self.frm_process_settings.grid(in_=self.frm_multi_file)
|
||||
self.ntb_file_selection.bind('<<NotebookTabChanged>>', on_tab_change)
|
||||
|
||||
|
||||
self.frm_process_settings = tk.Frame(self.window)
|
||||
self.frm_process_settings.grid(row=5, column=0, columnspan=2, sticky='ew', in_=self.frm_single_file)
|
||||
self.frm_process_settings.columnconfigure([0,1], weight=1)
|
||||
|
||||
|
||||
sep_general_settings = ttk.Separator(self.frm_process_settings, orient='horizontal')
|
||||
sep_general_settings.grid(row=5, column=0, columnspan=2, sticky='ew', pady='5')
|
||||
|
||||
### General settings
|
||||
self.frm_general_settings = tk.Frame(self.frm_process_settings)
|
||||
self.frm_general_settings.grid(row=6, column=0, columnspan=2, sticky='ew', pady='5')
|
||||
self.frm_general_settings.columnconfigure([0,1,2], weight=1)
|
||||
|
||||
self.btn_keep_color = tk.Button(self.frm_general_settings, text="Keep color", command=self.toggle_setting("keep_color"), bg="#ffcccb")
|
||||
self.btn_keep_channel = tk.Button(self.frm_general_settings, text="Keep channel name", command=self.toggle_setting("keep_channel"), bg="#ffcccb")
|
||||
self.btn_keep_lang_flag = tk.Button(self.frm_general_settings, text="Keep language flag", command=self.toggle_setting("keep_lang_flag"), bg="#ffcccb")
|
||||
self.btn_keep_original_part = tk.Button(self.frm_general_settings, text="Keep original text", command=self.toggle_setting("keep_original_part"), bg="#ffcccb")
|
||||
self.btn_keep_translated_part = tk.Button(self.frm_general_settings, text="Keep translated text", command=self.toggle_setting("keep_translated_part"), bg="#ffcccb")
|
||||
self.btn_keep_timestamp = tk.Button(self.frm_general_settings, text="Keep timestamp", command=self.toggle_setting("keep_timestamp"), bg="#ffcccb")
|
||||
self.btn_replace_charname = tk.Button(self.frm_general_settings, text="Replace charname", command=self.toggle_setting("replace_charname"), bg="#ffcccb")
|
||||
|
||||
self.btn_keep_color.grid(row=0, column=0, sticky='ew')
|
||||
self.btn_keep_channel.grid(row=0, column=1, sticky='ew')
|
||||
self.btn_keep_lang_flag.grid(row=0, column=2, sticky='ew')
|
||||
self.btn_keep_original_part.grid(row=1, column=0, sticky='ew')
|
||||
self.btn_keep_translated_part.grid(row=1, column=1, sticky='ew')
|
||||
self.btn_keep_timestamp.grid(row=1, column=2, sticky='ew')
|
||||
self.btn_replace_charname.grid(row=2, column=0, sticky='ew')
|
||||
|
||||
sep_channels = ttk.Separator(self.frm_process_settings, orient='horizontal')
|
||||
sep_channels.grid(row=10, column=0, columnspan=2, sticky='ew')
|
||||
|
||||
lbl_channel_select = tk.Label(self.frm_process_settings, text="Select channels to keep:")
|
||||
lbl_channel_select.grid(row=11, column=0, sticky='w')
|
||||
|
||||
self.btn_chan_toggle = []
|
||||
|
||||
self.frm_btn_channel = tk.Frame(self.frm_process_settings)
|
||||
self.frm_btn_channel.grid(row=12, column=0, columnspan=2, sticky='ew')
|
||||
self.frm_btn_channel.columnconfigure([0,1,2,3], weight=1)
|
||||
self.frm_btn_channel.rowconfigure([0,1,2], weight=1)
|
||||
for i,name in enumerate(channel_names):
|
||||
self.btn_chan_toggle.append(tk.Button(self.frm_btn_channel, text=name, command=self.toggle_channel(i), bg="#ffcccb"))
|
||||
self.btn_chan_toggle[i].grid(row=int(i/4), column=i%4, sticky='ew')
|
||||
|
||||
self.btn_sys_toggle = []
|
||||
|
||||
self.frm_btn_sys = tk.Frame(self.frm_process_settings, bg="#808080", borderwidth=5)
|
||||
self.frm_btn_sys.grid(row=13, column=0, columnspan=2, sticky='e')
|
||||
self.frm_btn_sys.columnconfigure([0,1,2,3,4,5,6], weight=1)
|
||||
self.frm_btn_sys.rowconfigure([0,1,2,3,4], weight=1)
|
||||
for i,(name,tooltip) in enumerate(system_info_categories):
|
||||
self.btn_sys_toggle.append(tk.Button(self.frm_btn_sys, text=name, command=self.toggle_system(i), bg="#ffcccb"))
|
||||
self.btn_sys_toggle[i].grid(row=int(i/7), column=i%7, sticky='ew')
|
||||
ttp_sys = CreateToolTip(self.btn_sys_toggle[i], tooltip)
|
||||
|
||||
self.btn_process = tk.Button(self.frm_process_settings, text="Process!", command=self.process_file)
|
||||
self.btn_process.grid(row=20, column=0, columnspan=2, sticky='ew')
|
||||
|
||||
# Default selection
|
||||
self.chan_toggle = [False] * len(channel_names)
|
||||
self.sys_toggle = [False] * len(system_info_categories)
|
||||
self.toggle_channel(0)()
|
||||
self.toggle_channel(1)()
|
||||
self.toggle_channel(12)()
|
||||
self.toggle_channel(13)()
|
||||
self.toggle_system(7)()
|
||||
self.toggle_setting("keep_translated_part")()
|
||||
|
||||
def toggle_setting(self, setting):
|
||||
def tgl_pref():
|
||||
if getattr(self, setting):
|
||||
getattr(self, f"btn_{setting}").config(relief="raised", bg="#ffcccb")
|
||||
setattr(self, setting, False)
|
||||
else:
|
||||
getattr(self, f"btn_{setting}").config(relief="sunken", bg="#99e599")
|
||||
setattr(self, setting, True)
|
||||
return tgl_pref
|
||||
|
||||
def get_input_filepath(self):
|
||||
filepath = filedialog.askopenfilename(
|
||||
filetypes=[("Text Files", "*.txt"), ("All Files", "*.*")],
|
||||
initialdir=os.path.dirname(self.ent_input.get())
|
||||
)
|
||||
if not filepath:
|
||||
return
|
||||
self.ent_input.delete(0, tk.END)
|
||||
self.ent_input.insert(0, filepath)
|
||||
filename = os.path.basename(filepath)
|
||||
name_start = filename.find("log_")
|
||||
name_end = filename.find("_", name_start+4)
|
||||
if name_end == -1:
|
||||
name_end = filename.find(".", name_start+4)
|
||||
if name_start != -1:
|
||||
self.ent_charname.delete(0, tk.END)
|
||||
self.ent_charname.insert(0, os.path.basename(filepath)[name_start+4:name_end])
|
||||
|
||||
def get_output_filepath(self):
|
||||
filepath = filedialog.asksaveasfilename(
|
||||
filetypes=[("Text Files", "*.txt"), ("All Files", "*.*")],
|
||||
initialdir=os.path.dirname(self.ent_output.get())
|
||||
)
|
||||
if not filepath:
|
||||
return
|
||||
self.ent_output.delete(0, tk.END)
|
||||
self.ent_output.insert(0, filepath)
|
||||
|
||||
def get_input_filepaths(self):
|
||||
filepaths = filedialog.askopenfilenames(
|
||||
filetypes=[("Text Files", "*.txt"), ("All Files", "*.*")],
|
||||
initialdir=os.path.dirname(self.ent_input_multi.get().split(';')[0])
|
||||
)
|
||||
if not filepaths:
|
||||
return
|
||||
self.ent_input_multi.delete(0, tk.END)
|
||||
self.ent_input_multi.insert(0, ';'.join(filepaths))
|
||||
|
||||
def get_output_directory(self):
|
||||
directory = filedialog.askdirectory(
|
||||
initialdir=self.ent_output_multi.get()
|
||||
)
|
||||
if not directory:
|
||||
return
|
||||
self.ent_output_multi.delete(0, tk.END)
|
||||
self.ent_output_multi.insert(0, directory)
|
||||
|
||||
def get_input_dir_orgalogs(self):
|
||||
directory = filedialog.askdirectory(
|
||||
initialdir=self.ent_input_orgalogs.get()
|
||||
)
|
||||
if not directory:
|
||||
return
|
||||
self.ent_input_orgalogs.delete(0, tk.END)
|
||||
self.ent_input_orgalogs.insert(0, directory)
|
||||
|
||||
def get_output_dir_orgalogs(self):
|
||||
directory = filedialog.askdirectory(
|
||||
initialdir=self.ent_output_orgalogs.get()
|
||||
)
|
||||
if not directory:
|
||||
return
|
||||
self.ent_output_orgalogs.delete(0, tk.END)
|
||||
self.ent_output_orgalogs.insert(0, directory)
|
||||
|
||||
|
||||
def toggle_channel(self, index):
|
||||
def tgl_chan():
|
||||
if self.chan_toggle[index]:
|
||||
self.btn_chan_toggle[index].config(relief="raised", bg="#ffcccb")
|
||||
self.chan_toggle[index] = False
|
||||
if channel_names[index] == "SYSTEM":
|
||||
self.frm_btn_sys.grid_remove()
|
||||
else:
|
||||
self.btn_chan_toggle[index].config(relief="sunken", bg="#99e599")
|
||||
self.chan_toggle[index] = True
|
||||
if channel_names[index] == "SYSTEM":
|
||||
self.frm_btn_sys.grid()
|
||||
return tgl_chan
|
||||
|
||||
def toggle_system(self,index):
|
||||
def tgl_sys():
|
||||
if self.sys_toggle[index]:
|
||||
self.btn_sys_toggle[index].config(relief="raised", bg="#ffcccb")
|
||||
self.sys_toggle[index] = False
|
||||
else:
|
||||
self.btn_sys_toggle[index].config(relief="sunken", bg="#99e599")
|
||||
self.sys_toggle[index] = True
|
||||
return tgl_sys
|
||||
|
||||
def process_file(self):
|
||||
if not self.check_path_exists("ent_input"):
|
||||
return
|
||||
chan_pattern = '|'.join(['\(' + name + '\)' for i,name in enumerate(channel_names[:-2]) if self.chan_toggle[i]])
|
||||
if self.chan_toggle[-2]:
|
||||
chan_pattern += '|\(SAY/EMT\)'
|
||||
if self.chan_toggle[-1]:
|
||||
if self.sys_toggle[0]:
|
||||
chan_pattern += '|\(SYSTEM\)'
|
||||
for i,(name,tooltip) in enumerate(system_info_categories[1:]):
|
||||
if self.sys_toggle[i+1]:
|
||||
chan_pattern += '|\(SYSTEM/' + name + '\)'
|
||||
chan_regex = re.compile(chan_pattern)
|
||||
with open(self.ent_input.get(), 'r', errors='surrogateescape') as in_file, open(self.ent_output.get(), 'w', errors='surrogateescape') as out_file:
|
||||
orig_lines = 0
|
||||
filtered_lines = 0
|
||||
self.btn_process["text"] = "Started Processing..."
|
||||
for line in in_file:
|
||||
orig_lines += 1
|
||||
if chan_regex.search(line) == None:
|
||||
continue
|
||||
if not self.keep_color:
|
||||
line = self.color_regex.sub('',line)
|
||||
if not self.keep_channel:
|
||||
line = line[:20] + line[line.find(') * ')+1:]
|
||||
if not self.keep_timestamp:
|
||||
line = line[20:]
|
||||
original_start = line.find('{:')
|
||||
if original_start != -1 and not self.keep_lang_flag:
|
||||
line = line[:original_start+1] + line[original_start+5:]
|
||||
original_end = line.find('}@{')
|
||||
if original_end != -1 and not self.keep_translated_part:
|
||||
line = line[:original_end+4] + '\n'
|
||||
if original_end != -1 and not self.keep_original_part:
|
||||
original_text_start = original_start + (5 if self.keep_lang_flag else 1)
|
||||
line = line[:original_text_start] + line[original_end:]
|
||||
if original_end != -1:
|
||||
original_end = line.find('}@{')
|
||||
line = line[:original_start] + line[original_start+1:original_end] + line[original_end+4:]
|
||||
|
||||
if self.replace_charname:
|
||||
char_name_start = line.find(' * ') + 3 if not self.keep_color or line.find('}') == -1 else line.find('}') + 1
|
||||
if line[char_name_start] == '[' and line[char_name_start+2] == ']':
|
||||
char_name_start += 3
|
||||
char_name_end = line.find(':', char_name_start)
|
||||
char_name_end -= len(line[:char_name_end].rstrip().split(' ')[-1]) + 1 + (len(line[:char_name_end])-len(line[:char_name_end].rstrip()))
|
||||
char_name = line[char_name_start:char_name_end]
|
||||
|
||||
if char_name == "Vous" or char_name == "You" or char_name == "Du":
|
||||
line = line[:char_name_start] + ' '.join([s.capitalize() for s in self.ent_charname.get().split(' ')]) + line[char_name_end:]
|
||||
|
||||
line = line[:line.find(' * ')] + line[line.find(' * ')+3:]
|
||||
# channel_name = line[21:line.find(')')]
|
||||
out_file.write(line.lstrip())
|
||||
filtered_lines += 1
|
||||
self.btn_process["text"]="Processing done! (" + str(filtered_lines) + " lines kept out of " + str(orig_lines) + " original lines)"
|
||||
|
||||
def process_files(self):
|
||||
input_filepaths = self.ent_input_multi.get().split(';')
|
||||
for filepath in input_filepaths:
|
||||
filename = os.path.basename(filepath)
|
||||
self.ent_input.delete(0, tk.END)
|
||||
self.ent_input.insert(0, filepath)
|
||||
self.ent_output.delete(0, tk.END)
|
||||
self.ent_output.insert(0, os.path.join(self.ent_output_multi.get(), filename))
|
||||
if len(self.ent_charname_multi.get()) == 0:
|
||||
name_start = filename.find("log_")
|
||||
name_end = filename.find("_", name_start+4)
|
||||
if name_end == -1:
|
||||
name_end = filename.find(".", name_start+4)
|
||||
if name_start != -1:
|
||||
self.ent_charname.delete(0, tk.END)
|
||||
self.ent_charname.insert(0, os.path.basename(filepath)[name_start+4:name_end])
|
||||
else:
|
||||
self.ent_charname.delete(0, tk.END)
|
||||
self.ent_charname.insert(0, self.ent_charname_multi.get())
|
||||
|
||||
self.process_file()
|
||||
|
||||
|
||||
def organise_logs(self):
|
||||
if not self.check_path_exists("ent_output_orgalogs") or not self.check_path_exists("ent_input_orgalogs"):
|
||||
return
|
||||
self.my_pathes = {}
|
||||
for dirpath, _, filenames in os.walk(self.ent_input_orgalogs.get()):
|
||||
for f in filenames:
|
||||
with open(os.path.join(dirpath, f), 'r', errors='surrogateescape') as in_f:
|
||||
last_year = -1
|
||||
last_month = -1
|
||||
last_day = -1
|
||||
out_f = None
|
||||
if len(self.ent_charname_orgalogs.get()) == 0:
|
||||
name_start = f.find("log_")
|
||||
name_end = f.find("_", name_start+4)
|
||||
if name_end == -1:
|
||||
name_end = f.find(".", name_start+4)
|
||||
if name_start != -1:
|
||||
self.ent_charname_orgalogs.delete(0, tk.END)
|
||||
self.ent_charname_orgalogs.insert(0, f[name_start+4:name_end])
|
||||
charname = self.ent_charname_orgalogs.get().lower()
|
||||
manual_check_p = self.make_path_safe(os.path.join(self.ent_output_orgalogs.get(), f"log_{charname}_manual_check.log"))
|
||||
manual_check_f = open(manual_check_p, 'a', errors='surrogateescape')
|
||||
for line in in_f:
|
||||
year_end = line.find('/')
|
||||
unclassified = False
|
||||
year = month = day = 0
|
||||
if year_end == -1 or year_end+3 >= len(line) or line[year_end+3] != '/':
|
||||
if last_year != -1:
|
||||
year, month, day = last_year, last_month, last_day
|
||||
else:
|
||||
unclassified = True
|
||||
else:
|
||||
try:
|
||||
year = int(line[:year_end])
|
||||
month = int(line[year_end+1:year_end+3])
|
||||
day = int(line[year_end+4:year_end+6])
|
||||
except ValueError:
|
||||
unclassified = True
|
||||
if not unclassified and (year != last_year or month != last_month or day != last_day):
|
||||
if out_f != None:
|
||||
out_f.close()
|
||||
out_p = self.make_path_safe(os.path.join(self.ent_output_orgalogs.get(), charname, f"{year:04d}", f"{month:02d}", f"log_{charname}_{year:04d}_{month:02d}_{day:02d}.log"))
|
||||
out_f = open(out_p, 'a', errors='surrogateescape')
|
||||
if unclassified:
|
||||
manual_check_f.write(line)
|
||||
else:
|
||||
out_f.write(line)
|
||||
last_year = year
|
||||
last_month = month
|
||||
last_day = day
|
||||
if out_f != None:
|
||||
out_f.close()
|
||||
manual_check_f.close()
|
||||
|
||||
def make_path_safe(self, path):
|
||||
if path in self.my_pathes:
|
||||
return self.my_pathes[path]
|
||||
(dirpath, filename) = os.path.split(path)
|
||||
(basefile, ext) = os.path.splitext(filename)
|
||||
if ext == '':
|
||||
os.makedirs(path, exist_ok=True)
|
||||
self.my_pathes[path] = path
|
||||
return path
|
||||
else:
|
||||
btn_chan_toggle[index].config(relief="sunken", bg="#99e599")
|
||||
chan_toggle[index] = True
|
||||
if channel_names[index] == "SYSTEM":
|
||||
frm_btn_sys.grid()
|
||||
return tgl_chan
|
||||
os.makedirs(dirpath, exist_ok=True)
|
||||
counter = 1
|
||||
new_path = path
|
||||
while os.path.exists(new_path):
|
||||
new_path = os.path.join(dirpath, f"{basefile}_{counter}{ext}")
|
||||
counter += 1
|
||||
self.my_pathes[path] = new_path
|
||||
return new_path
|
||||
|
||||
|
||||
def check_path_exists(self, attribute):
|
||||
if not hasattr(self, attribute) or getattr(self, attribute) == None or not os.path.exists(getattr(self, attribute).get()):
|
||||
tk.messagebox.showerror(title="Error in files selection", message=f"Error with input/output files. Make sur the input/output files or directories are set and exist")
|
||||
return False
|
||||
return True
|
||||
|
||||
def toggle_system(index):
|
||||
def tgl_sys():
|
||||
if sys_toggle[index]:
|
||||
btn_sys_toggle[index].config(relief="raised", bg="#ffcccb")
|
||||
sys_toggle[index] = False
|
||||
else:
|
||||
btn_sys_toggle[index].config(relief="sunken", bg="#99e599")
|
||||
sys_toggle[index] = True
|
||||
return tgl_sys
|
||||
|
||||
|
||||
input_filepath = ''
|
||||
output_filepath = ''
|
||||
btn_chan_toggle = []
|
||||
btn_sys_toggle = []
|
||||
chan_toggle = [False] * len(channel_names)
|
||||
sys_toggle = [False] * len(system_info_categories)
|
||||
ent_input = None
|
||||
ent_output = None
|
||||
ent_outfile = None
|
||||
frm_btn_sys = None
|
||||
btn_process = None
|
||||
window = None
|
||||
|
||||
def create_ui():
|
||||
global btn_chan_toggle
|
||||
global btn_sys_toggle
|
||||
global chan_toggle
|
||||
global sys_toggle
|
||||
global ent_input
|
||||
global ent_output
|
||||
global ent_outfile
|
||||
global frm_btn_sys
|
||||
global window
|
||||
global btn_process
|
||||
|
||||
window = tk.Tk()
|
||||
window.title("Ryzom Log Cleaner")
|
||||
|
||||
window.columnconfigure(0, weight=1)
|
||||
#window.rowconfigure([0,1], minsize=50)
|
||||
|
||||
|
||||
btn_input = tk.Button(window, text="Input file", command=get_input_filepath)
|
||||
ent_input = tk.Entry(window, text="Input path")
|
||||
# ent_input.insert(0, "~/log.txt")
|
||||
btn_output = tk.Button(window, text="Output directory", command=get_output_filepath)
|
||||
ent_output = tk.Entry(window, text="Output path")
|
||||
# ent_output.insert(0, "~/cleaned/")
|
||||
frm_outfile = tk.Frame(window)
|
||||
lbl_outfile = tk.Label(frm_outfile, text="Output filename:")
|
||||
ent_outfile = tk.Entry(frm_outfile, text="Output filename")
|
||||
|
||||
btn_input.grid(row=0, column=1)
|
||||
ent_input.grid(row=0, column=0, sticky='ew')
|
||||
btn_output.grid(row=1, column=1)
|
||||
ent_output.grid(row=1, column=0, sticky='ew')
|
||||
|
||||
frm_outfile.grid(row=2, column=0, columnspan=2, sticky='ew')
|
||||
frm_outfile.columnconfigure(1, weight=1)
|
||||
|
||||
lbl_outfile.grid(row=0, column=0)
|
||||
ent_outfile.grid(row=0, column=1, sticky='ew')
|
||||
|
||||
|
||||
|
||||
lbl_channel_select = tk.Label(window, text="Select channels to keep:")
|
||||
lbl_channel_select.grid(row=3, column=0, sticky='w')
|
||||
|
||||
btn_chan_toggle = []
|
||||
|
||||
frm_btn_channel = tk.Frame(window)
|
||||
frm_btn_channel.grid(row=4, column=0, columnspan=2, sticky='ew')
|
||||
frm_btn_channel.columnconfigure([0,1,2,3], weight=1)
|
||||
frm_btn_channel.rowconfigure([0,1,2], weight=1)
|
||||
for i,name in enumerate(channel_names):
|
||||
btn_chan_toggle.append(tk.Button(frm_btn_channel, text=name, command=toggle_channel(i), bg="#ffcccb"))
|
||||
btn_chan_toggle[i].grid(row=int(i/4), column=i%4, sticky='ew')
|
||||
|
||||
btn_sys_toggle = []
|
||||
|
||||
frm_btn_sys = tk.Frame(window, bg="#808080", borderwidth=5)
|
||||
frm_btn_sys.grid(row=5, column=0, columnspan=2, sticky='e')
|
||||
frm_btn_sys.columnconfigure([0,1,2,3,4,5,6], weight=1)
|
||||
frm_btn_sys.rowconfigure([0,1,2,3,4], weight=1)
|
||||
for i,(name,tooltip) in enumerate(system_info_categories):
|
||||
btn_sys_toggle.append(tk.Button(frm_btn_sys, text=name, command=toggle_system(i), bg="#ffcccb"))
|
||||
btn_sys_toggle[i].grid(row=int(i/7), column=i%7, sticky='ew')
|
||||
ttp_sys = CreateToolTip(btn_sys_toggle[i], tooltip)
|
||||
|
||||
btn_process = tk.Button(window, text="Process!", command=process_file)
|
||||
btn_process.grid(row=6, column=0, columnspan=2, sticky='ew')
|
||||
|
||||
# Default selection
|
||||
chan_toggle = [False] * len(channel_names)
|
||||
sys_toggle = [False] * len(system_info_categories)
|
||||
toggle_channel(0)()
|
||||
toggle_channel(1)()
|
||||
toggle_channel(12)()
|
||||
toggle_channel(13)()
|
||||
toggle_system(7)()
|
||||
|
||||
return window
|
||||
|
||||
color_regex = re.compile('@\{[A-F0-9]{4}\}')
|
||||
keep_color = False
|
||||
keep_channel = False
|
||||
language_flag = False
|
||||
original_part = False
|
||||
translated_part = True
|
||||
|
||||
def process_file():
|
||||
chan_pattern = '|'.join(['\(' + name + '\)' for i,name in enumerate(channel_names[:-2]) if chan_toggle[i]])
|
||||
if chan_toggle[-2]:
|
||||
chan_pattern += '|\(SAY/EMT\)'
|
||||
if chan_toggle[-1]:
|
||||
if sys_toggle[0]:
|
||||
chan_pattern += '|\(SYSTEM\)'
|
||||
for i,(name,tooltip) in enumerate(system_info_categories[1:]):
|
||||
if sys_toggle[i+1]:
|
||||
chan_pattern += '|\(SYSTEM/' + name + '\)'
|
||||
chan_regex = re.compile(chan_pattern)
|
||||
with open(ent_input.get(), 'r', errors='surrogateescape') as in_file, open(ent_output.get() + '/' + ent_outfile.get(), 'w', errors='surrogateescape') as out_file:
|
||||
orig_lines = 0
|
||||
filtered_lines = 0
|
||||
btn_process["text"] = "Started Processing..."
|
||||
for line in in_file:
|
||||
orig_lines += 1
|
||||
if chan_regex.search(line) == None:
|
||||
continue
|
||||
if not keep_color:
|
||||
line = color_regex.sub('',line)
|
||||
if not keep_channel:
|
||||
line = line[line.find(') * ')+4:]
|
||||
translation_start = line.find('{:')
|
||||
if translation_start != -1 and not language_flag:
|
||||
line = line[:translation_start+1] + line[translation_start+5:]
|
||||
translation_end = line.find('}@{')
|
||||
if translation_end != -1 and not original_part:
|
||||
line = line[:translation_start] + line[translation_end+3:]
|
||||
# char_name_start = line.find(' * ') + 3 if not keep_color or line.find('}') == -1 else line.find('}') + 1
|
||||
# char_name = ' '.join(line[char_name_start:line[char_name_start:].find(':')].split(' ')[:-1])
|
||||
# if char_name[0] == '[' and char_name[2] == ']':
|
||||
# char_name = char_name[3:]
|
||||
# channel_name = line[21:line.find(')')]
|
||||
out_file.write(line.lstrip())
|
||||
filtered_lines += 1
|
||||
btn_process["text"]="Processing done! (" + str(filtered_lines) + " lines kept out of " + str(orig_lines) + " original lines)"
|
||||
|
||||
originalfolderlog = "./logsource"
|
||||
finalfolder = "./final_logs"
|
||||
charname = "test"
|
||||
tmpfolder = "./tmpfolder"
|
||||
|
||||
def order_logs():
|
||||
(dirpath, _, filenames) = os.walk(originalfolderlog).next()
|
||||
for f in filenames:
|
||||
with open(os.path.join(dirpath, f), 'r') as in_f:
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
window = create_ui()
|
||||
gui = GUI()
|
||||
|
||||
window.mainloop()
|
||||
gui.window.mainloop()
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue