Metadata-Version: 2.4
Name: upapasta
Version: 0.10.4
Summary: A script to upload folders to Usenet with RAR, PAR2, and nyuu.
Author-email: Franzopl <franzopl@pm.me>
Project-URL: Homepage, https://github.com/franzopl/upapasta
Project-URL: Repository, https://github.com/franzopl/upapasta.git
Project-URL: Issues, https://github.com/franzopl/upapasta/issues
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Topic :: Communications :: File Sharing
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: End Users/Desktop
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# UpaPasta

**UpaPasta** é uma ferramenta de linha de comando (CLI) em Python para automatizar o processo completo de upload de arquivos e pastas para a Usenet. Na maioria dos casos, um único comando é suficiente:

```bash
upapasta /caminho/para/pasta
```

O fluxo completo cobre:

1. **Compactação em RAR5** (store, sem compressão) para preservar estrutura e hashes
2. **Geração de paridade PAR2** para recuperação de artigos faltando
3. **Upload via nyuu** para o newsgroup configurado
4. **Geração de NZB e NFO** automaticamente
5. **Limpeza automática** de RAR e PAR2 após upload

## Comportamento padrão

| Entrada | Comportamento |
|---------|---------------|
| Pasta | RAR (store) + PAR2 + upload → NZB + NFO |
| Arquivo único | PAR2 + upload direto (sem RAR) → NZB + NFO |
| Pasta com `--each` | Cada arquivo vira um release separado com seu próprio NZB |

**Quando `--obfuscate` ou `--password` é usado com arquivo único**, o UpaPasta cria o RAR automaticamente — sem a necessidade de flags adicionais.

## Pré-requisitos

| Binário | Obrigatório | Função |
|---------|-------------|--------|
| `rar` | Sim | Compactação RAR5 (store) |
| `nyuu` | Sim | Upload para Usenet |
| `parpar` ou `par2` | Sim | Geração de arquivos de paridade |
| `ffmpeg` / `ffprobe` | Recomendado | Metadados de vídeo no NFO de pastas |
| `mediainfo` | Recomendado | NFO de arquivos únicos e séries |

## Instalação

### Via PyPI

```bash
pip install upapasta
```

### Para desenvolvimento

```bash
git clone https://github.com/franzopl/upapasta.git
cd upapasta
python3 -m venv .venv
source .venv/bin/activate
pip install -e .
```

## Configuração

Na primeira execução, um assistente interativo solicita as informações essenciais e gera o arquivo `~/.config/upapasta/.env` automaticamente:

```
╔══════════════════════════════════════════════════════╗
║         Configuração inicial do UpaPasta             ║
╚══════════════════════════════════════════════════════╝

── Servidor NNTP ─────────────────────────────────────
  Servidor NNTP (ex: news.eweka.nl): news.eweka.nl
  Porta NNTP [563]:
  Usar SSL/TLS? [true]:
  Usuário NNTP: meu_usuario
  Senha NNTP:

── Upload ────────────────────────────────────────────
  Grupo Usenet [alt.binaries.boneless]:
  Conexões simultâneas [50]:
  Tamanho do artigo [700K]:
  Caminho de saída do .nzb [{filename}.nzb]:
```

O arquivo gerado contém todas as variáveis configuráveis com comentários. Para reconfigurar, delete o `.env` e execute o UpaPasta novamente.

### Variáveis principais do `.env`

| Variável | Descrição | Padrão |
|----------|-----------|--------|
| `NNTP_HOST` | Servidor NNTP | — |
| `NNTP_PORT` | Porta (563 = TLS) | `563` |
| `NNTP_SSL` | Usar SSL/TLS | `true` |
| `NNTP_USER` | Usuário NNTP | — |
| `NNTP_PASS` | Senha NNTP | — |
| `NNTP_CONNECTIONS` | Conexões simultâneas | `50` |
| `USENET_GROUP` | Grupo de upload | `alt.binaries.boneless` |
| `ARTICLE_SIZE` | Tamanho máximo de artigo | `700K` |
| `NZB_OUT` | Caminho do `.nzb` gerado | `{filename}.nzb` |

Consulte `.env.example` para a lista completa com descrições detalhadas.

## Como usar

### Uso básico

```bash
upapasta <caminho> [opções]
```

Sem argumentos, o UpaPasta exibe um guia rápido de uso.

### Exemplos

**Pasta inteira como release único:**
```bash
upapasta Curso.Python.2024/
```

**Arquivo único (sem RAR):**
```bash
upapasta Episodio.S01E01.mkv
```

**Temporada completa — cada episódio como release separado:**
```bash
upapasta Temporada.1/ --each
```
> Itera todos os arquivos da pasta. Cada `.mkv` vira um NZB independente.

**Release com nomes ofuscados:**
```bash
upapasta Pasta/ --obfuscate
```
> Renomeia RAR e PAR2 com nomes aleatórios antes do upload. O NZB é salvo com o nome original.

**Release com senha RAR:**
```bash
upapasta Pasta/ --password "MinhaSenh@"
```
> A senha é injetada no NZB como `<meta type="password">` para extração automática por SABnzbd/NZBGet.

**Ofuscado com senha (independentes, podem ser combinados):**
```bash
upapasta Pasta/ --obfuscate --password "abc123"
```

**Arquivo único ofuscado (RAR criado automaticamente):**
```bash
upapasta Episodio.mkv --obfuscate
```

**Mais paridade, mantendo os arquivos gerados:**
```bash
upapasta Pasta/ --par-profile safe --keep-files
```

**Simular sem enviar:**
```bash
upapasta Pasta/ --dry-run
```

**Upload com retry e timeout:**
```bash
upapasta Pasta/ --upload-retries 3 --upload-timeout 60
```

