import os import shutil import re import yaml import qrcode from qrcode.image.styledpil import StyledPilImage from qrcode.image.styles.moduledrawers import RoundedModuleDrawer, GappedSquareModuleDrawer from qrcode.image.styles.colormasks import SolidFillColorMask import PIL from PIL import Image, ImageDraw, ImageFont # ============================================ FUNÇÕES ================================================== def extract_qrcode_info(filename, quantidade, pasta, config): cor = config['cor'] site_de_publicacao = config['site_de_publicacao'] livro_url = config['livro_url'] ark = None if 'ark' in config: ark = 'https://n2t.net/'+config['ark'] with open(filename, 'r', encoding='utf-8') as file: markdown_text = file.read() # Definindo o padrão de expressão regular para capturar o conteúdo entre ::: { e } pattern = r':::\s*\{([^{}]*)\}\s*(.*?)\s*:::' matches = re.findall(pattern, markdown_text, re.DOTALL) # Loop pelas correspondências encontradas for match in matches: div_attributes = match[0].strip() content = match[1].strip() # Verifica se a div tem a classe .qrcode if '.qrcode' in div_attributes: quantidade += 1 print("------------ INICIO -------------", quantidade) print("Atributos:", div_attributes) print("Conteúdo:", content) # Verifica se a div tem a classe .content-visible content_visible = '.content-visible' in div_attributes if content_visible: print("Tem a classe .content-visible") # Extrai o valor do atributo when-format when_format_match = re.search(r'when-format="([^"]+)"', div_attributes) print("whenformat: ", when_format_match) if when_format_match: start_index = when_format_match.start() end_index = when_format_match.end() when_format_text = div_attributes[start_index:end_index] print("FORMA: ",when_format_text) else: print("Não tem a classe .content-visible") qrcor_attr = re.search(r'qrcor="([^"]+)"', div_attributes) if qrcor_attr: start_index = qrcor_attr.start() end_index = qrcor_attr.end() qrcor_text = div_attributes[start_index:end_index] padrao = r'"(.*?)"' resultados = re.findall(padrao, qrcor_text) print("RESULTADOS: ",resultados) if resultados[0] == "0": qrcor = False else: qrcor = True else: qrcor = True # ================================ GERAR QRCODE ================================ if not hasattr(PIL.Image, 'Resampling'): PIL.Image.Resampling = PIL.Image hex_color = cor rgb_color = hex_to_rgb(hex_color) qr = qrcode.QRCode(error_correction=qrcode.constants.ERROR_CORRECT_H) # ++++++++++++++++++++ DEFININDO OS LINKS DOS QR CODES +++++++++++++++++++++++++++++++++++++++++++++ # define qual será a base para os links internos no qrcode + if ark is not None: base = ark else: base = site_de_publicacao+'/'+livro_url # verifica se o link é externo ou interno if not 'http' in content and '#' in content: #link interno # Verifica se é para o um capítulo diferente do avaliado. Se tiver a barra, entao é para outro capítulo if '/' in content: content = base +'/'+ content else: cap = filename.split('.')[0] content = base +'/'+ cap +'/'+ content qr.add_data(content) qr_inner_eyes_img = qr.make_image(image_factory=StyledPilImage, eye_drawer=RoundedModuleDrawer(radius_ratio=1), color_mask=SolidFillColorMask(front_color=(rgb_color['red'], rgb_color['green'], rgb_color['blue']))) qr_outer_eyes_img = qr.make_image(image_factory=StyledPilImage, eye_drawer=RoundedModuleDrawer(radius_ratio=1)) qr_img = qr.make_image(image_factory=StyledPilImage, module_drawer=GappedSquareModuleDrawer(), embeded_image_path="editora/logo_roxo.png") inner_eye_mask = style_inner_eyes(qr_img) outer_eye_mask = style_outer_eyes(qr_img) intermediate_img = Image.composite(qr_inner_eyes_img, qr_img, inner_eye_mask) final_image = Image.composite(qr_outer_eyes_img, intermediate_img, outer_eye_mask) final_image = final_image.convert('CMYK') # Verifica se tem que ser preto e branco if not qrcor: final_image = final_image.convert('L') final_image = final_image.convert('CMYK') # Separa os canais CMYK c, m, y, k = final_image.split() # Cria novos canais C, M e Y com todos os valores definidos como zero c_new = c.point(lambda x: 0) m_new = m.point(lambda x: 0) y_new = y.point(lambda x: 0) # Cria uma nova imagem CMYK com os canais ajustados e o canal K original final_image = Image.merge('CMYK', (c_new, m_new, y_new, k)) arq = "qrcode_" + str(quantidade) + ".jpg" caminho_e_arq = os.path.join(pasta, arq) final_image.save(caminho_e_arq, quality=100) print("QRCOR: ",qrcor) print("------------ FIM -------------") return quantidade def obter_capitulos(arquivo_yaml): with open(arquivo_yaml, 'r') as file: # Carrega o conteúdo do arquivo YAML conteudo = yaml.safe_load(file) # Verifica se a chave 'capítulos' está presente no YAML if 'capitulos' in conteudo: return conteudo['capitulos'] else: print("A chave 'capítulos' não foi encontrada no YAML.") return None # A ideia aqui é obter as configuracoes do qrcode bem como o identificador ark e o site para publicacao def obter_metadados(arquivo_yaml): metadados = {} with open(arquivo_yaml, 'r') as file: # Carrega o conteúdo do arquivo YAML conteudo = yaml.safe_load(file) # Verifica se a chave 'capítulos' está presente no YAML if 'qrcode' in conteudo: metadados['cor'] = conteudo['qrcode']['cor'] if 'site-de-publicacao' in conteudo: metadados['site_de_publicacao'] = conteudo['site-de-publicacao'] metadados['livro_url'] = conteudo['pasta-livro-finalizado']['html'] with open('_quarto-html.yml', 'r') as file: conteudo_1 = yaml.safe_load(file) if 'ark' in conteudo_1['moan-dados']: metadados['ark'] = conteudo_1['moan-dados']['ark'] return metadados def criar_ou_limpar_pasta(nome_pasta): # Verifica se o diretório já existe if os.path.exists(nome_pasta): # Remove todo o conteúdo da pasta for filename in os.listdir(nome_pasta): file_path = os.path.join(nome_pasta, filename) try: if os.path.isfile(file_path) or os.path.islink(file_path): os.unlink(file_path) elif os.path.isdir(file_path): shutil.rmtree(file_path) except Exception as e: print(f"Erro ao remover {file_path}: {e}") else: # Cria a pasta se não existir try: os.makedirs(nome_pasta) except OSError as e: print(f"Erro ao criar a pasta {nome_pasta}: {e}") # ============================================ FUNÇÕES QRCODE ================================================== def hex_to_rgb(hex_color): # Remover o '#' se presente hex_color = hex_color.lstrip('#') # Converter para valores RGB red = int(hex_color[0:2], 16) green = int(hex_color[2:4], 16) blue = int(hex_color[4:6], 16) # Retornar como um dicionário return {'red': red, 'green': green, 'blue': blue} # Custom function for eye styling. These create the eye masks def style_inner_eyes(img): img_size = img.size[0] eye_size = 70 # default quiet_zone = 40 # default mask = Image.new('L', img.size, 0) draw = ImageDraw.Draw(mask) draw.rectangle((60, 60, 90, 90), fill=255) #top left eye draw.rectangle((img_size-90, 60, img_size-60, 90), fill=255) #top right eye draw.rectangle((60, img_size-90, 90, img_size-60), fill=255) #bottom left eye return mask def style_outer_eyes(img): img_size = img.size[0] eye_size = 70 # default quiet_zone = 40 # default mask = Image.new('L', img.size, 0) draw = ImageDraw.Draw(mask) draw.rectangle((40, 40, 110, 110), fill=255) #top left eye draw.rectangle((img_size-110, 40, img_size-40, 110), fill=255) #top right eye draw.rectangle((40, img_size-110, 110, img_size-40), fill=255) #bottom left eye draw.rectangle((60, 60, 90, 90), fill=0) #top left eye draw.rectangle((img_size-90, 60, img_size-60, 90), fill=0) #top right eye draw.rectangle((60, img_size-90, 90, img_size-60), fill=0) #bottom left eye return mask # ============================================ FIM DAS FUNÇÕES QRCODE ================================================== # ============================================ FIM DAS FUNÇÕES GERAIS================================================== contador = 0 # Caminho para o arquivo YAML caminho_arquivo = '_moan-config.yml' # Obtém os capítulos do arquivo YAML capitulos = obter_capitulos(caminho_arquivo) # metadados qrcode config = obter_metadados(caminho_arquivo) pasta_qr = "qr_code" criar_ou_limpar_pasta(pasta_qr) if capitulos: for capitulo in capitulos: # Usando a função para extrair informações de um arquivo .qmd contador = extract_qrcode_info(capitulo, contador, pasta_qr,config) else: print("Nenhum capítulo encontrado no arquivo YAML.") # Aguardar entrada do usuário antes de fechar o terminal input("Pressione Enter para fechar o terminal...")