AI-powered assistant for VFS Global visa applications
Size
18.6 KB
Version
1.0.0
Created
Apr 2, 2026
Updated
14 days ago
1// ==UserScript==
2// @name VFS Visa Application Assistant
3// @description AI-powered assistant for VFS Global visa applications
4// @version 1.0.0
5// @match https://*.visa.vfsglobal.com/*
6// @icon https://liftassets.vfsglobal.com/_angular/assets/images/global/vfs.ico
7// ==/UserScript==
8(function() {
9 'use strict';
10
11 // Main initialization function
12 async function init() {
13 console.log('VFS Visa Application Assistant loaded');
14
15 // Add custom CSS for our elements
16 addCustomStyles();
17
18 // Add floating button for auto-fill
19 addFloatingButton();
20
21 // Add control panel for bot operations
22 addControlPanel();
23
24 // Add auto-fill container for form data
25 addAutoFillContainer();
26
27 // Set up event listeners
28 setupEventListeners();
29
30 // Load saved data
31 loadSavedData();
32 }
33
34 // Add custom CSS styles
35 function addCustomStyles() {
36 const style = document.createElement('style');
37 style.textContent = `
38 .vfs-floating-btn {
39 position: fixed;
40 bottom: 20px;
41 right: 20px;
42 z-index: 9999;
43 background: #0066cc;
44 color: white;
45 border: none;
46 border-radius: 50%;
47 width: 60px;
48 height: 60px;
49 font-size: 24px;
50 cursor: pointer;
51 box-shadow: 0 2px 10px rgba(0,0,0,0.3);
52 transition: all 0.3s ease;
53 }
54
55 .vfs-floating-btn:hover {
56 transform: scale(1.1);
57 box-shadow: 0 4px 20px rgba(0,0,0,0.4);
58 }
59
60 .vfs-autofill-container {
61 position: fixed;
62 bottom: 100px;
63 right: 20px;
64 z-index: 9998;
65 background: white;
66 border-radius: 10px;
67 box-shadow: 0 4px 20px rgba(0,0,0,0.3);
68 padding: 20px;
69 width: 300px;
70 font-family: Arial, sans-serif;
71 display: none;
72 }
73
74 .vfs-autofill-header {
75 display: flex;
76 justify-content: space-between;
77 align-items: center;
78 margin-bottom: 15px;
79 border-bottom: 1px solid #eee;
80 padding-bottom: 10px;
81 }
82
83 .vfs-autofill-header span {
84 font-weight: bold;
85 font-size: 18px;
86 color: #333;
87 }
88
89 .vfs-close-btn {
90 background: none;
91 border: none;
92 font-size: 24px;
93 cursor: pointer;
94 color: #999;
95 }
96
97 .vfs-autofill-btn, .vfs-settings-btn, .vfs-save-btn {
98 width: 100%;
99 padding: 12px;
100 margin: 10px 0;
101 border: none;
102 border-radius: 5px;
103 cursor: pointer;
104 font-weight: bold;
105 }
106
107 .vfs-autofill-btn {
108 background: #0066cc;
109 color: white;
110 }
111
112 .vfs-settings-btn {
113 background: #f0f0f0;
114 color: #333;
115 }
116
117 .vfs-save-btn {
118 background: #4CAF50;
119 color: white;
120 }
121
122 .vfs-form-group {
123 margin-bottom: 15px;
124 }
125
126 .vfs-form-group label {
127 display: block;
128 margin-bottom: 5px;
129 font-weight: bold;
130 color: #555;
131 }
132
133 .vfs-form-group input {
134 width: 100%;
135 padding: 10px;
136 border: 1px solid #ddd;
137 border-radius: 5px;
138 box-sizing: border-box;
139 }
140
141 #vfs-status {
142 margin-top: 15px;
143 padding: 10px;
144 border-radius: 5px;
145 text-align: center;
146 display: none;
147 }
148
149 .vfs-success {
150 background: #d4edda;
151 color: #155724;
152 border: 1px solid #c3e6cb;
153 }
154
155 .vfs-error {
156 background: #f8d7da;
157 color: #721c24;
158 border: 1px solid #f5c6cb;
159 }
160 `;
161 document.head.appendChild(style);
162 }
163
164 // Add floating button for auto-fill
165 function addFloatingButton() {
166 const button = document.createElement('button');
167 button.className = 'vfs-floating-btn';
168 button.innerHTML = '🚀';
169 button.title = 'VFS Visa Assistant';
170 document.body.appendChild(button);
171 }
172
173 // Add control panel for bot operations
174 function addControlPanel() {
175 const panel = document.createElement('div');
176 panel.id = 'neonControlPanel';
177 panel.innerHTML = `
178 <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;">
179 <div style="width: 12px; height: 12px; border-radius: 50%; box-shadow: blue 0px 0px 10px; color: blue; background: blue;"></div>
180 <div style="color: white; font-size: 18px; font-weight: bold; text-align: center; flex: 1 1 0%; margin: 0px 8px; text-shadow: rgb(255, 255, 255) 0px 0px 5px, rgb(255, 255, 255) 0px 0px 10px;">OPT + LOGIN BOT</div>
181 <div style="width: 12px; height: 12px; border-radius: 50%; box-shadow: none; color: red; background: transparent;"></div>
182 </div>
183 <button style="width: 100%; margin: 5px 0px; padding: 6px; background: linear-gradient(90deg, rgb(0, 255, 85), rgb(0, 170, 51)); color: white; border: none; border-radius: 6px; cursor: pointer; font-weight: bold; box-shadow: rgb(0, 255, 85) 0px 0px 8px, rgb(0, 170, 51) 0px 0px 12px;">▶ Start Bot</button>
184 <button style="width: 100%; margin: 5px 0px; padding: 6px; background: linear-gradient(90deg, rgb(255, 0, 0), rgb(255, 85, 85)); color: white; border: none; border-radius: 6px; cursor: pointer; font-weight: bold; box-shadow: rgb(255, 0, 0) 0px 0px 8px, rgb(255, 85, 85) 0px 0px 12px;">🔄 Switch Account</button>
185 <button style="width: 100%; margin: 5px 0px; padding: 6px; background: linear-gradient(90deg, rgb(255, 255, 0), rgb(255, 234, 0)); color: black; border: none; border-radius: 6px; cursor: pointer; font-weight: bold; box-shadow: rgb(255, 255, 0) 0px 0px 8px, rgb(255, 234, 0) 0px 0px 12px;">❌ Close Panel</button>
186 <div style="display: none; max-height: 150px; overflow-y: auto; border: 1px solid rgb(0, 255, 102); margin-top: 5px; border-radius: 7px; background: rgb(2, 26, 12);">
187 <div style="padding: 5px; cursor: pointer; border-bottom: 1px solid rgba(0, 255, 102, 0.2); color: rgb(245, 230, 165);">yasar004@dollicons.com</div>
188 <div style="padding: 5px; cursor: pointer; border-bottom: 1px solid rgba(0, 255, 102, 0.2); color: rgb(245, 230, 165);">yasar005@dollicons.com</div>
189 <div style="padding: 5px; cursor: pointer; border-bottom: 1px solid rgba(0, 255, 102, 0.2); color: rgb(245, 230, 165);">yasar006@dollicons.com</div>
190 </div>
191 `;
192 panel.style.cssText = 'position: fixed; bottom: 100px; left: 0px; width: 210px; background: rgb(2, 26, 12); color: white; padding: 12px; border-radius: 15px; box-shadow: rgb(0, 255, 102) 0px 0px 20px, rgb(0, 255, 102) 0px 0px 40px, rgb(0, 255, 102) 0px 0px 60px; z-index: 999999; font-family: Scheherazade, serif; border: 3px solid rgb(0, 255, 102);';
193 document.body.appendChild(panel);
194 }
195
196 // Add auto-fill container for form data
197 function addAutoFillContainer() {
198 const container = document.createElement('div');
199 container.className = 'vfs-autofill-container';
200 container.id = 'vfs-autofill-container';
201 container.innerHTML = `
202 <div class="vfs-autofill-header">
203 <span>VFS Auto-Filler</span>
204 <button class="vfs-close-btn" id="vfs-close">×</button>
205 </div>
206 <button class="vfs-autofill-btn" id="vfs-fill-btn">Fill Form Now</button>
207 <button class="vfs-settings-btn" id="vfs-settings-btn">⚙️ Edit Saved Data</button>
208 <div id="vfs-settings-panel" style="display: none; margin-top: 15px; border-top: 1px solid #ddd; padding-top: 15px;">
209 <div class="vfs-form-group">
210 <label>Email:</label>
211 <input type="text" id="vfs-email" placeholder="Enter email">
212 </div>
213 <div class="vfs-form-group">
214 <label>Password:</label>
215 <input type="password" id="vfs-password" placeholder="Enter password">
216 </div>
217 <div class="vfs-form-group">
218 <label>First Name:</label>
219 <input type="text" id="vfs-firstname" placeholder="Enter first name">
220 </div>
221 <div class="vfs-form-group">
222 <label>Last Name:</label>
223 <input type="text" id="vfs-lastname" placeholder="Enter last name">
224 </div>
225 <div class="vfs-form-group">
226 <label>Passport Number:</label>
227 <input type="text" id="vfs-passport" placeholder="Enter passport number">
228 </div>
229 <div class="vfs-form-group">
230 <label>Nationality:</label>
231 <input type="text" id="vfs-nationality" placeholder="e.g., Algeria">
232 </div>
233 <button class="vfs-save-btn" id="vfs-save-btn">💾 Save Data</button>
234 </div>
235 <div id="vfs-status"></div>
236 `;
237 document.body.appendChild(container);
238 }
239
240 // Set up event listeners
241 function setupEventListeners() {
242 // Floating button click
243 document.addEventListener('click', function(e) {
244 if (e.target.closest('.vfs-floating-btn')) {
245 const container = document.getElementById('vfs-autofill-container');
246 container.style.display = container.style.display === 'block' ? 'none' : 'block';
247 }
248 });
249
250 // Close button
251 document.addEventListener('click', function(e) {
252 if (e.target.id === 'vfs-close') {
253 document.getElementById('vfs-autofill-container').style.display = 'none';
254 }
255 });
256
257 // Settings button
258 document.addEventListener('click', function(e) {
259 if (e.target.id === 'vfs-settings-btn') {
260 const panel = document.getElementById('vfs-settings-panel');
261 panel.style.display = panel.style.display === 'block' ? 'none' : 'block';
262 }
263 });
264
265 // Save button
266 document.addEventListener('click', function(e) {
267 if (e.target.id === 'vfs-save-btn') {
268 saveData();
269 }
270 });
271
272 // Fill button
273 document.addEventListener('click', function(e) {
274 if (e.target.id === 'vfs-fill-btn') {
275 fillForm();
276 }
277 });
278
279 // Control panel buttons
280 document.addEventListener('click', function(e) {
281 const panel = document.getElementById('neonControlPanel');
282 if (panel) {
283 if (e.target.textContent.includes('Start Bot')) {
284 autoLogin();
285 } else if (e.target.textContent.includes('Switch Account')) {
286 switchAccount();
287 } else if (e.target.textContent.includes('Close Panel')) {
288 panel.style.display = 'none';
289 }
290 }
291 });
292 }
293
294 // Load saved data
295 async function loadSavedData() {
296 try {
297 const savedData = await GM.getValue('vfs_saved_data', '{}');
298 const data = JSON.parse(savedData);
299
300 if (data.email) document.getElementById('vfs-email').value = data.email;
301 if (data.password) document.getElementById('vfs-password').value = data.password;
302 if (data.firstName) document.getElementById('vfs-firstname').value = data.firstName;
303 if (data.lastName) document.getElementById('vfs-lastname').value = data.lastName;
304 if (data.passport) document.getElementById('vfs-passport').value = data.passport;
305 if (data.nationality) document.getElementById('vfs-nationality').value = data.nationality;
306 } catch (error) {
307 console.error('Error loading saved data:', error);
308 }
309 }
310
311 // Save data
312 async function saveData() {
313 try {
314 const data = {
315 email: document.getElementById('vfs-email').value,
316 password: document.getElementById('vfs-password').value,
317 firstName: document.getElementById('vfs-firstname').value,
318 lastName: document.getElementById('vfs-lastname').value,
319 passport: document.getElementById('vfs-passport').value,
320 nationality: document.getElementById('vfs-nationality').value
321 };
322
323 await GM.setValue('vfs_saved_data', JSON.stringify(data));
324 showStatus('Data saved successfully!', 'success');
325 } catch (error) {
326 console.error('Error saving data:', error);
327 showStatus('Error saving data', 'error');
328 }
329 }
330
331 // Show status message
332 function showStatus(message, type) {
333 const statusDiv = document.getElementById('vfs-status');
334 statusDiv.textContent = message;
335 statusDiv.className = type === 'success' ? 'vfs-success' : 'vfs-error';
336 statusDiv.style.display = 'block';
337
338 setTimeout(() => {
339 statusDiv.style.display = 'none';
340 }, 3000);
341 }
342
343 // Fill form with saved data
344 async function fillForm() {
345 try {
346 // Get saved data
347 const savedData = await GM.getValue('vfs_saved_data', '{}');
348 const data = JSON.parse(savedData);
349
350 // Check if we're on the login page
351 const emailField = document.getElementById('email');
352 const passwordField = document.getElementById('password');
353
354 if (emailField && passwordField) {
355 // Fill login form
356 if (data.email) emailField.value = data.email;
357 if (data.password) passwordField.value = data.password;
358
359 showStatus('Login form filled! Click Sign In to proceed.', 'success');
360 return;
361 }
362
363 // Check if we're on the OTP page
364 const otpField = document.querySelector('input[formcontrolname="otp"]');
365 if (otpField) {
366 // We're on the OTP page, show a message to the user
367 showStatus('Please enter your OTP manually for security reasons.', 'success');
368 return;
369 }
370
371 // Try to fill application form fields
372 fillApplicationForm(data);
373
374 } catch (error) {
375 console.error('Error filling form:', error);
376 showStatus('Error filling form', 'error');
377 }
378 }
379
380 // Fill application form fields
381 function fillApplicationForm(data) {
382 // Common field selectors for VFS application forms
383 const fieldSelectors = {
384 firstName: ['input[name="firstName"]', 'input[name="first_name"]', '#firstName'],
385 lastName: ['input[name="lastName"]', 'input[name="last_name"]', '#lastName'],
386 passport: ['input[name="passport"]', 'input[name="passportNumber"]', '#passportNumber'],
387 nationality: ['select[name="nationality"]', 'input[name="nationality"]', '#nationality']
388 };
389
390 let filledCount = 0;
391
392 // Fill each field if data exists
393 for (const [key, selectors] of Object.entries(fieldSelectors)) {
394 if (data[key]) {
395 for (const selector of selectors) {
396 const field = document.querySelector(selector);
397 if (field) {
398 field.value = data[key];
399 filledCount++;
400 break;
401 }
402 }
403 }
404 }
405
406 if (filledCount > 0) {
407 showStatus(`Filled ${filledCount} fields successfully!`, 'success');
408 } else {
409 showStatus('No matching fields found to fill', 'error');
410 }
411 }
412
413 // Auto login function
414 async function autoLogin() {
415 try {
416 const savedData = await GM.getValue('vfs_saved_data', '{}');
417 const data = JSON.parse(savedData);
418
419 const emailField = document.getElementById('email');
420 const passwordField = document.getElementById('password');
421 const signInButton = Array.from(document.querySelectorAll('button')).find(btn =>
422 btn.textContent.trim().toLowerCase().includes('sign in'));
423
424 if (emailField && passwordField && data.email && data.password) {
425 emailField.value = data.email;
426 passwordField.value = data.password;
427
428 if (signInButton) {
429 signInButton.click();
430 showStatus('Auto login initiated!', 'success');
431 } else {
432 showStatus('Sign in button not found', 'error');
433 }
434 } else {
435 showStatus('Missing email or password', 'error');
436 }
437 } catch (error) {
438 console.error('Error during auto login:', error);
439 showStatus('Auto login failed', 'error');
440 }
441 }
442
443 // Switch account function
444 function switchAccount() {
445 // Clear current form
446 const emailField = document.getElementById('email');
447 const passwordField = document.getElementById('password');
448
449 if (emailField) emailField.value = '';
450 if (passwordField) passwordField.value = '';
451
452 // Show account selection
453 const accountList = document.querySelector('#neonControlPanel div[style*="display: none"]');
454 if (accountList) {
455 accountList.style.display = 'block';
456 }
457
458 showStatus('Please select an account', 'success');
459 }
460
461 // Initialize the assistant when the page loads
462 if (document.readyState === 'loading') {
463 document.addEventListener('DOMContentLoaded', init);
464 } else {
465 init();
466 }
467})();