Skip to content

Instantly share code, notes, and snippets.

@gbowsky
Last active September 21, 2022 07:01
Show Gist options
  • Save gbowsky/2b5592a133c466285e062e5d4561d40e to your computer and use it in GitHub Desktop.
Save gbowsky/2b5592a133c466285e062e5d4561d40e to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name IBI Presentations slide scraper
// @namespace https://gist.github.com/gbowsky
// @version 1.2
// @description Downloads first 300 slides from BBB video conference.
// @downloadURL https://gist.github.com/gbowsky/2b5592a133c466285e062e5d4561d40e/raw/ibi-scrape-pres.user.js
// @updateURL https://gist.github.com/gbowsky/2b5592a133c466285e062e5d4561d40e/raw/ibi-scrape-pres.user.js
// @author gbowsky
// @match https://vu.ibi.spb.ru/*/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=https://bigbluebutton.org/
// @grant GM_xmlhttpRequest
// ==/UserScript==
const maxSlideLength = 300;
if (typeof GM_download !== 'function') {
if (typeof GM_xmlhttpRequest !== 'function') {
throw new Error('GM_xmlhttpRequest is undefined. Please set @grant GM_xmlhttpRequest at metadata block.');
}
function GM_download (url, name) {
if (url == null) return;
var data = {
method: 'GET',
responseType: 'arraybuffer',
onload: function (res) {
var blob = new Blob([res.response], {type: 'application/octet-stream'});
var url = URL.createObjectURL(blob); // blob url
var a = document.createElement('a');
a.setAttribute('href', url);
a.setAttribute('download', data.name != null ? data.name : 'filename');
document.documentElement.appendChild(a);
// call download
// a.click() or CLICK the download link can't modify filename in Firefox (why?)
// Solution from FileSaver.js, https://github.com/eligrey/FileSaver.js/
var e = new MouseEvent('click');
a.dispatchEvent(e);
document.documentElement.removeChild(a);
setTimeout(function(){
// reduce memory usage
URL.revokeObjectURL(url);
if ('close' in blob) blob.close(); // File Blob.close() API, not supported by all the browser right now
blob = undefined;
}, 1000);
if (typeof data.onafterload === 'function') data.onafterload(); // call onload function
}
// error object of onerror function is not supported right now
};
if (typeof url === 'string') {
data.url = url;
data.name = name;
}
else {
if (url instanceof Object === false) return;
// as documentation, you can only use [url, name, headers, saveAs, onload, onerror] function, but we won't check them
// Notice: saveAs is not supported
if (url.url == null) return;
for (var i in url) {
if (i === 'onload') data.onafterload = url.onload; // onload function support
else data[i] = url[i];
}
}
// it returns this GM_xhr, thought not mentioned in documentation
return GM_xmlhttpRequest(data);
}
}
function addBtn() {
const parent = document.querySelector('button[aria-label="Транслировать веб-камеру"]').parentElement;
const button = document.createElement('button');
button.className = "button--Z2dosza lg--Q7ufB primary--1IbqAO";
button.textContent = "Скачать 100 слайдов";
button.addEventListener("click", downloadAll, false);
parent.appendChild(button);
}
function addBtnRecord() {
document.querySelector('style').textContent += '.bbb-download:before { content: "📥"; }'
const parent = document.querySelector('.right');
const div = document.createElement('div');
const button = document.createElement('button');
const inner = document.createElement('span');
inner.className = 'bbb-download';
div.className = 'button-wrapper';
button.className = "button default circle";
button.addEventListener("click", downloadRecording, false);
button.appendChild(inner);
div.appendChild(button);
parent.appendChild(div);
}
async function downloadRecording() {
const href = document.querySelector('.presentation image').getAttribute('href');
let parts = href.split('/');
for(let index = 1; index < maxSlideLength; index++) {
parts[parts.length - 1] = `slide-${index}.png`
if (await checkURL(parts.join('/'))) {
GM_download(parts.join('/'), `${index}-${parts[parts.length -2]}-bbimg.png`);
}
}
}
async function downloadAll() {
const href = document.querySelector('[data-test=whiteboard] image').getAttribute('xlink:href');
let parts = href.split('/');
parts[parts.length - 2] = 'png';
for(let index = 1; index < maxSlideLength; index++) {
parts[parts.length - 1] = String(index);
if (await checkURL(parts.join('/'))) {
GM_download(parts.join('/'), `${index}-${parts[parts.length -3]}-bbimg.png`);
}
}
}
async function checkURL(url) {
const data = await fetch(url);
return data.status === 200;
}
function callback() {
if (!checkIfRecording()) {
addBtn();
} else {
addBtnRecord();
}
}
function checkIfRecording() {
return document.querySelector('.presentation image') !== null;
}
function check() {
return document.querySelector('[data-test=whiteboard] image') !== null || document.querySelector('.presentation image') !== null;
}
(function() {
'use strict';
let inval = setInterval(() => {
if (check()) {
clearInterval(inval);
callback();
}
}, 500);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment