<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">import zipfile

from modules.logs.log_config import get_logger
from patch.include import *
from tqdm import tqdm


@app_context(commit=True)
def patch():
    """
    Р”Р»СЏ С‚РµСЃС‚РёСЂРѕРІР°РЅРёСЏ РїР°С‚С‡Р°: ( cd /opt/crm; python3 -m patch.20220XXXXXXX_PATCHNAME )
    Р—РґРµСЃСЊ РјРѕР¶РЅРѕ СЂР°Р±РѕС‚Р°С‚СЊ СЃ РјРѕРґРµР»СЏРјРё С‡РµСЂРµР· models.CmfTask Рё С‚.Рґ.
    Р”Р»СЏ РїСЂРѕРіСЂРµСЃСЃР±Р°СЂР° РёСЃРїРѕР»СЊР·СѓР№С‚Рµ:
    for task in tqdm(models.CmfTask.list()):
        ...
    """
    logger = get_logger('patch')
    root = '/opt/var/backup/files'
    os_max_length = 127
    for code in tqdm(os.listdir(root)):
        document = models.CmfDocument.get(code=code)
        logger.info(f'Р”РѕРєСѓРјРµРЅС‚ {document}')
        for filename in os.listdir(f'{root}/{code}'):
            file_path = f'{root}/{code}/{filename}'
            if zipfile.is_zipfile(file_path):
                with zipfile.ZipFile(file_path) as myzip:
                    for zip_attach_name in myzip.namelist():
                        if zip_attach_name.endswith('/'):
                            continue
                        logger.info(f'zip_attach_name={zip_attach_name}')
                        attach_name = zip_attach_name
                        ext = ''
                        if len(attach_name.split('.')) &gt; 0:
                            ext = attach_name.split('.')[-1]
                        if len(attach_name) &gt; os_max_length:
                            attach_name = f'{attach_name[:os_max_length - (5 + len(ext))].strip()}-{short_str_enc(attach_name, 4)}'
                            if ext:
                                attach_name = f'{attach_name}.{ext}'
                            logger.info(f'РќРѕРІРѕРµ РёРјСЏ: {attach_name}')
                        attach = models.CmfAttachment.get(filter=[['parent', '==', document],
                                                                  ['name', '==', attach_name]], fields=['url'])
                        if not attach:
                            attach = models.CmfAttachment(parent=document, name=attach_name)
                            attach.save()
                            logger.info(f'РЎРѕР·РґР°Р»Рё РІР»РѕР¶РµРЅРёРµ {attach}')
                        try:
                            with myzip.open(zip_attach_name) as attach_f:
                                attach.upload_file(attach_f.read(), overwrite=True)
                            logger.info(f'Р—Р°РіСЂСѓР·РёР»Рё {attach.url}')
                        except Exception as e:
                            logger.error(f'РќРµ СѓРґР°Р»РѕСЃСЊ СЃРѕС…СЂР°РЅРёС‚СЊ {zip_attach_name}: {e}')
            else:
                logger.info(f'attach_name={filename}')
                attach = models.CmfAttachment.get(filter=[['parent', '==', document],
                                                          ['name', '==', filename]], fields=['url'])
                if not attach:
                    attach = models.CmfAttachment(parent=document, name=filename)
                    attach.save()
                    logger.info(f'РЎРѕР·РґР°Р»Рё РІР»РѕР¶РµРЅРёРµ {attach}')
                with myzip.open(file_path) as attach_f:
                    attach.upload_file(attach_f.read(), overwrite=True)
                logger.info(f'Р—Р°РіСЂСѓР·РёР»Рё {attach.url}')

        models.CmfDocument.dp.commit()


import hashlib

enc_table_16 = "0123456789abcdef"
enc_table_64 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"


def int_to_enc(n, enc_table):
    """Encode integer into string, using digit encoding table.

    You can encode integer into hexadecimal string:

    &gt;&gt;&gt; int_to_enc(20190925, enc_table_16)
    '13416cd'

    To verify use, python's hex() function:

    &gt;&gt;&gt; hex(20190925)
    '0x13416cd'

    You can encode integer using 64 digit table:

    &gt;&gt;&gt; int_to_enc(20190925, enc_table_64)
    '1d1rd'

    """
    if n == 0:
        return enc_table[0]

    base = len(enc_table)
    digits = ""
    while n:
        digits += enc_table[int(n % base)]
        n //= base
    return digits[::-1]

def short_str_enc(s, char_length=8, enc_table=enc_table_64):
    """Geneate string hash with given length, using specified encoding table.

    Example 1:

    Generating hash with length of 8 characters, using hexadecimal encoding table:

    &gt;&gt;&gt; short_str_enc("hello world", 8, enc_table_16)
    '309ecc48'

    Generating hash with length of 8 charactes, using extended 64-digit encoding table:

    &gt;&gt;&gt; short_str_enc("hello world", 8, enc_table_64)
    'MDIN8D1b'
    """

    if char_length &gt; 128:
        raise ValueError("char_length {} exceeds 128".format(char_length))
    hash_object = hashlib.sha512(s.encode())
    hash_hex = hash_object.hexdigest()
    hash_enc = int_to_enc(int(hash_hex, 16), enc_table)
    return hash_enc[0:char_length]


if __name__ == "__main__":
    patch()
</pre></body></html>