**Processar vários itens em sequência:**
```bash
for pasta in /home/user/Uploads/*/; do
    upapasta "$pasta" --nzb-conflict fail
done
```

### Opções de linha de comando

#### Opções essenciais

| Opção | Descrição |
|-------|-----------|
| `--each` | Processa cada arquivo da pasta individualmente (ideal para temporadas) |
| `--obfuscate` | Nomes aleatórios nos arquivos RAR/PAR2 antes do upload |
| `--password SENHA` | Protege o RAR com senha; injetada no NZB automaticamente |
| `--skip-rar` | Não cria RAR — envia arquivos como estão. Incompatível com `--password` |
| `--dry-run` | Simula tudo sem criar ou enviar arquivos |

#### Opções de ajuste

| Opção | Descrição | Padrão |
|-------|-----------|--------|
| `--par-profile` | Perfil PAR2: `fast` (5%), `balanced` (10%), `safe` (20%) | `balanced` |
| `-r`, `--redundancy N` | Redundância PAR2 em % (sobrescreve `--par-profile`) | conforme perfil |
| `--keep-files` | Mantém RAR e PAR2 após o upload | desativado |
| `--log-file PATH` | Grava log completo da sessão em arquivo | — |
| `--upload-retries N` | Tentativas extras em caso de falha de upload | `0` |
| `--verbose` | Ativa log de debug detalhado | desativado |

#### Opções avançadas

| Opção | Descrição | Padrão |
|-------|-----------|--------|
| `--backend` | Backend PAR2: `parpar` ou `par2` | `parpar` |
| `--post-size SIZE` | Tamanho alvo de post (ex: `20M`, `700K`) | conforme perfil |
| `--par-slice-size SIZE` | Override manual do slice PAR2 | automático |
| `--rar-threads N` | Threads para criação do RAR | CPUs disponíveis |
| `--par-threads N` | Threads para geração do PAR2 | CPUs disponíveis |
| `--max-memory MB` | Limite de memória para PAR2 | automático |
| `-s`, `--subject` | Assunto da postagem | nome do arquivo/pasta |
| `-g`, `--group` | Newsgroup de destino | do `.env` |
| `--nzb-conflict` | Conflito de NZB: `rename`, `overwrite`, `fail` | `rename` |
| `--env-file PATH` | Caminho alternativo para o `.env` | `~/.config/upapasta/.env` |
| `--upload-timeout N` | Timeout de conexão para nyuu (segundos) | sem timeout |
| `-f`, `--force` | Sobrescreve RAR/PAR2 existentes | desativado |
| `--skip-par` | Pula geração de paridade | desativado |
| `--skip-upload` | Pula o upload (gera apenas RAR/PAR2) | desativado |

## Regras de comportamento

### RAR automático para arquivos únicos

Por padrão, arquivos únicos são enviados sem RAR. Mas nas situações abaixo o RAR é criado automaticamente:

| Situação | Comportamento |
|----------|---------------|
| `arquivo.mkv` | Upload direto, sem RAR |
| `arquivo.mkv --obfuscate` | Cria RAR → renomeia → upload |
| `arquivo.mkv --password abc` | Cria RAR com senha → upload |
| `arquivo.mkv --obfuscate --password abc` | Cria RAR com senha → renomeia → upload |

### Aviso de subpastas com `--skip-rar`

Quando `--skip-rar` é usado em uma pasta que contém subpastas, o UpaPasta exibe um aviso: PAR2 não preserva hierarquia de diretórios de forma confiável entre diferentes clientes Usenet. Para pastas com subpastas, o RAR é sempre recomendado.

### `--skip-rar` + `--password` é erro

Sem RAR não há container para proteger com senha. O UpaPasta encerra com mensagem clara de erro.

## Lógica de volumes RAR

| Tamanho total | Comportamento |
|---------------|---------------|
| ≤ 10 GB | RAR único (sem volumes) |
| > 10 GB | Volumes calculados para não ultrapassar 100 partes (mínimo 1 GB por volume) |

O RAR usa modo **store (`-m0`)** — sem compressão. Vídeos e áudios já são comprimidos; tentar comprimí-los novamente não reduz o tamanho e apenas consome CPU e tempo. O modo store é significativamente mais rápido e preserva os hashes dos arquivos originais após extração.

## Estrutura do projeto

```
upapasta/
├── upapasta/
│   ├── __init__.py    # Inicialização do pacote
│   ├── _process.py    # managed_popen: gerenciamento seguro de subprocessos
│   ├── config.py      # Configuração, perfis PAR2, wizard de primeiro uso
│   ├── main.py        # Orquestrador, CLI, PhaseBar, UpaPastaSession
│   ├── makerar.py     # Criação de arquivos RAR5 (pasta ou arquivo único)
│   ├── makepar.py     # Geração de PAR2 (parpar/par2), obfuscação
│   ├── nfo.py         # Geração de arquivos NFO
│   ├── nzb.py         # Geração e manipulação de NZB
│   ├── resources.py   # Cálculo automático de threads e memória
│   └── upfolder.py    # Upload via nyuu (sem cópia temporária)
├── tests/             # Testes unitários
├── .env.example       # Exemplo de configuração
├── pyproject.toml     # Metadados e dependências
├── CHANGELOG.md       # Histórico de versões
└── README.md          # Este arquivo
```

## Licença

Este projeto está licenciado sob a Licença MIT. Veja o arquivo [LICENSE](LICENSE) para mais detalhes.

## Contribuição

Contribuições são bem-vindas! Se você encontrar um bug ou tiver uma sugestão, abra uma *issue* ou envie um *pull request*.
