Skip to main content

HTTP automation package for DTP and DAMSP portals.

Project description

botdtp

Pacote de automacao para os portais SGPT e DAMSP da Prefeitura de Sao Paulo.

O que o projeto entrega

  • SGPTBot: login, alteracao de senha, comprovante de inspecao, aprovacao/reprovacao e relatorios.
  • DAMSPBot: fluxos CPF/CNPJ, emissao de licenca PF/PJ e guia PF/PJ.
  • HTTPClient + HTTPConfig: retry, timeout, proxy, sleep entre requests, sessao e echo de payloads.
  • Persistencia de sessao em arquivo (SessionStore) com TTL (SGPT).
  • Janela de acesso configuravel por dia/hora/fuso (SGPT).

Arquitetura (serie 0.4.x)

A arquitetura foi separada por camadas para facilitar manutencao, testes e evolucao:

  • botdtp.core: contratos centrais (Operacao, contexto), erros compartilhados e politica de acesso SGPT.
  • botdtp.sgpt: autenticacao, operacoes de inspecao e relatorios do SGPT.
  • botdtp.damsp: fluxos CPF/CNPJ, regras de servico/modalidade e resolucao de captcha.
  • http_ops: transporte HTTP generico (session, retry, timeout, proxy e persistencia opcional).
  • aspx_ops: operacoes ASPX reutilizaveis (__VIEWSTATE, postback, timeline e navegacao).

Essa separacao permite evoluir fluxos de negocio sem acoplar com detalhes de transporte e WebForms.

Requisitos

  • Python >=3.11

Instalacao

pip install botdtp

Dependencias

Dependencias diretas do pacote (em pyproject.toml):

  • requests>=2.32.0
  • beautifulsoup4>=4.12.0
  • lxml>=5.2.0
  • pillow>=10.0.0
  • langchain-core>=0.3.0
  • langchain-openai>=0.2.0
  • validate-docbr>=1.11.1
  • xhtml2pdf>=0.2.17

Contrato padrao de retorno

Toda operacao retorna Operacao:

  • ok: bool
  • mensagem: str
  • data: dict

Comportamento em falha:

  • Operacoes publicas de Bot e Client retornam Operacao(ok=False, ...).
  • Nao ha propagacao de excecao para o chamador nesse contrato padrao.
  • Em erros, data inclui operacao, classe e detalhe.

Uso de alto nivel (recomendado)

SGPTBot

from botdtp import SGPTBot
from botdtp.sgpt import (
    SGPTLoginInput,
    SGPTAlterarSenhaInput,
    SGPTComprovanteInspecaoInput,
    SGPTAprovacaoEscolarAnualInput,
    SGPTAprovacaoEscolarSemestralInput,
    SGPTAprovacaoTaxiInput,
    SGPTReprovacaoEscolarAnualInput,
    SGPTReprovacaoEscolarSemestralInput,
    SGPTReprovacaoTaxiInput,
    SGPTReprovacaoItemInput,
    SGPTRelatorioInput,
)

login = SGPTLoginInput(
    codigo_empresa="CODIGO_DA_EMPRESA",
    usuario="USUARIO",
    senha="SUA_SENHA",
)

sgpt = SGPTBot(login=login, reautenticar=True)

sgpt.autenticar(login)

sgpt.alterar_senha(
    SGPTAlterarSenhaInput(
        codigo_empresa="0035",
        usuario="123456",
        senha_atual="SENHA_ATUAL",
        nova_senha="SENHA_NOVA",
        confirmacao_nova_senha="SENHA_NOVA",
    )
)

sgpt.gerar_comprovante_inspecao(
    SGPTComprovanteInspecaoInput(
        numero_guia="055721",
        ano_guia="2026",
        resultado="APROVADA",
    ),
    destino="tmp",
    nome_arquivo="comprovante_guia_055721.pdf",
)

sgpt.aprovar_escolar_anual(
    SGPTAprovacaoEscolarAnualInput(
        placa="ABC1234",
        licenca="12345678",
        inspetor_codigo="111",
        inspetor_nome="INSPETOR",
        rt_codigo="222",
        rt_nome="RESPONSAVEL TECNICO",
        ano_guia="0000",
        numero_guia="00000",
        validade_extintor="00/0000",
        sn_tacografo="S",
    ),
    destino="tmp",
    nome_arquivo="comprovante_escolar_anual.pdf",
)

sgpt.aprovar_escolar_semestral(
    SGPTAprovacaoEscolarSemestralInput(
        placa="ABC1D23",
        licenca="12345678",
        inspetor_codigo="111",
        inspetor_nome="INSPETOR",
        rt_codigo="222",
        rt_nome="RESPONSAVEL TECNICO",
        validade_extintor="12/2026",
        sn_tacografo="S",
    ),
    destino="tmp",
    nome_arquivo="comprovante_escolar_semestral.pdf",
)

sgpt.aprovar_taxi(
    SGPTAprovacaoTaxiInput(
        placa="ABC1234",
        licenca="12345678",
        inspetor_codigo="111",
        inspetor_nome="INSPETOR",
        rt_codigo="222",
        rt_nome="RESPONSAVEL TECNICO",
        ano_guia="2026",
        numero_guia="055721",
        radio_taxi_cod="",
        radio_taxi_nome="",
    ),
    destino_comprovante="tmp",
    nome_arquivo="comprovante_taxi.pdf",
)

