corrigindo upload
Deploy / Deploy (push) Failing after 25m21s Details

This commit is contained in:
JotaChina 2026-04-04 12:42:42 -03:00
parent a8fdfde48e
commit f8ebce56a5
13 changed files with 6848493 additions and 979755 deletions

View File

@ -43,16 +43,16 @@ page_gen:
# Excluded items can be processed by explicitly listing the directories or # Excluded items can be processed by explicitly listing the directories or
# their entries' file path in the `include:` list. # their entries' file path in the `include:` list.
# #
#exclude: # Exclude from processing.
# - .sass-cache/ exclude:
# - .jekyll-cache/ - .sass-cache/
# - gemfiles/ - .jekyll-cache/
# - Gemfile - gemfiles/
# - Gemfile.lock - Gemfile
# - node_modules/ - Gemfile.lock
# - vendor/bundle/ - node_modules/
# - vendor/cache/ - vendor/ # Ignora toda a pasta vendor de uma vez
# - vendor/gems/ - scripts/ # Seus scripts Python não vão para o HTML
# - vendor/ruby/ - venv/ # Se você tiver um ambiente virtual Python aí dentro
# - scripts/ # - "*.db" # Ignora bancos de dados do SQLite (como o users.db)
#- mmp/instruments/lmms/presets/ZynAddSubFX - mmp/instruments/lmms/presets/ZynAddSubFX

View File

