'document is not defined' canvas/discord - node.js

I'm trying make a animated banner to discord server, but I have some problems with that. I don't know why document is not defined. I tried a bunch of ways, but none of them worked.
try {
let guild = await client.guilds.cache.get(guildId.id);
const voiceChannels = guild.channels.cache.filter((c) => c.type === "GUILD_VOICE");
let count = 0;
for (const [, voiceChannel] of voiceChannels) count += voiceChannel.members.size;
var canvas = createCanvas(420, 236);
var ctx = canvas.getContext('2d');
ctx.textAlign = "center"
ctx.font = "20px Kanit Black"
ctx.fillStyle = '000001'
const encoder = new GIFEncoder(420, 236, {emptyColor: true, dynamicColors: true})
encoder.setRepeat(0);
encoder.setQuality(10)
await gifFrames({ url: `${__dirname}/banner-beta.gif`, frames: 'all', outputType: 'canvas', cumulative: false}).then((frameData) => {
for(let i = 0; i < frameData.length; i++) {
encoder.setDelay(frameData[i].frameInfo.delay * 15);
console.log(frameData[0])
console.log(frameData[i])
ctx.drawImage((frameData[i]).getImage(), 0, 0, 420, 236)
ctx.fillText(`${count}`, 50, 90)
console.log(ctx)
encoder.addFrame(ctx);
}
encoder.finish();
console.log(encoder.out.getData())
var attachment = new MessageAttachment(encoder.out.getData(), 'banner.gif');
guild.channels.cache.get("909860310171648050").send({ files: [attachment] }).catch(console.log);
})
//guild.setBanner(canvas.toBuffer()).catch(console.error);
} catch (e) {
console.log(e)
}
error:
ReferenceError: document is not defined
at savePixels (C:\Users\hotab\Desktop\Root\node_modules\save-pixels-jpeg-js-upgrade\save-pixels.js:127:20)
at Object.getImage (C:\Users\hotab\Desktop\Root\node_modules\gif-frames\gif-frames.js:105:20)
at C:\Users\hotab\Desktop\Root\utils\banner.js:31:34

TL;DR:
Your code runs in NodeJS, in which there is no document object because it does not make sense on a backend server. So using document results in an exception.
More details
You are using the node module gif-frames that depends on another node module called save-pixels-jpeg-js-upgrade which tries to access the document object that only exists in a browser context (see code here).
Either the documentation of gif-frames stating that it can run in both Node and browsers contexts is incorrect or there are some restrictions to some APIs, which you are facing here. Based on the node module code, it seems to be limited to the CANVAS case, but I can't help you any further...

Related

Loading shapefile data into shp (leaflet plugin) says TypeError: this is undefined

