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,241 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
i18n Checker - Detects hardcoded strings and missing translations.
|
|
4
|
+
Scans for untranslated text in React, Vue, and Python files.
|
|
5
|
+
"""
|
|
6
|
+
import sys
|
|
7
|
+
import re
|
|
8
|
+
import json
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
# Fix Windows console encoding for Unicode output
|
|
12
|
+
try:
|
|
13
|
+
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
|
|
14
|
+
sys.stderr.reconfigure(encoding='utf-8', errors='replace')
|
|
15
|
+
except AttributeError:
|
|
16
|
+
pass # Python < 3.7
|
|
17
|
+
|
|
18
|
+
# Patterns that indicate hardcoded strings (should be translated)
|
|
19
|
+
HARDCODED_PATTERNS = {
|
|
20
|
+
'jsx': [
|
|
21
|
+
# Text directly in JSX: <div>Hello World</div>
|
|
22
|
+
r'>\s*[A-Z][a-zA-Z\s]{3,30}\s*</',
|
|
23
|
+
# JSX attribute strings: title="Welcome"
|
|
24
|
+
r'(title|placeholder|label|alt|aria-label)="[A-Z][a-zA-Z\s]{2,}"',
|
|
25
|
+
# Button/heading text
|
|
26
|
+
r'<(button|h[1-6]|p|span|label)[^>]*>\s*[A-Z][a-zA-Z\s!?.,]{3,}\s*</',
|
|
27
|
+
],
|
|
28
|
+
'vue': [
|
|
29
|
+
# Vue template text
|
|
30
|
+
r'>\s*[A-Z][a-zA-Z\s]{3,30}\s*</',
|
|
31
|
+
r'(placeholder|label|title)="[A-Z][a-zA-Z\s]{2,}"',
|
|
32
|
+
],
|
|
33
|
+
'python': [
|
|
34
|
+
# print/raise with string literals
|
|
35
|
+
r'(print|raise\s+\w+)\s*\(\s*["\'][A-Z][^"\']{5,}["\']',
|
|
36
|
+
# Flask flash messages
|
|
37
|
+
r'flash\s*\(\s*["\'][A-Z][^"\']{5,}["\']',
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
# Patterns that indicate proper i18n usage
|
|
42
|
+
I18N_PATTERNS = [
|
|
43
|
+
r't\(["\']', # t('key') - react-i18next
|
|
44
|
+
r'useTranslation', # React hook
|
|
45
|
+
r'\$t\(', # Vue i18n
|
|
46
|
+
r'_\(["\']', # Python gettext
|
|
47
|
+
r'gettext\(', # Python gettext
|
|
48
|
+
r'useTranslations', # next-intl
|
|
49
|
+
r'FormattedMessage', # react-intl
|
|
50
|
+
r'i18n\.', # Generic i18n
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
def find_locale_files(project_path: Path) -> list:
|
|
54
|
+
"""Find translation/locale files."""
|
|
55
|
+
patterns = [
|
|
56
|
+
"**/locales/**/*.json",
|
|
57
|
+
"**/translations/**/*.json",
|
|
58
|
+
"**/lang/**/*.json",
|
|
59
|
+
"**/i18n/**/*.json",
|
|
60
|
+
"**/messages/*.json",
|
|
61
|
+
"**/*.po", # gettext
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
files = []
|
|
65
|
+
for pattern in patterns:
|
|
66
|
+
files.extend(project_path.glob(pattern))
|
|
67
|
+
|
|
68
|
+
return [f for f in files if 'node_modules' not in str(f)]
|
|
69
|
+
|
|
70
|
+
def check_locale_completeness(locale_files: list) -> dict:
|
|
71
|
+
"""Check if all locales have the same keys."""
|
|
72
|
+
issues = []
|
|
73
|
+
passed = []
|
|
74
|
+
|
|
75
|
+
if not locale_files:
|
|
76
|
+
return {'passed': [], 'issues': ["[!] No locale files found"]}
|
|
77
|
+
|
|
78
|
+
# Group by parent folder (language)
|
|
79
|
+
locales = {}
|
|
80
|
+
for f in locale_files:
|
|
81
|
+
if f.suffix == '.json':
|
|
82
|
+
try:
|
|
83
|
+
lang = f.parent.name
|
|
84
|
+
content = json.loads(f.read_text(encoding='utf-8'))
|
|
85
|
+
if lang not in locales:
|
|
86
|
+
locales[lang] = {}
|
|
87
|
+
locales[lang][f.stem] = set(flatten_keys(content))
|
|
88
|
+
except:
|
|
89
|
+
continue
|
|
90
|
+
|
|
91
|
+
if len(locales) < 2:
|
|
92
|
+
passed.append(f"[OK] Found {len(locale_files)} locale file(s)")
|
|
93
|
+
return {'passed': passed, 'issues': issues}
|
|
94
|
+
|
|
95
|
+
passed.append(f"[OK] Found {len(locales)} language(s): {', '.join(locales.keys())}")
|
|
96
|
+
|
|
97
|
+
# Compare keys across locales
|
|
98
|
+
all_langs = list(locales.keys())
|
|
99
|
+
base_lang = all_langs[0]
|
|
100
|
+
|
|
101
|
+
for namespace in locales.get(base_lang, {}):
|
|
102
|
+
base_keys = locales[base_lang].get(namespace, set())
|
|
103
|
+
|
|
104
|
+
for lang in all_langs[1:]:
|
|
105
|
+
other_keys = locales.get(lang, {}).get(namespace, set())
|
|
106
|
+
|
|
107
|
+
missing = base_keys - other_keys
|
|
108
|
+
if missing:
|
|
109
|
+
issues.append(f"[X] {lang}/{namespace}: Missing {len(missing)} keys")
|
|
110
|
+
|
|
111
|
+
extra = other_keys - base_keys
|
|
112
|
+
if extra:
|
|
113
|
+
issues.append(f"[!] {lang}/{namespace}: {len(extra)} extra keys")
|
|
114
|
+
|
|
115
|
+
if not issues:
|
|
116
|
+
passed.append("[OK] All locales have matching keys")
|
|
117
|
+
|
|
118
|
+
return {'passed': passed, 'issues': issues}
|
|
119
|
+
|
|
120
|
+
def flatten_keys(d, prefix=''):
|
|
121
|
+
"""Flatten nested dict keys."""
|
|
122
|
+
keys = set()
|
|
123
|
+
for k, v in d.items():
|
|
124
|
+
new_key = f"{prefix}.{k}" if prefix else k
|
|
125
|
+
if isinstance(v, dict):
|
|
126
|
+
keys.update(flatten_keys(v, new_key))
|
|
127
|
+
else:
|
|
128
|
+
keys.add(new_key)
|
|
129
|
+
return keys
|
|
130
|
+
|
|
131
|
+
def check_hardcoded_strings(project_path: Path) -> dict:
|
|
132
|
+
"""Check for hardcoded strings in code files."""
|
|
133
|
+
issues = []
|
|
134
|
+
passed = []
|
|
135
|
+
|
|
136
|
+
# Find code files
|
|
137
|
+
extensions = {
|
|
138
|
+
'.tsx': 'jsx', '.jsx': 'jsx', '.ts': 'jsx', '.js': 'jsx',
|
|
139
|
+
'.vue': 'vue',
|
|
140
|
+
'.py': 'python'
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
code_files = []
|
|
144
|
+
for ext in extensions:
|
|
145
|
+
code_files.extend(project_path.rglob(f"*{ext}"))
|
|
146
|
+
|
|
147
|
+
code_files = [f for f in code_files if not any(x in str(f) for x in
|
|
148
|
+
['node_modules', '.git', 'dist', 'build', '__pycache__', 'venv', 'test', 'spec'])]
|
|
149
|
+
|
|
150
|
+
if not code_files:
|
|
151
|
+
return {'passed': ["[!] No code files found"], 'issues': []}
|
|
152
|
+
|
|
153
|
+
files_with_i18n = 0
|
|
154
|
+
files_with_hardcoded = 0
|
|
155
|
+
hardcoded_examples = []
|
|
156
|
+
|
|
157
|
+
for file_path in code_files[:50]: # Limit
|
|
158
|
+
try:
|
|
159
|
+
content = file_path.read_text(encoding='utf-8', errors='ignore')
|
|
160
|
+
ext = file_path.suffix
|
|
161
|
+
file_type = extensions.get(ext, 'jsx')
|
|
162
|
+
|
|
163
|
+
# Check for i18n usage
|
|
164
|
+
has_i18n = any(re.search(p, content) for p in I18N_PATTERNS)
|
|
165
|
+
if has_i18n:
|
|
166
|
+
files_with_i18n += 1
|
|
167
|
+
|
|
168
|
+
# Check for hardcoded strings
|
|
169
|
+
patterns = HARDCODED_PATTERNS.get(file_type, [])
|
|
170
|
+
hardcoded_found = False
|
|
171
|
+
|
|
172
|
+
for pattern in patterns:
|
|
173
|
+
matches = re.findall(pattern, content)
|
|
174
|
+
if matches and not has_i18n:
|
|
175
|
+
hardcoded_found = True
|
|
176
|
+
if len(hardcoded_examples) < 5:
|
|
177
|
+
hardcoded_examples.append(f"{file_path.name}: {str(matches[0])[:40]}...")
|
|
178
|
+
|
|
179
|
+
if hardcoded_found:
|
|
180
|
+
files_with_hardcoded += 1
|
|
181
|
+
|
|
182
|
+
except:
|
|
183
|
+
continue
|
|
184
|
+
|
|
185
|
+
passed.append(f"[OK] Analyzed {len(code_files)} code files")
|
|
186
|
+
|
|
187
|
+
if files_with_i18n > 0:
|
|
188
|
+
passed.append(f"[OK] {files_with_i18n} files use i18n")
|
|
189
|
+
|
|
190
|
+
if files_with_hardcoded > 0:
|
|
191
|
+
issues.append(f"[X] {files_with_hardcoded} files may have hardcoded strings")
|
|
192
|
+
for ex in hardcoded_examples:
|
|
193
|
+
issues.append(f" → {ex}")
|
|
194
|
+
else:
|
|
195
|
+
passed.append("[OK] No obvious hardcoded strings detected")
|
|
196
|
+
|
|
197
|
+
return {'passed': passed, 'issues': issues}
|
|
198
|
+
|
|
199
|
+
def main():
|
|
200
|
+
target = sys.argv[1] if len(sys.argv) > 1 else "."
|
|
201
|
+
project_path = Path(target)
|
|
202
|
+
|
|
203
|
+
print("\n" + "=" * 60)
|
|
204
|
+
print(" i18n CHECKER - Internationalization Audit")
|
|
205
|
+
print("=" * 60 + "\n")
|
|
206
|
+
|
|
207
|
+
# Check locale files
|
|
208
|
+
locale_files = find_locale_files(project_path)
|
|
209
|
+
locale_result = check_locale_completeness(locale_files)
|
|
210
|
+
|
|
211
|
+
# Check hardcoded strings
|
|
212
|
+
code_result = check_hardcoded_strings(project_path)
|
|
213
|
+
|
|
214
|
+
# Print results
|
|
215
|
+
print("[LOCALE FILES]")
|
|
216
|
+
print("-" * 40)
|
|
217
|
+
for item in locale_result['passed']:
|
|
218
|
+
print(f" {item}")
|
|
219
|
+
for item in locale_result['issues']:
|
|
220
|
+
print(f" {item}")
|
|
221
|
+
|
|
222
|
+
print("\n[CODE ANALYSIS]")
|
|
223
|
+
print("-" * 40)
|
|
224
|
+
for item in code_result['passed']:
|
|
225
|
+
print(f" {item}")
|
|
226
|
+
for item in code_result['issues']:
|
|
227
|
+
print(f" {item}")
|
|
228
|
+
|
|
229
|
+
# Summary
|
|
230
|
+
critical_issues = sum(1 for i in locale_result['issues'] + code_result['issues'] if i.startswith("[X]"))
|
|
231
|
+
|
|
232
|
+
print("\n" + "=" * 60)
|
|
233
|
+
if critical_issues == 0:
|
|
234
|
+
print("[OK] i18n CHECK: PASSED")
|
|
235
|
+
sys.exit(0)
|
|
236
|
+
else:
|
|
237
|
+
print(f"[X] i18n CHECK: {critical_issues} issues found")
|
|
238
|
+
sys.exit(1)
|
|
239
|
+
|
|
240
|
+
if __name__ == "__main__":
|
|
241
|
+
main()
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Configuração e verificação de conta Instagram.
|
|
3
|
+
|
|
4
|
+
Uso:
|
|
5
|
+
python scripts/account_setup.py --check # Detecta tipo de conta
|
|
6
|
+
python scripts/account_setup.py --guide # Guia de setup/migração
|
|
7
|
+
python scripts/account_setup.py --verify # Verifica pré-requisitos
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import argparse
|
|
12
|
+
import asyncio
|
|
13
|
+
import json
|
|
14
|
+
import sys
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
sys.path.insert(0, str(Path(__file__).parent))
|
|
18
|
+
|
|
19
|
+
from api_client import InstagramAPI, InstagramAPIError
|
|
20
|
+
from db import Database
|
|
21
|
+
|
|
22
|
+
db = Database()
|
|
23
|
+
db.init()
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
async def check_account() -> None:
|
|
27
|
+
"""Detecta tipo de conta e status."""
|
|
28
|
+
account = db.get_active_account()
|
|
29
|
+
if not account:
|
|
30
|
+
print(json.dumps({
|
|
31
|
+
"status": "not_configured",
|
|
32
|
+
"message": "Nenhuma conta configurada.",
|
|
33
|
+
"next_step": "Execute: python scripts/auth.py --setup",
|
|
34
|
+
}, indent=2, ensure_ascii=False))
|
|
35
|
+
return
|
|
36
|
+
|
|
37
|
+
try:
|
|
38
|
+
api = InstagramAPI()
|
|
39
|
+
profile = await api.get_user_profile()
|
|
40
|
+
await api.close()
|
|
41
|
+
|
|
42
|
+
result = {
|
|
43
|
+
"status": "ok",
|
|
44
|
+
"username": profile.get("username"),
|
|
45
|
+
"account_type": profile.get("account_type"),
|
|
46
|
+
"name": profile.get("name"),
|
|
47
|
+
"followers": profile.get("followers_count"),
|
|
48
|
+
"following": profile.get("follows_count"),
|
|
49
|
+
"posts": profile.get("media_count"),
|
|
50
|
+
"biography": profile.get("biography"),
|
|
51
|
+
"website": profile.get("website"),
|
|
52
|
+
}
|
|
53
|
+
print(json.dumps(result, indent=2, ensure_ascii=False))
|
|
54
|
+
|
|
55
|
+
except InstagramAPIError as e:
|
|
56
|
+
print(json.dumps({
|
|
57
|
+
"status": "error",
|
|
58
|
+
"error": str(e),
|
|
59
|
+
"code": e.code,
|
|
60
|
+
"suggestion": "Token pode estar expirado. Execute: python scripts/auth.py --refresh",
|
|
61
|
+
}, indent=2, ensure_ascii=False))
|
|
62
|
+
except ValueError as e:
|
|
63
|
+
print(json.dumps({
|
|
64
|
+
"status": "not_configured",
|
|
65
|
+
"error": str(e),
|
|
66
|
+
}, indent=2, ensure_ascii=False))
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def show_guide() -> None:
|
|
70
|
+
"""Mostra guia de setup/migração."""
|
|
71
|
+
account = db.get_active_account()
|
|
72
|
+
|
|
73
|
+
checklist = []
|
|
74
|
+
checklist.append(("Facebook account", "OK" if True else "PENDENTE",
|
|
75
|
+
"Crie em: https://www.facebook.com"))
|
|
76
|
+
checklist.append(("Instagram account", "OK" if account else "PENDENTE",
|
|
77
|
+
"Crie em: https://www.instagram.com"))
|
|
78
|
+
|
|
79
|
+
account_type = account.get("account_type") if account else None
|
|
80
|
+
is_business = account_type in ("BUSINESS", "CREATOR") if account_type else False
|
|
81
|
+
checklist.append((
|
|
82
|
+
f"Conta Business/Creator (atual: {account_type or '?'})",
|
|
83
|
+
"OK" if is_business else "PENDENTE",
|
|
84
|
+
"Precisa ser Business ou Creator para usar a API",
|
|
85
|
+
))
|
|
86
|
+
|
|
87
|
+
has_page = bool(account.get("facebook_page_id")) if account else False
|
|
88
|
+
checklist.append(("Facebook Page vinculada", "OK" if has_page else "PENDENTE",
|
|
89
|
+
"Vincule uma Page à sua conta Instagram"))
|
|
90
|
+
|
|
91
|
+
has_token = bool(account.get("access_token")) if account else False
|
|
92
|
+
checklist.append(("Token OAuth", "OK" if has_token else "PENDENTE",
|
|
93
|
+
"Execute: python scripts/auth.py --setup"))
|
|
94
|
+
|
|
95
|
+
print()
|
|
96
|
+
print("=" * 65)
|
|
97
|
+
print("CHECKLIST DE CONFIGURAÇÃO - INSTAGRAM")
|
|
98
|
+
print("=" * 65)
|
|
99
|
+
|
|
100
|
+
for item, status, hint in checklist:
|
|
101
|
+
icon = "[OK]" if status == "OK" else "[!!]"
|
|
102
|
+
print(f" {icon} {item}")
|
|
103
|
+
if status != "OK":
|
|
104
|
+
print(f" -> {hint}")
|
|
105
|
+
|
|
106
|
+
print()
|
|
107
|
+
|
|
108
|
+
if not is_business:
|
|
109
|
+
print("-" * 65)
|
|
110
|
+
print("COMO MIGRAR PARA CONTA BUSINESS:")
|
|
111
|
+
print("-" * 65)
|
|
112
|
+
print("""
|
|
113
|
+
1. Abra o app Instagram → Configurações → Conta
|
|
114
|
+
2. Toque em "Mudar para conta profissional"
|
|
115
|
+
3. Selecione "Business" (para empresas) ou "Creator" (para criadores)
|
|
116
|
+
4. Conecte à sua Facebook Page (ou crie uma)
|
|
117
|
+
5. Após migrar, execute: python scripts/account_setup.py --check
|
|
118
|
+
""")
|
|
119
|
+
|
|
120
|
+
if not has_page:
|
|
121
|
+
print("-" * 65)
|
|
122
|
+
print("COMO CRIAR/VINCULAR FACEBOOK PAGE:")
|
|
123
|
+
print("-" * 65)
|
|
124
|
+
print("""
|
|
125
|
+
1. Acesse: https://www.facebook.com/pages/create
|
|
126
|
+
2. Crie uma Page para seu negócio/marca
|
|
127
|
+
3. No Instagram: Configurações → Conta → Contas vinculadas → Facebook
|
|
128
|
+
4. Vincule a Page recém-criada
|
|
129
|
+
5. Execute: python scripts/auth.py --setup
|
|
130
|
+
""")
|
|
131
|
+
|
|
132
|
+
if not has_token:
|
|
133
|
+
print("-" * 65)
|
|
134
|
+
print("COMO CONFIGURAR O META APP:")
|
|
135
|
+
print("-" * 65)
|
|
136
|
+
print("""
|
|
137
|
+
1. Acesse: https://developers.facebook.com/apps/
|
|
138
|
+
2. Clique "Criar App" → Selecione "Business"
|
|
139
|
+
3. Em "Adicionar Produtos", adicione "Instagram Graph API"
|
|
140
|
+
4. No painel, copie App ID e App Secret
|
|
141
|
+
5. Execute: python scripts/auth.py --setup
|
|
142
|
+
6. Cole o App ID e App Secret quando solicitado
|
|
143
|
+
""")
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
async def verify_setup() -> None:
|
|
147
|
+
"""Verifica se todos os pré-requisitos estão OK."""
|
|
148
|
+
checks = []
|
|
149
|
+
|
|
150
|
+
# 1. Conta no banco
|
|
151
|
+
account = db.get_active_account()
|
|
152
|
+
checks.append({
|
|
153
|
+
"check": "Conta configurada",
|
|
154
|
+
"passed": account is not None,
|
|
155
|
+
"detail": f"@{account['username']}" if account else "Nenhuma conta",
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
if not account:
|
|
159
|
+
print(json.dumps({"checks": checks, "all_passed": False}, indent=2))
|
|
160
|
+
return
|
|
161
|
+
|
|
162
|
+
# 2. Token válido
|
|
163
|
+
try:
|
|
164
|
+
api = InstagramAPI()
|
|
165
|
+
profile = await api.get_user_profile()
|
|
166
|
+
checks.append({
|
|
167
|
+
"check": "Token válido",
|
|
168
|
+
"passed": True,
|
|
169
|
+
"detail": f"Conta @{profile.get('username')} acessível",
|
|
170
|
+
})
|
|
171
|
+
except Exception as e:
|
|
172
|
+
checks.append({
|
|
173
|
+
"check": "Token válido",
|
|
174
|
+
"passed": False,
|
|
175
|
+
"detail": str(e),
|
|
176
|
+
})
|
|
177
|
+
print(json.dumps({"checks": checks, "all_passed": False}, indent=2))
|
|
178
|
+
return
|
|
179
|
+
|
|
180
|
+
# 3. Tipo de conta
|
|
181
|
+
acct_type = profile.get("account_type", "UNKNOWN")
|
|
182
|
+
checks.append({
|
|
183
|
+
"check": "Conta Business/Creator",
|
|
184
|
+
"passed": acct_type in ("BUSINESS", "CREATOR"),
|
|
185
|
+
"detail": f"Tipo: {acct_type}",
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
# 4. Facebook Page vinculada
|
|
189
|
+
checks.append({
|
|
190
|
+
"check": "Facebook Page vinculada",
|
|
191
|
+
"passed": bool(account.get("facebook_page_id")),
|
|
192
|
+
"detail": f"Page ID: {account.get('facebook_page_id', 'N/A')}",
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
# 5. Permissões básicas (tenta buscar mídia)
|
|
196
|
+
try:
|
|
197
|
+
media = await api.get_user_media(limit=1)
|
|
198
|
+
checks.append({
|
|
199
|
+
"check": "Permissão instagram_basic",
|
|
200
|
+
"passed": True,
|
|
201
|
+
"detail": "OK - pode ler mídia",
|
|
202
|
+
})
|
|
203
|
+
except Exception:
|
|
204
|
+
checks.append({
|
|
205
|
+
"check": "Permissão instagram_basic",
|
|
206
|
+
"passed": False,
|
|
207
|
+
"detail": "Sem permissão para ler mídia",
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
await api.close()
|
|
211
|
+
|
|
212
|
+
all_passed = all(c["passed"] for c in checks)
|
|
213
|
+
print(json.dumps({"checks": checks, "all_passed": all_passed}, indent=2, ensure_ascii=False))
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def main():
|
|
217
|
+
parser = argparse.ArgumentParser(description="Configuração de conta Instagram")
|
|
218
|
+
group = parser.add_mutually_exclusive_group(required=True)
|
|
219
|
+
group.add_argument("--check", action="store_true", help="Detecta tipo de conta")
|
|
220
|
+
group.add_argument("--guide", action="store_true", help="Guia de setup/migração")
|
|
221
|
+
group.add_argument("--verify", action="store_true", help="Verifica pré-requisitos")
|
|
222
|
+
args = parser.parse_args()
|
|
223
|
+
|
|
224
|
+
if args.check:
|
|
225
|
+
asyncio.run(check_account())
|
|
226
|
+
elif args.guide:
|
|
227
|
+
show_guide()
|
|
228
|
+
elif args.verify:
|
|
229
|
+
asyncio.run(verify_setup())
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
if __name__ == "__main__":
|
|
233
|
+
main()
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Análise inteligente de dados do Instagram (SQL puro, sem dependências externas).
|
|
3
|
+
|
|
4
|
+
Uso:
|
|
5
|
+
python scripts/analyze.py --best-times # Melhores horários para postar
|
|
6
|
+
python scripts/analyze.py --top-posts --limit 10 # Top posts por engajamento
|
|
7
|
+
python scripts/analyze.py --growth --period 30 # Tendência de crescimento
|
|
8
|
+
python scripts/analyze.py --summary # Resumo geral
|
|
9
|
+
"""
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import argparse
|
|
13
|
+
import json
|
|
14
|
+
import sqlite3
|
|
15
|
+
import sys
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
sys.path.insert(0, str(Path(__file__).parent))
|
|
19
|
+
|
|
20
|
+
from config import DB_PATH
|
|
21
|
+
from db import Database
|
|
22
|
+
|
|
23
|
+
db = Database()
|
|
24
|
+
db.init()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _connect() -> sqlite3.Connection:
|
|
28
|
+
conn = sqlite3.connect(DB_PATH)
|
|
29
|
+
conn.row_factory = sqlite3.Row
|
|
30
|
+
return conn
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def best_times() -> None:
|
|
34
|
+
"""Analisa melhores horários para postar baseado em engajamento."""
|
|
35
|
+
conn = _connect()
|
|
36
|
+
|
|
37
|
+
# Agregar engajamento por hora do dia e dia da semana
|
|
38
|
+
sql = """
|
|
39
|
+
SELECT
|
|
40
|
+
strftime('%H', p.published_at) as hour,
|
|
41
|
+
strftime('%w', p.published_at) as weekday,
|
|
42
|
+
COUNT(DISTINCT p.id) as post_count,
|
|
43
|
+
AVG(i.metric_value) as avg_engagement,
|
|
44
|
+
MAX(i.metric_value) as max_engagement
|
|
45
|
+
FROM posts p
|
|
46
|
+
JOIN insights i ON i.ig_media_id = p.ig_media_id
|
|
47
|
+
WHERE p.status = 'published'
|
|
48
|
+
AND p.published_at IS NOT NULL
|
|
49
|
+
AND i.metric_name IN ('engagement', 'reach', 'impressions')
|
|
50
|
+
GROUP BY hour, weekday
|
|
51
|
+
HAVING post_count >= 1
|
|
52
|
+
ORDER BY avg_engagement DESC
|
|
53
|
+
"""
|
|
54
|
+
rows = conn.execute(sql).fetchall()
|
|
55
|
+
conn.close()
|
|
56
|
+
|
|
57
|
+
if not rows:
|
|
58
|
+
# Tentar com dados de user_insights se não houver dados granulares
|
|
59
|
+
print(json.dumps({
|
|
60
|
+
"message": "Dados insuficientes para análise. Publique mais posts e busque insights primeiro.",
|
|
61
|
+
"tip": "Execute: python scripts/insights.py --fetch-all --limit 50",
|
|
62
|
+
}, indent=2, ensure_ascii=False))
|
|
63
|
+
return
|
|
64
|
+
|
|
65
|
+
weekday_names = ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado"]
|
|
66
|
+
results = []
|
|
67
|
+
for r in rows:
|
|
68
|
+
results.append({
|
|
69
|
+
"hour": f"{r['hour']}:00",
|
|
70
|
+
"weekday": weekday_names[int(r["weekday"])] if r["weekday"] else "?",
|
|
71
|
+
"posts_analyzed": r["post_count"],
|
|
72
|
+
"avg_engagement": round(r["avg_engagement"], 1),
|
|
73
|
+
"max_engagement": round(r["max_engagement"], 1),
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
# Top 5 melhores combinações hora/dia
|
|
77
|
+
print(json.dumps({
|
|
78
|
+
"analysis": "best_times",
|
|
79
|
+
"top_5": results[:5],
|
|
80
|
+
"all_data": results,
|
|
81
|
+
}, indent=2, ensure_ascii=False))
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def top_posts(limit: int = 10) -> None:
|
|
85
|
+
"""Lista top posts por engajamento."""
|
|
86
|
+
conn = _connect()
|
|
87
|
+
sql = """
|
|
88
|
+
SELECT
|
|
89
|
+
p.id, p.ig_media_id, p.media_type, p.permalink, p.published_at,
|
|
90
|
+
SUBSTR(p.caption, 1, 80) as caption_preview,
|
|
91
|
+
SUM(CASE WHEN i.metric_name = 'engagement' THEN i.metric_value ELSE 0 END) as engagement,
|
|
92
|
+
SUM(CASE WHEN i.metric_name = 'impressions' THEN i.metric_value ELSE 0 END) as impressions,
|
|
93
|
+
SUM(CASE WHEN i.metric_name = 'reach' THEN i.metric_value ELSE 0 END) as reach,
|
|
94
|
+
SUM(CASE WHEN i.metric_name = 'saved' THEN i.metric_value ELSE 0 END) as saves
|
|
95
|
+
FROM posts p
|
|
96
|
+
LEFT JOIN insights i ON i.ig_media_id = p.ig_media_id
|
|
97
|
+
WHERE p.status = 'published'
|
|
98
|
+
GROUP BY p.id
|
|
99
|
+
ORDER BY engagement DESC
|
|
100
|
+
LIMIT ?
|
|
101
|
+
"""
|
|
102
|
+
rows = conn.execute(sql, [limit]).fetchall()
|
|
103
|
+
conn.close()
|
|
104
|
+
|
|
105
|
+
results = [dict(r) for r in rows]
|
|
106
|
+
print(json.dumps({"analysis": "top_posts", "total": len(results), "posts": results}, indent=2, ensure_ascii=False))
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def growth_trend(period_days: int = 30) -> None:
|
|
110
|
+
"""Analisa tendência de crescimento."""
|
|
111
|
+
conn = _connect()
|
|
112
|
+
sql = """
|
|
113
|
+
SELECT
|
|
114
|
+
DATE(end_time) as date,
|
|
115
|
+
metric_name,
|
|
116
|
+
metric_value
|
|
117
|
+
FROM user_insights
|
|
118
|
+
WHERE end_time >= date('now', ?)
|
|
119
|
+
AND metric_name IN ('follower_count', 'reach', 'impressions', 'profile_views')
|
|
120
|
+
ORDER BY end_time ASC
|
|
121
|
+
"""
|
|
122
|
+
rows = conn.execute(sql, [f"-{period_days} days"]).fetchall()
|
|
123
|
+
conn.close()
|
|
124
|
+
|
|
125
|
+
if not rows:
|
|
126
|
+
print(json.dumps({
|
|
127
|
+
"message": "Sem dados de crescimento. Busque insights da conta primeiro.",
|
|
128
|
+
"tip": "Execute: python scripts/insights.py --user --period day --since 30",
|
|
129
|
+
}, indent=2, ensure_ascii=False))
|
|
130
|
+
return
|
|
131
|
+
|
|
132
|
+
# Agrupar por métrica
|
|
133
|
+
metrics = {}
|
|
134
|
+
for r in rows:
|
|
135
|
+
name = r["metric_name"]
|
|
136
|
+
if name not in metrics:
|
|
137
|
+
metrics[name] = []
|
|
138
|
+
metrics[name].append({"date": r["date"], "value": r["metric_value"]})
|
|
139
|
+
|
|
140
|
+
# Calcular variação
|
|
141
|
+
summary = {}
|
|
142
|
+
for name, data in metrics.items():
|
|
143
|
+
if len(data) >= 2:
|
|
144
|
+
first = data[0]["value"]
|
|
145
|
+
last = data[-1]["value"]
|
|
146
|
+
change = last - first
|
|
147
|
+
pct = (change / first * 100) if first > 0 else 0
|
|
148
|
+
summary[name] = {
|
|
149
|
+
"first_value": first,
|
|
150
|
+
"last_value": last,
|
|
151
|
+
"change": change,
|
|
152
|
+
"change_pct": round(pct, 1),
|
|
153
|
+
"data_points": len(data),
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
print(json.dumps({
|
|
157
|
+
"analysis": "growth",
|
|
158
|
+
"period_days": period_days,
|
|
159
|
+
"summary": summary,
|
|
160
|
+
"details": metrics,
|
|
161
|
+
}, indent=2, ensure_ascii=False))
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def overall_summary() -> None:
|
|
165
|
+
"""Resumo geral da conta."""
|
|
166
|
+
stats = db.get_stats()
|
|
167
|
+
conn = _connect()
|
|
168
|
+
|
|
169
|
+
# Engajamento médio
|
|
170
|
+
avg_engagement = conn.execute("""
|
|
171
|
+
SELECT AVG(metric_value) as avg_val
|
|
172
|
+
FROM insights WHERE metric_name = 'engagement'
|
|
173
|
+
""").fetchone()
|
|
174
|
+
|
|
175
|
+
# Posts esta semana
|
|
176
|
+
posts_this_week = conn.execute("""
|
|
177
|
+
SELECT COUNT(*) FROM posts
|
|
178
|
+
WHERE status = 'published' AND published_at >= date('now', '-7 days')
|
|
179
|
+
""").fetchone()[0]
|
|
180
|
+
|
|
181
|
+
# Último post
|
|
182
|
+
last_post = conn.execute("""
|
|
183
|
+
SELECT published_at, SUBSTR(caption, 1, 60) as caption
|
|
184
|
+
FROM posts WHERE status = 'published'
|
|
185
|
+
ORDER BY published_at DESC LIMIT 1
|
|
186
|
+
""").fetchone()
|
|
187
|
+
|
|
188
|
+
conn.close()
|
|
189
|
+
|
|
190
|
+
result = {
|
|
191
|
+
"database_stats": stats,
|
|
192
|
+
"avg_engagement": round(avg_engagement["avg_val"], 1) if avg_engagement and avg_engagement["avg_val"] else 0,
|
|
193
|
+
"posts_this_week": posts_this_week,
|
|
194
|
+
"last_post": dict(last_post) if last_post else None,
|
|
195
|
+
}
|
|
196
|
+
print(json.dumps(result, indent=2, ensure_ascii=False))
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def main():
|
|
200
|
+
parser = argparse.ArgumentParser(description="Análise de dados Instagram")
|
|
201
|
+
group = parser.add_mutually_exclusive_group(required=True)
|
|
202
|
+
group.add_argument("--best-times", action="store_true", help="Melhores horários para postar")
|
|
203
|
+
group.add_argument("--top-posts", action="store_true", help="Top posts por engajamento")
|
|
204
|
+
group.add_argument("--growth", action="store_true", help="Tendência de crescimento")
|
|
205
|
+
group.add_argument("--summary", action="store_true", help="Resumo geral")
|
|
206
|
+
parser.add_argument("--limit", type=int, default=10, help="Limite (para --top-posts)")
|
|
207
|
+
parser.add_argument("--period", type=int, default=30, help="Dias (para --growth)")
|
|
208
|
+
args = parser.parse_args()
|
|
209
|
+
|
|
210
|
+
if args.best_times:
|
|
211
|
+
best_times()
|
|
212
|
+
elif args.top_posts:
|
|
213
|
+
top_posts(args.limit)
|
|
214
|
+
elif args.growth:
|
|
215
|
+
growth_trend(args.period)
|
|
216
|
+
elif args.summary:
|
|
217
|
+
overall_summary()
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
if __name__ == "__main__":
|
|
221
|
+
main()
|