coffeeinabit 0.0.26 → 0.0.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -543,7 +543,6 @@ export class LinkedInAutomation {
543
543
  try {
544
544
  const screenshot = await this.page.screenshot({
545
545
  fullPage: false,
546
- clip: { x: 0, y: 0, width: 1200, height: 800 },
547
546
  type: 'png',
548
547
  timeout: 60000
549
548
  });
@@ -963,7 +962,7 @@ export class LinkedInAutomation {
963
962
 
964
963
  const launchOptions = {
965
964
  headless: this.headless || false,
966
- viewport: null,
965
+ viewport: (this.headless || false) ? { width: 1920, height: 1080 } : null,
967
966
  ignoreHTTPSErrors: true,
968
967
  args: [
969
968
  '--disable-blink-features=AutomationControlled',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coffeeinabit",
3
- "version": "0.0.26",
3
+ "version": "0.0.27",
4
4
  "description": "CoffeeInABit App",
5
5
  "main": "server.js",
6
6
  "type": "module",
@@ -110,7 +110,7 @@
110
110
  <small class="text-muted" id="screenshotTimestamp">Last updated: --</small>
111
111
  </div>
112
112
  <div class="text-center">
113
- <img id="browserScreenshot" class="img-fluid border rounded shadow-sm" style="max-width: 100%; max-height: 400px;" alt="Browser Screenshot">
113
+ <img id="browserScreenshot" class="img-fluid border rounded shadow-sm" style="max-width: 100%; max-height: 400px; object-fit: contain;" alt="Browser Screenshot">
114
114
  </div>
115
115
  </div>
116
116
  </div>
@@ -44,7 +44,7 @@ export async function executeCommentPost(page, action) {
44
44
  }
45
45
  await waitRandom(1200, 3200, page);
46
46
  console.log('[CommentPost] Scrolling to middle of page');
47
- await page.evaluate(() => { window.scrollTo(0, document.body.scrollHeight / 2); });
47
+ await page.evaluate(function() { window.scrollTo(0, document.body.scrollHeight / 2); });
48
48
  await waitRandom(900, 2100, page);
49
49
 
50
50
  console.log('[CommentPost] Searching for comment editor');
@@ -17,7 +17,7 @@ export async function executeGetDailyLinkedInConnections(page, action) {
17
17
 
18
18
  await new Promise(resolve => setTimeout(resolve, Math.floor(Math.random() * 5000) + 500));
19
19
 
20
- const totalConnections = await page.evaluate(() => {
20
+ const totalConnections = await page.evaluate(function() {
21
21
  const headerElement = document.querySelector('h1');
22
22
  if (headerElement) {
23
23
  const match = headerElement.textContent.match(/(\d+)\s+Connections?/i);
@@ -33,7 +33,7 @@ export async function executeGetDailyLinkedInConnections(page, action) {
33
33
  const maxNoScrollAttempts = 2;
34
34
 
35
35
  while (!shouldStopScrolling) {
36
- const currentConnections = await page.evaluate(() => {
36
+ const currentConnections = await page.evaluate(function() {
37
37
  function parseConnectionDate(str) {
38
38
  if (!str) return null;
39
39
  const match = str.match(/Connected on (.+)/i);
@@ -98,7 +98,7 @@ export async function executeGetDailyLinkedInConnections(page, action) {
98
98
  }
99
99
  }
100
100
 
101
- const scrollInfoBefore = await page.evaluate(() => {
101
+ const scrollInfoBefore = await page.evaluate(function() {
102
102
  const main = document.querySelector('main');
103
103
  if (main) {
104
104
  return {
@@ -123,7 +123,7 @@ export async function executeGetDailyLinkedInConnections(page, action) {
123
123
  const containerExists = await mainElement.count();
124
124
 
125
125
  if (containerExists > 0) {
126
- await mainElement.evaluate(el => {
126
+ await mainElement.evaluate(function(el) {
127
127
  console.log('Main element found, scrolling...');
128
128
  console.log('Main scrollHeight:', el.scrollHeight);
129
129
  console.log('Main clientHeight:', el.clientHeight);
@@ -145,7 +145,7 @@ export async function executeGetDailyLinkedInConnections(page, action) {
145
145
  console.log('Stack trace:', e.stack);
146
146
  }
147
147
 
148
- const scrollInfoAfter = await page.evaluate(() => {
148
+ const scrollInfoAfter = await page.evaluate(function() {
149
149
  const main = document.querySelector('main');
150
150
  if (main) {
151
151
  return {
@@ -34,9 +34,9 @@ export async function executeGetMessages(page, action) {
34
34
  await waitRandom(900, 1400, page);
35
35
  await waitRandom(1600, 2600, page);
36
36
 
37
- await page.evaluate(() => { window.scrollTo(0, 0); });
37
+ await page.evaluate(function() { window.scrollTo(0, 0); });
38
38
  await waitRandom(400, 650, page);
39
- await page.evaluate(() => { window.scrollTo(0, 300); });
39
+ await page.evaluate(function() { window.scrollTo(0, 300); });
40
40
  await waitRandom(900, 1500, page);
41
41
 
42
42
  console.log('[get_messages] Closing all conversation bubbles');
@@ -199,7 +199,7 @@ export async function executeGetMessages(page, action) {
199
199
  await new Promise(resolve => setTimeout(resolve, Math.floor(Math.random() * 2000) + 1000));
200
200
 
201
201
  console.log('[get_messages] Looking for message input by aria-label');
202
- const messageData = await page.evaluate(() => {
202
+ const messageData = await page.evaluate(function() {
203
203
  const messageInput = document.querySelector('[aria-label="Write a message…"]');
204
204
  if (!messageInput) {
205
205
  console.log('[get_messages] Message input not found');
@@ -251,7 +251,7 @@ export async function executeGetMessages(page, action) {
251
251
 
252
252
  if (!messageData.found) {
253
253
  console.log('[get_messages] Fallback: trying to find message list directly');
254
- const fallbackData = await page.evaluate(() => {
254
+ const fallbackData = await page.evaluate(function() {
255
255
  const messageList = document.querySelector('.msg-s-message-list-container');
256
256
  if (messageList) {
257
257
  const content = messageList.innerText || messageList.textContent || '';
@@ -343,7 +343,7 @@ async function getButtonByText(page, text, inMain = false) {
343
343
 
344
344
  async function closeAllConversationBubbles(page) {
345
345
  console.log('[get_messages] Closing all conversation bubbles');
346
- await page.evaluate(() => {
346
+ await page.evaluate(function() {
347
347
  const allButtons = document.querySelectorAll('button');
348
348
  const closeButtons = Array.from(allButtons).filter(btn => {
349
349
  const useElement = btn.querySelector('svg use[href="#close-small"]');
@@ -239,7 +239,7 @@ export async function executeGetNewMessages(page, action, accessToken) {
239
239
 
240
240
 
241
241
  for (let i = 0; i < 5; i++) {
242
- await messageContainer.evaluate(el => {
242
+ await messageContainer.evaluate(function(el) {
243
243
  el.scrollBy({ top: -2000, behavior: 'smooth' });
244
244
  });
245
245
  console.log(`[GetNewMessages] Scrolled up -2000px (${i + 1}/5)`);
@@ -86,15 +86,45 @@ export async function executeGetProfile(page, action) {
86
86
  await new Promise(resolve => setTimeout(resolve, 2000));
87
87
  console.log('[GetProfile] Page fully loaded, starting to scroll and extract content');
88
88
 
89
+ try {
90
+ await page.waitForLoadState('networkidle', { timeout: 10000 }).catch(() => {});
91
+ } catch (error) {
92
+ console.warn('[GetProfile] Network idle timeout, continuing anyway');
93
+ }
94
+
89
95
  console.log('[GetProfile] Scrolling down to load profile content');
90
- await gentleScroll(page, 'down');
96
+ try {
97
+ await gentleScroll(page, 'down');
98
+ } catch (error) {
99
+ if (error.message.includes('well-serializable')) {
100
+ console.error('[GetProfile] Serialization error in gentleScroll, trying alternative scroll method');
101
+ await page.evaluate(function() {
102
+ window.scrollTo(0, document.documentElement.scrollHeight);
103
+ });
104
+ await waitRandom(500, 1000, page);
105
+ } else {
106
+ throw error;
107
+ }
108
+ }
91
109
  await waitRandom(260, 480, page);
92
110
  console.log('[GetProfile] Scrolling up');
93
- await gentleScroll(page, 'up');
111
+ try {
112
+ await gentleScroll(page, 'up');
113
+ } catch (error) {
114
+ if (error.message.includes('well-serializable')) {
115
+ console.error('[GetProfile] Serialization error in gentleScroll (up), trying alternative scroll method');
116
+ await page.evaluate(function() {
117
+ window.scrollTo(0, 0);
118
+ });
119
+ await waitRandom(300, 500, page);
120
+ } else {
121
+ throw error;
122
+ }
123
+ }
94
124
  await waitRandom(240, 420, page);
95
125
  console.log('[GetProfile] Extracting profile text content');
96
126
 
97
- const profileText = await page.evaluate(() => {
127
+ const profileText = await page.evaluate(function() {
98
128
  const mainContent = document.querySelector('main');
99
129
  if (!mainContent) return '';
100
130
  function getAllText(element) {
@@ -141,7 +171,7 @@ export async function executeGetProfile(page, action) {
141
171
  await gentleScroll(page, 'down', { stepRange: [140, 260], pauseRange: [80, 160], maxIterations: 40 });
142
172
  console.log('[GetProfile] Extracting recent posts');
143
173
 
144
- recentPosts = await page.evaluate(() => {
174
+ recentPosts = await page.evaluate(function() {
145
175
  const mainContent = document.querySelector('main');
146
176
  if (!mainContent) return {};
147
177
  const postContainers = mainContent.querySelectorAll('article, [data-urn*="activity"], .feed-shared-update-v2, .feed-shared-text');
@@ -241,7 +271,7 @@ async function getDropdownOptions(page) {
241
271
  }
242
272
  await new Promise(resolve => setTimeout(resolve, 1000));
243
273
 
244
- const dropdownOptions = await page.evaluate(() => {
274
+ const dropdownOptions = await page.evaluate(function() {
245
275
  const options = [];
246
276
  const dropdownItems = document.querySelectorAll('[role="menuitem"], [role="option"], .artdeco-dropdown__content-inner li, .artdeco-dropdown__content-inner button');
247
277
 
@@ -286,15 +316,30 @@ async function gentleScroll(page, direction = 'down', options = {}) {
286
316
  const stepRange = options.stepRange || [180, 320];
287
317
  const pauseRange = options.pauseRange || [90, 180];
288
318
  const maxIterations = options.maxIterations || 50;
289
- let { position, target } = await page.evaluate((isDown) => {
290
- const doc = document.documentElement;
291
- const start = window.scrollY || doc.scrollTop || 0;
292
- const limit = Math.max(doc.scrollHeight - window.innerHeight, 0);
293
- return {
294
- position: start,
295
- target: isDown ? limit : 0
296
- };
297
- }, down);
319
+
320
+ let position = 0;
321
+ let target = 0;
322
+
323
+ try {
324
+ const scrollInfo = await page.evaluate(function() {
325
+ const doc = document.documentElement;
326
+ const start = window.scrollY || doc.scrollTop || 0;
327
+ const limit = Math.max(doc.scrollHeight - window.innerHeight, 0);
328
+ return {
329
+ position: start,
330
+ target: limit
331
+ };
332
+ });
333
+ position = scrollInfo.position;
334
+ target = down ? scrollInfo.target : 0;
335
+ } catch (error) {
336
+ console.warn('[GetProfile] Error getting scroll position, using mouse wheel instead');
337
+ for (let i = 0; i < 10; i++) {
338
+ await page.mouse.wheel(0, down ? 300 : -300);
339
+ await waitRandom(pauseRange[0], pauseRange[1], page);
340
+ }
341
+ return;
342
+ }
298
343
 
299
344
  let iterations = 0;
300
345
  while ((down && position < target - 1) || (!down && position > 1)) {
@@ -302,16 +347,22 @@ async function gentleScroll(page, direction = 'down', options = {}) {
302
347
  Math.abs(target - position),
303
348
  Math.floor(randomBetween(stepRange[0], stepRange[1]))
304
349
  );
305
- position = await page.evaluate(({ isDown, shift }) => {
306
- const doc = document.documentElement;
307
- const current = window.scrollY || doc.scrollTop || 0;
308
- const limit = Math.max(doc.scrollHeight - window.innerHeight, 0);
309
- const next = isDown
310
- ? Math.min(current + shift, limit)
311
- : Math.max(current - shift, 0);
312
- window.scrollTo(0, next);
313
- return next;
314
- }, { isDown: down, shift: delta });
350
+
351
+ try {
352
+ const scrollDelta = down ? delta : -delta;
353
+ await page.mouse.wheel(0, scrollDelta);
354
+
355
+ position = await page.evaluate(function() {
356
+ return window.scrollY || document.documentElement.scrollTop || 0;
357
+ });
358
+ } catch (error) {
359
+ if (error.message.includes('well-serializable')) {
360
+ await page.mouse.wheel(0, down ? delta : -delta);
361
+ } else {
362
+ throw error;
363
+ }
364
+ }
365
+
315
366
  await waitRandom(pauseRange[0], pauseRange[1], page);
316
367
  iterations += 1;
317
368
  if (iterations >= maxIterations) {
@@ -24,10 +24,12 @@ const getViewportSize = async (page) => {
24
24
  return viewportGetter;
25
25
  }
26
26
  try {
27
- return await page.evaluate(() => ({
28
- width: window.innerWidth,
29
- height: window.innerHeight
30
- }));
27
+ return await page.evaluate(function() {
28
+ return {
29
+ width: window.innerWidth,
30
+ height: window.innerHeight
31
+ };
32
+ });
31
33
  } catch (_) {
32
34
  return { width: 1280, height: 720 };
33
35
  }
@@ -175,10 +177,12 @@ export const humanLikeAmbientMove = async (page) => {
175
177
 
176
178
  let viewport = page.viewportSize();
177
179
  if (!viewport) {
178
- viewport = await page.evaluate(() => ({
179
- width: window.innerWidth,
180
- height: window.innerHeight
181
- })).catch(() => ({ width: 1280, height: 720 }));
180
+ viewport = await page.evaluate(function() {
181
+ return {
182
+ width: window.innerWidth,
183
+ height: window.innerHeight
184
+ };
185
+ }).catch(() => ({ width: 1280, height: 720 }));
182
186
  }
183
187
 
184
188
  const safeMargin = 80;
@@ -31,7 +31,7 @@ export async function executeSendConnectionRequest(page, action) {
31
31
  await waitRandom(1700, 2600, page);
32
32
 
33
33
  console.log('[SendConnectionRequest] Scrolling page and detecting connection status');
34
- await page.evaluate(() => { window.scrollTo(0, 300); });
34
+ await page.evaluate(function() { window.scrollTo(0, 300); });
35
35
  await waitRandom(600, 2500, page);
36
36
 
37
37
  const result = await detectConnectionStatus(page, username);
@@ -38,7 +38,7 @@ export async function executeSendMessages(page, action) {
38
38
 
39
39
  await page.waitForLoadState('domcontentloaded');
40
40
  await waitRandom(800, 1400, page);
41
- await page.evaluate(() => { window.scrollTo(0, 300); });
41
+ await page.evaluate(function() { window.scrollTo(0, 300); });
42
42
  await waitRandom(600, 2500, page);
43
43
 
44
44
  console.log('[send_messages] Closing all conversation bubbles');
@@ -199,7 +199,7 @@ export async function executeSendMessages(page, action) {
199
199
  await waitRandom(180, 260, page);
200
200
 
201
201
  console.log('[send_messages] Clearing and focusing editor');
202
- await editor.evaluate((el) => {
202
+ await editor.evaluate(function(el) {
203
203
  el.focus();
204
204
  el.innerHTML = '';
205
205
  el.dispatchEvent(new Event('input', { bubbles: true }));
@@ -207,7 +207,7 @@ export async function executeSendMessages(page, action) {
207
207
 
208
208
  await waitRandom(130, 210, page);
209
209
 
210
- const isFocused = await editor.evaluate((el) => {
210
+ const isFocused = await editor.evaluate(function(el) {
211
211
  return document.activeElement === el;
212
212
  });
213
213
  console.log('[send_messages] Editor focused:', isFocused);
@@ -248,7 +248,7 @@ export async function executeSendMessages(page, action) {
248
248
  await humanLikeType(editor, message);
249
249
  await waitRandom(320, 620, page);
250
250
 
251
- const textTyped = await editor.evaluate((el) => {
251
+ const textTyped = await editor.evaluate(function(el) {
252
252
  const text = el.innerText || el.textContent || '';
253
253
  return text.trim().length > 0;
254
254
  });
@@ -258,7 +258,7 @@ export async function executeSendMessages(page, action) {
258
258
  console.warn('[send_messages] Text not typed, retrying...');
259
259
  await waitRandom(420, 620, page);
260
260
  await humanLikeClick(page, editor, { timeout: 3000 });
261
- await editor.evaluate((el) => {
261
+ await editor.evaluate(function(el) {
262
262
  el.focus();
263
263
  el.dispatchEvent(new Event('focus', { bubbles: true }));
264
264
  });
@@ -267,7 +267,7 @@ export async function executeSendMessages(page, action) {
267
267
  await humanLikeType(editor, message);
268
268
  await waitRandom(320, 620, page);
269
269
 
270
- const textTypedRetry = await editor.evaluate((el) => {
270
+ const textTypedRetry = await editor.evaluate(function(el) {
271
271
  const text = el.innerText || el.textContent || '';
272
272
  return text.trim().length > 0;
273
273
  });