bps-kit 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/templates/.agents/agents/backend-specialist.md +263 -0
- package/templates/.agents/agents/code-archaeologist.md +106 -0
- package/templates/.agents/agents/database-architect.md +226 -0
- package/templates/.agents/agents/debugger.md +225 -0
- package/templates/.agents/agents/devops-engineer.md +242 -0
- package/templates/.agents/agents/documentation-writer.md +104 -0
- package/templates/.agents/agents/explorer-agent.md +73 -0
- package/templates/.agents/agents/frontend-specialist.md +593 -0
- package/templates/.agents/agents/game-developer.md +162 -0
- package/templates/.agents/agents/mobile-developer.md +377 -0
- package/templates/.agents/agents/orchestrator.md +416 -0
- package/templates/.agents/agents/penetration-tester.md +188 -0
- package/templates/.agents/agents/performance-optimizer.md +187 -0
- package/templates/.agents/agents/product-manager.md +112 -0
- package/templates/.agents/agents/product-owner.md +95 -0
- package/templates/.agents/agents/project-planner.md +406 -0
- package/templates/.agents/agents/qa-automation-engineer.md +103 -0
- package/templates/.agents/agents/security-auditor.md +170 -0
- package/templates/.agents/agents/seo-specialist.md +111 -0
- package/templates/.agents/agents/test-engineer.md +158 -0
- package/templates/.agents/rules/GEMINI.md +219 -0
- package/templates/.agents/scripts/auto_preview.py +148 -0
- package/templates/.agents/scripts/checklist.py +217 -0
- package/templates/.agents/scripts/session_manager.py +120 -0
- package/templates/.agents/scripts/verify_all.py +327 -0
- package/templates/.agents/workflows/brainstorm.md +113 -0
- package/templates/.agents/workflows/create.md +59 -0
- package/templates/.agents/workflows/debug.md +103 -0
- package/templates/.agents/workflows/deploy.md +176 -0
- package/templates/.agents/workflows/enhance.md +63 -0
- package/templates/.agents/workflows/orchestrate.md +237 -0
- package/templates/.agents/workflows/plan.md +89 -0
- package/templates/.agents/workflows/preview.md +81 -0
- package/templates/.agents/workflows/setup-brain.md +39 -0
- package/templates/.agents/workflows/status.md +86 -0
- package/templates/.agents/workflows/test.md +144 -0
- package/templates/.agents/workflows/ui-ux-pro-max.md +296 -0
- package/templates/skills_normal/api-patterns/scripts/api_validator.py +211 -0
- package/templates/skills_normal/database-design/scripts/schema_validator.py +172 -0
- package/templates/skills_normal/frontend-design/scripts/accessibility_checker.py +183 -0
- package/templates/skills_normal/frontend-design/scripts/ux_audit.py +722 -0
- package/templates/skills_normal/git-pushing/scripts/smart_commit.sh +19 -0
- package/templates/skills_normal/lint-and-validate/scripts/lint_runner.py +184 -0
- package/templates/skills_normal/lint-and-validate/scripts/type_coverage.py +173 -0
- package/templates/skills_normal/performance-profiling/scripts/lighthouse_audit.py +76 -0
- package/templates/skills_normal/senior-fullstack/scripts/code_quality_analyzer.py +114 -0
- package/templates/skills_normal/senior-fullstack/scripts/fullstack_scaffolder.py +114 -0
- package/templates/skills_normal/senior-fullstack/scripts/project_scaffolder.py +114 -0
- package/templates/skills_normal/seo-fundamentals/scripts/seo_checker.py +219 -0
- package/templates/skills_normal/testing-patterns/scripts/test_runner.py +219 -0
- package/templates/skills_normal/vulnerability-scanner/scripts/security_scan.py +458 -0
- package/templates/vault/007/scripts/config.py +472 -0
- package/templates/vault/007/scripts/full_audit.py +1306 -0
- package/templates/vault/007/scripts/quick_scan.py +481 -0
- package/templates/vault/007/scripts/requirements.txt +26 -0
- package/templates/vault/007/scripts/scanners/__init__.py +0 -0
- package/templates/vault/007/scripts/scanners/dependency_scanner.py +1305 -0
- package/templates/vault/007/scripts/scanners/injection_scanner.py +1104 -0
- package/templates/vault/007/scripts/scanners/secrets_scanner.py +1008 -0
- package/templates/vault/007/scripts/score_calculator.py +693 -0
- package/templates/vault/agent-orchestrator/scripts/match_skills.py +329 -0
- package/templates/vault/agent-orchestrator/scripts/orchestrate.py +304 -0
- package/templates/vault/agent-orchestrator/scripts/requirements.txt +1 -0
- package/templates/vault/agent-orchestrator/scripts/scan_registry.py +508 -0
- package/templates/vault/ai-studio-image/scripts/config.py +613 -0
- package/templates/vault/ai-studio-image/scripts/generate.py +630 -0
- package/templates/vault/ai-studio-image/scripts/prompt_engine.py +424 -0
- package/templates/vault/ai-studio-image/scripts/requirements.txt +4 -0
- package/templates/vault/ai-studio-image/scripts/templates.py +349 -0
- package/templates/vault/android_ui_verification/scripts/verify_ui.sh +32 -0
- package/templates/vault/apify-audience-analysis/reference/scripts/run_actor.js +363 -0
- package/templates/vault/apify-brand-reputation-monitoring/reference/scripts/run_actor.js +363 -0
- package/templates/vault/apify-competitor-intelligence/reference/scripts/run_actor.js +363 -0
- package/templates/vault/apify-content-analytics/reference/scripts/run_actor.js +363 -0
- package/templates/vault/apify-ecommerce/reference/scripts/package.json +3 -0
- package/templates/vault/apify-ecommerce/reference/scripts/run_actor.js +369 -0
- package/templates/vault/apify-influencer-discovery/reference/scripts/run_actor.js +363 -0
- package/templates/vault/apify-lead-generation/reference/scripts/run_actor.js +363 -0
- package/templates/vault/apify-market-research/reference/scripts/run_actor.js +363 -0
- package/templates/vault/apify-trend-analysis/reference/scripts/run_actor.js +363 -0
- package/templates/vault/apify-ultimate-scraper/reference/scripts/run_actor.js +363 -0
- package/templates/vault/audio-transcriber/scripts/install-requirements.sh +190 -0
- package/templates/vault/audio-transcriber/scripts/transcribe.py +486 -0
- package/templates/vault/claude-monitor/scripts/api_bench.py +240 -0
- package/templates/vault/claude-monitor/scripts/config.py +69 -0
- package/templates/vault/claude-monitor/scripts/health_check.py +362 -0
- package/templates/vault/claude-monitor/scripts/monitor.py +296 -0
- package/templates/vault/content-creator/scripts/brand_voice_analyzer.py +185 -0
- package/templates/vault/content-creator/scripts/seo_optimizer.py +419 -0
- package/templates/vault/context-agent/scripts/active_context.py +227 -0
- package/templates/vault/context-agent/scripts/compressor.py +149 -0
- package/templates/vault/context-agent/scripts/config.py +69 -0
- package/templates/vault/context-agent/scripts/context_loader.py +155 -0
- package/templates/vault/context-agent/scripts/context_manager.py +302 -0
- package/templates/vault/context-agent/scripts/models.py +103 -0
- package/templates/vault/context-agent/scripts/project_registry.py +132 -0
- package/templates/vault/context-agent/scripts/requirements.txt +6 -0
- package/templates/vault/context-agent/scripts/search.py +115 -0
- package/templates/vault/context-agent/scripts/session_parser.py +206 -0
- package/templates/vault/context-agent/scripts/session_summary.py +319 -0
- package/templates/vault/context-guardian/scripts/context_snapshot.py +229 -0
- package/templates/vault/docx/ooxml/scripts/pack.py +159 -0
- package/templates/vault/docx/ooxml/scripts/unpack.py +29 -0
- package/templates/vault/docx/ooxml/scripts/validate.py +69 -0
- package/templates/vault/docx/ooxml/scripts/validation/__init__.py +15 -0
- package/templates/vault/docx/ooxml/scripts/validation/base.py +951 -0
- package/templates/vault/docx/ooxml/scripts/validation/docx.py +274 -0
- package/templates/vault/docx/ooxml/scripts/validation/pptx.py +315 -0
- package/templates/vault/docx/ooxml/scripts/validation/redlining.py +279 -0
- package/templates/vault/docx/scripts/__init__.py +1 -0
- package/templates/vault/docx/scripts/document.py +1276 -0
- package/templates/vault/docx/scripts/templates/comments.xml +3 -0
- package/templates/vault/docx/scripts/templates/commentsExtended.xml +3 -0
- package/templates/vault/docx/scripts/templates/commentsExtensible.xml +3 -0
- package/templates/vault/docx/scripts/templates/commentsIds.xml +3 -0
- package/templates/vault/docx/scripts/templates/people.xml +3 -0
- package/templates/vault/docx/scripts/utilities.py +374 -0
- package/templates/vault/docx-official/ooxml/scripts/pack.py +159 -0
- package/templates/vault/docx-official/ooxml/scripts/unpack.py +29 -0
- package/templates/vault/docx-official/ooxml/scripts/validate.py +69 -0
- package/templates/vault/docx-official/ooxml/scripts/validation/__init__.py +15 -0
- package/templates/vault/docx-official/ooxml/scripts/validation/base.py +951 -0
- package/templates/vault/docx-official/ooxml/scripts/validation/docx.py +274 -0
- package/templates/vault/docx-official/ooxml/scripts/validation/pptx.py +315 -0
- package/templates/vault/docx-official/ooxml/scripts/validation/redlining.py +279 -0
- package/templates/vault/docx-official/scripts/__init__.py +1 -0
- package/templates/vault/docx-official/scripts/document.py +1276 -0
- package/templates/vault/docx-official/scripts/templates/comments.xml +3 -0
- package/templates/vault/docx-official/scripts/templates/commentsExtended.xml +3 -0
- package/templates/vault/docx-official/scripts/templates/commentsExtensible.xml +3 -0
- package/templates/vault/docx-official/scripts/templates/commentsIds.xml +3 -0
- package/templates/vault/docx-official/scripts/templates/people.xml +3 -0
- package/templates/vault/docx-official/scripts/utilities.py +374 -0
- package/templates/vault/geo-fundamentals/scripts/geo_checker.py +289 -0
- package/templates/vault/helm-chart-scaffolding/scripts/validate-chart.sh +244 -0
- package/templates/vault/i18n-localization/scripts/i18n_checker.py +241 -0
- package/templates/vault/instagram/scripts/account_setup.py +233 -0
- package/templates/vault/instagram/scripts/analyze.py +221 -0
- package/templates/vault/instagram/scripts/api_client.py +444 -0
- package/templates/vault/instagram/scripts/auth.py +411 -0
- package/templates/vault/instagram/scripts/comments.py +160 -0
- package/templates/vault/instagram/scripts/config.py +111 -0
- package/templates/vault/instagram/scripts/db.py +467 -0
- package/templates/vault/instagram/scripts/export.py +138 -0
- package/templates/vault/instagram/scripts/governance.py +233 -0
- package/templates/vault/instagram/scripts/hashtags.py +114 -0
- package/templates/vault/instagram/scripts/insights.py +170 -0
- package/templates/vault/instagram/scripts/media.py +65 -0
- package/templates/vault/instagram/scripts/messages.py +103 -0
- package/templates/vault/instagram/scripts/profile.py +58 -0
- package/templates/vault/instagram/scripts/publish.py +449 -0
- package/templates/vault/instagram/scripts/requirements.txt +5 -0
- package/templates/vault/instagram/scripts/run_all.py +189 -0
- package/templates/vault/instagram/scripts/schedule.py +189 -0
- package/templates/vault/instagram/scripts/serve_api.py +234 -0
- package/templates/vault/instagram/scripts/templates.py +155 -0
- package/templates/vault/junta-leiloeiros/scripts/db.py +216 -0
- package/templates/vault/junta-leiloeiros/scripts/export.py +137 -0
- package/templates/vault/junta-leiloeiros/scripts/requirements.txt +15 -0
- package/templates/vault/junta-leiloeiros/scripts/run_all.py +190 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/__init__.py +4 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/base_scraper.py +209 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/generic_scraper.py +110 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucap.py +110 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/juceac.py +72 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/juceal.py +72 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/juceb.py +68 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucec.py +63 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucema.py +211 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucemg.py +218 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucep.py +70 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucepa.py +74 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucepar.py +80 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucepe.py +78 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucepi.py +69 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucer.py +256 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucerja.py +170 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucern.py +71 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucesc.py +89 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucesp.py +233 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucetins.py +134 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucis_df.py +63 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucisrs.py +299 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/states.py +99 -0
- package/templates/vault/junta-leiloeiros/scripts/serve_api.py +164 -0
- package/templates/vault/junta-leiloeiros/scripts/web_scraper_fallback.py +233 -0
- package/templates/vault/last30days/scripts/last30days.py +521 -0
- package/templates/vault/last30days/scripts/lib/__init__.py +1 -0
- package/templates/vault/last30days/scripts/lib/cache.py +152 -0
- package/templates/vault/last30days/scripts/lib/dates.py +124 -0
- package/templates/vault/last30days/scripts/lib/dedupe.py +120 -0
- package/templates/vault/last30days/scripts/lib/env.py +149 -0
- package/templates/vault/last30days/scripts/lib/http.py +152 -0
- package/templates/vault/last30days/scripts/lib/models.py +175 -0
- package/templates/vault/last30days/scripts/lib/normalize.py +160 -0
- package/templates/vault/last30days/scripts/lib/openai_reddit.py +230 -0
- package/templates/vault/last30days/scripts/lib/reddit_enrich.py +232 -0
- package/templates/vault/last30days/scripts/lib/render.py +383 -0
- package/templates/vault/last30days/scripts/lib/schema.py +336 -0
- package/templates/vault/last30days/scripts/lib/score.py +311 -0
- package/templates/vault/last30days/scripts/lib/ui.py +324 -0
- package/templates/vault/last30days/scripts/lib/websearch.py +401 -0
- package/templates/vault/last30days/scripts/lib/xai_x.py +217 -0
- package/templates/vault/leiloeiro-avaliacao/scripts/governance.py +106 -0
- package/templates/vault/leiloeiro-avaliacao/scripts/requirements.txt +1 -0
- package/templates/vault/leiloeiro-edital/scripts/governance.py +106 -0
- package/templates/vault/leiloeiro-edital/scripts/requirements.txt +1 -0
- package/templates/vault/leiloeiro-ia/scripts/governance.py +106 -0
- package/templates/vault/leiloeiro-ia/scripts/requirements.txt +1 -0
- package/templates/vault/leiloeiro-juridico/scripts/governance.py +106 -0
- package/templates/vault/leiloeiro-juridico/scripts/requirements.txt +1 -0
- package/templates/vault/leiloeiro-mercado/scripts/governance.py +106 -0
- package/templates/vault/leiloeiro-mercado/scripts/requirements.txt +1 -0
- package/templates/vault/leiloeiro-risco/scripts/governance.py +106 -0
- package/templates/vault/leiloeiro-risco/scripts/requirements.txt +1 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/database.ts +24 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/db.ts +35 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/index.ts +2 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/migrations.ts +31 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/schema.sql +8 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/index.ts +44 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/routes/todos.ts +155 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/types/index.ts +35 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/App.css +384 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/App.tsx +81 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/api/todos.ts +57 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/ConfirmDialog.tsx +26 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/EmptyState.tsx +8 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/TodoForm.tsx +43 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/TodoItem.tsx +36 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/TodoList.tsx +27 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/hooks/useTodos.ts +81 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/index.css +48 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/main.tsx +10 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/vite-env.d.ts +1 -0
- package/templates/vault/loki-mode/scripts/export-to-vibe-kanban.sh +178 -0
- package/templates/vault/loki-mode/scripts/loki-wrapper.sh +281 -0
- package/templates/vault/loki-mode/scripts/take-screenshots.js +55 -0
- package/templates/vault/matematico-tao/scripts/complexity_analyzer.py +544 -0
- package/templates/vault/matematico-tao/scripts/dependency_graph.py +538 -0
- package/templates/vault/mcp-builder/scripts/connections.py +151 -0
- package/templates/vault/mcp-builder/scripts/evaluation.py +373 -0
- package/templates/vault/mcp-builder/scripts/example_evaluation.xml +22 -0
- package/templates/vault/mcp-builder/scripts/requirements.txt +2 -0
- package/templates/vault/mobile-design/scripts/mobile_audit.py +670 -0
- package/templates/vault/notebooklm/scripts/__init__.py +81 -0
- package/templates/vault/notebooklm/scripts/ask_question.py +256 -0
- package/templates/vault/notebooklm/scripts/auth_manager.py +358 -0
- package/templates/vault/notebooklm/scripts/browser_session.py +255 -0
- package/templates/vault/notebooklm/scripts/browser_utils.py +107 -0
- package/templates/vault/notebooklm/scripts/cleanup_manager.py +302 -0
- package/templates/vault/notebooklm/scripts/config.py +44 -0
- package/templates/vault/notebooklm/scripts/notebook_manager.py +410 -0
- package/templates/vault/notebooklm/scripts/run.py +102 -0
- package/templates/vault/notebooklm/scripts/setup_environment.py +204 -0
- package/templates/vault/pdf/scripts/check_bounding_boxes.py +70 -0
- package/templates/vault/pdf/scripts/check_bounding_boxes_test.py +226 -0
- package/templates/vault/pdf/scripts/check_fillable_fields.py +12 -0
- package/templates/vault/pdf/scripts/convert_pdf_to_images.py +35 -0
- package/templates/vault/pdf/scripts/create_validation_image.py +41 -0
- package/templates/vault/pdf/scripts/extract_form_field_info.py +152 -0
- package/templates/vault/pdf/scripts/fill_fillable_fields.py +114 -0
- package/templates/vault/pdf/scripts/fill_pdf_form_with_annotations.py +108 -0
- package/templates/vault/pdf-official/scripts/check_bounding_boxes.py +70 -0
- package/templates/vault/pdf-official/scripts/check_bounding_boxes_test.py +226 -0
- package/templates/vault/pdf-official/scripts/check_fillable_fields.py +12 -0
- package/templates/vault/pdf-official/scripts/convert_pdf_to_images.py +35 -0
- package/templates/vault/pdf-official/scripts/create_validation_image.py +41 -0
- package/templates/vault/pdf-official/scripts/extract_form_field_info.py +152 -0
- package/templates/vault/pdf-official/scripts/fill_fillable_fields.py +114 -0
- package/templates/vault/pdf-official/scripts/fill_pdf_form_with_annotations.py +108 -0
- package/templates/vault/planning-with-files/scripts/check-complete.sh +44 -0
- package/templates/vault/planning-with-files/scripts/init-session.sh +120 -0
- package/templates/vault/pptx/ooxml/scripts/pack.py +159 -0
- package/templates/vault/pptx/ooxml/scripts/unpack.py +29 -0
- package/templates/vault/pptx/ooxml/scripts/validate.py +69 -0
- package/templates/vault/pptx/ooxml/scripts/validation/__init__.py +15 -0
- package/templates/vault/pptx/ooxml/scripts/validation/base.py +951 -0
- package/templates/vault/pptx/ooxml/scripts/validation/docx.py +274 -0
- package/templates/vault/pptx/ooxml/scripts/validation/pptx.py +315 -0
- package/templates/vault/pptx/ooxml/scripts/validation/redlining.py +279 -0
- package/templates/vault/pptx/scripts/html2pptx.js +979 -0
- package/templates/vault/pptx/scripts/inventory.py +1020 -0
- package/templates/vault/pptx/scripts/rearrange.py +231 -0
- package/templates/vault/pptx/scripts/replace.py +385 -0
- package/templates/vault/pptx/scripts/thumbnail.py +450 -0
- package/templates/vault/pptx-official/ooxml/scripts/pack.py +159 -0
- package/templates/vault/pptx-official/ooxml/scripts/unpack.py +29 -0
- package/templates/vault/pptx-official/ooxml/scripts/validate.py +69 -0
- package/templates/vault/pptx-official/ooxml/scripts/validation/__init__.py +15 -0
- package/templates/vault/pptx-official/ooxml/scripts/validation/base.py +951 -0
- package/templates/vault/pptx-official/ooxml/scripts/validation/docx.py +274 -0
- package/templates/vault/pptx-official/ooxml/scripts/validation/pptx.py +315 -0
- package/templates/vault/pptx-official/ooxml/scripts/validation/redlining.py +279 -0
- package/templates/vault/pptx-official/scripts/html2pptx.js +979 -0
- package/templates/vault/pptx-official/scripts/inventory.py +1020 -0
- package/templates/vault/pptx-official/scripts/rearrange.py +231 -0
- package/templates/vault/pptx-official/scripts/replace.py +385 -0
- package/templates/vault/pptx-official/scripts/thumbnail.py +450 -0
- package/templates/vault/product-manager-toolkit/scripts/customer_interview_analyzer.py +441 -0
- package/templates/vault/product-manager-toolkit/scripts/rice_prioritizer.py +296 -0
- package/templates/vault/prompt-engineering-patterns/scripts/optimize-prompt.py +279 -0
- package/templates/vault/scripts/.skill_cache.json +7538 -0
- package/templates/vault/scripts/skill_search.py +228 -0
- package/templates/vault/senior-architect/scripts/architecture_diagram_generator.py +114 -0
- package/templates/vault/senior-architect/scripts/dependency_analyzer.py +114 -0
- package/templates/vault/senior-architect/scripts/project_architect.py +114 -0
- package/templates/vault/shopify-development/scripts/requirements.txt +19 -0
- package/templates/vault/shopify-development/scripts/shopify_graphql.py +428 -0
- package/templates/vault/shopify-development/scripts/shopify_init.py +441 -0
- package/templates/vault/shopify-development/scripts/tests/test_shopify_init.py +379 -0
- package/templates/vault/skill-creator/scripts/init_skill.py +303 -0
- package/templates/vault/skill-creator/scripts/package_skill.py +110 -0
- package/templates/vault/skill-creator/scripts/quick_validate.py +95 -0
- package/templates/vault/skill-installer/scripts/detect_skills.py +318 -0
- package/templates/vault/skill-installer/scripts/install_skill.py +1708 -0
- package/templates/vault/skill-installer/scripts/package_skill.py +417 -0
- package/templates/vault/skill-installer/scripts/requirements.txt +1 -0
- package/templates/vault/skill-installer/scripts/validate_skill.py +430 -0
- package/templates/vault/skill-sentinel/scripts/analyzers/__init__.py +13 -0
- package/templates/vault/skill-sentinel/scripts/analyzers/code_quality.py +247 -0
- package/templates/vault/skill-sentinel/scripts/analyzers/cross_skill.py +134 -0
- package/templates/vault/skill-sentinel/scripts/analyzers/dependencies.py +121 -0
- package/templates/vault/skill-sentinel/scripts/analyzers/documentation.py +189 -0
- package/templates/vault/skill-sentinel/scripts/analyzers/governance_audit.py +153 -0
- package/templates/vault/skill-sentinel/scripts/analyzers/performance.py +164 -0
- package/templates/vault/skill-sentinel/scripts/analyzers/security.py +189 -0
- package/templates/vault/skill-sentinel/scripts/config.py +158 -0
- package/templates/vault/skill-sentinel/scripts/cost_optimizer.py +146 -0
- package/templates/vault/skill-sentinel/scripts/db.py +354 -0
- package/templates/vault/skill-sentinel/scripts/governance.py +58 -0
- package/templates/vault/skill-sentinel/scripts/recommender.py +228 -0
- package/templates/vault/skill-sentinel/scripts/report_generator.py +224 -0
- package/templates/vault/skill-sentinel/scripts/requirements.txt +1 -0
- package/templates/vault/skill-sentinel/scripts/run_audit.py +290 -0
- package/templates/vault/skill-sentinel/scripts/scanner.py +271 -0
- package/templates/vault/stability-ai/scripts/config.py +266 -0
- package/templates/vault/stability-ai/scripts/generate.py +687 -0
- package/templates/vault/stability-ai/scripts/requirements.txt +4 -0
- package/templates/vault/stability-ai/scripts/styles.py +174 -0
- package/templates/vault/telegram/assets/boilerplate/nodejs/src/bot-client.ts +86 -0
- package/templates/vault/telegram/assets/boilerplate/nodejs/src/handlers.ts +79 -0
- package/templates/vault/telegram/assets/boilerplate/nodejs/src/index.ts +32 -0
- package/templates/vault/telegram/scripts/send_message.py +143 -0
- package/templates/vault/telegram/scripts/setup_project.py +103 -0
- package/templates/vault/telegram/scripts/test_bot.py +144 -0
- package/templates/vault/typescript-expert/scripts/ts_diagnostic.py +203 -0
- package/templates/vault/ui-ux-pro-max/scripts/__pycache__/core.cpython-314.pyc +0 -0
- package/templates/vault/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-314.pyc +0 -0
- package/templates/vault/ui-ux-pro-max/scripts/core.py +257 -0
- package/templates/vault/ui-ux-pro-max/scripts/design_system.py +487 -0
- package/templates/vault/ui-ux-pro-max/scripts/search.py +76 -0
- package/templates/vault/videodb/scripts/ws_listener.py +204 -0
- package/templates/vault/web-artifacts-builder/scripts/bundle-artifact.sh +54 -0
- package/templates/vault/web-artifacts-builder/scripts/init-artifact.sh +322 -0
- package/templates/vault/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
- package/templates/vault/webapp-testing/scripts/with_server.py +106 -0
- package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/index.ts +125 -0
- package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/template-manager.ts +67 -0
- package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/types.ts +216 -0
- package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/webhook-handler.ts +173 -0
- package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/whatsapp-client.ts +193 -0
- package/templates/vault/whatsapp-cloud-api/scripts/send_test_message.py +137 -0
- package/templates/vault/whatsapp-cloud-api/scripts/setup_project.py +118 -0
- package/templates/vault/whatsapp-cloud-api/scripts/validate_config.py +190 -0
- package/templates/vault/youtube-summarizer/scripts/extract-transcript.py +65 -0
- package/templates/vault/youtube-summarizer/scripts/install-dependencies.sh +28 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Scraper JUCISRS — Junta Comercial, Industrial e Servicos do Rio Grande do Sul
|
|
3
|
+
URL: https://sistemas.jucisrs.rs.gov.br/leiloeiros/
|
|
4
|
+
Metodo: httpx POST com verify=False (SSL invalido mas conteudo OK)
|
|
5
|
+
Mecanismo real descoberto em 2026-02-25:
|
|
6
|
+
- GET https://sistemas.jucisrs.rs.gov.br/leiloeiros/
|
|
7
|
+
-> retorna formulario de busca PHP/Bootstrap
|
|
8
|
+
- POST https://sistemas.jucisrs.rs.gov.br/leiloeiros/busca/listar
|
|
9
|
+
com Nome=Todos (retorna todos os 376 registros)
|
|
10
|
+
Estrutura HTML: <b><font color="#A01A14">MATRICULA</font> - NOME<br>
|
|
11
|
+
separados por <hr> entre entradas
|
|
12
|
+
Total: 376 leiloeiros (261 ativos + 111 cancelados)
|
|
13
|
+
Nota: Antigo dominio jucers.rs.gov.br foi aposentado. Junta renomeada para JUCISRS.
|
|
14
|
+
"""
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import logging
|
|
18
|
+
import re
|
|
19
|
+
from typing import List
|
|
20
|
+
|
|
21
|
+
from .base_scraper import AbstractJuntaScraper, Leiloeiro
|
|
22
|
+
|
|
23
|
+
logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
# Regex para extrair dados do formato plano JUCISRS
|
|
26
|
+
RE_MATRICULA_NOME = re.compile(r"(\d+)\s*-\s*(.+)")
|
|
27
|
+
RE_POSSE = re.compile(r"[Pp]osse\s*:\s*(\d{2}/\d{2}/\d{4})")
|
|
28
|
+
RE_TELEFONE = re.compile(r"[Tt]elefone\s*:\s*(.+)")
|
|
29
|
+
RE_EMAIL = re.compile(r"[Ee]-[Mm]ail\s*:\s*(.+)")
|
|
30
|
+
RE_PREPOSTO = re.compile(r"[Pp]reposto\s*:\s*(.+)")
|
|
31
|
+
RE_CEP = re.compile(r"CEP\s+([\d.]+)")
|
|
32
|
+
RE_CANCELADO = re.compile(r"CANCELAD|CANCELAMENTO|canc\.", re.IGNORECASE)
|
|
33
|
+
RE_CIDADE_UF = re.compile(r"^([A-ZÁÉÍÓÚÀÃÕÇ][A-ZÁÉÍÓÚÀÃÕÇ\s]+)\s+-\s+RS$")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class JucisrsScraper(AbstractJuntaScraper):
|
|
37
|
+
estado = "RS"
|
|
38
|
+
junta = "JUCISRS"
|
|
39
|
+
url = "https://sistemas.jucisrs.rs.gov.br/leiloeiros/"
|
|
40
|
+
url_fallback = "https://jucisrs.rs.gov.br/leiloeiro"
|
|
41
|
+
|
|
42
|
+
_POST_URL = "https://sistemas.jucisrs.rs.gov.br/leiloeiros/busca/listar"
|
|
43
|
+
|
|
44
|
+
def _parse_plain_html(self, html: str) -> List[dict]:
|
|
45
|
+
"""
|
|
46
|
+
Parseia o formato plano HTML da JUCISRS.
|
|
47
|
+
Toda a lista esta dentro de um unico grande <b> com <hr> como separadores.
|
|
48
|
+
Estrutura por entrada (separada por <hr/>):
|
|
49
|
+
<font color="#A01A14">173</font> - NOME<br/>
|
|
50
|
+
[www.site.com.br<br/>]
|
|
51
|
+
<b>Posse : </b>DD/MM/AAAA<br/>
|
|
52
|
+
ENDERECO<br/>
|
|
53
|
+
CIDADE - RS<br/>
|
|
54
|
+
CEP XXXXX-XXX<br/>
|
|
55
|
+
Telefone : XXXXX<br/>
|
|
56
|
+
e-Mail : xxx@yyy<br/>
|
|
57
|
+
Preposto : NOME<hr/>
|
|
58
|
+
"""
|
|
59
|
+
from bs4 import BeautifulSoup
|
|
60
|
+
|
|
61
|
+
records = []
|
|
62
|
+
|
|
63
|
+
# Dividir o HTML bruto pelo separador <hr> ou <hr/>
|
|
64
|
+
# Isso e mais confiavel que navegar o DOM pois o <b> gigante contem tudo
|
|
65
|
+
blocks = re.split(r"<hr\s*/?>", html, flags=re.IGNORECASE)
|
|
66
|
+
logger.debug("[RS] Total de blocos (separados por <hr>): %d", len(blocks))
|
|
67
|
+
|
|
68
|
+
for block in blocks:
|
|
69
|
+
if not block.strip():
|
|
70
|
+
continue
|
|
71
|
+
|
|
72
|
+
# Parsear o bloco como HTML para extrair texto estruturado
|
|
73
|
+
block_soup = BeautifulSoup(block, "lxml")
|
|
74
|
+
lines_raw = block_soup.get_text("\n").splitlines()
|
|
75
|
+
lines = [l.strip() for l in lines_raw if l.strip()]
|
|
76
|
+
|
|
77
|
+
if not lines:
|
|
78
|
+
continue
|
|
79
|
+
|
|
80
|
+
# Primeira linha com matricula e nome: "NNN - NOME SOBRENOME"
|
|
81
|
+
# NOTA: O <font> de cor separa matricula e nome em linhas distintas:
|
|
82
|
+
# lines[0] = "365" (matricula dentro do <font>)
|
|
83
|
+
# lines[1] = "- ADAIR ABRAAO..." (nome apos o <font>)
|
|
84
|
+
# Precisamos reconhecer e juntar esses dois fragmentos.
|
|
85
|
+
nome = None
|
|
86
|
+
matricula = None
|
|
87
|
+
situacao = None
|
|
88
|
+
remaining = []
|
|
89
|
+
|
|
90
|
+
for i, line in enumerate(lines):
|
|
91
|
+
# Padrao 1: matricula e nome na mesma linha "365 - NOME"
|
|
92
|
+
m = RE_MATRICULA_NOME.match(line)
|
|
93
|
+
if m:
|
|
94
|
+
matricula = m.group(1)
|
|
95
|
+
nome_raw = m.group(2).strip()
|
|
96
|
+
if RE_CANCELADO.search(nome_raw):
|
|
97
|
+
situacao = "CANCELADO"
|
|
98
|
+
nome_raw = RE_CANCELADO.sub("", nome_raw).strip(" ")
|
|
99
|
+
nome = self.clean(nome_raw)
|
|
100
|
+
remaining = lines[i+1:]
|
|
101
|
+
break
|
|
102
|
+
# Padrao 2: so matricula (numero puro), proximo e "- NOME"
|
|
103
|
+
if line.isdigit() and i + 1 < len(lines):
|
|
104
|
+
next_line = lines[i+1]
|
|
105
|
+
if next_line.startswith("- ") or next_line.startswith("– "):
|
|
106
|
+
matricula = line
|
|
107
|
+
nome_raw = next_line[2:].strip()
|
|
108
|
+
if RE_CANCELADO.search(nome_raw):
|
|
109
|
+
situacao = "CANCELADO"
|
|
110
|
+
nome_raw = RE_CANCELADO.sub("", nome_raw).strip(" ")
|
|
111
|
+
nome = self.clean(nome_raw)
|
|
112
|
+
remaining = lines[i+2:]
|
|
113
|
+
break
|
|
114
|
+
|
|
115
|
+
if not nome or len(nome) < 3:
|
|
116
|
+
continue
|
|
117
|
+
|
|
118
|
+
record = {
|
|
119
|
+
"nome": nome,
|
|
120
|
+
"matricula": matricula,
|
|
121
|
+
"situacao": situacao,
|
|
122
|
+
"municipio": "Porto Alegre",
|
|
123
|
+
"data_registro": None,
|
|
124
|
+
"telefone": None,
|
|
125
|
+
"email": None,
|
|
126
|
+
"endereco": None,
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
for line in remaining:
|
|
130
|
+
if not line:
|
|
131
|
+
continue
|
|
132
|
+
# Cancelado inline (linha separada como "(Cancelado)")
|
|
133
|
+
if RE_CANCELADO.search(line) and not record["situacao"]:
|
|
134
|
+
record["situacao"] = "CANCELADO"
|
|
135
|
+
continue
|
|
136
|
+
m = RE_POSSE.search(line)
|
|
137
|
+
if m:
|
|
138
|
+
record["data_registro"] = m.group(1)
|
|
139
|
+
continue
|
|
140
|
+
m = RE_TELEFONE.search(line)
|
|
141
|
+
if m:
|
|
142
|
+
record["telefone"] = self.clean(m.group(1))
|
|
143
|
+
continue
|
|
144
|
+
m = RE_EMAIL.search(line)
|
|
145
|
+
if m:
|
|
146
|
+
record["email"] = self.clean(m.group(1))
|
|
147
|
+
continue
|
|
148
|
+
m = RE_PREPOSTO.match(line)
|
|
149
|
+
if m:
|
|
150
|
+
continue # ignorar preposto
|
|
151
|
+
# Cidade/UF: "CANELA - RS" ou "PORTO ALEGRE - RS"
|
|
152
|
+
m = RE_CIDADE_UF.search(line)
|
|
153
|
+
if m:
|
|
154
|
+
record["municipio"] = m.group(1).strip()
|
|
155
|
+
continue
|
|
156
|
+
if RE_CEP.search(line):
|
|
157
|
+
continue # linha de CEP
|
|
158
|
+
# Linha de url (site)
|
|
159
|
+
if line.startswith("www.") or line.startswith("http"):
|
|
160
|
+
continue
|
|
161
|
+
# Linha de endereco
|
|
162
|
+
if (not record["endereco"] and len(line) > 5 and
|
|
163
|
+
re.search(r"[A-ZÁÉÍÓÚÀÃÕÇ]", line)):
|
|
164
|
+
record["endereco"] = line
|
|
165
|
+
|
|
166
|
+
records.append(record)
|
|
167
|
+
|
|
168
|
+
return records
|
|
169
|
+
|
|
170
|
+
async def _fetch_post(self) -> List[dict]:
|
|
171
|
+
"""
|
|
172
|
+
POST para /leiloeiros/busca/listar com Nome=Todos.
|
|
173
|
+
Retorna todos os 376 registros em resposta unica.
|
|
174
|
+
"""
|
|
175
|
+
import httpx
|
|
176
|
+
|
|
177
|
+
try:
|
|
178
|
+
async with httpx.AsyncClient(
|
|
179
|
+
headers=self.HEADERS,
|
|
180
|
+
verify=False, # Cert autoassinado/invalido
|
|
181
|
+
follow_redirects=True,
|
|
182
|
+
timeout=60.0,
|
|
183
|
+
) as client:
|
|
184
|
+
# GET primeiro para obter cookies/CSRF se necessario
|
|
185
|
+
try:
|
|
186
|
+
await client.get(self.url)
|
|
187
|
+
except Exception:
|
|
188
|
+
pass
|
|
189
|
+
|
|
190
|
+
resp = await client.post(
|
|
191
|
+
self._POST_URL,
|
|
192
|
+
data={
|
|
193
|
+
"Nome": "",
|
|
194
|
+
"CodMunicipio": "0", # 0 = Todas as cidades
|
|
195
|
+
"Situacao": "TODOS",
|
|
196
|
+
"Funcao": "LEILOEIRO",
|
|
197
|
+
},
|
|
198
|
+
headers={
|
|
199
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
200
|
+
"Referer": self.url,
|
|
201
|
+
"Origin": "https://sistemas.jucisrs.rs.gov.br",
|
|
202
|
+
},
|
|
203
|
+
)
|
|
204
|
+
if resp.status_code >= 400:
|
|
205
|
+
logger.warning("[RS] POST retornou HTTP %d", resp.status_code)
|
|
206
|
+
return []
|
|
207
|
+
|
|
208
|
+
logger.info("[RS] POST OK - tamanho resposta: %d bytes", len(resp.content))
|
|
209
|
+
return self._parse_plain_html(resp.text)
|
|
210
|
+
|
|
211
|
+
except Exception as exc:
|
|
212
|
+
logger.error("[RS] Erro no POST: %s", exc)
|
|
213
|
+
return []
|
|
214
|
+
|
|
215
|
+
async def _fetch_get_all(self) -> List[dict]:
|
|
216
|
+
"""
|
|
217
|
+
Fallback: GET simples na URL principal com verify=False.
|
|
218
|
+
Pode retornar formulario ou lista parcial.
|
|
219
|
+
"""
|
|
220
|
+
import httpx
|
|
221
|
+
from bs4 import BeautifulSoup
|
|
222
|
+
|
|
223
|
+
try:
|
|
224
|
+
async with httpx.AsyncClient(
|
|
225
|
+
headers=self.HEADERS,
|
|
226
|
+
verify=False,
|
|
227
|
+
follow_redirects=True,
|
|
228
|
+
timeout=30.0,
|
|
229
|
+
) as client:
|
|
230
|
+
resp = await client.get(self.url)
|
|
231
|
+
if resp.status_code >= 400:
|
|
232
|
+
return []
|
|
233
|
+
soup = BeautifulSoup(resp.text, "lxml")
|
|
234
|
+
return self._parse_plain_html(resp.text)
|
|
235
|
+
except Exception as exc:
|
|
236
|
+
logger.error("[RS] Erro no GET: %s", exc)
|
|
237
|
+
return []
|
|
238
|
+
|
|
239
|
+
async def _playwright_ssl_bypass(self, url: str):
|
|
240
|
+
"""Playwright com SSL completamente desabilitado para cert autoassinado."""
|
|
241
|
+
try:
|
|
242
|
+
from playwright.async_api import async_playwright
|
|
243
|
+
from bs4 import BeautifulSoup
|
|
244
|
+
async with async_playwright() as pw:
|
|
245
|
+
browser = await pw.chromium.launch(
|
|
246
|
+
headless=True,
|
|
247
|
+
args=[
|
|
248
|
+
"--ignore-certificate-errors",
|
|
249
|
+
"--ignore-ssl-errors",
|
|
250
|
+
"--disable-web-security",
|
|
251
|
+
"--allow-insecure-localhost",
|
|
252
|
+
],
|
|
253
|
+
)
|
|
254
|
+
ctx = await browser.new_context(
|
|
255
|
+
user_agent=self.HEADERS["User-Agent"],
|
|
256
|
+
ignore_https_errors=True,
|
|
257
|
+
)
|
|
258
|
+
page = await ctx.new_page()
|
|
259
|
+
try:
|
|
260
|
+
await page.goto(url, timeout=60000, wait_until="networkidle")
|
|
261
|
+
# Submeter o formulario com "Todos"
|
|
262
|
+
try:
|
|
263
|
+
await page.fill("input[name='Nome']", "Todos")
|
|
264
|
+
await page.click("button[type='submit'], input[type='submit']")
|
|
265
|
+
await page.wait_for_load_state("networkidle", timeout=30000)
|
|
266
|
+
except Exception:
|
|
267
|
+
pass
|
|
268
|
+
except Exception:
|
|
269
|
+
pass
|
|
270
|
+
html = await page.content()
|
|
271
|
+
await browser.close()
|
|
272
|
+
return self._parse_plain_html(html)
|
|
273
|
+
except Exception as exc:
|
|
274
|
+
logger.error("[RS] Playwright SSL bypass falhou: %s", exc)
|
|
275
|
+
return []
|
|
276
|
+
|
|
277
|
+
async def parse_leiloeiros(self) -> List[Leiloeiro]:
|
|
278
|
+
# Estrategia 1: POST direto (mais eficiente, retorna todos de uma vez)
|
|
279
|
+
records = await self._fetch_post()
|
|
280
|
+
|
|
281
|
+
if not records:
|
|
282
|
+
# Estrategia 2: GET simples
|
|
283
|
+
logger.info("[RS] POST falhou, tentando GET simples")
|
|
284
|
+
records = await self._fetch_get_all()
|
|
285
|
+
|
|
286
|
+
if not records:
|
|
287
|
+
# Estrategia 3: Playwright com SSL bypass e submissao de formulario
|
|
288
|
+
logger.info("[RS] GET falhou, tentando Playwright com SSL bypass")
|
|
289
|
+
records = await self._playwright_ssl_bypass(self.url)
|
|
290
|
+
|
|
291
|
+
if not records:
|
|
292
|
+
# Estrategia 4: Pagina informativa (pode ter lista estatica)
|
|
293
|
+
logger.info("[RS] Tentando pagina informativa: %s", self.url_fallback)
|
|
294
|
+
soup = await self.fetch_page(url=self.url_fallback)
|
|
295
|
+
if soup:
|
|
296
|
+
records = self._parse_plain_html(str(soup))
|
|
297
|
+
|
|
298
|
+
logger.info("[RS] Total de registros encontrados: %d", len(records))
|
|
299
|
+
return [self.make_leiloeiro(**r) for r in records if r.get("nome")]
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Registro de todos os 27 scrapers das Juntas Comerciais do Brasil.
|
|
3
|
+
Cada entrada define estado, junta, URL e scraper a ser usado.
|
|
4
|
+
|
|
5
|
+
URLs verificadas e atualizadas em 2026-02-25.
|
|
6
|
+
Scrapers customizados têm lógica específica para cada site.
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from typing import Type
|
|
11
|
+
|
|
12
|
+
from .base_scraper import AbstractJuntaScraper
|
|
13
|
+
from .generic_scraper import GenericJuntaScraper
|
|
14
|
+
|
|
15
|
+
# Scrapers customizados — lógica específica por estado
|
|
16
|
+
from .jucesp import JucespScraper # SP
|
|
17
|
+
from .jucerja import JucerjaScraper # RJ (Playwright)
|
|
18
|
+
from .jucemg import JucemgScraper # MG
|
|
19
|
+
from .jucec import JucecScraper # CE
|
|
20
|
+
from .jucis_df import JucisDfScraper # DF
|
|
21
|
+
from .jucisrs import JucisrsScraper # RS (Playwright - JUCISRS, domínio antigo aposentado)
|
|
22
|
+
from .jucepar import JuceparScraper # PR (URL migrou para juntacomercial.pr.gov.br)
|
|
23
|
+
from .jucesc import JucescScraper # SC (sistema dedicado leiloeiros.jucesc.sc.gov.br)
|
|
24
|
+
from .juceb import JucebScraper # BA (URL migrou para ba.gov.br/juceb)
|
|
25
|
+
from .jucepe import JucepeScraper # PE (Playwright - portal.jucepe.pe.gov.br)
|
|
26
|
+
from .jucepa import JucepaScraper # PA (Drupal node/171)
|
|
27
|
+
from .jucema import JucemaScraper # MA (múltiplas tentativas de URL)
|
|
28
|
+
from .jucepi import JucepiScraper # PI (URL migrou para portal.pi.gov.br/jucepi)
|
|
29
|
+
from .jucern import JucernScraper # RN (HTTP com query string)
|
|
30
|
+
from .jucep import JucepScraper # PB (JUCEP - domínio migrou para jucep.pb.gov.br)
|
|
31
|
+
from .juceal import JucealScraper # AL (URL correta: /servicos/leiloeiros)
|
|
32
|
+
from .jucer import JucerScraper # RO (URL migrou para rondonia.ro.gov.br/jucer)
|
|
33
|
+
from .jucap import JucapScraper # AP (HTTP - cert TLS inválido)
|
|
34
|
+
from .juceac import JuceacScraper # AC (URL correta: /leiloeiro/ singular)
|
|
35
|
+
from .jucetins import JucetinsScraper # TO (JUCETINS - URL migrou para to.gov.br/jucetins)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _make(estado: str, junta: str, url: str, municipio_default: str = None) -> Type[AbstractJuntaScraper]:
|
|
39
|
+
"""Cria dinamicamente uma classe de scraper genérico para o estado."""
|
|
40
|
+
attrs = {
|
|
41
|
+
"estado": estado,
|
|
42
|
+
"junta": junta,
|
|
43
|
+
"url": url,
|
|
44
|
+
"municipio_default": municipio_default,
|
|
45
|
+
}
|
|
46
|
+
return type(f"{junta}Scraper", (GenericJuntaScraper,), attrs)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# Mapeamento completo: UF -> Classe de Scraper
|
|
50
|
+
# Todos os 27 estados com URLs verificadas e atualizadas em 2026-02-25
|
|
51
|
+
SCRAPERS: dict[str, Type[AbstractJuntaScraper]] = {
|
|
52
|
+
# Região Sudeste
|
|
53
|
+
"SP": JucespScraper, # JUCESP - https://www.institucional.jucesp.sp.gov.br/tradutores-leiloeiros.html
|
|
54
|
+
"RJ": JucerjaScraper, # JUCERJA - https://www.jucerja.rj.gov.br/AuxiliaresComercio/Leiloeiros (JS)
|
|
55
|
+
"MG": JucemgScraper, # JUCEMG - https://jucemg.mg.gov.br/pagina/139/leiloeiros-oficiais
|
|
56
|
+
"ES": _make("ES", "JUCEES", "https://jucees.es.gov.br/leiloeiros", "Vitória"),
|
|
57
|
+
|
|
58
|
+
# Região Sul
|
|
59
|
+
"RS": JucisrsScraper, # JUCISRS - https://sistemas.jucisrs.rs.gov.br/leiloeiros/ (JS)
|
|
60
|
+
"PR": JuceparScraper, # JUCEPAR - https://www.juntacomercial.pr.gov.br/Pagina/LEILOEIROS-OFICIAIS
|
|
61
|
+
"SC": JucescScraper, # JUCESC - https://leiloeiros.jucesc.sc.gov.br/site/
|
|
62
|
+
|
|
63
|
+
# Região Nordeste
|
|
64
|
+
"BA": JucebScraper, # JUCEB - https://www.ba.gov.br/juceb/home/matriculas-e-carteira-profissional/leiloeiros
|
|
65
|
+
"PE": JucepeScraper, # JUCEPE - https://portal.jucepe.pe.gov.br/leiloeiros (JS)
|
|
66
|
+
"CE": JucecScraper, # JUCEC - https://www.jucec.ce.gov.br/leiloeiros/
|
|
67
|
+
"MA": JucemaScraper, # JUCEMA - múltiplas URLs tentadas
|
|
68
|
+
"PI": JucepiScraper, # JUCEPI - https://portal.pi.gov.br/jucepi/leiloeiro-oficial/
|
|
69
|
+
"RN": JucernScraper, # JUCERN - http://www.jucern.rn.gov.br/Conteudo.asp?TRAN=ITEM&TARG=8695...
|
|
70
|
+
"PB": JucepScraper, # JUCEP - https://jucep.pb.gov.br/contatos/leiloeiros
|
|
71
|
+
"AL": JucealScraper, # JUCEAL - http://www.juceal.al.gov.br/servicos/leiloeiros
|
|
72
|
+
"SE": _make("SE", "JUCESE", "https://jucese.se.gov.br/leiloeiros/", "Aracaju"),
|
|
73
|
+
|
|
74
|
+
# Região Centro-Oeste
|
|
75
|
+
"DF": JucisDfScraper, # JUCIS-DF - https://jucis.df.gov.br/leiloeiros/
|
|
76
|
+
"GO": _make("GO", "JUCEG", "https://goias.gov.br/juceg/", "Goiânia"),
|
|
77
|
+
"MT": _make("MT", "JUCEMAT", "https://www.jucemat.mt.gov.br/leiloeiros", "Cuiabá"),
|
|
78
|
+
"MS": _make("MS", "JUCEMS", "https://www.jucems.ms.gov.br/empresas/controles-especiais/agentes-auxiliares/leiloeiros/", "Campo Grande"),
|
|
79
|
+
|
|
80
|
+
# Região Norte
|
|
81
|
+
"PA": JucepaScraper, # JUCEPA - https://www.jucepa.pa.gov.br/node/171
|
|
82
|
+
"AM": _make("AM", "JUCEA", "https://www.jucea.am.gov.br/leiloeiros/", "Manaus"),
|
|
83
|
+
"RO": JucerScraper, # JUCER - https://rondonia.ro.gov.br/jucer/lista-de-leiloeiros-oficiais/
|
|
84
|
+
"RR": _make("RR", "JUCERR", "https://jucerr.rr.gov.br/leiloeiros/", "Boa Vista"),
|
|
85
|
+
"AP": JucapScraper, # JUCAP - http://www.jucap.ap.gov.br/leiloeiros (HTTP - TLS inválido)
|
|
86
|
+
"AC": JuceacScraper, # JUCEAC - https://juceac.ac.gov.br/leiloeiro/
|
|
87
|
+
"TO": JucetinsScraper, # JUCETINS - https://www.to.gov.br/jucetins/leiloeiros/152aezl6blm0
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def get_all_scrapers() -> list[AbstractJuntaScraper]:
|
|
92
|
+
"""Retorna instâncias de todos os scrapers."""
|
|
93
|
+
return [cls() for cls in SCRAPERS.values()]
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def get_scraper(estado: str) -> AbstractJuntaScraper | None:
|
|
97
|
+
"""Retorna o scraper para um estado específico (UF)."""
|
|
98
|
+
cls = SCRAPERS.get(estado.upper())
|
|
99
|
+
return cls() if cls else None
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"""
|
|
2
|
+
API REST para consulta de leiloeiros das Juntas Comerciais do Brasil.
|
|
3
|
+
|
|
4
|
+
Uso:
|
|
5
|
+
python scripts/serve_api.py
|
|
6
|
+
python scripts/serve_api.py --port 8080 --host 0.0.0.0
|
|
7
|
+
|
|
8
|
+
Endpoints:
|
|
9
|
+
GET / → info da API
|
|
10
|
+
GET /leiloeiros → lista todos (filtros: estado, situacao, nome, limit, offset)
|
|
11
|
+
GET /leiloeiros/{estado} → por UF
|
|
12
|
+
GET /busca?q=texto → busca por nome/matrícula/município
|
|
13
|
+
GET /stats → contagem por estado
|
|
14
|
+
GET /export/json → dump completo em JSON
|
|
15
|
+
GET /export/csv → dump completo em CSV
|
|
16
|
+
"""
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
import argparse
|
|
20
|
+
import csv
|
|
21
|
+
import io
|
|
22
|
+
import json
|
|
23
|
+
import sys
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
from typing import List, Optional
|
|
26
|
+
|
|
27
|
+
sys.path.insert(0, str(Path(__file__).parent))
|
|
28
|
+
|
|
29
|
+
from db import Database
|
|
30
|
+
|
|
31
|
+
try:
|
|
32
|
+
from fastapi import FastAPI, HTTPException, Query
|
|
33
|
+
from fastapi.responses import JSONResponse, PlainTextResponse, StreamingResponse
|
|
34
|
+
import uvicorn
|
|
35
|
+
except ImportError:
|
|
36
|
+
print("FastAPI não instalado. Execute: pip install fastapi uvicorn")
|
|
37
|
+
sys.exit(1)
|
|
38
|
+
|
|
39
|
+
app = FastAPI(
|
|
40
|
+
title="Leiloeiros Juntas Comerciais Brasil",
|
|
41
|
+
description="API de dados de leiloeiros oficiais de todas as 27 Juntas Comerciais do Brasil",
|
|
42
|
+
version="1.0.0",
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
db = Database()
|
|
46
|
+
db.init()
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@app.get("/", summary="Informações da API")
|
|
50
|
+
def root():
|
|
51
|
+
total = db.get_total()
|
|
52
|
+
return {
|
|
53
|
+
"name": "Leiloeiros Juntas Comerciais Brasil",
|
|
54
|
+
"version": "1.0.0",
|
|
55
|
+
"total_registros": total,
|
|
56
|
+
"endpoints": {
|
|
57
|
+
"lista": "/leiloeiros",
|
|
58
|
+
"por_estado": "/leiloeiros/{estado}",
|
|
59
|
+
"busca": "/busca?q=texto",
|
|
60
|
+
"stats": "/stats",
|
|
61
|
+
"export_json": "/export/json",
|
|
62
|
+
"export_csv": "/export/csv",
|
|
63
|
+
},
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@app.get("/leiloeiros", summary="Lista leiloeiros com filtros")
|
|
68
|
+
def list_leiloeiros(
|
|
69
|
+
estado: Optional[str] = Query(None, description="UF ex: SP, RJ, MG"),
|
|
70
|
+
situacao: Optional[str] = Query(None, description="ATIVO, CANCELADO, SUSPENSO"),
|
|
71
|
+
nome: Optional[str] = Query(None, description="Busca parcial por nome"),
|
|
72
|
+
limit: int = Query(100, ge=1, le=5000),
|
|
73
|
+
offset: int = Query(0, ge=0),
|
|
74
|
+
):
|
|
75
|
+
records = db.get_all(
|
|
76
|
+
estado=estado,
|
|
77
|
+
situacao=situacao,
|
|
78
|
+
nome_like=nome,
|
|
79
|
+
limit=limit,
|
|
80
|
+
offset=offset,
|
|
81
|
+
)
|
|
82
|
+
return {"total": len(records), "offset": offset, "data": records}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@app.get("/leiloeiros/{estado}", summary="Leiloeiros de um estado específico")
|
|
86
|
+
def leiloeiros_por_estado(estado: str):
|
|
87
|
+
estado = estado.upper()
|
|
88
|
+
if len(estado) != 2:
|
|
89
|
+
raise HTTPException(status_code=400, detail="Estado deve ser a UF com 2 letras (ex: SP)")
|
|
90
|
+
records = db.get_by_estado(estado)
|
|
91
|
+
return {"estado": estado, "total": len(records), "data": records}
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@app.get("/busca", summary="Busca por nome, matrícula ou município")
|
|
95
|
+
def busca(
|
|
96
|
+
q: str = Query(..., description="Texto para buscar"),
|
|
97
|
+
limit: int = Query(50, ge=1, le=500),
|
|
98
|
+
):
|
|
99
|
+
if len(q) < 2:
|
|
100
|
+
raise HTTPException(status_code=400, detail="Query deve ter pelo menos 2 caracteres")
|
|
101
|
+
records = db.search(q, limit=limit)
|
|
102
|
+
return {"query": q, "total": len(records), "data": records}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
@app.get("/stats", summary="Estatísticas por estado")
|
|
106
|
+
def stats():
|
|
107
|
+
data = db.get_stats()
|
|
108
|
+
total = sum(r["total"] for r in data)
|
|
109
|
+
return {"total_geral": total, "por_estado": data}
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
@app.get("/export/json", summary="Exporta todos os dados em JSON")
|
|
113
|
+
def export_json():
|
|
114
|
+
records = db.get_all()
|
|
115
|
+
return JSONResponse(
|
|
116
|
+
content={"total": len(records), "data": records},
|
|
117
|
+
headers={"Content-Disposition": "attachment; filename=leiloeiros.json"},
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@app.get("/export/csv", summary="Exporta todos os dados em CSV")
|
|
122
|
+
def export_csv():
|
|
123
|
+
records = db.get_all()
|
|
124
|
+
if not records:
|
|
125
|
+
return PlainTextResponse("Nenhum dado encontrado.")
|
|
126
|
+
|
|
127
|
+
output = io.StringIO()
|
|
128
|
+
writer = csv.DictWriter(
|
|
129
|
+
output,
|
|
130
|
+
fieldnames=list(records[0].keys()),
|
|
131
|
+
extrasaction="ignore",
|
|
132
|
+
)
|
|
133
|
+
writer.writeheader()
|
|
134
|
+
writer.writerows(records)
|
|
135
|
+
output.seek(0)
|
|
136
|
+
|
|
137
|
+
return StreamingResponse(
|
|
138
|
+
iter([output.getvalue()]),
|
|
139
|
+
media_type="text/csv",
|
|
140
|
+
headers={"Content-Disposition": "attachment; filename=leiloeiros.csv"},
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def main():
|
|
145
|
+
parser = argparse.ArgumentParser(description="Servidor API de leiloeiros")
|
|
146
|
+
parser.add_argument("--host", default="127.0.0.1")
|
|
147
|
+
parser.add_argument("--port", type=int, default=8000)
|
|
148
|
+
parser.add_argument("--reload", action="store_true")
|
|
149
|
+
args = parser.parse_args()
|
|
150
|
+
|
|
151
|
+
print(f"\nAPI disponível em: http://{args.host}:{args.port}")
|
|
152
|
+
print(f"Docs interativos: http://{args.host}:{args.port}/docs\n")
|
|
153
|
+
|
|
154
|
+
uvicorn.run(
|
|
155
|
+
"serve_api:app",
|
|
156
|
+
host=args.host,
|
|
157
|
+
port=args.port,
|
|
158
|
+
reload=args.reload,
|
|
159
|
+
app_dir=str(Path(__file__).parent),
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
if __name__ == "__main__":
|
|
164
|
+
main()
|