I am working on Ionic angular platform.I get a shapefile that is converted to a Base64 string. I am converting it to a file and then trying to convert to arrayBuffer using 'FileReader' to fit the data to match (L.shapefile)
https://github.com/calvinmetcalf/leaflet.shapefile
EDIT: I fixed the previous problem, the current problem is the data (ArrayBuffer) added to leaflet.shapefile which returns the error.
Or if you got the zip some other way (like the File API) then with the arrayBuffer you can call
const geojson = await shp(buffer);
Source: https://www.npmjs.com/package/shpjs
I tried working in this direction to fit the shapefile into L.shapefile as follows:
import * as L from "leaflet";
import * as shp from "shpjs";
const l1 = require('../../assets/leaflet.shpfile.js');
export class Tab7Page {
map: L.Map
async ngOnInit() {
this.map = L.map("map", {
center: [49.7, 8.12],
zoom: 15,
renderer: L.canvas(),
});
L.tileLayer(
"https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
{
// maxZoom: 12,
attribution:
"Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community",
}
).addTo(this.map);
// this.map.setView(layer.getBounds()['_northEast'], 14);
setTimeout(() => {
this.map.invalidateSize();
}, 1);
var shape_data = "data:application/zip;base64,UEsDBAoAAAAAAHZwplQAAAAAAAAAAAAAAAAHAAAAbGF5ZXJzL1BLAwQKAAAAAAB2cKZUD7eKbDwBAAA8AQAAEgAAAGxheWVycy9QT0xZR09OLnNocAAAJwoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ7oAwAABQAAAAAAAFCyGiBAeNAJLjeZSEAAAACYlB0gQMAkzNp mUhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAaAUAAAAAAABQshogQHjQCS43mUhAAAAAmJQdIEDAJMzafplIQAEAAAAKAAAAAAAAAAAAAJjEGiBAwCTM2n6ZSEAAAABQshogQKOtBVtUmUhAAAAAeLYbIEC8k8/CPplIQAAAABBpHCBAsUVS7DyZSED/// v9RwgQMXhbjg/mUhAAAAA6IAdIEB40AkuN5lIQAAAAJiUHSBAeeTrB2mZSEAAAACo7hwgQFKQcddwmUhAAAAAcNwbIEDbe339cZlIQAAAAJjEGiBAwCTM2n6ZSEBQSwMECgAAAAAAdnCmVObu5cZsAAAAbAAAABIAAABsYXllcnMvUE9MWUdPTi5zaHgAACcKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA26AMAAAUAAAAAAABQshogQHjQCS43mUhAAAAAmJQdIEDAJMzafplIQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMgAAAGhQSwMECgAAAAAAdnCmVGt60SP0AgAA9AIAABIAAABsYXllcnMvUE9MWUdPTi5kYmYDegQGAQAAAMEAMwIAAAAAAAAAAAAAAAAAAAAAAAAAAHN0cm9rZQAAAAAAQwAAAAD AAAAAAAAAAAAAAAAAAAAc3Ryb2tlLXcAAABOAAAAABIAAAAAAAAAAAAAAAAAAABzdHJva2UtbwAAAE4AAAAAEgAAAAAAAAAAAAAAAAAAAGZpbGwAAAAAAAAAQwAAAAD AAAAAAAAAAAAAAAAAAAAZmlsbC1vcGEAAABOAAAAABIAAAAAAAAAAAAAAAAAAAAAICNjNWQ1NzMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAyICAgICAgICAgICAgICAgICAxI2RiZDc5MCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAwLhpQSwMECgAAAAAAdnCmVOPBUWqPAAAAjwAAABIAAABsYXllcnMvUE9MWUdPTi5wcmpHRU9HQ1NbIkdDU19XR1NfMTk4NCIsREFUVU1bIkRfV0dTXzE5ODQiLFNQSEVST0lEWyJXR1NfMTk4NCIsNjM3ODEzNywyOTguMjU3MjIzNTYzXV0sUFJJTUVNWyJHcmVlbndpY2giLDBdLFVOSVRbIkRlZ3JlZSIsMC4wMTc0NTMyOTI1MTk5NDMyOTVdXVBLAQIUAAoAAAAAAHZwplQAAAAAAAAAAAAAAAAHAAAAAAAAAAAAEAAAAAAAAABsYXllcnMvUEsBAhQACgAAAAAAdnCmVA 3imw8AQAAPAEAABIAAAAAAAAAAAAAAAAAJQAAAGxheWVycy9QT0xZR09OLnNocFBLAQIUAAoAAAAAAHZwplTm7uXGbAAAAGwAAAASAAAAAAAAAAAAAAAAAJEBAABsYXllcnMvUE9MWUdPTi5zaHhQSwECFAAKAAAAAAB2cKZUa3rRI/QCAAD0AgAAEgAAAAAAAAAAAAAAAAAtAgAAbGF5ZXJzL1BPTFlHT04uZGJmUEsBAhQACgAAAAAAdnCmVOPBUWqPAAAAjwAAABIAAAAAAAAAAAAAAAAAUQUAAGxheWVycy9QT0xZR09OLnByalBLBQYAAAAABQAFADUBAAAQBgAAAAA="
var shape_fileName = "TestFile"
var file = this.dataURLtoFile(shape_data,shape_fileName);
// console.log("Blob retrieved successfully..", blob);
// this.handleZipFile(file);
var reader = new FileReader();
reader.onload = function(){
if (reader.readyState != 2 || reader.error){
console.error("thats the error side");
return;
} else {
shp(reader.result).then(function (geojson) { //More info: https://github.com/calvinmetcalf/shapefile-js
L.geoJSON(geojson).addTo(this.map);//More info: https://github.com/calvinmetcalf/leaflet.shapefile
});
}
}
reader.readAsArrayBuffer(file);
}
dataURLtoFile(dataurl, filename) {
var bstr1 = atob(dataurl);
console.log("Byte sting", bstr1);
var arr = dataurl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(decodebase64),
n = bstr.length,
u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {type:mime});
}
I just get a map with the below error has informed. I am not sure which leaflet package to use shpjs or L.shapefile?
EDIT: As per comments from GIS platform i installed buffer and updated polyfill.ts and now I get the following error.

Effects / Spark AR "ERROR: undefined is not a function"

I'm trying to make a JS effect on Spark AR with a code and Native UI and also face mesh.
The effect have bottons to choose the effect, one of them have a face mesh where the texture is not recognize and the another one have a simple texture.
----- My code to script of two objects / two bottons:
const Materials = require('Materials');
const Scene = require('Scene');
const NativeUI = require('NativeUI');
const Textures = require('Textures');
const plane = Scene.root.find('plane0');
const index = 0;
const configuration = {
selectedIndex: index,
items: [
{image_texture: Textures.get('N1')},
{image_texture: Textures.get('N2')},
],
mats: [
{material: Materials.get("N1")},
{material: Materials.get("N2")},
]
};
const picker = NativeUI.picker;
picker.configure(configuration);
picker.visible = true;
picker.selectedIndex.monitor().subscribe(function(val) {
plane.material = configuration.mats[val.newValue].material;
;
});
----- The error message that shows when I open Spark AR Studio:
ERROR: undefined is not a function
{ "line": 6,
<br> "column": 30,
<br> "sourceURL": "scrip2obj.js"
}
I would like to know... what can I do to make this run and make the face mesh shows in the effect?
Starting from v85 of Spark AR Studio the current JavaScript APIs are deprecated in favor of asynchronous APIs.
This means some APIs will be deprecated and will need to be replaced in your projects. When creating new projects, new APIs should be used instead.
You can learn more about it here
Scripting Javascript Promise In Spark AR For Beginners
Try the following code to implement Native UI Picker
const Materials = require('Materials');
const NativeUI = require('NativeUI');
const Textures = require('Textures');
const Scene = require('Scene');
(async function () { // Enables async/await in JS [part 1]
// To access scene objects
const [plane0, n1, n2, n1Material] = await Promise.all([
Scene.root.findFirst('plane0'),
Textures.findFirst('N1'),
Textures.findFirst('N2'),
Materials.findFirst("N1"),
]);
const index = 0;
const configuration = {
selectedIndex: index,
items: [
{ image_texture: n1 },
{ image_texture: n2 },
]
};
const picker = NativeUI.picker;
picker.configure(configuration);
picker.visible = true;
picker.selectedIndex.monitor().subscribe(function (val) {
plane.material = configuration.mats[val.newValue].material;
});
})(); // Enables async/await in JS [part 2]

tf.image.cropAndResize throwing "method must be bilinear or nearest, but was undefined" error

I am trying to run an image categorization model in firebase cloud functions using tensorflow.js (specifically tfjs-node) but am running into the flowing error:
Error: method must be bilinear or nearest, but was undefined
at assert (/workspace/node_modules/#tensorflow/tfjs-core/dist/tf-core.node.js:698:15)
at cropAndResize_ (/workspace/node_modules/#tensorflow/tfjs-core/dist/tf-core.node.js:21340:5)
at Object.cropAndResize__op [as cropAndResize] (/workspace/node_modules/#tensorflow/tfjs-core/dist/tf-core.node.js:4287:29)
at prepImage (/workspace/handlers/models.js:58:35)
at /workspace/handlers/models.js:68:44
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at async exports.isFurnished (/workspace/handlers/models.js:10:17)
at async exports.getanalysis (/workspace/handlers/apis.js:103:16)
The error is being thrown by the tf.image.cropAndResize() function. What is strange about this error is that cropAndResize() should be automatically using its default value of "bilinear" as specified in the docs.
Stranger yet, when I run it locally I don't get any errors. My local machine is running node v12.16.0.
Below is my code. please note that I am only lading signature.json from the firebase storage and fetching /standardizing an image (I am not loading and running the actual ts model).
const { admin, db } = require("../util/admin");
const firebase = require("firebase");
const tf = require("#tensorflow/tfjs-node");
const fetch = require("node-fetch");
exports.isFurnished = async (imgUrl) => {
const sigPath = "models/signature.json";
const signature = await loadSignature(sigPath);
const image = await loadImage(imgUrl, signature);
return "It worked!";
};
//signature---------------------------
const loadSignature = (filePath) => {
let file = admin.storage().bucket().file(filePath);
return file
.download()
.then((res) => JSON.parse(res[0].toString("utf8")))
.catch((err) => err.message);
};
//Image-------------------------------
const loadImage = (imgUrl, signature) => {
return fetchImage(imgUrl).then((image) => prepImage(image, signature));
};
const fetchImage = async (url) => {
const response = await fetch(url);
const buffer = await response.buffer();
return buffer;
};
const prepImage = (rawImage, signature) => {
const image = tf.node.decodeImage(rawImage, 3);
const [height, width] = signature.inputs.Image.shape.slice(1, 3);
const [imgHeight, imgWidth] = image.shape.slice(0, 2);
const normalizedImage = tf.div(image, tf.scalar(255));
const reshapedImage = normalizedImage.reshape([1, ...normalizedImage.shape]);
let top = 0;
let left = 0;
let bottom = 1;
let right = 1;
if (imgHeight != imgWidth) {
const size = Math.min(imgHeight, imgWidth);
left = (imgWidth - size) / 2 / imgWidth;
top = (imgHeight - size) / 2 / imgHeight;
right = (imgWidth + size) / 2 / imgWidth;
bottom = (imgHeight + size) / 2 / imgHeight;
}
return tf.image.cropAndResize(
reshapedImage,
[[top, left, bottom, right]],
[0],
[height, width]
);
};
Have I made an error that I'm just not seeing or is this a node and/or tsjs issue?
Also, adding in the "bilinear" parameter yields this error:
Error: Invalid napi_status: A number was expected
As commented above, TensorFlow.js version 2.8.0 seems to have introduced some breaking changes. Workaround (at the time of writing) is to keep using version 2.7.0.
I am working with bodypix. It was working fine until this morning. Although I haven't changed anything, since this afternoon this exact error came up. It could be Tensorflow's issue. Or,
I checked on Windows 8.1. There, it works totally fine. The problem happens on windows 10.
EDIT: I am quite sure it's from TensorFlow. Not the windows. I was using CDN to get the bodypix and after updating the cdn address the error disappeared.
previous: https://cdn.jsdelivr.net/npm/#tensorflow-models/body-pix/dist/body-pix.min.js
https://cdn.jsdelivr.net/npm/#tensorflow/tfjs/dist/tf.min.js
Now: https://cdn.jsdelivr.net/npm/#tensorflow-models/body-pix#2.0.5/dist/body-pix.min.js
https://cdn.jsdelivr.net/npm/#tensorflow/tfjs#2.7.0/dist/tf.min.js

Passed function is not well-serializable

I am using Puppeteer to scrape the web from a file template that contains the data of an order.
For this, I am using a puppeteer evaluation function, which works correctly while the file is in .js
However, when the "pkg" package is used to compile the .exe file or evaluate to execute and initiate a return or error: "The passed function is not quite serializable!"
Below is the code:
const dados = {name: 'foo', year: 1}
await page.evaluate(dados => {
let dom = document.querySelector('body');
const tags = Object.keys(dados);
for (let i = 0; i < tags.length; i++) {
const tag = tags[i];
dom.innerHTML = dom.innerHTML.split(`{{${tag}}}`).join(dados[tag]);
}
}, dados);
I try to add --public argument with pkg.
Like: pkg start.js -t node14-win-x64 --public
Then I can freely use ElementHandle.evaluate( (elem)=> elem.textContent );
With the manual of pkg, the --public means that : speed up and disclose the sources of top-level project.
BTW
To fixup cannot find chrome binary file
browser = await puppeteer.launch({
executablePath: "node_modules/puppeteer/.local-chromium/win64-782078/chrome-win/chrome.exe"
});
(The path above can set anywhere as you like.)
To fixup start.exe cannot run
Sometime the output binary exe cannot executable. It
always popup a new cmd prompt window when we enter start.exe. (or just double click.)
Just delete the output exe then rerun pkg
Check the code whether is runnable with node start.js or not
The easiest solution for me is to wrap it with eval() :
async getText(selector: string) {
await this.page.waitForSelector(selector);
let text = await eval(`this.page.$eval('${selector}', el => el.textContent)`)
return text;
}
or this:
await eval(`this.page.evaluate(
(selector) => { (document.querySelector(selector).value = ''); },
selector);`);
I had this exact issue relating to puppeteer and pkg. For some reason pkg doesn't correctly interpret the contents of the callback. The solution that worked for me was to pass a string to evaluate rather than a function:
Change:
const dados = {name: 'foo', year: 1}
await page.evaluate(dados => {
let dom = document.querySelector('body');
const tags = Object.keys(dados);
for (let i = 0; i < tags.length; i++) {
const tag = tags[i];
dom.innerHTML = dom.innerHTML.split(`{{${tag}}}`).join(dados[tag]);
}
}, dados);
to
await page.evaluate(`
(() => {
const dados = {name: 'foo', year: 1};
let dom = document.querySelector('body');
const tags = Object.keys(dados);
for (let i = 0; i < tags.length; i++) {
const tag = tags[i];
dom.innerHTML = dom.innerHTML.split(`{{${tag}}}`).join(dados[tag]);
}
// return dom to do something with the data in node
return dom.innerHTML
})()`);
This answer on github suggests an alternative solution - using the pkg api to inject the callback at compile time, however it didn't work for me.

any code make sure json fully added to canvas?

var json = [];
json.push(json2);
function makeallImage(){
console.log('json length'+json.length);
for (var v = 0; v < json.length; v++){
convertImgToBase64(v, "jpg");
console.log("ksana"+v);
}
}
function convertImgToBase64(number, outputFormat){
var tmpData =
canvas.loadFromJSON(json[number], canvas.renderAll.bind(canvas), function(){
**//need to absolute comfirm it add all object in canvas, load complete json2 //**
canvas.on('object:added', function(e) {
toImg();
});
});
}
function toImg(outputFormat){
var s = document.getElementById("last_Image");
var url = canvas.toDataURL();
var newImg = document.createElement("img"); // create img tag
console.log(newImg);
newImg.src = url;
newImg.width = 100;
newImg.height = 100;
s.appendChild(newImg);
console.log('mpike sto dom');
}
i am using this code to create image to field , problem is if my json object contain image ,it will create empty image. so i figure it out is because loading the src need time and canvas create image before it fully load.
i need to make sure the json fully loaded on canvas first , so i found a fabric code call object:added , which can make sure object added in canvas , but it count object one by one , so if my json cotain 2 object it will create more image.
achievement
1. i need to make sure my json fully load or create in canvas before create image , is they any way to make sure json fully added to canvas?
Demo see my problem using object:added it load multiple image.
You should dump reviver and use just the callback function.
http://jsfiddle.net/v1nmtz02/2/
You will have some difficulties with fabricImages and objects that have a content that is async. That is not yet solved at library level.
function _callback() {
canvas.renderAll();
toImg();
}
function convertImgToBase64(number, outputFormat){
var tmpData = canvas.loadFromJSON(json[number], _callback);
}
Complete snippet:
var canvas = new fabric.Canvas('canvas');
var json2 = '{"objects":[{"type":"circle","originX":"center","originY":"center","left":300,"top":400,"width":200,"height":200,"fill":"rgb(166,111,213)","overlayFill":null,"stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":{"color":"#5b238A","blur":20,"offsetX":-20,"offsetY":-10},"visible":true,"clipTo":null,"radius":100},{"type":"rect","originX":"center","originY":"center","left":300,"top":500,"width":150,"height":150,"fill":"#fbb802","overlayFill":null,"stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":{"color":"rgba(94, 128, 191, 0.5)","blur":5,"offsetX":10,"offsetY":10},"visible":true,"clipTo":null,"rx":0,"ry":0,"x":0,"y":0}],"background":""}';
var json = [];
json.push(json2);
function makeallImage(){
for (var v = 0; v < json.length; v++){
convertImgToBase64(v, "jpg");
}
}
function _callback() {
canvas.renderAll();
toImg();
}
function convertImgToBase64(number, outputFormat){
var tmpData = canvas.loadFromJSON(json[number], _callback);
}
function toImg(outputFormat){
var s = document.getElementById("last_Image");
var url = canvas.toDataURL();
var newImg = document.createElement("img");
newImg.src = url;
newImg.width = 100;
newImg.height = 100;
s.appendChild(newImg);
}
<script src="http://fabricjs.com/lib/fabric.js"></script>
<canvas id='canvas' width="550" height="550" style="border:#000 1px solid;"></canvas>
<button onclick="makeallImage();">makepng</button>
<div id="last_Image" style="background:red"></div>

Resources