Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
76921d6
links-and-barcodes.js
moosanaeempc-lgtm Jan 16, 2026
441baba
delete me.txt
moosanaeempc-lgtm Jan 16, 2026
43b3823
Add files via upload
moosanaeempc-lgtm Jan 16, 2026
3d63a75
delete me.txt
moosanaeempc-lgtm Jan 16, 2026
286d1ee
extensions.js
moosanaeempc-lgtm Jan 16, 2026
ceacc01
Update extensions.js
moosanaeempc-lgtm Jan 16, 2026
5bfa6a9
Update links-and-barcodes.js
moosanaeempc-lgtm Jan 16, 2026
2bba9d5
Update extensions.js
moosanaeempc-lgtm Jan 16, 2026
7c42de1
Rename links-&-barcodes.png to links-and-barcodes.png
moosanaeempc-lgtm Jan 16, 2026
9b9cc26
Update extensions.js
moosanaeempc-lgtm Jan 16, 2026
b58d4e1
Update links-and-barcodes.js
moosanaeempc-lgtm Jan 16, 2026
f83f70e
Update extensions.js
moosanaeempc-lgtm Jan 16, 2026
f7fe6da
Update links-and-barcodes.js
moosanaeempc-lgtm Jan 16, 2026
8dc6a89
Update links-and-barcodes.js
moosanaeempc-lgtm Jan 16, 2026
6839b5a
Update extensions.js
moosanaeempc-lgtm Jan 16, 2026
276d6ed
Update links-and-barcodes.js
moosanaeempc-lgtm Jan 16, 2026
32c2727
Update links-and-barcodes.js
moosanaeempc-lgtm Jan 20, 2026
381de1b
Update extensions.js
moosanaeempc-lgtm Jan 20, 2026
8a2ab44
Update links-and-barcodes.js
moosanaeempc-lgtm Jan 20, 2026
44f0552
Update links-and-barcodes.js
moosanaeempc-lgtm Jan 20, 2026
9566be0
Update links-and-barcodes.js
moosanaeempc-lgtm Jan 20, 2026
cb87ee9
Update links-and-barcodes.js
moosanaeempc-lgtm Jan 20, 2026
fb24a5a
Update links-and-barcodes.js
moosanaeempc-lgtm Jan 20, 2026
584daba
Update links-and-barcodes.js
moosanaeempc-lgtm Jan 20, 2026
38f41ce
Update links-and-barcodes.js
moosanaeempc-lgtm Jan 20, 2026
581bf2b
Update links-and-barcodes.js
moosanaeempc-lgtm Jan 21, 2026
d704a62
Update links-and-barcodes.js
moosanaeempc-lgtm Jan 21, 2026
65b1eba
Delete static/images/codemaster/links-and-barcodes.png
moosanaeempc-lgtm Jan 21, 2026
591c9f5
Create delete me
moosanaeempc-lgtm Jan 21, 2026
c4d4c08
Add files via upload
moosanaeempc-lgtm Jan 21, 2026
b6c66bd
Delete static/images/codemaster/delete me
moosanaeempc-lgtm Jan 21, 2026
64a0c03
Create delete me
moosanaeempc-lgtm Jan 21, 2026
407ac87
Delete static/images/codemaster/links-and-barcodes.png
moosanaeempc-lgtm Jan 21, 2026
d94c029
Add files via upload
moosanaeempc-lgtm Jan 21, 2026
619c56d
Delete static/images/codemaster/links-and-barcodes.png
moosanaeempc-lgtm Jan 21, 2026
cf8b24a
Add files via upload
moosanaeempc-lgtm Jan 21, 2026
f9ae104
Delete static/images/codemaster/delete me
moosanaeempc-lgtm Jan 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 9 additions & 49 deletions src/lib/extensions.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,23 +80,22 @@ export default [
creator: "Steve0Greatness",
isGitHub: true,
},

{
name: "Dictation",
description: "Convert your voice into text. (not supported in all browsers)",
code: "pooiod/Dictation.js",
banner: "pooiod/Dictation.svg",
creator: "pooiod7",
},
{
{
name: "Doodle Recognition",
description: "A implementation of Google's Quick Draw image vision model",
code: "TheShovel/doodlerec.js",
banner: "TheShovel/thumbnail-doodlerec.avif",
creator: "TheShovel",
isGitHub: true,
},
{
{
name: "Stylus",
description: "Get the pressure and tilt of a stylus or graphic tablet",
code: "sourdoggy/stylus extension.js",
Expand Down Expand Up @@ -152,31 +151,6 @@ export default [
banner: "dumzdev/removebgbanner.svg",
creator: "dumzdev",
},
/*{
name: "PenguinAI",
description: "Talk to AI! Use Models like DALL-E-3, GPT, LLama, Claude, and more!",
code: "MubiLop/penguingpt.js",
banner: "MubiLop/penguingpt.avif",
creator: "cicerorph",
creatorAlias: "MubiLop",
isGitHub: true,
unstable: true,
documentation: "PenguinAI",
unstableReason: "AI models can generate unintended or inappropriate output.\nSome AI models may also become temporarily inaccessible.\n\nUse at your own risk.",
},*/
/*
{
name: "Block AI",
description: "An AI powered chat bot to help you code in your projects.",
code: "TheShovel/blockAI.js",
banner: "TheShovel/thumbnail-blockAI.avif",
creator: "TheShovel",
creatorAlias: "TheShovel",
isGitHub: true,
unstable: true,
unstableReason: "The AI model can generate inaccurate output and broken syntax!",
},
*/
{
name: "PenguinHook",
description: "Send Webhook requests, that can be Discord or any type of webhook.",
Expand Down Expand Up @@ -548,28 +522,14 @@ export default [
isGitHub: true,
creatorAlias: "gaimerI17",
},
/* these extensions are completely dead as of now
{
name: "Online Captcha",
description: "Protect your project with simple, easy to use captcha implementation. Fully client-side, bypass-proof captcha solution!",
code: "NotHouse/OnlineCaptcha.js",
banner: "NotHouse/OnlineCaptcha-banner.avif",
creator: "enderhacker",
name: "Links & Barcodes",
description: "Blocks to open web links and generate scannable QR codes on the stage.",
code: "codemaster/links-and-barcodes.js",
banner: "codemaster/links-and-barcodes.png",
creator: "moosanaeempc-lgtm",
creatorAlias: "codemaster",
isGitHub: true,
isUnsandboxed: true,
},
{
name: "Better Storage",
description: "Like PenguinMod's Storage Extension, but with a couple more features, and faster servers.",
code: "Gen1x/better_storage.js",
banner: "Gen1x/betterstorage.avif",
creator: "G1nX",
},
{
name: "Mouth Washer",
description: "Includes many utilities related to cleaning bad words, swearing and profanity. Thought of as an extra layer of security for filtering messages.\n\n(ft. violet and jwklong)",
code: "Gen1x/mouth_washer.js",
banner: "Gen1x/mw-placeholder.avif",
creator: "G1nX",
},
*/
];
110 changes: 110 additions & 0 deletions static/extensions/codemaster/links-and-barcodes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
(function(Scratch) {
'use strict';

class BarcodeExtension {
constructor() {
this.activeBarcodes = [];
this.currentSize = 100;

if (Scratch.vm && Scratch.vm.runtime) {
Scratch.vm.runtime.on('PROJECT_START', () => this.deleteAllBarcodes());
Scratch.vm.runtime.on('PROJECT_STOP_ALL', () => this.deleteAllBarcodes());
}
}

getInfo() {
return {
id: 'moosanaeempcLinksAndBarcodes',
name: 'Links & Barcodes',
blocks: [
{
opcode: 'openLink',
blockType: Scratch.BlockType.COMMAND,
text: 'open link [URL]',
arguments: {
URL: { type: Scratch.ArgumentType.STRING, defaultValue: 'https://penguinmod.com' }
}
},
{
opcode: 'generateBarcode',
blockType: Scratch.BlockType.COMMAND,
text: 'generate barcode of link [URL] at x [X] y [Y]',
arguments: {
URL: { type: Scratch.ArgumentType.STRING, defaultValue: 'https://penguinmod.com' },
X: { type: Scratch.ArgumentType.NUMBER, defaultValue: 0 },
Y: { type: Scratch.ArgumentType.NUMBER, defaultValue: 0 }
}
},
{
opcode: 'setSize',
blockType: Scratch.BlockType.COMMAND,
text: 'set barcode size to [SIZE]',
arguments: {
SIZE: { type: Scratch.ArgumentType.NUMBER, defaultValue: 100, min: 5, max: 300 }
}
},
{
opcode: 'deleteAllBarcodes',
blockType: Scratch.BlockType.COMMAND,
text: 'delete all barcodes'
}
]
};
}

_clampSize(size) {
return Math.min(Math.max(Number(size), 5), 300);
}

openLink(args) {
const url = args.URL;
if (Scratch.openWindow) {
Scratch.openWindow(url);
} else {
window.open(url, '_blank', 'noopener,noreferrer');
}
}

generateBarcode(args) {
const stageLayer = document.querySelector('.stage_stage_2SR8W') ||
document.querySelector('[class*="stage_stage"]') ||
document.body;

const img = document.createElement('img');
img.src = `https://api.qrserver.com/v1/create-qr-code/?data=${encodeURIComponent(args.URL)}`;

img.style.position = 'absolute';
img.style.pointerEvents = 'auto';
img.style.zIndex = '10';

const left = 240 + Number(args.X);
const top = 180 - Number(args.Y);

img.style.left = `${(left / 480) * 100}%`;
img.style.top = `${(top / 360) * 100}%`;
img.style.transform = 'translate(-50%, -50%)';

const finalSize = this._clampSize(this.currentSize);
img.style.width = `${finalSize}px`;
img.style.height = 'auto';

stageLayer.appendChild(img);
this.activeBarcodes.push(img);
}

setSize(args) {
this.currentSize = this._clampSize(args.SIZE);
}

deleteAllBarcodes() {
this.activeBarcodes.forEach(el => {
if (el && el.parentNode) {
el.remove();
}
});
this.activeBarcodes = [];
}
}

Scratch.extensions.register(new BarcodeExtension());
})(Scratch);
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.