diff --git a/Dockerfile b/Dockerfile index 997e10a..9aa7e56 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,12 @@ FROM python:3.8-slim-buster WORKDIR /app +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + wkhtmltopdf \ + gcc \ + libpq-dev \ + && rm -rf /var/lib/apt/lists/* RUN pip install \ pylint \ diff --git a/app/api.py b/app/api.py index 7dee007..110310f 100644 --- a/app/api.py +++ b/app/api.py @@ -1,12 +1,18 @@ """API Module""" import os -from flask import Flask, json +import tempfile +from flask import Flask, json, render_template, request, jsonify, send_file from cifraclub import CifraClub +from get_pdf import create_pdf_with_columns_portrait as gen_pdf app = Flask(__name__) -@app.route('/') +@app.route("/") +def index(): + return render_template("index.html") + +@app.route('/home') def home(): """Home route""" return app.response_class( @@ -15,14 +21,44 @@ def home(): mimetype='application/json' ) + +@app.route("/submit", methods=["POST"]) +def submit(): + data = request.json + items = data["items"] + file_name = data["fileName"] + + # Criando um arquivo temporário para armazenar o PDF + with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as temp_pdf: + temp_file_path = temp_pdf.name # Caminho do arquivo temporário + + # Gerar o PDF no arquivo temporário + gen_pdf(items, temp_file_path) + + # Enviar o arquivo para o cliente + try: + return send_file( + temp_file_path, as_attachment=True, download_name=f"{file_name}.pdf" + ) + finally: + # Após o envio, deletar o arquivo temporário + if os.path.exists(temp_file_path): + os.remove(temp_file_path) + + @app.route('/artists//songs/') def get_cifra(artist, song): """Get cifra by artist and song""" cifrablub = CifraClub() + musica = cifrablub.cifra(artist, song) + + saida = f"Artista: {musica['artist']}\nMusica: {musica['name']}\nYoutube: {musica['youtube_url']}\n\n" + for cifra in musica['cifra']: + saida = saida + "\n "+cifra return app.response_class( - response=json.dumps(cifrablub.cifra(artist, song), ensure_ascii=False), + response=saida, status=200, - mimetype='application/json' + mimetype="application/json", ) if __name__ == "__main__": diff --git a/app/cifraclub.py b/app/cifraclub.py index 3c2872d..601547a 100644 --- a/app/cifraclub.py +++ b/app/cifraclub.py @@ -3,14 +3,24 @@ from bs4 import BeautifulSoup from selenium import webdriver from selenium.webdriver.common.by import By -from selenium.webdriver.common.desired_capabilities import DesiredCapabilities +# from selenium.webdriver.common.desired_capabilities import DesiredCapabilities +from selenium.webdriver.firefox.options import Options CIFRACLUB_URL = "https://www.cifraclub.com.br/" class CifraClub(): """CifraClub Class""" def __init__(self): - self.driver = webdriver.Remote("http://selenium:4444/wd/hub", DesiredCapabilities.FIREFOX) + options = Options() + options.add_argument('--headless') # Executar o navegador em modo headless (opcional) + options.add_argument('--no-sandbox') # Necessário em alguns ambientes como Docker + options.add_argument('--disable-dev-shm-usage') # Evita problemas de memória compartilhada + + self.driver = webdriver.Remote( + command_executor="http://selenium:4444/wd/hub", + options=options, + # desired_capabilities=options.to_capabilities() # Garante compatibilidade + ) def cifra(self, artist: str, song: str) -> dict: """Lê a página HTML e extrai a cifra e meta dados da música.""" diff --git a/app/get_pdf.py b/app/get_pdf.py new file mode 100644 index 0000000..ec88825 --- /dev/null +++ b/app/get_pdf.py @@ -0,0 +1,63 @@ +from reportlab.lib.pagesizes import letter, A4 +from reportlab.pdfgen import canvas +from reportlab.lib.units import inch +import requests + + +def create_pdf_with_columns_portrait(data_list, output_pdf): + # Configurações básicas para o formato retrato + page_width, page_height = A4 + margin = 0.2 * inch + column_gap = 0.1 * inch + column_width = (page_width - 2 * margin - column_gap) / 2 + + # Iniciar canvas + c = canvas.Canvas(output_pdf, pagesize=A4) + + for data in data_list: + text_obj = c.beginText() + text_obj.setFont("Courier", 9) + text_obj.setTextOrigin(margin, page_height - margin) + + title = data["title"] + link = data["link"] + + # Extrair artista e música do link + artista, musica = link.rstrip("/").split("/")[-2:] + url = f"http://localhost:3000/artists/{artista}/songs/{musica}" + response = requests.get(url) + response.raise_for_status() + text = response.text + + # Escrever título (opcional) + text_obj.setFont("Courier-Bold", 10) + text_obj.textLine(f"{title}") + text_obj.setFont("Courier", 9) + text_obj.textLine("") # Linha em branco + + column = 0 + for line in text.splitlines(): + if text_obj.getY() < margin: + # Alternar coluna ou adicionar nova página + if column == 0: + column = 1 + text_obj.setTextOrigin( + margin + column_width + column_gap, page_height - margin + ) + else: + c.drawText(text_obj) + c.showPage() + text_obj = c.beginText() + text_obj.setFont("Courier", 9) + text_obj.setTextOrigin(margin, page_height - margin) + column = 0 + + # Adicionar linha ao texto + text_obj.textLine(line.rstrip()) + + # Renderizar o conteúdo do link na página atual + c.drawText(text_obj) + c.showPage() # Garantir nova página para o próximo link + + # Renderizar a última página + c.save() diff --git a/app/requirements.txt b/app/requirements.txt index 9502b39..353829b 100644 --- a/app/requirements.txt +++ b/app/requirements.txt @@ -1,3 +1,6 @@ -Flask==2.2.2 -beautifulsoup4==4.11.1 -selenium==4.6.0 +flask +bs4 +selenium +pdfkit +reportlab +requests \ No newline at end of file diff --git a/app/src/format.css b/app/src/format.css new file mode 100644 index 0000000..6b8e043 --- /dev/null +++ b/app/src/format.css @@ -0,0 +1,5 @@ + body { + column-count: 2; + column-gap: 1.5em; + /* Ajuste o espaçamento entre as colunas */ + } \ No newline at end of file diff --git a/app/templates/index.html b/app/templates/index.html new file mode 100644 index 0000000..2e1a951 --- /dev/null +++ b/app/templates/index.html @@ -0,0 +1,125 @@ + + + + + + + Formulário + + + + + + + + +
+

Criando SetList

+
+
+ + +
+
+ + +
+ +
+ +

Lista de músicas

+ + +
+ + +
+ + + + + +
+ + + + + + \ No newline at end of file