-
-
Notifications
You must be signed in to change notification settings - Fork 380
Smart JID validation, Session UI controls & Local Dev Infrastructure #248
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Refactor RabbitMQ configuration to use environment variables. - Expose PostgreSQL ports to the host for local access. - Update .env.sample with new configuration options.
- Add logic to switch between local relative path and binary path. - Add GO_ENV variable to .env to enable local development mode with Air.
…sOnWhatsApp" -m "- Replace basic parsing with online WhatsApp API check.\n- Automatically normalize regional formats (e.g., fix Mexico +52 to +521).\n- Validate existence of the number before sending.
- Introduce 'GetFormattedPhone' handler to verify numbers via WhatsApp API.\n- Register POST /misc/phone route.\n- Allow JID normalization (e.g., Mexico +521) without sending messages.
- Add MinIO container exposing ports 9000 (API) and 9001 (Console).\n- Configure default credentials and persistence volume.\n- Enable S3-compatible media storage for WuzAPI.
… logout) - Add Session section cards to dashboard.\n- Implement Semantic UI modals for session actions.\n- Add JS logic to consume /session/* endpoints with auth token.\n- Fix modal buttons with 'approve' class for event triggering.
- Add 'proxy-http' service (TinyProxy) on port 8888 for HTTP testing.\n- Add 'proxy-socks' service (Go-Socks5) on port 1080 for SOCKS5 auth testing.\n- Facilitate local development and testing of WuzAPI proxy configurations.
Summary of ChangesHello @lomeliDev, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a suite of enhancements across the application's core, frontend, and development infrastructure. It significantly improves the reliability of message handling by validating recipient phone numbers against the WhatsApp network, provides users with direct control over their session status through an intuitive dashboard interface, and expands the local development environment with essential tools for testing and debugging various integrations and proxy configurations. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces significant enhancements to the application's environment, Docker Compose setup, and core message handling logic, along with new UI features. The changes include adding GO_ENV, ADMINER_PORT, and MinIO configuration to .env.sample, and including tmp in .gitignore. The docker-compose.yml file is updated to make RabbitMQ configuration dynamic, expose the database port, and integrate new services like MinIO, Adminer, Webhook Tester, and HTTP/SOCKS5 proxies. Crucially, the handlers.go file refactors the validateMessageFields function to accept a whatsmeow.Client for real-time WhatsApp number validation and JID correction, applying this new logic across numerous message and group management handlers. A new /misc/phone API endpoint and corresponding GetFormattedPhone handler are added to leverage this validation. The routes.go file updates static file serving logic and registers the new /misc/phone route. The OpenAPI specification in static/api/spec.yml is updated for the new endpoint. Finally, the dashboard UI (static/dashboard/index.html and static/dashboard/js/app.js) gains new 'Session' management features, allowing users to connect, disconnect, and log out from WhatsApp sessions via dedicated buttons and modals. Review comments suggest translating Spanish comments in GetFormattedPhone to English, improving error handling for non-existent phone numbers in the GetFormattedPhone endpoint to return a structured {"exists": false} response, and extracting duplicated API token retrieval logic in app.js into a reusable helper function.
| // Necesitamos el cliente conectado para preguntar a la API de WhatsApp | ||
| client := clientManager.GetWhatsmeowClient(txtid) | ||
| if client == nil { | ||
| s.Respond(w, r, http.StatusInternalServerError, errors.New("no session found")) | ||
| return | ||
| } | ||
|
|
||
| decoder := json.NewDecoder(r.Body) | ||
| var t phoneStruct | ||
| err := decoder.Decode(&t) | ||
| if err != nil { | ||
| s.Respond(w, r, http.StatusBadRequest, errors.New("could not decode Payload")) | ||
| return | ||
| } | ||
|
|
||
| if t.Phone == "" { | ||
| s.Respond(w, r, http.StatusBadRequest, errors.New("missing Phone in Payload")) | ||
| return | ||
| } | ||
|
|
||
| // Usamos la función mágica que ya creamos/arreglamos | ||
| // Pasamos nil en stanza y participant porque no es un mensaje real, solo queremos validar el JID | ||
| jid, err := validateMessageFields(client, t.Phone, nil, nil) | ||
|
|
||
| if err != nil { | ||
| // Si falla (ej. el número no existe en WhatsApp), devolvemos error | ||
| s.Respond(w, r, http.StatusBadRequest, fmt.Errorf("validation failed: %v", err)) | ||
| return | ||
| } | ||
|
|
||
| // Preparamos la respuesta con los datos limpios | ||
| response := map[string]interface{}{ | ||
| "input": t.Phone, // Lo que enviaste (ej: 5233...) | ||
| "jid": jid.String(), // El JID completo (ej: 52133...@s.whatsapp.net) | ||
| "number": jid.User, // Solo el número corregido (ej: 52133...) | ||
| "exists": true, // Confirmación de que existe | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| if err != nil { | ||
| // Si falla (ej. el número no existe en WhatsApp), devolvemos error | ||
| s.Respond(w, r, http.StatusBadRequest, fmt.Errorf("validation failed: %v", err)) | ||
| return | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error handling for a non-existent phone number returns a generic error message. For a better and more consistent API experience, it would be beneficial to return a structured JSON response indicating the number does not exist, similar to the success case. You can check for the specific error no account exists from validateMessageFields and respond with {"exists": false}.
| if err != nil { | |
| // Si falla (ej. el número no existe en WhatsApp), devolvemos error | |
| s.Respond(w, r, http.StatusBadRequest, fmt.Errorf("validation failed: %v", err)) | |
| return | |
| } | |
| if err != nil { | |
| if err.Error() == "no account exists" { | |
| response := map[string]interface{}{ | |
| "input": t.Phone, | |
| "exists": false, | |
| } | |
| responseJson, _ := json.Marshal(response) | |
| s.Respond(w, r, http.StatusOK, string(responseJson)) | |
| return | |
| } | |
| s.Respond(w, r, http.StatusBadRequest, fmt.Errorf("validation failed: %v", err)) | |
| return | |
| } |
| const rawToken = localStorage.getItem('token'); | ||
| let apiToken = ""; | ||
| try { | ||
| if (rawToken) { | ||
| apiToken = JSON.parse(rawToken).value; | ||
| } | ||
| } catch (e) { | ||
| showError("Error parsing auth token"); | ||
| return; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic for retrieving and parsing the API token from localStorage is duplicated across the doConnect, doDisconnect, and doLogout functions. Consider extracting this into a helper function to reduce redundancy and improve maintainability. For example:
function getApiToken() {
const rawToken = localStorage.getItem('token');
if (!rawToken) {
showError("Auth token not found");
return null;
}
try {
return JSON.parse(rawToken).value;
} catch (e) {
showError("Error parsing auth token");
return null;
}
}Then you can simplify the calling functions to const apiToken = getApiToken();.
This PR introduces significant improvements to the core message handling, extends the Dashboard UI, and enhances the local development environment with Docker.
🚀 Key Changes
Smart JID Validation: Implemented a robust validation mechanism using IsOnWhatsApp.
Fix: Automatically corrects regional JID formats before sending messages. This specifically resolves issues with Mexican numbers (converting +52 to +521 when required by WhatsApp) and prevents sending messages to non-existent numbers.
New Endpoint (POST /misc/phone): Added a utility endpoint to validate and format phone numbers (returns the correct JID and existence status) without sending a message.
Code Cleanup: Fixed variable shadowing in handlers.go (MarkRead) and standardized logging to use zerolog for better consistency.
Session Management: Added a new "Session" widget section to the Dashboard.
Features: UI cards for Connect, Disconnect, and Logout.
UX: Implemented Semantic UI confirmation modals and toast notifications for success/error states.
Logic: Javascript functions now properly handle auth tokens and interact with /session/* endpoints.
Local S3 (MinIO): Added a minio service to docker-compose.yml (ports 9000/9001) to facilitate local testing of S3 media storage.
Proxy Testing: Added proxy-http (TinyProxy) and proxy-socks (Go-Socks5) services to the compose file to allow easy testing of WuzAPI's proxy configurations in a local environment.
Env Variables: Updated environment configuration to support these new services (RabbitMQ, MinIO, Adminer).
🧪 How to Test
Phone Validation:
POST to /misc/phone with a payload like {"phone": "521234567890"}.
Response should return the corrected JID (e.g., adding the '1' for Mexico if needed) and exists: true.
Dashboard:
Go to /dashboard.
Use the new Session cards to Disconnect and Reconnect the session.
Docker Infra:
Run docker-compose up -d minio proxy-http.
Verify MinIO console at http://localhost:9001.
📸 Screenshots
Checklist
[x] Code compiles correctly
[x] New endpoint /misc/phone tested
[x] Dashboard UI functional
[x] Docker containers build and run