smart-patcher 0.7.0

Patcher based on rules
Documentation
#!/usr/bin/env python

# this is test patch for `src/patch.rs` tests,
# but you also can use it for decoding and encoding `*.docx` files
import json
import os
import os.path
import shutil
import sys
import uuid
from xml.dom import minidom
import zipfile


OPENER = '<w:t>'
CLOSER = '</w:t>'
REPL = ' '

# this is `docx` decoder. it replaces all styles by the least used character and saves the replacement table into temp folder
def decode(path: str) -> str:
  with zipfile.ZipFile(path) as docx:
    content = docx.read('word/document.xml').decode('utf-8')

  replacement_table = {}
  cntr = 1

  l = 0

  while (b := content.find(OPENER, l)) != -1:
    replacement_table[REPL * cntr] = content[l : b + len(OPENER)]
    content = content[:l] + REPL * cntr + content[b + len(OPENER):]
    l = content.find(CLOSER, l)
    cntr += 1
  replacement_table[REPL * cntr] = content[l:]
  content = content[:l] + REPL * cntr

  with open('/tmp/smart-patcher-decode-info.json', "w") as f:
    json.dump(replacement_table, f)

  return content


# this is `docx` encoder. it replaces all styles back
def encode(content: str, path: str):
  replacement_table = {}
  with open('/tmp/smart-patcher-decode-info.json', "r") as f:
    replacement_table = json.load(f)

  sorted_keys = sorted(replacement_table.keys(), key=len, reverse=True)
  for key in sorted_keys:
    content = content.replace(key, replacement_table[key])

  with zipfile.ZipFile(path, 'r') as original:
    with zipfile.ZipFile('/tmp/smart-patcher-encode.docx', 'w') as temp:
      temp.writestr('word/document.xml', content)
      for item in original.infolist():
        if item.filename != 'word/document.xml':
          temp.writestr(item, original.read(item.filename))

  os.remove(path)
  shutil.copyfile('/tmp/smart-patcher-encode.docx', path)
  os.remove('/tmp/smart-patcher-encode.docx')
  os.remove('/tmp/smart-patcher-decode-info.json')


if __name__ == "__main__":
  if len(sys.argv) == 3:
    decode_input_file = sys.argv[1]
    decode_output_file = sys.argv[2]

    try:
      with open(decode_input_file, 'r', encoding='utf-8') as f:
        input_data = json.load(f)
      which_file_decode = input_data["encoded_file"]
      content = decode(which_file_decode)
      with open(decode_output_file, 'w', encoding='utf-8') as f:
        json.dump({"content": content}, f, ensure_ascii=False, indent=4)
    except Exception as e:
      print(f"Error: {str(e)}")
      sys.exit(1)

  if len(sys.argv) == 2:
    encode_input_file = sys.argv[1]

    try:
      with open(encode_input_file, 'r', encoding='utf-8') as f:
        input_data = json.load(f)
      which_file_encode = input_data["write_to_file"]
      content = input_data["content"]
      encode(content, which_file_encode)
    except Exception as e:
      print(f"Error: {str(e)}")
      sys.exit(1)