Convertinator / app.py
lazerkat's picture
Update app.py
aaec850 verified
import gradio as gr
import binascii
import os
import subprocess
import tempfile
from pathlib import Path
from typing import Tuple, List # Added Tuple import here
# Document Converter Class
class DocumentConverter:
def __init__(self):
self.temp_dir = tempfile.mkdtemp()
self.supported_conversions = {
".pdf": [".docx", ".txt", ".html"],
".docx": [".pdf", ".txt", ".html"],
".txt": [".pdf", ".docx", ".html"],
".html": [".pdf", ".docx", ".txt"]
}
def convert_document(self, input_path: str, output_ext: str) -> str:
"""Convert documents using LibreOffice"""
try:
output_path = os.path.join(self.temp_dir, f"{Path(input_path).stem}_converted{output_ext}")
subprocess.run([
"libreoffice", "--headless", "--convert-to",
output_ext[1:], "--outdir", self.temp_dir, input_path
], check=True)
return output_path
except Exception as e:
raise RuntimeError(f"Document conversion failed: {str(e)}")
# EXE to DOC Converter
def convert_exe_to_doc(input_path: str, output_name: str = "output.doc") -> str:
"""Convert EXE to DOC with embedded data"""
try:
with open(input_path, 'rb') as f:
file_content = f.read()
# RTF template (shortened for brevity)
rtf_template = "{\\rtf1\\ansi\\ansicpg1252\\deff0{\\fonttbl{\\f0\\fswiss\\fcharset0 Arial;}}"
hex_data = binascii.b2a_hex(file_content).decode()
output_dir = "outputs"
os.makedirs(output_dir, exist_ok=True)
output_path = os.path.join(output_dir, output_name if output_name.endswith('.doc') else f"{output_name}.doc")
with open(output_path, 'w', encoding='latin-1') as f:
f.write(rtf_template + hex_data + "{}}}}}}")
return output_path
except Exception as e:
raise RuntimeError(f"EXE conversion failed: {str(e)}")
def update_ui(file_info: gr.File) -> List:
"""Update UI components based on file type"""
if not file_info:
return [
gr.Dropdown(visible=False), # format_dropdown
gr.Textbox(visible=False), # exe_name_input
gr.Button(visible=False) # convert_btn
]
filename = file_info.name.lower()
if filename.endswith('.exe'):
return [
gr.Dropdown(visible=False),
gr.Textbox(visible=True, value="converted.doc"),
gr.Button(visible=True)
]
else:
ext = Path(filename).suffix.lower()
doc_converter = DocumentConverter()
formats = doc_converter.supported_conversions.get(ext, [])
return [
gr.Dropdown(
visible=bool(formats),
choices=[f[1:].upper() for f in formats], # Remove dot and uppercase
value=formats[0][1:].upper() if formats else None
),
gr.Textbox(visible=False),
gr.Button(visible=bool(formats))
]
def convert_file(file_info: gr.File, output_format: str, exe_output_name: str) -> Tuple[str, str]:
"""Handle file conversion"""
if not file_info:
raise gr.Error("Please upload a file first")
filename = file_info.name.lower()
try:
if filename.endswith('.exe'):
output_path = convert_exe_to_doc(file_info.name, exe_output_name)
return output_path, "EXE to DOC conversion successful!"
else:
if not output_format:
raise gr.Error("Please select an output format")
output_path = DocumentConverter().convert_document(file_info.name, f".{output_format.lower()}")
return output_path, f"Converted to {output_format.upper()} successfully!"
except Exception as e:
raise gr.Error(str(e))
with gr.Blocks(title="Universal Converter") as app:
gr.Markdown("# Universal File Converter")
gr.Markdown("Convert EXE to DOC or between document formats")
with gr.Row():
with gr.Column():
file_input = gr.File(label="Upload File")
format_dropdown = gr.Dropdown(
label="Output Format",
visible=False,
interactive=True
)
exe_name_input = gr.Textbox(
label="Output DOC Name",
visible=False,
value="converted.doc"
)
convert_btn = gr.Button("Convert", visible=False)
with gr.Column():
output_file = gr.File(label="Download Converted File")
status = gr.Textbox(label="Status", interactive=False)
# Update UI when file is uploaded
file_input.change(
update_ui,
inputs=file_input,
outputs=[format_dropdown, exe_name_input, convert_btn]
)
# Handle conversion
convert_btn.click(
convert_file,
inputs=[file_input, format_dropdown, exe_name_input],
outputs=[output_file, status]
)
if __name__ == "__main__":
app.launch()