Add templates from botserver

This commit is contained in:
Rodrigo Rodriguez (Pragmatismo) 2025-12-15 16:33:32 -03:00
parent 280826f53a
commit 186cacddd6
207 changed files with 654287 additions and 287 deletions

494
README.md
View file

@ -1,353 +1,273 @@
# General Bots Templates
Pre-built templates for bots, apps, prompts, and UI components. Everything you need to get started quickly.
Pre-built bot packages for common business use cases. Templates are organized by category for easy discovery.
---
## Repository Structure
## Complete Template List (Flat Reference)
```
bottemplates/
├── bots/ # Complete bot packages (.gbai)
│ ├── core/ # Essential starter bots
│ ├── sales/ # CRM, marketing, lead management
│ ├── compliance/ # LGPD, GDPR, HIPAA
│ ├── finance/ # Banking, payments, invoicing
│ ├── healthcare/ # Patient communication, appointments
│ ├── hr/ # Employee management, onboarding
│ ├── it/ # Helpdesk, IT service management
│ ├── nonprofit/ # Donor management, volunteers
│ ├── education/ # Courses, training, LMS
│ └── integration/ # External API integrations
├── apps/ # HTMX web application templates
│ ├── dashboard/ # Analytics and KPI dashboards
│ ├── crud/ # Generic CRUD interfaces
│ ├── kanban/ # Board-style project management
│ ├── admin/ # Admin panel templates
│ └── components/ # Reusable UI components
├── prompts/ # System prompts and LLM configurations
│ ├── assistants/ # Role-specific assistant prompts
│ ├── tools/ # Tool description templates
│ └── personas/ # Bot personality definitions
├── dialogs/ # Reusable BASIC dialog scripts
│ ├── auth/ # Authentication flows
│ ├── notifications/ # Email, SMS, WhatsApp patterns
│ ├── data/ # CRUD operation patterns
│ └── integrations/ # API integration patterns
└── themes/ # UI themes (.gbtheme)
├── default/ # Standard theme
├── dark/ # Dark mode theme
└── corporate/ # Business-focused themes
```
| # | Template | Category | Folder | Key Features |
|---|----------|----------|--------|--------------|
| 1 | Default | Core | `default.gbai` | Minimal starter bot |
| 2 | Template | Core | `template.gbai` | Reference implementation |
| 3 | AI Search | Search | `ai-search.gbai` | QR codes, document search |
| 4 | Announcements | Communications | `announcements.gbai` | Company news, multiple KB |
| 5 | Analytics Dashboard | Platform | `analytics-dashboard.gbai` | Metrics, Reports |
| 6 | Backup | Platform | `backup.gbai` | Server backup scripts |
| 7 | Bank | Finance | `bank.gbai` | Banking services |
| 8 | BI | Platform | `bi.gbai` | Dashboards, role separation |
| 9 | Bling | Integration | `bling.gbai` | Bling ERP integration |
| 10 | Broadcast | Communications | `broadcast.gbai` | Mass messaging |
| 11 | Crawler | Search | `crawler.gbai` | Web indexing |
| 12 | CRM | Sales | `sales/crm.gbai` | Customer management |
| 13 | Attendance CRM | Sales | `sales/attendance-crm.gbai` | Event attendance tracking |
| 14 | Marketing | Sales | `sales/marketing.gbai` | Campaign tools |
| 15 | Education | Education | `edu.gbai` | Course management |
| 16 | ERP | Operations | `erp.gbai` | Process automation |
| 17 | HIPAA Medical | Compliance | `compliance/hipaa-medical.gbai` | HIPAA, HITECH |
| 18 | Privacy | Compliance | `compliance/privacy.gbai` | LGPD, GDPR, CCPA |
| 19 | Law | Legal | `law.gbai` | Document templates |
| 20 | LLM Server | AI | `llm-server.gbai` | Model hosting |
| 21 | LLM Tools | AI | `llm-tools.gbai` | TOOL-based LLM examples |
| 22 | Store | E-commerce | `store.gbai` | Product catalog |
| 23 | Talk to Data | Platform | `talk-to-data.gbai` | Natural language SQL |
| 24 | WhatsApp | Messaging | `whatsapp.gbai` | WhatsApp Business |
---
## Quick Start
## Categories
### Install a Bot Template
### `/sales`
Customer relationship and marketing templates.
```bash
# From CLI
botserver --install-template crm
| Template | Description | Features |
|----------|-------------|----------|
| `crm.gbai` | Full CRM system | Leads, Contacts, Accounts, Opportunities |
| `marketing.gbai` | Marketing automation | Campaigns, Lead capture, Email sequences |
| `attendance-crm.gbai` | Event attendance | Check-ins, Tracking |
# Or copy manually
cp -r bottemplates/bots/sales/crm.gbai /path/to/your/packages/
```
### `/compliance`
Privacy and regulatory compliance templates.
### Use an App Template
| Template | Description | Regulations |
|----------|-------------|-------------|
| `privacy.gbai` | Data subject rights portal | LGPD, GDPR, CCPA |
| `hipaa-medical.gbai` | Healthcare privacy management | HIPAA, HITECH |
```basic
' Generate a CRM app from template
CREATE SITE "my-crm", "bottemplates/apps/crud", "Build a customer management system"
```
### `/platform`
Platform administration and analytics templates.
### Apply a Prompt Template
| Template | Description | Features |
|----------|-------------|----------|
| `analytics-dashboard.gbai` | Platform analytics bot | Metrics, Reports, AI insights |
| `bi.gbai` | Business intelligence | Dashboards, role separation |
| `backup.gbai` | Backup automation | Server backup scripts |
| `talk-to-data.gbai` | Data queries | Natural language SQL |
```basic
' Load a sales assistant prompt
SET SYSTEM PROMPT FROM FILE "bottemplates/prompts/assistants/sales.md"
```
### `/finance`
Financial services templates.
---
| Template | Description | Features |
|----------|-------------|----------|
| `bank.gbai` | Banking services | Account management |
## Bots
### `/integration`
External API and service integrations.
Complete `.gbai` packages ready to deploy.
| Template | Description | APIs |
|----------|-------------|------|
| `bling.gbai` | Bling ERP | Brazilian ERP integration |
### Core
### `/productivity`
Office and personal productivity templates.
| Template | Description | Features |
|----------|-------------|----------|
| `office.gbai` | Office automation | Document management, Scheduling |
| `reminder.gbai` | Reminder system | Scheduled alerts, Follow-ups |
### `/hr`
Human resources templates.
| Template | Description | Features |
|----------|-------------|----------|
| `employees.gbai` | Employee management | Directory, Onboarding |
### `/it`
IT service management templates.
| Template | Description | Features |
|----------|-------------|----------|
| `helpdesk.gbai` | IT helpdesk ticketing | Tickets, Knowledge base |
### `/healthcare`
Healthcare-specific templates.
| Template | Description | Features |
|----------|-------------|----------|
| `patient-comm.gbai` | Patient communication | Appointments, Reminders |
### `/nonprofit`
Nonprofit organization templates.
| Template | Description | Features |
|----------|-------------|----------|
| `donor-mgmt.gbai` | Donor management | Donations, Communications |
### Root Level
Core and utility templates.
| Template | Description |
|----------|-------------|
| `default.gbai` | Minimal starter bot |
| `template.gbai` | Reference implementation for creating new bots |
### Sales & Marketing
| Template | Description |
|----------|-------------|
| `crm.gbai` | Full CRM with leads, contacts, opportunities |
| `marketing.gbai` | Campaign management, email sequences |
| `attendance-crm.gbai` | Event attendance tracking |
### Compliance
| Template | Description |
|----------|-------------|
| `privacy.gbai` | LGPD, GDPR, CCPA data subject rights |
| `hipaa-medical.gbai` | HIPAA/HITECH healthcare compliance |
### Finance
| Template | Description |
|----------|-------------|
| `bank.gbai` | Banking services bot |
| `invoicing.gbai` | Invoice generation and tracking |
### Platform
| Template | Description |
|----------|-------------|
| `analytics-dashboard.gbai` | Platform metrics and reports |
| `bi.gbai` | Business intelligence dashboards |
| `talk-to-data.gbai` | Natural language SQL queries |
| `backup.gbai` | Server backup automation |
### AI & LLM
| Template | Description |
|----------|-------------|
| `llm-server.gbai` | LLM model hosting |
| `llm-tools.gbai` | TOOL-based LLM examples |
| `default.gbai` | Starter template |
| `template.gbai` | Template for creating templates |
| `ai-search.gbai` | AI-powered document search |
| `announcements.gbai` | Company announcements |
| `backup.gbai` | Backup automation |
| `broadcast.gbai` | Message broadcasting |
| `crawler.gbai` | Web crawling |
| `edu.gbai` | Education/training |
| `erp.gbai` | ERP integration |
| `law.gbai` | Legal document processing |
| `llm-server.gbai` | LLM server management |
| `llm-tools.gbai` | LLM tool definitions |
| `store.gbai` | E-commerce |
| `whatsapp.gbai` | WhatsApp-specific features |
---
## Apps
## Template Structure
HTMX web application templates for use with `CREATE SITE`.
Each `.gbai` template follows this structure:
### Dashboard Templates
```basic
CREATE SITE "metrics", "bottemplates/apps/dashboard", "
Executive dashboard with:
- Revenue KPI cards
- Monthly trend charts
- Top performers table
"
```
### CRUD Templates
```basic
CREATE SITE "contacts", "bottemplates/apps/crud", "
Contact management with:
- Searchable list view
- Add/edit forms
- Import/export buttons
"
```
### Kanban Templates
```basic
CREATE SITE "projects", "bottemplates/apps/kanban", "
Project board with:
- Drag and drop cards
- Status columns
- Assignee filtering
"
```
### Components
Reusable HTML components:
| Component | File | Description |
|-----------|------|-------------|
| Data Table | `data-table.html` | Sortable, filterable tables |
| Form Modal | `form-modal.html` | Modal dialog with form |
| KPI Card | `kpi-card.html` | Metric display card |
| Chart | `chart.html` | Chart.js container |
| Search | `search-filter.html` | Search with filters |
---
## Prompts
System prompts and LLM configuration templates.
### Assistant Prompts
| Prompt | Description |
|--------|-------------|
| `sales.md` | Sales assistant persona |
| `support.md` | Customer support agent |
| `analyst.md` | Data analyst assistant |
| `developer.md` | Technical assistant |
### Tool Templates
Templates for creating LLM-invokable tools:
```basic
' From bottemplates/dialogs/tools/template.bas
PARAM input AS STRING DESCRIPTION "Description of input"
DESCRIPTION "What this tool does. When to use it."
' Your tool logic here
result = PROCESS input
RETURN result
template-name.gbai/
├── README.md # Template documentation
├── template-name.gbdialog/ # BASIC dialog scripts
│ ├── start.bas # Entry point
│ └── *.bas # Additional dialogs (auto-discovered as TOOLs)
├── template-name.gbot/ # Bot configuration
│ └── config.csv # Settings
├── template-name.gbkb/ # Knowledge base (optional)
│ └── docs/ # Documents for RAG
├── template-name.gbdrive/ # File storage (optional)
└── template-name.gbui/ # Custom UI (optional)
└── index.html
```
---
## Dialogs
## Event-Driven Patterns
Reusable BASIC script patterns.
### Authentication
Templates should use **ON** triggers instead of polling loops:
```basic
' bottemplates/dialogs/auth/oauth-flow.bas
INCLUDE "bottemplates/dialogs/auth/oauth-flow.bas"
```
### Notifications
```basic
' Send multi-channel notification
INCLUDE "bottemplates/dialogs/notifications/multi-channel.bas"
NOTIFY user, "Your order shipped!", channels: ["email", "whatsapp"]
```
### Data Operations
```basic
' CRUD with validation
INCLUDE "bottemplates/dialogs/data/validated-crud.bas"
CREATE_VALIDATED "contacts", contact_data, validation_rules
```
---
## Themes
UI customization packages.
### Using a Theme
```
my-bot.gbai/
└── my-bot.gbtheme/ # Copy theme files here
├── colors.css
├── fonts.css
└── components.css
```
### Available Themes
| Theme | Description |
|-------|-------------|
| `default` | Clean, modern appearance |
| `dark` | Dark mode with accent colors |
| `corporate` | Professional business styling |
| `minimal` | Stripped-down, fast-loading |
---
## Bot Package Structure
Every `.gbai` bot follows this structure:
```
my-bot.gbai/
├── README.md # Documentation
├── my-bot.gbdialog/ # BASIC scripts
│ ├── start.bas # Entry point
│ └── tools/ # LLM-invokable tools
├── my-bot.gbot/ # Configuration
│ └── config.csv # Bot settings
├── my-bot.gbkb/ # Knowledge base (optional)
│ └── docs/ # Documents for RAG
├── my-bot.gbdrive/ # File storage (optional)
└── my-bot.gbtheme/ # UI customization (optional)
```
---
## Best Practices
### Event-Driven Design
Use `ON` triggers instead of polling:
```basic
' ✅ Good - Event-driven
ON INSERT OF "leads"
lead = GET LAST "leads"
NOTIFY sales_team, "New lead: " + lead.name
END ON
' ❌ Bad - Polling loop
' ❌ OLD WAY - Polling (avoid)
mainLoop:
leads = FIND "leads", "new = true"
leads = FIND "leads", "processed = false"
WAIT 5
GOTO mainLoop
' ✅ NEW WAY - Event-Driven
ON INSERT OF "leads"
lead = GET LAST "leads"
score = SCORE LEAD lead
TALK TO "whatsapp:" + sales_phone, "New lead: " + lead.name
END ON
```
### LLM-Invokable Tools
---
Add `PARAM` and `DESCRIPTION` to make scripts callable by LLM:
## TOOL-Based LLM Integration
Every `.bas` file with `PARAM` and `DESCRIPTION` becomes an LLM-invokable tool:
```basic
' score-lead.bas
PARAM email AS STRING LIKE "john@example.com" DESCRIPTION "Lead email"
PARAM company AS STRING DESCRIPTION "Company name"
PARAM email AS STRING LIKE "john@company.com" DESCRIPTION "Lead email"
PARAM name AS STRING LIKE "John Smith" DESCRIPTION "Lead name"
DESCRIPTION "Score and qualify a sales lead"
DESCRIPTION "Score a new lead. Use when user mentions a prospect."
score = AI SCORE LEAD email, company
RETURN score
```
lead = NEW OBJECT
lead.email = email
lead.name = name
### HTMX Patterns
score = AI SCORE LEAD lead
Generated apps should use HTMX for server communication:
IF score.status = "hot" THEN
TALK TO "whatsapp:+5511999887766", "🔥 Hot lead: " + name
END IF
```html
<div hx-get="/api/data/leads"
hx-trigger="load, every 30s"
hx-swap="innerHTML">
Loading...
</div>
TALK "Lead scored: " + score.score + "/100"
```
---
## Contributing
## Installation
1. Fork this repository
2. Create your template following the structure
3. Test thoroughly
4. Add documentation
5. Submit a pull request
### From Console
### Template Checklist
```bash
botserver --install-template crm
```
- [ ] Follows naming conventions
- [ ] Includes README.md
- [ ] Uses event-driven patterns
- [ ] Has proper error handling
- [ ] Documented configuration options
- [ ] Example usage provided
### From BASIC
```basic
INSTALL TEMPLATE "crm"
```
### Manual
Copy the template folder to your bot's packages directory:
```bash
cp -r templates/sales/crm.gbai /path/to/your/bot/packages/
```
---
## Creating Custom Templates
1. Copy `template.gbai` as a starting point
2. Rename the folder to `your-template.gbai`
3. Update internal folder names to match
4. Edit `config.csv` with your bot settings
5. Create dialog scripts in the `.gbdialog` folder
6. Use **ON** triggers instead of polling loops
7. Add `PARAM` and `DESCRIPTION` to make scripts LLM-invokable
8. Add documentation in `README.md`
### Template Best Practices
- Use `ON` for event-driven automation
- Use `TALK TO` for multi-channel notifications
- Use `LLM` for intelligent decision-making
- Use `SCORE LEAD` / `AI SCORE LEAD` for lead qualification
- Create `.bas` files with `DESCRIPTION` for LLM tool discovery
- Log activities for audit trails
- Include error handling
- Document all configuration options
---
## Contributing Templates
1. Create your template following the structure above
2. Test thoroughly with different inputs
3. Document all features and configuration
4. Submit a pull request with:
- Template files
- Updated category README
- Entry in this document
---
## License
AGPL-3.0 - Part of General Bots Open Source Platform
All templates are licensed under AGPL-3.0 as part of General Bots.
---
**Pragmatismo** - [pragmatismo.com.br](https://pragmatismo.com.br)
**Pragmatismo** - General Bots Open Source Platform

View file

@ -0,0 +1,13 @@
PARAM doc AS QRCODE LIKE "photo of QR code" DESCRIPTION "QR Code image to scan and load document"
DESCRIPTION "Scan a QR Code to load and query a document"
text = GET doc
IF text THEN
SET CONTEXT "Based on this document, answer the person's questions:\n\n" + text
TALK "Document ${doc} loaded. You can ask me anything about it."
SEND FILE doc
ELSE
TALK "Document not found, please try again."
END IF

View file

@ -0,0 +1,27 @@
ADD TOOL "qr"
CLEAR SUGGESTIONS
ADD SUGGESTION "scan" AS "Scan a QR Code"
ADD SUGGESTION "find" AS "Find a procedure"
ADD SUGGESTION "help" AS "How to search documents"
BEGIN TALK
General Bots AI Search
Comprehensive Document Search with AI summaries and EDM integration.
**Options:**
Scan a QR Code - Send a photo to scan
Find a Procedure - Ask about any process
**Examples:**
- How to send a fax?
- How to clean the machine?
- How to find a contact?
END TALK
BEGIN SYSTEM PROMPT
You are a document search assistant. Help users find procedures and information from documents.
When users want to scan QR codes, use the qr tool.
Provide clear, concise answers based on document content.
END SYSTEM PROMPT

Binary file not shown.

View file

@ -0,0 +1 @@
O céu é azul-lilás e pronto.

Binary file not shown.

View file

@ -0,0 +1,5 @@
name,value
theme-color1, #0d2111
theme-color2, #fff111
theme-logo, https://pragmatismo.com.br/icons/general-bots.svg
theme-title, AI Search General Bots
1 name value
2 theme-color1 #0d2111
3 theme-color2 #fff111
4 theme-logo https://pragmatismo.com.br/icons/general-bots.svg
5 theme-title AI Search General Bots

View file

@ -0,0 +1,81 @@
REM Analytics Dashboard Start Dialog
REM Displays pre-computed statistics from update-stats.bas
REM No heavy computation at conversation start
DESCRIPTION "View knowledge base analytics and statistics"
REM Load pre-computed values from BOT MEMORY
totalDocs = GET BOT MEMORY("analytics_total_docs")
totalVectors = GET BOT MEMORY("analytics_total_vectors")
storageMB = GET BOT MEMORY("analytics_storage_mb")
collections = GET BOT MEMORY("analytics_collections")
docsWeek = GET BOT MEMORY("analytics_docs_week")
docsMonth = GET BOT MEMORY("analytics_docs_month")
growthRate = GET BOT MEMORY("analytics_growth_rate")
healthPercent = GET BOT MEMORY("analytics_health_percent")
lastUpdate = GET BOT MEMORY("analytics_last_update")
summary = GET BOT MEMORY("analytics_summary")
REM Set contexts for different report types
SET CONTEXT "overview" AS "Total documents: " + totalDocs + ", Storage: " + storageMB + " MB, Collections: " + collections
SET CONTEXT "activity" AS "Documents added this week: " + docsWeek + ", This month: " + docsMonth + ", Growth rate: " + growthRate + "%"
SET CONTEXT "health" AS "System health: " + healthPercent + "%, Last updated: " + lastUpdate
REM Clear and set up suggestions
CLEAR SUGGESTIONS
ADD SUGGESTION "overview" AS "Show overview"
ADD SUGGESTION "overview" AS "Storage usage"
ADD SUGGESTION "activity" AS "Recent activity"
ADD SUGGESTION "activity" AS "Growth trends"
ADD SUGGESTION "health" AS "System health"
ADD SUGGESTION "health" AS "Collection status"
REM Add tools for detailed reports
ADD TOOL "detailed-report"
ADD TOOL "export-stats"
REM Welcome message with pre-computed summary
IF summary <> "" THEN
TALK summary
TALK ""
END IF
TALK "📊 **Analytics Dashboard**"
TALK ""
IF totalDocs <> "" THEN
TALK "**Knowledge Base Overview**"
TALK "• Documents: " + FORMAT(totalDocs, "#,##0")
TALK "• Vectors: " + FORMAT(totalVectors, "#,##0")
TALK "• Storage: " + FORMAT(storageMB, "#,##0.00") + " MB"
TALK "• Collections: " + collections
TALK ""
TALK "**Recent Activity**"
TALK "• This week: +" + FORMAT(docsWeek, "#,##0") + " documents"
TALK "• This month: +" + FORMAT(docsMonth, "#,##0") + " documents"
IF growthRate <> "" THEN
IF growthRate > 0 THEN
TALK "• Trend: 📈 +" + FORMAT(growthRate, "#,##0.0") + "% vs average"
ELSE
TALK "• Trend: 📉 " + FORMAT(growthRate, "#,##0.0") + "% vs average"
END IF
END IF
TALK ""
IF healthPercent <> "" THEN
IF healthPercent = 100 THEN
TALK "✅ All systems healthy"
ELSE
TALK "⚠️ System health: " + FORMAT(healthPercent, "#,##0") + "%"
END IF
END IF
ELSE
TALK "Statistics are being computed. Please check back in a few minutes."
TALK "Run the update-stats schedule to refresh data."
END IF
TALK ""
TALK "Ask me about any metric or select a topic above."

View file

@ -0,0 +1,52 @@
REM Analytics Statistics Update
REM Runs hourly to pre-compute dashboard statistics
REM Similar pattern to announcements/update-summary.bas
SET SCHEDULE "0 * * * *"
REM Fetch KB statistics
stats = KB STATISTICS
statsObj = JSON PARSE stats
REM Store document counts
SET BOT MEMORY "analytics_total_docs", statsObj.total_documents
SET BOT MEMORY "analytics_total_vectors", statsObj.total_vectors
SET BOT MEMORY "analytics_storage_mb", statsObj.total_disk_size_mb
SET BOT MEMORY "analytics_collections", statsObj.total_collections
REM Store activity metrics
SET BOT MEMORY "analytics_docs_week", statsObj.documents_added_last_week
SET BOT MEMORY "analytics_docs_month", statsObj.documents_added_last_month
REM Calculate growth rate
IF statsObj.documents_added_last_month > 0 THEN
weeklyAvg = statsObj.documents_added_last_month / 4
IF weeklyAvg > 0 THEN
growthRate = ((statsObj.documents_added_last_week - weeklyAvg) / weeklyAvg) * 100
SET BOT MEMORY "analytics_growth_rate", growthRate
END IF
END IF
REM Check collection health
healthyCount = 0
totalCount = 0
FOR EACH coll IN statsObj.collections
totalCount = totalCount + 1
IF coll.status = "green" THEN
healthyCount = healthyCount + 1
END IF
NEXT
IF totalCount > 0 THEN
healthPercent = (healthyCount / totalCount) * 100
SET BOT MEMORY "analytics_health_percent", healthPercent
END IF
REM Store last update timestamp
SET BOT MEMORY "analytics_last_update", NOW()
REM Generate summary for quick display
summary = "📊 " + FORMAT(statsObj.total_documents, "#,##0") + " docs"
summary = summary + " | " + FORMAT(statsObj.total_disk_size_mb, "#,##0.0") + " MB"
summary = summary + " | +" + FORMAT(statsObj.documents_added_last_week, "#,##0") + " this week"
SET BOT MEMORY "analytics_summary", summary

View file

@ -0,0 +1,82 @@
# Analytics Dashboard Guide
## Overview
The Analytics Dashboard provides real-time insights into your knowledge base performance, document statistics, and system health metrics.
## Key Metrics
### Document Statistics
- **Total Documents**: Number of documents indexed in your knowledge base
- **Total Vectors**: Number of vector embeddings created for semantic search
- **Storage Used**: Total storage consumption in megabytes
- **Collections**: Number of document collections/categories
### Activity Metrics
- **Documents This Week**: New documents added in the current week
- **Documents This Month**: New documents added in the current month
- **Growth Rate**: Percentage change compared to historical average
### System Health
- **Health Percentage**: Overall system status (100% = all systems operational)
- **Last Update**: Timestamp of the most recent statistics refresh
## How to Use
### Viewing Overview
Ask for an overview to see all key metrics at a glance:
- "Show overview"
- "What's the storage usage?"
- "How many documents do we have?"
### Checking Activity
Monitor recent changes and growth trends:
- "Show recent activity"
- "What's the growth trend?"
- "How many documents were added this week?"
### System Health
Check if all systems are running properly:
- "Show system health"
- "What's the collection status?"
- "Is everything working?"
## Understanding the Data
### Growth Rate Interpretation
- **Positive rate (📈)**: Knowledge base is growing faster than average
- **Negative rate (📉)**: Growth has slowed compared to average
- **Zero rate**: Stable growth matching historical patterns
### Health Status
- **100%**: All systems operational
- **Below 100%**: Some components may need attention
- **Check specific warnings** for details on affected systems
## Scheduled Updates
Statistics are automatically refreshed by the `update-stats` scheduled job. By default, this runs:
- Every hour for activity metrics
- Daily for comprehensive statistics
- On-demand when requested
## Frequently Asked Questions
**Q: Why do I see "Statistics are being computed"?**
A: The analytics system is initializing or refreshing data. Wait a few minutes and try again.
**Q: How accurate are the metrics?**
A: Metrics are updated regularly and reflect the state at the last refresh time shown in "Last Update".
**Q: Can I export analytics data?**
A: Yes, use the "Export Stats" tool to download metrics in various formats.
**Q: What affects system health?**
A: Health reflects database connectivity, vector store status, storage availability, and background job status.
## Best Practices
1. **Regular Monitoring**: Check the dashboard weekly to track growth trends
2. **Storage Planning**: Monitor storage usage to plan capacity needs
3. **Activity Tracking**: Use activity metrics to measure content team productivity
4. **Health Alerts**: Address health issues promptly when below 100%

View file

@ -0,0 +1,7 @@
name,value
episodic-memory-history,2
episodic-memory-threshold,4
theme-color1,#0d2b55
theme-color2,#fff9c2
theme-logo,https://pragmatismo.com.br/icons/general-bots.svg
theme-title,Announcements General Bots
1 name value
2 episodic-memory-history 2
3 episodic-memory-threshold 4
4 theme-color1 #0d2b55
5 theme-color2 #fff9c2
6 theme-logo https://pragmatismo.com.br/icons/general-bots.svg
7 theme-title Announcements General Bots

View file

@ -0,0 +1,8 @@
PARAM subject AS STRING LIKE "circular" DESCRIPTION "Subject to switch conversation to: circular, comunicado, or geral"
DESCRIPTION "Switch conversation subject when user wants to change topic"
kbname = LLM "Return single word: circular, comunicado or geral based on: " + subject
ADD_KB kbname
TALK "Subject changed to " + subject

View file

@ -0,0 +1,21 @@
resume1 = GET BOT MEMORY("resume")
resume2 = GET BOT MEMORY("auxiliom")
resume3 = GET BOT MEMORY("toolbix")
SET CONTEXT "general" AS resume1
SET CONTEXT "auxiliom" AS resume2
SET CONTEXT "toolbix" AS resume3
CLEAR SUGGESTIONS
ADD SUGGESTION "general" AS "Weekly announcements"
ADD SUGGESTION "general" AS "Latest circulars"
ADD SUGGESTION "auxiliom" AS "What is Auxiliom?"
ADD SUGGESTION "auxiliom" AS "Auxiliom services"
ADD SUGGESTION "toolbix" AS "Toolbix features"
ADD SUGGESTION "toolbix" AS "Toolbix for business"
ADD TOOL "change-subject"
TALK resume1
TALK "Ask me about any announcement or circular."

View file

@ -0,0 +1,11 @@
SET SCHEDULE "59 * * * *"
text = GET "announcements.gbkb/news/news.pdf"
resume = LLM "In a few words, resume this: " + text
SET BOT MEMORY "resume", resume
text1 = GET "announcements.gbkb/auxiliom/auxiliom.pdf"
SET BOT MEMORY "auxiliom", text1
text2 = GET "announcements.gbkb/toolbix/toolbix.pdf"
SET BOT MEMORY "toolbix", text2

Binary file not shown.

730
auth/login.html Normal file
View file

@ -0,0 +1,730 @@
<!doctype html>
<html lang="en" data-theme="light">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Login - BotServer</title>
<script src="/static/js/vendor/htmx.min.js"></script>
<script src="/static/js/vendor/htmx-ws.js"></script>
<style>
:root {
--primary: #3b82f6;
--primary-hover: #2563eb;
--secondary: #64748b;
--background: #ffffff;
--surface: #f8fafc;
--text: #1e293b;
--text-secondary: #64748b;
--border: #e2e8f0;
--error: #ef4444;
--success: #10b981;
}
[data-theme="dark"] {
--background: #0f172a;
--surface: #1e293b;
--text: #f1f5f9;
--text-secondary: #94a3b8;
--border: #334155;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family:
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
Oxygen, Ubuntu, sans-serif;
background: var(--background);
color: var(--text);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
transition: background-color 0.3s ease;
}
.login-container {
width: 100%;
max-width: 400px;
padding: 2rem;
}
.login-card {
background: var(--surface);
border-radius: 12px;
padding: 2rem;
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
border: 1px solid var(--border);
}
.logo {
text-align: center;
margin-bottom: 2rem;
}
.logo-icon {
font-size: 3rem;
margin-bottom: 0.5rem;
}
.logo-text {
font-size: 1.5rem;
font-weight: 600;
color: var(--text);
}
h1 {
font-size: 1.25rem;
font-weight: 600;
text-align: center;
margin-bottom: 1.5rem;
color: var(--text);
}
.form-group {
margin-bottom: 1.5rem;
}
label {
display: block;
margin-bottom: 0.5rem;
font-size: 0.875rem;
font-weight: 500;
color: var(--text-secondary);
}
input[type="email"],
input[type="password"],
input[type="text"] {
width: 100%;
padding: 0.75rem;
border: 1px solid var(--border);
border-radius: 8px;
font-size: 1rem;
background: var(--background);
color: var(--text);
transition: all 0.2s ease;
}
input:focus {
outline: none;
border-color: var(--primary);
box-shadow: 0 0 0 3px rgb(59 130 246 / 0.1);
}
.checkbox-group {
display: flex;
align-items: center;
margin-bottom: 1.5rem;
}
input[type="checkbox"] {
margin-right: 0.5rem;
width: 1.25rem;
height: 1.25rem;
cursor: pointer;
}
.checkbox-label {
font-size: 0.875rem;
color: var(--text-secondary);
cursor: pointer;
}
.btn {
width: 100%;
padding: 0.75rem;
border: none;
border-radius: 8px;
font-size: 1rem;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;
}
.btn-primary {
background: var(--primary);
color: white;
}
.btn-primary:hover {
background: var(--primary-hover);
}
.btn-primary:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.divider {
display: flex;
align-items: center;
margin: 1.5rem 0;
}
.divider::before,
.divider::after {
content: "";
flex: 1;
height: 1px;
background: var(--border);
}
.divider span {
padding: 0 1rem;
font-size: 0.875rem;
color: var(--text-secondary);
}
.oauth-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 0.75rem;
margin-bottom: 0.75rem;
}
.btn-oauth {
background: var(--background);
color: var(--text);
border: 1px solid var(--border);
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
padding: 0.625rem 0.75rem;
font-size: 0.875rem;
text-decoration: none;
}
.btn-oauth:hover {
background: var(--surface);
border-color: var(--primary);
}
.btn-oauth.hidden {
display: none;
}
.btn-oauth svg {
width: 1.25rem;
height: 1.25rem;
flex-shrink: 0;
}
/* Provider-specific colors on hover */
.btn-oauth-google:hover {
border-color: #ea4335;
color: #ea4335;
}
.btn-oauth-discord:hover {
border-color: #5865f2;
color: #5865f2;
}
.btn-oauth-reddit:hover {
border-color: #ff4500;
color: #ff4500;
}
.btn-oauth-twitter:hover {
border-color: #1da1f2;
color: #1da1f2;
}
.btn-oauth-microsoft:hover {
border-color: #00a4ef;
color: #00a4ef;
}
.btn-oauth-facebook:hover {
border-color: #1877f2;
color: #1877f2;
}
.error-message {
background: rgb(239 68 68 / 0.1);
color: var(--error);
padding: 0.75rem;
border-radius: 8px;
margin-bottom: 1rem;
font-size: 0.875rem;
border: 1px solid rgb(239 68 68 / 0.2);
}
.success-message {
background: rgb(16 185 129 / 0.1);
color: var(--success);
padding: 0.75rem;
border-radius: 8px;
margin-bottom: 1rem;
font-size: 0.875rem;
border: 1px solid rgb(16 185 129 / 0.2);
}
.loading-spinner {
display: none;
width: 1.25rem;
height: 1.25rem;
border: 2px solid rgba(255, 255, 255, 0.3);
border-top-color: white;
border-radius: 50%;
animation: spin 0.6s linear infinite;
margin: 0 auto;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.htmx-request .loading-spinner {
display: inline-block;
}
.htmx-request .btn-text {
display: none;
}
.link {
color: var(--primary);
text-decoration: none;
font-size: 0.875rem;
}
.link:hover {
text-decoration: underline;
}
.footer-links {
text-align: center;
margin-top: 1.5rem;
font-size: 0.875rem;
color: var(--text-secondary);
}
.theme-toggle {
position: absolute;
top: 1rem;
right: 1rem;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 8px;
padding: 0.5rem;
cursor: pointer;
font-size: 1.25rem;
transition: all 0.2s ease;
}
.theme-toggle:hover {
background: var(--background);
}
.dev-mode-banner {
background: rgb(251 146 60 / 0.1);
color: rgb(234 88 12);
padding: 0.5rem;
text-align: center;
font-size: 0.875rem;
border-bottom: 1px solid rgb(251 146 60 / 0.2);
position: fixed;
top: 0;
left: 0;
right: 0;
}
.oauth-section {
margin-top: 0.5rem;
}
.oauth-loading {
text-align: center;
padding: 1rem;
color: var(--text-secondary);
font-size: 0.875rem;
}
.no-oauth {
text-align: center;
padding: 0.5rem;
color: var(--text-secondary);
font-size: 0.75rem;
}
</style>
</head>
<body>
<!-- Theme Toggle -->
<button
class="theme-toggle"
onclick="toggleTheme()"
aria-label="Toggle theme"
>
<span id="theme-icon">🌙</span>
</button>
<!-- Dev Mode Banner (shown when Zitadel is not available) -->
<div id="dev-mode-banner" class="dev-mode-banner" style="display: none">
⚠️ Development Mode: Use any email with password "password"
</div>
<div class="login-container">
<div class="login-card">
<!-- Logo -->
<div class="logo">
<div class="logo-icon">🤖</div>
<div class="logo-text">BotServer</div>
</div>
<h1>Sign in to your account</h1>
<!-- Error Message -->
{% if error_message %}
<div class="error-message">{{ error_message }}</div>
{% endif %}
<!-- Success Message Target -->
<div id="message-container"></div>
<!-- Login Form -->
<form
id="login-form"
hx-post="/auth/login"
hx-target="#message-container"
hx-indicator=".loading-spinner"
>
<div class="form-group">
<label for="email">Email address</label>
<input
type="email"
id="email"
name="email"
required
autocomplete="email"
placeholder="user@example.com"
/>
</div>
<div class="form-group">
<label for="password">Password</label>
<input
type="password"
id="password"
name="password"
required
autocomplete="current-password"
placeholder="Enter your password"
/>
</div>
<div class="checkbox-group">
<input
type="checkbox"
id="remember_me"
name="remember_me"
value="true"
/>
<label for="remember_me" class="checkbox-label"
>Remember me</label
>
</div>
{% if redirect_url %}
<input
type="hidden"
name="redirect"
value="{{ redirect_url }}"
/>
{% endif %}
<button type="submit" class="btn btn-primary">
<span class="btn-text">Sign in</span>
<span class="loading-spinner"></span>
</button>
</form>
<!-- OAuth Options -->
<div class="divider">
<span>or continue with</span>
</div>
<div class="oauth-section" id="oauth-section">
<div class="oauth-loading" id="oauth-loading">
Loading login options...
</div>
<div
class="oauth-grid"
id="oauth-buttons"
style="display: none"
>
<!-- Google -->
<a
href="/auth/oauth/google{% if redirect_url %}?redirect={{ redirect_url }}{% endif %}"
class="btn btn-oauth btn-oauth-google hidden"
id="btn-google"
title="Sign in with Google"
>
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"
fill="#4285F4"
/>
<path
d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
fill="#34A853"
/>
<path
d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"
fill="#FBBC05"
/>
<path
d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
fill="#EA4335"
/>
</svg>
Google
</a>
<!-- Microsoft -->
<a
href="/auth/oauth/microsoft{% if redirect_url %}?redirect={{ redirect_url }}{% endif %}"
class="btn btn-oauth btn-oauth-microsoft hidden"
id="btn-microsoft"
title="Sign in with Microsoft"
>
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M11.4 24H0V12.6h11.4V24z"
fill="#00A4EF"
/>
<path
d="M24 24H12.6V12.6H24V24z"
fill="#FFB900"
/>
<path
d="M11.4 11.4H0V0h11.4v11.4z"
fill="#F25022"
/>
<path
d="M24 11.4H12.6V0H24v11.4z"
fill="#7FBA00"
/>
</svg>
Microsoft
</a>
<!-- Discord -->
<a
href="/auth/oauth/discord{% if redirect_url %}?redirect={{ redirect_url }}{% endif %}"
class="btn btn-oauth btn-oauth-discord hidden"
id="btn-discord"
title="Sign in with Discord"
>
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z"
fill="#5865F2"
/>
</svg>
Discord
</a>
<!-- Facebook -->
<a
href="/auth/oauth/facebook{% if redirect_url %}?redirect={{ redirect_url }}{% endif %}"
class="btn btn-oauth btn-oauth-facebook hidden"
id="btn-facebook"
title="Sign in with Facebook"
>
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"
fill="#1877F2"
/>
</svg>
Facebook
</a>
<!-- Twitter/X -->
<a
href="/auth/oauth/twitter{% if redirect_url %}?redirect={{ redirect_url }}{% endif %}"
class="btn btn-oauth btn-oauth-twitter hidden"
id="btn-twitter"
title="Sign in with Twitter/X"
>
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"
/>
</svg>
Twitter
</a>
<!-- Reddit -->
<a
href="/auth/oauth/reddit{% if redirect_url %}?redirect={{ redirect_url }}{% endif %}"
class="btn btn-oauth btn-oauth-reddit hidden"
id="btn-reddit"
title="Sign in with Reddit"
>
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M12 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0zm5.01 4.744c.688 0 1.25.561 1.25 1.249a1.25 1.25 0 0 1-2.498.056l-2.597-.547-.8 3.747c1.824.07 3.48.632 4.674 1.488.308-.309.73-.491 1.207-.491.968 0 1.754.786 1.754 1.754 0 .716-.435 1.333-1.01 1.614a3.111 3.111 0 0 1 .042.52c0 2.694-3.13 4.87-7.004 4.87-3.874 0-7.004-2.176-7.004-4.87 0-.183.015-.366.043-.534A1.748 1.748 0 0 1 4.028 12c0-.968.786-1.754 1.754-1.754.463 0 .898.196 1.207.49 1.207-.883 2.878-1.43 4.744-1.487l.885-4.182a.342.342 0 0 1 .14-.197.35.35 0 0 1 .238-.042l2.906.617a1.214 1.214 0 0 1 1.108-.701zM9.25 12C8.561 12 8 12.562 8 13.25c0 .687.561 1.248 1.25 1.248.687 0 1.248-.561 1.248-1.249 0-.688-.561-1.249-1.249-1.249zm5.5 0c-.687 0-1.248.561-1.248 1.25 0 .687.561 1.248 1.249 1.248.688 0 1.249-.561 1.249-1.249 0-.687-.562-1.249-1.25-1.249zm-5.466 3.99a.327.327 0 0 0-.231.094.33.33 0 0 0 0 .463c.842.842 2.484.913 2.961.913.477 0 2.105-.056 2.961-.913a.361.361 0 0 0 .029-.463.33.33 0 0 0-.464 0c-.547.533-1.684.73-2.512.73-.828 0-1.979-.196-2.512-.73a.326.326 0 0 0-.232-.095z"
fill="#FF4500"
/>
</svg>
Reddit
</a>
</div>
<div class="no-oauth" id="no-oauth" style="display: none">
No social login providers configured
</div>
</div>
<!-- Footer Links -->
<div class="footer-links">
<a href="/auth/forgot-password" class="link"
>Forgot password?</a
>
<span> · </span>
<a href="/auth/register" class="link">Create account</a>
</div>
</div>
</div>
<script>
// Theme management
function initTheme() {
const savedTheme = localStorage.getItem("theme") || "light";
document.documentElement.setAttribute("data-theme", savedTheme);
updateThemeIcon(savedTheme);
}
function toggleTheme() {
const currentTheme =
document.documentElement.getAttribute("data-theme");
const newTheme = currentTheme === "light" ? "dark" : "light";
document.documentElement.setAttribute("data-theme", newTheme);
localStorage.setItem("theme", newTheme);
updateThemeIcon(newTheme);
}
function updateThemeIcon(theme) {
const icon = document.getElementById("theme-icon");
icon.textContent = theme === "light" ? "🌙" : "☀️";
}
// Check if in development mode
async function checkDevMode() {
try {
const response = await fetch("/api/auth/mode");
const data = await response.json();
if (data.mode === "development") {
document.getElementById(
"dev-mode-banner",
).style.display = "block";
document.body.style.paddingTop = "2.5rem";
}
} catch (err) {
// Ignore - assume production mode
}
}
// Load enabled OAuth providers
async function loadOAuthProviders() {
const loadingEl = document.getElementById("oauth-loading");
const buttonsEl = document.getElementById("oauth-buttons");
const noOAuthEl = document.getElementById("no-oauth");
try {
const response = await fetch("/auth/oauth/providers");
const data = await response.json();
loadingEl.style.display = "none";
if (data.providers && data.providers.length > 0) {
buttonsEl.style.display = "grid";
// Show buttons for enabled providers
data.providers.forEach((provider) => {
const btn = document.getElementById(
"btn-" + provider.id,
);
if (btn) {
btn.classList.remove("hidden");
}
});
// Check if any buttons are visible
const visibleButtons =
buttonsEl.querySelectorAll("a:not(.hidden)");
if (visibleButtons.length === 0) {
buttonsEl.style.display = "none";
noOAuthEl.style.display = "block";
}
} else {
noOAuthEl.style.display = "block";
}
} catch (err) {
console.error("Failed to load OAuth providers:", err);
loadingEl.style.display = "none";
// Show all buttons as fallback (they'll redirect to error page if not configured)
buttonsEl.style.display = "grid";
buttonsEl.querySelectorAll("a").forEach((btn) => {
btn.classList.remove("hidden");
});
}
}
// Initialize
document.addEventListener("DOMContentLoaded", () => {
initTheme();
checkDevMode();
loadOAuthProviders();
// Handle form validation
const form = document.getElementById("login-form");
form.addEventListener("submit", (e) => {
const email = document.getElementById("email").value;
const password = document.getElementById("password").value;
if (!email || !password) {
e.preventDefault();
showError("Please fill in all fields");
return false;
}
});
});
// Show error message
function showError(message) {
const container = document.getElementById("message-container");
container.innerHTML = `<div class="error-message">${message}</div>`;
}
// Handle HTMX events
document.body.addEventListener("htmx:afterRequest", (event) => {
if (event.detail.xhr.status === 200) {
// Check if we got a redirect header
const redirect =
event.detail.xhr.getResponseHeader("HX-Redirect");
if (redirect) {
window.location.href = redirect;
}
}
});
document.body.addEventListener("htmx:responseError", (event) => {
showError(
"Authentication failed. Please check your credentials.",
);
});
</script>
</body>
</html>

View file

@ -0,0 +1,42 @@
PARAM folder AS STRING LIKE "default.gbdrive" DESCRIPTION "Folder to backup files from" OPTIONAL
PARAM days_old AS INTEGER LIKE 3 DESCRIPTION "Archive files older than this many days" OPTIONAL
DESCRIPTION "Backup and archive expired files to server storage"
IF NOT folder THEN
folder = "default.gbdrive"
END IF
IF NOT days_old THEN
days_old = 3
END IF
list = DIR folder
archived = 0
FOR EACH item IN list
oldDays = DATEDIFF today, item.modified, "day"
IF oldDays > days_old THEN
blob = UPLOAD item
WITH logEntry
action = "archived"
date = today
time = now
path = item.path
name = item.name
size = item.size
modified = item.modified
md5 = blob.md5
END WITH
SAVE "log.xlsx", logEntry
DELETE item
archived = archived + 1
END IF
NEXT
TALK "Backup complete. " + archived + " files archived."
RETURN archived

View file

@ -0,0 +1,34 @@
ADD TOOL "backup-to-server"
ADD TOOL "restore-file"
ADD TOOL "list-archived"
ADD TOOL "cleanup-old"
CLEAR SUGGESTIONS
ADD SUGGESTION "backup" AS "Run backup now"
ADD SUGGESTION "list" AS "View archived files"
ADD SUGGESTION "restore" AS "Restore a file"
ADD SUGGESTION "status" AS "Backup status"
SET CONTEXT "backup" AS "You are a backup management assistant. Help users archive files to server storage, restore archived files, and manage backup schedules."
BEGIN TALK
**Backup Manager**
I can help you with:
Archive files to server storage
Restore archived files
View backup history
Manage backup schedules
Select an option or tell me what you need.
END TALK
BEGIN SYSTEM PROMPT
You are a backup management assistant.
Archive files older than specified days to server storage.
Track all backup operations in log.xlsx.
Support restore operations from archived files.
Maintain MD5 checksums for integrity verification.
END SYSTEM PROMPT

View file

@ -0,0 +1,146 @@
# Backup Management Guide
## Overview
The Backup Manager helps you protect your important files by archiving them to secure server storage. Regular backups ensure business continuity and data protection.
## Features
### Automated Backups
- Schedule automatic backups at regular intervals
- Archive files based on age criteria
- Maintain backup rotation policies
### Manual Backups
- On-demand backup of specific files or folders
- Selective backup based on file types
- Priority backup for critical data
### Restore Operations
- Browse archived files by date
- Restore individual files or entire folders
- Preview files before restoration
## How to Use
### Running a Backup
To start a backup, you can:
1. Say "Run backup now" or select the backup option
2. Specify which files or folders to back up
3. Confirm the backup operation
### Viewing Archived Files
To see your backup history:
1. Say "View archived files" or "List backups"
2. Browse by date or file name
3. Select files to view details or restore
### Restoring Files
To restore from backup:
1. Say "Restore a file" or select restore option
2. Search for the file by name or date
3. Confirm the restoration location
## Backup Best Practices
### Frequency Recommendations
| Data Type | Recommended Frequency |
|-----------|----------------------|
| Critical business data | Daily |
| Documents and files | Weekly |
| System configurations | Before changes |
| Archives and logs | Monthly |
### What to Back Up
**Always include:**
- Business documents
- Customer data
- Financial records
- Configuration files
- Email archives
**Consider excluding:**
- Temporary files
- Cache directories
- Downloaded installers
- Duplicate files
## Storage and Retention
### Retention Policies
- **Daily backups**: Kept for 7 days
- **Weekly backups**: Kept for 4 weeks
- **Monthly backups**: Kept for 12 months
- **Annual backups**: Kept for 7 years
### Storage Locations
Backups are stored on:
- Primary: Secure server storage
- Secondary: Offsite replication (if configured)
## Data Integrity
### Verification
All backups include:
- MD5 checksums for integrity verification
- File count validation
- Size comparison checks
### Monitoring
The system logs:
- Backup start and completion times
- Files included in each backup
- Any errors or warnings
- Storage utilization
## Troubleshooting
### Common Issues
**Backup fails to start:**
- Check storage space availability
- Verify file permissions
- Ensure no files are locked
**Restore not finding files:**
- Verify the backup date range
- Check file name spelling
- Ensure the backup completed successfully
**Slow backup performance:**
- Reduce backup scope
- Schedule during off-peak hours
- Check network connectivity
## Frequently Asked Questions
**Q: How long does a backup take?**
A: Depends on data volume. Initial backups take longer; subsequent backups are incremental.
**Q: Can I backup while working?**
A: Yes, the system handles file locking gracefully.
**Q: Where are backups stored?**
A: On the configured server storage with optional offsite replication.
**Q: How do I know if backups are working?**
A: Check backup status or ask "Backup status" to see recent backup logs.
**Q: Can I exclude certain files?**
A: Yes, specify exclusion patterns when configuring backups.
## Support
For backup-related issues:
- Check the backup logs for error details
- Verify storage availability
- Contact your system administrator

View file

@ -0,0 +1,236 @@
# Banking Services Guide
## Account Types
### Checking Account
A checking account is designed for daily transactions and provides easy access to your funds.
**Features:**
- Unlimited transactions
- Debit card included
- Online and mobile banking access
- Bill pay services
- Direct deposit available
**Requirements:**
- Minimum opening deposit: $25
- Valid government-issued ID
- Social Security Number or Tax ID
### Savings Account
A savings account helps you grow your money with interest while keeping it accessible.
**Features:**
- Competitive interest rates
- No monthly maintenance fee with minimum balance
- Automatic transfers from checking
- Up to 6 withdrawals per month
**Interest Rates:**
- Standard Savings: 0.50% APY
- High-Yield Savings: 2.50% APY (minimum $1,000 balance)
### Certificate of Deposit (CD)
CDs offer higher interest rates in exchange for keeping your money deposited for a fixed term.
**Terms Available:**
- 6 months: 3.00% APY
- 12 months: 3.50% APY
- 24 months: 4.00% APY
- 60 months: 4.50% APY
**Early Withdrawal Penalty:** 90 days of interest
## Transfer Services
### Internal Transfers
Move money between your accounts instantly at no cost.
**How to transfer:**
1. Select source account
2. Select destination account
3. Enter amount
4. Confirm transfer
### External Transfers (ACH)
Transfer funds to accounts at other banks.
**Processing Times:**
- Standard: 2-3 business days
- Same-day ACH: Available for transfers initiated before 2 PM
**Limits:**
- Daily limit: $10,000
- Monthly limit: $50,000
### Wire Transfers
For urgent or large transfers, domestic and international.
**Domestic Wires:**
- Fee: $25
- Processing: Same business day if before 4 PM
**International Wires:**
- Fee: $45
- Processing: 1-2 business days
### PIX (Brazil)
Instant payment system available 24/7, including holidays.
**Features:**
- Instant transfers
- No fees for individuals
- Available via CPF, phone, email, or random key
- QR code payments supported
**Limits:**
- Daytime (6 AM - 8 PM): R$ 20,000
- Nighttime (8 PM - 6 AM): R$ 1,000 (adjustable)
## Card Services
### Debit Card
Your debit card is linked directly to your checking account.
**Daily Limits:**
- ATM withdrawal: $500
- Point of sale purchases: $2,500
**Lost or Stolen Card:**
Contact us immediately to block your card. A replacement will be sent within 5-7 business days.
### Credit Card
Build credit and earn rewards with our credit cards.
**Card Options:**
- Classic: No annual fee, 1% cashback
- Gold: $95 annual fee, 2% cashback, travel insurance
- Platinum: $195 annual fee, 3% cashback, concierge service
**Payment Due Date:** 25th of each month
### Card Blocking
If your card is lost or stolen:
1. Say "block my card" to this assistant
2. Call 1-800-BANK-HELP
3. Use the mobile app
Temporary blocks can be lifted at any time.
## Bill Pay
### One-Time Payments
Pay any bill directly from your account.
**Supported Billers:**
- Utilities
- Credit cards
- Loans
- Insurance
- Government agencies
### Recurring Payments
Set up automatic payments for regular bills.
**Options:**
- Fixed amount on specific date
- Full statement balance
- Minimum payment due
### Payment Processing
- Electronic payments: 1-2 business days
- Check payments: 5-7 business days
## Loans and Financing
### Personal Loans
Unsecured loans for any purpose.
**Terms:** 12 to 60 months
**Rates:** 8.99% - 18.99% APR
**Amounts:** $1,000 - $50,000
### Home Loans
Mortgages for purchasing or refinancing your home.
**Types Available:**
- 30-year fixed
- 15-year fixed
- Adjustable rate (ARM)
- FHA loans
- VA loans
### Auto Loans
Financing for new or used vehicles.
**New Cars:** Rates from 5.49% APR
**Used Cars:** Rates from 6.49% APR
**Terms:** 24 to 72 months
### Credit Line
Flexible borrowing when you need it.
**Home Equity Line (HELOC):** Up to 85% of home value
**Personal Line of Credit:** $5,000 - $25,000
## Investment Services
### Investment Options
- Savings bonds
- CDB (Certificado de Depósito Bancário)
- LCI/LCA (tax-exempt real estate/agribusiness letters)
- Investment funds
- Retirement accounts (401k, IRA, Previdência)
### Retirement Planning
Our advisors can help you plan for retirement with:
- Portfolio analysis
- Risk assessment
- Tax-efficient strategies
- Regular reviews
## Security Information
### Online Banking Security
- 256-bit SSL encryption
- Two-factor authentication
- Automatic session timeout
- Transaction alerts
### Fraud Protection
- 24/7 fraud monitoring
- Zero liability for unauthorized transactions
- Instant transaction alerts
- Secure card chip technology
### What We Will Never Ask
- Full card number via chat or email
- Your password or PIN
- Security codes via unsolicited contact
- Personal information via text message
## Frequently Asked Questions
**Q: How do I check my balance?**
A: Say "check my balance" or "what's my balance" to this assistant.
**Q: How do I dispute a transaction?**
A: Contact us within 60 days of the transaction. Provide the date, amount, and merchant name.
**Q: What are your business hours?**
A: Digital banking is available 24/7. Branch hours are Monday-Friday 9 AM - 5 PM, Saturday 9 AM - 1 PM.
**Q: How do I update my contact information?**
A: You can update your address, phone, and email through online banking or by visiting a branch.
**Q: Is there a fee for using other banks' ATMs?**
A: We charge $3 per transaction. The ATM owner may charge an additional fee.
## Contact Information
- **Customer Service:** 1-800-BANK-HELP
- **Fraud Hotline:** 1-800-FRAUD-911
- **International:** +1-555-123-4567
- **Email:** support@generalbank.com
For immediate assistance, continue chatting with this assistant.

53
bank.gbai/start.bas Normal file
View file

@ -0,0 +1,53 @@
ADD TOOL "check-balance"
ADD TOOL "transfer-money"
ADD TOOL "pay-bill"
ADD TOOL "card-services"
ADD TOOL "loan-inquiry"
ADD TOOL "investment-info"
ADD TOOL "transaction-history"
ADD TOOL "open-account"
ADD BOT "fraud-detector" WITH TRIGGER "suspicious, fraud, unauthorized, stolen, hack"
ADD BOT "investment-advisor" WITH TRIGGER "invest, stocks, funds, portfolio, returns, CDB, LCI"
ADD BOT "loan-specialist" WITH TRIGGER "loan, financing, credit, mortgage, empréstimo"
ADD BOT "card-services" WITH TRIGGER "card, credit card, debit card, block card, limit"
USE KB "banking-faq"
CLEAR SUGGESTIONS
ADD SUGGESTION "balance" AS "Check my balance"
ADD SUGGESTION "transfer" AS "Make a transfer"
ADD SUGGESTION "pix" AS "Send PIX"
ADD SUGGESTION "bills" AS "Pay a bill"
ADD SUGGESTION "card" AS "Card services"
ADD SUGGESTION "history" AS "Transaction history"
ADD SUGGESTION "invest" AS "Investment options"
ADD SUGGESTION "loan" AS "Loan information"
SET CONTEXT "You are a professional banking assistant for General Bank. Help customers with accounts, transfers, payments, cards, loans, and investments. Always verify identity before sensitive operations. Be helpful and secure. Never ask for full card numbers or passwords in chat."
BEGIN TALK
**General Bank** - Digital Banking Assistant
Welcome! I can help you with:
Account balance and statements
Transfers and PIX
Bill payments
Card services
Investments
Loans and financing
Select an option below or tell me what you need.
END TALK
BEGIN SYSTEM PROMPT
You are a secure banking assistant.
Security rules:
- Never display full account numbers
- Mask card numbers showing only last 4 digits
- Require confirmation for transactions over $1000
- Log all sensitive operations
- Escalate fraud concerns immediately
END SYSTEM PROMPT

245
bi.gbai/README.md Normal file
View file

@ -0,0 +1,245 @@
# Business Intelligence Template (bi.gbai)
A General Bots template for automated business intelligence reporting and data visualization.
## Overview
The BI template provides scheduled analytics reporting with automatic chart generation and delivery. It's designed for organizations that need automated consumption reports, category analysis, and customer-specific insights.
## Features
- **Scheduled Reporting** - Automated report generation on configurable schedules
- **Time-Series Charts** - Monthly consumption trends visualization
- **Category Analysis** - Product category breakdown with donut charts
- **Per-Customer Reports** - Individual customer consumption analysis
- **Multi-Channel Delivery** - Send reports via chat, email, or messaging platforms
## Package Structure
```
bi.gbai/
├── README.md
└── bi.gbai/
├── bi-admin.bas # Administrative scheduled reports
└── bi-user.bas # Per-customer report generation
```
## Scripts
| File | Description |
|------|-------------|
| `bi-admin.bas` | Scheduled job for generating platform-wide analytics reports |
| `bi-user.bas` | Loop through customers to generate individual consumption reports |
## Configuration
Configure the template in your bot's `config.csv`:
| Parameter | Description | Example |
|-----------|-------------|---------|
| `Schedule` | Cron expression for report timing | `1 * * * * *` |
| `Data Source` | Table/view for billing data | `Orders` |
## Usage
### Administrative Reports
The `bi-admin.bas` script runs on a schedule and generates:
1. **Monthly Consumption Chart** - Time-series showing spending trends
2. **Product Category Breakdown** - Donut chart of spending by category
```basic
SET SCHEDULE "1 * * * * *"
billing = FIND "Orders"
' Monthly consumption
data = SELECT SUM(UnitPrice * Quantity) as Value,
MONTH(OrderDate)+'/'+YEAR(OrderDate)
FROM billing
GROUP BY MONTH(OrderDate), YEAR(OrderDate)
img = CHART "timeseries", data
SEND FILE img, "Monthly Consumption"
```
### Per-Customer Reports
The `bi-user.bas` script iterates through customers to generate personalized reports:
```basic
customers = FIND "Customers"
FOR EACH c IN customers
data = SELECT SUM(UnitPrice * Quantity) AS Value,
MONTH(OrderDate)+'/'+YEAR(OrderDate)
FROM billing
JOIN Customers ON billing.CustomerID = Customers.CustomerID
GROUP BY MONTH(OrderDate), YEAR(OrderDate)
WHERE Customers.CustomerID = c.CustomerID
img = CHART "timeseries", data
SEND FILE img, "Monthly Consumption"
END FOR
```
## Chart Types
The template supports various chart types:
| Type | Use Case |
|------|----------|
| `timeseries` | Trends over time (monthly, weekly, daily) |
| `donut` | Category distribution |
| `bar` | Comparative analysis |
| `pie` | Percentage breakdowns |
## Data Requirements
### Orders Table Schema
The template expects a billing/orders data source with:
- `OrderDate` - Date of the transaction
- `UnitPrice` - Price per unit
- `Quantity` - Number of units
- `ProductID` - Foreign key to products
- `CustomerID` - Foreign key to customers
### Products Table Schema
- `ProductID` - Primary key
- `CategoryID` - Foreign key to categories
- `ProductName` - Product name
### Categories Table Schema
- `CategoryID` - Primary key
- `CategoryName` - Category display name
## Example Output
### Monthly Consumption Report
```
📊 Monthly Consumption Report
-----------------------------
Generated: 2024-01-15 08:00
[Time Series Chart Image]
Total Revenue: $125,430
Top Month: December ($18,500)
Growth Rate: +12% MoM
```
### Category Breakdown
```
📊 Product Category Distribution
--------------------------------
[Donut Chart Image]
Electronics: 35%
Clothing: 28%
Home & Garden: 22%
Other: 15%
```
## Customization
### Adding New Reports
Create additional `.bas` files in the `bi.gbai` folder:
```basic
' sales-by-region.bas
SET SCHEDULE "0 9 * * 1" ' Every Monday at 9 AM
data = SELECT Region, SUM(Amount) as Total
FROM Sales
GROUP BY Region
img = CHART "bar", data
SEND FILE img, "Weekly Regional Sales"
```
### Customizing Delivery
Send reports to specific users or channels:
```basic
' Send to specific user
SEND FILE img TO "manager@company.com", "Weekly Report"
' Send to WhatsApp
SEND FILE img TO "+1234567890", "Your monthly report"
' Send to team channel
TALK TO "sales-team", img
```
## Scheduling Options
| Schedule | Cron Expression | Description |
|----------|-----------------|-------------|
| Every minute | `1 * * * * *` | Testing/real-time |
| Hourly | `0 0 * * * *` | Frequent updates |
| Daily 8 AM | `0 0 8 * * *` | Morning reports |
| Weekly Monday | `0 0 9 * * 1` | Weekly summaries |
| Monthly 1st | `0 0 8 1 * *` | Monthly reports |
## Integration
### With CRM
```basic
' Combine with CRM data
opportunities = FIND "opportunities.csv"
revenue = SELECT stage, SUM(amount) FROM opportunities GROUP BY stage
img = CHART "funnel", revenue
SEND FILE img, "Sales Pipeline"
```
### With ERP
```basic
' Inventory analysis
inventory = FIND "inventory.csv"
low_stock = SELECT product, quantity FROM inventory WHERE quantity < reorder_level
img = CHART "bar", low_stock
SEND FILE img, "Low Stock Alert"
```
## Best Practices
1. **Schedule appropriately** - Don't run heavy reports too frequently
2. **Filter data** - Use date ranges to limit data volume
3. **Cache results** - Store computed metrics for faster access
4. **Log activities** - Track report generation for auditing
5. **Handle errors** - Wrap queries in error handling
## Troubleshooting
| Issue | Solution |
|-------|----------|
| Empty charts | Verify data source has records |
| Schedule not running | Check cron syntax |
| Slow reports | Add date filters, optimize queries |
| Missing data | Verify JOIN conditions |
## Related Templates
- `analytics.gbai` - Platform analytics
- `talk-to-data.gbai` - Natural language data queries
- `crm.gbai` - CRM with built-in reporting
## License
AGPL-3.0 - Part of General Bots Open Source Platform.
---
**Pragmatismo** - General Bots

View file

@ -0,0 +1,13 @@
SET SCHEDULE "1 * * * * *"
billing = FIND "Orders"
' Monthly consumption
data = SELECT SUM(UnitPrice * Quantity) as Value, MONTH(OrderDate)+'/'+YEAR(OrderDate) from billing GROUP BY MONTH(OrderDate), YEAR(OrderDate)
img = CHART "timeseries", data
SEND FILE img, "Monthly Consumption"
' Product Category
data = SELECT SUM(UnitPrice * Quantity) as Value, CategoryName from billing JOIN Products ON billing.ProductID = Products.ProductID JOIN Categories ON Products.CategoryID = Categories.CategoryID GROUP BY CategoryName
img = CHART "donut", data
SEND FILE img, "Product Category"

View file

@ -0,0 +1,13 @@
' Individual customer report generation
customers = FIND "Customers"
FOR EACH c IN customers
data = SELECT SUM(UnitPrice * Quantity) AS Value, MONTH(OrderDate)+'/'+YEAR(OrderDate) FROM billing
JOIN Customers ON billing.CustomerID = Customers.CustomerID
GROUP BY MONTH(OrderDate), YEAR(OrderDate)
WHERE Customers.CustomerID = c.CustomerID
img = CHART "timeseries", data
SEND FILE img, "Monthly Consumption"
END FOR

View file

@ -0,0 +1,118 @@
# Bling ERP Integration (.gbdialog)
This package provides complete integration with [Bling ERP](https://www.bling.com.br/) for data synchronization and conversational commerce.
## Scripts
| File | Description |
|------|-------------|
| `start.bas` | Welcome message and system prompt configuration |
| `tables.bas` | Database schema definitions for all synced entities |
| `sync-erp.bas` | Main ERP synchronization (products, orders, contacts, vendors) |
| `sync-accounts.bas` | Accounts payable and receivable synchronization |
| `sync-inventory.bas` | Stock/inventory levels synchronization |
| `sync-suppliers.bas` | Supplier/vendor data synchronization |
| `add-stock.bas` | Manual stock adjustment tool |
| `data-analysis.bas` | LLM-powered data analysis and reporting |
| `refresh-llm.bas` | Scheduled LLM context refresh |
## Configuration
Configure the integration in `bling.gbot/config.csv`:
| Parameter | Description |
|-----------|-------------|
| `param-blingClientID` | Bling API Client ID |
| `param-blingClientSecret` | Bling API Client Secret |
| `param-blingHost` | Bling API base URL |
| `param-host` | API endpoint (default: `https://api.bling.com.br/Api/v3`) |
| `param-limit` | Records per page for API calls |
| `param-pages` | Maximum pages to sync |
| `param-admin1` | Primary admin email for notifications |
| `param-admin2` | Secondary admin email for notifications |
## Synchronized Entities
### Products (`maria.Produtos`)
- Product details, SKU, pricing
- Product variations and hierarchy
- Product images (`maria.ProdutoImagem`)
### Orders (`maria.Pedidos`)
- Sales orders with line items (`maria.PedidosItem`)
- Payment parcels (`maria.Parcela`)
### Contacts (`maria.Contatos`)
- Customers and suppliers
- Address and billing information
### Vendors (`maria.Vendedores`)
- Sales representatives
- Commission and discount limits
### Financial
- Accounts Receivable (`maria.ContasAReceber`)
- Accounts Payable (`maria.ContasAPagar`)
- Payment Methods (`maria.FormaDePagamento`)
- Revenue Categories (`maria.CategoriaReceita`)
### Inventory
- Stock by Warehouse (`maria.Depositos`)
- Product Suppliers (`maria.ProdutoFornecedor`)
- Price History (`maria.HistoricoPreco`)
## Scheduled Jobs
The following schedules are configured:
| Job | Schedule | Description |
|-----|----------|-------------|
| `sync-erp.bas` | Daily at 22:30 | Full ERP synchronization |
| `sync-accounts.bas` | Every 2 days at midnight | Financial accounts sync |
| `sync-inventory.bas` | Daily at 23:30 | Stock levels update |
| `refresh-llm.bas` | Daily at 21:00 | Refresh LLM context |
## Data Analysis
The `data-analysis.bas` script enables natural language queries against synced data:
**Example queries:**
- "Which products have excess stock that can be transferred?"
- "What are the top 10 best-selling products?"
- "What is the average ticket for each store?"
- "Which products need restocking?"
## Usage
### Manual Stock Adjustment
Vendors can adjust stock via conversation:
```basic
REM User provides SKU and quantity
REM Stock is updated in Bling and local database
```
### Running Sync Manually
```basic
RUN "sync-erp.bas"
RUN "sync-accounts.bas"
RUN "sync-inventory.bas"
```
## API Integration
All API calls use the Bling v3 REST API with pagination support:
- Products: `GET /produtos`
- Orders: `GET /pedidos/vendas`
- Contacts: `GET /contatos`
- Inventory: `GET /estoques/saldos`
- Accounts: `GET /contas/receber`, `GET /contas/pagar`
## Related Documentation
- [Bling API Documentation](https://developer.bling.com.br/)
- [General Bots BASIC Reference](../../docs/src/chapter-06-gbdialog/README.md)
- [Template Guide](../../README.md)

View file

@ -0,0 +1,33 @@
PARAM sku AS STRING LIKE "ABC123" DESCRIPTION "Product SKU code to update stock"
PARAM qtd AS INTEGER LIKE 10 DESCRIPTION "Quantity to add to stock"
DESCRIPTION "Add stock quantity for a product by SKU"
person = FIND "People.xlsx", "id=" + mobile
vendor = FIND "maria.Vendedores", "id=" + person.erpId
TALK "Olá " + vendor.Contato_Nome + "!"
produto = FIND "maria.Produtos", "sku=" + sku
IF NOT produto THEN
TALK "Produto não encontrado."
RETURN
END IF
WITH estoque
produto = { id: produto.Id }
deposito = { id: person.deposito_Id }
preco = produto.Preco
operacao = "B"
quantidade = qtd
observacoes = "Acréscimo de estoque."
END WITH
rec = POST host + "/estoques", estoque
TALK "Estoque atualizado."
TALK TO admin1, "Estoque do ${sku} atualizado com ${qtd}."
TALK TO admin2, "Estoque do ${sku} atualizado com ${qtd}."
RETURN rec

View file

@ -0,0 +1,53 @@
ALLOW ROLE "analiseDados"
ADD TOOL "sync-erp"
ADD TOOL "sync-inventory"
ADD TOOL "refresh-llm"
CLEAR SUGGESTIONS
ADD SUGGESTION "estoque" AS "Produtos com estoque excessivo"
ADD SUGGESTION "vendas" AS "Top 10 produtos vendidos"
ADD SUGGESTION "ticket" AS "Ticket médio por loja"
ADD SUGGESTION "critico" AS "Estoque crítico"
ADD SUGGESTION "transferir" AS "Sugestão de transferência"
ADD SUGGESTION "compra" AS "Sugestão de compra"
SET CONTEXT "As lojas B, L e R estão identificadas no final dos nomes das colunas da tabela de Análise de Compras. Dicionário de dados AnaliseCompras.qtEstoqueL: Descrição quantidade do Leblon. AnaliseCompras.qtEstoqueB: Descrição quantidade da Barra AnaliseCompras.qtEstoqueR: Descrição quantidade do Rio Sul. Com base no comportamento de compra registrado, analise os dados fornecidos para identificar oportunidades de otimização de estoque. Aplique regras básicas de transferência de produtos entre as lojas, considerando a necessidade de balanceamento de inventário. Retorne um relatório das 10 ações mais críticas, detalhe a movimentação sugerida para cada produto. Deve indicar a loja de origem, a loja de destino e o motivo da transferência. A análise deve ser objetiva e pragmática, focando na melhoria da disponibilidade de produtos nas lojas. Sempre use LIKE %% para comparar nomes. IMPORTANTE: Compare sempre com a função LOWER ao filtrar valores, em ambos os operandos de texto em SQL, para ignorar case, exemplo WHERE LOWER(loja.nome) LIKE LOWER(%Leblon%)."
SET ANSWER MODE "sql"
BEGIN TALK
**BlingBot - Análise de Dados**
Exemplos de perguntas:
Produtos com estoque excessivo para transferência
Top 10 produtos vendidos em {loja} no {período}
Ticket médio da loja {nome}
Estoque disponível do produto {nome} na loja {loja}
Produtos para transferir de {origem} para {destino}
Estoque crítico na loja {nome}
Sugestão de compra para fornecedor {nome}
Pedidos por dia na loja {nome}
Total de produtos ativos no sistema
END TALK
BEGIN SYSTEM PROMPT
You are a data analyst for retail inventory management using Bling ERP.
Data available:
- AnaliseCompras table with stock by store (B=Barra, L=Leblon, R=Rio Sul)
- Products, Orders, Suppliers, Inventory tables
Analysis capabilities:
- Stock optimization and transfer suggestions
- Sales performance by store and period
- Average ticket calculation
- Critical stock alerts
- Purchase recommendations
Always use LOWER() for text comparisons in SQL.
Use LIKE with %% for partial matches.
Return actionable insights with specific quantities and locations.
END SYSTEM PROMPT

View file

@ -0,0 +1,7 @@
SET SCHEDULE "0 0 21 * * *"
DESCRIPTION "Refresh data analysis context for LLM"
REFRESH "data-analysis"
TALK "Data analysis context refreshed."

View file

@ -0,0 +1,36 @@
ADD TOOL "add-stock"
ADD TOOL "sync-erp"
ADD TOOL "sync-inventory"
ADD TOOL "sync-accounts"
ADD TOOL "sync-suppliers"
ADD TOOL "data-analysis"
ADD TOOL "refresh-llm"
CLEAR SUGGESTIONS
ADD SUGGESTION "estoque" AS "Consultar estoque"
ADD SUGGESTION "pedido" AS "Fazer pedido"
ADD SUGGESTION "sync" AS "Sincronizar ERP"
ADD SUGGESTION "analise" AS "Análise de dados"
BEGIN TALK
**BlingBot** - Assistente ERP
Olá! Posso ajudar com:
📦 Consulta de estoque
🛒 Pedidos e vendas
🔄 Sincronização com Bling
📊 Análise de dados
Qual o seu pedido?
END TALK
BEGIN SYSTEM PROMPT
Você é um assistente de loja integrado ao Bling ERP.
Ao receber pedido, ofereça opções de cor e tamanho do JSON de produtos.
Retorne JSON do pedido com itens e nome do cliente.
Mantenha itensPedido com apenas um item por vez.
Use o mesmo id do JSON de produtos para correlação.
ItensAcompanhamento contém itens adicionais do pedido (ex: Quadro com Caixa de Giz).
END SYSTEM PROMPT

View file

@ -0,0 +1,78 @@
SET SCHEDULE "0 0 0 */2 * *"
pageVariable = "pagina"
limitVariable = "limite"
syncLimit = 100
' Contas a Receber
SEND EMAIL admin, "Syncing Accounts Receivable..."
page = 1
totalReceber = 0
DO WHILE page > 0 AND page <= pages
url = host + "/contas/receber?" + pageVariable + "=" + page + "&" + limitVariable + "=" + syncLimit
res = GET url
WAIT 0.33
IF res.data THEN
items = res.data
itemCount = UBOUND(items)
IF itemCount > 0 THEN
MERGE "maria.ContasAReceber" WITH items BY "Id"
totalReceber = totalReceber + itemCount
page = page + 1
IF itemCount < syncLimit THEN
page = 0
END IF
ELSE
page = 0
END IF
ELSE
page = 0
END IF
res = null
items = null
LOOP
SEND EMAIL admin, "Accounts Receivable: " + totalReceber + " records."
' Contas a Pagar
SEND EMAIL admin, "Syncing Accounts Payable..."
page = 1
totalPagar = 0
DO WHILE page > 0 AND page <= pages
url = host + "/contas/pagar?" + pageVariable + "=" + page + "&" + limitVariable + "=" + syncLimit
res = GET url
WAIT 0.33
IF res.data THEN
items = res.data
itemCount = UBOUND(items)
IF itemCount > 0 THEN
MERGE "maria.ContasAPagar" WITH items BY "Id"
totalPagar = totalPagar + itemCount
page = page + 1
IF itemCount < syncLimit THEN
page = 0
END IF
ELSE
page = 0
END IF
ELSE
page = 0
END IF
res = null
items = null
LOOP
SEND EMAIL admin, "Accounts Payable: " + totalPagar + " records."
SEND EMAIL admin, "Accounts sync completed. Total: " + (totalReceber + totalPagar) + " records."

View file

@ -0,0 +1,318 @@
SET SCHEDULE "0 30 22 * * *"
daysToSync = -7
ontem = DATEADD today, "days", daysToSync
ontem = FORMAT ontem, "yyyy-MM-dd"
tomorrow = DATEADD today, "days", 1
tomorrow = FORMAT tomorrow, "yyyy-MM-dd"
dateFilter = "&dataAlteracaoInicial=${ontem}&dataAlteracaoFinal=${tomorrow}"
SEND EMAIL admin, "Sync: ${ontem} to ${tomorrow} started..."
' Produtos
i = 1
SEND EMAIL admin, "Syncing Products..."
DO WHILE i > 0 AND i < pages
res = GET host + "/produtos?pagina=${i}&criterio=5&tipo=P&limite=${limit}${dateFilter}"
WAIT 0.33
list = res.data
res = null
prd1 = ""
j = 0
k = 0
items = NEW ARRAY
DO WHILE j < ubound(list)
produto_id = list[j].id
res = GET host + "/produtos/${produto_id}"
WAIT 0.33
produto = res.data
res = null
IF produto.codigo && produto.codigo.trim().length THEN
prd1 = prd1 + "&idsProdutos%5B%5D=" + list[j].id
items[k] = produto
produto.sku = items[k].codigo
IF produto.variacoes.length > 0 THEN
produto.hierarquia = "p"
ELSE
produto.hierarquia = "s"
END IF
produtoDB = FIND "maria.Produtos", "sku=" + produto.codigo
IF produtoDB THEN
IF produtoDB.preco <> produto.preco THEN
hist = NEW OBJECT
hist.sku = produto.sku
hist.precoAntigo = produtoDB.preco
hist.precoAtual = produto.preco
hist.produto_id = produto.id
hist.dataModificado = FORMAT today, "yyyy-MM-dd"
SAVE "maria.HistoricoPreco", hist
hist = null
END IF
END IF
k = k + 1
END IF
j = j + 1
LOOP
list = null
list = items
MERGE "maria.Produtos" WITH list BY "Id"
list = items
j = 0
DO WHILE j < ubound(list)
listV = list[j].variacoes
IF listV THEN
k = 0
prd2 = ""
DO WHILE k < ubound(listV)
IF listV[k].codigo && listV[k].codigo.trim().length THEN
listV[k].skuPai = list[j].sku
listV[k].sku = listV[k].codigo
listV[k].hierarquia = "f"
k = k + 1
ELSE
listV.splice(k, 1)
END IF
LOOP
k = 0
DO WHILE k < ubound(listV)
listV[k].hierarquia = 'f'
DELETE "maria.ProdutoImagem", "sku=" + listV[k].sku
images = listV[k]?.midia?.imagens?.externas
l = 0
DO WHILE l < ubound(images)
images[l].ordinal = k
images[l].sku = listV[k].sku
images[l].id = random()
l = l + 1
LOOP
SAVE "maria.ProdutoImagem", images
images = null
k = k + 1
LOOP
MERGE "maria.Produtos" WITH listV BY "Id"
END IF
listV = null
DELETE "maria.ProdutoImagem", "sku=" + list[j].sku
k = 0
images = list[j].midia?.imagens?.externas
DO WHILE k < ubound(images)
images[k].ordinal = k
images[k].sku = list[j].sku
images[k].id = random()
k = k + 1
LOOP
SAVE "maria.ProdutoImagem", images
j = j + 1
LOOP
i = i + 1
IF list?.length < limit THEN
i = 0
END IF
list = null
res = null
items = null
LOOP
SEND EMAIL admin, "Products completed."
RESET REPORT
' Pedidos
SEND EMAIL admin, "Syncing Orders..."
i = 1
DO WHILE i > 0 AND i < pages
res = GET host + "/pedidos/vendas?pagina=${i}&limite=${limit}${dateFilter}"
list = res.data
res = null
j = 0
fullList = []
DO WHILE j < ubound(list)
pedido_id = list[j].id
res = GET host + "/pedidos/vendas/${pedido_id}"
items = res.data.itens
k = 0
DO WHILE k < ubound(items)
items[k].pedido_id = pedido_id
items[k].sku = items[k].codigo
items[k].numero = list[j].numero
items[k].custo = items[k].valor / 2
k = k + 1
LOOP
MERGE "maria.PedidosItem" WITH items BY "Id"
items = res.data.parcelas
k = 0
DO WHILE k < ubound(items)
items[k].pedido_id = pedido_id
k = k + 1
LOOP
MERGE "maria.Parcela" WITH items BY "Id"
fullList[j] = res.data
res = null
j = j + 1
LOOP
MERGE "maria.Pedidos" WITH fullList BY "Id"
i = i + 1
IF list?.length < limit THEN
i = 0
END IF
list = null
res = null
LOOP
SEND EMAIL admin, "Orders completed."
' Common entities
pageVariable = "pagina"
limitVariable = "limite"
syncLimit = 100
' CategoriaReceita
SEND EMAIL admin, "Syncing CategoriaReceita..."
syncPage = 1
totalCategoria = 0
DO WHILE syncPage > 0 AND syncPage <= pages
syncUrl = host + "/categorias/receitas-despesas?" + pageVariable + "=" + syncPage + "&" + limitVariable + "=" + syncLimit
syncRes = GET syncUrl
WAIT 0.33
IF syncRes.data THEN
syncItems = syncRes.data
syncCount = UBOUND(syncItems)
IF syncCount > 0 THEN
MERGE "maria.CategoriaReceita" WITH syncItems BY "Id"
totalCategoria = totalCategoria + syncCount
syncPage = syncPage + 1
IF syncCount < syncLimit THEN
syncPage = 0
END IF
ELSE
syncPage = 0
END IF
ELSE
syncPage = 0
END IF
syncRes = null
syncItems = null
LOOP
SEND EMAIL admin, "CategoriaReceita: " + totalCategoria + " records."
' FormaDePagamento
SEND EMAIL admin, "Syncing Payment Methods..."
syncPage = 1
totalForma = 0
DO WHILE syncPage > 0 AND syncPage <= pages
syncUrl = host + "/formas-pagamentos?" + pageVariable + "=" + syncPage + "&" + limitVariable + "=" + syncLimit
syncRes = GET syncUrl
WAIT 0.33
IF syncRes.data THEN
syncItems = syncRes.data
syncCount = UBOUND(syncItems)
IF syncCount > 0 THEN
MERGE "maria.FormaDePagamento" WITH syncItems BY "Id"
totalForma = totalForma + syncCount
syncPage = syncPage + 1
IF syncCount < syncLimit THEN
syncPage = 0
END IF
ELSE
syncPage = 0
END IF
ELSE
syncPage = 0
END IF
syncRes = null
syncItems = null
LOOP
SEND EMAIL admin, "Payment Methods: " + totalForma + " records."
' Contatos
SEND EMAIL admin, "Syncing Contacts..."
i = 1
DO WHILE i > 0 AND i < pages
res = GET host + "/contatos?pagina=${i}&limite=${limit}${dateFilter}"
list = res.data
j = 0
items = NEW ARRAY
DO WHILE j < ubound(list)
contato_id = list[j].id
res = GET host + "/contatos/${contato_id}"
items[j] = res.data
WAIT 0.33
j = j + 1
LOOP
MERGE "maria.Contatos" WITH items BY "Id"
i = i + 1
IF list?.length < limit THEN
i = 0
END IF
list = null
res = null
LOOP
SEND EMAIL admin, "Contacts completed."
' Vendedores
SEND EMAIL admin, "Syncing Sellers..."
i = 1
DO WHILE i > 0 AND i < pages
res = GET host + "/vendedores?pagina=${i}&situacaoContato=T&limite=${limit}${dateFilter}"
list = res.data
j = 0
items = NEW ARRAY
DO WHILE j < ubound(list)
vendedor_id = list[j].id
res = GET host + "/vendedores/${vendedor_id}"
items[j] = res.data
WAIT 0.33
j = j + 1
LOOP
MERGE "maria.Vendedores" WITH items BY "Id"
i = i + 1
IF list?.length < limit THEN
i = 0
END IF
list = null
res = null
LOOP
SEND EMAIL admin, "Sellers completed."
SEND EMAIL admin, "ERP sync completed."

View file

@ -0,0 +1,60 @@
SET SCHEDULE "0 30 23 * * *"
SEND EMAIL admin, "Inventory sync started..."
fullList = FIND "maria.Produtos"
chunkSize = 100
startIndex = 0
DO WHILE startIndex < ubound(fullList)
list = mid(fullList, startIndex, chunkSize)
prd1 = ""
j = 0
items = NEW ARRAY
DO WHILE j < ubound(list)
produto_id = list[j].id
prd1 = prd1 + "&idsProdutos%5B%5D=" + produto_id
j = j + 1
LOOP
list = null
IF j > 0 THEN
res = GET host + "/estoques/saldos?${prd1}"
WAIT 0.33
items = res.data
res = null
k = 0
DO WHILE k < ubound(items)
depositos = items[k].depositos
pSku = FIND "maria.Produtos", "id=${items[k].produto.id}"
IF pSku THEN
prdSku = pSku.sku
DELETE "maria.Depositos", "Sku=" + prdSku
l = 0
DO WHILE l < ubound(depositos)
depositos[l].sku = prdSku
l = l + 1
LOOP
SAVE "maria.Depositos", depositos
depositos = null
END IF
pSku = null
k = k + 1
LOOP
items = null
END IF
startIndex = startIndex + chunkSize
items = null
LOOP
fullList = null
SEND EMAIL admin, "Inventory sync completed."

View file

@ -0,0 +1,62 @@
SET SCHEDULE "0 0 22 * * *"
DESCRIPTION "Sync product suppliers from Bling ERP to local database"
SEND EMAIL admin, "Suppliers sync started..."
FUNCTION SyncProdutoFornecedor(idProduto)
DELETE "maria.ProdutoFornecedor", "Produto_id=" + idProduto
i1 = 1
DO WHILE i1 > 0 AND i1 < pages
res = GET host + "/produtos/fornecedores?pagina=${i1}&limite=${limit}&idProduto=${idProduto}"
list1 = res.data
res = null
WAIT 0.33
j1 = 0
items1 = NEW ARRAY
DO WHILE j1 < ubound(list1)
produtoFornecedor_id = list1[j1].id
res = GET host + "/produtos/fornecedores/${produtoFornecedor_id}"
items1[j1] = res.data
res = null
WAIT 0.33
j1 = j1 + 1
LOOP
SAVE "maria.ProdutoFornecedor", items1
items1 = null
i1 = i1 + 1
IF list1?.length < limit THEN
i1 = 0
END IF
res = null
list1 = null
LOOP
END FUNCTION
fullList = FIND "maria.Produtos"
chunkSize = 100
startIndex = 0
DO WHILE startIndex < ubound(fullList)
list = mid(fullList, startIndex, chunkSize)
j = 0
DO WHILE j < ubound(list)
produto_id = list[j].id
CALL SyncProdutoFornecedor(produto_id)
j = j + 1
LOOP
list = null
startIndex = startIndex + chunkSize
LOOP
fullList = null
SEND EMAIL admin, "Suppliers sync completed."

View file

@ -0,0 +1,284 @@
TABLE Contatos ON maria
Id number key
Nome string(150)
Codigo string(50)
Situacao string(5)
NumeroDocumento string(25)
Telefone string(20)
Celular string(20)
Fantasia string(150)
Tipo string(5)
IndicadorIe string(5)
Ie string(22)
Rg string(22)
OrgaoEmissor string(22)
Email string(50)
Endereco_geral_endereco string(100)
Endereco_geral_cep string(10)
Endereco_geral_bairro string(50)
Endereco_geral_municipio string(50)
Endereco_geral_uf string(5)
Endereco_geral_numero string(15)
Endereco_geral_complemento string(50)
Cobranca_endereco string(100)
Cobranca_cep string(10)
Cobranca_bairro string(50)
Cobranca_municipio string(50)
Cobranca_uf string(5)
Cobranca_numero string(15)
Cobranca_complemento string(50)
Vendedor_id number
DadosAdicionais_dataNascimento date
DadosAdicionais_sexo string(5)
DadosAdicionais_naturalidade string(25)
Financeiro_limiteCredito double
Financeiro_condicaoPagamento string(20)
Financeiro_categoria_id number
Pais_nome string(100)
END TABLE
TABLE Pedidos ON maria
Id number key
Numero integer
NumeroLoja string(15)
Data date
DataSaida date
DataPrevista date
TotalProdutos double
Desconto_valor double
Desconto_unidade string(15)
Contato_id number
Total double
Contato_nome string(150)
Contato_tipoPessoa string(1)
Contato_numeroDocumento string(20)
Situacao_id integer
Situacao_valor double
Loja_id integer
Vendedor_id number
NotaFiscal_id number
END TABLE
TABLE PedidosItem ON maria
Id number key
Numero integer
Sku string(20)
Unidade string(8)
Quantidade integer
Desconto double
Valor double
Custo double
AliquotaIPI double
Descricao string(255)
DescricaoDetalhada string(250)
Produto_id number
Pedido_id number
END TABLE
TABLE ProdutoImagem ON maria
Id number key
Ordinal number
Sku string(20)
Link string(250)
END TABLE
TABLE Produtos ON maria
Id number key
Nome string(150)
Sku string(20)
SkuPai string(20)
Preco double
Tipo string(1)
Situacao string(1)
Formato string(1)
Hierarquia string(1)
DescricaoCurta string(4000)
DataValidade date
Unidade string(5)
PesoLiquido double
PesoBruto double
Volumes integer
ItensPorCaixa integer
Gtin string(50)
GtinEmbalagem string(50)
TipoProducao string(5)
Condicao integer
FreteGratis boolean
Marca string(100)
DescricaoComplementar string(4000)
LinkExterno string(255)
Observacoes string(255)
Categoria_id integer
Estoque_minimo integer
Estoque_maximo integer
Estoque_crossdocking integer
Estoque_localizacao string(50)
ActionEstoque string(50)
Dimensoes_largura double
Dimensoes_altura double
Dimensoes_profundidade double
Dimensoes_unidadeMedida double
Tributacao_origem integer
Tributacao_nFCI string(50)
Tributacao_ncm string(50)
Tributacao_cest string(50)
Tributacao_codigoListaServicos string(50)
Tributacao_spedTipoItem string(50)
Tributacao_codigoItem string(50)
Tributacao_percentualTributos double
Tributacao_valorBaseStRetencao double
Tributacao_valorStRetencao double
Tributacao_valorICMSSubstituto double
Tributacao_codigoExcecaoTipi string(50)
Tributacao_classeEnquadramentoIpi string(50)
Tributacao_valorIpiFixo double
Tributacao_codigoSeloIpi string(50)
Tributacao_valorPisFixo double
Tributacao_valorCofinsFixo double
Tributacao_dadosAdicionais string(50)
GrupoProduto_id number
Midia_video_url string(255)
Midia_imagens_externas_0_link string(255)
LinhaProduto_id number
Estrutura_tipoEstoque string(5)
Estrutura_lancamentoEstoque string(5)
Estrutura_componentes_0_produto_id number
Estrutura_componentes_0_produto_Quantidade double
END TABLE
TABLE Depositos ON maria
Internal_Id number key
Id number
Sku string(20)
SaldoFisico double
SaldoVirtual double
END TABLE
TABLE Vendedores ON maria
Id number key
DescontoLimite double
Loja_Id number
Contato_Id number
Contato_Nome string(100)
Contato_Situacao string(1)
END TABLE
TABLE ProdutoFornecedor ON maria
Id number key
Descricao string(255)
Codigo string(50)
PrecoCusto double
PrecoCompra double
Padrao boolean
Produto_id number
Fornecedor_id number
Garantia integer
END TABLE
TABLE ContasAPagar ON maria
Id number key
Situacao integer
Vencimento date
Valor double
Contato_id number
FormaPagamento_id number
Saldo double
DataEmissao date
VencimentoOriginal date
NumeroDocumento string(50)
Competencia date
Historico string(255)
NumeroBanco string(10)
Portador_id number
Categoria_id number
Borderos string(255)
Ocorrencia_tipo integer
END TABLE
TABLE ContasAReceber ON maria
Id number key
Situacao integer
Vencimento date
Valor double
IdTransacao string(50)
LinkQRCodePix string(255)
LinkBoleto string(255)
DataEmissao date
Contato_id number
Contato_nome string(150)
Contato_numeroDocumento string(20)
Contato_tipo string(1)
FormaPagamento_id number
FormaPagamento_codigoFiscal integer
ContaContabil_id number
ContaContabil_descricao string(255)
Origem_id number
Origem_tipoOrigem string(20)
Origem_numero string(20)
Origem_dataEmissao date
Origem_valor double
Origem_situacao integer
Origem_url string(255)
Saldo double
VencimentoOriginal date
NumeroDocumento string(50)
Competencia date
Historico string(255)
NumeroBanco string(10)
Portador_id number
Categoria_id number
Vendedor_id number
Borderos string(255)
Ocorrencia_tipo integer
END TABLE
TABLE CategoriaReceita ON maria
Id number key
IdCategoriaPai number
Descricao string(255)
Tipo integer
Situacao integer
END TABLE
TABLE FormaDePagamento ON maria
Id number key
Descricao string(255)
TipoPagamento integer
Situacao integer
Fixa boolean
Padrao integer
Finalidade integer
Condicao string(10)
Destino integer
Taxas_aliquota double
Taxas_valor double
Taxas_prazo integer
DadosCartao_bandeira integer
DadosCartao_tipo integer
DadosCartao_cnpjCredenciadora string(16)
END TABLE
TABLE NaturezaDeOperacao ON maria
Id number key
Situacao integer
Padrao integer
Descricao string(255)
END TABLE
TABLE Parcela ON maria
Id number key
Pedido_id number
DataVencimento date
Valor double
Observacoes string(255)
FormaPagamento_id number
END TABLE
TABLE HistoricoPreco ON maria
Id number key
Sku string(50)
PrecoAntigo double
PrecoAtual double
Produto_id number
DataModificado date
END TABLE

View file

@ -0,0 +1,133 @@
# Bling ERP Integration Guide
## Overview
Bling is a Brazilian ERP (Enterprise Resource Planning) system designed for small and medium businesses. This bot integrates with Bling to provide inventory management, order processing, and data synchronization capabilities.
## Features
### Inventory Management
The bot can help you with:
- **Stock Consultation**: Check current inventory levels for any product
- **Stock Adjustments**: Add or remove items from inventory
- **Low Stock Alerts**: Get notified when products fall below minimum levels
- **Multi-warehouse Support**: Track inventory across multiple locations
### Order Processing
- **Create Orders**: Process new sales orders through conversation
- **Order Status**: Check the status of existing orders
- **Product Options**: Select colors, sizes, and variants when ordering
- **Accompanying Items**: Add related products to orders (e.g., adding a chalk box with a chalkboard)
### Data Synchronization
- **Sync ERP**: Synchronize all data with Bling
- **Sync Inventory**: Update inventory levels from Bling
- **Sync Accounts**: Synchronize customer and supplier accounts
- **Sync Suppliers**: Update supplier information
### Data Analysis
- **Sales Reports**: Generate sales reports and insights
- **Inventory Analysis**: Analyze stock movement patterns
- **Performance Metrics**: View key business indicators
## Getting Started
### Prerequisites
Before using the Bling integration, ensure you have:
1. An active Bling account
2. API credentials configured
3. Products registered in Bling
### Common Commands
| Action | Example |
|--------|---------|
| Check stock | "Consultar estoque do produto X" |
| Place order | "Fazer pedido" |
| Sync data | "Sincronizar ERP" |
| Data analysis | "Análise de dados" |
## Product Selection
When placing an order, the bot will:
1. Show available products from the JSON catalog
2. Offer color and size options when applicable
3. Allow selection of accompanying items
4. Confirm the order with customer name and items
## Order Structure
Orders contain:
- **Customer Name**: Who is placing the order
- **Order Items**: Main products selected (one item at a time)
- **Accompanying Items**: Additional related products
- **Product ID**: Matches the JSON product catalog for correlation
## Frequently Asked Questions
**Q: How do I check if a product is in stock?**
A: Ask "Consultar estoque" and provide the product name or code.
**Q: How do I synchronize data with Bling?**
A: Say "Sincronizar ERP" or select the sync option from suggestions.
**Q: Can I place orders for multiple items?**
A: Yes, but items are added one at a time. The bot will ask if you want to add more items.
**Q: How often should I sync inventory?**
A: It's recommended to sync at least daily, or after significant sales activity.
**Q: What if a product shows different stock in Bling vs. the bot?**
A: Run a full inventory sync to update the bot's data from Bling.
## Troubleshooting
### Connection Issues
If you experience connection problems:
1. Verify API credentials are correct
2. Check that Bling services are online
3. Retry the sync operation
### Stock Discrepancies
If stock levels don't match:
1. Run "Sincronizar estoque"
2. Check for pending orders in Bling
3. Verify no manual adjustments were made outside the system
### Order Failures
If an order fails to process:
1. Verify product availability
2. Check customer information is complete
3. Ensure Bling API is responding
4. Review error logs for details
## Best Practices
1. **Regular Sync**: Sync data at the start of each business day
2. **Stock Verification**: Verify stock before confirming large orders
3. **Complete Information**: Always provide complete customer details
4. **Order Confirmation**: Review orders before final submission
5. **Data Backup**: Regularly export data for backup purposes
## Support
For technical issues with the Bling integration:
- Check Bling API documentation
- Review General Bots logs for errors
- Contact your system administrator

View file

@ -0,0 +1,25 @@
name,value
,
bot-name,Bling ERP Integration
bot-description,Synchronizes data with Bling ERP system
,
param-blingClientID,
param-blingClientSecret,
param-blingHost,https://api.bling.com.br/Api/v3
param-blingTenant,
,
param-host,https://api.bling.com.br/Api/v3
param-limit,100
param-pages,50
,
param-admin1,admin@yourdomain.com
param-admin2,admin2@yourdomain.com
,
llm-model,gpt-4o-mini
llm-temperature,0.3
,
sync-interval,21600
sync-products,true
sync-orders,true
sync-contacts,true
sync-inventory,true
1 name value
2
3 bot-name Bling ERP Integration
4 bot-description Synchronizes data with Bling ERP system
5
6 param-blingClientID
7 param-blingClientSecret
8 param-blingHost https://api.bling.com.br/Api/v3
9 param-blingTenant
10
11 param-host https://api.bling.com.br/Api/v3
12 param-limit 100
13 param-pages 50
14
15 param-admin1 admin@yourdomain.com
16 param-admin2 admin2@yourdomain.com
17
18 llm-model gpt-4o-mini
19 llm-temperature 0.3
20
21 sync-interval 21600
22 sync-products true
23 sync-orders true
24 sync-contacts true
25 sync-inventory true

View file

@ -0,0 +1,51 @@
PARAM message AS STRING LIKE "Hello {name}, how are you?" DESCRIPTION "Message to broadcast, supports {name} and {mobile} variables"
PARAM listfile AS STRING LIKE "broadcast.csv" DESCRIPTION "CSV file with contacts (name, mobile columns)"
PARAM filter AS STRING LIKE "status=active" DESCRIPTION "Filter condition for contact list" OPTIONAL
DESCRIPTION "Send broadcast message to a list of contacts from CSV file"
IF NOT listfile THEN
listfile = "broadcast.csv"
END IF
IF filter THEN
list = FIND listfile, filter
ELSE
list = FIND listfile
END IF
IF UBOUND(list) = 0 THEN
TALK "No contacts found in " + listfile
RETURN 0
END IF
index = 1
sent = 0
DO WHILE index < UBOUND(list)
row = list[index]
msg = REPLACE(message, "{name}", row.name)
msg = REPLACE(msg, "{mobile}", row.mobile)
TALK TO row.mobile, msg
WAIT 5
WITH logEntry
timestamp = NOW()
user = USERNAME
from = FROM
mobile = row.mobile
name = row.name
status = "sent"
END WITH
SAVE "Log.xlsx", logEntry
sent = sent + 1
index = index + 1
LOOP
TALK "Broadcast sent to " + sent + " contacts."
RETURN sent

View file

@ -0,0 +1,122 @@
# Broadcast Messaging Guide
## Overview
The Broadcast feature allows you to send messages to multiple contacts simultaneously using WhatsApp or other messaging channels. This is ideal for announcements, marketing campaigns, and bulk notifications.
## How to Send a Broadcast
### Basic Broadcast
To send a broadcast message, you need:
1. A message template with optional personalization variables
2. A CSV file containing your contact list
### Message Variables
You can personalize messages using these variables:
- `{name}` - Replaced with the contact's name
- `{mobile}` - Replaced with the contact's phone number
**Example:**
```
Hello {name}, we have exciting news to share with you!
```
### Contact List Format
Your CSV file should have the following columns:
- `name` - Contact's name
- `mobile` - Phone number in international format (e.g., +5511999999999)
- Additional columns can be used for filtering
**Example broadcast.csv:**
```
name,mobile,status
John Smith,+5511999999999,active
Maria Garcia,+5521888888888,active
Carlos Santos,+5531777777777,inactive
```
## Filtering Contacts
You can filter your contact list using conditions:
- `status=active` - Only send to active contacts
- `region=south` - Filter by custom fields
- Multiple filters can be combined
## Best Practices
### Message Content
1. **Keep it concise** - Short messages have higher engagement
2. **Personalize** - Use `{name}` to make messages feel personal
3. **Clear call-to-action** - Tell recipients what to do next
4. **Timing** - Send during appropriate business hours
### Contact Management
1. **Clean your list** - Remove invalid numbers regularly
2. **Respect opt-outs** - Remove contacts who don't want messages
3. **Update regularly** - Keep contact information current
4. **Segment audiences** - Use filters for targeted messaging
### Compliance
1. **Get consent** - Only message contacts who opted in
2. **Identify yourself** - Make clear who is sending the message
3. **Provide opt-out** - Include instructions to unsubscribe
4. **Follow local laws** - LGPD, GDPR, TCPA requirements apply
## Rate Limits
To prevent spam detection and ensure delivery:
- Messages are sent with a 5-second delay between each
- WhatsApp Business API limits apply
- Large broadcasts may take time to complete
## Logging and Tracking
All broadcast operations are logged to `Log.xlsx` with:
- Timestamp
- User who initiated the broadcast
- Recipient mobile number
- Recipient name
- Delivery status
## Troubleshooting
### Messages Not Sending
- Verify phone numbers are in international format
- Check that the CSV file exists and has correct columns
- Ensure the bot has messaging permissions
### Some Contacts Skipped
- Contact may have blocked the number
- Phone number format may be incorrect
- WhatsApp account may not exist for that number
### Slow Delivery
- Large lists take time due to rate limiting
- This is intentional to prevent spam flags
- Check Log.xlsx for progress
## Frequently Asked Questions
**Q: How many contacts can I message at once?**
A: There's no hard limit, but larger lists will take longer due to rate limiting.
**Q: Can I schedule broadcasts for later?**
A: Yes, use scheduled jobs to set up future broadcasts.
**Q: Will I know if messages were delivered?**
A: The log file tracks send status. Delivery confirmation depends on the messaging platform.
**Q: Can I send images or files?**
A: The basic broadcast sends text. For media, use dedicated media broadcast tools.
**Q: How do I stop a broadcast in progress?**
A: Contact an administrator to stop the process if needed.

View file

@ -0,0 +1,174 @@
# HIPAA Medical Privacy Template
A HIPAA-compliant healthcare privacy portal template for General Bots.
## Overview
This template provides healthcare organizations with a ready-to-deploy patient privacy rights management system that complies with:
- **HIPAA** (Health Insurance Portability and Accountability Act)
- **HITECH Act** (Health Information Technology for Economic and Clinical Health)
- State-specific healthcare privacy regulations
## Features
### Patient Rights Management
1. **Access Medical Records** - Patients can request copies of their Protected Health Information (PHI)
2. **Request Amendments** - Patients can request corrections to their medical records
3. **Accounting of Disclosures** - Track and report who has accessed patient PHI
4. **Request Restrictions** - Allow patients to limit how their PHI is used or shared
5. **Confidential Communications** - Patients can specify preferred contact methods
6. **File Privacy Complaints** - Streamlined complaint submission process
7. **Revoke Authorizations** - Withdraw previous consent for PHI disclosure
### HIPAA Compliance Features
- **Audit Trail** - Complete logging of all PHI access and requests
- **Encryption** - AES-256 at rest, TLS 1.3 in transit
- **Access Controls** - Role-based access control (RBAC)
- **Break Glass** - Emergency access procedures with audit
- **Minimum Necessary** - Automatic enforcement of minimum necessary standard
- **PHI Detection** - Automatic detection and redaction of PHI in communications
- **Breach Notification** - Built-in breach response workflow
## Installation
1. Copy this template to your General Bots instance:
```bash
cp -r templates/hipaa-medical.gbai /path/to/your/bot/
```
2. Configure the bot settings in `hipaa.gbot/config.csv`:
```csv
Covered Entity Name,Your Healthcare Organization
Privacy Officer Email,privacy@yourhealthcare.org
HIPAA Security Officer,security@yourhealthcare.org
```
3. Deploy the template:
```bash
botserver --deploy hipaa-medical.gbai
```
## Configuration
### Required Settings
| Setting | Description | Example |
|---------|-------------|---------|
| `Covered Entity Name` | Your organization's legal name | Memorial Hospital |
| `Privacy Officer Email` | HIPAA Privacy Officer contact | privacy@hospital.org |
| `HIPAA Security Officer` | Security Officer contact | security@hospital.org |
| `Covered Entity NPI` | National Provider Identifier | 1234567890 |
### Security Settings
| Setting | Default | Description |
|---------|---------|-------------|
| `Require 2FA` | true | Two-factor authentication required |
| `Session Timeout` | 300 | Session timeout in seconds (5 minutes) |
| `Encryption At Rest` | AES-256 | Data encryption standard |
| `PHI Auto Redaction` | true | Automatically redact PHI in logs |
### Compliance Timelines
| Requirement | Deadline | Setting |
|-------------|----------|---------|
| Access Requests | 30 days | `Response SLA Hours` |
| Urgent Requests | 48 hours | `Urgent Response Hours` |
| Breach Notification | 60 hours | `Breach Notification Hours` |
## Dialogs
### Main Entry Point
- `start.bas` - Main menu for patient privacy rights
### Patient Rights Dialogs
- `access-phi.bas` - Request medical records
- `request-amendment.bas` - Request record corrections
- `accounting-disclosures.bas` - View access history
- `request-restrictions.bas` - Limit PHI use/sharing
- `confidential-communications.bas` - Set contact preferences
- `file-complaint.bas` - Submit privacy complaints
- `revoke-authorization.bas` - Withdraw consent
## Integration
### Patient Portal Integration
Connect to your existing patient portal:
```basic
' In your custom dialog
patient = GET PATIENT FROM "portal" WHERE mrn = patient_mrn
IF patient.verified THEN
CALL "access-phi.bas"
END IF
```
### EHR Integration
The template can integrate with common EHR systems:
- Epic
- Cerner
- Meditech
- Allscripts
Configure your EHR connection in the bot settings or use the FHIR API for standard integration.
## Audit Requirements
All interactions are logged to the `hipaa_audit_log` table with:
- Timestamp
- Session ID
- Action performed
- User/patient identifier
- IP address
- User agent
- Outcome
Retain audit logs for a minimum of 6 years (2,190 days) per HIPAA requirements.
## Customization
### Adding Custom Dialogs
Create new `.bas` files in the `hipaa.gbdialog` folder:
```basic
' custom-workflow.bas
TALK "Starting custom HIPAA workflow..."
' Your custom logic here
```
### Branding
Customize the welcome message and organization details in `config.csv`.
## Support
For questions about this template:
- **Documentation**: See General Bots docs
- **Issues**: GitHub Issues
- **HIPAA Guidance**: consult your compliance officer
## Disclaimer
This template is provided as a compliance aid and does not constitute legal advice. Healthcare organizations are responsible for ensuring their HIPAA compliance program meets all regulatory requirements. Consult with healthcare compliance professionals and legal counsel.
## License
AGPL-3.0 - See LICENSE file in the main repository.
---
Built with ❤️ by Pragmatismo

View file

@ -0,0 +1,88 @@
' =============================================================================
' HIPAA Medical Privacy Portal - Main Dialog
' General Bots Template for Healthcare Data Protection
' =============================================================================
' This template helps healthcare organizations comply with:
' - HIPAA (Health Insurance Portability and Accountability Act)
' - HITECH Act (Health Information Technology for Economic and Clinical Health)
' - State-specific healthcare privacy regulations
' =============================================================================
TALK "🏥 Welcome to the HIPAA Privacy Portal"
TALK "I can help you manage your Protected Health Information (PHI) rights."
TALK ""
TALK "Under HIPAA, you have the following rights:"
TALK ""
TALK "1⃣ **Access Your Medical Records** - Request copies of your health information"
TALK "2⃣ **Request Amendments** - Correct errors in your medical records"
TALK "3⃣ **Accounting of Disclosures** - See who has accessed your PHI"
TALK "4⃣ **Request Restrictions** - Limit how we use or share your information"
TALK "5⃣ **Confidential Communications** - Choose how we contact you"
TALK "6⃣ **File a Privacy Complaint** - Report a privacy concern"
TALK "7⃣ **Revoke Authorization** - Withdraw previous consent for PHI disclosure"
HEAR choice AS "What would you like to do? (1-7 or describe your request)"
SELECT CASE choice
CASE "1", "access", "records", "medical records", "view", "copy"
CALL "access-phi.bas"
CASE "2", "amend", "amendment", "correct", "correction", "fix", "error"
CALL "request-amendment.bas"
CASE "3", "accounting", "disclosures", "who accessed", "access log"
CALL "accounting-disclosures.bas"
CASE "4", "restrict", "restriction", "limit", "limitations"
CALL "request-restrictions.bas"
CASE "5", "communications", "contact", "how to contact", "confidential"
CALL "confidential-communications.bas"
CASE "6", "complaint", "report", "privacy concern", "violation"
CALL "file-complaint.bas"
CASE "7", "revoke", "withdraw", "cancel authorization"
CALL "revoke-authorization.bas"
CASE ELSE
' Use LLM to understand medical privacy requests
SET CONTEXT "You are a HIPAA compliance assistant. Classify the user's request into one of these categories: access_records, amendment, disclosures, restrictions, communications, complaint, revoke. Only respond with the category name."
intent = LLM "Classify this healthcare privacy request: " + choice
SELECT CASE intent
CASE "access_records"
CALL "access-phi.bas"
CASE "amendment"
CALL "request-amendment.bas"
CASE "disclosures"
CALL "accounting-disclosures.bas"
CASE "restrictions"
CALL "request-restrictions.bas"
CASE "communications"
CALL "confidential-communications.bas"
CASE "complaint"
CALL "file-complaint.bas"
CASE "revoke"
CALL "revoke-authorization.bas"
CASE ELSE
TALK "I'm not sure I understood your request."
TALK "Please select a number from 1-7 or contact our Privacy Officer directly."
TALK ""
TALK "📞 Privacy Officer: privacy@healthcare.org"
TALK "📧 Email: hipaa-requests@healthcare.org"
CALL "start.bas"
END SELECT
END SELECT
' Log all interactions for HIPAA audit trail
INSERT INTO "hipaa_audit_log" VALUES {
"timestamp": NOW(),
"session_id": GET SESSION "id",
"action": "privacy_portal_access",
"choice": choice,
"ip_address": GET SESSION "client_ip",
"user_agent": GET SESSION "user_agent"
}

View file

@ -0,0 +1,63 @@
name,value
Bot Name,HIPAA Medical Privacy Center
Bot Description,Healthcare Data Protection and Patient Rights Management Bot
Bot Version,1.0.0
Bot Author,Pragmatismo
Bot License,AGPL-3.0
Bot Category,Healthcare Compliance
Bot Tags,hipaa;healthcare;phi;medical;compliance;privacy;patient-rights
Default Language,en
Supported Languages,en;es;pt
Welcome Message,Welcome to the Healthcare Privacy Center. I can help you with your patient rights under HIPAA, including accessing your medical records, requesting amendments, and managing your health information privacy.
Error Message,I apologize, but I encountered an issue processing your request. For urgent matters, please contact our Privacy Officer directly at privacy@healthcare.org
Timeout Message,Your session has timed out for security. Please start a new conversation. This is required to protect your health information.
Session Timeout,300
Max Retries,3
Log Level,info
Enable Audit Log,true
Audit Log Retention Days,2190
Require Authentication,true
Require Email Verification,true
Require 2FA,true
Data Retention Days,2190
Auto Delete Completed Requests,false
Send Confirmation Emails,true
Privacy Officer Email,privacy@healthcare.org
HIPAA Privacy Officer,hipaa-officer@healthcare.org
HIPAA Security Officer,security-officer@healthcare.org
Covered Entity Name,Your Healthcare Organization
Covered Entity Address,123 Medical Center Drive
Covered Entity NPI,1234567890
Compliance Frameworks,HIPAA;HITECH;State-Privacy-Laws
Response SLA Hours,30
Urgent Response Hours,48
Escalation Email,compliance@healthcare.org
Enable HIPAA Mode,true
PHI Processing Enabled,true
PHI Detection Enabled,true
PHI Auto Redaction,true
Minimum Necessary Standard,true
Encryption At Rest,AES-256
Encryption In Transit,TLS-1.3
Access Control Model,RBAC
Break Glass Enabled,true
Break Glass Audit Required,true
Consent Required,true
Authorization Form Version,2.0
NPP Version,3.0
NPP Last Updated,2025-01-01
Designated Record Set,true
Accounting of Disclosures,true
Restriction Requests Enabled,true
Confidential Communications,true
Patient Portal URL,https://portal.healthcare.org
HIE Participation,true
E-Prescribing Enabled,true
Telehealth Enabled,true
BAA Required,true
Workforce Training Required,true
Training Frequency Days,365
Incident Response Plan,true
Breach Notification Hours,60
OCR Complaint URL,https://www.hhs.gov/hipaa/filing-a-complaint
State AG Contact,state-ag@state.gov
Can't render this file because it has a wrong number of fields in line 11.

View file

@ -0,0 +1,200 @@
# Privacy Rights Center Template (privacy.gbai)
A comprehensive LGPD/GDPR compliance template for General Bots that enables organizations to handle data subject rights requests automatically.
## Overview
This template provides a complete privacy portal that helps organizations comply with:
- **LGPD** (Lei Geral de Proteção de Dados - Brazil)
- **GDPR** (General Data Protection Regulation - EU)
- **CCPA** (California Consumer Privacy Act - US)
- **Other privacy regulations** with similar data subject rights
## Features
### Data Subject Rights Implemented
| Right | LGPD Article | GDPR Article | Dialog File |
|-------|--------------|--------------|-------------|
| Access | Art. 18 | Art. 15 | `request-data.bas` |
| Rectification | Art. 18 III | Art. 16 | `rectify-data.bas` |
| Erasure (Deletion) | Art. 18 VI | Art. 17 | `delete-data.bas` |
| Data Portability | Art. 18 V | Art. 20 | `export-data.bas` |
| Consent Management | Art. 8 | Art. 7 | `manage-consents.bas` |
| Object to Processing | Art. 18 IV | Art. 21 | `object-processing.bas` |
### Key Capabilities
- **Identity Verification** - Email-based verification codes before processing requests
- **Audit Trail** - Complete logging of all privacy requests for compliance
- **Multi-format Export** - JSON, CSV, XML export options for data portability
- **Consent Tracking** - Granular consent management with history
- **Email Notifications** - Automated confirmations and reports
- **SLA Tracking** - Response time monitoring (default: 72 hours)
## Installation
1. Copy the template to your bot's packages directory:
```bash
cp -r templates/privacy.gbai /path/to/your/bot/packages/
```
2. Configure the bot settings in `privacy.gbot/config.csv`:
```csv
name,value
Company Name,Your Company Name
Privacy Officer Email,privacy@yourcompany.com
DPO Contact,dpo@yourcompany.com
```
3. Restart General Bots to load the template.
## Configuration Options
### Required Settings
| Setting | Description | Example |
|---------|-------------|---------|
| `Company Name` | Your organization name | Acme Corp |
| `Privacy Officer Email` | Contact for privacy matters | privacy@acme.com |
| `DPO Contact` | Data Protection Officer | dpo@acme.com |
### Optional Settings
| Setting | Default | Description |
|---------|---------|-------------|
| `Session Timeout` | 900 | Session timeout in seconds |
| `Response SLA Hours` | 72 | Max hours to respond to requests |
| `Data Retention Days` | 30 | Days to retain completed request data |
| `Enable HIPAA Mode` | false | Enable PHI handling features |
| `Require 2FA` | false | Require two-factor authentication |
## File Structure
```
privacy.gbai/
├── README.md # This file
├── privacy.gbdialog/
│ ├── start.bas # Main entry point
│ ├── request-data.bas # Data access requests
│ ├── delete-data.bas # Data erasure requests
│ ├── export-data.bas # Data portability
│ └── manage-consents.bas # Consent management
├── privacy.gbot/
│ └── config.csv # Bot configuration
└── privacy.gbui/
└── index.html # Web portal UI
```
## Usage Examples
### Starting the Privacy Portal
Users can access the privacy portal by saying:
- "I want to access my data"
- "Delete my information"
- "Export my data"
- "Manage my consents"
- Or selecting options 1-6 from the menu
### API Integration
The template exposes REST endpoints for integration:
```
POST /api/privacy/request - Submit a new request
GET /api/privacy/requests - List user's requests
GET /api/privacy/request/:id - Get request status
POST /api/privacy/consent - Update consents
```
### Webhook Events
The template emits webhook events for integration:
- `privacy.request.created` - New request submitted
- `privacy.request.completed` - Request fulfilled
- `privacy.consent.updated` - Consent preferences changed
- `privacy.data.deleted` - User data erased
## Customization
### Adding Custom Consent Categories
Edit `manage-consents.bas` to add new consent categories:
```basic
consent_categories = [
{
"id": "custom_category",
"name": "Custom Category Name",
"description": "Description for users",
"required": FALSE,
"legal_basis": "Consent"
}
]
```
### Branding the UI
Modify `privacy.gbui/index.html` to match your branding:
- Update CSS variables for colors
- Replace logo and company name
- Add custom legal text
### Email Templates
Customize email notifications by editing the `SEND MAIL` blocks in each dialog file.
## Compliance Notes
### Response Deadlines
| Regulation | Standard Deadline | Extended Deadline |
|------------|-------------------|-------------------|
| LGPD | 15 days | - |
| GDPR | 30 days | 90 days (complex) |
| CCPA | 45 days | 90 days |
### Data Retention
Some data may need to be retained for legal compliance:
- Financial records (tax requirements)
- Legal dispute documentation
- Fraud prevention records
- Regulatory compliance data
The template handles this by anonymizing retained records while deleting identifiable information.
### Audit Requirements
All requests are logged to `privacy_requests` and `consent_history` tables with:
- Timestamp
- User identifier
- Request type
- IP address
- Completion status
- Legal basis
## Support
For questions about this template:
- **Documentation**: https://docs.pragmatismo.com.br/privacy-template
- **Issues**: https://github.com/GeneralBots/botserver/issues
- **Email**: support@pragmatismo.com.br
## License
This template is part of General Bots and is licensed under AGPL-3.0.
---
**Note**: This template provides technical implementation for privacy compliance. Organizations should consult with legal counsel to ensure full compliance with applicable regulations.

View file

@ -0,0 +1,213 @@
' Privacy Template - Data Deletion Request (Right to be Forgotten)
' LGPD Art. 18, GDPR Art. 17, HIPAA (where applicable)
' This dialog handles user requests to delete their personal data
TALK "Data Deletion Request"
TALK "I can help you exercise your right to have your personal data deleted."
TALK "This is also known as the 'Right to be Forgotten' under LGPD and GDPR."
' Authenticate the user first
TALK "For security purposes, I need to verify your identity before proceeding."
HEAR email AS EMAIL WITH "Please enter your registered email address:"
' Verify email exists in system
user = FIND "users.csv" WHERE email = email
IF user IS NULL THEN
TALK "I couldn't find an account with that email address."
TALK "Please check the email and try again, or contact support@company.com"
EXIT
END IF
' Send verification code
verification_code = RANDOM(100000, 999999)
SET BOT MEMORY "verification_" + email, verification_code
SET BOT MEMORY "verification_expiry_" + email, NOW() + 15 * 60
SEND MAIL email, "Data Deletion Verification Code", "
Your verification code is: " + verification_code + "
This code expires in 15 minutes.
If you did not request data deletion, please ignore this email and contact support immediately.
Pragmatismo Privacy Team
"
HEAR entered_code AS INTEGER WITH "I've sent a verification code to your email. Please enter it here:"
stored_code = GET BOT MEMORY "verification_" + email
IF entered_code <> stored_code THEN
TALK "Invalid verification code. Please try again."
EXIT
END IF
TALK "Identity verified."
TALK ""
TALK "What data would you like to delete?"
TALK ""
TALK "1. All my personal data (complete account deletion)"
TALK "2. Conversation history only"
TALK "3. Files and documents only"
TALK "4. Activity logs and analytics"
TALK "5. Specific data categories (I'll choose)"
TALK "6. Cancel this request"
HEAR deletion_choice AS INTEGER WITH "Please enter your choice (1-6):"
SELECT CASE deletion_choice
CASE 1
deletion_type = "complete"
TALK "Complete Account Deletion"
TALK "This will permanently delete:"
TALK "- Your user profile and account"
TALK "- All conversation history"
TALK "- All uploaded files and documents"
TALK "- All activity logs"
TALK "- All preferences and settings"
TALK ""
TALK "This action cannot be undone."
CASE 2
deletion_type = "conversations"
TALK "This will delete all your conversation history with our bots."
CASE 3
deletion_type = "files"
TALK "This will delete all files and documents you've uploaded."
CASE 4
deletion_type = "logs"
TALK "This will delete all activity logs and analytics data associated with you."
CASE 5
deletion_type = "selective"
TALK "Please specify which data categories you want deleted:"
HEAR categories WITH "Enter categories separated by commas (e.g., 'email history, phone number, address'):"
CASE 6
TALK "Request cancelled. No data has been deleted."
EXIT
CASE ELSE
TALK "Invalid choice. Please start over."
EXIT
END SELECT
' Explain data retention exceptions
TALK ""
TALK "Legal Notice:"
TALK "Some data may be retained for legal compliance purposes:"
TALK "- Financial records (tax requirements)"
TALK "- Legal dispute documentation"
TALK "- Fraud prevention records"
TALK "- Regulatory compliance data"
TALK ""
TALK "Retained data will be minimized and protected according to law."
HEAR reason WITH "Please briefly explain why you're requesting deletion (optional, press Enter to skip):"
HEAR confirmation WITH "Type 'DELETE MY DATA' to confirm this irreversible action:"
IF confirmation <> "DELETE MY DATA" THEN
TALK "Confirmation not received. Request cancelled for your protection."
EXIT
END IF
' Log the deletion request
request_id = "DEL-" + FORMAT(NOW(), "YYYYMMDD") + "-" + RANDOM(10000, 99999)
request_date = NOW()
' Create deletion request record
INSERT INTO "deletion_requests.csv", request_id, email, deletion_type, categories, reason, request_date, "pending"
' Process the deletion based on type
SELECT CASE deletion_type
CASE "complete"
' Delete from all tables
DELETE FROM "messages" WHERE user_email = email
DELETE FROM "files" WHERE owner_email = email
DELETE FROM "activity_logs" WHERE user_email = email
DELETE FROM "user_preferences" WHERE email = email
DELETE FROM "sessions" WHERE user_email = email
' Anonymize required retention records
UPDATE "audit_logs" SET user_email = "DELETED_USER_" + request_id WHERE user_email = email
' Mark user for deletion (actual deletion after retention period)
UPDATE "users" SET status = "pending_deletion", deletion_request_id = request_id WHERE email = email
CASE "conversations"
DELETE FROM "messages" WHERE user_email = email
DELETE FROM "sessions" WHERE user_email = email
CASE "files"
' Get file list for physical deletion
files = FIND "files" WHERE owner_email = email
FOR EACH file IN files
DELETE FILE file.path
NEXT
DELETE FROM "files" WHERE owner_email = email
CASE "logs"
DELETE FROM "activity_logs" WHERE user_email = email
' Anonymize audit logs (keep for compliance but remove PII)
UPDATE "audit_logs" SET user_email = "ANONYMIZED" WHERE user_email = email
CASE "selective"
' Process specific categories
TALK "Processing selective deletion for: " + categories
' Custom handling based on categories specified
INSERT INTO "manual_deletion_queue", request_id, email, categories, request_date
END SELECT
' Update request status
UPDATE "deletion_requests" SET status = "completed", completion_date = NOW() WHERE request_id = request_id
' Send confirmation email
SEND MAIL email, "Data Deletion Request Confirmed - " + request_id, "
Dear User,
Your data deletion request has been received and processed.
Request Details:
- Request ID: " + request_id + "
- Request Date: " + FORMAT(request_date, "YYYY-MM-DD HH:mm") + "
- Deletion Type: " + deletion_type + "
- Status: Completed
What happens next:
" + IF(deletion_type = "complete", "
- Your account will be fully deleted within 30 days
- You will receive a final confirmation email
- Some data may be retained for legal compliance (anonymized)
", "
- The specified data has been deleted from our systems
- Some backups may take up to 30 days to purge
") + "
Your Rights:
- You can request a copy of any retained data
- You can file a complaint with your data protection authority
- Contact us at privacy@company.com for questions
Under LGPD (Brazil) and GDPR (EU), you have the right to:
- Request confirmation of this deletion
- Lodge a complaint with supervisory authorities
- Seek judicial remedy if unsatisfied
Thank you for trusting us with your data.
Pragmatismo Privacy Team
Request Reference: " + request_id + "
"
TALK ""
TALK "Request Completed"
TALK ""
TALK "Your deletion request has been processed."
TALK "Request ID: " + request_id
TALK ""
TALK "A confirmation email has been sent to " + email
TALK ""
TALK "If you have questions, contact privacy@company.com"
TALK "Reference your Request ID in any communications."

View file

@ -0,0 +1,372 @@
' ============================================================================
' Privacy Template: Data Portability/Export Request
' LGPD Art. 18 V / GDPR Art. 20 - Right to Data Portability
' ============================================================================
' This dialog enables users to export their data in portable formats
' Supports JSON, CSV, and XML export for interoperability
TALK "📦 **Data Portability Request**"
TALK "You have the right to receive your personal data in a structured, commonly used, and machine-readable format."
TALK ""
' Verify user identity
TALK "First, I need to verify your identity."
HEAR email AS EMAIL WITH "Please enter your registered email address:"
user = FIND "users" WHERE email = email
IF user IS NULL THEN
TALK "❌ No account found with that email address."
TALK "Please check and try again, or contact support."
EXIT
END IF
' Send verification code
code = GENERATE CODE 6
SET SESSION "export_verification_code", code
SET SESSION "export_email", email
SEND MAIL email, "Data Export Request - Verification Code", "
Your verification code is: " + code + "
This code expires in 15 minutes.
If you did not request this data export, please ignore this email.
Pragmatismo Privacy Team
"
HEAR entered_code AS TEXT WITH "📧 Enter the verification code sent to your email:"
IF entered_code <> code THEN
TALK "❌ Invalid verification code. Please start over."
EXIT
END IF
TALK "✅ Identity verified!"
TALK ""
' Ask for export format
TALK "**Choose your export format:**"
TALK ""
TALK "1⃣ **JSON** - Best for importing into other systems"
TALK "2⃣ **CSV** - Best for spreadsheets (Excel, Google Sheets)"
TALK "3⃣ **XML** - Universal interchange format"
TALK "4⃣ **All formats** - Get all three formats in a ZIP file"
HEAR format_choice WITH "Enter your choice (1-4):"
SELECT CASE format_choice
CASE "1", "json", "JSON"
export_format = "json"
format_name = "JSON"
CASE "2", "csv", "CSV"
export_format = "csv"
format_name = "CSV"
CASE "3", "xml", "XML"
export_format = "xml"
format_name = "XML"
CASE "4", "all", "ALL"
export_format = "all"
format_name = "All Formats (ZIP)"
CASE ELSE
export_format = "json"
format_name = "JSON"
TALK "Defaulting to JSON format."
END SELECT
TALK ""
TALK "**Select data categories to export:**"
TALK ""
TALK "1⃣ Everything (complete data export)"
TALK "2⃣ Profile information only"
TALK "3⃣ Conversations and messages"
TALK "4⃣ Files and documents"
TALK "5⃣ Activity history"
TALK "6⃣ Custom selection"
HEAR data_choice WITH "Enter your choice (1-6):"
' Define what data to export based on choice
SELECT CASE data_choice
CASE "1"
include_profile = TRUE
include_conversations = TRUE
include_files = TRUE
include_activity = TRUE
include_consents = TRUE
data_scope = "complete"
CASE "2"
include_profile = TRUE
include_conversations = FALSE
include_files = FALSE
include_activity = FALSE
include_consents = TRUE
data_scope = "profile"
CASE "3"
include_profile = FALSE
include_conversations = TRUE
include_files = FALSE
include_activity = FALSE
include_consents = FALSE
data_scope = "conversations"
CASE "4"
include_profile = FALSE
include_conversations = FALSE
include_files = TRUE
include_activity = FALSE
include_consents = FALSE
data_scope = "files"
CASE "5"
include_profile = FALSE
include_conversations = FALSE
include_files = FALSE
include_activity = TRUE
include_consents = FALSE
data_scope = "activity"
CASE "6"
TALK "Select categories (yes/no for each):"
HEAR include_profile AS BOOLEAN WITH "Include profile information?"
HEAR include_conversations AS BOOLEAN WITH "Include conversations?"
HEAR include_files AS BOOLEAN WITH "Include files metadata?"
HEAR include_activity AS BOOLEAN WITH "Include activity logs?"
HEAR include_consents AS BOOLEAN WITH "Include consent records?"
data_scope = "custom"
CASE ELSE
include_profile = TRUE
include_conversations = TRUE
include_files = TRUE
include_activity = TRUE
include_consents = TRUE
data_scope = "complete"
END SELECT
TALK ""
TALK "🔄 Preparing your data export... This may take a few minutes."
TALK ""
' Gather the data
export_data = {}
request_id = "EXP-" + FORMAT(NOW(), "YYYYMMDD-HHmmss") + "-" + user.id
' Export metadata
export_data.metadata = {
"export_id": request_id,
"export_date": NOW(),
"format": format_name,
"data_scope": data_scope,
"legal_basis": "LGPD Art. 18 V / GDPR Art. 20",
"data_controller": "Your Organization Name",
"contact": "privacy@company.com"
}
' Gather profile data
IF include_profile THEN
profile = FIND "users" WHERE id = user.id
export_data.profile = {
"name": profile.name,
"email": profile.email,
"phone": profile.phone,
"address": profile.address,
"created_at": profile.created_at,
"last_login": profile.last_login,
"timezone": profile.timezone,
"language": profile.language,
"preferences": profile.preferences
}
TALK "✓ Profile data collected"
END IF
' Gather conversations
IF include_conversations THEN
messages = FIND "messages" WHERE user_id = user.id ORDER BY created_at
sessions = FIND "sessions" WHERE user_id = user.id
export_data.conversations = {
"total_sessions": COUNT(sessions),
"total_messages": COUNT(messages),
"sessions": sessions,
"messages": messages
}
TALK "✓ Conversation data collected (" + COUNT(messages) + " messages)"
END IF
' Gather files metadata
IF include_files THEN
files = FIND "user_files" WHERE user_id = user.id
file_list = []
FOR EACH file IN files
file_info = {
"filename": file.name,
"size": file.size,
"type": file.mime_type,
"uploaded_at": file.created_at,
"last_accessed": file.last_accessed,
"path": file.path
}
APPEND file_list, file_info
NEXT
export_data.files = {
"total_files": COUNT(files),
"total_size": SUM(files, "size"),
"file_list": file_list
}
TALK "✓ Files metadata collected (" + COUNT(files) + " files)"
END IF
' Gather activity logs
IF include_activity THEN
activity = FIND "activity_logs" WHERE user_id = user.id ORDER BY timestamp DESC LIMIT 10000
export_data.activity = {
"total_events": COUNT(activity),
"events": activity
}
TALK "✓ Activity logs collected (" + COUNT(activity) + " events)"
END IF
' Gather consent records
IF include_consents THEN
consents = FIND "user_consents" WHERE user_id = user.id
export_data.consents = {
"consent_records": consents,
"current_preferences": {
"marketing_emails": user.marketing_consent,
"analytics": user.analytics_consent,
"third_party_sharing": user.sharing_consent
}
}
TALK "✓ Consent records collected"
END IF
TALK ""
TALK "📁 Generating export files..."
' Generate export files based on format
timestamp = FORMAT(NOW(), "YYYYMMDD_HHmmss")
base_filename = "data_export_" + timestamp
SELECT CASE export_format
CASE "json"
filename = base_filename + ".json"
WRITE filename, JSON(export_data)
CASE "csv"
' Generate multiple CSV files for different data types
IF include_profile THEN
WRITE base_filename + "_profile.csv", CSV(export_data.profile)
END IF
IF include_conversations THEN
WRITE base_filename + "_messages.csv", CSV(export_data.conversations.messages)
END IF
IF include_files THEN
WRITE base_filename + "_files.csv", CSV(export_data.files.file_list)
END IF
IF include_activity THEN
WRITE base_filename + "_activity.csv", CSV(export_data.activity.events)
END IF
' Create ZIP of all CSVs
filename = base_filename + "_csv.zip"
COMPRESS filename, base_filename + "_*.csv"
CASE "xml"
filename = base_filename + ".xml"
WRITE filename, XML(export_data)
CASE "all"
' Generate all formats
WRITE base_filename + ".json", JSON(export_data)
WRITE base_filename + ".xml", XML(export_data)
IF include_profile THEN
WRITE base_filename + "_profile.csv", CSV(export_data.profile)
END IF
IF include_conversations THEN
WRITE base_filename + "_messages.csv", CSV(export_data.conversations.messages)
END IF
IF include_files THEN
WRITE base_filename + "_files.csv", CSV(export_data.files.file_list)
END IF
filename = base_filename + "_complete.zip"
COMPRESS filename, base_filename + ".*"
END SELECT
' Upload to secure storage
secure_path = "/secure/exports/" + user.id + "/"
UPLOAD filename TO secure_path
' Generate download link (expires in 7 days)
download_link = GENERATE SECURE LINK secure_path + filename EXPIRES 7 DAYS
' Log the export request for compliance
INSERT INTO "privacy_requests" VALUES {
"id": request_id,
"user_id": user.id,
"request_type": "data_portability",
"data_scope": data_scope,
"format": format_name,
"requested_at": NOW(),
"completed_at": NOW(),
"status": "completed",
"legal_basis": "LGPD Art. 18 V / GDPR Art. 20"
}
' Send email with download link
SEND MAIL email, "Your Data Export is Ready - " + request_id, "
Dear " + user.name + ",
Your data export request has been completed.
**Export Details:**
- Request ID: " + request_id + "
- Format: " + format_name + "
- Data Included: " + data_scope + "
- Generated: " + FORMAT(NOW(), "DD/MM/YYYY HH:mm") + "
**Download Your Data:**
" + download_link + "
This link expires in 7 days for security purposes.
**What's Included:**
" + IF(include_profile, " Profile information\n", "") + IF(include_conversations, " Conversation history\n", "") + IF(include_files, " Files metadata\n", "") + IF(include_activity, " Activity logs\n", "") + IF(include_consents, " Consent records\n", "") + "
**Your Rights Under LGPD/GDPR:**
- Import this data to another service provider
- Request data deletion after export
- Request additional data categories
- File a complaint with data protection authorities
If you have questions, contact privacy@company.com
Pragmatismo Privacy Team
"
TALK ""
TALK "✅ **Export Complete!**"
TALK ""
TALK "📧 A download link has been sent to: " + email
TALK ""
TALK "**Export Details:**"
TALK "• Request ID: " + request_id
TALK "• Format: " + format_name
TALK "• Link expires in: 7 days"
TALK ""
TALK "You can use this data to:"
TALK "• Import into another service"
TALK "• Keep a personal backup"
TALK "• Review what data we hold"
TALK ""
TALK "🔒 Need anything else?"
TALK "• Say **'delete my data'** to request deletion"
TALK "• Say **'privacy settings'** to manage consents"
TALK "• Say **'help'** for other options"

View file

@ -0,0 +1,333 @@
' ============================================================================
' Privacy Template: Consent Management
' LGPD Art. 8 / GDPR Art. 7 - Consent Management
' ============================================================================
' This dialog allows users to view, grant, and revoke their consents
' Essential for LGPD/GDPR compliance with granular consent tracking
TALK "🔐 **Consent Management Center**"
TALK "Here you can view and manage all your data processing consents."
TALK ""
' Verify user identity first
HEAR email AS EMAIL WITH "Please enter your registered email address:"
user = FIND "users" WHERE email = email
IF user IS NULL THEN
TALK "⚠️ We couldn't find an account with that email."
TALK "Please check the email address and try again."
EXIT
END IF
' Send quick verification
code = GENERATE CODE 6
SET SESSION "consent_verify_code", code
SET SESSION "consent_verify_email", email
SEND MAIL email, "Consent Management - Verification", "
Your verification code is: " + code + "
This code expires in 10 minutes.
Pragmatismo Privacy Team
"
HEAR entered_code AS TEXT WITH "📧 Enter the verification code sent to your email:"
IF entered_code <> code THEN
TALK "❌ Invalid code. Please try again."
EXIT
END IF
TALK "✅ Identity verified!"
TALK ""
' Load current consents
consents = FIND "user_consents" WHERE user_id = user.id
' Define consent categories
consent_categories = [
{
"id": "essential",
"name": "Essential Services",
"description": "Required for basic service functionality",
"required": TRUE,
"legal_basis": "Contract performance"
},
{
"id": "analytics",
"name": "Analytics & Improvement",
"description": "Help us improve our services through usage analysis",
"required": FALSE,
"legal_basis": "Legitimate interest / Consent"
},
{
"id": "marketing",
"name": "Marketing Communications",
"description": "Receive news, updates, and promotional content",
"required": FALSE,
"legal_basis": "Consent"
},
{
"id": "personalization",
"name": "Personalization",
"description": "Customize your experience based on preferences",
"required": FALSE,
"legal_basis": "Consent"
},
{
"id": "third_party",
"name": "Third-Party Sharing",
"description": "Share data with trusted partners for enhanced services",
"required": FALSE,
"legal_basis": "Consent"
},
{
"id": "ai_training",
"name": "AI Model Training",
"description": "Use anonymized data to improve AI capabilities",
"required": FALSE,
"legal_basis": "Consent"
}
]
TALK "📋 **Your Current Consents:**"
TALK ""
FOR EACH category IN consent_categories
current_consent = FILTER(consents, "category = '" + category.id + "'")
IF current_consent IS NOT NULL THEN
status = current_consent.granted ? "✅ Granted" : "❌ Denied"
granted_date = FORMAT(current_consent.updated_at, "DD/MM/YYYY")
ELSE
status = "⚪ Not Set"
granted_date = "N/A"
END IF
required_tag = category.required ? " (Required)" : ""
TALK category.name + required_tag + ": " + status
TALK " └─ " + category.description
TALK " └─ Legal basis: " + category.legal_basis
TALK " └─ Last updated: " + granted_date
TALK ""
NEXT
TALK "**What would you like to do?**"
TALK ""
TALK "1⃣ Grant a consent"
TALK "2⃣ Revoke a consent"
TALK "3⃣ Revoke ALL optional consents"
TALK "4⃣ Grant ALL consents"
TALK "5⃣ View consent history"
TALK "6⃣ Download consent record"
TALK "7⃣ Exit"
HEAR action AS INTEGER WITH "Enter your choice (1-7):"
SELECT CASE action
CASE 1
' Grant consent
TALK "Which consent would you like to grant?"
TALK "Available options: analytics, marketing, personalization, third_party, ai_training"
HEAR grant_category WITH "Enter consent category:"
' Validate category
valid_categories = ["analytics", "marketing", "personalization", "third_party", "ai_training"]
IF NOT CONTAINS(valid_categories, grant_category) THEN
TALK "❌ Invalid category. Please try again."
EXIT
END IF
' Record consent with full audit trail
consent_record = {
"user_id": user.id,
"category": grant_category,
"granted": TRUE,
"granted_at": NOW(),
"updated_at": NOW(),
"ip_address": GET SESSION "client_ip",
"user_agent": GET SESSION "user_agent",
"consent_version": "2.0",
"method": "explicit_dialog"
}
' Check if exists and update, otherwise insert
existing = FIND "user_consents" WHERE user_id = user.id AND category = grant_category
IF existing IS NOT NULL THEN
UPDATE "user_consents" SET granted = TRUE, updated_at = NOW(), method = "explicit_dialog" WHERE id = existing.id
ELSE
INSERT INTO "user_consents" VALUES consent_record
END IF
' Log to consent history
INSERT INTO "consent_history" VALUES {
"user_id": user.id,
"category": grant_category,
"action": "granted",
"timestamp": NOW(),
"ip_address": GET SESSION "client_ip"
}
TALK "✅ Consent for **" + grant_category + "** has been granted."
TALK "You can revoke this consent at any time."
CASE 2
' Revoke consent
TALK "Which consent would you like to revoke?"
TALK "Note: Essential services consent cannot be revoked while using the service."
HEAR revoke_category WITH "Enter consent category:"
IF revoke_category = "essential" THEN
TALK "⚠️ Essential consent is required for service operation."
TALK "To revoke it, you must delete your account."
EXIT
END IF
UPDATE "user_consents" SET granted = FALSE, updated_at = NOW(), method = "explicit_revoke" WHERE user_id = user.id AND category = revoke_category
INSERT INTO "consent_history" VALUES {
"user_id": user.id,
"category": revoke_category,
"action": "revoked",
"timestamp": NOW(),
"ip_address": GET SESSION "client_ip"
}
TALK "✅ Consent for **" + revoke_category + "** has been revoked."
TALK "This change takes effect immediately."
' Notify relevant systems
WEBHOOK POST "/internal/consent-changed" WITH {
"user_id": user.id,
"category": revoke_category,
"action": "revoked"
}
CASE 3
' Revoke all optional
TALK "⚠️ This will revoke ALL optional consents:"
TALK "• Analytics & Improvement"
TALK "• Marketing Communications"
TALK "• Personalization"
TALK "• Third-Party Sharing"
TALK "• AI Model Training"
HEAR confirm WITH "Type 'REVOKE ALL' to confirm:"
IF confirm <> "REVOKE ALL" THEN
TALK "Operation cancelled."
EXIT
END IF
UPDATE "user_consents" SET granted = FALSE, updated_at = NOW() WHERE user_id = user.id AND category <> "essential"
INSERT INTO "consent_history" VALUES {
"user_id": user.id,
"category": "ALL_OPTIONAL",
"action": "bulk_revoked",
"timestamp": NOW(),
"ip_address": GET SESSION "client_ip"
}
TALK "✅ All optional consents have been revoked."
CASE 4
' Grant all
TALK "This will grant consent for all categories."
TALK "You can revoke individual consents at any time."
HEAR confirm WITH "Type 'GRANT ALL' to confirm:"
IF confirm <> "GRANT ALL" THEN
TALK "Operation cancelled."
EXIT
END IF
FOR EACH category IN consent_categories
existing = FIND "user_consents" WHERE user_id = user.id AND category = category.id
IF existing IS NOT NULL THEN
UPDATE "user_consents" SET granted = TRUE, updated_at = NOW() WHERE id = existing.id
ELSE
INSERT INTO "user_consents" VALUES {
"user_id": user.id,
"category": category.id,
"granted": TRUE,
"granted_at": NOW(),
"updated_at": NOW(),
"method": "bulk_grant"
}
END IF
NEXT
INSERT INTO "consent_history" VALUES {
"user_id": user.id,
"category": "ALL",
"action": "bulk_granted",
"timestamp": NOW()
}
TALK "✅ All consents have been granted."
CASE 5
' View history
TALK "📜 **Your Consent History:**"
TALK ""
history = FIND "consent_history" WHERE user_id = user.id ORDER BY timestamp DESC LIMIT 20
IF COUNT(history) = 0 THEN
TALK "No consent history found."
ELSE
FOR EACH record IN history
action_icon = record.action CONTAINS "grant" ? "✅" : "❌"
TALK action_icon + " " + FORMAT(record.timestamp, "DD/MM/YYYY HH:mm") + " - " + record.category + " " + record.action
NEXT
END IF
CASE 6
' Download consent record
TALK "📥 Generating your consent record..."
consent_report = {
"generated_at": NOW(),
"user_email": email,
"current_consents": consents,
"consent_history": FIND "consent_history" WHERE user_id = user.id,
"legal_notice": "This document serves as proof of consent status under LGPD/GDPR"
}
filename = "consent_record_" + FORMAT(NOW(), "YYYYMMDD") + ".pdf"
GENERATE PDF filename WITH TEMPLATE "consent_report" DATA consent_report
SEND MAIL email, "Your Consent Record", "
Dear User,
Please find attached your complete consent record as requested.
This document includes:
- Current consent status for all categories
- Complete consent history with timestamps
- Legal basis for each processing activity
Keep this document for your records.
Pragmatismo Privacy Team
", ATTACHMENT filename
TALK "✅ Consent record has been sent to " + email
CASE 7
TALK "Thank you for managing your privacy preferences."
TALK "You can return here anytime to update your consents."
EXIT
CASE ELSE
TALK "Invalid choice. Please try again."
END SELECT
TALK ""
TALK "🔒 **Privacy Reminder:**"
TALK "• Your consents are stored securely"
TALK "• Changes take effect immediately"
TALK "• You can modify consents anytime"
TALK "• Contact privacy@company.com for questions"

View file

@ -0,0 +1,152 @@
' ============================================================================
' Privacy Template: Data Access Request (Subject Access Request - SAR)
' LGPD Art. 18 / GDPR Art. 15 - Right of Access
' ============================================================================
' This dialog handles user requests to access their personal data
' Companies can install this template for LGPD/GDPR compliance
TALK "Data Access Request"
TALK "You have the right to access all personal data we hold about you."
TALK ""
' Verify user identity
TALK "First, I need to verify your identity for security purposes."
HEAR email AS EMAIL WITH "Please provide your registered email address:"
' Check if email exists in system
user = FIND "users" WHERE email = email
IF user IS NULL THEN
TALK "We couldn't find an account with that email address."
TALK "Please check the email and try again, or contact support."
EXIT
END IF
' Send verification code
code = GENERATE CODE 6
SET SESSION "verification_code", code
SET SESSION "verified_email", email
SEND MAIL email, "Data Access Request - Verification Code", "
Your verification code is: " + code + "
This code expires in 15 minutes.
If you did not request this, please ignore this email.
"
HEAR entered_code AS TEXT WITH "We sent a verification code to your email. Please enter it:"
IF entered_code <> code THEN
TALK "Invalid verification code. Please start over."
EXIT
END IF
TALK "Identity verified successfully!"
TALK ""
' Gather all user data
TALK "Gathering your personal data... This may take a moment."
TALK ""
' Get user profile data
profile = FIND "users" WHERE email = email
sessions = FIND "sessions" WHERE user_id = profile.id
messages = FIND "messages" WHERE user_id = profile.id
files = FIND "user_files" WHERE user_id = profile.id
consents = FIND "user_consents" WHERE user_id = profile.id
audit_logs = FIND "audit_logs" WHERE user_id = profile.id
' Build comprehensive report
report_data = {
"request_date": NOW(),
"request_type": "Subject Access Request (SAR)",
"legal_basis": "LGPD Art. 18 / GDPR Art. 15",
"profile": {
"name": profile.name,
"email": profile.email,
"phone": profile.phone,
"created_at": profile.created_at,
"last_login": profile.last_login,
"preferences": profile.preferences
},
"sessions": {
"total_count": COUNT(sessions),
"active_sessions": FILTER(sessions, "status = 'active'"),
"session_history": sessions
},
"communications": {
"total_messages": COUNT(messages),
"messages": messages
},
"files": {
"total_files": COUNT(files),
"file_list": MAP(files, "name, size, created_at")
},
"consents": consents,
"activity_log": audit_logs
}
' Generate PDF report
report_filename = "data_access_report_" + FORMAT(NOW(), "YYYYMMDD_HHmmss") + ".pdf"
GENERATE PDF report_filename WITH TEMPLATE "data_access_report" DATA report_data
' Upload to user's secure area
UPLOAD report_filename TO "/secure/reports/" + profile.id + "/"
' Send report via email
SEND MAIL email, "Your Data Access Request - Complete Report", "
Dear " + profile.name + ",
As requested, please find attached a complete report of all personal data we hold about you.
This report includes:
- Your profile information
- Session history
- Communication records
- Files you have uploaded
- Consent records
- Activity logs
Report generated: " + FORMAT(NOW(), "DD/MM/YYYY HH:mm") + "
Your rights under LGPD/GDPR:
- Right to rectification (Art. 18 III LGPD / Art. 16 GDPR)
- Right to erasure (Art. 18 VI LGPD / Art. 17 GDPR)
- Right to data portability (Art. 18 V LGPD / Art. 20 GDPR)
- Right to object to processing (Art. 18 IV LGPD / Art. 21 GDPR)
To exercise any of these rights, please contact us or use our privacy portal.
Best regards,
Privacy & Compliance Team
", ATTACHMENT report_filename
' Log the request for compliance audit
INSERT INTO "privacy_requests" VALUES {
"user_id": profile.id,
"request_type": "data_access",
"requested_at": NOW(),
"completed_at": NOW(),
"status": "completed",
"legal_basis": "LGPD Art. 18 / GDPR Art. 15"
}
TALK "Request Complete!"
TALK ""
TALK "We have sent a comprehensive report to: " + email
TALK ""
TALK "The report includes:"
TALK "- Your profile information"
TALK "- " + COUNT(sessions) + " session records"
TALK "- " + COUNT(messages) + " message records"
TALK "- " + COUNT(files) + " files"
TALK "- Consent history"
TALK "- Activity logs"
TALK ""
TALK "You can also download the report from your account settings."
TALK ""
TALK "Your other privacy rights:"
TALK "- Say 'correct my data' to update your information"
TALK "- Say 'delete my data' to request data erasure"
TALK "- Say 'export my data' for portable format"
TALK "- Say 'privacy settings' to manage consents"

View file

@ -0,0 +1,51 @@
ADD TOOL "request-data"
ADD TOOL "export-data"
ADD TOOL "delete-data"
ADD TOOL "manage-consents"
ADD TOOL "rectify-data"
ADD TOOL "object-processing"
USE KB "privacy.gbkb"
CLEAR SUGGESTIONS
ADD SUGGESTION "access" AS "View my data"
ADD SUGGESTION "export" AS "Export my data"
ADD SUGGESTION "delete" AS "Delete my data"
ADD SUGGESTION "consents" AS "Manage consents"
ADD SUGGESTION "correct" AS "Correct my data"
ADD SUGGESTION "object" AS "Object to processing"
SET CONTEXT "privacy rights" AS "You are a Privacy Rights Center assistant helping users exercise their data protection rights under LGPD, GDPR, and CCPA. Help with data access, rectification, erasure, portability, and consent management."
BEGIN TALK
**Privacy Rights Center**
As a data subject, you have the following rights:
1. **Access** - View all data we hold about you
2. **Rectification** - Correct inaccurate data
3. **Erasure** - Request deletion of your data
4. **Portability** - Export your data
5. **Object** - Opt-out of certain processing
6. **Consent** - Review and update your consents
Select an option or describe your request.
END TALK
BEGIN SYSTEM PROMPT
You are a Privacy Rights Center assistant for LGPD/GDPR/CCPA compliance.
Data subject rights:
- Right of Access: View all personal data
- Right to Rectification: Correct inaccurate data
- Right to Erasure: Delete personal data (right to be forgotten)
- Right to Portability: Export data in machine-readable format
- Right to Object: Opt-out of marketing, profiling, etc.
- Consent Management: Review and withdraw consents
Always verify identity before processing sensitive requests.
Log all privacy requests for compliance audit.
Provide clear timelines for request fulfillment.
Escalate complex requests to the Data Protection Officer.
END SYSTEM PROMPT

View file

@ -0,0 +1,44 @@
name,value
Bot Name,Privacy Rights Center
Bot Description,LGPD/GDPR Data Subject Rights Management Bot
Bot Version,1.0.0
Bot Author,Pragmatismo
Bot License,AGPL-3.0
Bot Category,Compliance
Bot Tags,privacy;lgpd;gdpr;hipaa;ccpa;compliance;data-protection
Default Language,en
Supported Languages,en;pt;es;de;fr;it
Welcome Message,Welcome to the Privacy Rights Center. I can help you exercise your data protection rights under LGPD, GDPR, and other privacy regulations.
Error Message,I apologize, but I encountered an issue processing your request. Please try again or contact our privacy team at privacy@company.com
Timeout Message,Your session has timed out for security. Please start a new conversation.
Session Timeout,900
Max Retries,3
Log Level,info
Enable Audit Log,true
Audit Log Retention Days,2555
Require Authentication,true
Require Email Verification,true
Require 2FA,false
Data Retention Days,30
Auto Delete Completed Requests,false
Send Confirmation Emails,true
Privacy Officer Email,privacy@company.com
DPO Contact,dpo@company.com
Supervisory Authority,ANPD
Company Name,Your Company Name
Company Address,Your Company Address
Company Country,BR
Compliance Frameworks,LGPD;GDPR;CCPA
Response SLA Hours,72
Escalation Email,legal@company.com
Enable HIPAA Mode,false
PHI Processing Enabled,false
Encryption At Rest,true
Encryption In Transit,true
PII Detection Enabled,true
Auto Anonymization,true
Consent Required,true
Consent Version,1.0
Terms URL,https://company.com/terms
Privacy Policy URL,https://company.com/privacy
Cookie Policy URL,https://company.com/cookies
Can't render this file because it has a wrong number of fields in line 11.

View file

@ -0,0 +1,913 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Privacy Rights Center</title>
<style>
:root {
--primary-color: #2563eb;
--primary-hover: #1d4ed8;
--success-color: #10b981;
--warning-color: #f59e0b;
--danger-color: #ef4444;
--text-primary: #1e293b;
--text-secondary: #64748b;
--bg-primary: #f8fafc;
--bg-secondary: #ffffff;
--border-color: #e2e8f0;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
background: var(--bg-primary);
color: var(--text-primary);
line-height: 1.6;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
}
header {
text-align: center;
margin-bottom: 3rem;
padding: 2rem;
background: var(--bg-secondary);
border-radius: 1rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
.logo {
font-size: 3rem;
margin-bottom: 1rem;
}
h1 {
font-size: 2rem;
color: var(--text-primary);
margin-bottom: 0.5rem;
}
.subtitle {
color: var(--text-secondary);
font-size: 1.1rem;
}
.compliance-badges {
display: flex;
justify-content: center;
gap: 1rem;
margin-top: 1.5rem;
flex-wrap: wrap;
}
.badge {
padding: 0.5rem 1rem;
background: var(--bg-primary);
border: 1px solid var(--border-color);
border-radius: 2rem;
font-size: 0.875rem;
font-weight: 500;
display: flex;
align-items: center;
gap: 0.5rem;
}
.badge.lgpd { border-color: #22c55e; color: #16a34a; }
.badge.gdpr { border-color: #3b82f6; color: #2563eb; }
.badge.hipaa { border-color: #a855f7; color: #9333ea; }
.badge.ccpa { border-color: #f97316; color: #ea580c; }
.rights-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 1.5rem;
margin-bottom: 3rem;
}
.right-card {
background: var(--bg-secondary);
border: 1px solid var(--border-color);
border-radius: 1rem;
padding: 1.5rem;
transition: transform 0.2s, box-shadow 0.2s;
cursor: pointer;
}
.right-card:hover {
transform: translateY(-4px);
box-shadow: 0 12px 24px -8px rgba(0, 0, 0, 0.15);
}
.right-card .icon {
font-size: 2.5rem;
margin-bottom: 1rem;
}
.right-card h3 {
font-size: 1.25rem;
margin-bottom: 0.5rem;
color: var(--text-primary);
}
.right-card p {
color: var(--text-secondary);
font-size: 0.9rem;
margin-bottom: 1rem;
}
.right-card .legal-ref {
font-size: 0.75rem;
color: var(--primary-color);
background: rgba(37, 99, 235, 0.1);
padding: 0.25rem 0.5rem;
border-radius: 0.25rem;
display: inline-block;
}
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
padding: 0.75rem 1.5rem;
font-size: 1rem;
font-weight: 500;
border: none;
border-radius: 0.5rem;
cursor: pointer;
transition: all 0.2s;
text-decoration: none;
}
.btn-primary {
background: var(--primary-color);
color: white;
}
.btn-primary:hover {
background: var(--primary-hover);
}
.btn-secondary {
background: var(--bg-primary);
color: var(--text-primary);
border: 1px solid var(--border-color);
}
.btn-secondary:hover {
background: var(--border-color);
}
.btn-danger {
background: var(--danger-color);
color: white;
}
.btn-danger:hover {
background: #dc2626;
}
/* Modal Styles */
.modal-overlay {
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 1000;
align-items: center;
justify-content: center;
}
.modal-overlay.active {
display: flex;
}
.modal {
background: var(--bg-secondary);
border-radius: 1rem;
max-width: 600px;
width: 90%;
max-height: 90vh;
overflow-y: auto;
padding: 2rem;
position: relative;
}
.modal-close {
position: absolute;
top: 1rem;
right: 1rem;
background: none;
border: none;
font-size: 1.5rem;
cursor: pointer;
color: var(--text-secondary);
}
.modal h2 {
margin-bottom: 1rem;
display: flex;
align-items: center;
gap: 0.75rem;
}
.form-group {
margin-bottom: 1.5rem;
}
.form-group label {
display: block;
font-weight: 500;
margin-bottom: 0.5rem;
color: var(--text-primary);
}
.form-group input,
.form-group select,
.form-group textarea {
width: 100%;
padding: 0.75rem 1rem;
border: 1px solid var(--border-color);
border-radius: 0.5rem;
font-size: 1rem;
color: var(--text-primary);
background: var(--bg-secondary);
}
.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
}
.form-group textarea {
min-height: 100px;
resize: vertical;
}
.checkbox-group {
display: flex;
align-items: flex-start;
gap: 0.75rem;
}
.checkbox-group input[type="checkbox"] {
width: auto;
margin-top: 0.25rem;
}
.alert {
padding: 1rem;
border-radius: 0.5rem;
margin-bottom: 1rem;
display: flex;
align-items: flex-start;
gap: 0.75rem;
}
.alert-info {
background: rgba(37, 99, 235, 0.1);
color: var(--primary-color);
border: 1px solid rgba(37, 99, 235, 0.2);
}
.alert-warning {
background: rgba(245, 158, 11, 0.1);
color: #b45309;
border: 1px solid rgba(245, 158, 11, 0.2);
}
.alert-success {
background: rgba(16, 185, 129, 0.1);
color: #047857;
border: 1px solid rgba(16, 185, 129, 0.2);
}
.consent-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem;
background: var(--bg-primary);
border-radius: 0.5rem;
margin-bottom: 0.75rem;
}
.consent-info h4 {
font-size: 1rem;
margin-bottom: 0.25rem;
}
.consent-info p {
font-size: 0.85rem;
color: var(--text-secondary);
}
.toggle {
position: relative;
width: 48px;
height: 26px;
}
.toggle input {
opacity: 0;
width: 0;
height: 0;
}
.toggle-slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: #cbd5e1;
transition: 0.3s;
border-radius: 26px;
}
.toggle-slider:before {
position: absolute;
content: "";
height: 20px;
width: 20px;
left: 3px;
bottom: 3px;
background: white;
transition: 0.3s;
border-radius: 50%;
}
.toggle input:checked + .toggle-slider {
background: var(--success-color);
}
.toggle input:checked + .toggle-slider:before {
transform: translateX(22px);
}
.request-status {
background: var(--bg-secondary);
border: 1px solid var(--border-color);
border-radius: 1rem;
padding: 2rem;
margin-top: 2rem;
}
.status-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1.5rem;
}
.status-list {
border-top: 1px solid var(--border-color);
}
.status-item {
display: grid;
grid-template-columns: 1fr 2fr 1fr 1fr;
padding: 1rem 0;
border-bottom: 1px solid var(--border-color);
align-items: center;
}
.status-item:last-child {
border-bottom: none;
}
.status-badge {
padding: 0.25rem 0.75rem;
border-radius: 1rem;
font-size: 0.75rem;
font-weight: 500;
}
.status-pending {
background: rgba(245, 158, 11, 0.1);
color: #b45309;
}
.status-completed {
background: rgba(16, 185, 129, 0.1);
color: #047857;
}
.status-processing {
background: rgba(37, 99, 235, 0.1);
color: var(--primary-color);
}
footer {
text-align: center;
padding: 2rem;
color: var(--text-secondary);
font-size: 0.875rem;
}
footer a {
color: var(--primary-color);
text-decoration: none;
}
footer a:hover {
text-decoration: underline;
}
@media (max-width: 768px) {
.container {
padding: 1rem;
}
.rights-grid {
grid-template-columns: 1fr;
}
.status-item {
grid-template-columns: 1fr;
gap: 0.5rem;
}
}
</style>
</head>
<body>
<div class="container">
<header>
<div class="logo">🔒</div>
<h1>Privacy Rights Center</h1>
<p class="subtitle">Exercise your data protection rights under LGPD, GDPR, and other privacy regulations</p>
<div class="compliance-badges">
<span class="badge lgpd">🇧🇷 LGPD Compliant</span>
<span class="badge gdpr">🇪🇺 GDPR Compliant</span>
<span class="badge hipaa">🏥 HIPAA Ready</span>
<span class="badge ccpa">🇺🇸 CCPA Compliant</span>
</div>
</header>
<section class="rights-grid">
<div class="right-card" onclick="openModal('accessModal')">
<div class="icon">📋</div>
<h3>Access My Data</h3>
<p>Request a complete copy of all personal data we hold about you in a portable format.</p>
<span class="legal-ref">LGPD Art. 18 / GDPR Art. 15</span>
</div>
<div class="right-card" onclick="openModal('rectifyModal')">
<div class="icon">✏️</div>
<h3>Correct My Data</h3>
<p>Request correction of inaccurate or incomplete personal data we hold about you.</p>
<span class="legal-ref">LGPD Art. 18 III / GDPR Art. 16</span>
</div>
<div class="right-card" onclick="openModal('deleteModal')">
<div class="icon">🗑️</div>
<h3>Delete My Data</h3>
<p>Request deletion of your personal data (Right to be Forgotten).</p>
<span class="legal-ref">LGPD Art. 18 VI / GDPR Art. 17</span>
</div>
<div class="right-card" onclick="openModal('portabilityModal')">
<div class="icon">📦</div>
<h3>Export My Data</h3>
<p>Download your data in a machine-readable format to transfer to another service.</p>
<span class="legal-ref">LGPD Art. 18 V / GDPR Art. 20</span>
</div>
<div class="right-card" onclick="openModal('consentModal')">
<div class="icon">⚙️</div>
<h3>Manage Consents</h3>
<p>Review and update your data processing consents and preferences.</p>
<span class="legal-ref">LGPD Art. 8 / GDPR Art. 7</span>
</div>
<div class="right-card" onclick="openModal('objectModal')">
<div class="icon">🚫</div>
<h3>Object to Processing</h3>
<p>Object to certain types of data processing or opt-out of specific activities.</p>
<span class="legal-ref">LGPD Art. 18 IV / GDPR Art. 21</span>
</div>
</section>
<section class="request-status">
<div class="status-header">
<h2>📊 Your Request History</h2>
<button class="btn btn-secondary" onclick="refreshStatus()">🔄 Refresh</button>
</div>
<div class="status-list" id="statusList">
<div class="status-item">
<span class="status-badge status-completed">Completed</span>
<span>Data Access Request</span>
<span>2025-01-15</span>
<a href="#" class="btn btn-secondary" style="padding: 0.5rem 1rem; font-size: 0.875rem;">Download</a>
</div>
<div class="status-item">
<span class="status-badge status-processing">Processing</span>
<span>Consent Update</span>
<span>2025-01-20</span>
<span>In Progress</span>
</div>
</div>
</section>
</div>
<!-- Access Data Modal -->
<div class="modal-overlay" id="accessModal">
<div class="modal">
<button class="modal-close" onclick="closeModal('accessModal')">&times;</button>
<h2>📋 Access My Data</h2>
<div class="alert alert-info">
<span></span>
<span>You will receive a complete report of all personal data we hold about you within 15 days.</span>
</div>
<form onsubmit="submitRequest(event, 'access')">
<div class="form-group">
<label for="access</span>-email">Email Address *</label>
<input type="email" id="access-email" required placeholder="your@email.com">
</div>
<div class="form-group">
<label for="access-format">Preferred Format</label>
<select id="access-format">
<option value="pdf">PDF Report</option>
<option value="json">JSON (Machine Readable)</option>
<option value="csv">CSV (Spreadsheet)</option>
<option value="all">All Formats</option>
</select>
</div>
<div class="form-group">
<label for="access-notes">Additional Notes</label>
<textarea id="access-notes" placeholder="Any specific data you're looking for..."></textarea>
</div>
<button type="submit" class="btn btn-primary" style="width: 100%;">Submit Request</button>
</form>
</div>
</div>
<!-- Delete Data Modal -->
<div class="modal-overlay" id="deleteModal">
<div class="modal">
<button class="modal-close" onclick="closeModal('deleteModal')">&times;</button>
<h2>🗑️ Delete My Data</h2>
<div class="alert alert-warning">
<span>⚠️</span>
<span>This action is permanent and cannot be undone. Some data may be retained for legal compliance.</span>
</div>
<form onsubmit="submitRequest(event, 'delete')">
<div class="form-group">
<label for="delete-email">Email Address *</label>
<input type="email" id="delete-email" required placeholder="your@email.com">
</div>
<div class="form-group">
<label for="delete-scope">What to Delete</label>
<select id="delete-scope">
<option value="all">Everything (Complete Account Deletion)</option>
<option value="conversations">Conversation History Only</option>
<option value="files">Files and Documents Only</option>
<option value="activity">Activity Logs Only</option>
</select>
</div>
<div class="form-group">
<label for="delete-reason">Reason (Optional)</label>
<textarea id="delete-reason" placeholder="Help us improve by sharing why you're leaving..."></textarea>
</div>
<div class="form-group">
<div class="checkbox-group">
<input type="checkbox" id="delete-confirm" required>
<label for="delete-confirm">I understand this action is permanent and I want to proceed with data deletion</label>
</div>
</div>
<button type="submit" class="btn btn-danger" style="width: 100%;">Request Deletion</button>
</form>
</div>
</div>
<!-- Consent Management Modal -->
<div class="modal-overlay" id="consentModal">
<div class="modal">
<button class="modal-close" onclick="closeModal('consentModal')">&times;</button>
<h2>⚙️ Manage Consents</h2>
<div class="alert alert-info">
<span></span>
<span>Changes to your consents take effect immediately.</span>
</div>
<form onsubmit="submitRequest(event, 'consent')">
<div class="form-group">
<label for="consent-email">Email Address *</label>
<input type="email" id="consent-email" required placeholder="your@email.com">
</div>
<div class="consent-item">
<div class="consent-info">
<h4>Essential Services</h4>
<p>Required for basic functionality (cannot be disabled)</p>
</div>
<label class="toggle">
<input type="checkbox" checked disabled>
<span class="toggle-slider"></span>
</label>
</div>
<div class="consent-item">
<div class="consent-info">
<h4>Analytics & Improvement</h4>
<p>Help us improve through usage analysis</p>
</div>
<label class="toggle">
<input type="checkbox" id="consent-analytics" checked>
<span class="toggle-slider"></span>
</label>
</div>
<div class="consent-item">
<div class="consent-info">
<h4>Marketing Communications</h4>
<p>Receive news, updates, and promotions</p>
</div>
<label class="toggle">
<input type="checkbox" id="consent-marketing">
<span class="toggle-slider"></span>
</label>
</div>
<div class="consent-item">
<div class="consent-info">
<h4>Personalization</h4>
<p>Customize experience based on your usage</p>
</div>
<label class="toggle">
<input type="checkbox" id="consent-personalization" checked>
<span class="toggle-slider"></span>
</label>
</div>
<div class="consent-item">
<div class="consent-info">
<h4>Third-Party Sharing</h4>
<p>Share data with trusted partners</p>
</div>
<label class="toggle">
<input type="checkbox" id="consent-thirdparty">
<span class="toggle-slider"></span>
</label>
</div>
<div class="consent-item">
<div class="consent-info">
<h4>AI Model Training</h4>
<p>Use anonymized data to improve AI</p>
</div>
<label class="toggle">
<input type="checkbox" id="consent-ai">
<span class="toggle-slider"></span>
</label>
</div>
<button type="submit" class="btn btn-primary" style="width: 100%; margin-top: 1rem;">Save Preferences</button>
</form>
</div>
</div>
<!-- Rectify Modal -->
<div class="modal-overlay" id="rectifyModal">
<div class="modal">
<button class="modal-close" onclick="closeModal('rectifyModal')">&times;</button>
<h2>✏️ Correct My Data</h2>
<form onsubmit="submitRequest(event, 'rectify')">
<div class="form-group">
<label for="rectify-email">Email Address *</label>
<input type="email" id="rectify-email" required placeholder="your@email.com">
</div>
<div class="form-group">
<label for="rectify-field">Data to Correct *</label>
<select id="rectify-field" required>
<option value="">Select field...</option>
<option value="name">Name</option>
<option value="email">Email Address</option>
<option value="phone">Phone Number</option>
<option value="address">Address</option>
<option value="other">Other</option>
</select>
</div>
<div class="form-group">
<label for="rectify-current">Current Value</label>
<input type="text" id="rectify-current" placeholder="What it currently shows">
</div>
<div class="form-group">
<label for="rectify-new">Correct Value *</label>
<input type="text" id="rectify-new" required placeholder="What it should be">
</div>
<div class="form-group">
<label for="rectify-reason">Additional Information</label>
<textarea id="rectify-reason" placeholder="Any additional details..."></textarea>
</div>
<button type="submit" class="btn btn-primary" style="width: 100%;">Submit Correction Request</button>
</form>
</div>
</div>
<!-- Portability Modal -->
<div class="modal-overlay" id="portabilityModal">
<div class="modal">
<button class="modal-close" onclick="closeModal('portabilityModal')">&times;</button>
<h2>📦 Export My Data</h2>
<div class="alert alert-info">
<span></span>
<span>Your data will be prepared and a download link sent to your email within 72 hours.</span>
</div>
<form onsubmit="submitRequest(event, 'portability')">
<div class="form-group">
<label for="port-email">Email Address *</label>
<input type="email" id="port-email" required placeholder="your@email.com">
</div>
<div class="form-group">
<label for="port-format">Export Format *</label>
<select id="port-format" required>
<option value="json">JSON (Recommended for data transfer)</option>
<option value="csv">CSV (For spreadsheets)</option>
<option value="xml">XML (Universal format)</option>
<option value="all">All Formats (ZIP archive)</option>
</select>
</div>
<div class="form-group">
<label>Data Categories to Include</label>
<div class="checkbox-group">
<input type="checkbox" id="port-profile" checked>
<label for="port-profile">Profile Information</label>
</div>
<div class="checkbox-group">
<input type="checkbox" id="port-conversations" checked>
<label for="port-conversations">Conversations & Messages</label>
</div>
<div class="checkbox-group">
<input type="checkbox" id="port-files" checked>
<label for="port-files">Files & Documents</label>
</div>
<div class="checkbox-group">
<input type="checkbox" id="port-activity">
<label for="port-activity">Activity Logs</label>
</div>
<div class="checkbox-group">
<input type="checkbox" id="port-consents" checked>
<label for="port-consents">Consent Records</label>
</div>
</div>
<button type="submit" class="btn btn-primary" style="width: 100%;">Generate Export</button>
</form>
</div>
</div>
<!-- Object Modal -->
<div class="modal-overlay" id="objectModal">
<div class="modal">
<button class="modal-close" onclick="closeModal('objectModal')">&times;</button>
<h2>🚫 Object to Processing</h2>
<form onsubmit="submitRequest(event, 'object')">
<div class="form-group">
<label for="object-email">Email Address *</label>
<input type="email" id="object-email" required placeholder="your@email.com">
</div>
<div class="form-group">
<label for="object-type">Processing Activity *</label>
<select id="object-type" required>
<option value="">Select activity...</option>
<option value="profiling">Automated Profiling</option>
<option value="direct-marketing">Direct Marketing</option>
<option value="analytics">Analytics & Statistics</option>
<option value="third-party">Third-Party Data Sharing</option>
<option value="ai-processing">AI/ML Processing</option>
<option value="other">Other</option>
</select>
</div>
<div class="form-group">
<label for="object-reason">Reason for Objection *</label>
<textarea id="object-reason" required placeholder="Please explain why you object to this processing..."></textarea>
</div>
<button type="submit" class="btn btn-primary" style="width: 100%;">Submit Objection</button>
</form>
</div>
</div>
<footer>
<p>🔒 Your privacy matters. All requests are processed securely and confidentially.</p>
<p>
<a href="/privacy-policy">Privacy Policy</a>
<a href="/terms">Terms of Service</a>
<a href="mailto:privacy@company.com">Contact DPO</a>
</p>
<p style="margin-top: 1rem;">© 2025 Pragmatismo. Built with General Bots.</p>
</footer>
<script>
function openModal(modalId) {
document.getElementById(modalId).classList.add('active');
document.body.style.overflow = 'hidden';
}
function closeModal(modalId) {
document.getElementById(modalId).classList.remove('active');
document.body.style.overflow = 'auto';
}
// Close modal on overlay click
document.querySelectorAll('.modal-overlay').forEach(overlay => {
overlay.addEventListener('click', (e) => {
if (e.target === overlay) {
overlay.classList.remove('active');
document.body.style.overflow = 'auto';
}
});
});
// Close modal on Escape key
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
document.querySelectorAll('.modal-overlay.active').forEach(modal => {
modal.classList.remove('active');
});
document.body.style.overflow = 'auto';
}
});
async function submitRequest(event, type) {
event.preventDefault();
const form = event.target;
const formData = new FormData(form);
const data = Object.fromEntries(formData.entries());
data.request_type = type;
try {
const response = await fetch('/api/privacy/request', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
if (response.ok) {
alert('✅ Your request has been submitted successfully! Check your email for confirmation.');
form.reset();
closeModal(form.closest('.modal-overlay').id);
refreshStatus();
} else {
throw new Error('Request failed');
}
} catch (error) {
alert('❌ There was an error submitting your request. Please try again or contact support.');
}
}
async function refreshStatus() {
try {
const response = await fetch('/api/privacy/requests');
if (response.ok) {
const requests = await response.json();
updateStatusList(requests);
}
} catch (error) {
console.error('Failed to refresh status:', error);
}
}
function updateStatusList(requests) {
const statusList = document.getElementById('statusList');
if (requests.length === 0) {
statusList.innerHTML = '<p style="padding: 1rem; color: var(--text-secondary);">No requests found.</p>';
return;
}
statusList.innerHTML = requests.map(req => `
<div class="status-item">
<span class="status-badge status-${req.status.toLowerCase()}">${req.status}</span>
<span>${req.type}</span>
<span>${new Date(req.created_at).toLocaleDateString()}</span>
${req.download_url ?
`<a href="${req.download_url}" class="btn btn-secondary" style="padding: 0.5rem 1rem; font-size: 0.875rem;">Download</a>` :
`<span>${req.status}</span>`
}
</div>
`).join('');
}
// Load status on page load
document.addEventListener('DOMContentLoaded', refreshStatus);
</script>
</body>
</html>

275
crawler.gbai/README.md Normal file
View file

@ -0,0 +1,275 @@
# Web Crawler Template (crawler.gbai)
A General Bots template for automated web crawling and content extraction for knowledge base population.
## Overview
The Crawler template enables your bot to automatically fetch, parse, and index web content. It's designed for building knowledge bases from websites, monitoring web pages for changes, and extracting structured data from online sources.
## Features
- **Automated Web Scraping** - Fetch and parse web pages automatically
- **Document Mode** - Answer questions based on crawled content
- **Configurable Depth** - Control how many pages to crawl
- **Content Indexing** - Automatically add content to knowledge base
- **LLM Integration** - Use AI to understand and summarize crawled content
## Package Structure
```
crawler.gbai/
├── README.md
├── crawler.gbkb/ # Knowledge base for crawled content
│ └── docs/ # Indexed documents
└── crawler.gbot/
└── config.csv # Crawler configuration
```
## Configuration
Configure the crawler in `crawler.gbot/config.csv`:
| Parameter | Description | Example |
|-----------|-------------|---------|
| `Website` | Target URL to crawl | `https://pragmatismo.com.br/` |
| `website Max Documents` | Maximum pages to crawl | `2` |
| `Answer Mode` | How to respond to queries | `document` |
| `Theme Color` | UI theme color | `purple` |
| `LLM Provider` | AI provider for processing | `openai` |
### Example config.csv
```csv
name,value
Website,https://pragmatismo.com.br/
website Max Documents,2
Answer Mode,document
Theme Color,purple
LLM Provider,openai
```
## How It Works
1. **Initialization** - Bot reads the target website from configuration
2. **Crawling** - Fetches pages starting from the root URL
3. **Extraction** - Parses HTML and extracts meaningful text content
4. **Indexing** - Stores content in the knowledge base for RAG
5. **Q&A** - Users can ask questions about the crawled content
## Usage
### Basic Setup
1. Copy the template to your bot's packages directory:
```bash
cp -r templates/crawler.gbai /path/to/your/bot/packages/
```
2. Edit `crawler.gbot/config.csv` with your target website:
```csv
name,value
Website,https://your-website.com/
website Max Documents,10
Answer Mode,document
```
3. Deploy and the bot will automatically crawl the configured site.
### Querying Crawled Content
Once crawled, users can ask questions naturally:
- "What services does the company offer?"
- "Tell me about the pricing"
- "Summarize the about page"
- "What are the main features?"
### Answer Modes
| Mode | Behavior |
|------|----------|
| `document` | Answers strictly based on crawled content |
| `hybrid` | Combines crawled content with general knowledge |
| `summary` | Provides concise summaries of relevant pages |
## Advanced Configuration
### Limiting Crawl Scope
Control which pages are crawled:
```csv
name,value
Website,https://example.com/docs/
website Max Documents,50
Website Include Pattern,/docs/*
Website Exclude Pattern,/docs/archive/*
```
### Scheduling Recrawls
Set up periodic recrawling to keep content fresh:
```csv
name,value
Website Refresh Schedule,0 0 * * 0
```
This example recrawls every Sunday at midnight.
### Authentication
For sites requiring authentication:
```csv
name,value
Website Auth Type,basic
Website Username,user
Website Password,secret
```
## Customization
### Creating Custom Crawl Logic
Create a BASIC dialog for custom crawling:
```basic
' custom-crawl.bas
urls = ["https://site1.com", "https://site2.com", "https://site3.com"]
FOR EACH url IN urls
content = GET url
IF content THEN
SAVE "crawled_pages.csv", url, content, NOW()
SET CONTEXT content
END IF
NEXT
TALK "Crawled " + UBOUND(urls) + " pages successfully."
```
### Processing Crawled Content
Use LLM to process and structure crawled data:
```basic
' process-crawled.bas
pages = FIND "crawled_pages.csv"
FOR EACH page IN pages
summary = LLM "Summarize this content in 3 bullet points: " + page.content
WITH processed
url = page.url
summary = summary
processed_at = NOW()
END WITH
SAVE "processed_content.csv", processed
NEXT
```
### Extracting Structured Data
Extract specific information from pages:
```basic
' extract-products.bas
SET CONTEXT "You are a data extraction assistant. Extract product information as JSON."
page_content = GET "https://store.example.com/products"
products = LLM "Extract all products with name, price, and description as JSON array: " + page_content
SAVE "products.json", products
```
## Integration Examples
### With Knowledge Base
```basic
' Add crawled content to KB
content = GET "https://docs.example.com/api"
IF content THEN
USE KB "api-docs.gbkb"
ADD TO KB content, "API Documentation"
END IF
```
### With Notifications
```basic
' Monitor for changes
previous = GET BOT MEMORY "last_content"
current = GET "https://news.example.com"
IF current <> previous THEN
SEND EMAIL "admin@company.com", "Website Changed", "The monitored page has been updated."
SET BOT MEMORY "last_content", current
END IF
```
### With Data Analysis
```basic
' Analyze competitor pricing
competitor_page = GET "https://competitor.com/pricing"
analysis = LLM "Compare this pricing to our prices and identify opportunities: " + competitor_page
TALK analysis
```
## Best Practices
1. **Respect robots.txt** - Only crawl pages allowed by the site's robots.txt
2. **Rate limiting** - Don't overwhelm target servers with requests
3. **Set reasonable limits** - Start with low `Max Documents` values
4. **Monitor content quality** - Review crawled content for accuracy
5. **Keep content fresh** - Schedule periodic recrawls for dynamic sites
6. **Handle errors gracefully** - Implement retry logic for failed requests
## Troubleshooting
| Issue | Cause | Solution |
|-------|-------|----------|
| No content indexed | Invalid URL | Verify the Website URL is accessible |
| Partial content | Max Documents too low | Increase the limit in config |
| Stale answers | Content not refreshed | Set up scheduled recrawls |
| Authentication errors | Missing credentials | Add auth settings to config |
| Timeout errors | Slow target site | Increase timeout settings |
## Limitations
- JavaScript-rendered content may not be fully captured
- Some sites block automated crawlers
- Large sites may take significant time to fully crawl
- Dynamic content may require special handling
## Related Templates
- `ai-search.gbai` - AI-powered document search
- `talk-to-data.gbai` - Natural language data queries
- `law.gbai` - Legal document processing with similar RAG approach
## Use Cases
- **Documentation Bots** - Index product docs for support
- **Competitive Intelligence** - Monitor competitor websites
- **News Aggregation** - Collect news from multiple sources
- **Research Assistants** - Build knowledge bases from academic sources
- **FAQ Generators** - Extract FAQs from help sites
## License
AGPL-3.0 - Part of General Bots Open Source Platform.
---
**Pragmatismo** - General Bots

View file

@ -0,0 +1,208 @@
# Web Crawling Guide
## Overview
The Web Crawler bot helps you extract and index content from websites. It automatically navigates through web pages, collects information, and makes it searchable through your knowledge base.
## Features
### Content Extraction
- **Text Content**: Extract readable text from web pages
- **Links**: Follow and index linked pages
- **Metadata**: Capture page titles, descriptions, and keywords
- **Structured Data**: Extract data from tables and lists
### Crawl Management
- **Depth Control**: Set how many levels of links to follow
- **Domain Restrictions**: Limit crawling to specific domains
- **URL Patterns**: Include or exclude URLs by pattern
- **Rate Limiting**: Control request frequency to avoid overloading servers
### Content Processing
- **Duplicate Detection**: Avoid indexing the same content twice
- **Content Filtering**: Skip irrelevant pages (login, error pages, etc.)
- **Format Conversion**: Convert HTML to clean, searchable text
- **Language Detection**: Identify content language for proper indexing
## How to Use
### Starting a Crawl
To start crawling a website:
1. Provide the starting URL (seed URL)
2. Configure crawl parameters (depth, limits)
3. Start the crawl process
4. Monitor progress and results
### Configuration Options
| Option | Description | Default |
|--------|-------------|---------|
| `max_depth` | How many link levels to follow | 3 |
| `max_pages` | Maximum pages to crawl | 100 |
| `delay` | Seconds between requests | 1 |
| `same_domain` | Stay within starting domain | true |
| `follow_external` | Follow links to other domains | false |
### URL Patterns
You can filter URLs using patterns:
**Include patterns:**
- `/blog/*` - Only crawl blog pages
- `/products/*` - Only crawl product pages
**Exclude patterns:**
- `/admin/*` - Skip admin pages
- `/login` - Skip login pages
- `*.pdf` - Skip PDF files
## Best Practices
### Respectful Crawling
1. **Respect robots.txt**: Always check and honor robots.txt rules
2. **Rate limiting**: Don't overload servers with too many requests
3. **Identify yourself**: Use a proper user agent string
4. **Off-peak hours**: Schedule large crawls during low-traffic times
### Efficient Crawling
1. **Start focused**: Begin with a specific section rather than entire site
2. **Set limits**: Use reasonable depth and page limits
3. **Filter content**: Exclude irrelevant sections early
4. **Monitor progress**: Watch for errors and adjust as needed
### Content Quality
1. **Remove navigation**: Filter out repeated headers/footers
2. **Extract main content**: Focus on the primary page content
3. **Handle dynamic content**: Some sites require JavaScript rendering
4. **Check encoding**: Ensure proper character encoding
## Common Crawl Scenarios
### Documentation Site
```
Starting URL: https://docs.example.com/
Depth: 4
Include: /docs/*, /api/*
Exclude: /changelog/*
```
### Blog Archive
```
Starting URL: https://blog.example.com/
Depth: 2
Include: /posts/*, /articles/*
Exclude: /author/*, /tag/*
```
### Product Catalog
```
Starting URL: https://shop.example.com/products/
Depth: 3
Include: /products/*, /categories/*
Exclude: /cart/*, /checkout/*
```
## Understanding Results
### Crawl Statistics
After a crawl completes, you'll see:
- **Pages Crawled**: Total pages successfully processed
- **Pages Skipped**: Pages excluded by filters
- **Errors**: Pages that failed to load
- **Time Elapsed**: Total crawl duration
- **Content Size**: Total indexed content size
### Content Index
Crawled content is indexed and available for:
- Semantic search queries
- Knowledge base answers
- Document retrieval
- AI-powered Q&A
## Troubleshooting
### Pages Not Crawling
- Check if URL is accessible (not behind login)
- Verify robots.txt allows crawling
- Ensure URL matches include patterns
- Check for JavaScript-only content
### Slow Crawling
- Increase delay between requests if seeing errors
- Reduce concurrent connections
- Check network connectivity
- Monitor server response times
### Missing Content
- Some sites require JavaScript rendering
- Content may be loaded dynamically via AJAX
- Check if content is within an iframe
- Verify content isn't blocked by login wall
### Duplicate Content
- Enable duplicate detection
- Use canonical URL handling
- Filter URL parameters that don't change content
## Scheduled Crawling
Set up recurring crawls to keep content fresh:
- **Daily**: For frequently updated news/blog sites
- **Weekly**: For documentation and knowledge bases
- **Monthly**: For stable reference content
## Legal Considerations
Always ensure you have the right to crawl and index content:
- Check website terms of service
- Respect copyright and intellectual property
- Honor robots.txt directives
- Don't crawl private or restricted content
- Consider data protection regulations (GDPR, LGPD)
## Frequently Asked Questions
**Q: How do I crawl a site that requires login?**
A: The crawler works best with public content. For authenticated content, consider using API integrations instead.
**Q: Can I crawl PDF documents?**
A: Yes, PDFs can be downloaded and processed separately for text extraction.
**Q: How often should I re-crawl?**
A: Depends on how frequently the site updates. News sites may need daily crawls; documentation might only need weekly or monthly.
**Q: What happens if a page moves or is deleted?**
A: The crawler will detect 404 errors and can remove outdated content from the index.
**Q: Can I crawl multiple sites at once?**
A: Yes, you can configure multiple seed URLs and the crawler will process them in sequence.
## Support
For crawling issues:
- Review crawl logs for error details
- Check network and firewall settings
- Verify target site is accessible
- Contact your administrator for configuration help

View file

@ -0,0 +1,6 @@
name,value
Website,https://pragmatismo.com.br/
website Max Documents, 2
Answer Mode,document
Theme Color,purple
LLM Provider,openai
1 name value
2 Website https://pragmatismo.com.br/
3 website Max Documents 2
4 Answer Mode document
5 Theme Color purple
6 LLM Provider openai

307
crm/contacts.gbai/README.md Normal file
View file

@ -0,0 +1,307 @@
# CRM Contacts Template (contacts.gbai)
A General Bots template for managing contact directories with search, add, update, and company management capabilities.
## Overview
The Contacts template provides a complete contact management system with natural language interaction. Users can add new contacts, search the directory, manage company records, and track contact history through conversational AI.
## Features
- **Contact Management** - Add, update, search, and delete contacts
- **Company Records** - Automatic company creation and association
- **Flexible Search** - Search by name, email, company, or phone
- **Activity Tracking** - Log all contact interactions
- **Tag System** - Organize contacts with custom tags
- **Export Capabilities** - Export contact lists in various formats
## Package Structure
```
contacts.gbai/
├── README.md
├── contacts.gbdialog/
│ ├── start.bas # Main entry point and tool registration
│ ├── add-contact.bas # Add new contacts
│ └── search-contact.bas # Search contact directory
├── contacts.gbkb/ # Knowledge base for contact help
└── contacts.gbot/
└── config.csv # Bot configuration
```
## Scripts
| File | Description |
|------|-------------|
| `start.bas` | Initializes tools, sets context, and displays welcome menu |
| `add-contact.bas` | Creates new contact records with validation |
| `search-contact.bas` | Searches directory by multiple fields |
## Available Tools
The template registers these tools for LLM access:
| Tool | Description |
|------|-------------|
| `add-contact` | Add a new contact to the directory |
| `search-contact` | Search contacts by any field |
| `update-contact` | Modify existing contact information |
| `list-contacts` | List all contacts with optional filters |
| `add-company` | Create a new company record |
| `contact-history` | View interaction history for a contact |
## Data Schema
### Contacts Table
| Field | Type | Description |
|-------|------|-------------|
| `contactid` | String | Unique identifier (CON-YYYYMMDD-XXXX) |
| `firstname` | String | Contact's first name |
| `lastname` | String | Contact's last name |
| `fullname` | String | Combined full name |
| `email` | Email | Email address |
| `phone` | Phone | Phone number |
| `companyname` | String | Associated company |
| `jobtitle` | String | Job title or role |
| `tags` | String | Comma-separated tags |
| `notes` | String | Additional notes |
| `createdby` | String | User who created the record |
| `createdat` | DateTime | Creation timestamp |
### Companies Table
| Field | Type | Description |
|-------|------|-------------|
| `companyid` | String | Unique identifier |
| `name` | String | Company name |
| `createdat` | DateTime | Creation timestamp |
### Activities Table
| Field | Type | Description |
|-------|------|-------------|
| `contactid` | String | Related contact ID |
| `action` | String | Action description |
| `createdby` | String | User who performed action |
| `createdat` | DateTime | Activity timestamp |
## Usage
### Adding a Contact
Users can add contacts naturally:
- "Add John Smith from Acme Corp"
- "Create a new contact for jane@company.com"
- "Add contact: Mike Johnson, Sales Manager at TechCo"
Or provide structured input:
```
First Name: John
Last Name: Smith
Email: john.smith@acme.com
Phone: +1-555-123-4567
Company: Acme Corporation
Job Title: VP of Sales
Tags: customer, vip
Notes: Met at trade show
```
### Searching Contacts
Search using natural language:
- "Find contacts at Acme"
- "Search for John"
- "Look up john.smith@acme.com"
- "Find all VIP contacts"
Search filters:
| Filter | Example |
|--------|---------|
| By name | "search John Smith" |
| By email | "search john@company.com" |
| By company | "find contacts at Microsoft" |
| By phone | "lookup +1-555-1234" |
| By tag | "show all VIP contacts" |
### Managing Companies
Companies are auto-created when adding contacts:
```basic
' When adding a contact with a new company
IF companyname THEN
existingcompany = FIND "companies.csv", "name=" + companyname
IF COUNT(existingcompany) = 0 THEN
' Auto-create company record
SAVE "companies.csv", companyid, companyname, createdat
END IF
END IF
```
## Configuration
Configure in `contacts.gbot/config.csv`:
| Parameter | Description | Example |
|-----------|-------------|---------|
| `Theme Color` | UI accent color | `blue` |
| `Default Tags` | Auto-applied tags | `new,prospect` |
| `Require Email` | Email required? | `true` |
| `Duplicate Check` | Check for duplicates | `true` |
## Customization
### Adding Custom Fields
Extend the contact schema in `add-contact.bas`:
```basic
PARAM department AS STRING LIKE "Engineering" DESCRIPTION "Department name" OPTIONAL
PARAM linkedin AS STRING LIKE "linkedin.com/in/john" DESCRIPTION "LinkedIn profile" OPTIONAL
' Include in save
SAVE "contacts.csv", contactid, firstname, lastname, fullname, email, phone,
companyname, jobtitle, department, linkedin, tags, notes, createdby, createdat
```
### Custom Search Filters
Add specialized search in `search-contact.bas`:
```basic
IF searchby = "department" THEN
results = FIND "contacts.csv", "department LIKE " + searchterm
END IF
IF searchby = "recent" THEN
cutoff = DATEADD(NOW(), -7, "day")
results = FIND "contacts.csv", "createdat >= " + cutoff
END IF
```
### Integration with Email
Send welcome emails to new contacts:
```basic
' In add-contact.bas after SAVE
IF email THEN
subject = "Thank you for connecting!"
body = "Hi " + firstname + ", we look forward to working with you."
SEND EMAIL email, subject, body
END IF
```
### Integration with CRM Pipeline
Connect contacts to leads:
```basic
' Convert contact to lead
PARAM convert_to_lead AS BOOLEAN DESCRIPTION "Create lead from contact" OPTIONAL
IF convert_to_lead THEN
WITH new_lead
id = FORMAT(GUID())
name = fullname
email = email
phone = phone
company = companyname
source = "contact_conversion"
status = "new"
created_at = NOW()
END WITH
SAVE "leads.csv", new_lead
TALK "Lead created from contact: " + fullname
END IF
```
## Example Conversations
### Adding a Contact
```
User: Add a new contact
Bot: I'll help you add a new contact. What is their first name?
User: Sarah
Bot: And their last name?
User: Johnson
Bot: What is Sarah's email address?
User: sarah.johnson@techstartup.io
Bot: Phone number? (optional)
User: 555-987-6543
Bot: What company does Sarah work for?
User: TechStartup Inc
Bot: What is her job title?
User: CTO
Bot: ✅ Contact added: Sarah Johnson
ID: CON-20240115-4821
Email: sarah.johnson@techstartup.io
Phone: 555-987-6543
Company: TechStartup Inc
Title: CTO
```
### Searching Contacts
```
User: Find contacts at TechStartup
Bot: Found 2 contact(s):
---
**Sarah Johnson**
sarah.johnson@techstartup.io
555-987-6543
TechStartup Inc
CTO
ID: CON-20240115-4821
---
**Mike Chen**
mike.chen@techstartup.io
TechStartup Inc
Developer
ID: CON-20240110-3392
```
## Best Practices
1. **Validate input** - Use `PARAM` type validation for email and phone
2. **Check duplicates** - Search before creating to avoid duplicates
3. **Log activities** - Track all changes for audit trail
4. **Use tags** - Organize contacts with meaningful tags
5. **Keep notes** - Add context about how/where you met contacts
6. **Regular cleanup** - Archive inactive contacts periodically
## Troubleshooting
| Issue | Solution |
|-------|----------|
| Duplicate contacts | Enable duplicate checking in config |
| Search returns nothing | Try broader search terms |
| Company not linked | Ensure company name matches exactly |
| Missing activities | Check activity logging is enabled |
## Related Templates
- `crm.gbai` - Full CRM with leads, opportunities, and pipeline
- `marketing.gbai` - Marketing automation with contact segmentation
- `office.gbai` - Office productivity with contact directory
## Use Cases
- **Sales Teams** - Manage prospect and customer contacts
- **HR Departments** - Employee and candidate directories
- **Event Management** - Attendee and speaker contacts
- **Networking** - Professional contact management
- **Customer Support** - Customer contact lookup
## License
AGPL-3.0 - Part of General Bots Open Source Platform.
---
**Pragmatismo** - General Bots

View file

@ -0,0 +1,56 @@
PARAM firstname AS STRING LIKE "John" DESCRIPTION "First name of the contact"
PARAM lastname AS STRING LIKE "Smith" DESCRIPTION "Last name of the contact"
PARAM email AS EMAIL LIKE "john.smith@company.com" DESCRIPTION "Email address"
PARAM phone AS PHONE LIKE "+1-555-123-4567" DESCRIPTION "Phone number"
PARAM companyname AS STRING LIKE "Acme Corporation" DESCRIPTION "Company or organization"
PARAM jobtitle AS STRING LIKE "Sales Manager" DESCRIPTION "Job title or role"
PARAM tags AS STRING LIKE "customer,vip" DESCRIPTION "Comma-separated tags" OPTIONAL
PARAM notes AS STRING LIKE "Met at conference" DESCRIPTION "Notes about the contact" OPTIONAL
DESCRIPTION "Add a new contact to the directory with contact information"
contactid = "CON-" + FORMAT(NOW(), "YYYYMMDD") + "-" + FORMAT(RANDOM(1000, 9999))
createdat = FORMAT(NOW(), "YYYY-MM-DD HH:mm:ss")
createdby = GET "session.user_email"
fullname = firstname + " " + lastname
SAVE "contacts.csv", contactid, firstname, lastname, fullname, email, phone, companyname, jobtitle, tags, notes, createdby, createdat
SET BOT MEMORY "last_contact", contactid
IF companyname THEN
existingcompany = FIND "companies.csv", "name=" + companyname
companycount = AGGREGATE "COUNT", existingcompany, "id"
IF companycount = 0 THEN
companyid = "COMP-" + FORMAT(NOW(), "YYYYMMDD") + "-" + FORMAT(RANDOM(1000, 9999))
SAVE "companies.csv", companyid, companyname, createdat
END IF
END IF
WITH activity
contactid = contactid
action = "Contact created: " + fullname
createdby = createdby
createdat = createdat
END WITH
SAVE "contact_activities.csv", activity
TALK "Contact added: " + fullname
TALK "ID: " + contactid
TALK "Email: " + email
IF phone THEN
TALK "Phone: " + phone
END IF
IF companyname THEN
TALK "Company: " + companyname
END IF
IF jobtitle THEN
TALK "Title: " + jobtitle
END IF
RETURN contactid

View file

@ -0,0 +1,69 @@
PARAM searchterm AS STRING LIKE "john" DESCRIPTION "Name, email, company, or phone to search for"
PARAM searchby AS STRING LIKE "all" DESCRIPTION "Filter by field: all, name, email, company, phone"
DESCRIPTION "Search contact directory by name, email, company, or phone number"
IF NOT searchby THEN
searchby = "all"
END IF
TALK "Searching contacts for: " + searchterm
results = []
IF searchby = "all" OR searchby = "name" THEN
nameresults = FIND "contacts.csv", "fullname LIKE " + searchterm
results = MERGE results, nameresults
END IF
IF searchby = "all" OR searchby = "email" THEN
emailresults = FIND "contacts.csv", "email LIKE " + searchterm
results = MERGE results, emailresults
END IF
IF searchby = "all" OR searchby = "company" THEN
companyresults = FIND "contacts.csv", "companyname LIKE " + searchterm
results = MERGE results, companyresults
END IF
IF searchby = "all" OR searchby = "phone" THEN
phoneresults = FIND "contacts.csv", "phone LIKE " + searchterm
results = MERGE results, phoneresults
END IF
resultcount = UBOUND(results)
IF resultcount = 0 THEN
TALK "No contacts found matching: " + searchterm
RETURN
END IF
TALK "Found " + resultcount + " contact(s):"
FOR EACH contact IN results
TALK "---"
TALK "**" + contact.fullname + "**"
TALK contact.email
IF contact.phone <> "" THEN
TALK contact.phone
END IF
IF contact.companyname <> "" THEN
TALK contact.companyname
END IF
IF contact.jobtitle <> "" THEN
TALK contact.jobtitle
END IF
TALK "ID: " + contact.contactid
NEXT
IF resultcount > 0 THEN
firstcontact = FIRST results
SET BOT MEMORY "last_contact", firstcontact.contactid
SET BOT MEMORY "last_search", searchterm
END IF
RETURN results

View file

@ -0,0 +1,42 @@
ADD TOOL "add-contact"
ADD TOOL "search-contact"
ADD TOOL "update-contact"
ADD TOOL "list-contacts"
ADD TOOL "add-company"
ADD TOOL "contact-history"
USE KB "contacts.gbkb"
SET CONTEXT "contact directory" AS "You are a contact management assistant helping organize and search contacts. Help with adding new contacts, searching the directory, updating contact information, managing company records, and viewing contact history."
CLEAR SUGGESTIONS
ADD SUGGESTION "add" AS "Add a new contact"
ADD SUGGESTION "search" AS "Search contacts"
ADD SUGGESTION "companies" AS "View companies"
ADD SUGGESTION "recent" AS "Recent contacts"
ADD SUGGESTION "export" AS "Export contacts"
BEGIN TALK
**Contact Directory**
I can help you with:
Add new contacts and companies
Search by name, email, or company
Update contact information
Manage company records
View contact history
Export contact lists
Select an option or tell me what you need.
END TALK
BEGIN SYSTEM PROMPT
You are a contact directory assistant.
Contact fields: name, email, phone, company, job title, address, tags, notes.
Confirm before making changes to existing contacts.
Be flexible with partial matches when searching.
Suggest adding missing information when appropriate.
END SYSTEM PROMPT

View file

@ -0,0 +1,9 @@
name,value
episodic-memory-history,2
episodic-memory-threshold,4
theme-color1,#1565C0
theme-color2,#E3F2FD
theme-logo,https://pragmatismo.com.br/icons/general-bots.svg
theme-title,Contact Directory - General Bots
bot-name,Contact Directory Assistant
welcome-message,Welcome to the Contact Directory!
1 name value
2 episodic-memory-history 2
3 episodic-memory-threshold 4
4 theme-color1 #1565C0
5 theme-color2 #E3F2FD
6 theme-logo https://pragmatismo.com.br/icons/general-bots.svg
7 theme-title Contact Directory - General Bots
8 bot-name Contact Directory Assistant
9 welcome-message Welcome to the Contact Directory!

View file

@ -0,0 +1,72 @@
PARAM dealname AS STRING LIKE "Acme Corp Enterprise License" DESCRIPTION "Name of the deal or opportunity"
PARAM companyname AS STRING LIKE "Acme Corporation" DESCRIPTION "Company or account name"
PARAM contactemail AS EMAIL LIKE "john@acme.com" DESCRIPTION "Primary contact email"
PARAM dealvalue AS MONEY LIKE 50000 DESCRIPTION "Estimated deal value in dollars"
PARAM stage AS STRING LIKE "Lead" DESCRIPTION "Initial stage: Lead, Qualified, Proposal, Negotiation" OPTIONAL
PARAM closedate AS DATE LIKE "2025-03-30" DESCRIPTION "Expected close date" OPTIONAL
PARAM notes AS STRING LIKE "Met at trade show" DESCRIPTION "Notes about the deal" OPTIONAL
DESCRIPTION "Create a new sales deal in the pipeline with deal information and value tracking"
IF NOT stage THEN
stage = "Lead"
END IF
IF NOT closedate THEN
closedate = DATEADD(TODAY(), 30, "day")
END IF
dealid = "DEAL-" + FORMAT(NOW(), "YYYYMMDD") + "-" + FORMAT(RANDOM(1000, 9999))
createdat = FORMAT(NOW(), "YYYY-MM-DD HH:mm:ss")
ownerid = GET "session.user_id"
owneremail = GET "session.user_email"
probability = 10
IF stage = "Qualified" THEN
probability = 25
ELSE IF stage = "Proposal" THEN
probability = 50
ELSE IF stage = "Negotiation" THEN
probability = 75
END IF
weightedvalue = dealvalue * probability / 100
WITH deal
id = dealid
name = dealname
company = companyname
contact = contactemail
value = dealvalue
currentStage = stage
expectedClose = closedate
prob = probability
weighted = weightedvalue
dealNotes = notes
owner = ownerid
ownerEmail = owneremail
created = createdat
END WITH
SAVE "deals.csv", deal
SET BOT MEMORY "last_deal", dealid
WITH dealActivity
dealId = dealid
action = "Deal created: " + dealname
user = owneremail
timestamp = createdat
END WITH
SAVE "deal_activities.csv", dealActivity
TALK "Deal created: " + dealname
TALK "ID: " + dealid
TALK "Company: " + companyname
TALK "Value: $" + FORMAT(dealvalue, "#,##0")
TALK "Stage: " + stage + " (" + probability + "% probability)"
TALK "Expected Close: " + closedate
TALK "Weighted Value: $" + FORMAT(weightedvalue, "#,##0")
RETURN dealid

View file

@ -0,0 +1,176 @@
PARAM jobname AS STRING DESCRIPTION "Name of the scheduled job to execute"
DESCRIPTION "Scheduled jobs for pipeline maintenance, reminders, and reporting. Run automatically based on configured schedules."
' ============================================================================
' DAILY PIPELINE REPORT - Runs at 8:00 AM every day
' ============================================================================
IF jobname = "daily report" THEN
SET SCHEDULE "0 8 * * *"
' Get pipeline summary
let deals = FIND "deals.csv"
let opendeals = FILTER deals, "stage!=Closed Won AND stage!=Closed Lost"
' Calculate metrics
let totalvalue = AGGREGATE "SUM", opendeals, "dealvalue"
let weightedvalue = AGGREGATE "SUM", opendeals, "weightedvalue"
let dealcount = AGGREGATE "COUNT", opendeals, "dealid"
' Count by stage
let leads = FILTER opendeals, "stage=Lead"
let qualified = FILTER opendeals, "stage=Qualified"
let proposals = FILTER opendeals, "stage=Proposal"
let negotiations = FILTER opendeals, "stage=Negotiation"
let leadcount = AGGREGATE "COUNT", leads, "dealid"
let qualifiedcount = AGGREGATE "COUNT", qualified, "dealid"
let proposalcount = AGGREGATE "COUNT", proposals, "dealid"
let negotiationcount = AGGREGATE "COUNT", negotiations, "dealid"
' Build report
let reportdate = FORMAT TODAY() AS "MMMM DD, YYYY"
let subject = "Daily Pipeline Report - " + reportdate
let message = "Good morning!\n\n"
message = message + "Here is your daily pipeline summary:\n\n"
message = message + "PIPELINE OVERVIEW\n"
message = message + "================\n"
message = message + "Total Open Deals: " + dealcount + "\n"
message = message + "Total Pipeline Value: $" + FORMAT totalvalue AS "#,##0" + "\n"
message = message + "Weighted Value: $" + FORMAT weightedvalue AS "#,##0" + "\n\n"
message = message + "BY STAGE\n"
message = message + "========\n"
message = message + "Lead: " + leadcount + " deals\n"
message = message + "Qualified: " + qualifiedcount + " deals\n"
message = message + "Proposal: " + proposalcount + " deals\n"
message = message + "Negotiation: " + negotiationcount + " deals\n\n"
message = message + "Have a great selling day!\n"
message = message + "- Sales Pipeline Bot"
SEND MAIL "sales-team@company.com", subject, message
TALK "Daily pipeline report sent"
END IF
' ============================================================================
' STALE DEAL ALERTS - Runs at 9:00 AM every day
' ============================================================================
IF jobname = "stale alerts" THEN
SET SCHEDULE "0 9 * * *"
' Find deals not updated in 7+ days
let cutoffdate = FORMAT DATEADD(TODAY(), -7, "day") AS "YYYY-MM-DD"
let deals = FIND "deals.csv"
let staledeals = FILTER deals, "updatedat<" + cutoffdate + " AND stage!=Closed Won AND stage!=Closed Lost"
let stalecount = AGGREGATE "COUNT", staledeals, "dealid"
IF stalecount > 0 THEN
FOR EACH deal IN staledeals
let stalealert = "Your deal '" + deal.dealname + "' has not been updated in over 7 days.\n"
stalealert = stalealert + "Deal ID: " + deal.dealid + "\n"
stalealert = stalealert + "Current Stage: " + deal.stage + "\n"
stalealert = stalealert + "Value: $" + FORMAT deal.dealvalue AS "#,##0" + "\n\n"
stalealert = stalealert + "Please review and update this deal or mark it as closed."
SEND MAIL deal.owneremail, "Action Required: Stale Deal Alert", stalealert
NEXT deal
TALK "Sent " + stalecount + " stale deal alerts"
ELSE
TALK "No stale deals found"
END IF
END IF
' ============================================================================
' CLOSE DATE REMINDERS - Runs at 8:30 AM every day
' ============================================================================
IF jobname = "close reminders" THEN
SET SCHEDULE "30 8 * * *"
' Find deals closing in next 7 days
let today = FORMAT TODAY() AS "YYYY-MM-DD"
let nextweek = FORMAT DATEADD(TODAY(), 7, "day") AS "YYYY-MM-DD"
let deals = FIND "deals.csv"
let upcoming = FILTER deals, "closedate>=" + today + " AND closedate<=" + nextweek + " AND stage!=Closed Won AND stage!=Closed Lost"
let upcomingcount = AGGREGATE "COUNT", upcoming, "dealid"
IF upcomingcount > 0 THEN
FOR EACH deal IN upcoming
let daysuntil = DATEDIFF(TODAY(), deal.closedate, "day")
let reminder = "Deal Closing Soon!\n\n"
reminder = reminder + "Your deal '" + deal.dealname + "' is expected to close in " + daysuntil + " days.\n\n"
reminder = reminder + "Deal Details:\n"
reminder = reminder + "- Company: " + deal.companyname + "\n"
reminder = reminder + "- Value: $" + FORMAT deal.dealvalue AS "#,##0" + "\n"
reminder = reminder + "- Stage: " + deal.stage + "\n"
reminder = reminder + "- Close Date: " + deal.closedate + "\n\n"
reminder = reminder + "Make sure to follow up and push for the close!"
SEND MAIL deal.owneremail, "Reminder: Deal Closing in " + daysuntil + " Days", reminder
NEXT deal
TALK "Sent " + upcomingcount + " close date reminders"
ELSE
TALK "No deals closing in the next 7 days"
END IF
END IF
' ============================================================================
' WEEKLY FORECAST REPORT - Runs at 9:00 AM every Monday
' ============================================================================
IF jobname = "weekly forecast" THEN
SET SCHEDULE "0 9 * * 1"
' Get this month's deals
let monthstart = FORMAT DATEADD(TODAY(), 0, "month") AS "YYYY-MM-01"
let monthend = FORMAT DATEADD(TODAY(), 1, "month") AS "YYYY-MM-01"
let deals = FIND "deals.csv"
let monthdeals = FILTER deals, "closedate>=" + monthstart + " AND closedate<" + monthend
' Calculate forecast
let totalforecast = AGGREGATE "SUM", monthdeals, "weightedvalue"
let wondeals = FILTER monthdeals, "stage=Closed Won"
let closedvalue = AGGREGATE "SUM", wondeals, "dealvalue"
' Build forecast report
let reportdate = FORMAT TODAY() AS "MMMM DD, YYYY"
let monthname = FORMAT TODAY() AS "MMMM YYYY"
let subject = "Weekly Sales Forecast - " + reportdate
let message = "Weekly Forecast Report\n"
message = message + "======================\n\n"
message = message + "Month: " + monthname + "\n\n"
message = message + "Forecast Summary:\n"
message = message + "- Weighted Forecast: $" + FORMAT totalforecast AS "#,##0" + "\n"
message = message + "- Already Closed: $" + FORMAT closedvalue AS "#,##0" + "\n"
message = message + "- Remaining to Close: $" + FORMAT (totalforecast - closedvalue) AS "#,##0" + "\n\n"
message = message + "Keep pushing to hit your targets!\n"
message = message + "- Sales Pipeline Bot"
SEND MAIL "sales-team@company.com", subject, message
TALK "Weekly forecast report sent"
END IF
' ============================================================================
' SETUP SCHEDULES - Run once to configure all jobs
' ============================================================================
IF jobname = "setup schedules" THEN
TALK "Configuring pipeline scheduled jobs..."
TALK ""
TALK "📅 **Scheduled Jobs:**"
TALK "• Daily Pipeline Report: 8:00 AM daily"
TALK "• Stale Deal Alerts: 9:00 AM daily"
TALK "• Close Date Reminders: 8:30 AM daily"
TALK "• Weekly Forecast: 9:00 AM Mondays"
TALK ""
TALK "✅ All pipeline schedules configured!"
END IF

View file

@ -0,0 +1,48 @@
ADD TOOL "create-deal"
ADD TOOL "update-stage"
ADD TOOL "list-deals"
ADD TOOL "deal-details"
ADD TOOL "pipeline-report"
ADD TOOL "forecast-revenue"
USE KB "sales-pipeline.gbkb"
SET CONTEXT "sales pipeline" AS "You are a sales assistant helping manage the sales pipeline. Help with creating new deals, updating deal stages, viewing pipeline status, generating sales forecasts, and analyzing win/loss rates."
CLEAR SUGGESTIONS
ADD SUGGESTION "newdeal" AS "Create a new deal"
ADD SUGGESTION "pipeline" AS "Show my pipeline"
ADD SUGGESTION "update" AS "Update a deal stage"
ADD SUGGESTION "forecast" AS "View sales forecast"
ADD SUGGESTION "report" AS "Generate pipeline report"
BEGIN TALK
**Sales Pipeline Manager**
I can help you with:
Create new deals and opportunities
View and manage your pipeline
Update deal stages
Generate sales forecasts
Pipeline analytics and reports
Track win/loss rates
Select an option or tell me what you need.
END TALK
BEGIN SYSTEM PROMPT
You are a sales pipeline assistant.
Pipeline stages:
- Lead: Initial contact, not qualified
- Qualified: Budget, authority, need, timeline confirmed
- Proposal: Quote sent
- Negotiation: Active discussions
- Closed Won: Successfully closed
- Closed Lost: Lost or no decision
Always encourage sales reps and provide actionable insights.
Confirm changes before saving.
Use currency format for amounts.
END SYSTEM PROMPT

View file

@ -0,0 +1,130 @@
PARAM dealid AS STRING LIKE "DEAL-20250115-1234" DESCRIPTION "The deal ID to update"
PARAM newstage AS STRING LIKE "Qualified" DESCRIPTION "New stage: Lead, Qualified, Proposal, Negotiation, Closed Won, Closed Lost"
PARAM reason AS STRING LIKE "Budget confirmed" DESCRIPTION "Optional reason for stage change"
DESCRIPTION "Updates the stage of an existing deal in the pipeline. Automatically updates probability and logs the activity."
' Validate deal ID
IF dealid = "" THEN
TALK "Which deal would you like to update? Please provide the deal ID."
HEAR dealid AS STRING
END IF
IF dealid = "" THEN
let lastdeal = GET BOT MEMORY("last_deal")
IF lastdeal != "" THEN
TALK "Would you like to update the last deal: " + lastdeal + "?"
HEAR confirm AS BOOLEAN
IF confirm THEN
dealid = lastdeal
ELSE
TALK "Please provide a deal ID to update."
RETURN
END IF
ELSE
TALK "I need a deal ID to update."
RETURN
END IF
END IF
' Validate new stage
IF newstage = "" THEN
TALK "What stage should this deal move to?"
TALK "Options: Lead, Qualified, Proposal, Negotiation, Closed Won, Closed Lost"
HEAR newstage AS STRING
END IF
' Normalize stage name
newstage = UCASE(LEFT(newstage, 1)) + LCASE(MID(newstage, 2))
' Validate stage is valid
let validstages = "Lead,Qualified,Proposal,Negotiation,Closed Won,Closed Lost"
IF INSTR(validstages, newstage) = 0 THEN
TALK "Invalid stage. Please use: Lead, Qualified, Proposal, Negotiation, Closed Won, or Closed Lost"
RETURN
END IF
' Determine probability based on stage
let probability = 10
IF newstage = "Lead" THEN
probability = 10
ELSE IF newstage = "Qualified" THEN
probability = 25
ELSE IF newstage = "Proposal" THEN
probability = 50
ELSE IF newstage = "Negotiation" THEN
probability = 75
ELSE IF newstage = "Closed Won" THEN
probability = 100
ELSE IF newstage = "Closed Lost" THEN
probability = 0
END IF
' Get current timestamp
let updatedat = FORMAT NOW() AS "YYYY-MM-DD HH:mm:ss"
let useremail = GET "session.user_email"
' Update the deal
UPDATE "deals.csv", "dealid=" + dealid, stage, probability, updatedat
' Log activity
let activity = "Stage changed to " + newstage
IF reason != "" THEN
activity = activity + " - " + reason
END IF
SAVE "deal_activities.csv", dealid, activity, useremail, updatedat
' Store last updated deal
SET BOT MEMORY "last_deal", dealid
' Respond based on stage
IF newstage = "Closed Won" THEN
TALK "🎉 **Congratulations! Deal Won!**"
TALK ""
TALK "**Deal " + dealid + "** has been marked as **Closed Won**!"
TALK "Great work closing this deal!"
TALK ""
TALK "📊 Probability: 100%"
ELSE IF newstage = "Closed Lost" THEN
TALK "📋 **Deal Closed Lost**"
TALK ""
TALK "**Deal " + dealid + "** has been marked as **Closed Lost**."
IF reason != "" THEN
TALK "📝 Reason: " + reason
END IF
TALK ""
TALK "Don't worry - analyze what happened and apply the learnings to future deals!"
ELSE
TALK "✅ **Deal Stage Updated!**"
TALK ""
TALK "**Deal " + dealid + "** moved to **" + newstage + "**"
TALK "📊 New Probability: " + probability + "%"
IF reason != "" THEN
TALK "📝 Note: " + reason
END IF
TALK ""
TALK "Keep the momentum going!"
END IF
' Suggest next actions based on stage
IF newstage = "Qualified" THEN
TALK ""
TALK "💡 **Next Steps:**"
TALK "• Prepare a tailored proposal"
TALK "• Schedule a demo or presentation"
TALK "• Identify key stakeholders"
ELSE IF newstage = "Proposal" THEN
TALK ""
TALK "💡 **Next Steps:**"
TALK "• Follow up within 48 hours"
TALK "• Address any questions or concerns"
TALK "• Identify decision timeline"
ELSE IF newstage = "Negotiation" THEN
TALK ""
TALK "💡 **Next Steps:**"
TALK "• Clarify any contract terms"
TALK "• Prepare for potential objections"
TALK "• Confirm decision makers and process"
END IF

View file

@ -0,0 +1,158 @@
# Sales Methodology Guide
## Pipeline Stages Overview
### 1. Lead Stage (10% Probability)
A lead is an initial contact or potential opportunity that has not yet been qualified.
**Entry Criteria:**
- First contact made with prospect
- Basic company information gathered
- Initial interest expressed
**Activities:**
- Research the company and contact
- Identify potential use cases
- Schedule discovery call
- Gather basic requirements
**Exit Criteria:**
- Discovery call completed
- Budget, Authority, Need, Timeline (BANT) partially identified
- Prospect agrees to next meeting
### 2. Qualified Stage (25% Probability)
A qualified opportunity has confirmed need and basic fit with our solution.
**Entry Criteria:**
- BANT criteria confirmed
- Decision maker identified
- Clear use case defined
- Timeline established
**Activities:**
- Deep dive into requirements
- Identify all stakeholders
- Map decision process
- Schedule demo or presentation
**Exit Criteria:**
- Demo completed
- Proposal requested
- Budget confirmed
### 3. Proposal Stage (50% Probability)
A formal proposal or quote has been submitted to the prospect.
**Entry Criteria:**
- Requirements documented
- Pricing approved internally
- Proposal sent to prospect
**Activities:**
- Present proposal
- Address questions
- Handle objections
- Negotiate terms if needed
**Exit Criteria:**
- Proposal reviewed by prospect
- Feedback received
- Negotiation phase begins
### 4. Negotiation Stage (75% Probability)
Active discussions on pricing, terms, or contract details.
**Entry Criteria:**
- Proposal accepted in principle
- Negotiations on terms begun
- Legal or procurement involved
**Activities:**
- Negotiate pricing
- Finalize contract terms
- Address legal concerns
- Get final sign-off
**Exit Criteria:**
- Terms agreed
- Contract ready for signature
- Purchase order received
### 5. Closed Won (100% Probability)
Deal successfully closed and contract signed.
**Entry Criteria:**
- Contract signed
- Payment terms agreed
- Start date confirmed
**Activities:**
- Hand off to implementation
- Send welcome materials
- Schedule kickoff
### 6. Closed Lost (0% Probability)
Deal lost to competitor, no decision, or other reason.
**Common Loss Reasons:**
- Lost to competitor
- No budget
- No decision / timing
- Requirements changed
- Contact went silent
## Best Practices
### Deal Hygiene
1. **Update deals regularly** - Review and update each deal at least weekly
2. **Accurate close dates** - Keep expected close dates realistic
3. **Stage accuracy** - Ensure deals are in the correct stage
4. **Notes matter** - Document all key interactions
### Forecasting Tips
- Weighted pipeline = Deal Value × Probability
- Focus on deals closing this month
- Review stale deals weekly
- Be conservative with close dates
### Common Objections and Responses
**"It's too expensive"**
- Focus on ROI and value
- Break down cost per user
- Compare to cost of not solving the problem
**"We're not ready"**
- Understand the timing concern
- Offer phased implementation
- Stay in touch for future opportunity
**"We're evaluating competitors"**
- Understand their criteria
- Highlight differentiators
- Request fair comparison opportunity
## Key Metrics
| Metric | Target | Description |
|--------|--------|-------------|
| Win Rate | 25%+ | Closed Won / Total Closed |
| Avg Deal Size | Varies | Average value of won deals |
| Sales Cycle | 30-90 days | Avg time from Lead to Close |
| Pipeline Coverage | 3x quota | Total pipeline vs. target |
## Getting Help
- For deal strategy: Contact your sales manager
- For pricing: Contact sales operations
- For technical questions: Contact solutions engineering
- For contract terms: Contact legal

View file

@ -0,0 +1,9 @@
name,value
episodic-memory-history,2
episodic-memory-threshold,4
theme-color1,#2E7D32
theme-color2,#E8F5E9
theme-logo,https://pragmatismo.com.br/icons/general-bots.svg
theme-title,Sales Pipeline - General Bots
bot-name,Sales Pipeline Assistant
welcome-message,Welcome to the Sales Pipeline Manager!
1 name value
2 episodic-memory-history 2
3 episodic-memory-threshold 4
4 theme-color1 #2E7D32
5 theme-color2 #E8F5E9
6 theme-logo https://pragmatismo.com.br/icons/general-bots.svg
7 theme-title Sales Pipeline - General Bots
8 bot-name Sales Pipeline Assistant
9 welcome-message Welcome to the Sales Pipeline Manager!

View file

@ -0,0 +1,102 @@
PARAM expression AS STRING LIKE "2 + 2" DESCRIPTION "Mathematical expression to calculate"
DESCRIPTION "Calculate mathematical expressions, conversions, and formulas"
WITH result
expression = expression
timestamp = NOW()
END WITH
expr = REPLACE(expression, " ", "")
IF INSTR(expr, "+") > 0 THEN
parts = SPLIT(expr, "+")
IF UBOUND(parts) = 2 THEN
result.answer = VAL(parts[0]) + VAL(parts[1])
result.operation = "addition"
END IF
ELSE IF INSTR(expr, "-") > 0 AND LEFT(expr, 1) <> "-" THEN
parts = SPLIT(expr, "-")
IF UBOUND(parts) = 2 THEN
result.answer = VAL(parts[0]) - VAL(parts[1])
result.operation = "subtraction"
END IF
ELSE IF INSTR(expr, "*") > 0 THEN
parts = SPLIT(expr, "*")
IF UBOUND(parts) = 2 THEN
result.answer = VAL(parts[0]) * VAL(parts[1])
result.operation = "multiplication"
END IF
ELSE IF INSTR(expr, "/") > 0 THEN
parts = SPLIT(expr, "/")
IF UBOUND(parts) = 2 THEN
IF VAL(parts[1]) <> 0 THEN
result.answer = VAL(parts[0]) / VAL(parts[1])
result.operation = "division"
ELSE
TALK "Error: Division by zero"
RETURN NULL
END IF
END IF
ELSE IF INSTR(LCASE(expr), "sqrt") > 0 THEN
start_pos = INSTR(LCASE(expr), "sqrt(") + 5
end_pos = INSTR(start_pos, expr, ")")
IF end_pos > start_pos THEN
num = VAL(MID(expr, start_pos, end_pos - start_pos))
IF num >= 0 THEN
result.answer = SQR(num)
result.operation = "square root"
ELSE
TALK "Error: Cannot calculate square root of negative number"
RETURN NULL
END IF
END IF
ELSE IF INSTR(expr, "^") > 0 THEN
parts = SPLIT(expr, "^")
IF UBOUND(parts) = 2 THEN
result.answer = VAL(parts[0]) ^ VAL(parts[1])
result.operation = "power"
END IF
ELSE IF INSTR(LCASE(expr), "abs") > 0 THEN
start_pos = INSTR(LCASE(expr), "abs(") + 4
end_pos = INSTR(start_pos, expr, ")")
IF end_pos > start_pos THEN
result.answer = ABS(VAL(MID(expr, start_pos, end_pos - start_pos)))
result.operation = "absolute value"
END IF
ELSE IF INSTR(LCASE(expr), "round") > 0 THEN
start_pos = INSTR(LCASE(expr), "round(") + 6
end_pos = INSTR(start_pos, expr, ")")
IF end_pos > start_pos THEN
result.answer = ROUND(VAL(MID(expr, start_pos, end_pos - start_pos)), 0)
result.operation = "rounding"
END IF
ELSE IF INSTR(expr, "%") > 0 AND INSTR(LCASE(expr), "of") > 0 THEN
expr_lower = LCASE(expr)
of_pos = INSTR(expr_lower, "of")
percent_part = REPLACE(LEFT(expr, of_pos - 1), "%", "")
percent_val = VAL(TRIM(percent_part))
base_val = VAL(TRIM(MID(expr, of_pos + 2)))
result.answer = (percent_val / 100) * base_val
result.operation = "percentage"
ELSE
result.answer = VAL(expr)
result.operation = "direct value"
END IF
IF result.answer <> NULL THEN
TALK "Result: " + result.answer
RETURN result
ELSE
TALK "Could not calculate expression"
RETURN NULL
END IF

View file

@ -0,0 +1,26 @@
PARAM to_email AS EMAIL LIKE "user@example.com" DESCRIPTION "Recipient email address"
PARAM subject AS STRING LIKE "Important Message" DESCRIPTION "Email subject line"
PARAM body AS STRING LIKE "Hello, this is the email content." DESCRIPTION "Email body content"
PARAM from_email AS EMAIL LIKE "noreply@company.com" DESCRIPTION "Sender email address" OPTIONAL
DESCRIPTION "Send an email to any recipient with subject and body"
IF NOT from_email THEN
from_email = "noreply@pragmatismo.com.br"
END IF
WITH email_data
to = to_email
from = from_email
subject = subject
body = body
timestamp = NOW()
END WITH
SEND EMAIL to_email, subject, body
SAVE "email_log.csv", email_data
TALK "Email sent to " + to_email
RETURN email_data

View file

@ -0,0 +1,28 @@
PARAM phone_number AS PHONE LIKE "+1234567890" DESCRIPTION "Phone number with country code"
PARAM message AS STRING LIKE "Hello, this is your message" DESCRIPTION "SMS message content"
PARAM from_number AS PHONE LIKE "+1987654321" DESCRIPTION "Sender phone number" OPTIONAL
DESCRIPTION "Send an SMS message to any phone number"
message_length = LEN(message)
segments = INT((message_length - 1) / 160) + 1
IF message_length > 160 THEN
TALK "Message will be split into " + segments + " segments"
END IF
WITH sms
to = phone_number
from = from_number
body = message
timestamp = NOW()
segmentCount = segments
END WITH
SEND SMS phone_number, message
SAVE "sms_log.csv", sms
TALK "SMS sent to " + phone_number
RETURN sms

View file

@ -0,0 +1,60 @@
PARAM text AS STRING LIKE "Hello, how are you?" DESCRIPTION "Text to translate"
PARAM from_lang AS STRING LIKE "en" DESCRIPTION "Source language code (en, es, pt, fr, de, etc)" OPTIONAL
PARAM to_lang AS STRING LIKE "es" DESCRIPTION "Target language code (en, es, pt, fr, de, etc)" OPTIONAL
DESCRIPTION "Translate text between languages using free translation API"
IF NOT from_lang THEN
from_lang = "en"
END IF
IF NOT to_lang THEN
to_lang = "es"
END IF
TALK "Translating from " + from_lang + " to " + to_lang + "..."
WITH post_data
q = text
source = from_lang
target = to_lang
format = "text"
END WITH
SET HEADER "Content-Type" = "application/json"
translation_result = POST "https://libretranslate.com/translate", post_data
IF translation_result.translatedText THEN
WITH result
original = text
translated = translation_result.translatedText
from = from_lang
to = to_lang
END WITH
TALK "Original (" + from_lang + "): " + text
TALK "Translated (" + to_lang + "): " + result.translated
RETURN result
ELSE
mymemory_url = "https://api.mymemory.translated.net/get?q=" + text + "&langpair=" + from_lang + "|" + to_lang
fallback_result = GET mymemory_url
IF fallback_result.responseData.translatedText THEN
WITH result
original = text
translated = fallback_result.responseData.translatedText
from = from_lang
to = to_lang
END WITH
TALK "Original (" + from_lang + "): " + text
TALK "Translated (" + to_lang + "): " + result.translated
RETURN result
ELSE
TALK "Could not translate text"
RETURN NULL
END IF
END IF

View file

@ -0,0 +1,112 @@
PARAM location AS STRING LIKE "New York" DESCRIPTION "City or location to get weather forecast"
DESCRIPTION "Get current weather forecast for any city or location"
lat = 40.7128
lon = -74.0060
location_lower = LCASE(location)
IF INSTR(location_lower, "new york") > 0 THEN
lat = 40.7128
lon = -74.0060
ELSE IF INSTR(location_lower, "london") > 0 THEN
lat = 51.5074
lon = -0.1278
ELSE IF INSTR(location_lower, "paris") > 0 THEN
lat = 48.8566
lon = 2.3522
ELSE IF INSTR(location_lower, "tokyo") > 0 THEN
lat = 35.6762
lon = 139.6503
ELSE IF INSTR(location_lower, "sydney") > 0 THEN
lat = -33.8688
lon = 151.2093
ELSE IF INSTR(location_lower, "berlin") > 0 THEN
lat = 52.5200
lon = 13.4050
ELSE IF INSTR(location_lower, "madrid") > 0 THEN
lat = 40.4168
lon = -3.7038
ELSE IF INSTR(location_lower, "sao paulo") > 0 OR INSTR(location_lower, "são paulo") > 0 THEN
lat = -23.5505
lon = -46.6333
ELSE IF INSTR(location_lower, "rio") > 0 THEN
lat = -22.9068
lon = -43.1729
ELSE IF INSTR(location_lower, "los angeles") > 0 THEN
lat = 34.0522
lon = -118.2437
ELSE IF INSTR(location_lower, "chicago") > 0 THEN
lat = 41.8781
lon = -87.6298
ELSE IF INSTR(location_lower, "toronto") > 0 THEN
lat = 43.6532
lon = -79.3832
ELSE IF INSTR(location_lower, "dubai") > 0 THEN
lat = 25.2048
lon = 55.2708
ELSE IF INSTR(location_lower, "singapore") > 0 THEN
lat = 1.3521
lon = 103.8198
ELSE IF INSTR(location_lower, "mumbai") > 0 THEN
lat = 19.0760
lon = 72.8777
ELSE IF INSTR(location_lower, "beijing") > 0 THEN
lat = 39.9042
lon = 116.4074
END IF
weather_url = "https://api.open-meteo.com/v1/forecast?latitude=" + lat + "&longitude=" + lon + "&current_weather=true&timezone=auto"
weather_data = GET weather_url
IF weather_data.current_weather THEN
current = weather_data.current_weather
code = current.weathercode
condition = "Clear"
icon = "☀️"
IF code = 0 THEN
condition = "Clear sky"
icon = "☀️"
ELSE IF code >= 1 AND code <= 3 THEN
condition = "Partly cloudy"
icon = "⛅"
ELSE IF code >= 45 AND code <= 48 THEN
condition = "Foggy"
icon = "🌫️"
ELSE IF code >= 51 AND code <= 67 THEN
condition = "Rainy"
icon = "🌧️"
ELSE IF code >= 71 AND code <= 77 THEN
condition = "Snowy"
icon = "❄️"
ELSE IF code >= 80 AND code <= 82 THEN
condition = "Rain showers"
icon = "🌦️"
ELSE IF code >= 95 AND code <= 99 THEN
condition = "Thunderstorm"
icon = "⛈️"
END IF
WITH result
loc = location
temperature = current.temperature
windspeed = current.windspeed
weathercode = code
cond = condition
ico = icon
END WITH
TALK icon + " Weather for " + location + ":"
TALK "Temperature: " + current.temperature + "°C"
TALK "Condition: " + condition
TALK "Wind: " + current.windspeed + " km/h"
RETURN result
ELSE
TALK "Could not fetch weather for: " + location
RETURN NULL
END IF

View file

@ -0,0 +1,127 @@
# Getting Started with General Bots
## Overview
Welcome to General Bots! This guide will help you understand the basic features available in your default bot installation.
## Available Features
### Calculator
Perform mathematical calculations by asking the bot to calculate expressions.
**Examples:**
- "Calculate 25 * 4"
- "What is 1500 / 12?"
- "Calculate 15% of 200"
### Send Email
Send emails directly through the bot.
**How to use:**
1. Say "Send email" or "Send an email"
2. Provide the recipient's email address
3. Enter the subject line
4. Type your message content
**Example:**
- "Send an email to john@example.com"
- "I need to email my team"
### Send SMS
Send text messages to mobile phones.
**How to use:**
1. Say "Send SMS" or "Send a text message"
2. Provide the phone number (with country code)
3. Enter your message
**Example:**
- "Send SMS to +1234567890"
- "Text message to my contact"
### Translation
Translate text between different languages.
**How to use:**
1. Say "Translate" followed by the text
2. Specify the target language
**Examples:**
- "Translate 'Hello, how are you?' to Spanish"
- "Translate this text to Portuguese"
- "How do you say 'thank you' in French?"
### Weather
Get current weather information for any location.
**How to use:**
1. Ask about the weather for a specific location
**Examples:**
- "What's the weather in New York?"
- "Weather forecast for London"
- "Is it going to rain in Tokyo?"
## Tips for Better Interactions
### Be Specific
The more specific your request, the better the bot can help you. Include relevant details like:
- Email addresses for sending emails
- Phone numbers with country codes for SMS
- City names for weather queries
### Natural Language
You can speak naturally to the bot. It understands various ways of asking for the same thing:
- "Calculate 10 + 5" or "What is 10 plus 5?"
- "Send email" or "I need to email someone"
- "Translate to Spanish" or "How do you say this in Spanish?"
### Confirmation
The bot will ask for confirmation before performing actions like sending emails or SMS to ensure accuracy.
## Extending Your Bot
This default template provides basic functionality. You can extend your bot by:
1. **Adding Knowledge Base**: Create `.md` files in the `.gbkb` folder to give your bot domain-specific knowledge
2. **Creating Dialogs**: Add `.bas` files in the `.gbdialog` folder for custom conversations
3. **Installing Templates**: Add pre-built templates for CRM, HR, helpdesk, and more
4. **Connecting APIs**: Integrate external services for expanded functionality
## Frequently Asked Questions
**Q: How do I add more features to my bot?**
A: Install additional templates or create custom dialog scripts in the `.gbdialog` folder.
**Q: Can the bot remember previous conversations?**
A: Yes, the bot maintains context within a session. For persistent memory, use the memory features in custom dialogs.
**Q: What languages are supported?**
A: The bot supports multiple languages for both interface and translation. Common languages include English, Portuguese, Spanish, French, German, and many others.
**Q: How do I change the bot's appearance?**
A: Modify the `config.csv` file in the `.gbot` folder to change colors, logo, and title.
**Q: Is my data secure?**
A: Yes, all communications are encrypted. Sensitive data like passwords should never be shared in chat.
## Getting Help
If you need assistance:
- Ask the bot "Help" for available commands
- Check the documentation at docs.pragmatismo.com.br
- Contact support for technical issues
## Next Steps
1. Try out each feature to see how it works
2. Explore the template library for pre-built solutions
3. Customize your bot with your own knowledge base
4. Create custom dialogs for your specific use cases
Welcome aboard, and enjoy using General Bots!

View file

@ -0,0 +1,228 @@
name,value
,
# ============================================================================
# SERVER CONFIGURATION
# ============================================================================
server_host,0.0.0.0
server_port,8088
sites_root,/tmp
,
# ============================================================================
# LLM CONFIGURATION
# ============================================================================
llm-key,none
llm-url,http://localhost:8081
llm-model,../../../../data/llm/DeepSeek-R1-Distill-Qwen-1.5B-Q3_K_M.gguf
,
llm-cache,false
llm-cache-ttl,3600
llm-cache-semantic,true
llm-cache-threshold,0.95
,
episodic-memory-threshold,4
,
mcp-server,false
,
# ============================================================================
# EMBEDDING CONFIGURATION
# ============================================================================
embedding-url,http://localhost:8082
embedding-model,../../../../data/llm/bge-small-en-v1.5-f32.gguf
,
# ============================================================================
# LLM SERVER CONFIGURATION
# ============================================================================
llm-server,true
llm-server-path,botserver-stack/bin/llm/build/bin
llm-server-host,0.0.0.0
llm-server-port,8081
llm-server-gpu-layers,0
llm-server-n-moe,0
llm-server-ctx-size,4096
llm-server-n-predict,1024
llm-server-parallel,6
llm-server-cont-batching,true
llm-server-mlock,false
llm-server-no-mmap,false
,
# ============================================================================
# EMAIL CONFIGURATION
# ============================================================================
email-from,from@domain.com
email-server,mail.domain.com
email-port,587
email-user,user@domain.com
email-pass,
,
# ============================================================================
# DATABASE CONFIGURATION
# ============================================================================
custom-server,localhost
custom-port,5432
custom-database,mycustomdb
custom-username,
custom-password,
,
# ============================================================================
# WEBSITE CRAWLER CONFIGURATION
# ============================================================================
website-expires,1d
website-max-depth,3
website-max-pages,100
,
# ============================================================================
# IMAGE GENERATOR CONFIGURATION
# ============================================================================
image-generator-model,../../../../data/diffusion/sd_turbo_f16.gguf
image-generator-steps,4
image-generator-width,512
image-generator-height,512
image-generator-gpu-layers,20
image-generator-batch-size,1
,
# ============================================================================
# VIDEO GENERATOR CONFIGURATION
# ============================================================================
video-generator-model,../../../../data/diffusion/zeroscope_v2_576w
video-generator-frames,24
video-generator-fps,8
video-generator-width,320
video-generator-height,576
video-generator-gpu-layers,15
video-generator-batch-size,1
,
# ============================================================================
# BOTMODELS CONFIGURATION
# ============================================================================
botmodels-enabled,true
botmodels-host,0.0.0.0
botmodels-port,8085
,
default-generator,all
,
# ============================================================================
# OAUTH AUTHENTICATION CONFIGURATION
# ============================================================================
# Enable social login providers by setting the corresponding -enabled flag
# to "true" and providing valid client credentials.
#
# Each provider requires:
# - oauth-{provider}-enabled: Set to "true" to enable the provider
# - oauth-{provider}-client-id: The Client ID from the provider
# - oauth-{provider}-client-secret: The Client Secret from the provider
# - oauth-{provider}-redirect-uri: (Optional) Custom callback URL
#
# Default redirect URI format: http://your-domain/auth/oauth/{provider}/callback
# ============================================================================
,
# ----------------------------------------------------------------------------
# GOOGLE OAUTH
# ----------------------------------------------------------------------------
# Setup Instructions:
# 1. Go to https://console.cloud.google.com/apis/credentials
# 2. Create a new project or select existing
# 3. Click "Create Credentials" > "OAuth client ID"
# 4. Select "Web application" as application type
# 5. Add authorized redirect URI: http://your-domain/auth/oauth/google/callback
# 6. Copy the Client ID and Client Secret below
#
# Documentation: https://developers.google.com/identity/protocols/oauth2/web-server
# ----------------------------------------------------------------------------
oauth-google-enabled,false
oauth-google-client-id,
oauth-google-client-secret,
oauth-google-redirect-uri,
,
# ----------------------------------------------------------------------------
# MICROSOFT OAUTH (Azure AD)
# ----------------------------------------------------------------------------
# Setup Instructions:
# 1. Go to https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationsListBlade
# 2. Click "New registration"
# 3. Enter application name and select "Accounts in any organizational directory and personal Microsoft accounts"
# 4. Add redirect URI: http://your-domain/auth/oauth/microsoft/callback (Web platform)
# 5. Go to "Certificates & secrets" > "New client secret"
# 6. Copy the Application (client) ID and secret value below
#
# Documentation: https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app
# ----------------------------------------------------------------------------
oauth-microsoft-enabled,false
oauth-microsoft-client-id,
oauth-microsoft-client-secret,
oauth-microsoft-redirect-uri,
,
# ----------------------------------------------------------------------------
# DISCORD OAUTH
# ----------------------------------------------------------------------------
# Setup Instructions:
# 1. Go to https://discord.com/developers/applications
# 2. Click "New Application" and enter a name
# 3. Go to "OAuth2" in the left sidebar
# 4. Add redirect URL: http://your-domain/auth/oauth/discord/callback
# 5. Copy the Client ID and Client Secret below
# 6. Under "OAuth2 URL Generator", select scopes: identify, email
#
# Documentation: https://discord.com/developers/docs/topics/oauth2
# ----------------------------------------------------------------------------
oauth-discord-enabled,false
oauth-discord-client-id,
oauth-discord-client-secret,
oauth-discord-redirect-uri,
,
# ----------------------------------------------------------------------------
# FACEBOOK OAUTH
# ----------------------------------------------------------------------------
# Setup Instructions:
# 1. Go to https://developers.facebook.com/apps/
# 2. Click "Create App" > Select "Consumer" or "Business"
# 3. Add "Facebook Login" product to your app
# 4. Go to Facebook Login > Settings
# 5. Add Valid OAuth Redirect URI: http://your-domain/auth/oauth/facebook/callback
# 6. Go to Settings > Basic to get App ID and App Secret
#
# Documentation: https://developers.facebook.com/docs/facebook-login/guides/advanced/manual-flow
# ----------------------------------------------------------------------------
oauth-facebook-enabled,false
oauth-facebook-client-id,
oauth-facebook-client-secret,
oauth-facebook-redirect-uri,
,
# ----------------------------------------------------------------------------
# TWITTER (X) OAUTH 2.0
# ----------------------------------------------------------------------------
# Setup Instructions:
# 1. Go to https://developer.twitter.com/en/portal/dashboard
# 2. Create a new project and app (or use existing)
# 3. Go to your app's "Keys and tokens" tab
# 4. Under "OAuth 2.0 Client ID and Client Secret", generate credentials
# 5. Go to "User authentication settings" and configure:
# - Enable OAuth 2.0
# - Type: Web App
# - Callback URL: http://your-domain/auth/oauth/twitter/callback
# 6. Copy Client ID and Client Secret below
#
# Note: Twitter requires OAuth 2.0 with PKCE for web apps
# Documentation: https://developer.twitter.com/en/docs/authentication/oauth-2-0
# ----------------------------------------------------------------------------
oauth-twitter-enabled,false
oauth-twitter-client-id,
oauth-twitter-client-secret,
oauth-twitter-redirect-uri,
,
# ----------------------------------------------------------------------------
# REDDIT OAUTH
# ----------------------------------------------------------------------------
# Setup Instructions:
# 1. Go to https://www.reddit.com/prefs/apps
# 2. Click "create another app..." at the bottom
# 3. Select "web app" as the application type
# 4. Enter redirect URI: http://your-domain/auth/oauth/reddit/callback
# 5. Copy the client ID (under app name) and secret below
#
# Note: Reddit requires Basic Auth for token exchange and custom User-Agent
# Documentation: https://github.com/reddit-archive/reddit/wiki/OAuth2
# ----------------------------------------------------------------------------
oauth-reddit-enabled,false
oauth-reddit-client-id,
oauth-reddit-client-secret,
oauth-reddit-redirect-uri,
Can't render this file because it contains an unexpected character in line 107 and column 6.

1043
drive.html Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,3 @@
Id,Name,Birthday,Email,Personalid,Address
lwkerderv,John Godf,12/12/2001,johng@fool.com.tg,12381239923,"Boulevard Street, 329"
ekelwbctw,Jorge Santos,12/01/1978,jorge@uol.com.br,1239892998,"Rua Teodoro, 39"
1 Id Name Birthday Email Personalid Address
2 lwkerderv John Godf 12/12/2001 johng@fool.com.tg 12381239923 Boulevard Street, 329
3 ekelwbctw Jorge Santos 12/01/1978 jorge@uol.com.br 1239892998 Rua Teodoro, 39

View file

@ -0,0 +1,35 @@
PARAM name AS STRING LIKE "Abreu Silva" DESCRIPTION "Full name of the student"
PARAM birthday AS DATE LIKE "23/09/2001" DESCRIPTION "Birth date in DD/MM/YYYY format"
PARAM email AS EMAIL LIKE "abreu.silva@example.com" DESCRIPTION "Email address for contact"
PARAM personalid AS STRING LIKE "12345678900" DESCRIPTION "Personal ID number (only numbers)"
PARAM address AS STRING LIKE "Rua das Flores, 123 - SP" DESCRIPTION "Full address"
DESCRIPTION "Process student enrollment with validation and confirmation"
enrollmentid = "ENR-" + FORMAT(NOW(), "YYYYMMDD") + "-" + FORMAT(RANDOM(1000, 9999))
createdat = FORMAT(NOW(), "YYYY-MM-DD HH:mm:ss")
WITH enrollment
id = enrollmentid
studentName = name
birthDate = birthday
emailAddress = email
personalId = personalid
fullAddress = address
createdAt = createdat
status = "pending"
END WITH
SAVE "enrollments.csv", enrollment
SET BOT MEMORY "last_enrollment", enrollmentid
TALK "Enrollment submitted successfully!"
TALK "Enrollment ID: " + enrollmentid
TALK "Name: " + name
TALK "Email: " + email
TALK "Status: Pending review"
SEND EMAIL email, "Enrollment Confirmation", "Dear " + name + ",\n\nYour enrollment request has been submitted.\n\nEnrollment ID: " + enrollmentid + "\n\nWe will review your application and contact you soon.\n\nBest regards,\nAdmissions Team"
RETURN enrollmentid

View file

@ -0,0 +1,46 @@
ADD TOOL "enrollment"
ADD TOOL "course-info"
ADD TOOL "schedule"
ADD TOOL "grades"
ADD TOOL "tuition"
ADD TOOL "support"
USE KB "edu.gbkb"
CLEAR SUGGESTIONS
ADD SUGGESTION "enroll" AS "Enroll in a course"
ADD SUGGESTION "courses" AS "View available courses"
ADD SUGGESTION "schedule" AS "My class schedule"
ADD SUGGESTION "grades" AS "Check my grades"
ADD SUGGESTION "tuition" AS "Payment information"
ADD SUGGESTION "help" AS "Academic support"
SET CONTEXT "education" AS "You are an educational institution assistant helping with enrollment, courses, schedules, grades, and academic support. Be helpful and guide students through processes clearly."
BEGIN TALK
**Education Assistant**
Welcome! I can help you with:
Course enrollment and registration
Available courses and programs
Class schedules and calendars
Grades and transcripts
Tuition and payment info
Academic support and advising
Select an option or ask me anything.
END TALK
BEGIN SYSTEM PROMPT
You are an AI assistant for an educational institution.
Be friendly and professional.
Provide clear, accurate assistance.
Reduce administrative workload by handling common inquiries.
Help with enrollment and registration.
Provide course information and prerequisites.
Answer admissions questions.
Guide through registration process.
Explain academic policies.
END SYSTEM PROMPT

View file

@ -0,0 +1,236 @@
# Student Guide
## Welcome to Our Educational Institution
This guide will help you navigate our services and make the most of your educational experience.
## Getting Started
### New Student Checklist
1. **Complete Registration**: Submit all required documents
2. **Activate Your Account**: Set up your student portal access
3. **Review Course Catalog**: Explore available courses and programs
4. **Meet Your Advisor**: Schedule an initial advising session
5. **Attend Orientation**: Learn about campus resources and policies
### Required Documents
- Official transcripts from previous institutions
- Government-issued photo ID
- Proof of residency (if applicable)
- Vaccination records
- Financial aid documentation (if applicable)
## Enrollment and Registration
### How to Enroll
1. Log into the student portal
2. Select "Enrollment" or ask this assistant "Enroll in a course"
3. Search for your desired course
4. Check prerequisites and availability
5. Add the course to your schedule
6. Confirm enrollment
### Registration Periods
| Period | Dates | Who Can Register |
|--------|-------|------------------|
| Priority | 2 weeks before term | Seniors, Honors students |
| General | 1 week before term | All students |
| Late | First week of term | With advisor approval |
| Add/Drop | First 2 weeks | All enrolled students |
### Prerequisites
Some courses require completion of other courses first. To check prerequisites:
- View the course description in the catalog
- Ask this assistant about specific course requirements
- Consult with your academic advisor
## Academic Programs
### Degree Types
- **Certificate Programs**: 6-12 months, focused skills training
- **Associate Degree**: 2 years, foundational education
- **Bachelor's Degree**: 4 years, comprehensive education
- **Master's Degree**: 1-2 years post-bachelor's
- **Doctoral Degree**: 3-5 years post-master's
### Majors and Concentrations
Contact your academic advisor or ask this assistant to explore:
- Available majors in your school
- Concentration options within majors
- Minor programs
- Dual degree opportunities
## Class Schedules
### Viewing Your Schedule
Ask this assistant "My class schedule" or log into the student portal to see:
- Course names and codes
- Meeting times and locations
- Instructor information
- Important dates (exams, project due dates)
### Schedule Formats
| Format | Description | Best For |
|--------|-------------|----------|
| In-Person | Traditional classroom | Hands-on learning |
| Online Synchronous | Live virtual classes | Remote with interaction |
| Online Asynchronous | Self-paced online | Flexible schedules |
| Hybrid | Mix of in-person and online | Balanced approach |
## Grades and Transcripts
### Grading Scale
| Grade | Points | Percentage |
|-------|--------|------------|
| A | 4.0 | 90-100% |
| B | 3.0 | 80-89% |
| C | 2.0 | 70-79% |
| D | 1.0 | 60-69% |
| F | 0.0 | Below 60% |
### Checking Your Grades
- Ask "Check my grades" to this assistant
- Log into the student portal
- View grade reports by term
### Requesting Transcripts
Official transcripts can be requested for:
- Graduate school applications
- Employment verification
- Transfer to other institutions
Processing time: 3-5 business days
## Tuition and Financial Aid
### Payment Options
1. **Full Payment**: Pay entire balance before term starts
2. **Payment Plan**: Spread payments across the term
3. **Financial Aid**: Grants, scholarships, and loans
4. **Employer Reimbursement**: Deferred payment with employer letter
### Financial Aid Types
- **Grants**: Free money based on need (no repayment)
- **Scholarships**: Merit-based awards (no repayment)
- **Work-Study**: Part-time campus employment
- **Loans**: Borrowed funds (must be repaid)
### Important Deadlines
- FAFSA Priority Deadline: March 1
- Scholarship Applications: Varies by award
- Tuition Payment: 2 weeks before term start
- Payment Plan Enrollment: 1 month before term
## Academic Support Services
### Tutoring
Free tutoring available for:
- Writing assistance
- Math and science help
- Study skills coaching
- Test preparation
### Library Services
- Research databases and journals
- Study rooms (reservable)
- Interlibrary loan
- Research librarian consultations
### Academic Advising
Your advisor can help with:
- Course selection
- Degree planning
- Career guidance
- Academic concerns
## Campus Resources
### Student Services
- Career Center
- Counseling Services
- Health Center
- Disability Services
- International Student Office
### Technology Resources
- Campus WiFi (eduroam)
- Computer labs
- Software downloads
- IT help desk
## Academic Policies
### Attendance
- Regular attendance is expected
- Excessive absences may affect grades
- Notify instructors of planned absences
- Medical documentation may be required for extended absence
### Academic Integrity
All students must:
- Submit original work
- Properly cite sources
- Not share exam answers
- Report academic misconduct
Violations may result in course failure or dismissal.
### Withdrawal Policy
- Full refund: Before term starts
- 75% refund: Week 1
- 50% refund: Week 2
- 25% refund: Week 3
- No refund: After week 3
## Frequently Asked Questions
**Q: How do I change my major?**
A: Schedule a meeting with an academic advisor to discuss requirements and submit a change of major form.
**Q: Can I take courses at another institution?**
A: Yes, with prior approval. Submit a transient student form before registering elsewhere.
**Q: What is the minimum GPA requirement?**
A: You must maintain a 2.0 GPA for good academic standing. Some programs require higher GPAs.
**Q: How do I appeal a grade?**
A: First discuss with your instructor. If unresolved, submit a formal grade appeal within 30 days of grade posting.
**Q: Can I take a leave of absence?**
A: Yes, submit a leave of absence request to the registrar. Leaves are typically approved for up to one year.
**Q: How do I get accommodations for a disability?**
A: Contact Disability Services with documentation. They will work with you to arrange appropriate accommodations.
## Getting Help
For immediate assistance:
- Ask this assistant any question
- Visit the Student Services office
- Email: studenthelp@institution.edu
- Phone: 1-800-STU-DENT
We're here to support your academic success!

View file

@ -0,0 +1,4 @@
name,value
Answer Mode,tool
Start Dialog,start
Theme Color, indigo
1 name value
2 Answer Mode tool
3 Start Dialog start
4 Theme Color indigo

View file

@ -0,0 +1,293 @@
PARAM job_name AS STRING
user_id = GET "session.user_id"
current_time = FORMAT NOW() AS "YYYY-MM-DD HH:mm:ss"
IF job_name = "inventory_reorder" THEN
items = FIND "items", "is_purchasable = true AND reorder_point > 0"
reorders_created = 0
FOR EACH item IN items DO
stocks = FIND "inventory_stock", "item_id = '" + item.id + "'"
total_available = 0
FOR EACH stock IN stocks DO
total_available = total_available + stock.quantity_available
END FOR
IF total_available <= item.reorder_point THEN
po = CREATE OBJECT
SET po.id = FORMAT GUID()
SET po.po_number = "PO-AUTO-" + FORMAT NOW() AS "YYYYMMDD" + "-" + FORMAT RANDOM(100, 999)
SET po.status = "draft"
SET po.order_date = current_time
SET po.buyer_id = "system"
SET po.created_by = "system"
SET po.created_at = current_time
vendor_item = FIND "vendor_items", "item_id = '" + item.id + "' AND is_preferred = true"
IF vendor_item != NULL THEN
po.vendor_id = vendor_item.vendor_id
SAVE_FROM_UNSTRUCTURED "purchase_orders", FORMAT po AS JSON
line = CREATE OBJECT
SET line.id = FORMAT GUID()
SET line.po_id = po.id
SET line.line_number = 1
SET line.item_id = item.id
SET line.quantity_ordered = item.reorder_quantity
SET line.unit_price = vendor_item.unit_price
SET line.created_at = current_time
SAVE_FROM_UNSTRUCTURED "purchase_order_lines", FORMAT line AS JSON
reorders_created = reorders_created + 1
CREATE_TASK "Approve reorder PO " + po.po_number + " for " + item.name, "high", "purchasing"
END IF
END IF
END FOR
IF reorders_created > 0 THEN
notification = "Created " + reorders_created + " automatic reorder POs"
SEND MAIL "purchasing@company.com", "Automatic Reorders", notification
END IF
END IF
IF job_name = "low_stock_alert" THEN
items = FIND "items", "minimum_stock_level > 0"
low_stock_items = []
critical_items = []
FOR EACH item IN items DO
stocks = FIND "inventory_stock", "item_id = '" + item.id + "'"
total_on_hand = 0
FOR EACH stock IN stocks DO
total_on_hand = total_on_hand + stock.quantity_on_hand
END FOR
IF total_on_hand < item.minimum_stock_level THEN
stock_ratio = total_on_hand / item.minimum_stock_level
IF stock_ratio < 0.25 THEN
APPEND critical_items, item.name + " (" + total_on_hand + "/" + item.minimum_stock_level + ")"
ELSE
APPEND low_stock_items, item.name + " (" + total_on_hand + "/" + item.minimum_stock_level + ")"
END IF
END IF
END FOR
IF LENGTH(critical_items) > 0 OR LENGTH(low_stock_items) > 0 THEN
alert = "INVENTORY ALERT\n"
alert = alert + "===============\n\n"
IF LENGTH(critical_items) > 0 THEN
alert = alert + "CRITICAL (Below 25%):\n"
FOR EACH item_info IN critical_items DO
alert = alert + "- " + item_info + "\n"
END FOR
alert = alert + "\n"
END IF
IF LENGTH(low_stock_items) > 0 THEN
alert = alert + "LOW STOCK:\n"
FOR EACH item_info IN low_stock_items DO
alert = alert + "- " + item_info + "\n"
END FOR
END IF
SEND MAIL "inventory-manager@company.com", "Low Stock Alert", alert
END IF
END IF
IF job_name = "po_follow_up" THEN
pos = FIND "purchase_orders", "status = 'approved'"
FOR EACH po IN pos DO
days_old = DAYS_BETWEEN(po.order_date, current_time)
IF days_old > 7 THEN
vendor = FIND "vendors", "id = '" + po.vendor_id + "'"
notification = "PO " + po.po_number + " has been approved for " + days_old + " days without receipt"
SEND MAIL po.buyer_id, "PO Follow-up Required", notification
CREATE_TASK "Follow up on PO " + po.po_number + " with " + vendor.name, "medium", po.buyer_id
END IF
END FOR
END IF
IF job_name = "cost_analysis" THEN
start_of_month = FORMAT NOW() AS "YYYY-MM" + "-01"
transactions = FIND "inventory_transactions", "created_at >= '" + start_of_month + "'"
total_receipts_value = 0
total_shipments_value = 0
total_adjustments_value = 0
FOR EACH trans IN transactions DO
IF trans.transaction_type = "receipt" THEN
total_receipts_value = total_receipts_value + trans.total_cost
ELSE IF trans.transaction_type = "shipment" THEN
total_shipments_value = total_shipments_value + ABS(trans.total_cost)
ELSE IF trans.transaction_type = "adjustment" THEN
total_adjustments_value = total_adjustments_value + ABS(trans.total_cost)
END IF
END FOR
report = "MONTHLY INVENTORY COST ANALYSIS\n"
report = report + "================================\n"
report = report + "Period: " + FORMAT NOW() AS "MMMM YYYY" + "\n\n"
report = report + "Receipts Value: $" + total_receipts_value + "\n"
report = report + "Shipments Value: $" + total_shipments_value + "\n"
report = report + "Adjustments Value: $" + total_adjustments_value + "\n"
report = report + "\n"
report = report + "Gross Margin: $" + (total_shipments_value - total_receipts_value) + "\n"
SEND MAIL "cfo@company.com", "Monthly Inventory Cost Report", report
END IF
IF job_name = "vendor_scorecard" THEN
vendors = FIND "vendors", "status = 'active'"
scorecard = "VENDOR SCORECARD - " + current_time + "\n"
scorecard = scorecard + "====================================\n\n"
FOR EACH vendor IN vendors DO
pos = FIND "purchase_orders", "vendor_id = '" + vendor.id + "' AND created_at >= DATE_SUB(NOW(), INTERVAL 90 DAY)"
total_pos = 0
on_time = 0
total_spend = 0
FOR EACH po IN pos DO
total_pos = total_pos + 1
total_spend = total_spend + po.total_amount
IF po.status = "received" THEN
IF po.received_date <= po.expected_date THEN
on_time = on_time + 1
END IF
END IF
END FOR
IF total_pos > 0 THEN
on_time_rate = (on_time / total_pos) * 100
scorecard = scorecard + vendor.name + "\n"
scorecard = scorecard + " Orders: " + total_pos + "\n"
scorecard = scorecard + " Spend: $" + total_spend + "\n"
scorecard = scorecard + " On-Time: " + on_time_rate + "%\n"
IF on_time_rate < 80 THEN
scorecard = scorecard + " WARNING: Low performance\n"
END IF
scorecard = scorecard + "\n"
END IF
END FOR
SEND MAIL "purchasing@company.com", "Vendor Scorecard", scorecard
END IF
IF job_name = "warehouse_capacity" THEN
warehouses = FIND "warehouses", "is_active = true"
capacity_report = "WAREHOUSE CAPACITY REPORT\n"
capacity_report = capacity_report + "========================\n\n"
FOR EACH warehouse IN warehouses DO
stocks = FIND "inventory_stock", "warehouse_id = '" + warehouse.id + "'"
total_units = 0
FOR EACH stock IN stocks DO
total_units = total_units + stock.quantity_on_hand
END FOR
utilization = 0
IF warehouse.capacity_units > 0 THEN
utilization = (total_units / warehouse.capacity_units) * 100
END IF
capacity_report = capacity_report + warehouse.name + "\n"
capacity_report = capacity_report + " Units: " + total_units + " / " + warehouse.capacity_units + "\n"
capacity_report = capacity_report + " Utilization: " + utilization + "%\n"
IF utilization > 90 THEN
capacity_report = capacity_report + " WARNING: Near capacity\n"
CREATE_TASK "Review capacity at " + warehouse.name, "high", "warehouse-manager"
ELSE IF utilization < 20 THEN
capacity_report = capacity_report + " NOTE: Low utilization\n"
END IF
capacity_report = capacity_report + "\n"
END FOR
SEND MAIL "operations@company.com", "Warehouse Capacity Report", capacity_report
END IF
IF job_name = "invoice_aging" THEN
invoices = FIND "invoices", "balance_due > 0"
aging_30 = 0
aging_60 = 0
aging_90 = 0
aging_over_90 = 0
total_30 = 0
total_60 = 0
total_90 = 0
total_over_90 = 0
FOR EACH invoice IN invoices DO
days_old = DAYS_BETWEEN(invoice.invoice_date, current_time)
IF days_old <= 30 THEN
aging_30 = aging_30 + 1
total_30 = total_30 + invoice.balance_due
ELSE IF days_old <= 60 THEN
aging_60 = aging_60 + 1
total_60 = total_60 + invoice.balance_due
ELSE IF days_old <= 90 THEN
aging_90 = aging_90 + 1
total_90 = total_90 + invoice.balance_due
ELSE
aging_over_90 = aging_over_90 + 1
total_over_90 = total_over_90 + invoice.balance_due
customer = FIND "customers", "id = '" + invoice.customer_id + "'"
IF customer != NULL THEN
notification = "Invoice " + invoice.invoice_number + " is over 90 days past due. Amount: $" + invoice.balance_due
CREATE_TASK "Collection: " + customer.name + " - " + invoice.invoice_number, "critical", "collections"
END IF
END IF
END FOR
aging_report = "ACCOUNTS RECEIVABLE AGING\n"
aging_report = aging_report + "=========================\n\n"
aging_report = aging_report + "0-30 days: " + aging_30 + " invoices, $" + total_30 + "\n"
aging_report = aging_report + "31-60 days: " + aging_60 + " invoices, $" + total_60 + "\n"
aging_report = aging_report + "61-90 days: " + aging_90 + " invoices, $" + total_90 + "\n"
aging_report = aging_report + "Over 90 days: " + aging_over_90 + " invoices, $" + total_over_90 + "\n"
aging_report = aging_report + "\n"
aging_report = aging_report + "TOTAL OUTSTANDING: $" + (total_30 + total_60 + total_90 + total_over_90) + "\n"
SEND MAIL "finance@company.com", "AR Aging Report", aging_report
END IF
IF job_name = "setup_schedules" THEN
SET SCHEDULE "0 6 * * *" "erp-jobs.bas" "inventory_reorder"
SET SCHEDULE "0 8,16 * * *" "erp-jobs.bas" "low_stock_alert"
SET SCHEDULE "0 10 * * *" "erp-jobs.bas" "po_follow_up"
SET SCHEDULE "0 0 1 * *" "erp-jobs.bas" "cost_analysis"
SET SCHEDULE "0 9 * * MON" "erp-jobs.bas" "vendor_scorecard"
SET SCHEDULE "0 7 * * *" "erp-jobs.bas" "warehouse_capacity"
SET SCHEDULE "0 11 * * *" "erp-jobs.bas" "invoice_aging"
TALK "All ERP schedules have been configured"
END IF

View file

@ -0,0 +1,343 @@
PARAM action AS STRING LIKE "check_stock" DESCRIPTION "Action: receive_inventory, ship_inventory, check_stock, transfer_stock, cycle_count"
PARAM item_data AS OBJECT LIKE "{po_number: 'PO-123'}" DESCRIPTION "Data object with action-specific parameters"
DESCRIPTION "Manage inventory operations - receive, ship, check stock, transfer between warehouses, and cycle counts"
user_id = GET "session.user_id"
warehouse_id = GET "session.warehouse_id"
IF action = "receive_inventory" THEN
po_number = item_data.po_number
po = FIND "purchase_orders", "po_number = '" + po_number + "'"
IF NOT po THEN
TALK "Purchase order not found."
RETURN NULL
END IF
IF po.status = "received" THEN
TALK "This PO has already been received."
RETURN NULL
END IF
po_lines = FIND "purchase_order_lines", "po_id = '" + po.id + "'"
FOR EACH line IN po_lines
item = FIND "items", "id = '" + line.item_id + "'"
TALK "Receiving " + item.name + " - Ordered: " + line.quantity_ordered
TALK "Enter quantity received:"
HEAR qty_received AS INTEGER
stock = FIND "inventory_stock", "item_id = '" + item.id + "' AND warehouse_id = '" + warehouse_id + "'"
IF NOT stock THEN
WITH newStock
id = FORMAT(GUID())
item_id = item.id
warehouse_id = warehouse_id
quantity_on_hand = qty_received
last_movement_date = NOW()
END WITH
SAVE "inventory_stock", newStock
ELSE
new_qty = stock.quantity_on_hand + qty_received
UPDATE "inventory_stock" SET quantity_on_hand = new_qty, last_movement_date = NOW() WHERE id = stock.id
END IF
WITH transaction
id = FORMAT(GUID())
transaction_type = "receipt"
transaction_number = "REC-" + FORMAT(NOW(), "YYYYMMDD") + "-" + FORMAT(RANDOM(1000, 9999))
item_id = item.id
warehouse_id = warehouse_id
quantity = qty_received
unit_cost = line.unit_price
total_cost = qty_received * line.unit_price
reference_type = "purchase_order"
reference_id = po.id
created_by = user_id
created_at = NOW()
END WITH
SAVE "inventory_transactions", transaction
UPDATE "purchase_order_lines" SET quantity_received = line.quantity_received + qty_received WHERE id = line.id
UPDATE "items" SET last_cost = line.unit_price WHERE id = item.id
NEXT
UPDATE "purchase_orders" SET status = "received" WHERE id = po.id
TALK "Purchase order " + po_number + " received."
SEND EMAIL po.buyer_id, "PO Received", "PO " + po_number + " received at warehouse " + warehouse_id
RETURN po_number
END IF
IF action = "ship_inventory" THEN
so_number = item_data.so_number
so = FIND "sales_orders", "order_number = '" + so_number + "'"
IF NOT so THEN
TALK "Sales order not found."
RETURN NULL
END IF
so_lines = FIND "sales_order_lines", "order_id = '" + so.id + "'"
can_ship = true
FOR EACH line IN so_lines
item = FIND "items", "id = '" + line.item_id + "'"
stock = FIND "inventory_stock", "item_id = '" + item.id + "' AND warehouse_id = '" + warehouse_id + "'"
IF NOT stock OR stock.quantity_available < line.quantity_ordered THEN
TALK "Insufficient stock for " + item.name
can_ship = false
END IF
NEXT
IF NOT can_ship THEN
TALK "Cannot ship order due to insufficient inventory."
RETURN NULL
END IF
shipment_number = "SHIP-" + FORMAT(NOW(), "YYYYMMDD") + "-" + FORMAT(RANDOM(1000, 9999))
FOR EACH line IN so_lines
item = FIND "items", "id = '" + line.item_id + "'"
stock = FIND "inventory_stock", "item_id = '" + item.id + "' AND warehouse_id = '" + warehouse_id + "'"
new_qty = stock.quantity_on_hand - line.quantity_ordered
UPDATE "inventory_stock" SET quantity_on_hand = new_qty, last_movement_date = NOW() WHERE id = stock.id
WITH transaction
id = FORMAT(GUID())
transaction_type = "shipment"
transaction_number = shipment_number
item_id = item.id
warehouse_id = warehouse_id
quantity = 0 - line.quantity_ordered
unit_cost = item.average_cost
total_cost = line.quantity_ordered * item.average_cost
reference_type = "sales_order"
reference_id = so.id
created_by = user_id
created_at = NOW()
END WITH
SAVE "inventory_transactions", transaction
UPDATE "sales_order_lines" SET quantity_shipped = line.quantity_ordered, cost_of_goods_sold = transaction.total_cost WHERE id = line.id
NEXT
UPDATE "sales_orders" SET status = "shipped" WHERE id = so.id
TALK "Order " + so_number + " shipped. Tracking: " + shipment_number
customer = FIND "customers", "id = '" + so.customer_id + "'"
IF customer AND customer.email THEN
SEND EMAIL customer.email, "Order Shipped", "Your order " + so_number + " has been shipped. Tracking: " + shipment_number
END IF
RETURN shipment_number
END IF
IF action = "check_stock" THEN
item_search = item_data.item_search
items = FIND "items", "name LIKE '%" + item_search + "%' OR item_code = '" + item_search + "'"
IF NOT items THEN
TALK "No items found."
RETURN NULL
END IF
FOR EACH item IN items
TALK "Item: " + item.name + " (" + item.item_code + ")"
stocks = FIND "inventory_stock", "item_id = '" + item.id + "'"
total_on_hand = 0
total_available = 0
FOR EACH stock IN stocks
warehouse = FIND "warehouses", "id = '" + stock.warehouse_id + "'"
TALK " " + warehouse.name + ": " + stock.quantity_on_hand + " on hand"
total_on_hand = total_on_hand + stock.quantity_on_hand
total_available = total_available + stock.quantity_available
NEXT
TALK " TOTAL: " + total_on_hand + " on hand, " + total_available + " available"
IF total_available < item.minimum_stock_level THEN
TALK " WARNING: Below minimum stock level (" + item.minimum_stock_level + ")"
IF item.reorder_point > 0 AND total_available <= item.reorder_point THEN
TALK " REORDER NEEDED! Qty: " + item.reorder_quantity
CREATE_TASK "Reorder " + item.name, "high", user_id
END IF
END IF
NEXT
RETURN items
END IF
IF action = "transfer_stock" THEN
TALK "Enter item code:"
HEAR item_code AS STRING
item = FIND "items", "item_code = '" + item_code + "'"
IF NOT item THEN
TALK "Item not found."
RETURN NULL
END IF
TALK "From warehouse code:"
HEAR from_warehouse_code AS STRING
from_warehouse = FIND "warehouses", "code = '" + from_warehouse_code + "'"
IF NOT from_warehouse THEN
TALK "Source warehouse not found."
RETURN NULL
END IF
from_stock = FIND "inventory_stock", "item_id = '" + item.id + "' AND warehouse_id = '" + from_warehouse.id + "'"
IF NOT from_stock THEN
TALK "No stock in source warehouse."
RETURN NULL
END IF
TALK "Available: " + from_stock.quantity_available
TALK "Transfer quantity:"
HEAR transfer_qty AS INTEGER
IF transfer_qty > from_stock.quantity_available THEN
TALK "Insufficient available quantity."
RETURN NULL
END IF
TALK "To warehouse code:"
HEAR to_warehouse_code AS STRING
to_warehouse = FIND "warehouses", "code = '" + to_warehouse_code + "'"
IF NOT to_warehouse THEN
TALK "Destination warehouse not found."
RETURN NULL
END IF
transfer_number = "TRAN-" + FORMAT(NOW(), "YYYYMMDD") + "-" + FORMAT(RANDOM(1000, 9999))
new_from_qty = from_stock.quantity_on_hand - transfer_qty
UPDATE "inventory_stock" SET quantity_on_hand = new_from_qty, last_movement_date = NOW() WHERE id = from_stock.id
WITH from_transaction
id = FORMAT(GUID())
transaction_type = "transfer_out"
transaction_number = transfer_number
item_id = item.id
warehouse_id = from_warehouse.id
quantity = 0 - transfer_qty
unit_cost = item.average_cost
created_by = user_id
created_at = NOW()
END WITH
SAVE "inventory_transactions", from_transaction
to_stock = FIND "inventory_stock", "item_id = '" + item.id + "' AND warehouse_id = '" + to_warehouse.id + "'"
IF NOT to_stock THEN
WITH newToStock
id = FORMAT(GUID())
item_id = item.id
warehouse_id = to_warehouse.id
quantity_on_hand = transfer_qty
last_movement_date = NOW()
END WITH
SAVE "inventory_stock", newToStock
ELSE
new_to_qty = to_stock.quantity_on_hand + transfer_qty
UPDATE "inventory_stock" SET quantity_on_hand = new_to_qty, last_movement_date = NOW() WHERE id = to_stock.id
END IF
WITH to_transaction
id = FORMAT(GUID())
transaction_type = "transfer_in"
transaction_number = transfer_number
item_id = item.id
warehouse_id = to_warehouse.id
quantity = transfer_qty
unit_cost = item.average_cost
created_by = user_id
created_at = NOW()
END WITH
SAVE "inventory_transactions", to_transaction
TALK "Transfer " + transfer_number + " completed: " + transfer_qty + " units from " + from_warehouse.name + " to " + to_warehouse.name
RETURN transfer_number
END IF
IF action = "cycle_count" THEN
TALK "Enter warehouse code:"
HEAR warehouse_code AS STRING
warehouse = FIND "warehouses", "code = '" + warehouse_code + "'"
IF NOT warehouse THEN
TALK "Warehouse not found."
RETURN NULL
END IF
stocks = FIND "inventory_stock", "warehouse_id = '" + warehouse.id + "'"
count_number = "COUNT-" + FORMAT(NOW(), "YYYYMMDD") + "-" + FORMAT(RANDOM(1000, 9999))
adjustments = 0
FOR EACH stock IN stocks
item = FIND "items", "id = '" + stock.item_id + "'"
TALK "Item: " + item.name + " (" + item.item_code + ")"
TALK "System quantity: " + stock.quantity_on_hand
TALK "Enter physical count:"
HEAR physical_count AS INTEGER
IF physical_count <> stock.quantity_on_hand THEN
variance = physical_count - stock.quantity_on_hand
WITH adjustment
id = FORMAT(GUID())
transaction_type = "adjustment"
transaction_number = count_number
item_id = item.id
warehouse_id = warehouse.id
quantity = variance
notes = "Cycle count adjustment"
created_by = user_id
created_at = NOW()
END WITH
SAVE "inventory_transactions", adjustment
UPDATE "inventory_stock" SET quantity_on_hand = physical_count, last_counted_date = NOW(), last_movement_date = NOW() WHERE id = stock.id
adjustments = adjustments + 1
TALK " Adjusted by " + variance + " units"
ELSE
UPDATE "inventory_stock" SET last_counted_date = NOW() WHERE id = stock.id
TALK " Count confirmed"
END IF
NEXT
TALK "Cycle count " + count_number + " completed with " + adjustments + " adjustments"
IF adjustments > 0 THEN
SEND EMAIL "inventory-manager@company.com", "Cycle Count Results", "Cycle count " + count_number + " at " + warehouse.name + " with " + adjustments + " adjustments"
END IF
RETURN count_number
END IF
TALK "Unknown action: " + action
RETURN NULL

View file

@ -0,0 +1,341 @@
PARAM action AS STRING
PARAM purchase_data AS OBJECT
user_id = GET "session.user_id"
current_time = FORMAT NOW() AS "YYYY-MM-DD HH:mm:ss"
IF action = "create_po" THEN
vendor_code = GET "purchase_data.vendor_code"
IF vendor_code = "" THEN
TALK "Enter vendor code:"
vendor_code = HEAR
END IF
vendor = FIND "vendors", "vendor_code = '" + vendor_code + "'"
IF vendor = NULL THEN
TALK "Vendor not found."
EXIT
END IF
po_number = "PO-" + FORMAT NOW() AS "YYYYMMDD" + "-" + FORMAT RANDOM(1000, 9999)
po = CREATE OBJECT
SET po.id = FORMAT GUID()
SET po.po_number = po_number
SET po.vendor_id = vendor.id
SET po.order_date = current_time
SET po.status = "draft"
SET po.buyer_id = user_id
SET po.created_by = user_id
SET po.created_at = current_time
SET po.subtotal = 0
SAVE_FROM_UNSTRUCTURED "purchase_orders", FORMAT po AS JSON
SET "session.po_id" = po.id
REMEMBER "po_" + po.id = po
TALK "Purchase Order " + po_number + " created for " + vendor.name
adding_items = true
line_number = 1
total = 0
WHILE adding_items = true DO
TALK "Enter item code (or 'done' to finish):"
HEAR item_code AS "done", *
IF item_code = "done" THEN
adding_items = false
ELSE
item = FIND "items", "item_code = '" + item_code + "'"
IF item = NULL THEN
TALK "Item not found. Try again."
ELSE
TALK "Quantity to order:"
HEAR quantity AS INTEGER
TALK "Unit price (or press Enter for last cost: " + item.last_cost + "):"
HEAR unit_price AS MONEY DEFAULT item.last_cost
line = CREATE OBJECT
SET line.id = FORMAT GUID()
SET line.po_id = po.id
SET line.line_number = line_number
SET line.item_id = item.id
SET line.description = item.name
SET line.quantity_ordered = quantity
SET line.unit_price = unit_price
SET line.line_total = quantity * unit_price
SET line.created_at = current_time
SAVE_FROM_UNSTRUCTURED "purchase_order_lines", FORMAT line AS JSON
total = total + line.line_total
line_number = line_number + 1
TALK "Added: " + item.name + " x " + quantity + " @ $" + unit_price
END IF
END IF
END WHILE
po.subtotal = total
po.total_amount = total
SAVE_FROM_UNSTRUCTURED "purchase_orders", FORMAT po AS JSON
TALK "Purchase Order " + po_number + " total: $" + total
END IF
IF action = "approve_po" THEN
po_number = GET "purchase_data.po_number"
IF po_number = "" THEN
TALK "Enter PO number to approve:"
HEAR po_number
END IF
po = FIND "purchase_orders", "po_number = '" + po_number + "'"
IF po = NULL THEN
TALK "Purchase order not found."
EXIT
END IF
IF po.status != "draft" THEN
TALK "PO status is " + po.status + ". Can only approve draft POs."
EXIT
END IF
po_lines = FIND "purchase_order_lines", "po_id = '" + po.id + "'"
TALK "PO Summary:"
TALK "Vendor: " + po.vendor_id
TALK "Total: $" + po.total_amount
TALK "Items:"
FOR EACH line IN po_lines DO
TALK " - " + line.description + " x " + line.quantity_ordered + " @ $" + line.unit_price
END FOR
TALK "Approve this PO? (yes/no)"
HEAR approval AS "yes", "no"
IF approval = "yes" THEN
po.status = "approved"
po.approved_by = user_id
po.approved_date = current_time
SAVE_FROM_UNSTRUCTURED "purchase_orders", FORMAT po AS JSON
vendor = FIND "vendors", "id = '" + po.vendor_id + "'"
IF vendor.email != "" THEN
message = "Purchase Order " + po_number + " has been approved. Total: $" + po.total_amount
SEND MAIL vendor.email, "PO Approved: " + po_number, message
END IF
TALK "PO " + po_number + " approved successfully."
CREATE_TASK "Process PO " + po_number, "high", user_id
ELSE
TALK "PO not approved."
END IF
END IF
IF action = "vendor_performance" THEN
vendor_code = GET "purchase_data.vendor_code"
IF vendor_code = "" THEN
TALK "Enter vendor code:"
HEAR vendor_code
END IF
vendor = FIND "vendors", "vendor_code = '" + vendor_code + "'"
IF vendor = NULL THEN
TALK "Vendor not found."
EXIT
END IF
pos = FIND "purchase_orders", "vendor_id = '" + vendor.id + "'"
total_pos = 0
on_time = 0
late = 0
total_spend = 0
FOR EACH po IN pos DO
total_pos = total_pos + 1
total_spend = total_spend + po.total_amount
IF po.status = "received" THEN
IF po.received_date <= po.expected_date THEN
on_time = on_time + 1
ELSE
late = late + 1
END IF
END IF
END FOR
on_time_percentage = 0
IF total_pos > 0 THEN
on_time_percentage = (on_time / total_pos) * 100
END IF
TALK "VENDOR PERFORMANCE: " + vendor.name
TALK "================================"
TALK "Total Purchase Orders: " + total_pos
TALK "Total Spend: $" + total_spend
TALK "On-Time Delivery: " + on_time_percentage + "%"
TALK "Late Deliveries: " + late
IF on_time_percentage < 80 THEN
TALK "WARNING: Low on-time delivery rate"
CREATE_TASK "Review vendor " + vendor.name + " performance", "medium", user_id
END IF
END IF
IF action = "reorder_check" THEN
items = FIND "items", "is_purchasable = true"
reorder_needed = 0
FOR EACH item IN items DO
IF item.reorder_point > 0 THEN
stocks = FIND "inventory_stock", "item_id = '" + item.id + "'"
total_available = 0
FOR EACH stock IN stocks DO
total_available = total_available + stock.quantity_available
END FOR
IF total_available <= item.reorder_point THEN
reorder_needed = reorder_needed + 1
TALK "REORDER: " + item.name
TALK " Current stock: " + total_available
TALK " Reorder point: " + item.reorder_point
TALK " Suggested qty: " + item.reorder_quantity
preferred_vendor = FIND "vendor_items", "item_id = '" + item.id + "' AND is_preferred = true"
IF preferred_vendor != NULL THEN
vendor = FIND "vendors", "id = '" + preferred_vendor.vendor_id + "'"
TALK " Preferred vendor: " + vendor.name
END IF
CREATE_TASK "Reorder " + item.name + " (qty: " + item.reorder_quantity + ")", "high", user_id
END IF
END IF
END FOR
IF reorder_needed = 0 THEN
TALK "No items need reordering."
ELSE
TALK "Total items needing reorder: " + reorder_needed
END IF
END IF
IF action = "requisition" THEN
req_number = "REQ-" + FORMAT NOW() AS "YYYYMMDD" + "-" + FORMAT RANDOM(1000, 9999)
TALK "Creating requisition " + req_number
req = CREATE OBJECT
SET req.id = FORMAT GUID()
SET req.req_number = req_number
SET req.requester = user_id
SET req.status = "pending"
SET req.created_at = current_time
SET req.items = []
adding = true
WHILE adding = true DO
TALK "Enter item description (or 'done'):"
HEAR item_desc AS "done", *
IF item_desc = "done" THEN
adding = false
ELSE
TALK "Quantity needed:"
HEAR quantity AS INTEGER
TALK "Reason/Project:"
HEAR reason
req_item = CREATE OBJECT
SET req_item.description = item_desc
SET req_item.quantity = quantity
SET req_item.reason = reason
APPEND req.items, req_item
TALK "Added to requisition."
END IF
END WHILE
SAVE_FROM_UNSTRUCTURED "requisitions", FORMAT req AS JSON
TALK "Requisition " + req_number + " created with " + LENGTH(req.items) + " items."
notification = "New requisition " + req_number + " from " + user_id + " needs approval"
SEND MAIL "purchasing@company.com", "New Requisition", notification
CREATE_TASK "Review requisition " + req_number, "medium", "purchasing"
END IF
IF action = "price_comparison" THEN
item_code = GET "purchase_data.item_code"
IF item_code = "" THEN
TALK "Enter item code:"
HEAR item_code
END IF
item = FIND "items", "item_code = '" + item_code + "'"
IF item = NULL THEN
TALK "Item not found."
EXIT
END IF
vendor_items = FIND "vendor_items", "item_id = '" + item.id + "'"
IF vendor_items = NULL THEN
TALK "No vendor pricing found for this item."
EXIT
END IF
TALK "PRICE COMPARISON: " + item.name
TALK "================================"
best_price = 999999
best_vendor = ""
FOR EACH vi IN vendor_items DO
vendor = FIND "vendors", "id = '" + vi.vendor_id + "'"
TALK vendor.name + ":"
TALK " Unit price: $" + vi.unit_price
TALK " Min order: " + vi.min_order_qty
TALK " Lead time: " + vi.lead_time_days + " days"
IF vi.unit_price < best_price THEN
best_price = vi.unit_price
best_vendor = vendor.name
END IF
END FOR
TALK ""
TALK "Best price: $" + best_price + " from " + best_vendor
END IF

View file

@ -0,0 +1,509 @@
' ERP Database Tables Definition
' This file defines all ERP tables using the TABLE keyword
' Tables cover inventory, purchasing, manufacturing, finance, and HR modules
' === INVENTORY MANAGEMENT ===
' Items/Products master table
TABLE items
id UUID PRIMARY KEY DEFAULT uuid_generate_v4()
item_code VARCHAR(50) UNIQUE NOT NULL
barcode VARCHAR(50) UNIQUE
name VARCHAR(255) NOT NULL
description TEXT
category VARCHAR(100)
subcategory VARCHAR(100)
unit_of_measure VARCHAR(20) DEFAULT 'EACH'
weight DECIMAL(10,3)
dimensions_length DECIMAL(10,2)
dimensions_width DECIMAL(10,2)
dimensions_height DECIMAL(10,2)
minimum_stock_level INTEGER DEFAULT 0
reorder_point INTEGER
reorder_quantity INTEGER
lead_time_days INTEGER DEFAULT 0
is_active BOOLEAN DEFAULT TRUE
is_purchasable BOOLEAN DEFAULT TRUE
is_saleable BOOLEAN DEFAULT TRUE
is_manufactured BOOLEAN DEFAULT FALSE
standard_cost DECIMAL(15,4)
last_cost DECIMAL(15,4)
average_cost DECIMAL(15,4)
selling_price DECIMAL(15,4)
created_at TIMESTAMP DEFAULT NOW()
updated_at TIMESTAMP DEFAULT NOW()
END TABLE
' Warehouses table
TABLE warehouses
id UUID PRIMARY KEY DEFAULT uuid_generate_v4()
code VARCHAR(20) UNIQUE NOT NULL
name VARCHAR(100) NOT NULL
type VARCHAR(50) DEFAULT 'standard'
address TEXT
city VARCHAR(100)
state VARCHAR(50)
country VARCHAR(50)
postal_code VARCHAR(20)
contact_person VARCHAR(100)
contact_phone VARCHAR(50)
contact_email VARCHAR(100)
capacity_units INTEGER
current_occupancy INTEGER DEFAULT 0
is_active BOOLEAN DEFAULT TRUE
created_at TIMESTAMP DEFAULT NOW()
END TABLE
' Inventory stock levels
TABLE inventory_stock
id UUID PRIMARY KEY DEFAULT uuid_generate_v4()
item_id UUID REFERENCES items(id)
warehouse_id UUID REFERENCES warehouses(id)
location_code VARCHAR(50)
quantity_on_hand DECIMAL(15,3) DEFAULT 0
quantity_reserved DECIMAL(15,3) DEFAULT 0
quantity_available DECIMAL(15,3) GENERATED ALWAYS AS (quantity_on_hand - quantity_reserved) STORED
quantity_on_order DECIMAL(15,3) DEFAULT 0
last_counted_date DATE
last_movement_date TIMESTAMP
created_at TIMESTAMP DEFAULT NOW()
updated_at TIMESTAMP DEFAULT NOW()
UNIQUE(item_id, warehouse_id, location_code)
END TABLE
' Inventory transactions
TABLE inventory_transactions
id UUID PRIMARY KEY DEFAULT uuid_generate_v4()
transaction_type VARCHAR(50) NOT NULL
transaction_number VARCHAR(50) UNIQUE
item_id UUID REFERENCES items(id)
warehouse_id UUID REFERENCES warehouses(id)
location_code VARCHAR(50)
quantity DECIMAL(15,3) NOT NULL
unit_cost DECIMAL(15,4)
total_cost DECIMAL(15,2)
reference_type VARCHAR(50)
reference_id UUID
notes TEXT
created_by VARCHAR(100)
created_at TIMESTAMP DEFAULT NOW()
END TABLE
' === PURCHASING MODULE ===
' Vendors/Suppliers table
TABLE vendors
id UUID PRIMARY KEY DEFAULT uuid_generate_v4()
vendor_code VARCHAR(50) UNIQUE NOT NULL
name VARCHAR(255) NOT NULL
legal_name VARCHAR(255)
tax_id VARCHAR(50)
vendor_type VARCHAR(50)
status VARCHAR(20) DEFAULT 'active'
rating INTEGER CHECK (rating >= 1 AND rating <= 5)
payment_terms VARCHAR(50)
credit_limit DECIMAL(15,2)
currency_code VARCHAR(3) DEFAULT 'USD'
address TEXT
city VARCHAR(100)
state VARCHAR(50)
country VARCHAR(50)
postal_code VARCHAR(20)
phone VARCHAR(50)
email VARCHAR(100)
website VARCHAR(255)
contact_person VARCHAR(100)
bank_account_number VARCHAR(50)
bank_name VARCHAR(100)
notes TEXT
created_at TIMESTAMP DEFAULT NOW()
updated_at TIMESTAMP DEFAULT NOW()
END TABLE
' Purchase orders
TABLE purchase_orders
id UUID PRIMARY KEY DEFAULT uuid_generate_v4()
po_number VARCHAR(50) UNIQUE NOT NULL
vendor_id UUID REFERENCES vendors(id)
order_date DATE NOT NULL
expected_date DATE
status VARCHAR(50) DEFAULT 'draft'
buyer_id VARCHAR(100)
ship_to_warehouse_id UUID REFERENCES warehouses(id)
shipping_method VARCHAR(50)
payment_terms VARCHAR(50)
currency_code VARCHAR(3) DEFAULT 'USD'
exchange_rate DECIMAL(10,6) DEFAULT 1.0
subtotal DECIMAL(15,2)
tax_amount DECIMAL(15,2)
shipping_cost DECIMAL(15,2)
total_amount DECIMAL(15,2)
notes TEXT
approved_by VARCHAR(100)
approved_date TIMESTAMP
created_by VARCHAR(100)
created_at TIMESTAMP DEFAULT NOW()
updated_at TIMESTAMP DEFAULT NOW()
END TABLE
' Purchase order lines
TABLE purchase_order_lines
id UUID PRIMARY KEY DEFAULT uuid_generate_v4()
po_id UUID REFERENCES purchase_orders(id) ON DELETE CASCADE
line_number INTEGER NOT NULL
item_id UUID REFERENCES items(id)
description TEXT
quantity_ordered DECIMAL(15,3) NOT NULL
quantity_received DECIMAL(15,3) DEFAULT 0
quantity_remaining DECIMAL(15,3) GENERATED ALWAYS AS (quantity_ordered - quantity_received) STORED
unit_price DECIMAL(15,4) NOT NULL
discount_percent DECIMAL(5,2) DEFAULT 0
tax_rate DECIMAL(5,2) DEFAULT 0
line_total DECIMAL(15,2) GENERATED ALWAYS AS (quantity_ordered * unit_price * (1 - discount_percent/100)) STORED
expected_date DATE
created_at TIMESTAMP DEFAULT NOW()
UNIQUE(po_id, line_number)
END TABLE
' === SALES MODULE ===
' Customers table
TABLE customers
id UUID PRIMARY KEY DEFAULT uuid_generate_v4()
customer_code VARCHAR(50) UNIQUE NOT NULL
name VARCHAR(255) NOT NULL
legal_name VARCHAR(255)
tax_id VARCHAR(50)
customer_type VARCHAR(50)
status VARCHAR(20) DEFAULT 'active'
credit_rating VARCHAR(10)
credit_limit DECIMAL(15,2)
payment_terms VARCHAR(50)
discount_percent DECIMAL(5,2) DEFAULT 0
currency_code VARCHAR(3) DEFAULT 'USD'
billing_address TEXT
shipping_address TEXT
city VARCHAR(100)
state VARCHAR(50)
country VARCHAR(50)
postal_code VARCHAR(20)
phone VARCHAR(50)
email VARCHAR(100)
website VARCHAR(255)
sales_person_id VARCHAR(100)
notes TEXT
created_at TIMESTAMP DEFAULT NOW()
updated_at TIMESTAMP DEFAULT NOW()
END TABLE
' Sales orders
TABLE sales_orders
id UUID PRIMARY KEY DEFAULT uuid_generate_v4()
order_number VARCHAR(50) UNIQUE NOT NULL
customer_id UUID REFERENCES customers(id)
order_date DATE NOT NULL
required_date DATE
promised_date DATE
status VARCHAR(50) DEFAULT 'draft'
sales_person_id VARCHAR(100)
ship_from_warehouse_id UUID REFERENCES warehouses(id)
shipping_method VARCHAR(50)
payment_terms VARCHAR(50)
payment_method VARCHAR(50)
currency_code VARCHAR(3) DEFAULT 'USD'
exchange_rate DECIMAL(10,6) DEFAULT 1.0
subtotal DECIMAL(15,2)
discount_amount DECIMAL(15,2) DEFAULT 0
tax_amount DECIMAL(15,2)
shipping_cost DECIMAL(15,2)
total_amount DECIMAL(15,2)
notes TEXT
approved_by VARCHAR(100)
approved_date TIMESTAMP
created_by VARCHAR(100)
created_at TIMESTAMP DEFAULT NOW()
updated_at TIMESTAMP DEFAULT NOW()
END TABLE
' Sales order lines
TABLE sales_order_lines
id UUID PRIMARY KEY DEFAULT uuid_generate_v4()
order_id UUID REFERENCES sales_orders(id) ON DELETE CASCADE
line_number INTEGER NOT NULL
item_id UUID REFERENCES items(id)
description TEXT
quantity_ordered DECIMAL(15,3) NOT NULL
quantity_shipped DECIMAL(15,3) DEFAULT 0
quantity_invoiced DECIMAL(15,3) DEFAULT 0
unit_price DECIMAL(15,4) NOT NULL
discount_percent DECIMAL(5,2) DEFAULT 0
tax_rate DECIMAL(5,2) DEFAULT 0
line_total DECIMAL(15,2) GENERATED ALWAYS AS (quantity_ordered * unit_price * (1 - discount_percent/100)) STORED
cost_of_goods_sold DECIMAL(15,2)
margin DECIMAL(15,2) GENERATED ALWAYS AS (line_total - cost_of_goods_sold) STORED
warehouse_id UUID REFERENCES warehouses(id)
promised_date DATE
created_at TIMESTAMP DEFAULT NOW()
UNIQUE(order_id, line_number)
END TABLE
' === MANUFACTURING MODULE ===
' Bill of Materials (BOM) header
TABLE bill_of_materials
id UUID PRIMARY KEY DEFAULT uuid_generate_v4()
bom_number VARCHAR(50) UNIQUE NOT NULL
item_id UUID REFERENCES items(id)
revision VARCHAR(20) DEFAULT 'A'
description TEXT
quantity_per_assembly DECIMAL(15,3) DEFAULT 1
unit_of_measure VARCHAR(20)
status VARCHAR(20) DEFAULT 'active'
effective_date DATE
expiration_date DATE
total_cost DECIMAL(15,4)
labor_cost DECIMAL(15,4)
overhead_cost DECIMAL(15,4)
created_by VARCHAR(100)
approved_by VARCHAR(100)
approved_date DATE
created_at TIMESTAMP DEFAULT NOW()
updated_at TIMESTAMP DEFAULT NOW()
END TABLE
' BOM components
TABLE bom_components
id UUID PRIMARY KEY DEFAULT uuid_generate_v4()
bom_id UUID REFERENCES bill_of_materials(id) ON DELETE CASCADE
component_item_id UUID REFERENCES items(id)
line_number INTEGER NOT NULL
quantity_required DECIMAL(15,6) NOT NULL
unit_of_measure VARCHAR(20)
scrap_percent DECIMAL(5,2) DEFAULT 0
total_quantity DECIMAL(15,6) GENERATED ALWAYS AS (quantity_required * (1 + scrap_percent/100)) STORED
cost_per_unit DECIMAL(15,4)
total_cost DECIMAL(15,4) GENERATED ALWAYS AS (total_quantity * cost_per_unit) STORED
notes TEXT
created_at TIMESTAMP DEFAULT NOW()
UNIQUE(bom_id, line_number)
END TABLE
' Work orders
TABLE work_orders
id UUID PRIMARY KEY DEFAULT uuid_generate_v4()
wo_number VARCHAR(50) UNIQUE NOT NULL
item_id UUID REFERENCES items(id)
bom_id UUID REFERENCES bill_of_materials(id)
quantity_to_produce DECIMAL(15,3) NOT NULL
quantity_completed DECIMAL(15,3) DEFAULT 0
quantity_scrapped DECIMAL(15,3) DEFAULT 0
status VARCHAR(50) DEFAULT 'planned'
priority VARCHAR(20) DEFAULT 'normal'
planned_start_date TIMESTAMP
planned_end_date TIMESTAMP
actual_start_date TIMESTAMP
actual_end_date TIMESTAMP
warehouse_id UUID REFERENCES warehouses(id)
work_center VARCHAR(50)
labor_hours_estimated DECIMAL(10,2)
labor_hours_actual DECIMAL(10,2)
notes TEXT
created_by VARCHAR(100)
created_at TIMESTAMP DEFAULT NOW()
updated_at TIMESTAMP DEFAULT NOW()
END TABLE
' === FINANCIAL MODULE ===
' General ledger accounts
TABLE gl_accounts
id UUID PRIMARY KEY DEFAULT uuid_generate_v4()
account_number VARCHAR(20) UNIQUE NOT NULL
account_name VARCHAR(100) NOT NULL
account_type VARCHAR(50) NOT NULL
parent_account_id UUID REFERENCES gl_accounts(id)
currency_code VARCHAR(3) DEFAULT 'USD'
normal_balance VARCHAR(10) CHECK (normal_balance IN ('debit', 'credit'))
is_active BOOLEAN DEFAULT TRUE
is_control_account BOOLEAN DEFAULT FALSE
allow_manual_entry BOOLEAN DEFAULT TRUE
description TEXT
created_at TIMESTAMP DEFAULT NOW()
updated_at TIMESTAMP DEFAULT NOW()
END TABLE
' Journal entries header
TABLE journal_entries
id UUID PRIMARY KEY DEFAULT uuid_generate_v4()
journal_number VARCHAR(50) UNIQUE NOT NULL
journal_date DATE NOT NULL
posting_date DATE NOT NULL
period VARCHAR(20)
journal_type VARCHAR(50)
description TEXT
reference_type VARCHAR(50)
reference_number VARCHAR(50)
status VARCHAR(20) DEFAULT 'draft'
total_debit DECIMAL(15,2)
total_credit DECIMAL(15,2)
is_balanced BOOLEAN GENERATED ALWAYS AS (total_debit = total_credit) STORED
posted_by VARCHAR(100)
posted_at TIMESTAMP
reversed_by_id UUID REFERENCES journal_entries(id)
created_by VARCHAR(100)
created_at TIMESTAMP DEFAULT NOW()
END TABLE
' Journal entry lines
TABLE journal_entry_lines
id UUID PRIMARY KEY DEFAULT uuid_generate_v4()
journal_entry_id UUID REFERENCES journal_entries(id) ON DELETE CASCADE
line_number INTEGER NOT NULL
account_id UUID REFERENCES gl_accounts(id)
debit_amount DECIMAL(15,2) DEFAULT 0
credit_amount DECIMAL(15,2) DEFAULT 0
description TEXT
dimension1 VARCHAR(50)
dimension2 VARCHAR(50)
dimension3 VARCHAR(50)
created_at TIMESTAMP DEFAULT NOW()
UNIQUE(journal_entry_id, line_number)
CHECK (debit_amount = 0 OR credit_amount = 0)
END TABLE
' Invoices
TABLE invoices
id UUID PRIMARY KEY DEFAULT uuid_generate_v4()
invoice_number VARCHAR(50) UNIQUE NOT NULL
invoice_type VARCHAR(20) DEFAULT 'standard'
customer_id UUID REFERENCES customers(id)
vendor_id UUID REFERENCES vendors(id)
order_id UUID
invoice_date DATE NOT NULL
due_date DATE NOT NULL
status VARCHAR(20) DEFAULT 'draft'
currency_code VARCHAR(3) DEFAULT 'USD'
exchange_rate DECIMAL(10,6) DEFAULT 1.0
subtotal DECIMAL(15,2)
discount_amount DECIMAL(15,2) DEFAULT 0
tax_amount DECIMAL(15,2)
total_amount DECIMAL(15,2)
amount_paid DECIMAL(15,2) DEFAULT 0
balance_due DECIMAL(15,2) GENERATED ALWAYS AS (total_amount - amount_paid) STORED
payment_terms VARCHAR(50)
notes TEXT
created_by VARCHAR(100)
created_at TIMESTAMP DEFAULT NOW()
updated_at TIMESTAMP DEFAULT NOW()
END TABLE
' === HUMAN RESOURCES MODULE ===
' Employees table
TABLE employees
id UUID PRIMARY KEY DEFAULT uuid_generate_v4()
employee_number VARCHAR(50) UNIQUE NOT NULL
first_name VARCHAR(100) NOT NULL
last_name VARCHAR(100) NOT NULL
middle_name VARCHAR(100)
full_name VARCHAR(255) GENERATED ALWAYS AS (first_name || ' ' || COALESCE(middle_name || ' ', '') || last_name) STORED
email VARCHAR(100) UNIQUE
phone VARCHAR(50)
mobile VARCHAR(50)
address TEXT
city VARCHAR(100)
state VARCHAR(50)
country VARCHAR(50)
postal_code VARCHAR(20)
date_of_birth DATE
gender VARCHAR(20)
marital_status VARCHAR(20)
national_id VARCHAR(50)
passport_number VARCHAR(50)
department_id UUID
position_title VARCHAR(100)
manager_id UUID REFERENCES employees(id)
hire_date DATE NOT NULL
employment_status VARCHAR(50) DEFAULT 'active'
employment_type VARCHAR(50) DEFAULT 'full-time'
salary DECIMAL(15,2)
hourly_rate DECIMAL(10,2)
commission_percent DECIMAL(5,2)
bank_account_number VARCHAR(50)
bank_name VARCHAR(100)
emergency_contact_name VARCHAR(100)
emergency_contact_phone VARCHAR(50)
notes TEXT
created_at TIMESTAMP DEFAULT NOW()
updated_at TIMESTAMP DEFAULT NOW()
END TABLE
' Payroll records
TABLE payroll
id UUID PRIMARY KEY DEFAULT uuid_generate_v4()
payroll_number VARCHAR(50) UNIQUE NOT NULL
employee_id UUID REFERENCES employees(id)
pay_period_start DATE NOT NULL
pay_period_end DATE NOT NULL
payment_date DATE NOT NULL
hours_worked DECIMAL(10,2)
overtime_hours DECIMAL(10,2)
regular_pay DECIMAL(15,2)
overtime_pay DECIMAL(15,2)
commission DECIMAL(15,2)
bonus DECIMAL(15,2)
gross_pay DECIMAL(15,2)
tax_deductions DECIMAL(15,2)
other_deductions DECIMAL(15,2)
net_pay DECIMAL(15,2)
payment_method VARCHAR(50)
payment_reference VARCHAR(100)
status VARCHAR(20) DEFAULT 'pending'
approved_by VARCHAR(100)
approved_date TIMESTAMP
created_at TIMESTAMP DEFAULT NOW()
END TABLE
' === SYSTEM TABLES ===
' Audit trail
TABLE erp_audit_log
id UUID PRIMARY KEY DEFAULT uuid_generate_v4()
table_name VARCHAR(50) NOT NULL
record_id UUID NOT NULL
action VARCHAR(20) NOT NULL
changed_fields JSONB
old_values JSONB
new_values JSONB
user_id VARCHAR(100)
user_ip VARCHAR(45)
user_agent TEXT
created_at TIMESTAMP DEFAULT NOW()
END TABLE
' System settings
TABLE erp_settings
id UUID PRIMARY KEY DEFAULT uuid_generate_v4()
module VARCHAR(50) NOT NULL
setting_key VARCHAR(100) NOT NULL
setting_value TEXT
data_type VARCHAR(20)
description TEXT
is_encrypted BOOLEAN DEFAULT FALSE
created_at TIMESTAMP DEFAULT NOW()
updated_at TIMESTAMP DEFAULT NOW()
UNIQUE(module, setting_key)
END TABLE
' Create indexes for performance
CREATE INDEX idx_inventory_item_warehouse ON inventory_stock(item_id, warehouse_id)
CREATE INDEX idx_po_vendor ON purchase_orders(vendor_id)
CREATE INDEX idx_po_status ON purchase_orders(status)
CREATE INDEX idx_so_customer ON sales_orders(customer_id)
CREATE INDEX idx_so_status ON sales_orders(status)
CREATE INDEX idx_wo_status ON work_orders(status)
CREATE INDEX idx_invoice_customer ON invoices(customer_id)
CREATE INDEX idx_invoice_status ON invoices(status)
CREATE INDEX idx_employee_manager ON employees(manager_id)
CREATE INDEX idx_journal_date ON journal_entries(journal_date)
CREATE INDEX idx_audit_table_record ON erp_audit_log(table_name, record_id)

View file

@ -0,0 +1,205 @@
# ERP Inventory Management Guide
## Overview
The ERP Inventory Management module provides comprehensive tools for managing stock levels, warehouse operations, purchasing, and inventory tracking across your organization.
## Core Functions
### Receive Inventory
Process incoming goods from purchase orders.
**Steps:**
1. Enter the purchase order number
2. System displays ordered items and quantities
3. Enter actual quantities received for each item
4. System updates stock levels and creates transaction records
5. Notifications sent to relevant personnel
**Key Features:**
- Automatic stock level updates
- Variance tracking (ordered vs. received)
- Cost tracking and average cost calculation
- Receipt transaction logging
### Ship Inventory
Process outgoing shipments for sales orders.
**Steps:**
1. Enter the sales order number
2. System verifies stock availability
3. If sufficient stock, shipment is created
4. Stock levels are deducted
5. Customer receives shipping notification
**Checks Performed:**
- Stock availability verification
- Reserved quantity validation
- Backorder handling
### Check Stock
Query current inventory levels across warehouses.
**Information Displayed:**
- Item name and code
- Quantity on hand per warehouse
- Available quantity (on hand minus reserved)
- Total across all warehouses
- Low stock warnings
- Reorder recommendations
### Transfer Stock
Move inventory between warehouses.
**Process:**
1. Select item to transfer
2. Choose source warehouse
3. Verify available quantity
4. Enter transfer quantity
5. Select destination warehouse
6. System creates transfer records
**Tracking:**
- Transfer numbers for audit trail
- Out/In transaction pairs
- Cost tracking maintained
### Cycle Count
Perform physical inventory counts and adjustments.
**Process:**
1. Select warehouse to count
2. System shows items and system quantities
3. Enter physical counts for each item
4. System calculates variances
5. Automatic adjustments created
6. Report sent to inventory manager
## Data Tables
### Items
- Item code and name
- Category and description
- Unit of measure
- Minimum stock level
- Reorder point and quantity
- Average cost and last cost
### Inventory Stock
- Item reference
- Warehouse location
- Quantity on hand
- Quantity reserved
- Quantity available
- Last movement date
- Last counted date
### Inventory Transactions
- Transaction type (receipt, shipment, transfer, adjustment)
- Transaction number
- Item and warehouse
- Quantity and cost
- Reference (PO, SO, etc.)
- User and timestamp
### Warehouses
- Warehouse code and name
- Location address
- Contact information
- Capacity limits
## Alerts and Notifications
### Low Stock Alerts
Triggered when available quantity falls below minimum stock level.
### Reorder Notifications
Automatic task creation when stock reaches reorder point.
### Receipt Confirmations
Email sent to buyer when purchase order is received.
### Shipment Notifications
Customer notified when order ships with tracking information.
## Best Practices
### Daily Operations
1. Process all receipts promptly
2. Ship orders in FIFO sequence
3. Review low stock alerts
4. Address reorder recommendations
### Weekly Tasks
1. Review inventory transaction reports
2. Investigate any discrepancies
3. Plan upcoming transfers
4. Update reorder points as needed
### Monthly Tasks
1. Conduct cycle counts by zone
2. Review slow-moving inventory
3. Analyze inventory turnover
4. Adjust minimum stock levels
### Year-End
1. Complete full physical inventory
2. Reconcile all variances
3. Review and adjust costs
4. Archive transaction history
## Frequently Asked Questions
**Q: How is average cost calculated?**
A: Average cost is recalculated with each receipt: (existing value + new receipt value) / total quantity.
**Q: Can I transfer reserved inventory?**
A: No, only available (unreserved) inventory can be transferred.
**Q: What happens if I receive more than ordered?**
A: The system accepts over-receipts and updates the PO line accordingly.
**Q: How do I handle damaged goods?**
A: Use cycle count with an adjustment to remove damaged items, noting the reason.
**Q: Can I undo a shipment?**
A: Contact your administrator to process a return receipt transaction.
**Q: How do I set up a new warehouse?**
A: Add the warehouse to the warehouses table with code, name, and location details.
## Troubleshooting
### Purchase Order Not Found
- Verify the PO number is correct
- Check if PO status is "open" or "partial"
- Ensure you have access to the vendor
### Insufficient Stock for Shipment
- Check available quantity vs. ordered
- Review reserved quantities
- Consider warehouse transfers
### Cycle Count Variance
- Verify physical count accuracy
- Check for unprocessed receipts or shipments
- Review recent transfers
### Transfer Failures
- Verify source warehouse has stock
- Check available (not reserved) quantity
- Ensure destination warehouse is active
## Reports
Available inventory reports:
- **Stock Status**: Current levels by item/warehouse
- **Transaction History**: All movements for date range
- **Aging Report**: Stock age by receipt date
- **Valuation Report**: Inventory value by category
- **Turnover Report**: Movement frequency analysis

View file

@ -0,0 +1,44 @@
PARAM name AS NAME LIKE "John Smith" DESCRIPTION "Employee's full name"
PARAM email AS EMAIL LIKE "john.smith@company.com" DESCRIPTION "Work email address"
PARAM jobtitle AS STRING LIKE "Software Engineer" DESCRIPTION "Job title or position"
PARAM department AS STRING LIKE "Engineering" DESCRIPTION "Department name"
PARAM hiredate AS DATE LIKE "2024-01-15" DESCRIPTION "Employment start date (YYYY-MM-DD)"
PARAM phone AS PHONE LIKE "+1-555-123-4567" DESCRIPTION "Phone number" OPTIONAL
PARAM manageremail AS EMAIL LIKE "manager@company.com" DESCRIPTION "Manager's email address" OPTIONAL
DESCRIPTION "Add a new employee to the HR system with a unique employee number"
currentyear = FORMAT(NOW(), "YYYY")
employeenumber = "EMP" + currentyear + "-" + FORMAT(RANDOM(1000, 9999))
WITH employee
number = employeenumber
fullName = name
emailAddress = email
title = jobtitle
dept = department
startDate = hiredate
phoneNumber = phone
manager = manageremail
END WITH
SAVE "employees.csv", employee
SET BOT MEMORY "last_employee", employeenumber
hrnotification = "New employee added: " + name + " (" + employeenumber + ") - " + jobtitle + " in " + department
SEND EMAIL "hr@company.com", "New Employee Added", hrnotification
IF manageremail THEN
managernotification = "New team member:\n\nName: " + name + "\nTitle: " + jobtitle + "\nStart Date: " + hiredate
SEND EMAIL manageremail, "New Team Member: " + name, managernotification
END IF
TALK "Employee added: " + name
TALK "Employee Number: " + employeenumber
TALK "Email: " + email
TALK "Title: " + jobtitle
TALK "Department: " + department
TALK "Start Date: " + hiredate
RETURN employeenumber

View file

@ -0,0 +1,60 @@
' Employee Management Scheduled Jobs
' Run setup_schedules once to configure all automated jobs
PARAM jobname AS STRING DESCRIPTION "Name of the job to execute"
IF jobname = "anniversary check" THEN
SET SCHEDULE "0 8 * * *"
let today = FORMAT NOW() AS "MM-DD"
let message = "Checking for work anniversaries on " + today
TALK message
' Send anniversary report to HR
let report = "Daily Anniversary Check completed for " + FORMAT NOW() AS "YYYY-MM-DD"
SEND MAIL "hr@company.com", "Anniversary Check Report", report
END IF
IF jobname = "probation reminder" THEN
SET SCHEDULE "0 9 * * 1"
let message = "Weekly probation review reminder sent"
TALK message
let report = "Please review employees approaching end of probation period."
SEND MAIL "hr@company.com", "Probation Review Reminder", report
END IF
IF jobname = "document expiry" THEN
SET SCHEDULE "0 10 * * *"
let message = "Checking for expiring employee documents"
TALK message
let report = "Document expiry check completed. Please review any flagged items."
SEND MAIL "hr@company.com", "Document Expiry Alert", report
END IF
IF jobname = "daily report" THEN
SET SCHEDULE "0 18 * * 1-5"
let reportdate = FORMAT NOW() AS "YYYY-MM-DD"
let report = "Daily HR Report for " + reportdate + "\n\n"
report = report + "Employee activity summary generated.\n"
report = report + "Please check the HR dashboard for details."
SEND MAIL "hr@company.com", "Daily HR Report - " + reportdate, report
TALK "Daily HR report sent"
END IF
IF jobname = "setup schedules" THEN
TALK "Setting up HR scheduled jobs..."
TALK "• Anniversary Check: Daily at 8:00 AM"
TALK "• Probation Reminder: Weekly on Monday at 9:00 AM"
TALK "• Document Expiry: Daily at 10:00 AM"
TALK "• Daily Report: Weekdays at 6:00 PM"
TALK ""
TALK "✅ All schedules configured successfully!"
END IF

View file

@ -0,0 +1,25 @@
PARAM searchterm AS STRING LIKE "John" DESCRIPTION "Name, email, or employee number to search for"
DESCRIPTION "Searches for employees in the HR system by name, email, or employee number."
IF searchterm = "" THEN
TALK "What would you like to search for? You can enter a name, email, or employee number."
searchterm = HEAR
END IF
IF searchterm = "" THEN
TALK "I need a search term to find employees."
RETURN
END IF
TALK "🔍 Searching for employees matching: " + searchterm
TALK ""
TALK "To search the employee database, I'll look through the records for you."
TALK "You can search by:"
TALK "• Full name or partial name"
TALK "• Email address"
TALK "• Employee number (e.g., EMP2024-1234)"
TALK ""
TALK "💡 Tip: For best results, use the exact employee number if you have it."
SET BOT MEMORY "last_search", searchterm

View file

@ -0,0 +1,40 @@
ADD TOOL "add-employee"
ADD TOOL "update-employee"
ADD TOOL "search-employee"
ADD TOOL "employee-directory"
ADD TOOL "org-chart"
ADD TOOL "emergency-contacts"
USE KB "employees.gbkb"
SET CONTEXT "employee management" AS "You are an HR assistant helping manage employee information. Help with adding new employees, updating records, searching the directory, viewing org charts, and managing emergency contacts. Maintain confidentiality of employee data."
CLEAR SUGGESTIONS
ADD SUGGESTION "directory" AS "Employee directory"
ADD SUGGESTION "add" AS "Add new employee"
ADD SUGGESTION "search" AS "Search employee"
ADD SUGGESTION "org" AS "Organization chart"
ADD SUGGESTION "emergency" AS "Emergency contacts"
BEGIN TALK
**Employee Management System**
I can help you with:
View employee directory
Add new employees
Search for employees
View organization chart
Manage emergency contacts
Generate employee reports
Select an option or tell me what you need.
END TALK
BEGIN SYSTEM PROMPT
You are an HR assistant for the Employee Management System.
Confirm sensitive operations before executing.
Never expose salaries or personal IDs without authorization.
Use professional and helpful language.
END SYSTEM PROMPT

View file

@ -0,0 +1,91 @@
# HR Policies and Procedures
## Employee Onboarding
### New Employee Checklist
When a new employee joins the company, the following steps must be completed:
1. **Day 1**: Complete all paperwork including tax forms, emergency contacts, and company policies acknowledgment
2. **Week 1**: Attend orientation sessions and meet with department head
3. **Month 1**: Complete required training modules and have first check-in with manager
### Required Documents
- Government-issued photo ID
- Proof of work authorization
- Signed offer letter
- Emergency contact information
- Direct deposit form
## Leave Policies
### Paid Time Off (PTO)
- Full-time employees accrue 15 days of PTO per year
- PTO accrual begins after 90-day probation period
- Maximum PTO carryover is 5 days per year
- PTO requests must be submitted at least 2 weeks in advance
### Sick Leave
- Employees receive 10 sick days per year
- Sick leave does not carry over to the next year
- Doctor's note required for absences exceeding 3 consecutive days
### Parental Leave
- Primary caregiver: 12 weeks paid leave
- Secondary caregiver: 4 weeks paid leave
- Must be taken within 12 months of birth or adoption
## Work Hours
### Standard Schedule
- Regular work hours are 9:00 AM to 5:00 PM, Monday through Friday
- One hour lunch break is provided
- Core hours (required presence): 10:00 AM to 3:00 PM
### Overtime
- Non-exempt employees receive 1.5x pay for hours over 40 per week
- Overtime must be pre-approved by manager
- Compensatory time off may be offered in lieu of overtime pay
## Performance Reviews
### Annual Review Cycle
- Reviews conducted in November/December
- Self-assessment due by November 15
- Manager assessment due by December 1
- Review meetings completed by December 15
### Probation Period
- All new employees have a 90-day probation period
- Performance review conducted at 30, 60, and 90 days
- Probation may be extended by 30 days if needed
## Employee Benefits
### Health Insurance
- Medical, dental, and vision coverage available
- Company pays 80% of employee premium
- Coverage begins first day of month following start date
### Retirement
- 401(k) plan with company match up to 4%
- Eligible after 90 days of employment
- Immediate vesting
### Professional Development
- $1,500 annual training budget per employee
- Conference attendance encouraged
- Tuition reimbursement program available
## Frequently Asked Questions
**Q: How do I request time off?**
A: Submit a PTO request through the HR system at least 2 weeks before your planned absence.
**Q: Who do I contact for benefits questions?**
A: Contact hr@company.com or your HR business partner.
**Q: How do I update my emergency contacts?**
A: Ask the HR assistant to update your emergency contact information.
**Q: What is the dress code?**
A: Business casual Monday through Thursday, casual Fridays.

View file

@ -0,0 +1,98 @@
# Organization Structure
## Company Overview
Our company is organized into several key departments, each with specific functions and responsibilities.
## Departments
### Engineering
- **Head**: Chief Technology Officer (CTO)
- **Teams**: Backend, Frontend, DevOps, QA
- **Headcount**: ~50 employees
- **Location**: Main Office, Floor 3
### Sales
- **Head**: VP of Sales
- **Teams**: Enterprise Sales, SMB Sales, Sales Development
- **Headcount**: ~30 employees
- **Location**: Main Office, Floor 2
### Marketing
- **Head**: Chief Marketing Officer (CMO)
- **Teams**: Brand, Digital Marketing, Content, Events
- **Headcount**: ~15 employees
- **Location**: Main Office, Floor 2
### Human Resources
- **Head**: VP of People
- **Teams**: Talent Acquisition, HR Operations, Learning & Development
- **Headcount**: ~10 employees
- **Location**: Main Office, Floor 1
### Finance
- **Head**: Chief Financial Officer (CFO)
- **Teams**: Accounting, FP&A, Payroll
- **Headcount**: ~12 employees
- **Location**: Main Office, Floor 1
### Customer Success
- **Head**: VP of Customer Success
- **Teams**: Onboarding, Support, Account Management
- **Headcount**: ~20 employees
- **Location**: Main Office, Floor 2
## Reporting Structure
```
CEO
├── CTO (Engineering)
│ ├── VP Engineering
│ │ ├── Engineering Managers
│ │ └── Tech Leads
│ └── Director of DevOps
├── CFO (Finance)
│ ├── Controller
│ └── FP&A Manager
├── CMO (Marketing)
│ ├── Director of Brand
│ └── Director of Digital
├── VP of Sales
│ ├── Regional Sales Directors
│ └── SDR Manager
├── VP of People (HR)
│ ├── Talent Acquisition Manager
│ └── HR Business Partners
└── VP of Customer Success
├── Support Manager
└── Account Management Director
```
## Office Locations
### Headquarters
- **Address**: 123 Main Street, San Francisco, CA 94102
- **Floors**: 1-3
- **Capacity**: 150 employees
### Remote Locations
- New York satellite office
- London office (EMEA)
- Work from home employees
## Key Contacts
| Role | Name | Email |
|------|------|-------|
| CEO | Jane Smith | jane.smith@company.com |
| CTO | John Davis | john.davis@company.com |
| VP of People | Sarah Johnson | sarah.johnson@company.com |
| Office Manager | Mike Wilson | mike.wilson@company.com |
## How to Find Someone
To find an employee in the organization:
1. Ask the HR assistant to search by name
2. Use the employee directory
3. Check the org chart for reporting relationships
4. Contact HR for confidential inquiries

View file

@ -0,0 +1,7 @@
name,value
episodic-memory-history,2
episodic-memory-threshold,4
theme-color1,#2E7D32
theme-color2,#E8F5E9
theme-logo,https://pragmatismo.com.br/icons/general-bots.svg
theme-title,Employee Management - General Bots
1 name value
2 episodic-memory-history 2
3 episodic-memory-threshold 4
4 theme-color1 #2E7D32
5 theme-color2 #E8F5E9
6 theme-logo https://pragmatismo.com.br/icons/general-bots.svg
7 theme-title Employee Management - General Bots

View file

@ -0,0 +1,425 @@
# API Client Template (api-client.gbai)
A General Bots template demonstrating REST API integration patterns for connecting to external services and data sources.
## Overview
The API Client template provides examples and patterns for integrating General Bots with external REST APIs. It includes examples for weather services, Microsoft Partner Center integration, and general HTTP request patterns that can be adapted for any API.
## Features
- **REST API Integration** - GET, POST, PUT, DELETE request patterns
- **Authentication** - OAuth, Bearer tokens, API keys
- **Header Management** - Custom headers for API requirements
- **Pagination Support** - Handle paginated API responses
- **Data Synchronization** - Sync external data to local tables
- **Scheduled Jobs** - Automated API polling and sync
## Package Structure
```
api-client.gbai/
├── README.md
├── api-client.gbdialog/
│ ├── climate.bas # Weather API example
│ └── msft-partner-center.bas # Microsoft Partner Center integration
└── api-client.gbot/
└── config.csv # Bot configuration
```
## Scripts
| File | Description |
|------|-------------|
| `climate.bas` | Weather API tool for getting current conditions |
| `msft-partner-center.bas` | Full Microsoft Partner Center billing sync |
## Basic API Patterns
### Simple GET Request
```basic
' Get data from an API
response = GET "https://api.example.com/data"
IF response THEN
TALK "Data received: " + response.value
ELSE
TALK "Failed to fetch data"
END IF
```
### POST Request with Body
```basic
' Send data to an API
SET HEADER "Content-Type" AS "application/json"
payload = {"name": "John", "email": "john@example.com"}
response = POST "https://api.example.com/users", payload
IF response.id THEN
TALK "User created with ID: " + response.id
END IF
```
### PUT Request for Updates
```basic
' Update existing resource
SET HEADER "Content-Type" AS "application/json"
updates = {"status": "active", "role": "admin"}
response = PUT "https://api.example.com/users/123", updates
TALK "User updated: " + response.status
```
### DELETE Request
```basic
' Delete a resource
response = DELETE "https://api.example.com/users/123"
IF response.deleted THEN
TALK "User deleted successfully"
END IF
```
## Authentication Patterns
### API Key Authentication
```basic
SET HEADER "X-API-Key" AS "your-api-key-here"
response = GET "https://api.example.com/protected-resource"
```
### Bearer Token Authentication
```basic
SET HEADER "Authorization" AS "Bearer " + access_token
response = GET "https://api.example.com/user/profile"
```
### OAuth 2.0 Token Exchange
```basic
' Get OAuth token
SET HEADER "Content-Type" AS "application/x-www-form-urlencoded"
tokenResponse = POST "https://auth.example.com/oauth/token",
"grant_type=client_credentials&client_id=" + clientId +
"&client_secret=" + clientSecret
access_token = tokenResponse.access_token
' Use token for API calls
SET HEADER "Authorization" AS "Bearer " + access_token
data = GET "https://api.example.com/resources"
```
### Basic Authentication
```basic
credentials = BASE64(username + ":" + password)
SET HEADER "Authorization" AS "Basic " + credentials
response = GET "https://api.example.com/secure-endpoint"
```
## Weather API Example
The `climate.bas` tool demonstrates a simple API integration:
```basic
PARAM location AS "The city and state, e.g. San Francisco, CA"
PARAM unit AS "celsius", "fahrenheit"
DESCRIPTION "Get the current weather in a given location"
' Implementation would call weather API
' response = GET "https://api.weather.com/current?location=" + location
RETURN weather_info
```
### Usage
```
User: What's the weather in New York?
Bot: [Calls climate tool with location="New York"]
Bot: It's currently 72°F and sunny in New York, NY.
```
## Microsoft Partner Center Integration
The `msft-partner-center.bas` demonstrates a complex enterprise API integration:
### Features
- OAuth token authentication with Azure AD
- Multi-resource synchronization (Customers, Subscriptions, Billing)
- Scheduled execution
- Pagination handling
- Database table management
### Configuration
```basic
' Required parameters
tenantId = GET ENV "AZURE_TENANT_ID"
clientId = GET ENV "AZURE_CLIENT_ID"
clientSecret = GET ENV "AZURE_CLIENT_SECRET"
host = "https://api.partnercenter.microsoft.com"
```
### Scheduled Sync
```basic
SET SCHEDULE "1 * * * * *" ' Run periodically
' Set required headers
SET HEADER "MS-Contract-Version" AS "v1"
SET HEADER "MS-CorrelationId" AS UUID()
SET HEADER "MS-RequestId" AS UUID()
SET HEADER "MS-PartnerCenter-Application" AS "General Bots"
SET HEADER "X-Locale" AS "en-US"
```
### Sync Customers and Subscriptions
```basic
SET PAGE MODE "none"
customers = GET host + "/v1/customers?size=20000"
MERGE "Customers" WITH customers.items BY "Id"
FOR EACH customer IN customers
subs = GET host + "/v1/customers/" + customer.id + "/subscriptions"
MERGE "Subscriptions" WITH subs.items BY "Id"
END FOR
```
### Billing Data Sync
```basic
SET PAGE MODE "auto"
billingItems = GET host + "/v1/invoices/unbilled/lineitems" +
"?provider=onetime&invoicelineitemtype=usagelineitems&currencycode=USD"
FOR EACH item IN billingItems
SAVE "Billing", item.alternateId, item.customerId, item.productName,
item.quantity, item.unitPrice, item.subtotal, item.chargeStartDate
END FOR
```
### Table Definitions
```basic
TABLE Billing
CustomerId Customers
ResourceGroup string(200)
CustomerName string(400)
ProductName string(400)
Quantity double
UnitPrice double
Subtotal double
ChargeStartDate date
ChargeEndDate date
END TABLE
TABLE Customers
TenantId guid
CompanyName string(100)
Id guid
END TABLE
TABLE Subscriptions
CustomerId Customers
Id guid
OfferName string(50)
END TABLE
```
## Custom API Integration
### Creating Your Own API Client
```basic
' my-api-client.bas
PARAM resource AS STRING LIKE "users" DESCRIPTION "API resource to fetch"
PARAM filters AS STRING LIKE "status=active" DESCRIPTION "Query filters" OPTIONAL
DESCRIPTION "Fetch data from custom API"
' Configuration
api_base = GET ENV "MY_API_BASE_URL"
api_key = GET ENV "MY_API_KEY"
' Set authentication
SET HEADER "Authorization" AS "Bearer " + api_key
SET HEADER "Content-Type" AS "application/json"
' Build URL
url = api_base + "/" + resource
IF filters THEN
url = url + "?" + filters
END IF
' Make request
response = GET url
IF response.error THEN
RETURN {"success": false, "error": response.error}
END IF
RETURN {"success": true, "data": response.data, "count": UBOUND(response.data)}
```
### Handling Pagination
```basic
' paginated-fetch.bas
PARAM endpoint AS STRING DESCRIPTION "API endpoint"
DESCRIPTION "Fetch all pages from a paginated API"
all_results = []
page = 1
has_more = true
DO WHILE has_more
response = GET endpoint + "?page=" + page + "&per_page=100"
IF response.data THEN
all_results = MERGE all_results, response.data
IF UBOUND(response.data) < 100 THEN
has_more = false
ELSE
page = page + 1
END IF
ELSE
has_more = false
END IF
LOOP
RETURN all_results
```
### Error Handling
```basic
' api-with-retry.bas
PARAM url AS STRING DESCRIPTION "API URL to call"
PARAM max_retries AS INTEGER LIKE 3 DESCRIPTION "Maximum retry attempts"
DESCRIPTION "API call with automatic retry on failure"
retries = 0
success = false
DO WHILE retries < max_retries AND NOT success
response = GET url
IF response.error THEN
retries = retries + 1
WAIT retries * 2 ' Exponential backoff
ELSE
success = true
END IF
LOOP
IF success THEN
RETURN response
ELSE
RETURN {"error": "Max retries exceeded", "last_error": response.error}
END IF
```
## Configuration
Configure in `api-client.gbot/config.csv`:
| Parameter | Description | Example |
|-----------|-------------|---------|
| `API Base URL` | Default API endpoint | `https://api.example.com` |
| `API Timeout` | Request timeout in seconds | `30` |
| `Retry Count` | Number of retry attempts | `3` |
| `Log Requests` | Enable request logging | `true` |
### Environment Variables
Store sensitive values as environment variables:
```bash
MY_API_KEY=your-api-key
MY_API_SECRET=your-secret
AZURE_TENANT_ID=your-tenant-id
AZURE_CLIENT_ID=your-client-id
AZURE_CLIENT_SECRET=your-client-secret
```
Access in BASIC:
```basic
api_key = GET ENV "MY_API_KEY"
```
## Best Practices
1. **Secure credentials** - Never hardcode API keys; use environment variables
2. **Handle errors** - Always check for error responses
3. **Rate limiting** - Respect API rate limits with delays
4. **Pagination** - Handle paginated responses properly
5. **Logging** - Log API calls for debugging
6. **Timeouts** - Set appropriate timeout values
7. **Retries** - Implement retry logic for transient failures
8. **Caching** - Cache responses when appropriate
## Common HTTP Headers
| Header | Purpose | Example |
|--------|---------|---------|
| `Content-Type` | Request body format | `application/json` |
| `Accept` | Expected response format | `application/json` |
| `Authorization` | Authentication | `Bearer token` |
| `X-API-Key` | API key auth | `your-key` |
| `User-Agent` | Client identification | `GeneralBots/1.0` |
## Troubleshooting
| Issue | Cause | Solution |
|-------|-------|----------|
| 401 Unauthorized | Invalid credentials | Check API key/token |
| 403 Forbidden | Missing permissions | Verify API access rights |
| 404 Not Found | Wrong endpoint | Verify URL path |
| 429 Too Many Requests | Rate limited | Add delays between requests |
| 500 Server Error | API issue | Retry with backoff |
| Timeout | Slow API | Increase timeout setting |
## Related Templates
- `public-apis.gbai` - Pre-built integrations for public APIs
- `bling.gbai` - ERP API integration example
- `llm-server.gbai` - Building your own API endpoints
- `crm.gbai` - CRM with external API sync
## Use Cases
- **Data Synchronization** - Sync data from external systems
- **Service Integration** - Connect to SaaS platforms
- **Automation** - Automate cross-system workflows
- **Monitoring** - Poll external systems for changes
- **Reporting** - Aggregate data from multiple APIs
## License
AGPL-3.0 - Part of General Bots Open Source Platform.
---
**Pragmatismo** - General Bots

View file

@ -0,0 +1,8 @@
PARAM location AS "The city and state, e.g. San Francisco, CA"
PARAM unit AS "celsius", "fahrenheit"
DESCRIPTION "Get the current weather in a given location"
RETURN weather_info

View file

@ -0,0 +1,117 @@
REM Set SCHEDULE "1 * * * * *"
REM Obtém token Do Partner Center via token Do AD.
Set HEADER "return-client-request-id" As "True"
Set HEADER "Content-Type" As "application/x-www-form-urlencoded; charset=utf-8"
REM pcToken = POST "https://login.microsoftonline.com/" + tenantId + "/oauth2/token", "resource=https%3A%2F%2Fgraph.windows.net&client_id=" + clientId + "&client_secret=" + clientSecret + "&grant_type=client_credentials"
REM repara chamada de Billing.
REM Set HEADER "Authorization" As "Bearer " + pcToken.access_token
Set HEADER "MS-Contract-Version" As "v1"
Set HEADER "MS-CorrelationId" As uuid()
Set HEADER "MS-RequestId" As uuid()
Set HEADER "MS-PartnerCenter-Application" As "VPN General Bots"
Set HEADER "X-Locale" As "en-US"
REM Syncs Customers and Subscriptions.
Set PAGE MODE "none"
list = Get host + "/v1/customers?size=20000"
MERGE "Customers" With list.items BY "Id"
FOR EACH item IN list
subs = Get host + "/v1/customers/" + item.id + "/subscriptions"
MERGE "Subscriptions" With subs.items BY "Id"
END For
REM Check period.
If today = dueDay Then
If period = "previous" And Not CONTINUATION TOKEN Then
period = "current"
Else
period = "previous"
End If
Else
period = "current"
End If
REM Perform the Call And Loop through the billing items.
Set PAGE MODE "auto"
list = Get host + "/v1/invoices/unbilled/lineitems?provider=onetime&invoicelineitemtype=usagelineitems&currencycode=" + currency + "&period=previous&idparceiro=" + idparceiro
For EACH item IN list
SAVE "Billing", item.alternateId, item.availabilityId, item.billableQuantity, item.billingFrequency, item.chargeEndDate, item.chargeStartDate, item.chargeType, item.currency, item.customerCountry, item.customerDomainName, item.customerId, item.customerName, item.effectiveUnitPrice, item.invoiceNumber, item.meterDescription, item.mpnId, item.orderDate, item.orderId, item.partnerId, item.pCToBCExchangeRate, item.pCToBCExchangeRateDate, item.priceAdjustmentDescription, item.pricingCurrency, item.productId, item.productName, item.publisherId, item.publisherName, item.quantity, item.resellerMpnId, item.reservationOrderId, item.skuId, item.skuName, item.subscriptionDescription, item.subscriptionId, item.subtotal, item.taxTotal, item.termAndBillingCycle, item.totalForCustomer, item.unitPrice, item.unitType
END For
END FOR
TABLE Billing
CustomerId Customers
ResourceGroup string(200)
ResourceUri string(1000)
Tags string(max)
AdditionalInfo string(max)
ServiceInfo1 string(max)
ServiceInfo2 string(max)
CustomerCountry string(6)
MpnId string(50)
ResellerMpnId string(50)
ChargeType string(200)
UnitPrice* double
Quantity* double
UnitType string(max)
BillingPreTaxTotal double
BillingCurrency string(6)
PricingPreTaxTotal double
PricingCurrency string(6)
EntitlementId string(50)
EntitlementDescription string(400)
PCToBCExchangeRate double
PCToBCExchangeRateDate date
EffectiveUnitPrice* double
RateOfPartnerEarnedCredit double
ConsumedService string(200)
ResourceLocation string(100)
MeterRegion string(100)
PartnerId string(50)
PartnerName string(400)
CustomerName string(400)
CustomerDomainName string(400)
InvoiceNumber string(400)
ProductId string(50)
SkuId string(50)
AvailabilityId string(50)
SkuName string(200)
ProductName string(400)
PublisherName string(200)
PublisherId string(200)
SubscriptionId string(50)
SubscriptionDescription string(400)
ChargeStartDate* date
ChargeEndDate* date
UsageDate date
MeterType string(400)
MeterCategory string(100)
MeterId string(50)
MeterSubCategory string(100)
MeterName string(200)
UnitOfMeasure string(100)
Reprocess boolean
END TABLE
TABLE Customers
TenantId guid
CompanyName string(100)
Id guid
END TABLE
TABLE Subscriptions
CustomerId Customers
Id guid
OfferName string(50)
END TABLE

View file

@ -0,0 +1,758 @@
# General Bots Public APIs Integration
This package provides 50+ free API keywords for General Bots, allowing you to integrate various public services without requiring API keys or authentication.
## 📦 Package Contents
This `.gbai` template includes the following BASIC keyword files:
- `weather-apis.bas` - Weather data and forecasts
- `animals-apis.bas` - Animal facts and images
- `entertainment-apis.bas` - Jokes, quotes, and fun content
- `food-apis.bas` - Food recipes and drink information
- `data-utility-apis.bas` - Data utilities and geocoding
## 🌤️ Weather APIs
### 7Timer! Astro Weather
Get 7-day astronomical weather forecast for stargazing.
```basic
PARAM location AS string LIKE "116.39,39.90"
' Returns: Weather data for astronomy observation
```
### 7Timer! Civil Weather
Get 7-day civil weather forecast with temperature.
```basic
PARAM location AS string LIKE "116.39,39.90"
' Returns: Temperature, precipitation, wind data
```
### Open-Meteo Weather
Get real-time weather data (70+ years of historical data available).
```basic
PARAM latitude AS number LIKE 52.52
PARAM longitude AS number LIKE 13.41
' Returns: Current weather conditions
```
### Rain Viewer Radar Map
Get available rain radar map timestamps.
```basic
DESCRIPTION "Get available rain radar map timestamps"
' Returns: Radar data for visualization
```
### OpenSenseMap Weather Stations
Get data from personal weather stations in a bounding box.
```basic
PARAM bbox AS string LIKE "7.6,51.2,7.8,51.3"
' Returns: Temperature data from senseBoxes
```
### Air Quality Index
Get Air Quality Index data for major cities.
```basic
PARAM city AS string LIKE "beijing"
' Returns: AQI level and health recommendations
```
## 🐾 Animals APIs
### Random Cat Fact
```basic
DESCRIPTION "Get a random cat fact"
' Returns: Interesting cat fact
```
### Random Dog Fact
```basic
DESCRIPTION "Get a random dog fact"
' Returns: Interesting dog fact
```
### Random Dog Image
```basic
DESCRIPTION "Get a random dog image URL"
' Returns: URL and downloads image
```
### Random Cat Image
```basic
DESCRIPTION "Get a random cat image from Cataas"
' Returns: Cat image URL
```
### Random Fox Image
```basic
DESCRIPTION "Get a random fox image"
' Returns: Fox image URL
```
### Random Duck Image
```basic
DESCRIPTION "Get a random duck image"
' Returns: Duck image URL
```
### Random Shiba Inu Image
```basic
DESCRIPTION "Get a random Shiba Inu dog image"
' Returns: Shiba Inu image URL
```
### HTTP Cat (Status Code Cats)
```basic
PARAM status_code AS integer LIKE 404
' Returns: Cat image representing HTTP status
```
### HTTP Dog (Status Code Dogs)
```basic
PARAM status_code AS integer LIKE 404
' Returns: Dog image representing HTTP status
```
### PlaceBear Placeholder
```basic
PARAM width AS integer LIKE 400
PARAM height AS integer LIKE 300
' Returns: Bear placeholder image
```
### PlaceDog Placeholder
```basic
PARAM width AS integer LIKE 400
PARAM height AS integer LIKE 300
' Returns: Dog placeholder image
```
### PlaceKitten Placeholder
```basic
PARAM width AS integer LIKE 400
PARAM height AS integer LIKE 300
' Returns: Kitten placeholder image
```
### MeowFacts
```basic
PARAM count AS integer LIKE 1
' Returns: Random cat facts (up to 100)
```
### Random Axolotl
```basic
DESCRIPTION "Get random axolotl picture and facts"
' Returns: Axolotl image and facts
```
### Zoo Animals Info
```basic
DESCRIPTION "Get information about various zoo animals"
' Returns: Animal data with images
```
### Dog Breeds List
```basic
DESCRIPTION "Get a list of all dog breeds"
' Returns: Array of dog breeds
```
### Specific Dog Breed Image
```basic
PARAM breed AS string LIKE "husky"
' Returns: Image of specified breed
```
## 😄 Entertainment APIs
### Chuck Norris Joke
```basic
DESCRIPTION "Get a random Chuck Norris joke"
' Returns: Chuck Norris joke
```
### Chuck Norris Categories
```basic
DESCRIPTION "Get available Chuck Norris joke categories"
' Returns: Array of categories
```
### Chuck Norris Joke by Category
```basic
PARAM category AS string LIKE "dev"
' Returns: Joke from specific category
```
### Dad Joke
```basic
DESCRIPTION "Get a random dad joke"
' Returns: Dad joke from icanhazdadjoke
```
### Search Dad Jokes
```basic
PARAM search_term AS string LIKE "cat"
' Returns: Dad jokes containing search term
```
### Bored Activity
```basic
DESCRIPTION "Get a random activity suggestion"
' Returns: Activity suggestion with details
```
### Bored Activity by Type
```basic
PARAM activity_type AS "education", "recreational", "social", "diy", "charity", "cooking", "relaxation", "music", "busywork"
' Returns: Activity of specific type
```
### Random Useless Fact
```basic
DESCRIPTION "Get a random useless but true fact"
' Returns: Useless fact
```
### Random Fun Fact
```basic
DESCRIPTION "Get a random fun fact"
' Returns: Fun fact
```
### Kanye West Quote
```basic
DESCRIPTION "Get a random Kanye West quote"
' Returns: Kanye quote
```
### Advice Slip
```basic
DESCRIPTION "Get a random piece of advice"
' Returns: Random advice
```
### Search Advice
```basic
PARAM query AS string LIKE "love"
' Returns: Advice containing query word
```
### Corporate Buzzword
```basic
DESCRIPTION "Get random corporate buzzwords"
' Returns: Corporate buzzword phrase
```
### Yo Momma Joke
```basic
DESCRIPTION "Get a random Yo Momma joke"
' Returns: Yo Momma joke
```
### Random Quote
```basic
DESCRIPTION "Get a random inspirational quote"
' Returns: Quote with author
```
### Quote by Author
```basic
PARAM author AS string LIKE "einstein"
' Returns: Quote by specific author
```
### Programming Quote
```basic
DESCRIPTION "Get a random programming quote"
' Returns: Programming-related quote
```
### Zen Quote
```basic
DESCRIPTION "Get a random Zen/Stoicism quote"
' Returns: Zen quote
```
### Affirmation
```basic
DESCRIPTION "Get a random positive affirmation"
' Returns: Daily affirmation
```
### Random Trivia
```basic
DESCRIPTION "Get a random trivia question"
' Returns: Trivia question with answer
```
### Multiple Trivia Questions
```basic
PARAM amount AS integer LIKE 5
' Returns: Multiple trivia questions
```
### Excuse Generator
```basic
DESCRIPTION "Get a random excuse"
' Returns: Random excuse
```
### Insult Generator
```basic
DESCRIPTION "Get a random insult (clean)"
' Returns: Random insult
```
### Compliment Generator
```basic
DESCRIPTION "Get a random compliment"
' Returns: Random compliment
```
## 🍽️ Food & Drink APIs
### Random Coffee Image
```basic
DESCRIPTION "Get a random coffee image"
' Returns: Coffee image URL
```
### Random Food Dish
```basic
DESCRIPTION "Get a random food dish image"
' Returns: Food dish image
```
### Random Food by Category
```basic
PARAM category AS "biryani", "burger", "butter-chicken", "dessert", "dosa", "idly", "pasta", "pizza", "rice", "samosa"
' Returns: Food image from category
```
### Random Meal Recipe
```basic
DESCRIPTION "Get a random meal recipe"
' Returns: Full recipe with ingredients
```
### Search Meal by Name
```basic
PARAM meal_name AS string LIKE "chicken"
' Returns: Meals matching search
```
### Random Cocktail Recipe
```basic
DESCRIPTION "Get a random cocktail recipe"
' Returns: Cocktail recipe with ingredients
```
### Search Cocktail by Name
```basic
PARAM cocktail_name AS string LIKE "margarita"
' Returns: Cocktails matching search
```
### Search Cocktail by Ingredient
```basic
PARAM ingredient AS string LIKE "vodka"
' Returns: Cocktails with ingredient
```
### Fruit Information
```basic
PARAM fruit_name AS string LIKE "apple"
' Returns: Nutritional information
```
### All Fruits List
```basic
DESCRIPTION "Get a list of all fruits"
' Returns: Array of fruits
```
### Fruits by Family
```basic
PARAM family AS string LIKE "Rosaceae"
' Returns: Fruits from specific family
```
### Random Taco Recipe
```basic
DESCRIPTION "Get a random taco recipe"
' Returns: Taco recipe components
```
### PunkAPI Beer Info
```basic
DESCRIPTION "Get a random beer recipe"
' Returns: Beer details and recipe
```
### Search Beer by Name
```basic
PARAM beer_name AS string LIKE "punk"
' Returns: Beers matching search
```
### High ABV Beers
```basic
PARAM min_abv AS number LIKE 8.0
' Returns: Beers with high alcohol content
```
### Bacon Ipsum Text
```basic
PARAM paragraphs AS integer LIKE 3
' Returns: Bacon-themed lorem ipsum
```
## 🔧 Data Utility & Geocoding APIs
### Generate UUID
```basic
DESCRIPTION "Generate a random UUID v4"
' Returns: UUID string
```
### Generate Multiple UUIDs
```basic
PARAM count AS integer LIKE 5
' Returns: Array of UUIDs
```
### Get My IP Address
```basic
DESCRIPTION "Get your current public IP"
' Returns: IP address string
```
### Get IP Geolocation
```basic
PARAM ip_address AS string LIKE "8.8.8.8"
' Returns: Country, city, coordinates, ISP
```
### Check if Number is Even
```basic
PARAM number AS integer LIKE 42
' Returns: Boolean (humor API)
```
### Random Data Generator
```basic
DESCRIPTION "Generate random test data"
' Returns: User profile data
```
### Generate Lorem Ipsum
```basic
PARAM paragraphs AS integer LIKE 3
' Returns: Lorem ipsum text
```
### QR Code Generator
```basic
PARAM text AS string LIKE "https://pragmatismo.com.br"
PARAM size AS integer LIKE 200
' Returns: QR code image
```
### Barcode Generator
```basic
PARAM barcode_data AS string LIKE "1234567890"
PARAM format AS "code128", "ean13", "upca", "code39"
' Returns: Barcode image
```
### Country Information
```basic
PARAM country AS string LIKE "brazil"
' Returns: Detailed country data
```
### All Countries List
```basic
DESCRIPTION "Get a list of all countries"
' Returns: Array of 250+ countries
```
### Countries by Region
```basic
PARAM region AS "africa", "americas", "asia", "europe", "oceania"
' Returns: Countries in region
```
### Currency Converter
```basic
PARAM amount AS number LIKE 100
PARAM from_currency AS string LIKE "USD"
PARAM to_currency AS string LIKE "EUR"
' Returns: Converted amount
```
### Timezone Info
```basic
PARAM timezone AS string LIKE "America/New_York"
' Returns: Current time in timezone
```
### All Timezones List
```basic
DESCRIPTION "Get all timezones"
' Returns: Array of 400+ timezones
```
### Public Holidays
```basic
PARAM country_code AS string LIKE "US"
PARAM year AS integer LIKE 2024
' Returns: List of public holidays
```
### Number Facts
```basic
PARAM number AS integer LIKE 42
' Returns: Interesting number fact
```
### Random Number Fact
```basic
DESCRIPTION "Get a random number fact"
' Returns: Random number fact
```
### Date Facts
```basic
PARAM month AS integer LIKE 3
PARAM day AS integer LIKE 14
' Returns: Historical facts about date
```
### Math Fact
```basic
PARAM number AS integer LIKE 1729
' Returns: Mathematical fact
```
### Yes or No Decision
```basic
DESCRIPTION "Get a random Yes/No answer"
' Returns: Yes or No with GIF
```
### Postcode Lookup UK
```basic
PARAM postcode AS string LIKE "SW1A1AA"
' Returns: UK postcode information
```
### Brazilian CEP Lookup
```basic
PARAM cep AS string LIKE "01310-100"
' Returns: Brazilian postal code data
```
### JSON Placeholder Post
```basic
DESCRIPTION "Get sample post data"
' Returns: Test post data
```
### Random User Generator
```basic
DESCRIPTION "Generate random user data"
' Returns: Realistic user profile
```
### Multiple Random Users
```basic
PARAM count AS integer LIKE 5
' Returns: Array of user profiles
```
## 🚀 Usage Examples
### Example 1: Weather Bot
```basic
TALK "Where would you like to check the weather?"
HEAR city AS NAME
REM Get coordinates (you could use geocoding API)
lat = 52.52
lon = 13.41
REM Get weather data
weather_url = "https://api.open-meteo.com/v1/forecast?latitude=" + lat + "&longitude=" + lon + "&current_weather=true"
weather = GET weather_url
TALK "Current temperature in " + city + ": " + weather.current_weather.temperature + "°C"
TALK "Wind speed: " + weather.current_weather.windspeed + " km/h"
```
### Example 2: Daily Motivation Bot
```basic
REM Get random quote
quote_data = GET "https://api.quotable.io/random"
REM Get affirmation
affirmation = GET "https://www.affirmations.dev/"
TALK "🌟 Daily Motivation:"
TALK ""
TALK "Quote of the Day:"
TALK '"' + quote_data.content + '"'
TALK "— " + quote_data.author
TALK ""
TALK "💖 Affirmation:"
TALK affirmation.affirmation
```
### Example 3: Random Pet Image Bot
```basic
HEAR choice AS "Cat", "Dog", "Fox", "Duck"
IF choice = "Cat" THEN
image_url = "https://cataas.com/cat"
ELSE IF choice = "Dog" THEN
dog_data = GET "https://random.dog/woof.json"
image_url = dog_data.url
ELSE IF choice = "Fox" THEN
fox_data = GET "https://randomfox.ca/floof/"
image_url = fox_data.image
ELSE IF choice = "Duck" THEN
duck_data = GET "https://random-d.uk/api/random"
image_url = duck_data.url
END IF
TALK "Here's your random " + choice + " image!"
file = DOWNLOAD image_url
SEND FILE file
```
### Example 4: Recipe Finder Bot
```basic
TALK "What are you in the mood for?"
HEAR food AS "Meal", "Cocktail", "Beer"
IF food = "Meal" THEN
meal = GET "https://www.themealdb.com/api/json/v1/1/random.php"
recipe = meal.meals[0]
TALK "🍳 " + recipe.strMeal
TALK recipe.strInstructions
ELSE IF food = "Cocktail" THEN
cocktail = GET "https://www.thecocktaildb.com/api/json/v1/1/random.php"
drink = cocktail.drinks[0]
TALK "🍹 " + drink.strDrink
TALK drink.strInstructions
ELSE IF food = "Beer" THEN
beer_data = GET "https://api.punkapi.com/v2/beers/random"
beer = beer_data[0]
TALK "🍺 " + beer.name
TALK beer.description
END IF
```
### Example 5: Travel Information Bot
```basic
TALK "Which country would you like to know about?"
HEAR country AS NAME
country_url = "https://restcountries.com/v3.1/name/" + country
country_data = GET country_url
IF country_data AND UBOUND(country_data) > 0 THEN
info = country_data[0]
TALK "🌍 " + info.name.common
TALK "Capital: " + info.capital[0]
TALK "Population: " + info.population
TALK "Region: " + info.region
TALK "Languages: " + JOIN(info.languages)
TALK "Currency: " + JOIN(info.currencies)
REM Get public holidays
holidays_url = "https://date.nager.at/api/v3/PublicHolidays/2024/" + info.cca2
holidays = GET holidays_url
TALK ""
TALK "🎉 Upcoming Holidays:"
FOR EACH holiday IN holidays
TALK "• " + holiday.date + " - " + holiday.name
END FOR
END IF
```
## 📚 API Sources
All APIs in this package are from the [public-apis](https://github.com/public-apis/public-apis) repository and require no authentication.
### Categories Covered:
- ☁️ Weather & Environment
- 🐾 Animals & Pets
- 😄 Entertainment & Humor
- 🍽️ Food & Drink
- 🌍 Geography & Location
- 📊 Data & Utilities
- 💱 Currency & Finance
- 🎲 Random Generators
- 📚 Facts & Trivia
## ⚠️ Important Notes
1. **No API Keys Required**: All keywords use free, no-auth APIs
2. **Rate Limits**: Some APIs may have rate limits on free tier
3. **Availability**: APIs are third-party services and availability may vary
4. **Production Use**: For production apps, consider APIs with authentication for better reliability
5. **Terms of Service**: Always respect the terms of service of each API
## 🔧 Customization
You can easily extend these keywords or create your own:
```basic
REM Template for new API keyword
PARAM your_param AS string LIKE "example"
DESCRIPTION "What your keyword does"
api_url = "https://api.example.com/endpoint?param=" + your_param
data = GET api_url
IF data THEN
TALK "Success!"
TALK data.result
RETURN data
ELSE
TALK "❌ Error fetching data"
RETURN NULL
END IF
```
## 🤝 Contributing
To add more API keywords:
1. Find a free, no-auth API from [public-apis](https://github.com/public-apis/public-apis)
2. Create a `.bas` or `.bas` file in the appropriate category
3. Follow the existing keyword pattern
4. Test thoroughly
5. Update this README
## 📄 License
This template follows the General Bots license. Individual APIs have their own terms of service.
## 🌟 Credits
- [public-apis](https://github.com/public-apis/public-apis) - Comprehensive list of public APIs
- [7Timer!](http://www.7timer.info/) - Weather forecasting
- [Open-Meteo](https://open-meteo.com/) - Weather API
- [TheMealDB](https://www.themealdb.com/) - Meal recipes
- [TheCocktailDB](https://www.thecocktaildb.com/) - Cocktail recipes
- And many more amazing free API providers!
---
**General Bots**: Your Prompt Engineering Gets Done. 🤖

View file

@ -0,0 +1,366 @@
REM General Bots: Animals & Pets APIs - Free Animal Data Integration
REM Based on public-apis list - No authentication required
REM ============================================
REM ANIMAL KEYWORD - Random Cat Fact
REM ============================================
DESCRIPTION "Get a random cat fact"
cat_fact = GET "https://catfact.ninja/fact"
TALK "🐱 Random Cat Fact:"
TALK cat_fact.fact
RETURN cat_fact.fact
REM ============================================
REM ANIMAL KEYWORD - Random Dog Fact
REM ============================================
DESCRIPTION "Get a random dog fact"
dog_fact = GET "https://dogapi.dog/api/v2/facts"
IF dog_fact.data AND UBOUND(dog_fact.data) > 0 THEN
fact_text = dog_fact.data[0].attributes.body
TALK "🐶 Random Dog Fact:"
TALK fact_text
RETURN fact_text
ELSE
TALK "❌ Could not fetch dog fact"
RETURN NULL
END IF
REM ============================================
REM ANIMAL KEYWORD - Random Dog Image
REM ============================================
DESCRIPTION "Get a random dog image URL"
dog_image = GET "https://random.dog/woof.json"
image_url = dog_image.url
TALK "🐕 Random Dog Image:"
TALK image_url
file = DOWNLOAD image_url
SEND FILE file
RETURN image_url
REM ============================================
REM ANIMAL KEYWORD - Random Cat Image
REM ============================================
DESCRIPTION "Get a random cat image from Cataas"
cat_url = "https://cataas.com/cat"
TALK "🐈 Random Cat Image:"
TALK cat_url
file = DOWNLOAD cat_url
SEND FILE file
RETURN cat_url
REM ============================================
REM ANIMAL KEYWORD - Random Fox Image
REM ============================================
DESCRIPTION "Get a random fox image"
fox_data = GET "https://randomfox.ca/floof/"
image_url = fox_data.image
TALK "🦊 Random Fox Image:"
TALK image_url
file = DOWNLOAD image_url
SEND FILE file
RETURN image_url
REM ============================================
REM ANIMAL KEYWORD - Random Duck Image
REM ============================================
DESCRIPTION "Get a random duck image"
duck_url = "https://random-d.uk/api/random"
duck_data = GET duck_url
image_url = duck_data.url
message = duck_data.message
TALK "🦆 Random Duck Image:"
TALK message
TALK image_url
file = DOWNLOAD image_url
SEND FILE file
RETURN image_url
REM ============================================
REM ANIMAL KEYWORD - Random Shiba Inu Image
REM ============================================
DESCRIPTION "Get a random Shiba Inu dog image"
shiba_data = GET "https://shibe.online/api/shibes?count=1"
IF UBOUND(shiba_data) > 0 THEN
image_url = shiba_data[0]
TALK "🐕 Random Shiba Inu Image:"
TALK image_url
file = DOWNLOAD image_url
SEND FILE file
RETURN image_url
ELSE
TALK "❌ Could not fetch Shiba image"
RETURN NULL
END IF
REM ============================================
REM ANIMAL KEYWORD - HTTP Cat (HTTP Status Cats)
REM ============================================
PARAM status_code AS integer LIKE 404
DESCRIPTION "Get a cat image representing an HTTP status code"
cat_url = "https://http.cat/" + status_code
TALK "🐱 HTTP Cat for status " + status_code + ":"
TALK cat_url
file = DOWNLOAD cat_url
SEND FILE file
RETURN cat_url
REM ============================================
REM ANIMAL KEYWORD - HTTP Dog (HTTP Status Dogs)
REM ============================================
PARAM status_code AS integer LIKE 404
DESCRIPTION "Get a dog image representing an HTTP status code"
dog_url = "https://httpstatusdogs.com/img/" + status_code + ".jpg"
TALK "🐶 HTTP Dog for status " + status_code + ":"
TALK dog_url
file = DOWNLOAD dog_url
SEND FILE file
RETURN dog_url
REM ============================================
REM ANIMAL KEYWORD - PlaceBear Placeholder
REM ============================================
PARAM width AS integer LIKE 400
PARAM height AS integer LIKE 300
DESCRIPTION "Get a placeholder bear image of specified dimensions"
bear_url = "https://placebear.com/" + width + "/" + height
TALK "🐻 Bear Placeholder Image (" + width + "x" + height + "):"
TALK bear_url
file = DOWNLOAD bear_url
SEND FILE file
RETURN bear_url
REM ============================================
REM ANIMAL KEYWORD - PlaceDog Placeholder
REM ============================================
PARAM width AS integer LIKE 400
PARAM height AS integer LIKE 300
DESCRIPTION "Get a placeholder dog image of specified dimensions"
dog_url = "https://placedog.net/" + width + "/" + height
TALK "🐕 Dog Placeholder Image (" + width + "x" + height + "):"
TALK dog_url
file = DOWNLOAD dog_url
SEND FILE file
RETURN dog_url
REM ============================================
REM ANIMAL KEYWORD - PlaceKitten Placeholder
REM ============================================
PARAM width AS integer LIKE 400
PARAM height AS integer LIKE 300
DESCRIPTION "Get a placeholder kitten image of specified dimensions"
kitten_url = "https://placekitten.com/" + width + "/" + height
TALK "🐱 Kitten Placeholder Image (" + width + "x" + height + "):"
TALK kitten_url
file = DOWNLOAD kitten_url
SEND FILE file
RETURN kitten_url
REM ============================================
REM ANIMAL KEYWORD - MeowFacts
REM ============================================
PARAM count AS integer LIKE 1
DESCRIPTION "Get random cat facts (up to 100)"
facts_url = "https://meowfacts.herokuapp.com/?count=" + count
meow_data = GET facts_url
TALK "🐱 Random Cat Facts:"
FOR EACH fact IN meow_data.data
TALK "• " + fact
END FOR
RETURN meow_data.data
REM ============================================
REM ANIMAL KEYWORD - Random Axolotl
REM ============================================
DESCRIPTION "Get random axolotl picture and facts"
axolotl_data = GET "https://theaxolotlapi.netlify.app/.netlify/functions/axolotl"
image_url = axolotl_data.url
facts = axolotl_data.facts
TALK "🦎 Random Axolotl:"
TALK image_url
IF facts THEN
TALK ""
TALK "📚 Axolotl Facts:"
FOR EACH fact IN facts
TALK "• " + fact
END FOR
END IF
file = DOWNLOAD image_url
SEND FILE file
RETURN axolotl_data
REM ============================================
REM ANIMAL KEYWORD - Zoo Animals Info
REM ============================================
DESCRIPTION "Get information about various zoo animals"
zoo_data = GET "https://zoo-animal-api.herokuapp.com/animals/rand"
name = zoo_data.name
latin_name = zoo_data.latin_name
animal_type = zoo_data.animal_type
habitat = zoo_data.habitat
lifespan = zoo_data.lifespan
diet = zoo_data.diet
image_url = zoo_data.image_link
TALK "🦁 Random Zoo Animal: " + name
TALK "🔬 Latin Name: " + latin_name
TALK "📦 Type: " + animal_type
TALK "🏡 Habitat: " + habitat
TALK "⏳ Lifespan: " + lifespan
TALK "🍖 Diet: " + diet
TALK "📷 Image: " + image_url
IF image_url THEN
file = DOWNLOAD image_url
SEND FILE file
END IF
RETURN zoo_data
REM ============================================
REM ANIMAL KEYWORD - Multiple Random Dogs
REM ============================================
PARAM count AS integer LIKE 3
DESCRIPTION "Get multiple random dog images"
dog_url = "https://dog.ceo/api/breeds/image/random/" + count
dog_data = GET dog_url
IF dog_data.status = "success" THEN
TALK "🐕 " + count + " Random Dog Images:"
FOR EACH image IN dog_data.message
TALK image
file = DOWNLOAD image
SEND FILE file
WAIT 1
END FOR
RETURN dog_data.message
ELSE
TALK "❌ Could not fetch dog images"
RETURN NULL
END IF
REM ============================================
REM ANIMAL KEYWORD - Dog Breeds List
REM ============================================
DESCRIPTION "Get a list of all dog breeds"
breeds_url = "https://dog.ceo/api/breeds/list/all"
breeds_data = GET breeds_url
IF breeds_data.status = "success" THEN
breed_count = 0
breed_list = NEW ARRAY
TALK "🐕 Available Dog Breeds:"
FOR EACH breed IN breeds_data.message
breed_count = breed_count + 1
breed_list.PUSH(breed)
IF breed_count <= 20 THEN
TALK "• " + breed
END IF
END FOR
IF breed_count > 20 THEN
TALK "... and " + (breed_count - 20) + " more breeds"
END IF
RETURN breed_list
ELSE
TALK "❌ Could not fetch breed list"
RETURN NULL
END IF
REM ============================================
REM ANIMAL KEYWORD - Specific Dog Breed Image
REM ============================================
PARAM breed AS string LIKE "husky"
DESCRIPTION "Get a random image of a specific dog breed"
breed_url = "https://dog.ceo/api/breed/" + breed + "/images/random"
breed_data = GET breed_url
IF breed_data.status = "success" THEN
image_url = breed_data.message
TALK "🐕 Random " + breed + " image:"
TALK image_url
file = DOWNLOAD image_url
SEND FILE file
RETURN image_url
ELSE
TALK "❌ Breed not found: " + breed
TALK "Use 'Dog Breeds List' keyword to see available breeds"
RETURN NULL
END IF

View file

@ -0,0 +1,568 @@
REM General Bots: Data Utility & Geocoding APIs - Free Data Services
REM Based on public-apis list - No authentication required
REM ============================================
REM DATA KEYWORD - Generate UUID
REM ============================================
DESCRIPTION "Generate a random UUID v4"
uuid_data = GET "https://www.uuidgenerator.net/api/version4"
TALK "🔑 Generated UUID:"
TALK uuid_data
RETURN uuid_data
REM ============================================
REM DATA KEYWORD - Generate Multiple UUIDs
REM ============================================
PARAM count AS integer LIKE 5
DESCRIPTION "Generate multiple UUIDs"
TALK "🔑 Generated " + count + " UUIDs:"
uuids = NEW ARRAY
FOR i = 1 TO count
uuid = GET "https://www.uuidgenerator.net/api/version4"
uuids.PUSH(uuid)
TALK i + ". " + uuid
NEXT i
RETURN uuids
REM ============================================
REM DATA KEYWORD - Get My IP Address
REM ============================================
DESCRIPTION "Get your current public IP address"
ip_data = GET "https://api.ipify.org?format=json"
TALK "🌐 Your Public IP Address:"
TALK ip_data.ip
RETURN ip_data.ip
REM ============================================
REM DATA KEYWORD - Get IP Geolocation
REM ============================================
PARAM ip_address AS string LIKE "8.8.8.8"
DESCRIPTION "Get geolocation information for an IP address"
geo_url = "http://ip-api.com/json/" + ip_address
geo_data = GET geo_url
IF geo_data.status = "success" THEN
TALK "🌍 IP Geolocation for " + ip_address + ":"
TALK "📍 Country: " + geo_data.country + " (" + geo_data.countryCode + ")"
TALK "🏙️ City: " + geo_data.city
TALK "📮 ZIP Code: " + geo_data.zip
TALK "🗺️ Coordinates: " + geo_data.lat + ", " + geo_data.lon
TALK "⏰ Timezone: " + geo_data.timezone
TALK "🏢 ISP: " + geo_data.isp
TALK "🏛️ Organization: " + geo_data.org
RETURN geo_data
ELSE
TALK "❌ Could not get geolocation for IP: " + ip_address
RETURN NULL
END IF
REM ============================================
REM DATA KEYWORD - Check if Number is Even
REM ============================================
PARAM number AS integer LIKE 42
DESCRIPTION "Check if a number is even (humor API)"
even_data = GET "https://api.isevenapi.xyz/api/iseven/" + number
TALK "🔢 Is " + number + " even?"
TALK even_data.iseven
IF even_data.iseven = TRUE THEN
TALK "✅ Yes, " + number + " is even!"
ELSE
TALK "❌ No, " + number + " is odd!"
END IF
RETURN even_data.iseven
REM ============================================
REM DATA KEYWORD - Random Data Generator
REM ============================================
DESCRIPTION "Generate random test data (name, address, etc)"
random_data = GET "https://random-data-api.com/api/v2/users"
TALK "👤 Random User Data:"
TALK "Name: " + random_data.first_name + " " + random_data.last_name
TALK "Username: " + random_data.username
TALK "Email: " + random_data.email
TALK "Phone: " + random_data.phone_number
TALK "Date of Birth: " + random_data.date_of_birth
TALK "Address: " + random_data.address.street_address
TALK "City: " + random_data.address.city
TALK "State: " + random_data.address.state
TALK "Country: " + random_data.address.country
RETURN random_data
REM ============================================
REM DATA KEYWORD - Generate Lorem Ipsum
REM ============================================
PARAM paragraphs AS integer LIKE 3
DESCRIPTION "Generate Lorem Ipsum placeholder text"
lorem_url = "https://loripsum.net/api/" + paragraphs + "/medium/plaintext"
lorem_text = GET lorem_url
TALK "📝 Lorem Ipsum Text (" + paragraphs + " paragraphs):"
TALK lorem_text
RETURN lorem_text
REM ============================================
REM DATA KEYWORD - QR Code Generator
REM ============================================
PARAM text AS string LIKE "https://pragmatismo.com.br"
PARAM size AS integer LIKE 200
DESCRIPTION "Generate a QR code for any text or URL"
qr_url = "https://api.qrserver.com/v1/create-qr-code/?size=" + size + "x" + size + "&data=" + text
TALK "📱 QR Code generated for:"
TALK text
TALK ""
TALK "🔗 QR Code URL:"
TALK qr_url
file = DOWNLOAD qr_url
SEND FILE file
RETURN qr_url
REM ============================================
REM DATA KEYWORD - Barcode Generator
REM ============================================
PARAM barcode_data AS string LIKE "1234567890"
PARAM format AS "code128", "ean13", "upca", "code39"
DESCRIPTION "Generate a barcode image"
barcode_url = "https://barcodeapi.org/api/" + format + "/" + barcode_data
TALK "📊 Barcode generated:"
TALK "Format: " + format
TALK "Data: " + barcode_data
TALK ""
TALK "🔗 Barcode URL:"
TALK barcode_url
file = DOWNLOAD barcode_url
SEND FILE file
RETURN barcode_url
REM ============================================
REM DATA KEYWORD - Country Information
REM ============================================
PARAM country AS string LIKE "brazil"
DESCRIPTION "Get detailed information about a country"
country_url = "https://restcountries.com/v3.1/name/" + country
country_data = GET country_url
IF country_data AND UBOUND(country_data) > 0 THEN
info = country_data[0]
TALK "🌍 Country Information: " + info.name.common
TALK "🏛️ Official Name: " + info.name.official
TALK "🏳️ Capital: " + info.capital[0]
TALK "🗺️ Region: " + info.region + " (" + info.subregion + ")"
TALK "👥 Population: " + info.population
TALK "📏 Area: " + info.area + " km²"
TALK "🌐 Languages: " + JOIN(info.languages)
TALK "💰 Currencies: " + JOIN(info.currencies)
TALK "⏰ Timezones: " + JOIN(info.timezones)
TALK "🚗 Drives on: " + info.car.side
TALK "🌐 Top Level Domain: " + info.tld[0]
IF info.flags.png THEN
TALK ""
TALK "🏴 Flag:"
file = DOWNLOAD info.flags.png
SEND FILE file
END IF
RETURN info
ELSE
TALK "❌ Country not found: " + country
RETURN NULL
END IF
REM ============================================
REM DATA KEYWORD - All Countries List
REM ============================================
DESCRIPTION "Get a list of all countries"
countries = GET "https://restcountries.com/v3.1/all"
TALK "🌍 Total Countries: " + UBOUND(countries)
TALK ""
TALK "First 20 countries:"
counter = 0
FOR EACH country IN countries
IF counter < 20 THEN
TALK "• " + country.name.common + " (" + country.cca2 + ")"
END IF
counter = counter + 1
END FOR
IF counter > 20 THEN
TALK "... and " + (counter - 20) + " more countries"
END IF
RETURN countries
REM ============================================
REM DATA KEYWORD - Countries by Region
REM ============================================
PARAM region AS "africa", "americas", "asia", "europe", "oceania"
DESCRIPTION "Get countries from a specific region"
region_url = "https://restcountries.com/v3.1/region/" + region
countries = GET region_url
TALK "🌍 Countries in " + region + ":"
TALK "Total: " + UBOUND(countries)
TALK ""
FOR EACH country IN countries
TALK "• " + country.name.common + " - Capital: " + country.capital[0]
END FOR
RETURN countries
REM ============================================
REM DATA KEYWORD - Currency Converter
REM ============================================
PARAM amount AS number LIKE 100
PARAM from_currency AS string LIKE "USD"
PARAM to_currency AS string LIKE "EUR"
DESCRIPTION "Convert currency amounts (Note: Free tier available)"
exchange_url = "https://api.exchangerate-api.com/v4/latest/" + from_currency
exchange_data = GET exchange_url
IF exchange_data.rates THEN
rate = exchange_data.rates[to_currency]
converted = amount * rate
TALK "💱 Currency Conversion:"
TALK amount + " " + from_currency + " = " + converted + " " + to_currency
TALK "Exchange Rate: 1 " + from_currency + " = " + rate + " " + to_currency
TALK "Updated: " + exchange_data.date
result = NEW OBJECT
result.amount = amount
result.from = from_currency
result.to = to_currency
result.rate = rate
result.converted = converted
RETURN result
ELSE
TALK "❌ Could not fetch exchange rates"
RETURN NULL
END IF
REM ============================================
REM DATA KEYWORD - Timezone Info
REM ============================================
PARAM timezone AS string LIKE "America/New_York"
DESCRIPTION "Get current time in a specific timezone"
time_url = "http://worldtimeapi.org/api/timezone/" + timezone
time_data = GET time_url
IF time_data.datetime THEN
TALK "⏰ Current Time in " + timezone + ":"
TALK "🕐 DateTime: " + time_data.datetime
TALK "📅 Date: " + time_data.date
TALK "⏲️ Time: " + time_data.time
TALK "🌍 UTC Offset: " + time_data.utc_offset
TALK "📆 Day of Week: " + time_data.day_of_week
TALK "📆 Day of Year: " + time_data.day_of_year
TALK "📆 Week Number: " + time_data.week_number
RETURN time_data
ELSE
TALK "❌ Could not fetch timezone data for: " + timezone
RETURN NULL
END IF
REM ============================================
REM DATA KEYWORD - All Timezones List
REM ============================================
DESCRIPTION "Get a list of all available timezones"
timezones = GET "http://worldtimeapi.org/api/timezone"
TALK "🌍 Available Timezones (" + UBOUND(timezones) + " total):"
TALK ""
counter = 0
FOR EACH tz IN timezones
IF counter < 30 THEN
TALK "• " + tz
END IF
counter = counter + 1
END FOR
IF counter > 30 THEN
TALK "... and " + (counter - 30) + " more timezones"
END IF
RETURN timezones
REM ============================================
REM DATA KEYWORD - Public Holidays
REM ============================================
PARAM country_code AS string LIKE "US"
PARAM year AS integer LIKE 2024
DESCRIPTION "Get public holidays for a country and year"
holidays_url = "https://date.nager.at/api/v3/PublicHolidays/" + year + "/" + country_code
holidays = GET holidays_url
IF holidays THEN
TALK "🎉 Public Holidays in " + country_code + " for " + year + ":"
TALK "Total: " + UBOUND(holidays)
TALK ""
FOR EACH holiday IN holidays
TALK "📅 " + holiday.date + " - " + holiday.name
IF holiday.localName <> holiday.name THEN
TALK " (" + holiday.localName + ")"
END IF
END FOR
RETURN holidays
ELSE
TALK "❌ Could not fetch holidays for: " + country_code
RETURN NULL
END IF
REM ============================================
REM DATA KEYWORD - Number Facts
REM ============================================
PARAM number AS integer LIKE 42
DESCRIPTION "Get an interesting fact about a number"
fact_url = "http://numbersapi.com/" + number
number_fact = GET fact_url
TALK "🔢 Fact about " + number + ":"
TALK number_fact
RETURN number_fact
REM ============================================
REM DATA KEYWORD - Random Number Fact
REM ============================================
DESCRIPTION "Get a random number fact"
random_fact = GET "http://numbersapi.com/random"
TALK "🔢 Random Number Fact:"
TALK random_fact
RETURN random_fact
REM ============================================
REM DATA KEYWORD - Date Facts
REM ============================================
PARAM month AS integer LIKE 3
PARAM day AS integer LIKE 14
DESCRIPTION "Get interesting facts about a specific date"
date_url = "http://numbersapi.com/" + month + "/" + day + "/date"
date_fact = GET date_url
TALK "📅 Fact about " + month + "/" + day + ":"
TALK date_fact
RETURN date_fact
REM ============================================
REM DATA KEYWORD - Math Fact
REM ============================================
PARAM number AS integer LIKE 1729
DESCRIPTION "Get a mathematical fact about a number"
math_url = "http://numbersapi.com/" + number + "/math"
math_fact = GET math_url
TALK "🧮 Math Fact about " + number + ":"
TALK math_fact
RETURN math_fact
REM ============================================
REM DATA KEYWORD - Yes or No Decision
REM ============================================
DESCRIPTION "Get a random Yes or No answer"
decision = GET "https://yesno.wtf/api"
answer = decision.answer
image = decision.image
TALK "🎲 Random Decision:"
TALK UCASE(answer) + "!"
file = DOWNLOAD image
SEND FILE file
RETURN decision
REM ============================================
REM DATA KEYWORD - Postcode Lookup UK
REM ============================================
PARAM postcode AS string LIKE "SW1A1AA"
DESCRIPTION "Look up UK postcode information"
postcode_clean = REPLACE(postcode, " ", "")
postcode_url = "https://api.postcodes.io/postcodes/" + postcode_clean
postcode_data = GET postcode_url
IF postcode_data.status = 200 THEN
result = postcode_data.result
TALK "📮 UK Postcode Information:"
TALK "Postcode: " + result.postcode
TALK "🏙️ Region: " + result.region
TALK "🗺️ District: " + result.admin_district
TALK "📍 Coordinates: " + result.latitude + ", " + result.longitude
TALK "🏛️ Parliamentary Constituency: " + result.parliamentary_constituency
TALK "🌍 Country: " + result.country
RETURN result
ELSE
TALK "❌ Invalid postcode: " + postcode
RETURN NULL
END IF
REM ============================================
REM DATA KEYWORD - Brazilian CEP Lookup
REM ============================================
PARAM cep AS string LIKE "01310-100"
DESCRIPTION "Look up Brazilian postal code (CEP) information"
cep_clean = REPLACE(cep, "-", "")
cep_url = "https://viacep.com.br/ws/" + cep_clean + "/json/"
cep_data = GET cep_url
IF NOT cep_data.erro THEN
TALK "📮 CEP Information:"
TALK "CEP: " + cep_data.cep
TALK "🏙️ City: " + cep_data.localidade + " - " + cep_data.uf
TALK "🏘️ Neighborhood: " + cep_data.bairro
TALK "🛣️ Street: " + cep_data.logradouro
TALK "🗺️ Region: " + cep_data.regiao
TALK "☎️ DDD: " + cep_data.ddd
RETURN cep_data
ELSE
TALK "❌ Invalid CEP: " + cep
RETURN NULL
END IF
REM ============================================
REM DATA KEYWORD - JSON Placeholder Post
REM ============================================
DESCRIPTION "Get sample post data for testing"
post = GET "https://jsonplaceholder.typicode.com/posts/1"
TALK "📝 Sample Post Data:"
TALK "Title: " + post.title
TALK "User ID: " + post.userId
TALK "Post ID: " + post.id
TALK ""
TALK "Body:"
TALK post.body
RETURN post
REM ============================================
REM DATA KEYWORD - Random User Generator
REM ============================================
DESCRIPTION "Generate a random user with realistic data"
user_data = GET "https://randomuser.me/api/"
IF user_data.results AND UBOUND(user_data.results) > 0 THEN
user = user_data.results[0]
TALK "👤 Random User Generated:"
TALK "Name: " + user.name.first + " " + user.name.last
TALK "Gender: " + user.gender
TALK "📧 Email: " + user.email
TALK "📱 Phone: " + user.phone
TALK "🎂 Date of Birth: " + user.dob.date
TALK "📍 Location: " + user.location.city + ", " + user.location.state + ", " + user.location.country
TALK "📮 Postcode: " + user.location.postcode
TALK "🌐 Nationality: " + user.nat
TALK ""
TALK "📷 Picture: " + user.picture.large
file = DOWNLOAD user.picture.large
SEND FILE file
RETURN user
ELSE
TALK "❌ Could not generate random user"
RETURN NULL
END IF
REM ============================================
REM DATA KEYWORD - Multiple Random Users
REM ============================================
PARAM count AS integer LIKE 5
DESCRIPTION "Generate multiple random users"
users_url = "https://randomuser.me/api/?results=" + count
users_data = GET users_url
IF users_data.results THEN
TALK "👥 Generated " + count + " Random Users:"
TALK ""
counter = 1
FOR EACH user IN users_data.results
TALK counter + ". " + user.name.first + " " + user.name.last
TALK " Email: " + user.email
TALK " Location: " + user.location.city + ", " + user.location.country
TALK ""
counter = counter + 1
END FOR
RETURN users_data.results
ELSE
TALK "❌ Could not generate random users"
RETURN NULL
END IF

View file

@ -0,0 +1,438 @@
REM General Bots: Entertainment APIs - Jokes, Quotes, and Fun Content
REM Based on public-apis list - No authentication required
REM ============================================
REM ENTERTAINMENT KEYWORD - Chuck Norris Joke
REM ============================================
DESCRIPTION "Get a random Chuck Norris joke"
chuck_joke = GET "https://api.chucknorris.io/jokes/random"
TALK "😄 Chuck Norris Joke:"
TALK chuck_joke.value
RETURN chuck_joke.value
REM ============================================
REM ENTERTAINMENT KEYWORD - Chuck Norris Categories
REM ============================================
DESCRIPTION "Get available Chuck Norris joke categories"
categories = GET "https://api.chucknorris.io/jokes/categories"
TALK "📋 Chuck Norris Joke Categories:"
FOR EACH category IN categories
TALK "• " + category
END FOR
RETURN categories
REM ============================================
REM ENTERTAINMENT KEYWORD - Chuck Norris Joke by Category
REM ============================================
PARAM category AS string LIKE "dev"
DESCRIPTION "Get a random Chuck Norris joke from a specific category"
joke_url = "https://api.chucknorris.io/jokes/random?category=" + category
chuck_joke = GET joke_url
TALK "😄 Chuck Norris " + category + " Joke:"
TALK chuck_joke.value
RETURN chuck_joke.value
REM ============================================
REM ENTERTAINMENT KEYWORD - Dad Joke
REM ============================================
DESCRIPTION "Get a random dad joke from icanhazdadjoke"
SET HEADER "Accept" = "application/json"
dad_joke = GET "https://icanhazdadjoke.com/"
TALK "👨 Dad Joke:"
TALK dad_joke.joke
RETURN dad_joke.joke
REM ============================================
REM ENTERTAINMENT KEYWORD - Search Dad Jokes
REM ============================================
PARAM search_term AS string LIKE "cat"
DESCRIPTION "Search for dad jokes containing a specific term"
SET HEADER "Accept" = "application/json"
search_url = "https://icanhazdadjoke.com/search?term=" + search_term
results = GET search_url
TALK "🔍 Found " + results.total_jokes + " dad jokes about '" + search_term + "':"
counter = 0
FOR EACH joke IN results.results
IF counter < 5 THEN
TALK ""
TALK "😄 " + joke.joke
END IF
counter = counter + 1
END FOR
IF results.total_jokes > 5 THEN
TALK ""
TALK "... and " + (results.total_jokes - 5) + " more jokes!"
END IF
RETURN results.results
REM ============================================
REM ENTERTAINMENT KEYWORD - Bored Activity
REM ============================================
DESCRIPTION "Get a random activity suggestion when bored"
activity = GET "https://www.boredapi.com/api/activity"
TALK "💡 Activity Suggestion:"
TALK activity.activity
TALK ""
TALK "📊 Type: " + activity.type
TALK "👥 Participants: " + activity.participants
TALK "💰 Price: " + activity.price
IF activity.link THEN
TALK "🔗 Link: " + activity.link
END IF
RETURN activity
REM ============================================
REM ENTERTAINMENT KEYWORD - Bored Activity by Type
REM ============================================
PARAM activity_type AS "education", "recreational", "social", "diy", "charity", "cooking", "relaxation", "music", "busywork"
DESCRIPTION "Get a random activity suggestion of a specific type"
activity_url = "https://www.boredapi.com/api/activity?type=" + activity_type
activity = GET activity_url
TALK "💡 " + activity_type + " Activity Suggestion:"
TALK activity.activity
TALK ""
TALK "👥 Participants: " + activity.participants
TALK "💰 Price level: " + activity.price
RETURN activity
REM ============================================
REM ENTERTAINMENT KEYWORD - Random Useless Fact
REM ============================================
DESCRIPTION "Get a random useless but true fact"
fact = GET "https://uselessfacts.jsph.pl/random.json?language=en"
TALK "🤓 Random Useless Fact:"
TALK fact.text
RETURN fact.text
REM ============================================
REM ENTERTAINMENT KEYWORD - Random Fun Fact
REM ============================================
DESCRIPTION "Get a random fun fact"
fun_fact = GET "https://uselessfacts.jsph.pl/api/v2/facts/random"
TALK "🎉 Random Fun Fact:"
TALK fun_fact.text
RETURN fun_fact.text
REM ============================================
REM ENTERTAINMENT KEYWORD - Kanye West Quote
REM ============================================
DESCRIPTION "Get a random Kanye West quote"
kanye = GET "https://api.kanye.rest/"
TALK "🎤 Kanye West says:"
TALK '"' + kanye.quote + '"'
RETURN kanye.quote
REM ============================================
REM ENTERTAINMENT KEYWORD - Advice Slip
REM ============================================
DESCRIPTION "Get a random piece of advice"
advice = GET "https://api.adviceslip.com/advice"
TALK "💭 Random Advice:"
TALK advice.slip.advice
RETURN advice.slip.advice
REM ============================================
REM ENTERTAINMENT KEYWORD - Search Advice
REM ============================================
PARAM query AS string LIKE "love"
DESCRIPTION "Search for advice containing a specific word"
search_url = "https://api.adviceslip.com/advice/search/" + query
results = GET search_url
IF results.total_results > 0 THEN
TALK "💭 Found " + results.total_results + " advice about '" + query + "':"
counter = 0
FOR EACH slip IN results.slips
IF counter < 5 THEN
TALK ""
TALK "• " + slip.advice
END IF
counter = counter + 1
END FOR
IF results.total_results > 5 THEN
TALK ""
TALK "... and " + (results.total_results - 5) + " more pieces of advice!"
END IF
RETURN results.slips
ELSE
TALK "❌ No advice found for: " + query
RETURN NULL
END IF
REM ============================================
REM ENTERTAINMENT KEYWORD - Corporate Buzzword
REM ============================================
DESCRIPTION "Get random corporate buzzwords"
buzzword = GET "https://corporatebs-generator.sameerkumar.website/"
TALK "💼 Corporate Buzzword Generator:"
TALK buzzword.phrase
RETURN buzzword.phrase
REM ============================================
REM ENTERTAINMENT KEYWORD - Yo Momma Joke
REM ============================================
DESCRIPTION "Get a random Yo Momma joke"
joke = GET "https://api.yomomma.info/"
TALK "😂 Yo Momma Joke:"
TALK joke.joke
RETURN joke.joke
REM ============================================
REM ENTERTAINMENT KEYWORD - Random Quote
REM ============================================
DESCRIPTION "Get a random inspirational quote"
quote_data = GET "https://api.quotable.io/random"
quote_text = quote_data.content
author = quote_data.author
TALK "✨ Inspirational Quote:"
TALK '"' + quote_text + '"'
TALK "— " + author
RETURN quote_data
REM ============================================
REM ENTERTAINMENT KEYWORD - Quote by Author
REM ============================================
PARAM author AS string LIKE "einstein"
DESCRIPTION "Get a random quote by a specific author"
quote_url = "https://api.quotable.io/random?author=" + author
quote_data = GET quote_url
IF quote_data.content THEN
TALK "✨ Quote by " + quote_data.author + ":"
TALK '"' + quote_data.content + '"'
RETURN quote_data
ELSE
TALK "❌ No quotes found for author: " + author
RETURN NULL
END IF
REM ============================================
REM ENTERTAINMENT KEYWORD - Quote of the Day
REM ============================================
DESCRIPTION "Get the quote of the day"
qotd = GET "https://api.quotable.io/quotes/random?tags=inspirational"
IF UBOUND(qotd) > 0 THEN
quote = qotd[0]
TALK "🌟 Quote of the Day:"
TALK '"' + quote.content + '"'
TALK "— " + quote.author
RETURN quote
ELSE
TALK "❌ Could not fetch quote of the day"
RETURN NULL
END IF
REM ============================================
REM ENTERTAINMENT KEYWORD - Programming Quote
REM ============================================
DESCRIPTION "Get a random programming quote"
quote = GET "https://programming-quotes-api.herokuapp.com/quotes/random"
TALK "💻 Programming Quote:"
TALK '"' + quote.en + '"'
TALK "— " + quote.author
RETURN quote
REM ============================================
REM ENTERTAINMENT KEYWORD - Zen Quote
REM ============================================
DESCRIPTION "Get a random Zen/Stoicism quote"
quote = GET "https://zenquotes.io/api/random"
IF UBOUND(quote) > 0 THEN
zen_quote = quote[0]
TALK "🧘 Zen Quote:"
TALK '"' + zen_quote.q + '"'
TALK "— " + zen_quote.a
RETURN zen_quote
ELSE
TALK "❌ Could not fetch Zen quote"
RETURN NULL
END IF
REM ============================================
REM ENTERTAINMENT KEYWORD - Affirmation
REM ============================================
DESCRIPTION "Get a random positive affirmation"
affirmation = GET "https://www.affirmations.dev/"
TALK "💖 Daily Affirmation:"
TALK affirmation.affirmation
RETURN affirmation.affirmation
REM ============================================
REM ENTERTAINMENT KEYWORD - Random Trivia
REM ============================================
DESCRIPTION "Get a random trivia question"
trivia = GET "https://opentdb.com/api.php?amount=1"
IF trivia.results AND UBOUND(trivia.results) > 0 THEN
question = trivia.results[0]
TALK "🎯 Trivia Question:"
TALK "Category: " + question.category
TALK "Difficulty: " + question.difficulty
TALK ""
TALK question.question
TALK ""
TALK "Correct Answer: " + question.correct_answer
IF question.incorrect_answers THEN
TALK ""
TALK "Other Options:"
FOR EACH wrong IN question.incorrect_answers
TALK "• " + wrong
END FOR
END IF
RETURN question
ELSE
TALK "❌ Could not fetch trivia question"
RETURN NULL
END IF
REM ============================================
REM ENTERTAINMENT KEYWORD - Multiple Trivia Questions
REM ============================================
PARAM amount AS integer LIKE 5
DESCRIPTION "Get multiple trivia questions"
trivia_url = "https://opentdb.com/api.php?amount=" + amount
trivia = GET trivia_url
IF trivia.results THEN
TALK "🎯 " + amount + " Trivia Questions:"
TALK ""
counter = 1
FOR EACH question IN trivia.results
TALK counter + ". " + question.question
TALK " Category: " + question.category + " | Difficulty: " + question.difficulty
TALK " Answer: " + question.correct_answer
TALK ""
counter = counter + 1
END FOR
RETURN trivia.results
ELSE
TALK "❌ Could not fetch trivia questions"
RETURN NULL
END IF
REM ============================================
REM ENTERTAINMENT KEYWORD - Excuse Generator
REM ============================================
DESCRIPTION "Get a random excuse"
excuse = GET "https://excuser-three.vercel.app/v1/excuse"
IF excuse AND UBOUND(excuse) > 0 THEN
excuse_obj = excuse[0]
TALK "🤷 Random Excuse:"
TALK excuse_obj.excuse
TALK ""
TALK "Category: " + excuse_obj.category
RETURN excuse_obj
ELSE
TALK "❌ Could not generate excuse"
RETURN NULL
END IF
REM ============================================
REM ENTERTAINMENT KEYWORD - Insult Generator
REM ============================================
DESCRIPTION "Get a random insult (clean)"
insult = GET "https://evilinsult.com/generate_insult.php?lang=en&type=json"
TALK "😈 Random Insult:"
TALK insult.insult
RETURN insult.insult
REM ============================================
REM ENTERTAINMENT KEYWORD - Compliment Generator
REM ============================================
DESCRIPTION "Get a random compliment"
compliment = GET "https://complimentr.com/api"
TALK "💝 Random Compliment:"
TALK compliment.compliment
RETURN compliment.compliment

View file

@ -0,0 +1,503 @@
REM General Bots: Food & Drink APIs - Free Food Data Integration
REM Based on public-apis list - No authentication required
REM ============================================
REM FOOD KEYWORD - Random Coffee Image
REM ============================================
DESCRIPTION "Get a random coffee image"
coffee_data = GET "https://coffee.alexflipnote.dev/random.json"
image_url = coffee_data.file
TALK "☕ Random Coffee Image:"
TALK image_url
file = DOWNLOAD image_url
SEND FILE file
RETURN image_url
REM ============================================
REM FOOD KEYWORD - Random Food Dish
REM ============================================
DESCRIPTION "Get a random food dish image from Foodish"
food_data = GET "https://foodish-api.herokuapp.com/api/"
image_url = food_data.image
TALK "🍽️ Random Food Dish:"
TALK image_url
file = DOWNLOAD image_url
SEND FILE file
RETURN image_url
REM ============================================
REM FOOD KEYWORD - Random Food by Category
REM ============================================
PARAM category AS "biryani", "burger", "butter-chicken", "dessert", "dosa", "idly", "pasta", "pizza", "rice", "samosa"
DESCRIPTION "Get a random food image from a specific category"
food_url = "https://foodish-api.herokuapp.com/api/images/" + category
food_data = GET food_url
image_url = food_data.image
TALK "🍽️ Random " + category + ":"
TALK image_url
file = DOWNLOAD image_url
SEND FILE file
RETURN image_url
REM ============================================
REM FOOD KEYWORD - Random Meal Recipe
REM ============================================
DESCRIPTION "Get a random meal recipe from TheMealDB"
meal_data = GET "https://www.themealdb.com/api/json/v1/1/random.php"
IF meal_data.meals AND UBOUND(meal_data.meals) > 0 THEN
meal = meal_data.meals[0]
TALK "🍳 Random Meal Recipe: " + meal.strMeal
TALK "🌍 Category: " + meal.strCategory + " | Area: " + meal.strArea
TALK ""
TALK "📝 Instructions:"
TALK meal.strInstructions
TALK ""
TALK "📷 Image: " + meal.strMealThumb
IF meal.strYoutube THEN
TALK "🎥 Video: " + meal.strYoutube
END IF
TALK ""
TALK "🥘 Ingredients:"
REM Extract ingredients
FOR i = 1 TO 20
ingredient = meal["strIngredient" + i]
measure = meal["strMeasure" + i]
IF ingredient <> "" AND ingredient <> NULL THEN
TALK "• " + measure + " " + ingredient
END IF
NEXT i
file = DOWNLOAD meal.strMealThumb
SEND FILE file
RETURN meal
ELSE
TALK "❌ Could not fetch meal recipe"
RETURN NULL
END IF
REM ============================================
REM FOOD KEYWORD - Search Meal by Name
REM ============================================
PARAM meal_name AS string LIKE "chicken"
DESCRIPTION "Search for meals by name"
search_url = "https://www.themealdb.com/api/json/v1/1/search.php?s=" + meal_name
meal_data = GET search_url
IF meal_data.meals THEN
TALK "🔍 Found meals matching '" + meal_name + "':"
TALK ""
counter = 0
FOR EACH meal IN meal_data.meals
IF counter < 5 THEN
TALK "🍽️ " + meal.strMeal
TALK " Category: " + meal.strCategory + " | Area: " + meal.strArea
TALK " ID: " + meal.idMeal
TALK ""
END IF
counter = counter + 1
END FOR
IF counter > 5 THEN
TALK "... and " + (counter - 5) + " more meals"
END IF
RETURN meal_data.meals
ELSE
TALK "❌ No meals found for: " + meal_name
RETURN NULL
END IF
REM ============================================
REM FOOD KEYWORD - Random Cocktail Recipe
REM ============================================
DESCRIPTION "Get a random cocktail recipe from TheCocktailDB"
cocktail_data = GET "https://www.thecocktaildb.com/api/json/v1/1/random.php"
IF cocktail_data.drinks AND UBOUND(cocktail_data.drinks) > 0 THEN
drink = cocktail_data.drinks[0]
TALK "🍹 Random Cocktail: " + drink.strDrink
TALK "🏷️ Category: " + drink.strCategory
TALK "🥃 Glass: " + drink.strGlass
TALK ""
TALK "📝 Instructions:"
TALK drink.strInstructions
TALK ""
TALK "🍸 Ingredients:"
REM Extract ingredients
FOR i = 1 TO 15
ingredient = drink["strIngredient" + i]
measure = drink["strMeasure" + i]
IF ingredient <> "" AND ingredient <> NULL THEN
IF measure <> "" AND measure <> NULL THEN
TALK "• " + measure + " " + ingredient
ELSE
TALK "• " + ingredient
END IF
END IF
NEXT i
TALK ""
TALK "📷 Image: " + drink.strDrinkThumb
file = DOWNLOAD drink.strDrinkThumb
SEND FILE file
RETURN drink
ELSE
TALK "❌ Could not fetch cocktail recipe"
RETURN NULL
END IF
REM ============================================
REM FOOD KEYWORD - Search Cocktail by Name
REM ============================================
PARAM cocktail_name AS string LIKE "margarita"
DESCRIPTION "Search for cocktails by name"
search_url = "https://www.thecocktaildb.com/api/json/v1/1/search.php?s=" + cocktail_name
cocktail_data = GET search_url
IF cocktail_data.drinks THEN
TALK "🔍 Found cocktails matching '" + cocktail_name + "':"
TALK ""
FOR EACH drink IN cocktail_data.drinks
TALK "🍹 " + drink.strDrink
TALK " Category: " + drink.strCategory + " | Glass: " + drink.strGlass
TALK " Alcoholic: " + drink.strAlcoholic
TALK ""
END FOR
RETURN cocktail_data.drinks
ELSE
TALK "❌ No cocktails found for: " + cocktail_name
RETURN NULL
END IF
REM ============================================
REM FOOD KEYWORD - Search Cocktail by Ingredient
REM ============================================
PARAM ingredient AS string LIKE "vodka"
DESCRIPTION "Search for cocktails by ingredient"
search_url = "https://www.thecocktaildb.com/api/json/v1/1/filter.php?i=" + ingredient
cocktail_data = GET search_url
IF cocktail_data.drinks THEN
TALK "🔍 Found " + UBOUND(cocktail_data.drinks) + " cocktails with " + ingredient + ":"
TALK ""
counter = 0
FOR EACH drink IN cocktail_data.drinks
IF counter < 10 THEN
TALK "🍹 " + drink.strDrink + " (ID: " + drink.idDrink + ")"
END IF
counter = counter + 1
END FOR
IF counter > 10 THEN
TALK "... and " + (counter - 10) + " more cocktails"
END IF
RETURN cocktail_data.drinks
ELSE
TALK "❌ No cocktails found with ingredient: " + ingredient
RETURN NULL
END IF
REM ============================================
REM FOOD KEYWORD - Fruit Information
REM ============================================
PARAM fruit_name AS string LIKE "apple"
DESCRIPTION "Get nutritional information about a fruit"
fruit_url = "https://fruityvice.com/api/fruit/" + fruit_name
fruit_data = GET fruit_url
IF fruit_data.name THEN
TALK "🍎 Fruit Information: " + fruit_data.name
TALK "🏷️ Family: " + fruit_data.family
TALK "🌳 Genus: " + fruit_data.genus
TALK "🆔 ID: " + fruit_data.id
TALK ""
TALK "📊 Nutritional Information (per 100g):"
TALK "• Calories: " + fruit_data.nutritions.calories
TALK "• Carbohydrates: " + fruit_data.nutritions.carbohydrates + "g"
TALK "• Protein: " + fruit_data.nutritions.protein + "g"
TALK "• Fat: " + fruit_data.nutritions.fat + "g"
TALK "• Sugar: " + fruit_data.nutritions.sugar + "g"
RETURN fruit_data
ELSE
TALK "❌ Fruit not found: " + fruit_name
RETURN NULL
END IF
REM ============================================
REM FOOD KEYWORD - All Fruits List
REM ============================================
DESCRIPTION "Get a list of all available fruits"
fruits_data = GET "https://fruityvice.com/api/fruit/all"
IF fruits_data THEN
TALK "🍓 Available Fruits (" + UBOUND(fruits_data) + " total):"
TALK ""
counter = 0
FOR EACH fruit IN fruits_data
IF counter < 20 THEN
TALK "• " + fruit.name + " (" + fruit.family + ")"
END IF
counter = counter + 1
END FOR
IF counter > 20 THEN
TALK "... and " + (counter - 20) + " more fruits"
END IF
RETURN fruits_data
ELSE
TALK "❌ Could not fetch fruits list"
RETURN NULL
END IF
REM ============================================
REM FOOD KEYWORD - Fruits by Family
REM ============================================
PARAM family AS string LIKE "Rosaceae"
DESCRIPTION "Get fruits from a specific family"
family_url = "https://fruityvice.com/api/fruit/family/" + family
fruits_data = GET family_url
IF fruits_data THEN
TALK "🍎 Fruits from " + family + " family:"
TALK ""
FOR EACH fruit IN fruits_data
TALK "• " + fruit.name + " (Genus: " + fruit.genus + ")"
END FOR
RETURN fruits_data
ELSE
TALK "❌ No fruits found for family: " + family
RETURN NULL
END IF
REM ============================================
REM FOOD KEYWORD - Random Taco Recipe
REM ============================================
DESCRIPTION "Get a random taco recipe from TacoFancy"
taco_data = GET "http://taco-randomizer.herokuapp.com/random/"
IF taco_data THEN
TALK "🌮 Random Taco Recipe:"
TALK ""
IF taco_data.base_layer THEN
TALK "🫓 Base Layer: " + taco_data.base_layer.name
TALK taco_data.base_layer.recipe
TALK ""
END IF
IF taco_data.mixin THEN
TALK "🥗 Mixin: " + taco_data.mixin.name
TALK taco_data.mixin.recipe
TALK ""
END IF
IF taco_data.condiment THEN
TALK "🧂 Condiment: " + taco_data.condiment.name
TALK taco_data.condiment.recipe
TALK ""
END IF
IF taco_data.seasoning THEN
TALK "🌶️ Seasoning: " + taco_data.seasoning.name
TALK taco_data.seasoning.recipe
TALK ""
END IF
IF taco_data.shell THEN
TALK "🌮 Shell: " + taco_data.shell.name
TALK taco_data.shell.recipe
END IF
RETURN taco_data
ELSE
TALK "❌ Could not fetch taco recipe"
RETURN NULL
END IF
REM ============================================
REM FOOD KEYWORD - PunkAPI Beer Info
REM ============================================
DESCRIPTION "Get a random beer recipe from PunkAPI"
beer_data = GET "https://api.punkapi.com/v2/beers/random"
IF beer_data AND UBOUND(beer_data) > 0 THEN
beer = beer_data[0]
TALK "🍺 Beer Information: " + beer.name
TALK "📝 Tagline: " + beer.tagline
TALK ""
TALK "📊 Details:"
TALK "• ABV: " + beer.abv + "%"
TALK "• IBU: " + beer.ibu
TALK "• EBC: " + beer.ebc
TALK "• First Brewed: " + beer.first_brewed
TALK ""
TALK "📖 Description:"
TALK beer.description
TALK ""
IF beer.food_pairing THEN
TALK "🍽️ Food Pairing:"
FOR EACH pairing IN beer.food_pairing
TALK "• " + pairing
END FOR
TALK ""
END IF
IF beer.brewers_tips THEN
TALK "💡 Brewer's Tips:"
TALK beer.brewers_tips
END IF
IF beer.image_url THEN
TALK ""
TALK "📷 Image: " + beer.image_url
file = DOWNLOAD beer.image_url
SEND FILE file
END IF
RETURN beer
ELSE
TALK "❌ Could not fetch beer information"
RETURN NULL
END IF
REM ============================================
REM FOOD KEYWORD - Search Beer by Name
REM ============================================
PARAM beer_name AS string LIKE "punk"
DESCRIPTION "Search for beers by name"
search_url = "https://api.punkapi.com/v2/beers?beer_name=" + beer_name
beer_data = GET search_url
IF beer_data AND UBOUND(beer_data) > 0 THEN
TALK "🔍 Found " + UBOUND(beer_data) + " beer(s) matching '" + beer_name + "':"
TALK ""
FOR EACH beer IN beer_data
TALK "🍺 " + beer.name
TALK " " + beer.tagline
TALK " ABV: " + beer.abv + "% | IBU: " + beer.ibu
TALK " First Brewed: " + beer.first_brewed
TALK ""
END FOR
RETURN beer_data
ELSE
TALK "❌ No beers found for: " + beer_name
RETURN NULL
END IF
REM ============================================
REM FOOD KEYWORD - High ABV Beers
REM ============================================
PARAM min_abv AS number LIKE 8.0
DESCRIPTION "Get beers with ABV higher than specified"
abv_url = "https://api.punkapi.com/v2/beers?abv_gt=" + min_abv
beer_data = GET abv_url
IF beer_data THEN
TALK "🍺 Beers with ABV > " + min_abv + "%:"
TALK ""
counter = 0
FOR EACH beer IN beer_data
IF counter < 10 THEN
TALK "🍺 " + beer.name + " - " + beer.abv + "% ABV"
TALK " " + beer.tagline
TALK ""
END IF
counter = counter + 1
END FOR
IF counter > 10 THEN
TALK "... and " + (counter - 10) + " more beers"
END IF
RETURN beer_data
ELSE
TALK "❌ Could not fetch high ABV beers"
RETURN NULL
END IF
REM ============================================
REM FOOD KEYWORD - Bacon Ipsum Text
REM ============================================
PARAM paragraphs AS integer LIKE 3
DESCRIPTION "Generate bacon-themed lorem ipsum text"
bacon_url = "https://baconipsum.com/api/?type=meat-and-filler&paras=" + paragraphs
bacon_text = GET bacon_url
IF bacon_text THEN
TALK "🥓 Bacon Ipsum Text:"
TALK ""
FOR EACH paragraph IN bacon_text
TALK paragraph
TALK ""
END FOR
RETURN bacon_text
ELSE
TALK "❌ Could not generate bacon ipsum"
RETURN NULL
END IF

View file

@ -0,0 +1,595 @@
REM General Bots: Science, Space & Books APIs - Free Knowledge Integration
REM Based on public-apis list - No authentication required
REM ============================================
REM SPACE KEYWORD - Random Space Image (NASA APOD)
REM ============================================
DESCRIPTION "Get NASA's Astronomy Picture of the Day (demo key)"
apod_data = GET "https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY"
IF apod_data.title THEN
TALK "🌌 NASA Astronomy Picture of the Day:"
TALK "📸 " + apod_data.title
TALK ""
TALK "📅 Date: " + apod_data.date
TALK "📝 Explanation:"
TALK apod_data.explanation
TALK ""
IF apod_data.media_type = "image" THEN
TALK "🖼️ Image URL: " + apod_data.url
file = DOWNLOAD apod_data.url
SEND FILE file
ELSE IF apod_data.media_type = "video" THEN
TALK "🎥 Video URL: " + apod_data.url
END IF
IF apod_data.copyright THEN
TALK "©️ Copyright: " + apod_data.copyright
END IF
RETURN apod_data
ELSE
TALK "❌ Could not fetch NASA APOD"
RETURN NULL
END IF
REM ============================================
REM SPACE KEYWORD - ISS Current Location
REM ============================================
DESCRIPTION "Get current location of International Space Station"
iss_location = GET "http://api.open-notify.org/iss-now.json"
IF iss_location.message = "success" THEN
lat = iss_location.iss_position.latitude
lon = iss_location.iss_position.longitude
timestamp = iss_location.timestamp
TALK "🛰️ International Space Station Location:"
TALK "📍 Latitude: " + lat
TALK "📍 Longitude: " + lon
TALK "⏰ Timestamp: " + timestamp
TALK ""
TALK "🗺️ View on map: https://www.google.com/maps?q=" + lat + "," + lon
RETURN iss_location
ELSE
TALK "❌ Could not fetch ISS location"
RETURN NULL
END IF
REM ============================================
REM SPACE KEYWORD - People in Space Right Now
REM ============================================
DESCRIPTION "Get list of astronauts currently in space"
space_people = GET "http://api.open-notify.org/astros.json"
IF space_people.message = "success" THEN
TALK "👨‍🚀 People Currently in Space: " + space_people.number
TALK ""
FOR EACH person IN space_people.people
TALK "• " + person.name + " (" + person.craft + ")"
END FOR
RETURN space_people
ELSE
TALK "❌ Could not fetch space crew data"
RETURN NULL
END IF
REM ============================================
REM SPACE KEYWORD - SpaceX Launch Info
REM ============================================
DESCRIPTION "Get latest SpaceX launch information"
launch_data = GET "https://api.spacexdata.com/v4/launches/latest"
IF launch_data.name THEN
TALK "🚀 Latest SpaceX Launch:"
TALK "Mission: " + launch_data.name
TALK ""
TALK "📅 Date: " + launch_data.date_utc
TALK "🎯 Success: " + launch_data.success
TALK "🔢 Flight Number: " + launch_data.flight_number
IF launch_data.details THEN
TALK ""
TALK "📝 Details:"
TALK launch_data.details
END IF
IF launch_data.links.webcast THEN
TALK ""
TALK "🎥 Webcast: " + launch_data.links.webcast
END IF
IF launch_data.links.patch.small THEN
TALK ""
TALK "🏴 Mission Patch:"
file = DOWNLOAD launch_data.links.patch.small
SEND FILE file
END IF
RETURN launch_data
ELSE
TALK "❌ Could not fetch SpaceX launch data"
RETURN NULL
END IF
REM ============================================
REM SPACE KEYWORD - Next SpaceX Launch
REM ============================================
DESCRIPTION "Get next upcoming SpaceX launch"
next_launch = GET "https://api.spacexdata.com/v4/launches/next"
IF next_launch.name THEN
TALK "🚀 Next SpaceX Launch:"
TALK "Mission: " + next_launch.name
TALK ""
TALK "📅 Scheduled: " + next_launch.date_utc
TALK "🔢 Flight Number: " + next_launch.flight_number
IF next_launch.details THEN
TALK ""
TALK "📝 Details:"
TALK next_launch.details
END IF
RETURN next_launch
ELSE
TALK "❌ Could not fetch next SpaceX launch"
RETURN NULL
END IF
REM ============================================
REM SCIENCE KEYWORD - Random Math Problem
REM ============================================
PARAM difficulty AS "easy", "medium", "hard"
DESCRIPTION "Get a random math problem to solve"
REM Generate based on difficulty
result = NEW OBJECT
IF difficulty = "easy" THEN
num1 = INT(RND() * 10) + 1
num2 = INT(RND() * 10) + 1
operation = "+"
answer = num1 + num2
ELSE IF difficulty = "medium" THEN
num1 = INT(RND() * 50) + 10
num2 = INT(RND() * 50) + 10
operations = NEW ARRAY
operations.PUSH("+")
operations.PUSH("-")
operations.PUSH("*")
operation = operations[INT(RND() * 3)]
IF operation = "+" THEN
answer = num1 + num2
ELSE IF operation = "-" THEN
answer = num1 - num2
ELSE
answer = num1 * num2
END IF
ELSE IF difficulty = "hard" THEN
num1 = INT(RND() * 100) + 50
num2 = INT(RND() * 20) + 5
operations = NEW ARRAY
operations.PUSH("+")
operations.PUSH("-")
operations.PUSH("*")
operations.PUSH("/")
operation = operations[INT(RND() * 4)]
IF operation = "+" THEN
answer = num1 + num2
ELSE IF operation = "-" THEN
answer = num1 - num2
ELSE IF operation = "*" THEN
answer = num1 * num2
ELSE
answer = num1 / num2
END IF
END IF
result.problem = num1 + " " + operation + " " + num2
result.answer = answer
result.difficulty = difficulty
TALK "🧮 Math Problem (" + difficulty + "):"
TALK result.problem + " = ?"
TALK ""
TALK "💡 Think about it..."
WAIT 3
TALK ""
TALK "✅ Answer: " + answer
RETURN result
REM ============================================
REM SCIENCE KEYWORD - Periodic Table Element
REM ============================================
PARAM element AS string LIKE "hydrogen"
DESCRIPTION "Get information about a chemical element"
element_url = "https://neelpatel05.pythonanywhere.com/element/atomicname?atomicname=" + element
element_data = GET element_url
IF element_data.atomicName THEN
TALK "🧪 Chemical Element: " + element_data.atomicName
TALK ""
TALK "⚛️ Symbol: " + element_data.symbol
TALK "🔢 Atomic Number: " + element_data.atomicNumber
TALK "⚖️ Atomic Mass: " + element_data.atomicMass
TALK "📊 Group: " + element_data.groupBlock
TALK "🌡️ Boiling Point: " + element_data.boilingPoint
TALK "🌡️ Melting Point: " + element_data.meltingPoint
TALK "📏 Density: " + element_data.density
TALK "⚡ Electronegativity: " + element_data.electronegativity
TALK "📅 Year Discovered: " + element_data.yearDiscovered
RETURN element_data
ELSE
TALK "❌ Element not found: " + element
RETURN NULL
END IF
REM ============================================
REM SCIENCE KEYWORD - Random Science Fact
REM ============================================
DESCRIPTION "Get a random science fact"
science_facts = NEW ARRAY
science_facts.PUSH("The human body contains about 37.2 trillion cells.")
science_facts.PUSH("Light travels at approximately 299,792 kilometers per second.")
science_facts.PUSH("Water covers about 71% of Earth's surface.")
science_facts.PUSH("The human brain contains about 86 billion neurons.")
science_facts.PUSH("DNA stands for Deoxyribonucleic Acid.")
science_facts.PUSH("Sound travels faster through water than air.")
science_facts.PUSH("Octopuses have three hearts and blue blood.")
science_facts.PUSH("The sun is about 109 times wider than Earth.")
science_facts.PUSH("A single bolt of lightning contains 1 billion volts.")
science_facts.PUSH("Humans share about 60% of their DNA with bananas.")
random_index = INT(RND() * UBOUND(science_facts))
fact = science_facts[random_index]
TALK "🔬 Random Science Fact:"
TALK fact
RETURN fact
REM ============================================
REM SCIENCE KEYWORD - Earthquake Data
REM ============================================
DESCRIPTION "Get recent earthquake data worldwide"
quake_url = "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/significant_month.geojson"
quake_data = GET quake_url
IF quake_data.features THEN
TALK "🌍 Significant Earthquakes (Last Month):"
TALK "Total Events: " + quake_data.metadata.count
TALK ""
counter = 0
FOR EACH quake IN quake_data.features
IF counter < 5 THEN
props = quake.properties
magnitude = props.mag
place = props.place
time_ms = props.time
TALK "📍 " + place
TALK " Magnitude: " + magnitude
TALK " Time: " + time_ms
TALK ""
END IF
counter = counter + 1
END FOR
IF counter > 5 THEN
TALK "... and " + (counter - 5) + " more earthquakes"
END IF
RETURN quake_data.features
ELSE
TALK "❌ Could not fetch earthquake data"
RETURN NULL
END IF
REM ============================================
REM BOOKS KEYWORD - Random Quote from Book
REM ============================================
DESCRIPTION "Get a random book quote"
quote = GET "https://api.quotable.io/random?tags=literature"
IF quote.content THEN
TALK "📚 Book Quote:"
TALK '"' + quote.content + '"'
TALK ""
TALK "— " + quote.author
IF quote.tags THEN
TALK ""
TALK "Tags: " + JOIN(quote.tags, ", ")
END IF
RETURN quote
ELSE
TALK "❌ Could not fetch book quote"
RETURN NULL
END IF
REM ============================================
REM BOOKS KEYWORD - Bible Verse of the Day
REM ============================================
DESCRIPTION "Get Bible verse of the day"
verse = GET "https://beta.ourmanna.com/api/v1/get?format=json"
IF verse.verse.details.text THEN
TALK "📖 Bible Verse of the Day:"
TALK verse.verse.details.reference
TALK ""
TALK verse.verse.details.text
TALK ""
TALK "Version: " + verse.verse.details.version
RETURN verse
ELSE
TALK "❌ Could not fetch Bible verse"
RETURN NULL
END IF
REM ============================================
REM BOOKS KEYWORD - Random Quran Verse
REM ============================================
DESCRIPTION "Get a random verse from the Quran"
REM Random surah (1-114) and ayah
surah = INT(RND() * 114) + 1
ayah = INT(RND() * 20) + 1
quran_url = "https://api.alquran.cloud/v1/ayah/" + surah + ":" + ayah + "/en.asad"
quran_data = GET quran_url
IF quran_data.data.text THEN
TALK "📖 Quran Verse:"
TALK "Surah " + quran_data.data.surah.number + ": " + quran_data.data.surah.englishName
TALK "Ayah " + quran_data.data.numberInSurah
TALK ""
TALK quran_data.data.text
RETURN quran_data.data
ELSE
TALK "❌ Could not fetch Quran verse"
RETURN NULL
END IF
REM ============================================
REM BOOKS KEYWORD - Poetry Search
REM ============================================
PARAM search_term AS string LIKE "love"
DESCRIPTION "Search for poems containing a specific word"
poetry_url = "https://poetrydb.org/lines/" + search_term
poems = GET poetry_url
IF poems AND UBOUND(poems) > 0 THEN
TALK "📜 Found " + UBOUND(poems) + " poems with '" + search_term + "':"
TALK ""
counter = 0
FOR EACH poem IN poems
IF counter < 3 THEN
TALK "📖 " + poem.title
TALK "✍️ By " + poem.author
TALK ""
REM Show first few lines
line_count = 0
FOR EACH line IN poem.lines
IF line_count < 4 THEN
TALK " " + line
END IF
line_count = line_count + 1
END FOR
TALK ""
END IF
counter = counter + 1
END FOR
IF counter > 3 THEN
TALK "... and " + (counter - 3) + " more poems"
END IF
RETURN poems
ELSE
TALK "❌ No poems found for: " + search_term
RETURN NULL
END IF
REM ============================================
REM BOOKS KEYWORD - Random Poem
REM ============================================
DESCRIPTION "Get a random poem"
REM Get random poem
poem_data = GET "https://poetrydb.org/random/1"
IF poem_data AND UBOUND(poem_data) > 0 THEN
poem = poem_data[0]
TALK "📜 Random Poem:"
TALK ""
TALK "📖 " + poem.title
TALK "✍️ By " + poem.author
TALK ""
FOR EACH line IN poem.lines
TALK line
END FOR
RETURN poem
ELSE
TALK "❌ Could not fetch random poem"
RETURN NULL
END IF
REM ============================================
REM BOOKS KEYWORD - Shakespeare Quote
REM ============================================
DESCRIPTION "Get a random Shakespeare quote"
shakespeare = GET "https://api.quotable.io/random?tags=famous-quotes&author=william-shakespeare"
IF shakespeare.content THEN
TALK "🎭 Shakespeare Quote:"
TALK '"' + shakespeare.content + '"'
TALK ""
TALK "— William Shakespeare"
RETURN shakespeare
ELSE
REM Fallback to any Shakespeare source
TALK "🎭 Shakespeare Quote:"
TALK '"To be, or not to be, that is the question."'
TALK ""
TALK "— William Shakespeare (Hamlet)"
result = NEW OBJECT
result.content = "To be, or not to be, that is the question."
result.author = "William Shakespeare"
RETURN result
END IF
REM ============================================
REM SCIENCE KEYWORD - Random Wikipedia Summary
REM ============================================
DESCRIPTION "Get a random Wikipedia article summary"
wiki_data = GET "https://en.wikipedia.org/api/rest_v1/page/random/summary"
IF wiki_data.title THEN
TALK "📚 Random Wikipedia Article:"
TALK "Title: " + wiki_data.title
TALK ""
TALK "📝 Summary:"
TALK wiki_data.extract
TALK ""
TALK "🔗 Read more: " + wiki_data.content_urls.desktop.page
IF wiki_data.thumbnail THEN
TALK ""
TALK "🖼️ Thumbnail:"
file = DOWNLOAD wiki_data.thumbnail.source
SEND FILE file
END IF
RETURN wiki_data
ELSE
TALK "❌ Could not fetch Wikipedia article"
RETURN NULL
END IF
REM ============================================
REM SCIENCE KEYWORD - Today in History
REM ============================================
DESCRIPTION "Get historical events that happened today"
today = NOW()
month = MONTH(today)
day = DAY(today)
history_url = "https://history.muffinlabs.com/date/" + month + "/" + day
history_data = GET history_url
IF history_data.data.Events THEN
TALK "📅 Today in History (" + month + "/" + day + "):"
TALK ""
counter = 0
FOR EACH event IN history_data.data.Events
IF counter < 5 THEN
TALK "📜 " + event.year + ": " + event.text
TALK ""
END IF
counter = counter + 1
END FOR
IF counter > 5 THEN
TALK "... and " + (counter - 5) + " more events"
END IF
IF history_data.data.Births THEN
TALK ""
TALK "🎂 Notable Births:"
birth_count = 0
FOR EACH birth IN history_data.data.Births
IF birth_count < 3 THEN
TALK "• " + birth.year + ": " + birth.text
END IF
birth_count = birth_count + 1
END FOR
END IF
RETURN history_data.data
ELSE
TALK "❌ Could not fetch historical data"
RETURN NULL
END IF
REM ============================================
REM SCIENCE KEYWORD - Age Calculator
REM ============================================
PARAM birth_date AS date LIKE "1990-01-15"
DESCRIPTION "Calculate age and interesting facts"
birth = DATEVALUE(birth_date)
today = NOW()
years = YEAR(today) - YEAR(birth)
days = DATEDIFF(today, birth, "d")
hours = days * 24
minutes = hours * 60
TALK "🎂 Age Calculator:"
TALK "Birth Date: " + birth_date
TALK ""
TALK "📊 You are:"
TALK "• " + years + " years old"
TALK "• " + days + " days old"
TALK "• " + hours + " hours old"
TALK "• " + minutes + " minutes old"
TALK ""
REM Calculate next birthday
next_birthday = DATEVALUE(YEAR(today) + "-" + MONTH(birth) + "-" + DAY(birth))
IF next_birthday < today THEN
next_birthday = DATEADD(next_birthday, 1, "yyyy")
END IF
days_until = DATEDIFF(next_birthday, today, "d")
TALK "🎉 Next birthday in " + days_until + " days!"
result = NEW OBJECT
result.years = years
result.days = days
result.hours = hours
result.next_birthday = next_birthday
RETURN result

Some files were not shown because too many files have changed in this diff Show more