@ -0,0 +1,730 @@
bpm: '140'
file: a-return-from-the-dancing-stars
original_title: a-return-from-the-dancing-stars
src: /var/www/html/trens/src_mmpSearch/mmp/a-return-from-the-dancing-stars.mmp
tags:
TAG:
- bassline
- plugin
- automation
automation:
- Traccia di automazione
bassline:
- Kick
- HiHatC
plugin:
- audiofileprocessor
- zynaddsubfx
sample: []
tracks:
- bassline_name: Kick
instruments:
- audiofileprocessor:
amp: '100'
eframe: '1'
interp: '1'
lframe: '0.02'
looped: '0'
reversed: '0'
sframe: '0.02'
src: drums/kick01.ogg
stutter: '0'
basenote: '57'
fxch: '1'
instrument_name: Kick
instrument_type: '0'
pan: '0'
patterns:
- name: Kick
pos: '0'
steps:
- false
- false
- true
- false
- true
- false
- false
- false
- true
- false
- false
- false
- true
- false
- false
- false
- name: Kick
pos: '192'
steps:
- false
- false
- false
- false
- false
- false
- false
- false
- false
- false
- false
- false
- false
- false
- false
- false
pitch: '0'
pitchrange: '1'
plugin_name: audiofileprocessor
usemasterpitch: '1'
vol: '100'
- audiofileprocessor:
amp: '100'
eframe: '1'
interp: '1'
lframe: '0'
looped: '0'
reversed: '0'
sframe: '0'
src: drums/hihat_closed01.ogg
stutter: '0'
basenote: '57'
fxch: '2'
instrument_name: hihat_closed01.ogg
instrument_type: '0'
pan: '0'
patterns:
- name: hihat_closed01.ogg
pos: '0'
steps:
- false
- false
- false
- false
- false
- false
- false
- false
- false
- false
- false
- false
- false
- false
- false
- false
- name: hihat_closed01.ogg
pos: '192'
steps:
- true
- false
- true
- false
- true
- false
- true
- false
- true
- false
- true
- false
- false
- true
- true
- true
pitch: '0'
pitchrange: '1'
plugin_name: audiofileprocessor
usemasterpitch: '1'
vol: '100'
- audiofileprocessor:
amp: '100'
eframe: '1'
interp: '1'
lframe: '0'
looped: '0'
reversed: '0'
sframe: '0'
src: drums/hihat_opened01.ogg
stutter: '0'
basenote: '57'
fxch: '3'
instrument_name: Piatto 1
instrument_type: '0'
pan: '0'
patterns:
- name: Piatto 1
pos: '0'
steps:
- false
- false
- true
- false
- false
- false
- false
- false
- false
- false
- false
- false
- false
- false
- false
- false
- name: Piatto 1
pos: '192'
steps:
- false
- false
- false
- false
- false
- false
- false
- false
- false
- false
- false
- false
- false
- false
- false
- false
pitch: '0'
pitchrange: '1'
plugin_name: audiofileprocessor
usemasterpitch: '1'
vol: '100'
playlist_clips:
- len: 2688
name: Kick
pos: 0
- len: 3072
name: Kick
pos: 5760
- len: 1536
name: Kick
pos: 9408
- len: 5376
name: Kick
pos: 14208
- len: 1920
name: Kick
pos: 10944
tags: audiofileprocessor
track_name: Kick
type: bassline
- arpeggiator:
arp: '0'
arp-enabled: '0'
arpcycle: '0'
arpdir: '0'
arpgate: '100'
arpmiss: '0'
arpmode: '0'
arprange: '2'
arpskip: '0'
arptime: '100'
arptime_denominator: '4'
arptime_numerator: '4'
arptime_syncmode: '0'
audiofileprocessor:
amp: '90'
eframe: '1'
interp: '1'
lframe: '0.09'
looped: '0'
reversed: '0'
sframe: '0.09'
src: drumsynth/misc_synth/wowmelodictone.ds
stutter: '0'
chordcreator:
chord: '0'
chord-enabled: '1'
chordrange: '3'
elcut:
amt: '0'
att: '0'
ctlenvamt: '0'
dec: '0.5'
hold: '0.5'
lamt: '1'
latt: '0'
lpdel: '0'
lshp: '0'
lspd: '0.01'
lspd_denominator: '4'
lspd_numerator: '4'
lspd_syncmode: '0'
pdel: '0'
rel: '0.1'
sustain: '0.5'
userwavefile: ''
x100: '0'
eldata:
fcut: '2940'
fres: '3.51'
ftype: '0'
fwet: '0'
elres:
amt: '0'
att: '0'
ctlenvamt: '0'
dec: '0.5'
hold: '0.5'
lamt: '0'
latt: '0'
lpdel: '0'
lshp: '0'
lspd: '0.1'
lspd_denominator: '4'
lspd_numerator: '4'
lspd_syncmode: '0'
pdel: '0'
rel: '0.1'
sustain: '0.5'
userwavefile: ''
x100: '0'
elvol:
amt: '1'
att: '0'
ctlenvamt: '0'
dec: '0'
hold: '0'
lamt: '0'
latt: '0'
lpdel: '0'
lshp: '0'
lspd: '0.1'
lspd_denominator: '4'
lspd_numerator: '4'
lspd_syncmode: '0'
pdel: '0'
rel: '0.23'
sustain: '0.95'
userwavefile: ''
x100: '0'
fxchain:
enabled: '1'
numofeffects: '3'
instrumenttrack:
basenote: '69'
fxch: '6'
pan: '0'
pitch: '0'
pitchrange: '1'
usemasterpitch: '1'
vol: '100'
midiport:
basevelocity: '127'
fixedinputvelocity: '0'
fixedoutputnote: '-1'
fixedoutputvelocity: '0'
inputchannel: '0'
inputcontroller: '0'
outputchannel: '1'
outputcontroller: '0'
outputprogram: '1'
readable: '0'
writable: '0'
plugin_name: audiofileprocessor
track_name: Tamburo Elettronico
type: plugin
- bassline_name: HiHatC
instruments: []
playlist_clips:
- len: 8832
name: HiHatC
pos: 0
- len: 7296
name: HiHatC
pos: 11520
- len: 1536
name: HiHatC
pos: 9408
tags: ''
track_name: HiHatC
type: bassline
- arpeggiator:
arp: '0'
arp-enabled: '0'
arpcycle: '0'
arpdir: '0'
arpgate: '100'
arpmiss: '0'
arpmode: '0'
arprange: '1'
arpskip: '0'
arptime: '100'
arptime_denominator: '4'
arptime_numerator: '4'
arptime_syncmode: '0'
chordcreator:
chord: '0'
chord-enabled: '0'
chordrange: '1'
controller:
bandwidth_depth: '64'
filter_cutoff_depth: '64'
filter_q_depth: '64'
mod_wheel_depth: '80'
panning_depth: '64'
pitchwheel_bendrange: '200'
portamento_pitchthresh: '3'
portamento_pitchthreshtype: '1'
portamento_portamento: '0'
portamento_propdepth: '90'
portamento_proportional: '0'
portamento_proprate: '80'
portamento_time: '64'
portamento_updowntimestretch: '64'
resonance_bandwidth_depth: '64'
resonance_center_depth: '64'
elcut:
amt: '0'
att: '0'
ctlenvamt: '0'
dec: '0.5'
hold: '0.5'
lamt: '0'
latt: '0'
lpdel: '0'
lshp: '0'
lspd: '0.1'
lspd_denominator: '4'
lspd_numerator: '4'
lspd_syncmode: '0'
pdel: '0'
rel: '0.1'
sustain: '0.5'
userwavefile: ''
x100: '0'
eldata:
fcut: '14000'
fres: '0.5'
ftype: '0'
fwet: '0'
elres:
amt: '0'
att: '0'
ctlenvamt: '0'
dec: '0.5'
hold: '0.5'
lamt: '0'
latt: '0'
lpdel: '0'
lshp: '0'
lspd: '0.1'
lspd_denominator: '4'
lspd_numerator: '4'
lspd_syncmode: '0'
pdel: '0'
rel: '0.1'
sustain: '0.5'
userwavefile: ''
x100: '0'
elvol:
amt: '0'
att: '0'
ctlenvamt: '0'
dec: '0.5'
hold: '0.5'
lamt: '0'
latt: '0'
lpdel: '0'
lshp: '0'
lspd: '0.1'
lspd_denominator: '4'
lspd_numerator: '4'
lspd_syncmode: '0'
pdel: '0'
rel: '0.1'
sustain: '0.5'
userwavefile: ''
x100: '0'
fxchain:
enabled: '1'
numofeffects: '2'
insertion_effects:
- part: '-1'
type: '0'
- part: '-1'
type: '0'
- part: '-1'
type: '0'
- part: '-1'
type: '0'
- part: '-1'
type: '0'
- part: '-1'
type: '0'
- part: '-1'
type: '0'
- part: '-1'
type: '0'
instrument_effects:
- route: '0'
type: '0'
- route: '0'
type: '0'
- route: '0'
type: '0'
instrument_name: zynaddsubfx
instrumenttrack:
basenote: '57'
fxch: '5'
pan: '0'
pitch: '0'
pitchrange: '1'
usemasterpitch: '1'
vol: '100'
midiport:
basevelocity: '127'
fixedinputvelocity: '-1'
fixedoutputnote: '-1'
fixedoutputvelocity: '-1'
inputchannel: '0'
inputcontroller: '0'
outputchannel: '1'
outputcontroller: '0'
outputprogram: '1'
readable: '0'
writable: '0'
system_effects:
- send_vol: '0'
type: '0'
vol: '0'
- send_vol: '0'
type: '0'
vol: '0'
- send_vol: '0'
type: '0'
vol: '0'
- type: '0'
vol: '0'
track_name: Basso Elettronico 1
type: plugin
- arpeggiator:
arp: '0'
arp-enabled: '0'
arpcycle: '0'
arpdir: '0'
arpgate: '100'
arpmiss: '0'
arpmode: '0'
arprange: '1'
arpskip: '0'
arptime: '100'
arptime_denominator: '4'
arptime_numerator: '4'
arptime_syncmode: '0'
chordcreator:
chord: '0'
chord-enabled: '0'
chordrange: '1'
controller:
bandwidth_depth: '64'
filter_cutoff_depth: '64'
filter_q_depth: '64'
mod_wheel_depth: '80'
panning_depth: '64'
pitchwheel_bendrange: '200'
portamento_pitchthresh: '3'
portamento_pitchthreshtype: '1'
portamento_portamento: '0'
portamento_propdepth: '90'
portamento_proportional: '0'
portamento_proprate: '80'
portamento_time: '64'
portamento_updowntimestretch: '64'
resonance_bandwidth_depth: '64'
resonance_center_depth: '64'
elcut:
amt: '0'
att: '0'
ctlenvamt: '0'
dec: '0.5'
hold: '0.5'
lamt: '0'
latt: '0'
lpdel: '0'
lshp: '0'
lspd: '0.1'
lspd_denominator: '4'
lspd_numerator: '4'
lspd_syncmode: '0'
pdel: '0'
rel: '0.1'
sustain: '0.5'
userwavefile: ''
x100: '0'
eldata:
fcut: '14000'
fres: '0.5'
ftype: '0'
fwet: '0'
elres:
amt: '0'
att: '0'
ctlenvamt: '0'
dec: '0.5'
hold: '0.5'
lamt: '0'
latt: '0'
lpdel: '0'
lshp: '0'
lspd: '0.1'
lspd_denominator: '4'
lspd_numerator: '4'
lspd_syncmode: '0'
pdel: '0'
rel: '0.1'
sustain: '0.5'
userwavefile: ''
x100: '0'
elvol:
amt: '0'
att: '0'
ctlenvamt: '0'
dec: '0.5'
hold: '0.5'
lamt: '0'
latt: '0'
lpdel: '0'
lshp: '0'
lspd: '0.1'
lspd_denominator: '4'
lspd_numerator: '4'
lspd_syncmode: '0'
pdel: '0'
rel: '0.1'
sustain: '0.5'
userwavefile: ''
x100: '0'
fxchain:
enabled: '1'
numofeffects: '1'
insertion_effects:
- part: '-1'
type: '0'
- part: '-1'
type: '0'
- part: '-1'
type: '0'
- part: '-1'
type: '0'
- part: '-1'
type: '0'
- part: '-1'
type: '0'
- part: '-1'
type: '0'
- part: '-1'
type: '0'
instrument_effects:
- route: '0'
type: '0'
- route: '0'
type: '0'
- route: '0'
type: '0'
instrument_name: zynaddsubfx
instrumenttrack:
basenote: '45'
fxch: '0'
pan: '0'
pitch: '0'
pitchrange: '1'
usemasterpitch: '1'
vol: '100'
midiport:
basevelocity: '127'
fixedinputvelocity: '-1'
fixedoutputnote: '-1'
fixedoutputvelocity: '-1'
inputchannel: '0'
inputcontroller: '0'
outputchannel: '1'
outputcontroller: '0'
outputprogram: '1'
readable: '0'
writable: '0'
system_effects:
- send_vol: '0'
type: '0'
vol: '0'
- send_vol: '0'
type: '0'
vol: '0'
- send_vol: '0'
type: '0'
vol: '0'
- type: '0'
vol: '0'
track_name: Strings Elettronica 4
type: plugin
- automations:
- automation_name: Traccia di automazione
automation_patterns:
- len: '1728'
mute: '0'
name: Volume principale
pos: '17280'
prog: '1'
tens: '1'
times:
- pos: '0'
value: '100'
- pos: '1536'
value: '6'
- len: '192'
mute: '0'
name: Volume principale
pos: '0'
prog: '0'
tens: '1'
times:
- pos: '0'
value: '100'
- len: '1536'
mute: '0'
name: Volume principale
pos: '14208'
prog: '1'
tens: '1'
times:
- pos: '0'
value: '100'
- pos: '576'
value: '199'
- pos: '1800'
value: '98'
- len: '1536'
mute: '0'
name: Volume principale
pos: '15744'
prog: '1'
tens: '1'
times:
- pos: '0'
value: '100'
- pos: '576'
value: '198'
- pos: '1800'
value: '98'
- len: '1536'
mute: '0'
name: Volume principale
pos: '4224'
prog: '1'
tens: '1'
times:
- pos: '0'
value: '100'
- pos: '576'
value: '199'
- pos: '1800'
value: '98'
automationtrack: Present
type: automation

