gcharanteja commited on
Commit
6ad81dc
·
1 Parent(s): cbde997
Files changed (1) hide show
  1. server.js +46 -20
server.js CHANGED
@@ -33,23 +33,23 @@ app.get("/hello", (req, res) => {
33
  res.send("hello world pal");
34
  });
35
 
 
 
 
36
  function fetchSecret(key) {
 
37
  return new Promise((resolve, reject) => {
38
  const url = `${API_BASE}/${key}`;
39
-
40
- https
41
  .get(
42
  url,
43
  { headers: { accept: "application/json", "X-API-Key": API_KEY } },
44
  (res) => {
45
  let data = "";
46
-
47
- res.on("data", (chunk) => {
48
- data += chunk;
49
- });
50
-
51
  res.on("end", () => {
52
  try {
 
53
  resolve(JSON.parse(data).value);
54
  } catch (error) {
55
  reject(new Error(`Failed to parse response for ${key}: ${data}`));
@@ -57,7 +57,14 @@ function fetchSecret(key) {
57
  });
58
  },
59
  )
60
- .on("error", reject);
 
 
 
 
 
 
 
61
  });
62
  }
63
 
@@ -82,21 +89,29 @@ function writeState(state) {
82
  }
83
 
84
  async function sendEmail(subject, body) {
 
85
  const cfg = await getSmtpConfig();
 
86
 
87
  const transporter = nodemailer.createTransport({
88
  host: cfg.host,
89
  port: cfg.port,
90
  secure: cfg.port === 465,
91
  auth: { user: cfg.user, pass: cfg.pass },
 
 
 
92
  });
93
 
94
- return transporter.sendMail({
 
95
  from: cfg.from,
96
  to: cfg.to,
97
  subject,
98
  text: body,
99
  });
 
 
100
  }
101
 
102
  function valuesChanged(oldVals, newVals) {
@@ -108,7 +123,9 @@ function valuesChanged(oldVals, newVals) {
108
  }
109
 
110
  async function scrape() {
 
111
  const browser = await firefox.launch({ headless: true });
 
112
 
113
  try {
114
  const context = await browser.newContext({
@@ -118,7 +135,9 @@ async function scrape() {
118
 
119
  const page = await context.newPage();
120
 
 
121
  await page.goto(URL, { waitUntil: "domcontentloaded", timeout: 60000 });
 
122
 
123
  const title = await page.title();
124
  if (title === "Access Denied") {
@@ -170,16 +189,17 @@ async function scrape() {
170
  }
171
 
172
  async function main() {
173
- console.log(`[${new Date().toISOString()}] Checking visa ballot...`);
174
 
175
  const current = await scrape();
176
  if (!current) {
177
- console.log("Scrape failed, will retry next run");
178
  return;
179
  }
180
 
181
- console.log("Current India values:", current);
182
 
 
183
  const state = readState();
184
  const prevIndia = state.india || {
185
  selection1: "TBA",
@@ -191,8 +211,11 @@ async function main() {
191
 
192
  let emailSent = false;
193
 
 
 
 
194
  if (changed) {
195
- console.log("Values changed! Sending alert email.");
196
 
197
  const subject = "[Visa Alert] India ballot values changed";
198
  const body = `India Work and Holiday ballot values have changed:
@@ -205,10 +228,10 @@ async function main() {
205
 
206
  try {
207
  await sendEmail(subject, body);
208
- console.log("Change alert email sent");
209
  emailSent = true;
210
  } catch (error) {
211
- console.error("Failed to send change email:", error.message);
212
  }
213
 
214
  state.lastChangeTime = new Date().toISOString();
@@ -223,7 +246,7 @@ async function main() {
223
  const hoursSinceLastDaily = (now - lastDailyEmail) / 3600000;
224
 
225
  if (allStillTba && hoursSinceLastDaily >= 24) {
226
- console.log("Still TBA - sending daily status email");
227
 
228
  try {
229
  await sendEmail(
@@ -236,11 +259,11 @@ async function main() {
236
 
237
  Check: ${URL}`,
238
  );
239
- console.log("Daily status email sent");
240
  emailSent = true;
241
  state.lastDailyEmailTime = new Date().toISOString();
242
  } catch (error) {
243
- console.error("Failed to send daily email:", error.message);
244
  }
245
  }
246
  }
@@ -248,9 +271,11 @@ async function main() {
248
  state.india = current;
249
  state.lastCheckTime = new Date().toISOString();
250
  if (emailSent) state.lastEmailTime = new Date().toISOString();
 
251
  writeState(state);
 
252
 
253
- console.log("Done");
254
  }
255
 
256
  const isDirectRun =
@@ -263,7 +288,8 @@ if (isDirectRun) {
263
  });
264
 
265
  main().catch((error) => {
266
- console.error("Fatal error:", error);
 
267
  process.exit(1);
268
  });
269
  }
 
33
  res.send("hello world pal");
34
  });
35
 
36
+ const log = (msg) => console.log(`[${new Date().toISOString()}] ${msg}`);
37
+ const err = (msg) => console.error(`[${new Date().toISOString()}] ${msg}`);
38
+
39
  function fetchSecret(key) {
40
+ log(`Fetching secret: ${key}`);
41
  return new Promise((resolve, reject) => {
42
  const url = `${API_BASE}/${key}`;
43
+ const req = https
 
44
  .get(
45
  url,
46
  { headers: { accept: "application/json", "X-API-Key": API_KEY } },
47
  (res) => {
48
  let data = "";
49
+ res.on("data", (chunk) => { data += chunk; });
 
 
 
 
50
  res.on("end", () => {
51
  try {
52
+ log(`Secret ${key} fetched OK`);
53
  resolve(JSON.parse(data).value);
54
  } catch (error) {
55
  reject(new Error(`Failed to parse response for ${key}: ${data}`));
 
57
  });
58
  },
59
  )
60
+ .on("error", (e) => {
61
+ err(`Secret fetch failed for ${key}: ${e.message}`);
62
+ reject(e);
63
+ });
64
+ req.setTimeout(15000, () => {
65
+ req.destroy();
66
+ reject(new Error(`Timeout fetching secret ${key}`));
67
+ });
68
  });
69
  }
70
 
 
89
  }
90
 
91
  async function sendEmail(subject, body) {
92
+ log("Fetching SMTP config...");
93
  const cfg = await getSmtpConfig();
94
+ log(`SMTP config loaded (host=${cfg.host}, port=${cfg.port}, from=${cfg.from}, to=${cfg.to})`);
95
 
96
  const transporter = nodemailer.createTransport({
97
  host: cfg.host,
98
  port: cfg.port,
99
  secure: cfg.port === 465,
100
  auth: { user: cfg.user, pass: cfg.pass },
101
+ connectionTimeout: 30000,
102
+ greetingTimeout: 30000,
103
+ socketTimeout: 60000,
104
  });
105
 
106
+ log("Sending email...");
107
+ const result = await transporter.sendMail({
108
  from: cfg.from,
109
  to: cfg.to,
110
  subject,
111
  text: body,
112
  });
113
+ log(`Email sent (messageId=${result.messageId})`);
114
+ return result;
115
  }
116
 
117
  function valuesChanged(oldVals, newVals) {
 
123
  }
124
 
125
  async function scrape() {
126
+ log("Launching Firefox browser...");
127
  const browser = await firefox.launch({ headless: true });
128
+ log("Browser launched");
129
 
130
  try {
131
  const context = await browser.newContext({
 
135
 
136
  const page = await context.newPage();
137
 
138
+ log(`Navigating to ${URL}...`);
139
  await page.goto(URL, { waitUntil: "domcontentloaded", timeout: 60000 });
140
+ log("Page loaded");
141
 
142
  const title = await page.title();
143
  if (title === "Access Denied") {
 
189
  }
190
 
191
  async function main() {
192
+ log("=== Starting visa ballot check ===");
193
 
194
  const current = await scrape();
195
  if (!current) {
196
+ log("Scrape failed (null returned), will retry next run");
197
  return;
198
  }
199
 
200
+ log(`Scraped India values: ${JSON.stringify(current)}`);
201
 
202
+ log("Reading saved state...");
203
  const state = readState();
204
  const prevIndia = state.india || {
205
  selection1: "TBA",
 
211
 
212
  let emailSent = false;
213
 
214
+ log(`Prev India values: ${JSON.stringify(prevIndia)}`);
215
+ log(`Changed: ${changed}`);
216
+
217
  if (changed) {
218
+ log("Values changed! Sending alert email.");
219
 
220
  const subject = "[Visa Alert] India ballot values changed";
221
  const body = `India Work and Holiday ballot values have changed:
 
228
 
229
  try {
230
  await sendEmail(subject, body);
231
+ log("Change alert email sent");
232
  emailSent = true;
233
  } catch (error) {
234
+ err(`Failed to send change email: ${error.message}`);
235
  }
236
 
237
  state.lastChangeTime = new Date().toISOString();
 
246
  const hoursSinceLastDaily = (now - lastDailyEmail) / 3600000;
247
 
248
  if (allStillTba && hoursSinceLastDaily >= 24) {
249
+ log("Still TBA and 24h since last daily email - sending daily status");
250
 
251
  try {
252
  await sendEmail(
 
259
 
260
  Check: ${URL}`,
261
  );
262
+ log("Daily status email sent");
263
  emailSent = true;
264
  state.lastDailyEmailTime = new Date().toISOString();
265
  } catch (error) {
266
+ err(`Failed to send daily email: ${error.message}`);
267
  }
268
  }
269
  }
 
271
  state.india = current;
272
  state.lastCheckTime = new Date().toISOString();
273
  if (emailSent) state.lastEmailTime = new Date().toISOString();
274
+ log("Writing state to disk...");
275
  writeState(state);
276
+ log("State saved");
277
 
278
+ log("=== Visa ballot check complete ===");
279
  }
280
 
281
  const isDirectRun =
 
288
  });
289
 
290
  main().catch((error) => {
291
+ err(`Fatal error: ${error.message}`);
292
+ if (error.stack) err(error.stack);
293
  process.exit(1);
294
  });
295
  }