AUXteam commited on
Commit
fcb47be
Β·
verified Β·
1 Parent(s): 4ccc89a

Upload folder using huggingface_hub

Browse files
Files changed (2) hide show
  1. frontend.py +33 -52
  2. src/app.ts +17 -15
frontend.py CHANGED
@@ -1,5 +1,6 @@
1
  import gradio as gr
2
  import requests
 
3
  import time
4
  import os
5
 
@@ -10,119 +11,99 @@ def get_status():
10
  r = requests.get(f"{NODE_URL}/health", timeout=2)
11
  return r.json()
12
  except Exception as e:
13
- return {"whatsappStatus": "Offline", "connected": False, "ready": False, "logs": [f"Error connecting to backend: {str(e)}"]}
14
 
15
  def update_ui():
16
  status = get_status()
 
17
 
18
- # Connection info
19
- status_msg = status.get('whatsappStatus', 'Unknown')
20
- connected = "βœ… Yes" if status.get('connected') else "❌ No"
21
- ready = "πŸš€ Ready" if status.get('ready') else "⏳ Initializing"
22
-
23
- info_text = f"WhatsApp Status: {status_msg}\nConnected: {connected}\nReady: {ready}"
24
-
25
- # QR Code handling
26
- qr_html = "<div style='text-align:center; padding:40px; color:#888;'>Waiting for WhatsApp to initialize...</div>"
27
  if status.get('hasQR'):
28
  try:
29
  qr_r = requests.get(f"{NODE_URL}/qr-data", timeout=1)
30
  if qr_r.status_code == 200:
31
  qr_data = qr_r.json()
32
- ascii_qr = qr_data.get('ascii', '')
33
  qr_html = f"""
34
- <div style='background:white; color:black; padding:20px; display:flex; flex-direction:column; align-items:center; border-radius:12px; box-shadow: 0 8px 24px rgba(0,0,0,0.2);'>
35
- <h3 style='margin:0 0 15px 0; font-family:sans-serif; color:#128c7e;'>Scan with WhatsApp</h3>
36
- <pre style='font-size:7px; line-height:1; margin:0; font-family:monospace; font-weight:bold; letter-spacing:0;'>{ascii_qr}</pre>
37
- <p style='margin-top:15px; font-size:13px; font-family:sans-serif;'>Open WhatsApp > Linked Devices > Link a Device</p>
38
  </div>
39
  """
40
  except:
41
  pass
42
  elif status.get('ready'):
43
- qr_html = """
44
- <div style='text-align:center; padding:40px; color:#4caf50; background:#f0f9f0; border-radius:12px; border:2px dashed #4caf50;'>
45
- <h2 style='margin:0;'>βœ… Connected!</h2>
46
- <p>You can now use the API to send messages.</p>
47
- </div>
48
- """
49
 
50
  logs = "\n".join(status.get('logs', []))
51
 
52
- # Handle screenshot as local file to bypass Gradio SSRF protection
53
  screenshot_path = None
54
  try:
55
  sc_r = requests.get(f"{NODE_URL}/screenshot", timeout=5)
56
  if sc_r.status_code == 200:
57
- screenshot_path = "current_debug_screen.png"
58
  with open(screenshot_path, "wb") as f:
59
  f.write(sc_r.content)
60
  except:
61
  pass
62
 
63
- return info_text, qr_html, logs, screenshot_path
64
 
65
  def trigger_init():
66
  try:
67
  requests.post(f"{NODE_URL}/init")
68
- return "Initialization command sent."
69
  except Exception as e:
70
  return f"Error: {str(e)}"
71
 
72
- def send_poll(number, title, options):
73
  try:
74
- opts = [o.strip() for o in options.split(",")]
75
- r = requests.post(f"{NODE_URL}/send-poll", json={"telnumber": number, "name": title, "choices": opts})
76
- return r.json()
77
  except Exception as e:
78
- return {"error": str(e)}
79
 
80
- def send_message(number, message):
81
  try:
82
- r = requests.post(f"{NODE_URL}/send-message", json={"telnumber": number, "message": message})
 
83
  return r.json()
84
  except Exception as e:
85
  return {"error": str(e)}
86
 
87
  with gr.Blocks(title="WPPConnect Dashboard") as demo:
88
- gr.Markdown("# πŸ€– WPPConnect WhatsApp Control Center")
89
 
90
  with gr.Row():
91
  with gr.Column(scale=1):
92
- status_display = gr.Label(label="Session Info")
93
- init_btn = gr.Button("πŸš€ Start/Restart Session", variant="primary")
 
 
94
  refresh_btn = gr.Button("πŸ”„ Refresh UI")
95
 
96
  with gr.Column(scale=2):
97
- qr_display = gr.HTML(label="Connection Status / QR Code")
98
 
99
  with gr.Tabs():
100
  with gr.TabItem("πŸ“Š Send Poll"):
101
  with gr.Row():
102
  poll_num = gr.Textbox(label="Phone Number", placeholder="5511999999999")
103
  poll_title = gr.Textbox(label="Poll Question")
104
- poll_opts = gr.Textbox(label="Choices (comma separated)", placeholder="Option 1, Option 2, Option 3")
105
- poll_send = gr.Button("Send Poll", variant="primary")
106
  poll_out = gr.JSON(label="Result")
107
 
108
- with gr.TabItem("πŸ’¬ Send Text"):
109
- with gr.Row():
110
- msg_num = gr.Textbox(label="Phone Number")
111
- msg_txt = gr.Textbox(label="Message", lines=2)
112
- msg_btn = gr.Button("Send Message")
113
- msg_out = gr.JSON(label="Result")
114
-
115
- with gr.TabItem("πŸ“‹ Debug Logs"):
116
- log_display = gr.Code(label="Backend Logs", lines=15, language="markdown")
117
 
118
- with gr.TabItem("πŸ” Live Browser"):
119
- gr.Markdown("Visual debugging of the underlying browser page.")
120
- screenshot_display = gr.Image(label="Browser Screenshot")
121
 
122
  init_btn.click(trigger_init, outputs=status_display)
 
123
  refresh_btn.click(update_ui, outputs=[status_display, qr_display, log_display, screenshot_display])
124
  poll_send.click(send_poll, inputs=[poll_num, poll_title, poll_opts], outputs=poll_out)
125
- msg_btn.click(send_message, inputs=[msg_num, msg_txt], outputs=msg_out)
126
 
127
  try:
128
  demo.load(update_ui, outputs=[status_display, qr_display, log_display, screenshot_display], every=10)
@@ -130,4 +111,4 @@ with gr.Blocks(title="WPPConnect Dashboard") as demo:
130
  demo.load(update_ui, outputs=[status_display, qr_display, log_display, screenshot_display])
131
 
132
  if __name__ == "__main__":
133
- demo.launch(server_name="0.0.0.0", server_port=7860, theme=gr.themes.Soft(primary_hue="green"))
 
1
  import gradio as gr
2
  import requests
3
+ import subprocess
4
  import time
5
  import os
6
 
 
11
  r = requests.get(f"{NODE_URL}/health", timeout=2)
12
  return r.json()
13
  except Exception as e:
14
+ return {"whatsappStatus": "Offline", "connected": False, "ready": False, "logs": [str(e)]}
15
 
16
  def update_ui():
17
  status = get_status()
18
+ msg = f"Status: {status.get('whatsappStatus', 'Unknown')}\nConnected: {status.get('connected', False)}\nReady: {status.get('ready', False)}"
19
 
20
+ qr_html = "<div style='text-align:center; padding:20px; color:#666;'>QR code will appear here.</div>"
 
 
 
 
 
 
 
 
21
  if status.get('hasQR'):
22
  try:
23
  qr_r = requests.get(f"{NODE_URL}/qr-data", timeout=1)
24
  if qr_r.status_code == 200:
25
  qr_data = qr_r.json()
26
+ ascii_qr = qr_data['ascii']
27
  qr_html = f"""
28
+ <div style='background:white; color:black; padding:15px; display:flex; flex-direction:column; align-items:center; border-radius:8px; box-shadow: 0 4px 12px rgba(0,0,0,0.15);'>
29
+ <h3 style='margin:0 0 10px 0; font-family:sans-serif;'>Scan to Login</h3>
30
+ <pre style='font-size:7px; line-height:1; margin:0; font-family:monospace; font-weight:bold;'>{ascii_qr}</pre>
 
31
  </div>
32
  """
33
  except:
34
  pass
35
  elif status.get('ready'):
36
+ qr_html = "<div style='text-align:center; padding:20px; color:#4caf50; font-weight:bold;'>WhatsApp is connected!</div>"
 
 
 
 
 
37
 
38
  logs = "\n".join(status.get('logs', []))
39
 
 
40
  screenshot_path = None
41
  try:
42
  sc_r = requests.get(f"{NODE_URL}/screenshot", timeout=5)
43
  if sc_r.status_code == 200:
44
+ screenshot_path = "current_screen.png"
45
  with open(screenshot_path, "wb") as f:
46
  f.write(sc_r.content)
47
  except:
48
  pass
49
 
50
+ return msg, qr_html, logs, screenshot_path
51
 
52
  def trigger_init():
53
  try:
54
  requests.post(f"{NODE_URL}/init")
55
+ return "Initialization triggered."
56
  except Exception as e:
57
  return f"Error: {str(e)}"
58
 
59
+ def trigger_reload():
60
  try:
61
+ requests.post(f"{NODE_URL}/reload")
62
+ return "Reload command sent."
 
63
  except Exception as e:
64
+ return f"Error: {str(e)}"
65
 
66
+ def send_poll(number, title, options):
67
  try:
68
+ opts = [o.strip() for o in options.split(",")]
69
+ r = requests.post(f"{NODE_URL}/send-poll", json={"telnumber": number, "name": title, "choices": opts})
70
  return r.json()
71
  except Exception as e:
72
  return {"error": str(e)}
73
 
74
  with gr.Blocks(title="WPPConnect Dashboard") as demo:
75
+ gr.Markdown("# πŸ€– WPPConnect WhatsApp Control Panel")
76
 
77
  with gr.Row():
78
  with gr.Column(scale=1):
79
+ status_display = gr.Label(label="System Status")
80
+ with gr.Row():
81
+ init_btn = gr.Button("πŸš€ Start/Retry Session", variant="primary")
82
+ reload_btn = gr.Button("πŸ”„ Force Reload Page", variant="secondary")
83
  refresh_btn = gr.Button("πŸ”„ Refresh UI")
84
 
85
  with gr.Column(scale=2):
86
+ qr_display = gr.HTML(label="Login QR Code")
87
 
88
  with gr.Tabs():
89
  with gr.TabItem("πŸ“Š Send Poll"):
90
  with gr.Row():
91
  poll_num = gr.Textbox(label="Phone Number", placeholder="5511999999999")
92
  poll_title = gr.Textbox(label="Poll Question")
93
+ poll_opts = gr.Textbox(label="Choices (comma separated)", placeholder="Yes, No, Maybe")
94
+ poll_send = gr.Button("Send Poll Now", variant="primary")
95
  poll_out = gr.JSON(label="Result")
96
 
97
+ with gr.TabItem("πŸ“‹ System Logs"):
98
+ log_display = gr.Code(label="Recent Logs", lines=15, language="markdown")
 
 
 
 
 
 
 
99
 
100
+ with gr.TabItem("πŸ” Browser Debug"):
101
+ screenshot_display = gr.Image(label="Live Browser View")
 
102
 
103
  init_btn.click(trigger_init, outputs=status_display)
104
+ reload_btn.click(trigger_reload, outputs=status_display)
105
  refresh_btn.click(update_ui, outputs=[status_display, qr_display, log_display, screenshot_display])
106
  poll_send.click(send_poll, inputs=[poll_num, poll_title, poll_opts], outputs=poll_out)
 
107
 
108
  try:
109
  demo.load(update_ui, outputs=[status_display, qr_display, log_display, screenshot_display], every=10)
 
111
  demo.load(update_ui, outputs=[status_display, qr_display, log_display, screenshot_display])
112
 
113
  if __name__ == "__main__":
114
+ demo.launch(server_name="0.0.0.0", server_port=7860)
src/app.ts CHANGED
@@ -18,7 +18,7 @@ const log = (msg: string) => {
18
  const entry = `${new Date().toISOString()} - ${msg}`;
19
  console.log(entry);
20
  appLogs.push(entry);
21
- if (appLogs.length > 200) appLogs.shift();
22
  };
23
 
24
  app.use(express.json());
@@ -40,7 +40,7 @@ app.get('/qr-data', (req, res) => {
40
  });
41
 
42
  app.get('/screenshot', async (req, res) => {
43
- if (whatsappClient && whatsappClient.page) {
44
  try {
45
  const screenshot = await whatsappClient.page.screenshot({ encoding: 'base64' });
46
  const img = Buffer.from(screenshot as string, 'base64');
@@ -50,7 +50,7 @@ app.get('/screenshot', async (req, res) => {
50
  res.status(500).json({ error: e.message });
51
  }
52
  } else {
53
- res.status(404).json({ error: 'Browser not active' });
54
  }
55
  });
56
 
@@ -60,13 +60,18 @@ app.post('/init', (req, res) => {
60
  res.json({ success: true });
61
  });
62
 
63
- app.post('/send-message', async (req, res) => {
64
- const { telnumber, message } = req.body;
65
- if (!whatsappClient || !isReady) return res.status(503).json({ error: 'WhatsApp not ready' });
66
- try {
67
- const result = await whatsappClient.sendText(`${telnumber}@c.us`, message);
68
- res.json({ success: true, result });
69
- } catch (e: any) { res.status(500).json({ error: e.message }); }
 
 
 
 
 
70
  });
71
 
72
  app.post('/send-poll', async (req, res) => {
@@ -84,8 +89,7 @@ async function startWPP() {
84
  statusMsg = 'Initializing...';
85
  log('Starting WPPConnect init...');
86
 
87
- // Try to get IP for web.whatsapp.com manually
88
- let waIP = '157.240.22.60';
89
  try {
90
  const resolver = new Resolver();
91
  resolver.setServers(['8.8.8.8', '1.1.1.1']);
@@ -100,11 +104,9 @@ async function startWPP() {
100
  log(`DNS failure, using fallback IP ${waIP}`);
101
  }
102
 
103
- // Cleanup tokens to avoid locks
104
  try {
105
  const tokensDir = path.join(process.cwd(), 'tokens');
106
  if (fs.existsSync(tokensDir)) fs.rmSync(tokensDir, { recursive: true, force: true });
107
- log('Cleaned tokens directory');
108
  } catch (e) {}
109
 
110
  try {
@@ -133,6 +135,7 @@ async function startWPP() {
133
  ],
134
  },
135
  autoClose: 0,
 
136
  updatesLog: false,
137
  waitForLogin: false,
138
  });
@@ -147,6 +150,5 @@ async function startWPP() {
147
 
148
  app.listen(port, () => {
149
  log(`Node Backend started on port ${port}`);
150
- // Initial start after 5 seconds
151
  setTimeout(startWPP, 5000);
152
  });
 
18
  const entry = `${new Date().toISOString()} - ${msg}`;
19
  console.log(entry);
20
  appLogs.push(entry);
21
+ if (appLogs.length > 100) appLogs.shift();
22
  };
23
 
24
  app.use(express.json());
 
40
  });
41
 
42
  app.get('/screenshot', async (req, res) => {
43
+ if (whatsappClient && whatsappClient.page && !whatsappClient.page.isClosed()) {
44
  try {
45
  const screenshot = await whatsappClient.page.screenshot({ encoding: 'base64' });
46
  const img = Buffer.from(screenshot as string, 'base64');
 
50
  res.status(500).json({ error: e.message });
51
  }
52
  } else {
53
+ res.status(404).json({ error: 'Browser not active or page closed' });
54
  }
55
  });
56
 
 
60
  res.json({ success: true });
61
  });
62
 
63
+ app.post('/reload', async (req, res) => {
64
+ if (whatsappClient && whatsappClient.page) {
65
+ try {
66
+ await whatsappClient.page.reload();
67
+ log('Page reloaded manually');
68
+ res.json({ success: true });
69
+ } catch (e: any) {
70
+ res.status(500).json({ error: e.message });
71
+ }
72
+ } else {
73
+ res.status(404).json({ error: 'Client not active' });
74
+ }
75
  });
76
 
77
  app.post('/send-poll', async (req, res) => {
 
89
  statusMsg = 'Initializing...';
90
  log('Starting WPPConnect init...');
91
 
92
+ let waIP = '31.13.66.56';
 
93
  try {
94
  const resolver = new Resolver();
95
  resolver.setServers(['8.8.8.8', '1.1.1.1']);
 
104
  log(`DNS failure, using fallback IP ${waIP}`);
105
  }
106
 
 
107
  try {
108
  const tokensDir = path.join(process.cwd(), 'tokens');
109
  if (fs.existsSync(tokensDir)) fs.rmSync(tokensDir, { recursive: true, force: true });
 
110
  } catch (e) {}
111
 
112
  try {
 
135
  ],
136
  },
137
  autoClose: 0,
138
+ deviceSyncTimeout: 0, // Prevent timeout during slow sync
139
  updatesLog: false,
140
  waitForLogin: false,
141
  });
 
150
 
151
  app.listen(port, () => {
152
  log(`Node Backend started on port ${port}`);
 
153
  setTimeout(startWPP, 5000);
154
  });