itens = [
    SGPTReprovacaoItemInput(
        grupo="X",
        item="X",
        subitem="X",
        valor="X",
        opcao="X",
        descricao="XXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    )
]

sgpt.reprovar_escolar_anual(
    SGPTReprovacaoEscolarAnualInput(
        placa="ABC1234",
        licenca="12345678",
        inspetor_codigo="111",
        inspetor_nome="INSPETOR",
        rt_codigo="222",
        rt_nome="RESPONSAVEL TECNICO",
        ano_guia="2026",
        numero_guia="055721",
        itens_reprovacao=itens,
    )
)

sgpt.reprovar_escolar_semestral(
    SGPTReprovacaoEscolarSemestralInput(
        placa="ABC1D23",
        licenca="12345678",
        inspetor_codigo="111",
        inspetor_nome="INSPETOR",
        rt_codigo="222",
        rt_nome="RESPONSAVEL TECNICO",
        itens_reprovacao=itens,
    )
)

sgpt.reprovar_taxi(
    SGPTReprovacaoTaxiInput(
        placa="ABC1234",
        licenca="12345678",
        inspetor_codigo="111",
        inspetor_nome="INSPETOR",
        rt_codigo="222",
        rt_nome="RESPONSAVEL TECNICO",
        ano_guia="2026",
        numero_guia="055721",
        itens_reprovacao=itens,
    )
)

sgpt.gerar_relatorio_inspecoes(
    SGPTRelatorioInput(
        mes=5,
        ano=2026,
        modalidade="E",  # C, E, F, T ou M
        resultado="",     # "", A, P ou R
    ),
    destino="tmp",
    nome_arquivo="relatorio_sgpt_maio_2026",
    salvar_html=True,
)

As URLs do portal SGPT sao resolvidas internamente pelo modulo botdtp.sgpt.params.

Politica de autenticacao SGPT:

  • Login obrigatorio: passe login=SGPTLoginInput(...) ao instanciar o bot.
  • Manual: use sgpt.autenticar(...) para renovar explicitamente a sessao.
  • Gerenciada: com reautenticar=True, o bot tenta reautenticar ao detectar SGPTAuthenticationError.
  • Sessao: SGPTBot restaura/salva cookies via SessionStore.

DAMSPBot

from botdtp import DAMSPBot
from botdtp.damsp import (
    DAMSPCPFInput,
    DAMSPCPFGuiaInput,
    DAMSPCNPJInput,
    DAMSPCNPJGuiaInput,
    DAMSPModalidadeVeiculoEnum,
    DAMSPServicoEscolarEnum,
    DAMSPServicoTaxiEnum,
    OpenAICaptchaSolver,
)

damsp = DAMSPBot(
    captcha_solver=OpenAICaptchaSolver(api_key="SUA_OPENAI_KEY"),
    max_tentativas=3,
)

# 1) Iniciar fluxo CPF
damsp.iniciar_fluxo_cpf(
    DAMSPCPFInput(
        cpf="529.982.247-25",
        licenca="123.456-78",
        modalidade=DAMSPModalidadeVeiculoEnum.TAXI,
    )
)

# 2) Iniciar fluxo CNPJ
damsp.iniciar_fluxo_cnpj(
    DAMSPCNPJInput(
        cpf_responsavel="529.982.247-25",
        numero_empresa="123456",
        licenca="123.456-78",
        modalidade=DAMSPModalidadeVeiculoEnum.ESCOLAR,
    )
)

# 3) Gerar licenca PF
damsp.gerar_licenca_pf(
    DAMSPCPFInput(
        cpf="529.982.247-25",
        licenca="123.456-78",
        modalidade=DAMSPModalidadeVeiculoEnum.TAXI,
    ),
    destino="tmp",
)

# 4) Gerar licenca PJ
damsp.gerar_licenca_pj(
    DAMSPCNPJInput(
        cpf_responsavel="529.982.247-25",
        numero_empresa="123456",
        licenca="123.456-78",
        modalidade=DAMSPModalidadeVeiculoEnum.ESCOLAR,
    ),
    destino="tmp",
)

# 5) Gerar guia PF
damsp.gerar_guia_pf(
    DAMSPCPFGuiaInput(
        cpf="529.982.247-25",
        licenca="123.456-78",
        codigo_servico=DAMSPServicoTaxiEnum.RENOVACAO_ALVARA,
        modalidade=DAMSPModalidadeVeiculoEnum.TAXI,
    ),
    destino="tmp",
)

# 6) Gerar guia PJ
damsp.gerar_guia_pj(
    DAMSPCNPJGuiaInput(
        cpf_responsavel="529.982.247-25",
        numero_empresa="123456",
        licenca="123.456-78",
        codigo_servico=DAMSPServicoEscolarEnum.RENOVACAO_CRM,
        modalidade=DAMSPModalidadeVeiculoEnum.ESCOLAR,
    ),
    destino="tmp",
)

Retorno DAMSP de guias:

Operacao(
    ok=True,
    mensagem="Guia DAMSP PF gerada com sucesso.",
    data={
        "arquivo": "guia_01024700.pdf",
        "caminho_arquivo": "C:\\Users\\...\\guia_01024700.pdf",
        "data": {
            "licenca": "01024700",
            "marca_modelo": "CITROEN/JUMP GREENCAR ES",
            "placa": "FJP5G96",
            "validade": "2026-06-19",
            "situacao": "ATIVO",
        },
        "servico": {
            "codigo": "712",
            "radio_value": "a1",
            "descricao": "RENOVACAO C.R.M.",
        },
        "reemissao": False,
    },
)

Nas operacoes que geram PDF, arquivo contem somente o nome do arquivo e caminho_arquivo contem o caminho absoluto salvo em disco.

Uso de baixo nivel (infra)

import requests

from botdtp import HTTPClient, HTTPConfig, DAMSPBot

http = HTTPClient(config=HTTPConfig(), session=requests.Session())
damsp = DAMSPBot(http=http)

Nos metodos publicos do DAMSPBot, use echo_post=True para imprimir no terminal as URLs e payloads enviados por POST. Use echo_get=True para imprimir tambem as chamadas GET. Os parametros sao independentes e ficam desligados por padrao:

resultado = damsp.gerar_guia_pf(
    payload,
    destino="tmp",
    nome_arquivo="guia_01024700",
    echo_post=True,
    echo_get=False,
)

Campos sensiveis conhecidos sao mascarados no log.

Captcha DAMSP

botdtp.damsp.captcha contem:

  • OpenAICaptchaSolver (automatico via OpenAI/LangChain)
  • ManualCaptchaSolver (entrada manual)
  • OpenAICaptchaConfig
  • converter_para_bytes_png

Configuracao recomendada:

  • Forneca api_key explicitamente em OpenAICaptchaSolver.
  • Use max_tentativas no DAMSPBot para controlar novas tentativas quando o portal recusar o captcha.
  • Ajuste preset do modelo via OpenAICaptchaConfig(model=..., max_tokens=..., temperature=...).
  • Se usar env, resolva no bootstrap da aplicacao e injete os valores no construtor.

Janela de acesso (SGPT) e sessao

Janela padrao: segunda a sabado (1,2,3,4,5,6), 07:00 ate 20:00, fuso America/Sao_Paulo.

Personalizacao via codigo:

  • Janela: passe ControleAcessoConfig(...) ao criar SGPTBot.
  • Persistencia em arquivo: disponivel no SGPTBot via SessionPersistenceConfig(...).
  • DAMSPBot: sem persistencia em disco; cada operacao refaz o fluxo de identificacao do perfil (PF/PJ).
  • HTTP: use HTTPConfig(...) com timeout, retry e proxy; em DAMSPBot, ligue rastreio por operacao com echo_post e echo_get.

Scripts de runtime e testes

Exemplos de runtime:

  • examples/runtime_sgpt_smoke.py
  • examples/runtime_sgpt_alterar_senha_smoke.py
  • examples/runtime_sgpt_relatorio_smoke.py
  • examples/runtime_damsp_licenca_pf_smoke.py
  • examples/runtime_damsp_licenca_pj_smoke.py
  • cli/sgpt_menu_cli.py
  • cli/sgpt_menu_config.example.json
  • cli/damsp_menu_cli.py
  • cli/damsp_menu_config.example.json
  • examples/django_adapter_example.py

Testes:

pytest -q

Publicacao da versao 0.4.0

Checklist recomendado para publicar a 0.4.0 refletindo a nova arquitetura:

  1. Atualize versao e metadados no pyproject.toml (version = "0.4.0").
  2. Garanta que este README reflita a API publica atual e a divisao por camadas.
  3. Registre mudancas de migracao no release notes: arquivo contem somente o nome do PDF, dados de licenca DAMSP ficam em data, e o rastreio HTTP usa echo_post/echo_get.
  4. Execute a suite local:
    • pytest -q
  5. Gere os artefatos:
    • python -m build
  6. Valide distribuicoes:
    • python -m twine check dist/*
  7. Publique (preferencialmente validando antes no TestPyPI):
    • python -m twine upload dist/*
  8. Crie tag e release:
    • git tag v0.4.0
    • git push origin v0.4.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

botdtp-0.4.0.tar.gz (75.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

botdtp-0.4.0-py3-none-any.whl (75.0 kB view details)

Uploaded Python 3

File details

Details for the file botdtp-0.4.0.tar.gz.

File metadata

  • Download URL: botdtp-0.4.0.tar.gz
  • Upload date:
  • Size: 75.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for botdtp-0.4.0.tar.gz
Algorithm Hash digest
SHA256 d403b80bf06fb8fb9fb29658231c5af686302d556e7580c84f42d67428a74390
MD5 dde081b178482720cbad9c9685381191
BLAKE2b-256 68747829b167f1f45b0388da011ba9bc4867f88ae5e00c63325f24c3d5b0df82

See more details on using hashes here.

File details

Details for the file botdtp-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: botdtp-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 75.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for botdtp-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3a9f10a100c0102592f18f63acb70c7e57767a85d6224b737eabf61836e3dd6e
MD5 bc6bcaab9687c72109a80f5e638eb0c6
BLAKE2b-256 2156feddd39af09850e51f066f516d5165403ff62c3d10393c4c1f04433e21f0

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page