GCloud Function with Puppeteer - 'Process exited with code 16' error - javascript

Having trouble finding any documentation or cause for this sort of issue. I'm trying to run a headless chrome browser script that pulls the the current song playing from kexp.org and returns it as a JSON object. Testing with the NPM package #Google-clound/functions-framework does return the correct response however when deployed into GCloud, I receive the following error when hitting the API trigger:
Error: could not handle the request
Error: Process exited with code 16
at process.on.code (invoker.js:396)
at process.emit (events.js:198)
at process.EventEmitter.emit (domain.js:448)
at process.exit (per_thread.js:168)
at logAndSendError (/workspace/node_modules/#google-cloud/functions framework/build/src/invoker.js:184)
at process.on.err (invoker.js:393)
at process.emit (events.js:198)
at process.EventEmitter.emit (domain.js:448)
at emitPromiseRejectionWarnings (internal/process/promises.js:140)
at process._tickCallback (next_tick.js:69)
Full Script:
const puppeteer = require('puppeteer');
let browserPromise = puppeteer.launch({
args: [
'--no-sandbox'
]
})
exports.getkexp = async (req, res) => {
const browser = await browserPromise
const context = await browser.createIncognitoBrowserContext()
const page = await context.newPage()
try {
const url = 'https://www.kexp.org/'
await page.goto(url)
await page.waitFor('.Player-meta')
let content = await page.evaluate(() => {
// finds elements by data type and maps to array note: needs map because puppeeter needs a serialized element
let player = [...document.querySelectorAll('[data-player-meta]')].map((player) =>
// cleans up and removes empty strings from array
player.innerHTML.trim());
// creates object and removes empty strings
player = {...player.filter(n => n)}
let songList = {
"show":player[0],
"artist":player[1],
"song":player[2].substring(2),
"album":player[3]
}
return songList
});
context.close()
res.set('Content-Type', 'application/json')
res.status(200).send(content)
} catch (e) {
console.log('error occurred: '+e)
context.close()
res.set('Content-Type', 'application/json')
res.status(200).send({
"error":"occurred"
})
}
}
Is there documentation for this error type? It's been deployed on GCloud via CLI shell with the following parameters:
gcloud functions deploy getkexp --trigger-http --runtime=nodejs10 --memory=1024mb

Related

Async Await in firebase functions

I'm using Async/Await in a firebase function as follows
const functions = require("firebase-functions");
const puppeteer = require('puppeteer');
async function getHtml(url) {
const browser = await puppeteer.launch({
headless: true,
args: ['--no-sandbox', '--disable-setuid-sandbox',]
});
const page = await browser.newPage();
await page.goto(url,
{ waitUntil: ['networkidle0', 'networkidle2', 'load', 'domcontentloaded'] });
const k = await page.content()
await browser.close();
return k
};
// Create and deploy your first functions
// https://firebase.google.com/docs/functions/get-started
exports.api = functions.runWith({ memory: '512MB' })
.https.onRequest((request, response) => {
// console.log(request.query.url)
functions.logger.info("Hello logs!", { structuredData: true });
getHtml(request.query.url)
.then(function (res) {
response.send(res);
console.log(res)
})
.catch(function (err) {
response.send(err);
})
})
;
This fails the pre-deploy with the error Parsing error: Unexpected token function for the line async function getHtml(url) {
I just assumed that it's an issue with the eslint which is why I removed the predeploy "predeploy": [ "npm --prefix \"$RESOURCE_DIR\" run lint"] in the firebase json which helped me deploy successfully but returned an empty response on testing out the deployed code.
Everything on my local system works flawlessly with firebase serve
Any help would be much appriciated!
Edit:
Steps to reproduce
run firebase init in a directory
Select functions... , Javascript and (optionally)select no for eslint
install puppeteer using npm and paste the code above in the /functions/index.js file
run firebase serve and test the code with a url parameter on your local system. This will respond with a rendered html page.
Run firebase deploy
Now, on going to the hosted URL and appending a url parameter should just return {} instead of the html

How to use proxy servers with aws lambda + Puppeteer?

I am trying to run puppeteer with proxy chain package on aws lambda but I am getting this error message:
"errorType": "Error",
"errorMessage": "Protocol error (Target.createTarget): Target closed.",
Code:
const chromium = require('chrome-aws-lambda');
const { addExtra } = require("puppeteer-extra");
const puppeteerExtra = addExtra(chromium.puppeteer);
const proxyChain = require('proxy-chain');
const StealthPlugin = require("puppeteer-extra-plugin-stealth");
puppeteerExtra.use(StealthPlugin());
exports.handler = async (event, context, callback) => {
let finalResult = [];
const url = ``;
let browser;
const oldProxyUrl = ''; // --> bright data proxy
const newProxyUrl = await proxyChain.anonymizeProxy(oldProxyUrl);
console.log("newProxyUrl", newProxyUrl)
try {
browser = await puppeteerExtra.launch({
args: ['--no-sandbox', '--disable-setuid-sandbox', `--proxy-server=${newProxyUrl}`],
defaultViewport: chromium.defaultViewport,
executablePath: await chromium.executablePath,
headless: chromium.headless
});
const page = await browser.newPage();
await page.goto(url);
finalResult = await extractElements(page);
} catch (error) {
return callback(error);
} finally {
await browser.close();
}
return callback(null, finalResult);
};
Above code works fine on aws lambda without proxy-server url. I also tested same code without proxy server url on serverless functions like vercel and netlify and it worked. Only issue is when I add proxy server url it throws protocol error.
Here are a few things you can try to troubleshoot this issue:
Make sure that the url variable has a value. This is currently an empty string, which means that the page.goto() method will not have a valid URL to navigate to.
Make sure that the oldProxyUrl variable has a value. This is currently an empty string, which means that the proxyChain.anonymizeProxy() method will not have a valid proxy to anonymize.
Make sure that the extractElements() function is defined and can be called. This function is not present in the code you provided, so you may need to include it or modify the code to remove the call to this function.
Check the logs of your AWS Lambda function to see if there are any additional error messages that might provide more information about the issue.
Check the documentation for the puppeteer-extra-plugin-stealth and proxy-chain packages to see if there are any known issues or compatibility issues with AWS Lambda.

Delete Discord.js v13 slash command that doesnt exist

lately, I started working on a discord bot and added slash commands.
I noticed that I have a ping(replies with pong) command that I didn't create or I did and I can't get rid of it.
Here is my interactionHandler.js
const { REST } = require("#discordjs/rest");
const { Routes } = require("discord-api-types/v9");
module.exports = async (err, files, client) => {
if (err) return console.error(err);
client.interactionsArray = [];
files.forEach((file) => {
const interaction = require(`./../interactions/${file}`);
client.interactions.set(interaction.data.name, interaction);
client.interactionsArray.push(interaction.data.toJSON());
});
const rest = new REST({ version: "9" }).setToken(process.env.DISCORD_TOKEN);
(async () => {
try {
// console.log("Refreshing slash command list");
// const guildIds = await client.guilds.cache.map((guild) => guild.id);
// const clientId = await client.user.id;
// guildIds.forEach(async (guildId) => {
// await rest.put(Routes.applicationGuildCommands(clientId, guildId), {
// body: client.interactionsArray,
// });
// });
await rest.put(
Routes.applicationGuildCommands("934895917453168653", "967384688069066852"),
{ body: client.interactionsArray},
);
console.log("Successfully refreshed slash command list");
} catch (error) {
console.error(error);
}
})();
};
Is there a way to delete the command because I cant find a way.
I was thinking of getting the ID of the command but I don't know how.
Thanks for all the helpers :)
Discord.js v13
These commands may not be refreshing because of 2 reasons:
These commands may be global commands to change that to refreshing global (instead of guild) commands replace Routes.applicationGuildCommands to Routes.applicationCommands
These commands may be from a different guild which in the case you should change the guild ID
To figure out the problem you should do client.application.commands.fetch() to get all your commands and then console.log() the result.
Example
//This will fetch all your slash commands
const commands = await client.application.commands.fetch();
//Returns a collection of application commands
console.log(commands);

The npm puppeter package is returning an error regarding node_package space

Here is the error that it is returning
Here is a picture of the error i'm getting when I run npm install puppeter
I found some stuff online with permissions, but this is about node_package space. It is not disk space as I've looked over my disk storage availability and there's plenty. Working on an Apify SDK, and I'm following the documentation, but the console is returning a whole bunch of error messages.
Can someone please help?
const Apify = require('apify')
Apify.main(async () => {
const requestQueue = await Apify.openRequestQueue();
await requestQueue.addRequest({ url: 'https://www.iana.org/' });
const crawler = new Apify.PuppeteerCrawler({
requestQueue,
handlePageFunction: async ({ request, page }) => {
const title = await page.title();
console.log(`Title of ${request.url}: ${title}`);
await Apify.utils.enqueueLinks({
requestQueue,
page,
pseudoUrls: ['https://www.iana.org/[.*]'],
});
},
});
await crawler.run();
});

Example script provided by neo4j for JavaScript won't run

I am very new to the graph database ecosystem and for start I am experimenting with the neo4j. I would very much like to work with node and neo4j. So after a quick search I found neo4j-driver that is an officially supported driver for JavaScript and an example provided which is:
const neo4j = require('neo4j-driver')
const driver = neo4j.driver(uri, neo4j.auth.basic(user, password))
const session = driver.session()
const personName = 'Alice'
try {
const result = await session.run(
'CREATE (a:Person {name: $name}) RETURN a',
{ name: personName }
)
const singleRecord = result.records[0]
const node = singleRecord.get(0)
console.log(node.properties.name)
} finally {
await session.close()
}
// on application exit:
await driver.close()
now when I run this code, I immediately get the following error:
SyntaxError: await is only valid in async function
Now I thought I understood the error that I would have to wrap the try-catch block with anonymous async function to get rid of the error. The changed code body is:
const config = {
"neo4j": {
"url": "neo4j://localhost",
"authUser": "neo4j",
"authKey": "adminPassword"
}
}
const neo4j = require("neo4j-driver");
const driver = neo4j.driver(
config.neo4j.url,
neo4j.auth.basic(config.neo4j.authUser, config.neo4j.authKey)
);
const session = driver.session();
(async () => {
try {
const result = await session.run('CREATE (a:Person {name: $name}) RETURN a', { name: 'Alice' });
const singleRecord = result.records[0];
const node = singleRecord.get(0);
console.log(node.properties.name);
} catch (error) {
console.log("Error Body: ", error);
} finally {
await session.close();
}
})();
await driver.close();
But to my dismay, I have run into another error that is very cryptic:
{ Neo4jError: Could not perform discovery. No routing servers available. Known routing table: RoutingTable[database=Sample database, expirationTime=0, currentTime=1592397056399, routers=[], readers=[], writers=[]]
at captureStacktrace (/Users/pc/node_modules/neo4j-driver/lib/result.js:263:15)
at new Result (/Users/pc/node_modules/neo4j-driver/lib/result.js:68:19)
at Session._run (/Users/pc/node_modules/neo4j-driver/lib/session.js:174:14)
at Session.run (/Users/pc/node_modules/neo4j-driver/lib/session.js:135:19)
at /Users/pc/neoNode.js:20:38
at Object.<anonymous> (/Users/pc/neoNode.js:31:3)
at Module._compile (module.js:653:30)
at Object.Module._extensions..js (module.js:664:10)
at Module.load (module.js:566:32)
at tryModuleLoad (module.js:506:12) code: 'ServiceUnavailable', name: 'Neo4jError' }
I also had some problems with this.
First off, Natam Oliveira is correct. You need to use the bolt protocol, and await promises needs to be within an async function. For some reason the neo4j protocol is used in some examples in the docs. Additionally it would seem both examples currently provided by Neo4j—in the driver-manual and javascript-driver section—causes errors if you use them outside of some kind of unspecified environment.
There were some clues on the npmjs pagckage page, though, so by working them into the existing code, I was at least able to spit out some data. However I'm also wondering on how you could make this work inside the async function, so an explanation to how that could work with this driver would be very welcome.
Here's what worked for me:
const neo4j = require('neo4j-driver')
const cnx = {
user: 'neo4j',
password: 'some passphrase',
uri: 'bolt://localhost:7687'
}
const driver = neo4j.driver(cnx.uri, neo4j.auth.basic(cnx.user, cnx.password))
driver.verifyConnectivity()
.then((cnxMsg) => {
console.log(cnxMsg)
})
const session = driver.session({ database: 'neo4j' })
session.run('MATCH (n:Movie) RETURN n LIMIT 5')
.subscribe({
onKeys: keys => {
console.log(keys)
},
onNext: record => {
console.log(record.get('n').properties.title)
},
onCompleted: () => {
session.close()
},
onError: error => {
console.error(error)
}
})
This spits out some movies using the streaming API as seen in the NPM documentation. (Note: It will only work if you started/installed the Movie database, so double check that you didn't delete it, as its deletion is also part of the Neo4j tutorial.) Now just change the MATCH Cypher query to whatever you like, and play around with the output, for instance by piping it to Express.
Sources:
https://neo4j.com/docs/driver-manual/current/client-applications/
https://neo4j.com/developer/javascript/#javascript-driver
https://www.npmjs.com/package/neo4j-driver
https://neo4j.com/docs/api/javascript-driver/current/
first of all, I think your URL should be "url": "bolt://localhost:7687"
And you still with await driver.close() outside an async function
If you are starting to use neo4j, look for an OGM (Object Graph Model) to help you.

Categories

Resources