How to use Service Worker WebPush in Puppeteer headless mode? - puppeteer

I've trying to register service worker web push in puppetter headless mode, here is my code
import puppeteer from 'puppeteer';
(async () => {
const browser = await puppeteer.launch({
// headless: false,
args: [
'--user-data-dir=/tmp/chrome',
'--enable-features=NetworkService,NetworkServiceInProcess,'
],
ignoreHTTPSErrors: true,
});
const page = await browser.newPage();
const domain = 'http://127.0.0.1:3000'
await page.goto(domain);
page.on('console', msg => console.log('PAGE LOG:', msg.text()));
const token = await page.evaluate(async () => {
return await window.navigator.serviceWorker.ready.then(async (serviceWorkerRegistration) => {
// return serviceWorkerRegistration.pushManager.getSubscription()
const registration = await navigator.serviceWorker.getRegistration();
console.log(`getRegistration: ${registration}`);
try {
const subscription = await serviceWorkerRegistration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: new Uint8Array([4, 94, 104, 18, 141, 49, 13, 74, 96, 202, 82, 131, 78, 91, 29, 242, 150, 102, 197, 0, 53, 149, 230, 8, 54, 38, 62, 173, 43, 28, 89, 130, 191, 222, 213, 128, 147, 62, 21, 49, 187, 95, 212, 194, 196, 253, 140, 157, 234, 34, 8, 234, 143, 158, 221, 15, 83, 8, 222, 111, 100, 204, 213, 48, 75]),
});
return subscription.toJSON()
} catch (error) {
console.log(`error: ${error}`);
return null
}
})
}).catch(e => {});
console.log(`token: ${JSON.stringify(token)}`);
})();
in non-headless mode, the code is run pretty well
PAGE LOG: getRegistration: [object ServiceWorkerRegistration]
PAGE LOG: JSHandle#object
token: {"endpoint":"https://fcm.googleapis.com/fcm/send/fBqzufyQyzU:APA91bH1kHiKTzciB6KF7GqL4zV5yfeKLnlhAvyZLHRsVcStfqh7nZYbaJ7M0p6eFx24b38v-nFKy4FYFFDJtPiAgTAiaEErQ_2la9Y7S33Ok6J8rCCio5T_gK-wf8QxeF-J87Pjff_N","expirationTime":null,"keys":{"p256dh":"BGjLgRDRBlGcv9HXyg18T-4BQyKErKnzcFJhSNTziBpVHIeuBeNUiIXNjMFBKyQP6oNz9adL3wYBAIPzW106aAY","auth":"nRQCYhw96EOFMKVqoQlp-Q"}}
but if use headless: true, the puppeteer will got a error
PAGE LOG: getRegistration: [object ServiceWorkerRegistration]
PAGE LOG: error: AbortError: Registration failed - push service not available
token: null
how could i solve this problem ?
use Service Worker WebPush in Puppeteer headless mode

Related

get the count of dayname Failed - Laravel 9

For my case , I have a data table contains a timestamps data call "created_at" , right now , it want to get the count of the dayname of the time stamp
so ideally it will be like
and I like to save it on the array for me to pass the data to may chart.js chart
so what i do is
$getdate = DB::table('watchlists')
->select('created_at')
->get();
$getweekday = Carbon::parse($getdate)->format('l');
$dayarray=[];
if($getweekday =='Monday')
{
$mondaycount = Carbon::parse($getdate)->count();
$dayarray=[0];
}
elseif($getweekday =='Tuesday')
{
$tuesday = Carbon::parse($getdate)->count();
$dayarray=[1];
}
elseif($getweekday =='Wednesday')
{
$wednesday = Carbon::parse($getdate)->count();
$dayarray=[2];
}
elseif($getweekday =='Thursday')
{
$thursday = Carbon::parse($getdate)->count();
$dayarray=[3];
}
elseif($getweekday =='Friday')
{
$firday = Carbon::parse($getdate)->count();
$dayarray=[4];
}
elseif($getweekday =='Saturday')
{
$saturday = Carbon::parse($getdate)->count();
$dayarray=[5];
}
elseif($getweekday =='Sunday')
{
$sunday = Carbon::parse($getdate)->count();
$dayarray=[6];
}
<script>
const ctx = document.getElementById('chart1').getContext('2d');
const myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'],
datasets: [{
label: 'Visitor Volume by weekday',
data: [{{ $dayarray}}],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
y: {
beginAtZero: true
}
}
}
});
but when i try to run the code it gives the error of
Could not parse '[{"created_at":"2022-06-24 18:50:05"},{"created_at":"2022-06-26 13:24:42"},{"created_at":"2022-06-24 18:50:05"},{"created_at":"2022-06-26 13:24:42"},{"created_at":"2022-06-26 13:24:42"},{"created_at":"2022-06-26 13:24:42"}]': DateTime::__construct(): Failed to parse time string ([{"created_at":"2022-06-24 18:50:05"},{"created_at":"2022-06-26 13:24:42"},{"created_at":"2022-06-24 18:50:05"},{"created_at":"2022-06-26 13:24:42"},{"created_at":"2022-06-26 13:24:42"},{"created_at":"2022-06-26 13:24:42"}]) at position 0 ([): Unexpected character
I like to ask what is the error in the code , did I miss anything?
PS. I would also like to ask how to pass the data to the charts . i have a premade charts
You can use array reduce() function for this purpose. It is a php array function that you can find docs in here and also for laravel collection
$dayCounts = DB::table('watchlists')
->select('created_at')
->get()
->reduce(function ($car, $item) {
$day = Carbon::parse($item->created_at)->format('l');
$car[$day] = ($car[$day] ?? 0) + 1;
return $car;
});

How to decode a Gzip Http Response in Flutter?

I am new to Flutter. I am making a Network Request and I am getting the correct response, but the data is Gzipped. I have decompressed the same in Swift, but with Flutter, I am unable to do that. Can anyone please help?
Here's what I have tried:
import 'dart:convert';
import 'package:http/http.dart';
import 'package:archive/archive.dart';
import 'package:flutter_app/Constants/constants.dart';
class ServiceHelper {
static final sharedInstance = ServiceHelper();
Future<Response> sendRequest({String path, Map<String,dynamic> params}) async {
final String url = Constants.testURL+path;
var body = jsonEncode(params);
Response response = await post(url, body:body);
final gZipped_data = GZipDecoder().decodeBytes(response.bodyBytes);
print(gZipped_data); //flutter: [123, 34, 115, 116, 97, 116, 117, 115, 34, 58, 50, 48, 48, 44, 34, 109, 101, 115, 115, 97, 103, 101, 34, 58, 34, 83, 105, 103, 110, 32, 105, 110, 32, 67, 111, 109, 112, 108, 101, 116, 101, 100, 32, 83, 117, 99, 99, 101, 115, 115, 102, 117, 108, 108, 121, 34, 44, 34, 100, 97, 116, 97, 34, 58, 123, 34, 117, 115, 101, 114, 95, 105, 110, 102, 111, 34, 58, 123, 34, 112, 108, 97, 121, 101, 114, 95, 105, 100, 34, 58, 49, 52, 56, 54, 57, 44, 34, 112, 108, 95, 97, 112, 112, 95, 105, 100, 34, 58, 34, 57, 90, 104, 57, 82, 66, 108, 70, 34, 44, 34, 112, 114, 111, 102, 105, 108, 101, 95, 112, 105, 99, 34, 58, 34, 104, 116, 116, 112, 115, 58, 92, 47, 92, 47, 119, 119, 119, 46, 115, 112, 111, 114, 116, 115, 113, 119, 105, 122, 122, 46, 99, 111, 109, 92, 47, 118, 51, 92, 47, 105, 109, 103, 92, 47, 112, 108, 97, 121, 101, 114, 115, 92, 47, 112, 105, 99, 92, 47, 105, 80, 45, 49, 53, 50, 51, 56, 54, 57, 50, 57, 56, 46, 112, 110, 103, 34, 44, 34, 101, 109, 97, 105, 108, 34, 58, 34, 116, 101, 99, 104, 121, <…>
//This throws an error: Unhandled Exception: FormatException: Bad UTF-8 encoding 0x8b (at offset 1)
return response;
}
}
//This is the login function and it is in a different file main.dart
Future<void> login(
{String email,
String name,
int source,
String sourceStr,
String picString,
String idToken}) async {
final String playerID = '';
final String token = await getIOSToken().then((token){
return token;
});
Map<String, dynamic> params = {
"email": email,
"name": name,
"player_id": playerID,
"source_id": source,
"profile_pic": picString,
"password": passwordController.text ?? "",
"ios_token":token,
"device_type": "I",
"language_iso": "en",
"referred_by": "loginDefault",
"firebase_id_token": idToken,
"app_version": "4.4.9"
};
Response response = await ServiceHelper.sharedInstance
.sendRequest(path: Constants.login, params: params);
if (response.statusCode == 201) {
// If server returns an OK response, parse the JSON.
return UserDetails.fromJson(json.decode(response.body));
} else {
// If that response was not OK, throw an error.
throw Exception('Failed to load post');
}
}
The expected response is JSON, but as it is Gzipped and I am unable to decompress it, I do not know how to get the JSON from it. I have tried decoding it and it gives me gzipped_data as a List of Integers as you can see above. How can I get the JSON from it?
I'm using GZipCodec from dart:io.
Try it like this to return the response as a String.
Future<String> sendRequest({String path, Map<String,dynamic> params}) async {
final String url = Constants.testURL+path;
var body = jsonEncode(params);
Response response = await post(url, body:body);
final decoded_data = GZipCodec().decode(response.bodyBytes);
return utf8.decode(decoded_data, allowMalformed: true);
}
The body of a response will be automatically uncompressed.
Visit https://api.flutter.dev/flutter/dart-io/HttpClient/autoUncompress.html

Google Apps Script equivalent for JS typed arrays (Uint8Array and Uint16Array)

When I try to run the following code in google apps script
var numArray = [31, -117, 8, 8, -102, -124, 75, 88, 2, 0, 106, 117, 108, 121, 46, 116, 120, 116, 0, 1, 4, 0, -5, -1, 106, 117, 108, 121, -13, -113, 116, -57, 4, 0, 0, 0];
var typedArray = new Uint8Array(numArray);
...I get:
ReferenceError: "Uint8Array" is not defined.
At the same time
var numArray = [31, -117, 8, 8, -102, -124, 75, 88, 2, 0, 106, 117, 108, 121, 46, 116, 120, 116, 0, 1, 4, 0, -5, -1, 106, 117, 108, 121, -13, -113, 116, -57, 4, 0, 0, 0];
var typedArray = new Array(numArray);
...works just fine. Is there a clever workaround way to implement a Uint8Array in google apps script?
OK, so thanks to the comment from #Xepoch, here is the answer to my original question.
The equivalent to
var numArray = [31, -117, 8, 8, -102, -124, 75, 88, 2, 0, 106, 117, 108, 121, 46, 116, 120, 116, 0, 1, 4, 0, -5, -1, 106, 117, 108, 121, -13, -113, 116, -57, 4, 0, 0, 0];
var typedArray = new Uint8Array(numArray);
is (in the absence of Uint8Array):
var numArray = [31, -117, 8, 8, -102, -124, 75, 88, 2, 0, 106, 117, 108, 121, 46, 116, 120, 116, 0, 1, 4, 0, -5, -1, 106, 117, 108, 121, -13, -113, 116, -57, 4, 0, 0, 0];
var typedArray = [];
for(var i=0;i<numArray .length;i++) {
typedArray.push(numArray [i]<0?numArray [i]+256:numArray [i]);
}

Chrome not reading source map generated by elixir browserify

I'm using Laravel elixir to compile my js and css files with gulp. I'm using Chrome to debug, and it's picking up the sourcemaps generated by mix.styles and mix.scripts but not the one generated by mix.browserify. I can't see what I'm doing wrong. I want it to tell me that I have an error on custom-charts.js at line 45 of the source file but instead it says it is on line 14785 of the compiled file.
Here is my gulpfile:
var elixir = require('laravel-elixir');
elixir(function(mix) {
mix.less('app.less', 'resources/assets/css')
.styles([
'libs/jquery-ui.min.css',
'libs/jquery-ui.structure.min.css',
'libs/jquery-ui.theme.min.css',
'libs/select2.min.css',
'app.css'
])
.browserify('custom-charts.js')
.scripts([
'libs/jquery.min.js',
'libs/bootstrap.min.js',
'libs/select2.min.js',
'libs/jquery-ui.min.js',
'libs/vue.js',
'plugin-options.js',
'custom-jquery.js',
'custom-vue.js',
]);
});
Here is custom-charts.js:
import Chart from 'chart.js';
var ctx = document.getElementById("graph").getContext("2d");
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}
});
new Vue({
el: 'body',
components: { Graph }
});
It does produce a custom-charts.js.map file, and the compiled scripts does say this at the end: //# sourceMappingURL=custom-charts.js.map. Chrome is just not reading it.
Hope this might help a bit
The browserify function as mention in the documentation
elixir(function(mix) {
mix.browserify('index.js');
});
assumes that your scripts are stored in resources/assets/js, though you're free to override the default.
Alternatively you might want to use laravel-elixir-browserify here
npm install --save-dev laravel-elixir-browserify
and include in the gulpfile.js as
var browserify = require('laravel-elixir-browserify');