File diff suppressed because it is too large Load Diff

833214
_data/all.yml

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

34344
_data/another-dancefloor.yml Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -1,3 +1,8 @@
---
### `manual.md`
```markdown
Documentação Técnica: Arquitetura e Implementação do MMPSearch & MMPCreator Documentação Técnica: Arquitetura e Implementação do MMPSearch & MMPCreator
1. Visão Geral da Arquitetura 1. Visão Geral da Arquitetura
O sistema foi projetado para resolver o desafio de catalogar, processar e permitir a colaboração em projetos musicais (formato LMMS) na web. A solução adota uma Arquitetura Híbrida Dinâmica-Estática: O sistema foi projetado para resolver o desafio de catalogar, processar e permitir a colaboração em projetos musicais (formato LMMS) na web. A solução adota uma Arquitetura Híbrida Dinâmica-Estática:
@ -24,14 +29,14 @@ A funcionalidade mais crítica para a dissertação é a capacidade de gerar áu
Ambiente Offscreen: O script configura a variável de ambiente QT_QPA_PLATFORM="offscreen". Isso engana o LMMS (que é uma aplicação gráfica Qt), permitindo que ele rode via linha de comando dentro do servidor Linux. Ambiente Offscreen: O script configura a variável de ambiente QT_QPA_PLATFORM="offscreen". Isso engana o LMMS (que é uma aplicação gráfica Qt), permitindo que ele rode via linha de comando dentro do servidor Linux.
Renderização CLI: O áudio é gerado invocando o comando: lmms -r <input.mmp> -o <output.wav> -f wav. Renderização CLI: O áudio é gerado invocando o comando: lmms -r <input.mmp> -o <output.ogg> -f ogg. (O formato OGG foi escolhido como padrão do pipeline assíncrono para otimizar transferência e armazenamento web).
Paralelismo: Utiliza-se a biblioteca multiprocessing para criar um pool de workers, permitindo que múltiplos projetos sejam renderizados simultaneamente, otimizando o uso da CPU. Paralelismo: Utiliza-se a biblioteca multiprocessing para criar um pool de workers, permitindo que múltiplos projetos sejam renderizados simultaneamente, otimizando o uso da CPU.
4. Geração de Manifestos e Dados Estáticos 4. Geração de Manifestos e Dados Estáticos
Para desacoplar o banco de dados da interface pública, o sistema utiliza o script generate_manifest.py. Para desacoplar o banco de dados da interface pública, o sistema utiliza o script generate_manifest.py.
Indexação: O script varre os diretórios de mídia (samples, mmp, wav) e gera arquivos JSON e YAML. Indexação: O script varre os diretórios de mídia (samples, mmp, wav/ogg) e gera arquivos JSON e YAML.
Integração com Jekyll: Estes arquivos YAML são salvos diretamente na pasta _data do Jekyll, servindo como fonte de verdade para a geração das páginas HTML estáticas. Integração com Jekyll: Estes arquivos YAML são salvos diretamente na pasta _data do Jekyll, servindo como fonte de verdade para a geração das páginas HTML estáticas.
@ -61,12 +66,12 @@ HEALTHY: O caminho no XML bate com o servidor.
RECOVERED: O caminho original (ex: C:/Users/...) não existe, mas o sistema encontrou o arquivo pelo nome e remapeou o link automaticamente. RECOVERED: O caminho original (ex: C:/Users/...) não existe, mas o sistema encontrou o arquivo pelo nome e remapeou o link automaticamente.
BROKEN: Arquivo inexistente; o sistema marca para alerta. BROKEN: Arquivo inexistente, o sistema marca para alerta.
7. Frontend: Visualização e Sequenciador 7. Frontend: Visualização e Sequenciador
A interface (projetos.html) demonstra como dados complexos podem ser visualizados sem JavaScript pesado. A interface (projetos.html) demonstra como dados complexos podem ser visualizados sem JavaScript pesado.
Sequenciador CSS: A grade de bateria (Step Sequencer) é renderizada usando lógica de template Liquid e CSS puro. O template itera sobre o array de steps ({% for step in patterns %}) e aplica classes de cor condicionalmente. Sequenciador CSS: A grade de bateria (Step Sequencer) é renderizada usando lógica de template Liquid e CSS puro. O template itera sobre o array de steps ({% raw %}{% for step in patterns %}{% endraw %}) e aplica classes de cor condicionalmente.
Interatividade Híbrida: Interatividade Híbrida:
@ -107,8 +112,8 @@ Upload: Usuário envia .mmpz via API Flask (Porta 33002).
Trigger: Flask salva o arquivo e dispara a thread de processamento. Trigger: Flask salva o arquivo e dispara a thread de processamento.
Processamento: Python descompacta o projeto, renderiza o .wav (Headless LMMS) e extrai o .json. Processamento: Python descompacta o projeto, renderiza o .ogg (Headless LMMS) e extrai o .json.
Build: Python invoca bundle exec jekyll build para regenerar o HTML. Build: Python invoca bundle exec jekyll build para regenerar o HTML.
Serviço: Nginx serve o novo HTML estático; Node.js aguarda conexões para edição colaborativa. Serviço: Serve o novo HTML estático, Node.js aguarda conexões para edição colaborativa.

View File

@ -1,4 +1,15 @@
# mmpCreator - Documentação Técnica # mmpCreator & MMPSearch - Documentação Técnica
---
## 🏗️ Arquitetura do Sistema
O sistema é um ecossistema completo para submissão, processamento e colaboração em projetos musicais (LMMS), estruturado nos seguintes pilares:
1. **Banco de Dados e Autenticação (Flask / SQLite):** Gestão segura de usuários (Bcrypt, Flask-Login), controle de propriedade de projetos e samples, além de um painel de administração (`Flask-Admin`).
2. **Motor de Renderização Headless (Python):** Processamento assíncrono via biblioteca `multiprocessing`. Utiliza o binário do LMMS em modo `offscreen` para extrair dados do XML (`.mmp` / `.mmpz`) e exportar o áudio gerado nativamente no servidor.
3. **MMPSearch (Catálogo Front-end):** Biblioteca estática gerada via Jekyll a partir de arquivos JSON/YAML, focada em leveza, indexação e busca de projetos com renderização via Web Audio API.
4. **MMPCreator (Colaboração em Tempo Real):** Sequenciador interativo hospedado em Node.js. Utiliza WebSockets para sincronizar edições simultâneas (áudio e MIDI) entre múltiplos usuários em salas virtuais.
--- ---
@ -6,9 +17,7 @@
O site está sendo desenvolvido em um ambiente virtual Python (`venv`). Para executá-lo corretamente, ative o ambiente com o comando: O site está sendo desenvolvido em um ambiente virtual Python (`venv`). Para executá-lo corretamente, ative o ambiente com o comando:
```bash `source venv/bin/activate`
source venv/bin/activate
```
Isso garante que todas as dependências do projeto sejam utilizadas corretamente. Isso garante que todas as dependências do projeto sejam utilizadas corretamente.
@ -28,66 +37,49 @@ Dessa forma, os arquivos de manifesto serão gerados, contendo as informações
--- ---
## 👁️ Serviço de Monitoramento (Watchdog) ## 📤 Servidor de Upload, Samples e Build (Flask)
Um serviço systemd foi criado para monitorar alterações na pasta `src/samples`: O servidor `upload_server.py` atua como a API central do sistema. Ele recebe arquivos, gerencia a sessão dos usuários (Login/Registro) e automatiza a reconstrução da plataforma.
- **Serviço:** `/etc/systemd/system/mmpCreator-upload-server.service`
- **Nome do serviço:** `mmpCreator-upload-server.service`
- **Frequência:** A cada 5 segundos
- **Tecnologia utilizada: ** Python
### Funcionalidade:
Sempre que houver mudanças na pasta de samples, o serviço irá:
1. Detectar alterações via `watchdog`.
2. Executar um novo build do site.
3. Atualizar automaticamente o conteúdo do site em tempo real.
> **Nota:** O build atual está sendo feito apenas na parte de testes. Verificar e ajustar o caminho correto do build.
---
## 📤 Servidor de Upload de Samples
O servidor `upload_server.py` é responsável por receber arquivos de áudio (samples) para a plataforma. Ele é construído com:
- **Framework:** Flask - **Framework:** Flask
- **Monitoramento:** Biblioteca `watchdog` - **Banco de Dados:** SQLite (com SQLAlchemy)
- **Automação de Build:** Uso de Threads em segundo plano (Background Tasks) acionadas via rotas HTTP.
### Funcionamento: ### Funcionamento:
1. Após qualquer modificação nas pastas de samples: Sempre que um novo upload (Projeto ou Sample) é processado via API:
- O script atualiza os arquivos `samples-manifest.json` e `mmp-manifest.json`. 1. O arquivo é sanitizado e validado.
- Os caminhos dos arquivos são ajustados para garantir exibição e execução corretas. 2. O sistema verifica a dependência de samples externos no XML.
3. Os manifestos (`samples-manifest.json`, metadados de projetos) são atualizados em tempo real no servidor.
4. Uma thread secundária segura (com Lock) dispara o comando `bundle exec jekyll build`, reconstruindo o frontend estático do MMPSearch para refletir a submissão imediatamente.
### Acesso: ### Acesso da API:
- `http://127.0.0.1:5000` - `http://127.0.0.1:33002`
> ⚠️ **Importante:** Avaliar a segurança do servidor antes de validar como ferramenta oficial do projeto. Atualmente está sendo usado apenas para testes. > ⚠️ **Importante:** A estabilidade da reconstrução em produção depende do caminho absoluto do binário Ruby e do pacote Bundle configurados no script (`upload_server.py`).
--- ---
## 💻 Backend para controle das salas online (Colaboração) ## 💻 Backend para controle das salas online (Colaboração)
Um serviço systemd foi criado para hospedar o backend de um servidor em nodeJS responsável por gerenciar as salas e a colaboração online: Um serviço systemd foi criado para hospedar o backend de um servidor em nodeJS responsável por gerenciar as salas e a colaboração online do MMPCreator:
- **Serviço:** `/etc/systemd/system/backend-MMPCreator.service` - **Serviço:** `/etc/systemd/system/backend-MMPCreator.service`
- **Nome do serviço:** `backend-MMPCreator.service` - **Nome do serviço:** `backend-MMPCreator.service`
- **Frequência:** Tempo integral - **Frequência:** Tempo integral
- **Tecnologia utilizada: ** NodeJS - **Tecnologia utilizada:** NodeJS (Socket.io)
### Funcionalidade: ### Funcionalidade:
- Seu intuíto é deixar o backend online em tempo integral, possibilitando a utilização da plataforma em qualquer momento. - Seu intuíto é deixar o backend online em tempo integral, possibilitando a utilização da plataforma em qualquer momento.
- Para isso foi necessário inserir meu usuário no grupo de "ssl-cert" para acesso ao certificado - Para isso foi necessário inserir meu usuário no grupo de "ssl-cert" para acesso aos certificados (Let's Encrypt).
- Essa abordagem foi escolhida, pois a "não" utilização do apache traz algumas variáveis a mais para a implementação de um proxy reverso para a comunicação via wss e https nas salas. - Essa abordagem foi escolhida, pois a "não" utilização do apache traz algumas variáveis a mais para a implementação de um proxy reverso para a comunicação segura via `wss://` e `https://` nas salas de colaboração.
### Acesso: ### Acesso:
- `http://127.0.0.1:33001` - `http://127.0.0.1:33001`
--- ---
## ✅ Funcionalidades Já Implementadas ## ✅ Funcionalidades Já Implementadas
@ -107,6 +99,8 @@ Um serviço systemd foi criado para hospedar o backend de um servidor em nodeJS
- [x] Salas online e colaboração em tempo real - [x] Salas online e colaboração em tempo real
- [x] Botões de modo global e local para controle do editor de samples (controla play/pause/stop, loop e janela de loop) - [x] Botões de modo global e local para controle do editor de samples (controla play/pause/stop, loop e janela de loop)
- [x] Exibição de notificações em alterações nos projetos em tempo real - [x] Exibição de notificações em alterações nos projetos em tempo real
- [x] Gestão de usuários (Login, Registro, Perfis e painel Admin)
- [x] Identificação automática de samples externos faltantes no upload de projetos.
--- ---

BIN
scripts/handler/__pycache__/main.cpython-312.pyc Executable file → Normal file

Binary file not shown.

View File

@ -12,6 +12,8 @@ import re
import unicodedata import unicodedata
import csv import csv
import psutil import psutil
import glob
import json
from datetime import datetime, timedelta from datetime import datetime, timedelta
# Importando seus módulos locais # Importando seus módulos locais
@ -384,6 +386,38 @@ def process_single_file(args):
return result return result
def rebuild_all_yamls():
"""Lê todos os JSONs individuais e reconstrói APENAS os arquivos necessários (JSON e YAML leve)."""
logging.info("Reconstruindo all.json e all_leve.yml a partir dos projetos individuais...")
all_data = []
# Busca todos os arquivos .json na pasta de metadados
json_files = glob.glob(os.path.join(METADATA_FOLDER, "*.json"))
for j_file in json_files:
filename = os.path.basename(j_file)
if filename in ["all.json", "samples-manifest.json", "mmp-manifest.json", "dependency_report.json"]:
continue
try:
with open(j_file, 'r', encoding='utf-8') as f:
data = json.load(f)
all_data.append(data)
except Exception as e:
logging.error(f"Erro ao ler {j_file} para agregar: {e}")
if all_data:
# 1. Salva o JSON completo (A biblioteca JSON é nativa e MUITO mais eficiente em RAM)
save_to_json(all_data, os.path.join(METADATA_FOLDER, "all.json"))
# 2. Transforma o 'elefante' num 'camundongo' ANTES de passar pro YAML
dados_leves = create_lightweight_dataset(all_data)
# 3. Salva APENAS a versão leve para o Jekyll (Isso não vai estourar a memória)
save_to_yaml(dados_leves, os.path.join(DATA_FOLDER, "all_leve.yml"))
logging.info(f"Arquivos agregados (all.json / all_leve.yml) atualizados com {len(all_data)} projetos!")
def main_parallel(): def main_parallel():
logger, log_file_path = setup_logger() logger, log_file_path = setup_logger()

View File

@ -28,7 +28,7 @@ from flask_login import (
from flask_admin import Admin, AdminIndexView, expose from flask_admin import Admin, AdminIndexView, expose
from flask_admin.contrib.sqla import ModelView from flask_admin.contrib.sqla import ModelView
from main import process_single_file, generate_manifests, slugify from main import process_single_file, generate_manifests, slugify, rebuild_all_yamls
from utils import ( from utils import (
ALLOWED_EXTENSIONS, ALLOWED_EXTENSIONS,
ALLOWED_SAMPLE_EXTENSIONS, ALLOWED_SAMPLE_EXTENSIONS,
@ -174,9 +174,12 @@ def allowed_sample(filename):
and filename.rsplit(".", 1)[1].lower() in ALLOWED_SAMPLE_EXTENSIONS and filename.rsplit(".", 1)[1].lower() in ALLOWED_SAMPLE_EXTENSIONS
) )
def run_jekyll_build(): def run_jekyll_build():
RUBY_BIN_PATH = "/usr/bin/ruby3.2" RUBY_BIN_PATH = "/usr/bin/ruby3.2"
BUNDLE_PATH = "/nethome/jotachina/projetos/mmpSearch/vendor/bundle/ruby/3.2.0/bin/bundle" BUNDLE_PATH = (
"/nethome/jotachina/projetos/mmpSearch/vendor/bundle/ruby/3.2.0/bin/bundle"
)
env_vars = os.environ.copy() env_vars = os.environ.copy()
env_vars["PATH"] = f"{RUBY_BIN_PATH}:{env_vars.get('PATH', '')}" env_vars["PATH"] = f"{RUBY_BIN_PATH}:{env_vars.get('PATH', '')}"
@ -200,11 +203,13 @@ def run_jekyll_build():
env=env_vars, env=env_vars,
capture_output=True, capture_output=True,
text=True, text=True,
check=True check=True,
) )
logging.info("✅ Jekyll Build concluído com sucesso!") logging.info("✅ Jekyll Build concluído com sucesso!")
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
logging.error(f"❌ ERRO FATAL no Jekyll Build (Code {e.returncode}):\n{e.stderr}") logging.error(
f"❌ ERRO FATAL no Jekyll Build (Code {e.returncode}):\n{e.stderr}"
)
except Exception as e: except Exception as e:
logging.error(f"❌ Erro inesperado ao chamar Jekyll: {e}") logging.error(f"❌ Erro inesperado ao chamar Jekyll: {e}")
@ -331,11 +336,14 @@ def update_xml_paths_exact(mmp_filename, replacements):
print(f"Erro crítico ao editar XML: {e}") print(f"Erro crítico ao editar XML: {e}")
return False return False
def run_heavy_tasks_in_background(): def run_heavy_tasks_in_background():
logging.info("--- [BACKGROUND] Iniciando tarefas assíncronas ---") logging.info("--- [BACKGROUND] Iniciando tarefas assíncronas ---")
try: try:
generate_manifests(SRC_MMPSEARCH) generate_manifests(SRC_MMPSEARCH)
# ---> ATUALIZA OS ARQUIVOS "ALL" AQUI <---
rebuild_all_yamls()
run_jekyll_build() run_jekyll_build()
logging.info("--- [BACKGROUND] Todas as tarefas concluídas ---") logging.info("--- [BACKGROUND] Todas as tarefas concluídas ---")
except Exception as e: except Exception as e: