Skip to content

Instantly share code, notes, and snippets.

View eyecatchup's full-sized avatar

Stephan Schmitz eyecatchup

View GitHub Profile
#!/usr/bin/env sh
# Downloads the audio of all videos of the given playlist,
# saves as mp3 /with metadata and square(!) thumbnail.
# Note: yt-dlp and ffmpeg are required.
# Use: ./yt-dlp-playlist.sh YT_PLAYLIST_ID
./yt-dlp --extract-audio --audio-format mp3 --audio-quality 0 \
--add-metadata --embed-thumbnail --convert-thumbnails jpg \
--ppa 'EmbedThumbnail+ffmpeg_o:-c:v mjpeg -vf crop="'"'"'if(gt(ih,iw),iw,ih)'"':'"'if(gt(iw,ih),ih,iw)'"'"'"' \
@eyecatchup
eyecatchup / calc-sapisidhash.js
Last active November 14, 2024 10:23
Calculate SAPISIDHASH
// Generates the SAPISIDHASH token Google uses in the Authorization header of some API requests
async function getSApiSidHash(SAPISID, origin) {
function sha1(str) {
return window.crypto.subtle.digest("SHA-1", new TextEncoder("utf-8").encode(str)).then(buf => {
return Array.prototype.map.call(new Uint8Array(buf), x=>(('00'+x.toString(16)).slice(-2))).join('');
});
}
const TIMESTAMP_MS = Date.now();
const digest = await sha1(`${TIMESTAMP_MS} ${SAPISID} ${origin}`);
@eyecatchup
eyecatchup / draw-bootstrap-grid.js
Created March 30, 2022 10:18
Draw the Bootstrap grid as a full page overlay
var grid = 12
var cols = document.createDocumentFragment()
var col = document.createElement('div')
col.style.cssText = `height: ${document.documentElement.scrollHeight}px; width: calc(100% / ${grid}); background-color: rgba(240, 128, 128, 0.3);`
var innerCol = document.createElement('div')
innerCol.style.cssText = `height: ${document.documentElement.scrollHeight}px; width: calc(100% - 30px); margin: auto 15px; background-color: rgba(244, 0, 0, 0.1); position: relative;`
col.appendChild(innerCol)
for (var i, i = 1; i <= grid; i++) {
@eyecatchup
eyecatchup / vue.config.js
Created September 25, 2020 10:57
(Vue.js) Webpack dev server config to use a (corporate) proxy
const HttpsProxyAgent = require('https-proxy-agent')
const proxy = new HttpsProxyAgent('http://1.2.3.4:3128')
module.exports = {
// ...
configureWebpack: {
devServer: {
// ...
proxy: {
@eyecatchup
eyecatchup / error-stringify.js
Created February 18, 2020 11:57
Custom replace function for JSON.stringify to stringify JS Error Objects.
jsonFriendlyErrorReplacer = (key, value) => {
if (value instanceof Error) {
value = Object.assign({},
value, // Pull all enumerable properties, supporting properties on custom Errors
{ // Explicitly pull Error's non-enumerable properties
name: value.name,
message: value.message,
stack: value.stack
}
)
@eyecatchup
eyecatchup / ionic-native-cordova-inappbrowser-executescript-ios.md
Last active August 31, 2021 11:20
Ionic Native / Cordova InAppBrowser: Multiple `executeScript` Promises

Ionic Native / Cordova InAppBrowser: Multiple executeScript Promises

I recently worked on a project with Ionic Native and Cordova. One thing I noticed (and took me some time to resolve), was an issue with the then function of the InAppBrowser plugin's executeScript Promise not being executed on iOS.

TL;DR When you use multiple executeScript Promises within one method, the then functions will not fire on iOS. You have to await results.

To illustrate the issue, let's declare a new InAppBrowser instance:

const browser = this.iab.create('https://example.com', '_blank');
@eyecatchup
eyecatchup / catch-js-error-stacktrace.js
Created July 1, 2019 08:34
JavaScript global error handling
var sendError = function (err) {
console.log('Caught JS client error:');
console.dir(err);
var xhr = new XMLHttpRequest();
xhr.open('POST', '/api/error/add', true);
xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8');
xhr.send(JSON.stringify(err));
};
@eyecatchup
eyecatchup / search-devtools-history.md
Created May 24, 2019 07:06
Search Chrome Devtools history

Search Chrome Devtools history

  1. Undock the console (click on the icon in the bottom-left corner, ![undock icon][1]).
    (if you don't see ![the undock icon][2], but ![][3], then hold the mouse pressed for a few seconds to get the desired icon)
  2. Press Ctrl + Shift + J to open the console for this console. (On OSX use Cmd + Option + i)
  3. Use the following snippet to get an array of matches for your search term:
const searchHistory = query => {console.dir(JSON.parse(localStorage.getItem('consoleHistory')).filter(function(item){ return ~item.indexOf(query);}))}
searchHistory('token')
@eyecatchup
eyecatchup / js-generator-functions.md
Last active July 23, 2019 10:08
Creating a `GeneratorFunction` in JavaScript

Generator defined using the function* statement syntax:

// function *idMaker(){ <- also possible, even though no reference found
function* idMaker(){
  var index = 0;
  while(index < index+1)
    yield index++;
}