Draw line chart using shapes in adobe flex

I want to draw line chart for ECG reading using Shapes component. I want graph exactly like this image.
i finished 90% code. but when i call clear() means all lines cleared.
i want to give some space between two different reading.
My code:
<fx:Script>
<![CDATA[
private var arrSPO2:Array = [33, 35, 36, 33, 28, 21,35, 36, 33, 28, 21, 13, 6,33, 28, 21, 13, 6, 0, 0, 0,28, 21, 13, 6, 0, 0, 0, 0, 0, 10,28, 21, 13, 6, 0, 0, 0, 0, 0, 10, 31, 56, 78,13, 6, 0, 0, 0, 0, 0, 10, 31, 56, 78, 93, 98, 94,6, 0, 0, 0, 0, 0, 10, 31, 56, 78, 93, 98, 94, 82, 68, 55,0, 0, 0, 0, 0, 10, 31, 56, 78, 93, 98, 94, 82, 68, 55, 45, 41,0, 0, 0, 0, 10, 31, 56, 78, 93, 98, 94, 82, 68, 55, 45, 41, 41, 42, 44,0, 0, 0, 10, 31, 56, 78, 93, 98, 94, 82, 68, 55, 45, 41, 41, 42, 44, 43, 39, 32,0, 0, 10, 31, 56, 78, 93, 98, 94, 82, 68, 55, 45, 41, 41, 42, 44, 43, 39, 32, 24, 15, 7,0, 10, 31, 56, 78, 93, 98, 94, 82, 68, 55, 45, 41, 41, 42, 44, 43, 39, 32, 24, 15, 7, 1, 0, 0,10, 31, 56, 78, 93, 98, 94, 82, 68, 55, 45, 41, 41, 42, 44, 43, 39, 32, 24, 15, 7, 1, 0, 0, 0, 2, 19,31, 56, 78, 93, 98, 94, 82, 68, 55, 45, 41, 41, 42, 44, 43, 39, 32, 24, 15, 7, 1, 0, 0, 0, 2, 19, 43, 68, 90,56, 78, 93, 98, 94, 82, 68, 55, 45, 41, 41, 42, 44, 43, 39, 32, 24, 15, 7, 1, 0];
private var oldX:int = 0;
private var oldY:int = 0;
private var newX:int = 0;
private var newY:int = 0;
private static const TIMER_INTERVAL:int = 50;
private var timer:Timer = new Timer(TIMER_INTERVAL);
private var shapesSPO2:Shape = new Shape();
[Bindable] private var index:int = -1;
protected function init():void {
}
private function timerHandler(event:TimerEvent):void {
trace(timer.currentCount);
index = timer.currentCount - 1;
//draw SPO2
newX += 2;
newY = ((arrSPO2[index] * -1) / 2 + 120);
if (oldY == 0) {
oldY = newY;
}
shapesSPO2.graphics.moveTo(oldX, oldY);
shapesSPO2.graphics.lineTo(newX, newY);
ui1.addChild(shapesSPO2);
oldX = newX;
oldY = newY;
if (index > arrSPO2.length) {
shapesSPO2.graphics.clear();
shapesSPO2.graphics.lineStyle(2, 0x990000, .75);
oldX = newX = 0;
timer.reset();
timer.start();
}
}
protected function btnSPO2_clickHandler(event:MouseEvent):void {
oldX = newX = 0;
shapesSPO2.graphics.lineStyle(2, 0x990000, .75);
timer.addEventListener(TimerEvent.TIMER, timerHandler);
timer.reset();
timer.start();
}
]]>
</fx:Script>
<s:VGroup width="100%" height="100%"
horizontalAlign="center" verticalAlign="middle">
<mx:HBox width="550" height="500"
borderColor="#000000" borderVisible="true" borderStyle="solid" borderAlpha="0.2"
visible="true" includeInLayout="true">
<s:VGroup id="vgGraph" width="100%" height="100%"
horizontalAlign="center"
gap="10"
padding="10">
<s:HGroup width="100%">
<s:Label text="Current Index : {index}" fontSize="16"
fontWeight="bold" />
</s:HGroup>
<mx:UIComponent id="ui1" width="100%" height="100%" />
<!--<s:SpriteVisualElement id="spriteVis" width="100%" height="100%" />-->
<s:Button id="btnSPO2" label="Draw SPO2 Graph" click="btnSPO2_clickHandler(event)" />
</s:VGroup>
</mx:HBox>
</s:VGroup>
To do that you can change your code like this :
private const margin:int = 10;
private function timerHandler(event:TimerEvent):void {
if (index == arrSPO2.length - 1) {
// set the margin between the last chart and the new one
newX = newX + margin;
oldX = newX;
// reset index
index = 0;
timer.reset();
timer.start();
// exit if we have reached the last element of our array
return;
}
index = timer.currentCount - 1;
newX += 2;
newY = ((arrSPO2[index] * -1) / 2 + 120);
if (oldY == 0) {
oldY = newY;
}
shapesSPO2.graphics.moveTo(oldX, oldY);
shapesSPO2.graphics.lineTo(newX, newY);
ui1.addChild(shapesSPO2);
oldX = newX;
oldY = newY;
}
Which will give you something like this :
Hope that can help.
I've modified your timerHandler as below:
private function timerHandler(event:TimerEvent):void {
trace(timer.currentCount);
index = timer.currentCount - 1;
if (index > arrSPO2.length) {
//shapesSPO2.graphics.clear();
//shapesSPO2.graphics.lineStyle(2, 0x990000, .75);
newX += 10;
oldX = newX;
timer.reset();
timer.start();
return;
}
//draw SPO2
newX += 2;
if(newX > ui1.width)
{
oldX = newX = 0;
}
newY = ((arrSPO2[index] * -1) / 2 + 120);
if (oldY == 0) {
oldY = newY;
}
if(index ==0)
{
oldY = newY;
}
shapesSPO2.graphics.moveTo(oldX, oldY);
shapesSPO2.graphics.lineTo(newX, newY);
ui1.addChild(shapesSPO2);
oldX = newX;
oldY = newY;
}