From ebe8889adff7018ad7e0969077cff71ce38107c1 Mon Sep 17 00:00:00 2001
From: Lemon <165233560+BludIsAnLemon@users.noreply.github.com>
Date: Wed, 12 Mar 2025 19:03:59 +0800
Subject: [PATCH 01/10] Create websockets-plus.js
---
extensions/Cheddarphanie/websockets-plus.js | 587 ++++++++++++++++++++
1 file changed, 587 insertions(+)
create mode 100644 extensions/Cheddarphanie/websockets-plus.js
diff --git a/extensions/Cheddarphanie/websockets-plus.js b/extensions/Cheddarphanie/websockets-plus.js
new file mode 100644
index 0000000000..c63ef73e47
--- /dev/null
+++ b/extensions/Cheddarphanie/websockets-plus.js
@@ -0,0 +1,587 @@
+// Name: WebSockets+
+// ID: lemonWebSocketsPlus
+// Description: Connect to more than one WebSockets.
+// By: Cheddarphanie
+// License: Apache-2.0
+
+(function(Scratch) {
+ 'use strict';
+
+ if(!Scratch.extensions.unsandboxed) {
+ throw new Error('The WebSockets+ Extension must run unsandboxed.')
+ }
+
+ const vm = Scratch.vm
+ const extManager = vm.extensionManager
+ const runtime = vm.runtime
+ const Cast = Scratch.Cast
+
+ const regenReporters = ["lemonWebSocketsPlus_socketMessage"]
+
+ if(Scratch.gui) Scratch.gui.getBlockly().then(SB => {
+ const ogCheck = SB.scratchBlocksUtils.isShadowArgumentReporter
+ SB.scratchBlocksUtils.isShadowArgumentReporter = function(block) {
+ const result = ogCheck(block)
+ if(result) return true
+ return block.isShadow() && regenReporters.includes(block.type)
+ }
+ })
+
+ const createLabel = txt => {
+ return {
+ blockType: Scratch.BlockType.LABEL,
+ text: txt
+ }
+ }
+
+ class WebsocketsPlusExt {
+ constructor() {
+ this.debugging = false
+
+ this.sockets = {}
+
+ this.lastMessages = {}
+
+ this.socketStatuses = {}
+
+ this.socketCloseCodes = {}
+
+ this.socketCloseReasons = {}
+
+ this.fetchables = {}
+
+ this.WebSocketStates = {
+ 0: 'CONNECTING',
+ 1: 'OPEN',
+ 2: 'CLOSING',
+ 3: 'CLOSED'
+ }
+ /**
+ *
+ * @param {string} socket
+ * @returns {Function}
+ */
+ this.listener = function(socket='') {
+ return function({ data }) {
+ runtime.startHats('lemonWebSocketsPlus_socketMessageReceived', {
+ SOCKET: socket
+ }).forEach(thread => {
+ thread.socketMessage = data
+ })
+ }
+ }
+ }
+ getInfo() {
+ return {
+ id: 'lemonWebSocketsPlus',
+ name: Scratch.translate('WebSockets+'),
+ color1: "#307eff",
+ color2: "#2c5eb0",
+ blocks: [
+ {
+ func: 'toggleDebugging',
+ blockType: Scratch.BlockType.BUTTON,
+ text: Scratch.translate('Toggle Debugging')
+ },
+
+ createLabel('Variables'),
+
+ {
+ opcode: 'websockets',
+ blockType: Scratch.BlockType.REPORTER,
+ text: Scratch.translate('websockets')
+ },
+ {
+ opcode: 'socketState',
+ blockType: Scratch.BlockType.REPORTER,
+ text: Scratch.translate('state of socket [SOCKET]'),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: 'socket'
+ }
+ }
+ },
+ {
+ opcode: 'socketLastMessage',
+ blockType: Scratch.BlockType.REPORTER,
+ text: Scratch.translate('last message received from socket [SOCKET]'),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: 'socket'
+ }
+ }
+ },
+ {
+ opcode: 'socketCloseReason',
+ blockType: Scratch.BlockType.REPORTER,
+ text: Scratch.translate('reason of socket [SOCKET] closing'),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: 'socket'
+ }
+ }
+ },
+ {
+ opcode: 'socketCloseCode',
+ blockType: Scratch.BlockType.REPORTER,
+ text: Scratch.translate('code of socket [SOCKET] closing'),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: 'socket'
+ }
+ }
+ },
+
+ '---',
+
+ createLabel(Scratch.translate('Blocks')),
+
+ {
+ opcode: 'connect',
+ blockType: Scratch.BlockType.COMMAND,
+ text: Scratch.translate('connect to [URL] with id [ID]'),
+ arguments: {
+ URL: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: 'wss://echo.websocket.org/'
+ },
+ ID: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: 'socket'
+ }
+ }
+ },
+ {
+ opcode: 'disconnect',
+ blockType: Scratch.BlockType.COMMAND,
+ text: Scratch.translate('close connection with socket [ID] with code [C] and reason [R]'),
+ arguments: {
+ ID: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: 'socket'
+ },
+ C: {
+ type: Scratch.ArgumentType.NUMBER,
+ defaultValue: 1000
+ },
+ R: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: 'fulfilled'
+ }
+ }
+ },
+ {
+ opcode: 'sendMessage',
+ blockType: Scratch.BlockType.COMMAND,
+ text: Scratch.translate('send message [MESSAGE] to socket [SOCKET]'),
+ arguments: {
+ MESSAGE: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: Scratch.translate('Hello :)')
+ },
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: 'socket'
+ }
+ }
+ },
+
+ '---',
+
+ createLabel(Scratch.translate('Booleans')),
+
+ {
+ opcode: 'socketExists',
+ blockType: Scratch.BlockType.BOOLEAN,
+ text: Scratch.translate('socket [SOCKET] exists?'),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: 'socket'
+ }
+ }
+ },
+ {
+ opcode: 'socketConnected',
+ blockType: Scratch.BlockType.BOOLEAN,
+ text: Scratch.translate('connected to socket [SOCKET]?'),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: 'socket'
+ }
+ }
+ },
+ {
+ opcode: 'socketClosed',
+ blockType: Scratch.BlockType.BOOLEAN,
+ text: Scratch.translate('closed connection with [SOCKET]?'),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: 'socket'
+ }
+ }
+ },
+
+ '---',
+
+ createLabel(Scratch.translate('Events')),
+
+ {
+ opcode: 'socketMessageReceived',
+ blockType: Scratch.BlockType.EVENT,
+ text: Scratch.translate('when i receive a message from [SOCKET] [MESSAGE]'),
+ isEdgeActivated: false,
+ hideFromPalette: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ menu: 'socketMenu'
+ },
+ MESSAGE: {}
+ }
+ },
+ {
+ opcode: 'socketMessage',
+ blockType: Scratch.BlockType.REPORTER,
+ text: Scratch.translate('message'),
+ hideFromPalette: true,
+ disableMonitor: true
+ },
+ {
+ opcode: 'socketOpensConnection',
+ blockType: Scratch.BlockType.EVENT,
+ text: Scratch.translate('when connection with [SOCKET] opens'),
+ isEdgeActivated: false,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ menu: 'socketMenu'
+ }
+ }
+ },
+ {
+ blockType: Scratch.BlockType.XML,
+ xml: `
+
+
+
+ `
+ },
+ {
+ opcode: 'socketErrored',
+ blockType: Scratch.BlockType.EVENT,
+ text: Scratch.translate('when socket [SOCKET] errors'),
+ isEdgeActivated: false,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ menu: 'socketMenu'
+ },
+ }
+ },
+ {
+ opcode: 'socketClosedConnection',
+ blockType: Scratch.BlockType.EVENT,
+ text: Scratch.translate('when connection with [SOCKET] closes'),
+ isEdgeActivated: false,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ menu: 'socketMenu'
+ },
+ }
+ },
+ ],
+ menus: {
+ socketMenu: {
+ items: 'getSockets',
+ }
+ }
+ }
+ }
+
+ toggleDebugging() {
+ this.debugging = !this.debugging
+ window.alert(Scratch.translate('Toggled Debugging! :)'))
+ }
+
+ async connect({ ID, URL }) {
+ const id = Cast.toString(ID)
+ const url = Cast.toString(URL)
+
+ if(this.sockets[id] instanceof WebSocket) {
+ try {
+ this.sockets[id].removeEventListener('message', this.listener(id))
+ this.sockets[id].removeEventListener('error', () => {
+ runtime.startHats('lemonWebSocketsPlus_socketErrored', {
+ SOCKET: id
+ })
+ })
+ this.sockets[id].removeEventListener('message', ({data}) => {
+ this.lastMessages[id] = data
+ })
+ this.sockets[id].removeEventListener('close', ({reason, code}) => {
+ runtime.startHats('lemonWebSocketsPlus_socketClosedConnection', {
+ SOCKET: id
+ })
+ this.socketCloseReasons[id] = reason
+ this.socketCloseCodes[id] = code
+ })
+ this.sockets[id].removeEventListener('open', () => {
+ runtime.startHats('lemonWebSocketsPlus_socketOpensConnection', {
+ SOCKET: id
+ })
+ })
+ this.sockets[id].close()
+ } catch(err) {
+ console.error(err)
+ }
+ }
+
+ if(this.debugging) console.groupCollapsed('WebSockets+ Connecting')
+
+ if(this.debugging) console.log(`[WebSockets+] Attempting to connect to '${url}'..`)
+
+ if(!this.fetchables[url]) this.fetchables[url] = await Scratch.canFetch(url)
+
+ if(!this.fetchables[url]) {
+ this.socketStatuses[id] = 'failed to connect'
+ console.log(`[Websockets+] Connection to '${url}' denied!`)
+ if(this.debugging) console.groupEnd()
+ return
+ }
+
+ try {
+
+ this.sockets[id] = new WebSocket(url)
+ this.socketStatuses[id] = 'connected'
+ this.socketCloseCodes[id] = 0
+ this.socketCloseReasons[id] = ''
+
+ /**
+ * @type {WebSocket}
+ */
+ const socket = this.sockets[id]
+
+ socket.addEventListener('message', this.listener(id))
+ socket.addEventListener('error', () => {
+ runtime.startHats('lemonWebSocketsPlus_socketErrored', {
+ SOCKET: id
+ })
+ })
+ socket.addEventListener('message', ({data}) => {
+ this.lastMessages[id] = data
+ })
+ socket.addEventListener('close', ({reason, code}) => {
+ runtime.startHats('lemonWebSocketsPlus_socketClosedConnection', {
+ SOCKET: id
+ })
+ this.socketCloseReasons[id] = reason
+ this.socketCloseCodes[id] = code
+ })
+ socket.addEventListener('open', () => {
+ runtime.startHats('lemonWebSocketsPlus_socketOpensConnection', {
+ SOCKET: id
+ })
+ })
+
+ extManager.refreshBlocks('lemonWebSocketsPlus')
+ vm.refreshWorkspace()
+
+ if(this.debugging) console.log(`[WebSockets+] Successfully connected to '${url}'.`)
+ } catch(err) {
+ console.error(err)
+ this.socketStatuses[id] = 'failed to connect'
+ }
+
+ if(this.debugging) console.groupEnd()
+ }
+
+ disconnect({ ID, C, R }) {
+ const id = Cast.toString(ID)
+ const Code = Cast.toNumber(C)
+ const Reason = Cast.toString(R)
+
+ if(this.debugging) console.groupCollapsed('WebSockets+ Closing Connection')
+
+ if(this.debugging) console.log(`[WebSockets+] Attemping to close connection with '${id}'..`)
+
+ const socket = this.sockets[id]
+
+ if(socket instanceof WebSocket) {
+
+ socket.removeEventListener('message', this.listener(id))
+ socket.removeEventListener('error', () => {
+ runtime.startHats('lemonWebSocketsPlus_socketErrored', {
+ SOCKET: id
+ })
+ })
+ socket.removeEventListener('message', ({data}) => {
+ this.lastMessages[id] = data
+ })
+ socket.removeEventListener('close', ({reason, code}) => {
+ runtime.startHats('lemonWebSocketsPlus_socketClosedConnection', {
+ SOCKET: id
+ })
+ this.socketCloseReasons[id] = reason
+ this.socketCloseCodes[id] = code
+ })
+ socket.removeEventListener('open', () => {
+ runtime.startHats('lemonWebSocketsPlus_socketOpensConnection', {
+ SOCKET: id
+ })
+ })
+
+ socket.close(Code, Reason)
+
+ delete this.sockets[id]
+ this.socketCloseCodes[id] = Code
+ this.socketCloseReasons[id] = Reason
+ this.socketStatuses[id] = 'closed'
+
+ extManager.refreshBlocks('lemonWebSocketsPlus')
+ vm.refreshWorkspace()
+
+ if(this.debugging) console.log(`[WebSockets+] Successfully closed connection with '${id}'!`)
+ } else {
+ if(this.debugging) console.warn(`[WebSockets+] WebSocket '${id}' is not a WebSocket!`)
+ }
+
+ if(this.debugging) console.groupEnd()
+
+ return
+ }
+
+ sendMessage({ MESSAGE, SOCKET }) {
+ if(this.debugging) {
+ console.groupCollapsed('WebSockets+ Message Sending')
+
+ console.log(`[WebSockets+] Attempting to send a message to '${SOCKET}'..`)
+ }
+ SOCKET = Cast.toString(SOCKET)
+ const socket = this.sockets[SOCKET]
+
+ if(!socket) {
+ if(this.debugging) {
+ console.warn(`[WebSockets+] '${SOCKET}' doesn't exist!`)
+ console.groupEnd()
+ }
+ return
+ }
+
+ if(socket instanceof WebSocket) {
+ try {
+ socket.send(MESSAGE)
+ if(this.debugging) console.log(`[WebSockets+] Successfully sent a message to '${SOCKET}'!`)
+ } catch(err) {
+ console.error(err)
+ if(this.debugging) console.groupEnd()
+ }
+ } else {
+ if(this.debugging) console.warn(`[WebSockets+] '${SOCKET}' isn't a WebSocket!`)
+ }
+ if(this.debugging) console.groupEnd()
+ }
+
+ socketExists({ SOCKET }) {
+ return Cast.toBoolean(this.sockets[Cast.toString(SOCKET)])
+ }
+
+ socketConnected({ SOCKET }) {
+ const socket = this.sockets[Cast.toString(SOCKET)]
+
+ if(socket instanceof WebSocket) {
+ return socket.readyState === WebSocket.OPEN
+ }
+
+ return false
+ }
+
+ socketClosed({ SOCKET }) {
+ const socket = this.sockets[Cast.toString(SOCKET)]
+
+ if(socket instanceof WebSocket) {
+ return socket.readyState === WebSocket.CLOSED
+ }
+
+ return true
+ }
+
+ websockets() {
+ return JSON.stringify(Object.keys(this.sockets))
+ }
+
+ socketState({ SOCKET }) {
+ const socket = this.sockets[Cast.toString(SOCKET)]
+ if(socket instanceof WebSocket) {
+ return this.WebSocketStates[socket.readyState] ?? 'UNKNOWN'
+ }
+ return 'UNKNOWN'
+ }
+
+ socketLastMessage({ SOCKET }) {
+ const socket = this.lastMessages[Cast.toString(SOCKET)]
+ return socket ?? ''
+ }
+
+ socketCloseReason({ SOCKET }) {
+ return this.socketCloseReasons[Cast.toString(SOCKET)] ?? ''
+ }
+
+ socketCloseCode({ SOCKET }) {
+ return this.socketCloseCodes[Cast.toString(SOCKET)] ?? 0
+ }
+
+ getSockets() {
+ const Sockets = Object.keys(this.sockets)
+ return Sockets.length > 0 ? Sockets.map((socket) => {
+ return {
+ value: socket,
+ text: socket
+ }
+ }) : [{
+ value: Scratch.translate('None yet :('),
+ text: Scratch.translate('None yet :(')
+ }]
+ }
+
+ /**
+ * @param {{}} args
+ * @param {VM.BlockUtility} util
+ */
+ socketMessage(args, util) {
+ return util.thread.socketMessage ?? ''
+ }
+
+ socketOpensConnection() {
+ return
+ }
+
+ socketMessageReceived() {
+ return
+ }
+
+ socketErrored() {
+ return
+ }
+
+ socketClosedConnection() {
+ return
+ }
+ }
+
+ Scratch.extensions.register(new WebsocketsPlusExt())
+})(Scratch)
From 13192ce9ca13f1869a9ee2b2d4bdc0335fe81136 Mon Sep 17 00:00:00 2001
From: Lemon <165233560+BludIsAnLemon@users.noreply.github.com>
Date: Wed, 12 Mar 2025 19:05:49 +0800
Subject: [PATCH 02/10] Update extensions.json
---
extensions/extensions.json | 1 +
1 file changed, 1 insertion(+)
diff --git a/extensions/extensions.json b/extensions/extensions.json
index d8ed71e33d..2a79f01fc7 100644
--- a/extensions/extensions.json
+++ b/extensions/extensions.json
@@ -89,6 +89,7 @@
"vercte/dictionaries",
"godslayerakp/http",
"godslayerakp/ws",
+ "Cheddarphanie/websockets-plus",
"Lily/CommentBlocks",
"veggiecan/LongmanDictionary",
"CubesterYT/TurboHook",
From 3d1a23356a766a5e2430b116569d320d2636feec Mon Sep 17 00:00:00 2001
From: "DangoCat[bot]"
Date: Wed, 12 Mar 2025 11:10:44 +0000
Subject: [PATCH 03/10] [Automated] Format code
---
extensions/Cheddarphanie/websockets-plus.js | 1132 ++++++++++---------
1 file changed, 581 insertions(+), 551 deletions(-)
diff --git a/extensions/Cheddarphanie/websockets-plus.js b/extensions/Cheddarphanie/websockets-plus.js
index c63ef73e47..a64817696d 100644
--- a/extensions/Cheddarphanie/websockets-plus.js
+++ b/extensions/Cheddarphanie/websockets-plus.js
@@ -4,584 +4,614 @@
// By: Cheddarphanie
// License: Apache-2.0
-(function(Scratch) {
- 'use strict';
+(function (Scratch) {
+ "use strict";
+
+ if (!Scratch.extensions.unsandboxed) {
+ throw new Error("The WebSockets+ Extension must run unsandboxed.");
+ }
+
+ const vm = Scratch.vm;
+ const extManager = vm.extensionManager;
+ const runtime = vm.runtime;
+ const Cast = Scratch.Cast;
+
+ const regenReporters = ["lemonWebSocketsPlus_socketMessage"];
+
+ if (Scratch.gui)
+ Scratch.gui.getBlockly().then((SB) => {
+ const ogCheck = SB.scratchBlocksUtils.isShadowArgumentReporter;
+ SB.scratchBlocksUtils.isShadowArgumentReporter = function (block) {
+ const result = ogCheck(block);
+ if (result) return true;
+ return block.isShadow() && regenReporters.includes(block.type);
+ };
+ });
+
+ const createLabel = (txt) => {
+ return {
+ blockType: Scratch.BlockType.LABEL,
+ text: txt,
+ };
+ };
+
+ class WebsocketsPlusExt {
+ constructor() {
+ this.debugging = false;
+
+ this.sockets = {};
+
+ this.lastMessages = {};
+
+ this.socketStatuses = {};
+
+ this.socketCloseCodes = {};
+
+ this.socketCloseReasons = {};
+
+ this.fetchables = {};
+
+ this.WebSocketStates = {
+ 0: "CONNECTING",
+ 1: "OPEN",
+ 2: "CLOSING",
+ 3: "CLOSED",
+ };
+ /**
+ *
+ * @param {string} socket
+ * @returns {Function}
+ */
+ this.listener = function (socket = "") {
+ return function ({ data }) {
+ runtime
+ .startHats("lemonWebSocketsPlus_socketMessageReceived", {
+ SOCKET: socket,
+ })
+ .forEach((thread) => {
+ thread.socketMessage = data;
+ });
+ };
+ };
+ }
+ getInfo() {
+ return {
+ id: "lemonWebSocketsPlus",
+ name: Scratch.translate("WebSockets+"),
+ color1: "#307eff",
+ color2: "#2c5eb0",
+ blocks: [
+ {
+ func: "toggleDebugging",
+ blockType: Scratch.BlockType.BUTTON,
+ text: Scratch.translate("Toggle Debugging"),
+ },
+
+ createLabel("Variables"),
+
+ {
+ opcode: "websockets",
+ blockType: Scratch.BlockType.REPORTER,
+ text: Scratch.translate("websockets"),
+ },
+ {
+ opcode: "socketState",
+ blockType: Scratch.BlockType.REPORTER,
+ text: Scratch.translate("state of socket [SOCKET]"),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
+ },
+ },
+ },
+ {
+ opcode: "socketLastMessage",
+ blockType: Scratch.BlockType.REPORTER,
+ text: Scratch.translate(
+ "last message received from socket [SOCKET]"
+ ),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
+ },
+ },
+ },
+ {
+ opcode: "socketCloseReason",
+ blockType: Scratch.BlockType.REPORTER,
+ text: Scratch.translate("reason of socket [SOCKET] closing"),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
+ },
+ },
+ },
+ {
+ opcode: "socketCloseCode",
+ blockType: Scratch.BlockType.REPORTER,
+ text: Scratch.translate("code of socket [SOCKET] closing"),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
+ },
+ },
+ },
+
+ "---",
+
+ createLabel(Scratch.translate("Blocks")),
+
+ {
+ opcode: "connect",
+ blockType: Scratch.BlockType.COMMAND,
+ text: Scratch.translate("connect to [URL] with id [ID]"),
+ arguments: {
+ URL: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "wss://echo.websocket.org/",
+ },
+ ID: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
+ },
+ },
+ },
+ {
+ opcode: "disconnect",
+ blockType: Scratch.BlockType.COMMAND,
+ text: Scratch.translate(
+ "close connection with socket [ID] with code [C] and reason [R]"
+ ),
+ arguments: {
+ ID: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
+ },
+ C: {
+ type: Scratch.ArgumentType.NUMBER,
+ defaultValue: 1000,
+ },
+ R: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "fulfilled",
+ },
+ },
+ },
+ {
+ opcode: "sendMessage",
+ blockType: Scratch.BlockType.COMMAND,
+ text: Scratch.translate(
+ "send message [MESSAGE] to socket [SOCKET]"
+ ),
+ arguments: {
+ MESSAGE: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: Scratch.translate("Hello :)"),
+ },
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
+ },
+ },
+ },
+
+ "---",
+
+ createLabel(Scratch.translate("Booleans")),
+
+ {
+ opcode: "socketExists",
+ blockType: Scratch.BlockType.BOOLEAN,
+ text: Scratch.translate("socket [SOCKET] exists?"),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
+ },
+ },
+ },
+ {
+ opcode: "socketConnected",
+ blockType: Scratch.BlockType.BOOLEAN,
+ text: Scratch.translate("connected to socket [SOCKET]?"),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
+ },
+ },
+ },
+ {
+ opcode: "socketClosed",
+ blockType: Scratch.BlockType.BOOLEAN,
+ text: Scratch.translate("closed connection with [SOCKET]?"),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
+ },
+ },
+ },
+
+ "---",
+
+ createLabel(Scratch.translate("Events")),
+
+ {
+ opcode: "socketMessageReceived",
+ blockType: Scratch.BlockType.EVENT,
+ text: Scratch.translate(
+ "when i receive a message from [SOCKET] [MESSAGE]"
+ ),
+ isEdgeActivated: false,
+ hideFromPalette: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ menu: "socketMenu",
+ },
+ MESSAGE: {},
+ },
+ },
+ {
+ opcode: "socketMessage",
+ blockType: Scratch.BlockType.REPORTER,
+ text: Scratch.translate("message"),
+ hideFromPalette: true,
+ disableMonitor: true,
+ },
+ {
+ opcode: "socketOpensConnection",
+ blockType: Scratch.BlockType.EVENT,
+ text: Scratch.translate("when connection with [SOCKET] opens"),
+ isEdgeActivated: false,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ menu: "socketMenu",
+ },
+ },
+ },
+ {
+ blockType: Scratch.BlockType.XML,
+ xml: `
+
+
+
+ `,
+ },
+ {
+ opcode: "socketErrored",
+ blockType: Scratch.BlockType.EVENT,
+ text: Scratch.translate("when socket [SOCKET] errors"),
+ isEdgeActivated: false,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ menu: "socketMenu",
+ },
+ },
+ },
+ {
+ opcode: "socketClosedConnection",
+ blockType: Scratch.BlockType.EVENT,
+ text: Scratch.translate("when connection with [SOCKET] closes"),
+ isEdgeActivated: false,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ menu: "socketMenu",
+ },
+ },
+ },
+ ],
+ menus: {
+ socketMenu: {
+ items: "getSockets",
+ },
+ },
+ };
+ }
- if(!Scratch.extensions.unsandboxed) {
- throw new Error('The WebSockets+ Extension must run unsandboxed.')
+ toggleDebugging() {
+ this.debugging = !this.debugging;
+ window.alert(Scratch.translate("Toggled Debugging! :)"));
}
- const vm = Scratch.vm
- const extManager = vm.extensionManager
- const runtime = vm.runtime
- const Cast = Scratch.Cast
+ async connect({ ID, URL }) {
+ const id = Cast.toString(ID);
+ const url = Cast.toString(URL);
+
+ if (this.sockets[id] instanceof WebSocket) {
+ try {
+ this.sockets[id].removeEventListener("message", this.listener(id));
+ this.sockets[id].removeEventListener("error", () => {
+ runtime.startHats("lemonWebSocketsPlus_socketErrored", {
+ SOCKET: id,
+ });
+ });
+ this.sockets[id].removeEventListener("message", ({ data }) => {
+ this.lastMessages[id] = data;
+ });
+ this.sockets[id].removeEventListener("close", ({ reason, code }) => {
+ runtime.startHats("lemonWebSocketsPlus_socketClosedConnection", {
+ SOCKET: id,
+ });
+ this.socketCloseReasons[id] = reason;
+ this.socketCloseCodes[id] = code;
+ });
+ this.sockets[id].removeEventListener("open", () => {
+ runtime.startHats("lemonWebSocketsPlus_socketOpensConnection", {
+ SOCKET: id,
+ });
+ });
+ this.sockets[id].close();
+ } catch (err) {
+ console.error(err);
+ }
+ }
- const regenReporters = ["lemonWebSocketsPlus_socketMessage"]
+ if (this.debugging) console.groupCollapsed("WebSockets+ Connecting");
- if(Scratch.gui) Scratch.gui.getBlockly().then(SB => {
- const ogCheck = SB.scratchBlocksUtils.isShadowArgumentReporter
- SB.scratchBlocksUtils.isShadowArgumentReporter = function(block) {
- const result = ogCheck(block)
- if(result) return true
- return block.isShadow() && regenReporters.includes(block.type)
- }
- })
+ if (this.debugging)
+ console.log(`[WebSockets+] Attempting to connect to '${url}'..`);
- const createLabel = txt => {
- return {
- blockType: Scratch.BlockType.LABEL,
- text: txt
- }
+ if (!this.fetchables[url])
+ this.fetchables[url] = await Scratch.canFetch(url);
+
+ if (!this.fetchables[url]) {
+ this.socketStatuses[id] = "failed to connect";
+ console.log(`[Websockets+] Connection to '${url}' denied!`);
+ if (this.debugging) console.groupEnd();
+ return;
+ }
+
+ try {
+ this.sockets[id] = new WebSocket(url);
+ this.socketStatuses[id] = "connected";
+ this.socketCloseCodes[id] = 0;
+ this.socketCloseReasons[id] = "";
+
+ /**
+ * @type {WebSocket}
+ */
+ const socket = this.sockets[id];
+
+ socket.addEventListener("message", this.listener(id));
+ socket.addEventListener("error", () => {
+ runtime.startHats("lemonWebSocketsPlus_socketErrored", {
+ SOCKET: id,
+ });
+ });
+ socket.addEventListener("message", ({ data }) => {
+ this.lastMessages[id] = data;
+ });
+ socket.addEventListener("close", ({ reason, code }) => {
+ runtime.startHats("lemonWebSocketsPlus_socketClosedConnection", {
+ SOCKET: id,
+ });
+ this.socketCloseReasons[id] = reason;
+ this.socketCloseCodes[id] = code;
+ });
+ socket.addEventListener("open", () => {
+ runtime.startHats("lemonWebSocketsPlus_socketOpensConnection", {
+ SOCKET: id,
+ });
+ });
+
+ extManager.refreshBlocks("lemonWebSocketsPlus");
+ vm.refreshWorkspace();
+
+ if (this.debugging)
+ console.log(`[WebSockets+] Successfully connected to '${url}'.`);
+ } catch (err) {
+ console.error(err);
+ this.socketStatuses[id] = "failed to connect";
+ }
+
+ if (this.debugging) console.groupEnd();
}
- class WebsocketsPlusExt {
- constructor() {
- this.debugging = false
-
- this.sockets = {}
-
- this.lastMessages = {}
-
- this.socketStatuses = {}
-
- this.socketCloseCodes = {}
-
- this.socketCloseReasons = {}
-
- this.fetchables = {}
-
- this.WebSocketStates = {
- 0: 'CONNECTING',
- 1: 'OPEN',
- 2: 'CLOSING',
- 3: 'CLOSED'
- }
- /**
- *
- * @param {string} socket
- * @returns {Function}
- */
- this.listener = function(socket='') {
- return function({ data }) {
- runtime.startHats('lemonWebSocketsPlus_socketMessageReceived', {
- SOCKET: socket
- }).forEach(thread => {
- thread.socketMessage = data
- })
- }
- }
+ disconnect({ ID, C, R }) {
+ const id = Cast.toString(ID);
+ const Code = Cast.toNumber(C);
+ const Reason = Cast.toString(R);
+
+ if (this.debugging)
+ console.groupCollapsed("WebSockets+ Closing Connection");
+
+ if (this.debugging)
+ console.log(
+ `[WebSockets+] Attemping to close connection with '${id}'..`
+ );
+
+ const socket = this.sockets[id];
+
+ if (socket instanceof WebSocket) {
+ socket.removeEventListener("message", this.listener(id));
+ socket.removeEventListener("error", () => {
+ runtime.startHats("lemonWebSocketsPlus_socketErrored", {
+ SOCKET: id,
+ });
+ });
+ socket.removeEventListener("message", ({ data }) => {
+ this.lastMessages[id] = data;
+ });
+ socket.removeEventListener("close", ({ reason, code }) => {
+ runtime.startHats("lemonWebSocketsPlus_socketClosedConnection", {
+ SOCKET: id,
+ });
+ this.socketCloseReasons[id] = reason;
+ this.socketCloseCodes[id] = code;
+ });
+ socket.removeEventListener("open", () => {
+ runtime.startHats("lemonWebSocketsPlus_socketOpensConnection", {
+ SOCKET: id,
+ });
+ });
+
+ socket.close(Code, Reason);
+
+ delete this.sockets[id];
+ this.socketCloseCodes[id] = Code;
+ this.socketCloseReasons[id] = Reason;
+ this.socketStatuses[id] = "closed";
+
+ extManager.refreshBlocks("lemonWebSocketsPlus");
+ vm.refreshWorkspace();
+
+ if (this.debugging)
+ console.log(
+ `[WebSockets+] Successfully closed connection with '${id}'!`
+ );
+ } else {
+ if (this.debugging)
+ console.warn(`[WebSockets+] WebSocket '${id}' is not a WebSocket!`);
+ }
+
+ if (this.debugging) console.groupEnd();
+
+ return;
+ }
+
+ sendMessage({ MESSAGE, SOCKET }) {
+ if (this.debugging) {
+ console.groupCollapsed("WebSockets+ Message Sending");
+
+ console.log(
+ `[WebSockets+] Attempting to send a message to '${SOCKET}'..`
+ );
+ }
+ SOCKET = Cast.toString(SOCKET);
+ const socket = this.sockets[SOCKET];
+
+ if (!socket) {
+ if (this.debugging) {
+ console.warn(`[WebSockets+] '${SOCKET}' doesn't exist!`);
+ console.groupEnd();
}
- getInfo() {
- return {
- id: 'lemonWebSocketsPlus',
- name: Scratch.translate('WebSockets+'),
- color1: "#307eff",
- color2: "#2c5eb0",
- blocks: [
- {
- func: 'toggleDebugging',
- blockType: Scratch.BlockType.BUTTON,
- text: Scratch.translate('Toggle Debugging')
- },
-
- createLabel('Variables'),
-
- {
- opcode: 'websockets',
- blockType: Scratch.BlockType.REPORTER,
- text: Scratch.translate('websockets')
- },
- {
- opcode: 'socketState',
- blockType: Scratch.BlockType.REPORTER,
- text: Scratch.translate('state of socket [SOCKET]'),
- disableMonitor: true,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: 'socket'
- }
- }
- },
- {
- opcode: 'socketLastMessage',
- blockType: Scratch.BlockType.REPORTER,
- text: Scratch.translate('last message received from socket [SOCKET]'),
- disableMonitor: true,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: 'socket'
- }
- }
- },
- {
- opcode: 'socketCloseReason',
- blockType: Scratch.BlockType.REPORTER,
- text: Scratch.translate('reason of socket [SOCKET] closing'),
- disableMonitor: true,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: 'socket'
- }
- }
- },
- {
- opcode: 'socketCloseCode',
- blockType: Scratch.BlockType.REPORTER,
- text: Scratch.translate('code of socket [SOCKET] closing'),
- disableMonitor: true,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: 'socket'
- }
- }
- },
-
- '---',
-
- createLabel(Scratch.translate('Blocks')),
-
- {
- opcode: 'connect',
- blockType: Scratch.BlockType.COMMAND,
- text: Scratch.translate('connect to [URL] with id [ID]'),
- arguments: {
- URL: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: 'wss://echo.websocket.org/'
- },
- ID: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: 'socket'
- }
- }
- },
- {
- opcode: 'disconnect',
- blockType: Scratch.BlockType.COMMAND,
- text: Scratch.translate('close connection with socket [ID] with code [C] and reason [R]'),
- arguments: {
- ID: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: 'socket'
- },
- C: {
- type: Scratch.ArgumentType.NUMBER,
- defaultValue: 1000
- },
- R: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: 'fulfilled'
- }
- }
- },
- {
- opcode: 'sendMessage',
- blockType: Scratch.BlockType.COMMAND,
- text: Scratch.translate('send message [MESSAGE] to socket [SOCKET]'),
- arguments: {
- MESSAGE: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: Scratch.translate('Hello :)')
- },
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: 'socket'
- }
- }
- },
-
- '---',
-
- createLabel(Scratch.translate('Booleans')),
-
- {
- opcode: 'socketExists',
- blockType: Scratch.BlockType.BOOLEAN,
- text: Scratch.translate('socket [SOCKET] exists?'),
- disableMonitor: true,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: 'socket'
- }
- }
- },
- {
- opcode: 'socketConnected',
- blockType: Scratch.BlockType.BOOLEAN,
- text: Scratch.translate('connected to socket [SOCKET]?'),
- disableMonitor: true,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: 'socket'
- }
- }
- },
- {
- opcode: 'socketClosed',
- blockType: Scratch.BlockType.BOOLEAN,
- text: Scratch.translate('closed connection with [SOCKET]?'),
- disableMonitor: true,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: 'socket'
- }
- }
- },
-
- '---',
-
- createLabel(Scratch.translate('Events')),
-
- {
- opcode: 'socketMessageReceived',
- blockType: Scratch.BlockType.EVENT,
- text: Scratch.translate('when i receive a message from [SOCKET] [MESSAGE]'),
- isEdgeActivated: false,
- hideFromPalette: true,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- menu: 'socketMenu'
- },
- MESSAGE: {}
- }
- },
- {
- opcode: 'socketMessage',
- blockType: Scratch.BlockType.REPORTER,
- text: Scratch.translate('message'),
- hideFromPalette: true,
- disableMonitor: true
- },
- {
- opcode: 'socketOpensConnection',
- blockType: Scratch.BlockType.EVENT,
- text: Scratch.translate('when connection with [SOCKET] opens'),
- isEdgeActivated: false,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- menu: 'socketMenu'
- }
- }
- },
- {
- blockType: Scratch.BlockType.XML,
- xml: `
-
-
-
- `
- },
- {
- opcode: 'socketErrored',
- blockType: Scratch.BlockType.EVENT,
- text: Scratch.translate('when socket [SOCKET] errors'),
- isEdgeActivated: false,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- menu: 'socketMenu'
- },
- }
- },
- {
- opcode: 'socketClosedConnection',
- blockType: Scratch.BlockType.EVENT,
- text: Scratch.translate('when connection with [SOCKET] closes'),
- isEdgeActivated: false,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- menu: 'socketMenu'
- },
- }
- },
- ],
- menus: {
- socketMenu: {
- items: 'getSockets',
- }
- }
- }
+ return;
+ }
+
+ if (socket instanceof WebSocket) {
+ try {
+ socket.send(MESSAGE);
+ if (this.debugging)
+ console.log(
+ `[WebSockets+] Successfully sent a message to '${SOCKET}'!`
+ );
+ } catch (err) {
+ console.error(err);
+ if (this.debugging) console.groupEnd();
}
+ } else {
+ if (this.debugging)
+ console.warn(`[WebSockets+] '${SOCKET}' isn't a WebSocket!`);
+ }
+ if (this.debugging) console.groupEnd();
+ }
- toggleDebugging() {
- this.debugging = !this.debugging
- window.alert(Scratch.translate('Toggled Debugging! :)'))
- }
+ socketExists({ SOCKET }) {
+ return Cast.toBoolean(this.sockets[Cast.toString(SOCKET)]);
+ }
- async connect({ ID, URL }) {
- const id = Cast.toString(ID)
- const url = Cast.toString(URL)
-
- if(this.sockets[id] instanceof WebSocket) {
- try {
- this.sockets[id].removeEventListener('message', this.listener(id))
- this.sockets[id].removeEventListener('error', () => {
- runtime.startHats('lemonWebSocketsPlus_socketErrored', {
- SOCKET: id
- })
- })
- this.sockets[id].removeEventListener('message', ({data}) => {
- this.lastMessages[id] = data
- })
- this.sockets[id].removeEventListener('close', ({reason, code}) => {
- runtime.startHats('lemonWebSocketsPlus_socketClosedConnection', {
- SOCKET: id
- })
- this.socketCloseReasons[id] = reason
- this.socketCloseCodes[id] = code
- })
- this.sockets[id].removeEventListener('open', () => {
- runtime.startHats('lemonWebSocketsPlus_socketOpensConnection', {
- SOCKET: id
- })
- })
- this.sockets[id].close()
- } catch(err) {
- console.error(err)
- }
- }
-
- if(this.debugging) console.groupCollapsed('WebSockets+ Connecting')
-
- if(this.debugging) console.log(`[WebSockets+] Attempting to connect to '${url}'..`)
-
- if(!this.fetchables[url]) this.fetchables[url] = await Scratch.canFetch(url)
-
- if(!this.fetchables[url]) {
- this.socketStatuses[id] = 'failed to connect'
- console.log(`[Websockets+] Connection to '${url}' denied!`)
- if(this.debugging) console.groupEnd()
- return
- }
-
- try {
-
- this.sockets[id] = new WebSocket(url)
- this.socketStatuses[id] = 'connected'
- this.socketCloseCodes[id] = 0
- this.socketCloseReasons[id] = ''
-
- /**
- * @type {WebSocket}
- */
- const socket = this.sockets[id]
-
- socket.addEventListener('message', this.listener(id))
- socket.addEventListener('error', () => {
- runtime.startHats('lemonWebSocketsPlus_socketErrored', {
- SOCKET: id
- })
- })
- socket.addEventListener('message', ({data}) => {
- this.lastMessages[id] = data
- })
- socket.addEventListener('close', ({reason, code}) => {
- runtime.startHats('lemonWebSocketsPlus_socketClosedConnection', {
- SOCKET: id
- })
- this.socketCloseReasons[id] = reason
- this.socketCloseCodes[id] = code
- })
- socket.addEventListener('open', () => {
- runtime.startHats('lemonWebSocketsPlus_socketOpensConnection', {
- SOCKET: id
- })
- })
-
- extManager.refreshBlocks('lemonWebSocketsPlus')
- vm.refreshWorkspace()
-
- if(this.debugging) console.log(`[WebSockets+] Successfully connected to '${url}'.`)
- } catch(err) {
- console.error(err)
- this.socketStatuses[id] = 'failed to connect'
- }
-
- if(this.debugging) console.groupEnd()
- }
+ socketConnected({ SOCKET }) {
+ const socket = this.sockets[Cast.toString(SOCKET)];
- disconnect({ ID, C, R }) {
- const id = Cast.toString(ID)
- const Code = Cast.toNumber(C)
- const Reason = Cast.toString(R)
-
- if(this.debugging) console.groupCollapsed('WebSockets+ Closing Connection')
-
- if(this.debugging) console.log(`[WebSockets+] Attemping to close connection with '${id}'..`)
-
- const socket = this.sockets[id]
-
- if(socket instanceof WebSocket) {
-
- socket.removeEventListener('message', this.listener(id))
- socket.removeEventListener('error', () => {
- runtime.startHats('lemonWebSocketsPlus_socketErrored', {
- SOCKET: id
- })
- })
- socket.removeEventListener('message', ({data}) => {
- this.lastMessages[id] = data
- })
- socket.removeEventListener('close', ({reason, code}) => {
- runtime.startHats('lemonWebSocketsPlus_socketClosedConnection', {
- SOCKET: id
- })
- this.socketCloseReasons[id] = reason
- this.socketCloseCodes[id] = code
- })
- socket.removeEventListener('open', () => {
- runtime.startHats('lemonWebSocketsPlus_socketOpensConnection', {
- SOCKET: id
- })
- })
-
- socket.close(Code, Reason)
-
- delete this.sockets[id]
- this.socketCloseCodes[id] = Code
- this.socketCloseReasons[id] = Reason
- this.socketStatuses[id] = 'closed'
-
- extManager.refreshBlocks('lemonWebSocketsPlus')
- vm.refreshWorkspace()
-
- if(this.debugging) console.log(`[WebSockets+] Successfully closed connection with '${id}'!`)
- } else {
- if(this.debugging) console.warn(`[WebSockets+] WebSocket '${id}' is not a WebSocket!`)
- }
-
- if(this.debugging) console.groupEnd()
-
- return
- }
-
- sendMessage({ MESSAGE, SOCKET }) {
- if(this.debugging) {
- console.groupCollapsed('WebSockets+ Message Sending')
-
- console.log(`[WebSockets+] Attempting to send a message to '${SOCKET}'..`)
- }
- SOCKET = Cast.toString(SOCKET)
- const socket = this.sockets[SOCKET]
-
- if(!socket) {
- if(this.debugging) {
- console.warn(`[WebSockets+] '${SOCKET}' doesn't exist!`)
- console.groupEnd()
- }
- return
- }
-
- if(socket instanceof WebSocket) {
- try {
- socket.send(MESSAGE)
- if(this.debugging) console.log(`[WebSockets+] Successfully sent a message to '${SOCKET}'!`)
- } catch(err) {
- console.error(err)
- if(this.debugging) console.groupEnd()
- }
- } else {
- if(this.debugging) console.warn(`[WebSockets+] '${SOCKET}' isn't a WebSocket!`)
- }
- if(this.debugging) console.groupEnd()
- }
+ if (socket instanceof WebSocket) {
+ return socket.readyState === WebSocket.OPEN;
+ }
- socketExists({ SOCKET }) {
- return Cast.toBoolean(this.sockets[Cast.toString(SOCKET)])
- }
+ return false;
+ }
- socketConnected({ SOCKET }) {
- const socket = this.sockets[Cast.toString(SOCKET)]
+ socketClosed({ SOCKET }) {
+ const socket = this.sockets[Cast.toString(SOCKET)];
- if(socket instanceof WebSocket) {
- return socket.readyState === WebSocket.OPEN
- }
-
- return false
- }
+ if (socket instanceof WebSocket) {
+ return socket.readyState === WebSocket.CLOSED;
+ }
- socketClosed({ SOCKET }) {
- const socket = this.sockets[Cast.toString(SOCKET)]
+ return true;
+ }
- if(socket instanceof WebSocket) {
- return socket.readyState === WebSocket.CLOSED
- }
-
- return true
- }
+ websockets() {
+ return JSON.stringify(Object.keys(this.sockets));
+ }
- websockets() {
- return JSON.stringify(Object.keys(this.sockets))
- }
+ socketState({ SOCKET }) {
+ const socket = this.sockets[Cast.toString(SOCKET)];
+ if (socket instanceof WebSocket) {
+ return this.WebSocketStates[socket.readyState] ?? "UNKNOWN";
+ }
+ return "UNKNOWN";
+ }
- socketState({ SOCKET }) {
- const socket = this.sockets[Cast.toString(SOCKET)]
- if(socket instanceof WebSocket) {
- return this.WebSocketStates[socket.readyState] ?? 'UNKNOWN'
- }
- return 'UNKNOWN'
- }
+ socketLastMessage({ SOCKET }) {
+ const socket = this.lastMessages[Cast.toString(SOCKET)];
+ return socket ?? "";
+ }
- socketLastMessage({ SOCKET }) {
- const socket = this.lastMessages[Cast.toString(SOCKET)]
- return socket ?? ''
- }
+ socketCloseReason({ SOCKET }) {
+ return this.socketCloseReasons[Cast.toString(SOCKET)] ?? "";
+ }
- socketCloseReason({ SOCKET }) {
- return this.socketCloseReasons[Cast.toString(SOCKET)] ?? ''
- }
+ socketCloseCode({ SOCKET }) {
+ return this.socketCloseCodes[Cast.toString(SOCKET)] ?? 0;
+ }
- socketCloseCode({ SOCKET }) {
- return this.socketCloseCodes[Cast.toString(SOCKET)] ?? 0
- }
+ getSockets() {
+ const Sockets = Object.keys(this.sockets);
+ return Sockets.length > 0
+ ? Sockets.map((socket) => {
+ return {
+ value: socket,
+ text: socket,
+ };
+ })
+ : [
+ {
+ value: Scratch.translate("None yet :("),
+ text: Scratch.translate("None yet :("),
+ },
+ ];
+ }
- getSockets() {
- const Sockets = Object.keys(this.sockets)
- return Sockets.length > 0 ? Sockets.map((socket) => {
- return {
- value: socket,
- text: socket
- }
- }) : [{
- value: Scratch.translate('None yet :('),
- text: Scratch.translate('None yet :(')
- }]
- }
+ /**
+ * @param {{}} args
+ * @param {VM.BlockUtility} util
+ */
+ socketMessage(args, util) {
+ return util.thread.socketMessage ?? "";
+ }
- /**
- * @param {{}} args
- * @param {VM.BlockUtility} util
- */
- socketMessage(args, util) {
- return util.thread.socketMessage ?? ''
- }
+ socketOpensConnection() {
+ return;
+ }
- socketOpensConnection() {
- return
- }
+ socketMessageReceived() {
+ return;
+ }
- socketMessageReceived() {
- return
- }
-
- socketErrored() {
- return
- }
+ socketErrored() {
+ return;
+ }
- socketClosedConnection() {
- return
- }
+ socketClosedConnection() {
+ return;
}
+ }
- Scratch.extensions.register(new WebsocketsPlusExt())
-})(Scratch)
+ Scratch.extensions.register(new WebsocketsPlusExt());
+})(Scratch);
From 3a0657e0250498dd2b18cf970d77a55a01972b5b Mon Sep 17 00:00:00 2001
From: Lemon <165233560+BludIsAnLemon@users.noreply.github.com>
Date: Wed, 12 Mar 2025 19:12:10 +0800
Subject: [PATCH 04/10] will this work
---
extensions/Cheddarphanie/websockets-plus.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/extensions/Cheddarphanie/websockets-plus.js b/extensions/Cheddarphanie/websockets-plus.js
index a64817696d..6df939384c 100644
--- a/extensions/Cheddarphanie/websockets-plus.js
+++ b/extensions/Cheddarphanie/websockets-plus.js
@@ -368,6 +368,7 @@
console.log(`[WebSockets+] Attempting to connect to '${url}'..`);
if (!this.fetchables[url])
+ // eslint-disable-next-line extension/check-can-fetch
this.fetchables[url] = await Scratch.canFetch(url);
if (!this.fetchables[url]) {
From f58cdd367cafbbccd7645d7cf843ebf5f510fa2d Mon Sep 17 00:00:00 2001
From: Lemon <165233560+BludIsAnLemon@users.noreply.github.com>
Date: Wed, 12 Mar 2025 19:15:45 +0800
Subject: [PATCH 05/10] checking again if this works
---
extensions/Cheddarphanie/websockets-plus.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/extensions/Cheddarphanie/websockets-plus.js b/extensions/Cheddarphanie/websockets-plus.js
index 6df939384c..719939201d 100644
--- a/extensions/Cheddarphanie/websockets-plus.js
+++ b/extensions/Cheddarphanie/websockets-plus.js
@@ -368,7 +368,7 @@
console.log(`[WebSockets+] Attempting to connect to '${url}'..`);
if (!this.fetchables[url])
- // eslint-disable-next-line extension/check-can-fetch
+ // eslint-disable-next-line
this.fetchables[url] = await Scratch.canFetch(url);
if (!this.fetchables[url]) {
From 9ac80fc359943d79cd83970b6a865c96e2e1bf64 Mon Sep 17 00:00:00 2001
From: Lemon <165233560+BludIsAnLemon@users.noreply.github.com>
Date: Wed, 12 Mar 2025 19:17:33 +0800
Subject: [PATCH 06/10] might have to brute force
---
extensions/Cheddarphanie/websockets-plus.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/extensions/Cheddarphanie/websockets-plus.js b/extensions/Cheddarphanie/websockets-plus.js
index 719939201d..3158d6578c 100644
--- a/extensions/Cheddarphanie/websockets-plus.js
+++ b/extensions/Cheddarphanie/websockets-plus.js
@@ -368,7 +368,7 @@
console.log(`[WebSockets+] Attempting to connect to '${url}'..`);
if (!this.fetchables[url])
- // eslint-disable-next-line
+ // eslint-disable-next-line extension/check-can-fetch extension/check-can-fetch
this.fetchables[url] = await Scratch.canFetch(url);
if (!this.fetchables[url]) {
From 8a0b6df9198d98e8964f0a75cbaf3cac7a65b582 Mon Sep 17 00:00:00 2001
From: Lemon <165233560+BludIsAnLemon@users.noreply.github.com>
Date: Wed, 12 Mar 2025 19:19:39 +0800
Subject: [PATCH 07/10] i swear if its a missing space
---
extensions/Cheddarphanie/websockets-plus.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/extensions/Cheddarphanie/websockets-plus.js b/extensions/Cheddarphanie/websockets-plus.js
index 3158d6578c..b8a885830a 100644
--- a/extensions/Cheddarphanie/websockets-plus.js
+++ b/extensions/Cheddarphanie/websockets-plus.js
@@ -368,7 +368,7 @@
console.log(`[WebSockets+] Attempting to connect to '${url}'..`);
if (!this.fetchables[url])
- // eslint-disable-next-line extension/check-can-fetch extension/check-can-fetch
+ // eslint-disable-next-line extension/check-can-fetch extension/check-can-fetch
this.fetchables[url] = await Scratch.canFetch(url);
if (!this.fetchables[url]) {
From a711da40a1fe4877920b1c3a59462182650a1d64 Mon Sep 17 00:00:00 2001
From: Lemon <165233560+BludIsAnLemon@users.noreply.github.com>
Date: Wed, 12 Mar 2025 19:25:17 +0800
Subject: [PATCH 08/10] icl ts pmo sm rn
---
extensions/Cheddarphanie/websockets-plus.js | 1083 ++++++++++---------
1 file changed, 543 insertions(+), 540 deletions(-)
diff --git a/extensions/Cheddarphanie/websockets-plus.js b/extensions/Cheddarphanie/websockets-plus.js
index b8a885830a..7e8abf1053 100644
--- a/extensions/Cheddarphanie/websockets-plus.js
+++ b/extensions/Cheddarphanie/websockets-plus.js
@@ -4,615 +4,618 @@
// By: Cheddarphanie
// License: Apache-2.0
-(function (Scratch) {
- "use strict";
-
- if (!Scratch.extensions.unsandboxed) {
- throw new Error("The WebSockets+ Extension must run unsandboxed.");
- }
-
- const vm = Scratch.vm;
- const extManager = vm.extensionManager;
- const runtime = vm.runtime;
- const Cast = Scratch.Cast;
-
- const regenReporters = ["lemonWebSocketsPlus_socketMessage"];
+// eslint-ignore
- if (Scratch.gui)
- Scratch.gui.getBlockly().then((SB) => {
- const ogCheck = SB.scratchBlocksUtils.isShadowArgumentReporter;
- SB.scratchBlocksUtils.isShadowArgumentReporter = function (block) {
- const result = ogCheck(block);
- if (result) return true;
- return block.isShadow() && regenReporters.includes(block.type);
+(function (Scratch) {
+ "use strict";
+
+ if (!Scratch.extensions.unsandboxed) {
+ throw new Error("The WebSockets+ Extension must run unsandboxed.");
+ }
+
+ const vm = Scratch.vm;
+ const extManager = vm.extensionManager;
+ const runtime = vm.runtime;
+ const Cast = Scratch.Cast;
+
+ const regenReporters = ["lemonWebSocketsPlus_socketMessage"];
+
+ if (Scratch.gui)
+ Scratch.gui.getBlockly().then((SB) => {
+ const ogCheck = SB.scratchBlocksUtils.isShadowArgumentReporter;
+ SB.scratchBlocksUtils.isShadowArgumentReporter = function (block) {
+ const result = ogCheck(block);
+ if (result) return true;
+ return block.isShadow() && regenReporters.includes(block.type);
+ };
+ });
+
+ const createLabel = (txt) => {
+ return {
+ blockType: Scratch.BlockType.LABEL,
+ text: txt,
};
- });
-
- const createLabel = (txt) => {
- return {
- blockType: Scratch.BlockType.LABEL,
- text: txt,
};
- };
-
- class WebsocketsPlusExt {
- constructor() {
- this.debugging = false;
-
- this.sockets = {};
-
- this.lastMessages = {};
-
- this.socketStatuses = {};
-
- this.socketCloseCodes = {};
-
- this.socketCloseReasons = {};
-
- this.fetchables = {};
-
- this.WebSocketStates = {
- 0: "CONNECTING",
- 1: "OPEN",
- 2: "CLOSING",
- 3: "CLOSED",
- };
- /**
- *
- * @param {string} socket
- * @returns {Function}
- */
- this.listener = function (socket = "") {
- return function ({ data }) {
- runtime
- .startHats("lemonWebSocketsPlus_socketMessageReceived", {
- SOCKET: socket,
- })
- .forEach((thread) => {
- thread.socketMessage = data;
- });
+
+ class WebsocketsPlusExt {
+ constructor() {
+ this.debugging = false;
+
+ this.sockets = {};
+
+ this.lastMessages = {};
+
+ this.socketStatuses = {};
+
+ this.socketCloseCodes = {};
+
+ this.socketCloseReasons = {};
+
+ this.fetchables = {};
+
+ this.WebSocketStates = {
+ 0: "CONNECTING",
+ 1: "OPEN",
+ 2: "CLOSING",
+ 3: "CLOSED",
};
- };
- }
- getInfo() {
- return {
- id: "lemonWebSocketsPlus",
- name: Scratch.translate("WebSockets+"),
- color1: "#307eff",
- color2: "#2c5eb0",
- blocks: [
- {
- func: "toggleDebugging",
- blockType: Scratch.BlockType.BUTTON,
- text: Scratch.translate("Toggle Debugging"),
- },
-
- createLabel("Variables"),
-
- {
- opcode: "websockets",
- blockType: Scratch.BlockType.REPORTER,
- text: Scratch.translate("websockets"),
- },
- {
- opcode: "socketState",
- blockType: Scratch.BlockType.REPORTER,
- text: Scratch.translate("state of socket [SOCKET]"),
- disableMonitor: true,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "socket",
- },
+ /**
+ *
+ * @param {string} socket
+ * @returns {Function}
+ */
+ this.listener = function (socket = "") {
+ return function ({ data }) {
+ runtime
+ .startHats("lemonWebSocketsPlus_socketMessageReceived", {
+ SOCKET: socket,
+ })
+ .forEach((thread) => {
+ thread.socketMessage = data;
+ });
+ };
+ };
+ }
+ getInfo() {
+ return {
+ id: "lemonWebSocketsPlus",
+ name: Scratch.translate("WebSockets+"),
+ color1: "#307eff",
+ color2: "#2c5eb0",
+ blocks: [
+ {
+ func: "toggleDebugging",
+ blockType: Scratch.BlockType.BUTTON,
+ text: Scratch.translate("Toggle Debugging"),
},
- },
- {
- opcode: "socketLastMessage",
- blockType: Scratch.BlockType.REPORTER,
- text: Scratch.translate(
- "last message received from socket [SOCKET]"
- ),
- disableMonitor: true,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "socket",
- },
+
+ createLabel("Variables"),
+
+ {
+ opcode: "websockets",
+ blockType: Scratch.BlockType.REPORTER,
+ text: Scratch.translate("websockets"),
},
- },
- {
- opcode: "socketCloseReason",
- blockType: Scratch.BlockType.REPORTER,
- text: Scratch.translate("reason of socket [SOCKET] closing"),
- disableMonitor: true,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "socket",
+ {
+ opcode: "socketState",
+ blockType: Scratch.BlockType.REPORTER,
+ text: Scratch.translate("state of socket [SOCKET]"),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
+ },
},
},
- },
- {
- opcode: "socketCloseCode",
- blockType: Scratch.BlockType.REPORTER,
- text: Scratch.translate("code of socket [SOCKET] closing"),
- disableMonitor: true,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "socket",
+ {
+ opcode: "socketLastMessage",
+ blockType: Scratch.BlockType.REPORTER,
+ text: Scratch.translate(
+ "last message received from socket [SOCKET]"
+ ),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
+ },
},
},
- },
-
- "---",
-
- createLabel(Scratch.translate("Blocks")),
-
- {
- opcode: "connect",
- blockType: Scratch.BlockType.COMMAND,
- text: Scratch.translate("connect to [URL] with id [ID]"),
- arguments: {
- URL: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "wss://echo.websocket.org/",
- },
- ID: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "socket",
+ {
+ opcode: "socketCloseReason",
+ blockType: Scratch.BlockType.REPORTER,
+ text: Scratch.translate("reason of socket [SOCKET] closing"),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
+ },
},
},
- },
- {
- opcode: "disconnect",
- blockType: Scratch.BlockType.COMMAND,
- text: Scratch.translate(
- "close connection with socket [ID] with code [C] and reason [R]"
- ),
- arguments: {
- ID: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "socket",
- },
- C: {
- type: Scratch.ArgumentType.NUMBER,
- defaultValue: 1000,
+ {
+ opcode: "socketCloseCode",
+ blockType: Scratch.BlockType.REPORTER,
+ text: Scratch.translate("code of socket [SOCKET] closing"),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
+ },
},
- R: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "fulfilled",
+ },
+
+ "---",
+
+ createLabel(Scratch.translate("Blocks")),
+
+ {
+ opcode: "connect",
+ blockType: Scratch.BlockType.COMMAND,
+ text: Scratch.translate("connect to [URL] with id [ID]"),
+ arguments: {
+ URL: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "wss://echo.websocket.org/",
+ },
+ ID: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
+ },
},
},
- },
- {
- opcode: "sendMessage",
- blockType: Scratch.BlockType.COMMAND,
- text: Scratch.translate(
- "send message [MESSAGE] to socket [SOCKET]"
- ),
- arguments: {
- MESSAGE: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: Scratch.translate("Hello :)"),
+ {
+ opcode: "disconnect",
+ blockType: Scratch.BlockType.COMMAND,
+ text: Scratch.translate(
+ "close connection with socket [ID] with code [C] and reason [R]"
+ ),
+ arguments: {
+ ID: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
+ },
+ C: {
+ type: Scratch.ArgumentType.NUMBER,
+ defaultValue: 1000,
+ },
+ R: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "fulfilled",
+ },
},
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "socket",
+ },
+ {
+ opcode: "sendMessage",
+ blockType: Scratch.BlockType.COMMAND,
+ text: Scratch.translate(
+ "send message [MESSAGE] to socket [SOCKET]"
+ ),
+ arguments: {
+ MESSAGE: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: Scratch.translate("Hello :)"),
+ },
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
+ },
},
},
- },
-
- "---",
-
- createLabel(Scratch.translate("Booleans")),
-
- {
- opcode: "socketExists",
- blockType: Scratch.BlockType.BOOLEAN,
- text: Scratch.translate("socket [SOCKET] exists?"),
- disableMonitor: true,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "socket",
+
+ "---",
+
+ createLabel(Scratch.translate("Booleans")),
+
+ {
+ opcode: "socketExists",
+ blockType: Scratch.BlockType.BOOLEAN,
+ text: Scratch.translate("socket [SOCKET] exists?"),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
+ },
},
},
- },
- {
- opcode: "socketConnected",
- blockType: Scratch.BlockType.BOOLEAN,
- text: Scratch.translate("connected to socket [SOCKET]?"),
- disableMonitor: true,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "socket",
+ {
+ opcode: "socketConnected",
+ blockType: Scratch.BlockType.BOOLEAN,
+ text: Scratch.translate("connected to socket [SOCKET]?"),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
+ },
},
},
- },
- {
- opcode: "socketClosed",
- blockType: Scratch.BlockType.BOOLEAN,
- text: Scratch.translate("closed connection with [SOCKET]?"),
- disableMonitor: true,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "socket",
+ {
+ opcode: "socketClosed",
+ blockType: Scratch.BlockType.BOOLEAN,
+ text: Scratch.translate("closed connection with [SOCKET]?"),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
+ },
},
},
- },
-
- "---",
-
- createLabel(Scratch.translate("Events")),
-
- {
- opcode: "socketMessageReceived",
- blockType: Scratch.BlockType.EVENT,
- text: Scratch.translate(
- "when i receive a message from [SOCKET] [MESSAGE]"
- ),
- isEdgeActivated: false,
- hideFromPalette: true,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- menu: "socketMenu",
+
+ "---",
+
+ createLabel(Scratch.translate("Events")),
+
+ {
+ opcode: "socketMessageReceived",
+ blockType: Scratch.BlockType.EVENT,
+ text: Scratch.translate(
+ "when i receive a message from [SOCKET] [MESSAGE]"
+ ),
+ isEdgeActivated: false,
+ hideFromPalette: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ menu: "socketMenu",
+ },
+ MESSAGE: {},
},
- MESSAGE: {},
},
- },
- {
- opcode: "socketMessage",
- blockType: Scratch.BlockType.REPORTER,
- text: Scratch.translate("message"),
- hideFromPalette: true,
- disableMonitor: true,
- },
- {
- opcode: "socketOpensConnection",
- blockType: Scratch.BlockType.EVENT,
- text: Scratch.translate("when connection with [SOCKET] opens"),
- isEdgeActivated: false,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- menu: "socketMenu",
+ {
+ opcode: "socketMessage",
+ blockType: Scratch.BlockType.REPORTER,
+ text: Scratch.translate("message"),
+ hideFromPalette: true,
+ disableMonitor: true,
+ },
+ {
+ opcode: "socketOpensConnection",
+ blockType: Scratch.BlockType.EVENT,
+ text: Scratch.translate("when connection with [SOCKET] opens"),
+ isEdgeActivated: false,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ menu: "socketMenu",
+ },
},
},
- },
- {
- blockType: Scratch.BlockType.XML,
- xml: `
-
-
-
- `,
- },
- {
- opcode: "socketErrored",
- blockType: Scratch.BlockType.EVENT,
- text: Scratch.translate("when socket [SOCKET] errors"),
- isEdgeActivated: false,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- menu: "socketMenu",
+ {
+ blockType: Scratch.BlockType.XML,
+ xml: `
+
+
+
+ `,
+ },
+ {
+ opcode: "socketErrored",
+ blockType: Scratch.BlockType.EVENT,
+ text: Scratch.translate("when socket [SOCKET] errors"),
+ isEdgeActivated: false,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ menu: "socketMenu",
+ },
},
},
- },
- {
- opcode: "socketClosedConnection",
- blockType: Scratch.BlockType.EVENT,
- text: Scratch.translate("when connection with [SOCKET] closes"),
- isEdgeActivated: false,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- menu: "socketMenu",
+ {
+ opcode: "socketClosedConnection",
+ blockType: Scratch.BlockType.EVENT,
+ text: Scratch.translate("when connection with [SOCKET] closes"),
+ isEdgeActivated: false,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ menu: "socketMenu",
+ },
},
},
+ ],
+ menus: {
+ socketMenu: {
+ items: "getSockets",
+ },
},
- ],
- menus: {
- socketMenu: {
- items: "getSockets",
- },
- },
- };
- }
-
- toggleDebugging() {
- this.debugging = !this.debugging;
- window.alert(Scratch.translate("Toggled Debugging! :)"));
- }
-
- async connect({ ID, URL }) {
- const id = Cast.toString(ID);
- const url = Cast.toString(URL);
-
- if (this.sockets[id] instanceof WebSocket) {
+ };
+ }
+
+ toggleDebugging() {
+ this.debugging = !this.debugging;
+ window.alert(Scratch.translate("Toggled Debugging! :)"));
+ }
+
+ async connect({ ID, URL }) {
+ const id = Cast.toString(ID);
+ const url = Cast.toString(URL);
+
+ if (this.sockets[id] instanceof WebSocket) {
+ try {
+ this.sockets[id].removeEventListener("message", this.listener(id));
+ this.sockets[id].removeEventListener("error", () => {
+ runtime.startHats("lemonWebSocketsPlus_socketErrored", {
+ SOCKET: id,
+ });
+ });
+ this.sockets[id].removeEventListener("message", ({ data }) => {
+ this.lastMessages[id] = data;
+ });
+ this.sockets[id].removeEventListener("close", ({ reason, code }) => {
+ runtime.startHats("lemonWebSocketsPlus_socketClosedConnection", {
+ SOCKET: id,
+ });
+ this.socketCloseReasons[id] = reason;
+ this.socketCloseCodes[id] = code;
+ });
+ this.sockets[id].removeEventListener("open", () => {
+ runtime.startHats("lemonWebSocketsPlus_socketOpensConnection", {
+ SOCKET: id,
+ });
+ });
+ this.sockets[id].close();
+ } catch (err) {
+ console.error(err);
+ }
+ }
+
+ if (this.debugging) console.groupCollapsed("WebSockets+ Connecting");
+
+ if (this.debugging)
+ console.log(`[WebSockets+] Attempting to connect to '${url}'..`);
+
+ if (!this.fetchables[url])
+ this.fetchables[url] = await Scratch.canFetch(url);
+
+ if (!this.fetchables[url]) {
+ this.socketStatuses[id] = "failed to connect";
+ if (this.debugging) {
+ console.log(`[Websockets+] Connection to '${url}' denied!`);
+ console.groupEnd();
+ }
+ return;
+ }
+
try {
- this.sockets[id].removeEventListener("message", this.listener(id));
- this.sockets[id].removeEventListener("error", () => {
+ this.sockets[id] = new WebSocket(url);
+ this.socketStatuses[id] = "connected";
+ this.socketCloseCodes[id] = 0;
+ this.socketCloseReasons[id] = "";
+
+ /**
+ * @type {WebSocket}
+ */
+ const socket = this.sockets[id];
+
+ socket.addEventListener("message", this.listener(id));
+ socket.addEventListener("error", () => {
runtime.startHats("lemonWebSocketsPlus_socketErrored", {
SOCKET: id,
});
});
- this.sockets[id].removeEventListener("message", ({ data }) => {
+ socket.addEventListener("message", ({ data }) => {
this.lastMessages[id] = data;
});
- this.sockets[id].removeEventListener("close", ({ reason, code }) => {
+ socket.addEventListener("close", ({ reason, code }) => {
runtime.startHats("lemonWebSocketsPlus_socketClosedConnection", {
SOCKET: id,
});
this.socketCloseReasons[id] = reason;
this.socketCloseCodes[id] = code;
});
- this.sockets[id].removeEventListener("open", () => {
+ socket.addEventListener("open", () => {
runtime.startHats("lemonWebSocketsPlus_socketOpensConnection", {
SOCKET: id,
});
});
- this.sockets[id].close();
+
+ extManager.refreshBlocks("lemonWebSocketsPlus");
+ vm.refreshWorkspace();
+
+ if (this.debugging)
+ console.log(`[WebSockets+] Successfully connected to '${url}'.`);
} catch (err) {
console.error(err);
+ this.socketStatuses[id] = "failed to connect";
}
- }
-
- if (this.debugging) console.groupCollapsed("WebSockets+ Connecting");
-
- if (this.debugging)
- console.log(`[WebSockets+] Attempting to connect to '${url}'..`);
-
- if (!this.fetchables[url])
- // eslint-disable-next-line extension/check-can-fetch extension/check-can-fetch
- this.fetchables[url] = await Scratch.canFetch(url);
-
- if (!this.fetchables[url]) {
- this.socketStatuses[id] = "failed to connect";
- console.log(`[Websockets+] Connection to '${url}' denied!`);
+
if (this.debugging) console.groupEnd();
- return;
}
-
- try {
- this.sockets[id] = new WebSocket(url);
- this.socketStatuses[id] = "connected";
- this.socketCloseCodes[id] = 0;
- this.socketCloseReasons[id] = "";
-
- /**
- * @type {WebSocket}
- */
+
+ disconnect({ ID, C, R }) {
+ const id = Cast.toString(ID);
+ const Code = Cast.toNumber(C);
+ const Reason = Cast.toString(R);
+
+ if (this.debugging)
+ console.groupCollapsed("WebSockets+ Closing Connection");
+
+ if (this.debugging)
+ console.log(
+ `[WebSockets+] Attemping to close connection with '${id}'..`
+ );
+
const socket = this.sockets[id];
-
- socket.addEventListener("message", this.listener(id));
- socket.addEventListener("error", () => {
- runtime.startHats("lemonWebSocketsPlus_socketErrored", {
- SOCKET: id,
- });
- });
- socket.addEventListener("message", ({ data }) => {
- this.lastMessages[id] = data;
- });
- socket.addEventListener("close", ({ reason, code }) => {
- runtime.startHats("lemonWebSocketsPlus_socketClosedConnection", {
- SOCKET: id,
- });
- this.socketCloseReasons[id] = reason;
- this.socketCloseCodes[id] = code;
- });
- socket.addEventListener("open", () => {
- runtime.startHats("lemonWebSocketsPlus_socketOpensConnection", {
- SOCKET: id,
+
+ if (socket instanceof WebSocket) {
+ socket.removeEventListener("message", this.listener(id));
+ socket.removeEventListener("error", () => {
+ runtime.startHats("lemonWebSocketsPlus_socketErrored", {
+ SOCKET: id,
+ });
});
- });
-
- extManager.refreshBlocks("lemonWebSocketsPlus");
- vm.refreshWorkspace();
-
- if (this.debugging)
- console.log(`[WebSockets+] Successfully connected to '${url}'.`);
- } catch (err) {
- console.error(err);
- this.socketStatuses[id] = "failed to connect";
- }
-
- if (this.debugging) console.groupEnd();
- }
-
- disconnect({ ID, C, R }) {
- const id = Cast.toString(ID);
- const Code = Cast.toNumber(C);
- const Reason = Cast.toString(R);
-
- if (this.debugging)
- console.groupCollapsed("WebSockets+ Closing Connection");
-
- if (this.debugging)
- console.log(
- `[WebSockets+] Attemping to close connection with '${id}'..`
- );
-
- const socket = this.sockets[id];
-
- if (socket instanceof WebSocket) {
- socket.removeEventListener("message", this.listener(id));
- socket.removeEventListener("error", () => {
- runtime.startHats("lemonWebSocketsPlus_socketErrored", {
- SOCKET: id,
+ socket.removeEventListener("message", ({ data }) => {
+ this.lastMessages[id] = data;
});
- });
- socket.removeEventListener("message", ({ data }) => {
- this.lastMessages[id] = data;
- });
- socket.removeEventListener("close", ({ reason, code }) => {
- runtime.startHats("lemonWebSocketsPlus_socketClosedConnection", {
- SOCKET: id,
+ socket.removeEventListener("close", ({ reason, code }) => {
+ runtime.startHats("lemonWebSocketsPlus_socketClosedConnection", {
+ SOCKET: id,
+ });
+ this.socketCloseReasons[id] = reason;
+ this.socketCloseCodes[id] = code;
});
- this.socketCloseReasons[id] = reason;
- this.socketCloseCodes[id] = code;
- });
- socket.removeEventListener("open", () => {
- runtime.startHats("lemonWebSocketsPlus_socketOpensConnection", {
- SOCKET: id,
+ socket.removeEventListener("open", () => {
+ runtime.startHats("lemonWebSocketsPlus_socketOpensConnection", {
+ SOCKET: id,
+ });
});
- });
-
- socket.close(Code, Reason);
-
- delete this.sockets[id];
- this.socketCloseCodes[id] = Code;
- this.socketCloseReasons[id] = Reason;
- this.socketStatuses[id] = "closed";
-
- extManager.refreshBlocks("lemonWebSocketsPlus");
- vm.refreshWorkspace();
-
- if (this.debugging)
+
+ socket.close(Code, Reason);
+
+ delete this.sockets[id];
+ this.socketCloseCodes[id] = Code;
+ this.socketCloseReasons[id] = Reason;
+ this.socketStatuses[id] = "closed";
+
+ extManager.refreshBlocks("lemonWebSocketsPlus");
+ vm.refreshWorkspace();
+
+ if (this.debugging)
+ console.log(
+ `[WebSockets+] Successfully closed connection with '${id}'!`
+ );
+ } else {
+ if (this.debugging)
+ console.warn(`[WebSockets+] WebSocket '${id}' is not a WebSocket!`);
+ }
+
+ if (this.debugging) console.groupEnd();
+
+ return;
+ }
+
+ sendMessage({ MESSAGE, SOCKET }) {
+ if (this.debugging) {
+ console.groupCollapsed("WebSockets+ Message Sending");
+
console.log(
- `[WebSockets+] Successfully closed connection with '${id}'!`
+ `[WebSockets+] Attempting to send a message to '${SOCKET}'..`
);
- } else {
- if (this.debugging)
- console.warn(`[WebSockets+] WebSocket '${id}' is not a WebSocket!`);
+ }
+ SOCKET = Cast.toString(SOCKET);
+ const socket = this.sockets[SOCKET];
+
+ if (!socket) {
+ if (this.debugging) {
+ console.warn(`[WebSockets+] '${SOCKET}' doesn't exist!`);
+ console.groupEnd();
+ }
+ return;
+ }
+
+ if (socket instanceof WebSocket) {
+ try {
+ socket.send(MESSAGE);
+ if (this.debugging)
+ console.log(
+ `[WebSockets+] Successfully sent a message to '${SOCKET}'!`
+ );
+ } catch (err) {
+ console.error(err);
+ if (this.debugging) console.groupEnd();
+ }
+ } else {
+ if (this.debugging)
+ console.warn(`[WebSockets+] '${SOCKET}' isn't a WebSocket!`);
+ }
+ if (this.debugging) console.groupEnd();
}
-
- if (this.debugging) console.groupEnd();
-
- return;
- }
-
- sendMessage({ MESSAGE, SOCKET }) {
- if (this.debugging) {
- console.groupCollapsed("WebSockets+ Message Sending");
-
- console.log(
- `[WebSockets+] Attempting to send a message to '${SOCKET}'..`
- );
+
+ socketExists({ SOCKET }) {
+ return Cast.toBoolean(this.sockets[Cast.toString(SOCKET)]);
}
- SOCKET = Cast.toString(SOCKET);
- const socket = this.sockets[SOCKET];
-
- if (!socket) {
- if (this.debugging) {
- console.warn(`[WebSockets+] '${SOCKET}' doesn't exist!`);
- console.groupEnd();
+
+ socketConnected({ SOCKET }) {
+ const socket = this.sockets[Cast.toString(SOCKET)];
+
+ if (socket instanceof WebSocket) {
+ return socket.readyState === WebSocket.OPEN;
}
- return;
+
+ return false;
}
-
- if (socket instanceof WebSocket) {
- try {
- socket.send(MESSAGE);
- if (this.debugging)
- console.log(
- `[WebSockets+] Successfully sent a message to '${SOCKET}'!`
- );
- } catch (err) {
- console.error(err);
- if (this.debugging) console.groupEnd();
+
+ socketClosed({ SOCKET }) {
+ const socket = this.sockets[Cast.toString(SOCKET)];
+
+ if (socket instanceof WebSocket) {
+ return socket.readyState === WebSocket.CLOSED;
}
- } else {
- if (this.debugging)
- console.warn(`[WebSockets+] '${SOCKET}' isn't a WebSocket!`);
+
+ return true;
}
- if (this.debugging) console.groupEnd();
- }
-
- socketExists({ SOCKET }) {
- return Cast.toBoolean(this.sockets[Cast.toString(SOCKET)]);
- }
-
- socketConnected({ SOCKET }) {
- const socket = this.sockets[Cast.toString(SOCKET)];
-
- if (socket instanceof WebSocket) {
- return socket.readyState === WebSocket.OPEN;
+
+ websockets() {
+ return JSON.stringify(Object.keys(this.sockets));
}
-
- return false;
- }
-
- socketClosed({ SOCKET }) {
- const socket = this.sockets[Cast.toString(SOCKET)];
-
- if (socket instanceof WebSocket) {
- return socket.readyState === WebSocket.CLOSED;
+
+ socketState({ SOCKET }) {
+ const socket = this.sockets[Cast.toString(SOCKET)];
+ if (socket instanceof WebSocket) {
+ return this.WebSocketStates[socket.readyState] ?? "UNKNOWN";
+ }
+ return "UNKNOWN";
}
-
- return true;
- }
-
- websockets() {
- return JSON.stringify(Object.keys(this.sockets));
- }
-
- socketState({ SOCKET }) {
- const socket = this.sockets[Cast.toString(SOCKET)];
- if (socket instanceof WebSocket) {
- return this.WebSocketStates[socket.readyState] ?? "UNKNOWN";
+
+ socketLastMessage({ SOCKET }) {
+ const socket = this.lastMessages[Cast.toString(SOCKET)];
+ return socket ?? "";
+ }
+
+ socketCloseReason({ SOCKET }) {
+ return this.socketCloseReasons[Cast.toString(SOCKET)] ?? "";
+ }
+
+ socketCloseCode({ SOCKET }) {
+ return this.socketCloseCodes[Cast.toString(SOCKET)] ?? 0;
+ }
+
+ getSockets() {
+ const Sockets = Object.keys(this.sockets);
+ return Sockets.length > 0
+ ? Sockets.map((socket) => {
+ return {
+ value: socket,
+ text: socket,
+ };
+ })
+ : [
+ {
+ value: Scratch.translate("None yet :("),
+ text: Scratch.translate("None yet :("),
+ },
+ ];
+ }
+
+ /**
+ * @param {{}} args
+ * @param {VM.BlockUtility} util
+ */
+ socketMessage(args, util) {
+ return util.thread.socketMessage ?? "";
+ }
+
+ socketOpensConnection() {
+ return;
+ }
+
+ socketMessageReceived() {
+ return;
+ }
+
+ socketErrored() {
+ return;
+ }
+
+ socketClosedConnection() {
+ return;
}
- return "UNKNOWN";
- }
-
- socketLastMessage({ SOCKET }) {
- const socket = this.lastMessages[Cast.toString(SOCKET)];
- return socket ?? "";
- }
-
- socketCloseReason({ SOCKET }) {
- return this.socketCloseReasons[Cast.toString(SOCKET)] ?? "";
- }
-
- socketCloseCode({ SOCKET }) {
- return this.socketCloseCodes[Cast.toString(SOCKET)] ?? 0;
- }
-
- getSockets() {
- const Sockets = Object.keys(this.sockets);
- return Sockets.length > 0
- ? Sockets.map((socket) => {
- return {
- value: socket,
- text: socket,
- };
- })
- : [
- {
- value: Scratch.translate("None yet :("),
- text: Scratch.translate("None yet :("),
- },
- ];
- }
-
- /**
- * @param {{}} args
- * @param {VM.BlockUtility} util
- */
- socketMessage(args, util) {
- return util.thread.socketMessage ?? "";
- }
-
- socketOpensConnection() {
- return;
- }
-
- socketMessageReceived() {
- return;
- }
-
- socketErrored() {
- return;
- }
-
- socketClosedConnection() {
- return;
}
- }
-
- Scratch.extensions.register(new WebsocketsPlusExt());
-})(Scratch);
+
+ Scratch.extensions.register(new WebsocketsPlusExt());
+ })(Scratch);
From acff2935461f95d13a8fd7b4028027ef77bf1e70 Mon Sep 17 00:00:00 2001
From: "DangoCat[bot]"
Date: Wed, 12 Mar 2025 11:27:08 +0000
Subject: [PATCH 09/10] [Automated] Format code
---
extensions/Cheddarphanie/websockets-plus.js | 1076 +++++++++----------
1 file changed, 538 insertions(+), 538 deletions(-)
diff --git a/extensions/Cheddarphanie/websockets-plus.js b/extensions/Cheddarphanie/websockets-plus.js
index 7e8abf1053..1eab3c13a7 100644
--- a/extensions/Cheddarphanie/websockets-plus.js
+++ b/extensions/Cheddarphanie/websockets-plus.js
@@ -7,615 +7,615 @@
// eslint-ignore
(function (Scratch) {
- "use strict";
-
- if (!Scratch.extensions.unsandboxed) {
- throw new Error("The WebSockets+ Extension must run unsandboxed.");
- }
-
- const vm = Scratch.vm;
- const extManager = vm.extensionManager;
- const runtime = vm.runtime;
- const Cast = Scratch.Cast;
-
- const regenReporters = ["lemonWebSocketsPlus_socketMessage"];
-
- if (Scratch.gui)
- Scratch.gui.getBlockly().then((SB) => {
- const ogCheck = SB.scratchBlocksUtils.isShadowArgumentReporter;
- SB.scratchBlocksUtils.isShadowArgumentReporter = function (block) {
- const result = ogCheck(block);
- if (result) return true;
- return block.isShadow() && regenReporters.includes(block.type);
- };
- });
-
- const createLabel = (txt) => {
- return {
- blockType: Scratch.BlockType.LABEL,
- text: txt,
+ "use strict";
+
+ if (!Scratch.extensions.unsandboxed) {
+ throw new Error("The WebSockets+ Extension must run unsandboxed.");
+ }
+
+ const vm = Scratch.vm;
+ const extManager = vm.extensionManager;
+ const runtime = vm.runtime;
+ const Cast = Scratch.Cast;
+
+ const regenReporters = ["lemonWebSocketsPlus_socketMessage"];
+
+ if (Scratch.gui)
+ Scratch.gui.getBlockly().then((SB) => {
+ const ogCheck = SB.scratchBlocksUtils.isShadowArgumentReporter;
+ SB.scratchBlocksUtils.isShadowArgumentReporter = function (block) {
+ const result = ogCheck(block);
+ if (result) return true;
+ return block.isShadow() && regenReporters.includes(block.type);
};
+ });
+
+ const createLabel = (txt) => {
+ return {
+ blockType: Scratch.BlockType.LABEL,
+ text: txt,
};
-
- class WebsocketsPlusExt {
- constructor() {
- this.debugging = false;
-
- this.sockets = {};
-
- this.lastMessages = {};
-
- this.socketStatuses = {};
-
- this.socketCloseCodes = {};
-
- this.socketCloseReasons = {};
-
- this.fetchables = {};
-
- this.WebSocketStates = {
- 0: "CONNECTING",
- 1: "OPEN",
- 2: "CLOSING",
- 3: "CLOSED",
- };
- /**
- *
- * @param {string} socket
- * @returns {Function}
- */
- this.listener = function (socket = "") {
- return function ({ data }) {
- runtime
- .startHats("lemonWebSocketsPlus_socketMessageReceived", {
- SOCKET: socket,
- })
- .forEach((thread) => {
- thread.socketMessage = data;
- });
- };
+ };
+
+ class WebsocketsPlusExt {
+ constructor() {
+ this.debugging = false;
+
+ this.sockets = {};
+
+ this.lastMessages = {};
+
+ this.socketStatuses = {};
+
+ this.socketCloseCodes = {};
+
+ this.socketCloseReasons = {};
+
+ this.fetchables = {};
+
+ this.WebSocketStates = {
+ 0: "CONNECTING",
+ 1: "OPEN",
+ 2: "CLOSING",
+ 3: "CLOSED",
+ };
+ /**
+ *
+ * @param {string} socket
+ * @returns {Function}
+ */
+ this.listener = function (socket = "") {
+ return function ({ data }) {
+ runtime
+ .startHats("lemonWebSocketsPlus_socketMessageReceived", {
+ SOCKET: socket,
+ })
+ .forEach((thread) => {
+ thread.socketMessage = data;
+ });
};
- }
- getInfo() {
- return {
- id: "lemonWebSocketsPlus",
- name: Scratch.translate("WebSockets+"),
- color1: "#307eff",
- color2: "#2c5eb0",
- blocks: [
- {
- func: "toggleDebugging",
- blockType: Scratch.BlockType.BUTTON,
- text: Scratch.translate("Toggle Debugging"),
- },
-
- createLabel("Variables"),
-
- {
- opcode: "websockets",
- blockType: Scratch.BlockType.REPORTER,
- text: Scratch.translate("websockets"),
- },
- {
- opcode: "socketState",
- blockType: Scratch.BlockType.REPORTER,
- text: Scratch.translate("state of socket [SOCKET]"),
- disableMonitor: true,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "socket",
- },
+ };
+ }
+ getInfo() {
+ return {
+ id: "lemonWebSocketsPlus",
+ name: Scratch.translate("WebSockets+"),
+ color1: "#307eff",
+ color2: "#2c5eb0",
+ blocks: [
+ {
+ func: "toggleDebugging",
+ blockType: Scratch.BlockType.BUTTON,
+ text: Scratch.translate("Toggle Debugging"),
+ },
+
+ createLabel("Variables"),
+
+ {
+ opcode: "websockets",
+ blockType: Scratch.BlockType.REPORTER,
+ text: Scratch.translate("websockets"),
+ },
+ {
+ opcode: "socketState",
+ blockType: Scratch.BlockType.REPORTER,
+ text: Scratch.translate("state of socket [SOCKET]"),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
},
},
- {
- opcode: "socketLastMessage",
- blockType: Scratch.BlockType.REPORTER,
- text: Scratch.translate(
- "last message received from socket [SOCKET]"
- ),
- disableMonitor: true,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "socket",
- },
+ },
+ {
+ opcode: "socketLastMessage",
+ blockType: Scratch.BlockType.REPORTER,
+ text: Scratch.translate(
+ "last message received from socket [SOCKET]"
+ ),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
},
},
- {
- opcode: "socketCloseReason",
- blockType: Scratch.BlockType.REPORTER,
- text: Scratch.translate("reason of socket [SOCKET] closing"),
- disableMonitor: true,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "socket",
- },
+ },
+ {
+ opcode: "socketCloseReason",
+ blockType: Scratch.BlockType.REPORTER,
+ text: Scratch.translate("reason of socket [SOCKET] closing"),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
},
},
- {
- opcode: "socketCloseCode",
- blockType: Scratch.BlockType.REPORTER,
- text: Scratch.translate("code of socket [SOCKET] closing"),
- disableMonitor: true,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "socket",
- },
+ },
+ {
+ opcode: "socketCloseCode",
+ blockType: Scratch.BlockType.REPORTER,
+ text: Scratch.translate("code of socket [SOCKET] closing"),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
},
},
-
- "---",
-
- createLabel(Scratch.translate("Blocks")),
-
- {
- opcode: "connect",
- blockType: Scratch.BlockType.COMMAND,
- text: Scratch.translate("connect to [URL] with id [ID]"),
- arguments: {
- URL: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "wss://echo.websocket.org/",
- },
- ID: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "socket",
- },
+ },
+
+ "---",
+
+ createLabel(Scratch.translate("Blocks")),
+
+ {
+ opcode: "connect",
+ blockType: Scratch.BlockType.COMMAND,
+ text: Scratch.translate("connect to [URL] with id [ID]"),
+ arguments: {
+ URL: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "wss://echo.websocket.org/",
},
- },
- {
- opcode: "disconnect",
- blockType: Scratch.BlockType.COMMAND,
- text: Scratch.translate(
- "close connection with socket [ID] with code [C] and reason [R]"
- ),
- arguments: {
- ID: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "socket",
- },
- C: {
- type: Scratch.ArgumentType.NUMBER,
- defaultValue: 1000,
- },
- R: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "fulfilled",
- },
+ ID: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
},
},
- {
- opcode: "sendMessage",
- blockType: Scratch.BlockType.COMMAND,
- text: Scratch.translate(
- "send message [MESSAGE] to socket [SOCKET]"
- ),
- arguments: {
- MESSAGE: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: Scratch.translate("Hello :)"),
- },
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "socket",
- },
+ },
+ {
+ opcode: "disconnect",
+ blockType: Scratch.BlockType.COMMAND,
+ text: Scratch.translate(
+ "close connection with socket [ID] with code [C] and reason [R]"
+ ),
+ arguments: {
+ ID: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
+ },
+ C: {
+ type: Scratch.ArgumentType.NUMBER,
+ defaultValue: 1000,
+ },
+ R: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "fulfilled",
},
},
-
- "---",
-
- createLabel(Scratch.translate("Booleans")),
-
- {
- opcode: "socketExists",
- blockType: Scratch.BlockType.BOOLEAN,
- text: Scratch.translate("socket [SOCKET] exists?"),
- disableMonitor: true,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "socket",
- },
+ },
+ {
+ opcode: "sendMessage",
+ blockType: Scratch.BlockType.COMMAND,
+ text: Scratch.translate(
+ "send message [MESSAGE] to socket [SOCKET]"
+ ),
+ arguments: {
+ MESSAGE: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: Scratch.translate("Hello :)"),
+ },
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
},
},
- {
- opcode: "socketConnected",
- blockType: Scratch.BlockType.BOOLEAN,
- text: Scratch.translate("connected to socket [SOCKET]?"),
- disableMonitor: true,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "socket",
- },
+ },
+
+ "---",
+
+ createLabel(Scratch.translate("Booleans")),
+
+ {
+ opcode: "socketExists",
+ blockType: Scratch.BlockType.BOOLEAN,
+ text: Scratch.translate("socket [SOCKET] exists?"),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
},
},
- {
- opcode: "socketClosed",
- blockType: Scratch.BlockType.BOOLEAN,
- text: Scratch.translate("closed connection with [SOCKET]?"),
- disableMonitor: true,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "socket",
- },
+ },
+ {
+ opcode: "socketConnected",
+ blockType: Scratch.BlockType.BOOLEAN,
+ text: Scratch.translate("connected to socket [SOCKET]?"),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
},
},
-
- "---",
-
- createLabel(Scratch.translate("Events")),
-
- {
- opcode: "socketMessageReceived",
- blockType: Scratch.BlockType.EVENT,
- text: Scratch.translate(
- "when i receive a message from [SOCKET] [MESSAGE]"
- ),
- isEdgeActivated: false,
- hideFromPalette: true,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- menu: "socketMenu",
- },
- MESSAGE: {},
+ },
+ {
+ opcode: "socketClosed",
+ blockType: Scratch.BlockType.BOOLEAN,
+ text: Scratch.translate("closed connection with [SOCKET]?"),
+ disableMonitor: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "socket",
},
},
- {
- opcode: "socketMessage",
- blockType: Scratch.BlockType.REPORTER,
- text: Scratch.translate("message"),
- hideFromPalette: true,
- disableMonitor: true,
+ },
+
+ "---",
+
+ createLabel(Scratch.translate("Events")),
+
+ {
+ opcode: "socketMessageReceived",
+ blockType: Scratch.BlockType.EVENT,
+ text: Scratch.translate(
+ "when i receive a message from [SOCKET] [MESSAGE]"
+ ),
+ isEdgeActivated: false,
+ hideFromPalette: true,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ menu: "socketMenu",
+ },
+ MESSAGE: {},
},
- {
- opcode: "socketOpensConnection",
- blockType: Scratch.BlockType.EVENT,
- text: Scratch.translate("when connection with [SOCKET] opens"),
- isEdgeActivated: false,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- menu: "socketMenu",
- },
+ },
+ {
+ opcode: "socketMessage",
+ blockType: Scratch.BlockType.REPORTER,
+ text: Scratch.translate("message"),
+ hideFromPalette: true,
+ disableMonitor: true,
+ },
+ {
+ opcode: "socketOpensConnection",
+ blockType: Scratch.BlockType.EVENT,
+ text: Scratch.translate("when connection with [SOCKET] opens"),
+ isEdgeActivated: false,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ menu: "socketMenu",
},
},
- {
- blockType: Scratch.BlockType.XML,
- xml: `
+ },
+ {
+ blockType: Scratch.BlockType.XML,
+ xml: `
`,
- },
- {
- opcode: "socketErrored",
- blockType: Scratch.BlockType.EVENT,
- text: Scratch.translate("when socket [SOCKET] errors"),
- isEdgeActivated: false,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- menu: "socketMenu",
- },
+ },
+ {
+ opcode: "socketErrored",
+ blockType: Scratch.BlockType.EVENT,
+ text: Scratch.translate("when socket [SOCKET] errors"),
+ isEdgeActivated: false,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ menu: "socketMenu",
},
},
- {
- opcode: "socketClosedConnection",
- blockType: Scratch.BlockType.EVENT,
- text: Scratch.translate("when connection with [SOCKET] closes"),
- isEdgeActivated: false,
- arguments: {
- SOCKET: {
- type: Scratch.ArgumentType.STRING,
- menu: "socketMenu",
- },
+ },
+ {
+ opcode: "socketClosedConnection",
+ blockType: Scratch.BlockType.EVENT,
+ text: Scratch.translate("when connection with [SOCKET] closes"),
+ isEdgeActivated: false,
+ arguments: {
+ SOCKET: {
+ type: Scratch.ArgumentType.STRING,
+ menu: "socketMenu",
},
},
- ],
- menus: {
- socketMenu: {
- items: "getSockets",
- },
},
- };
- }
-
- toggleDebugging() {
- this.debugging = !this.debugging;
- window.alert(Scratch.translate("Toggled Debugging! :)"));
- }
-
- async connect({ ID, URL }) {
- const id = Cast.toString(ID);
- const url = Cast.toString(URL);
-
- if (this.sockets[id] instanceof WebSocket) {
- try {
- this.sockets[id].removeEventListener("message", this.listener(id));
- this.sockets[id].removeEventListener("error", () => {
- runtime.startHats("lemonWebSocketsPlus_socketErrored", {
- SOCKET: id,
- });
- });
- this.sockets[id].removeEventListener("message", ({ data }) => {
- this.lastMessages[id] = data;
- });
- this.sockets[id].removeEventListener("close", ({ reason, code }) => {
- runtime.startHats("lemonWebSocketsPlus_socketClosedConnection", {
- SOCKET: id,
- });
- this.socketCloseReasons[id] = reason;
- this.socketCloseCodes[id] = code;
- });
- this.sockets[id].removeEventListener("open", () => {
- runtime.startHats("lemonWebSocketsPlus_socketOpensConnection", {
- SOCKET: id,
- });
- });
- this.sockets[id].close();
- } catch (err) {
- console.error(err);
- }
- }
-
- if (this.debugging) console.groupCollapsed("WebSockets+ Connecting");
-
- if (this.debugging)
- console.log(`[WebSockets+] Attempting to connect to '${url}'..`);
-
- if (!this.fetchables[url])
- this.fetchables[url] = await Scratch.canFetch(url);
-
- if (!this.fetchables[url]) {
- this.socketStatuses[id] = "failed to connect";
- if (this.debugging) {
- console.log(`[Websockets+] Connection to '${url}' denied!`);
- console.groupEnd();
- }
- return;
- }
-
+ ],
+ menus: {
+ socketMenu: {
+ items: "getSockets",
+ },
+ },
+ };
+ }
+
+ toggleDebugging() {
+ this.debugging = !this.debugging;
+ window.alert(Scratch.translate("Toggled Debugging! :)"));
+ }
+
+ async connect({ ID, URL }) {
+ const id = Cast.toString(ID);
+ const url = Cast.toString(URL);
+
+ if (this.sockets[id] instanceof WebSocket) {
try {
- this.sockets[id] = new WebSocket(url);
- this.socketStatuses[id] = "connected";
- this.socketCloseCodes[id] = 0;
- this.socketCloseReasons[id] = "";
-
- /**
- * @type {WebSocket}
- */
- const socket = this.sockets[id];
-
- socket.addEventListener("message", this.listener(id));
- socket.addEventListener("error", () => {
+ this.sockets[id].removeEventListener("message", this.listener(id));
+ this.sockets[id].removeEventListener("error", () => {
runtime.startHats("lemonWebSocketsPlus_socketErrored", {
SOCKET: id,
});
});
- socket.addEventListener("message", ({ data }) => {
+ this.sockets[id].removeEventListener("message", ({ data }) => {
this.lastMessages[id] = data;
});
- socket.addEventListener("close", ({ reason, code }) => {
+ this.sockets[id].removeEventListener("close", ({ reason, code }) => {
runtime.startHats("lemonWebSocketsPlus_socketClosedConnection", {
SOCKET: id,
});
this.socketCloseReasons[id] = reason;
this.socketCloseCodes[id] = code;
});
- socket.addEventListener("open", () => {
+ this.sockets[id].removeEventListener("open", () => {
runtime.startHats("lemonWebSocketsPlus_socketOpensConnection", {
SOCKET: id,
});
});
-
- extManager.refreshBlocks("lemonWebSocketsPlus");
- vm.refreshWorkspace();
-
- if (this.debugging)
- console.log(`[WebSockets+] Successfully connected to '${url}'.`);
+ this.sockets[id].close();
} catch (err) {
console.error(err);
- this.socketStatuses[id] = "failed to connect";
}
-
- if (this.debugging) console.groupEnd();
}
-
- disconnect({ ID, C, R }) {
- const id = Cast.toString(ID);
- const Code = Cast.toNumber(C);
- const Reason = Cast.toString(R);
-
- if (this.debugging)
- console.groupCollapsed("WebSockets+ Closing Connection");
-
- if (this.debugging)
- console.log(
- `[WebSockets+] Attemping to close connection with '${id}'..`
- );
-
+
+ if (this.debugging) console.groupCollapsed("WebSockets+ Connecting");
+
+ if (this.debugging)
+ console.log(`[WebSockets+] Attempting to connect to '${url}'..`);
+
+ if (!this.fetchables[url])
+ this.fetchables[url] = await Scratch.canFetch(url);
+
+ if (!this.fetchables[url]) {
+ this.socketStatuses[id] = "failed to connect";
+ if (this.debugging) {
+ console.log(`[Websockets+] Connection to '${url}' denied!`);
+ console.groupEnd();
+ }
+ return;
+ }
+
+ try {
+ this.sockets[id] = new WebSocket(url);
+ this.socketStatuses[id] = "connected";
+ this.socketCloseCodes[id] = 0;
+ this.socketCloseReasons[id] = "";
+
+ /**
+ * @type {WebSocket}
+ */
const socket = this.sockets[id];
-
- if (socket instanceof WebSocket) {
- socket.removeEventListener("message", this.listener(id));
- socket.removeEventListener("error", () => {
- runtime.startHats("lemonWebSocketsPlus_socketErrored", {
- SOCKET: id,
- });
+
+ socket.addEventListener("message", this.listener(id));
+ socket.addEventListener("error", () => {
+ runtime.startHats("lemonWebSocketsPlus_socketErrored", {
+ SOCKET: id,
});
- socket.removeEventListener("message", ({ data }) => {
- this.lastMessages[id] = data;
+ });
+ socket.addEventListener("message", ({ data }) => {
+ this.lastMessages[id] = data;
+ });
+ socket.addEventListener("close", ({ reason, code }) => {
+ runtime.startHats("lemonWebSocketsPlus_socketClosedConnection", {
+ SOCKET: id,
});
- socket.removeEventListener("close", ({ reason, code }) => {
- runtime.startHats("lemonWebSocketsPlus_socketClosedConnection", {
- SOCKET: id,
- });
- this.socketCloseReasons[id] = reason;
- this.socketCloseCodes[id] = code;
+ this.socketCloseReasons[id] = reason;
+ this.socketCloseCodes[id] = code;
+ });
+ socket.addEventListener("open", () => {
+ runtime.startHats("lemonWebSocketsPlus_socketOpensConnection", {
+ SOCKET: id,
});
- socket.removeEventListener("open", () => {
- runtime.startHats("lemonWebSocketsPlus_socketOpensConnection", {
- SOCKET: id,
- });
- });
-
- socket.close(Code, Reason);
-
- delete this.sockets[id];
- this.socketCloseCodes[id] = Code;
- this.socketCloseReasons[id] = Reason;
- this.socketStatuses[id] = "closed";
-
- extManager.refreshBlocks("lemonWebSocketsPlus");
- vm.refreshWorkspace();
-
- if (this.debugging)
- console.log(
- `[WebSockets+] Successfully closed connection with '${id}'!`
- );
- } else {
- if (this.debugging)
- console.warn(`[WebSockets+] WebSocket '${id}' is not a WebSocket!`);
- }
-
- if (this.debugging) console.groupEnd();
-
- return;
+ });
+
+ extManager.refreshBlocks("lemonWebSocketsPlus");
+ vm.refreshWorkspace();
+
+ if (this.debugging)
+ console.log(`[WebSockets+] Successfully connected to '${url}'.`);
+ } catch (err) {
+ console.error(err);
+ this.socketStatuses[id] = "failed to connect";
}
-
- sendMessage({ MESSAGE, SOCKET }) {
- if (this.debugging) {
- console.groupCollapsed("WebSockets+ Message Sending");
-
+
+ if (this.debugging) console.groupEnd();
+ }
+
+ disconnect({ ID, C, R }) {
+ const id = Cast.toString(ID);
+ const Code = Cast.toNumber(C);
+ const Reason = Cast.toString(R);
+
+ if (this.debugging)
+ console.groupCollapsed("WebSockets+ Closing Connection");
+
+ if (this.debugging)
+ console.log(
+ `[WebSockets+] Attemping to close connection with '${id}'..`
+ );
+
+ const socket = this.sockets[id];
+
+ if (socket instanceof WebSocket) {
+ socket.removeEventListener("message", this.listener(id));
+ socket.removeEventListener("error", () => {
+ runtime.startHats("lemonWebSocketsPlus_socketErrored", {
+ SOCKET: id,
+ });
+ });
+ socket.removeEventListener("message", ({ data }) => {
+ this.lastMessages[id] = data;
+ });
+ socket.removeEventListener("close", ({ reason, code }) => {
+ runtime.startHats("lemonWebSocketsPlus_socketClosedConnection", {
+ SOCKET: id,
+ });
+ this.socketCloseReasons[id] = reason;
+ this.socketCloseCodes[id] = code;
+ });
+ socket.removeEventListener("open", () => {
+ runtime.startHats("lemonWebSocketsPlus_socketOpensConnection", {
+ SOCKET: id,
+ });
+ });
+
+ socket.close(Code, Reason);
+
+ delete this.sockets[id];
+ this.socketCloseCodes[id] = Code;
+ this.socketCloseReasons[id] = Reason;
+ this.socketStatuses[id] = "closed";
+
+ extManager.refreshBlocks("lemonWebSocketsPlus");
+ vm.refreshWorkspace();
+
+ if (this.debugging)
console.log(
- `[WebSockets+] Attempting to send a message to '${SOCKET}'..`
+ `[WebSockets+] Successfully closed connection with '${id}'!`
);
- }
- SOCKET = Cast.toString(SOCKET);
- const socket = this.sockets[SOCKET];
-
- if (!socket) {
- if (this.debugging) {
- console.warn(`[WebSockets+] '${SOCKET}' doesn't exist!`);
- console.groupEnd();
- }
- return;
- }
-
- if (socket instanceof WebSocket) {
- try {
- socket.send(MESSAGE);
- if (this.debugging)
- console.log(
- `[WebSockets+] Successfully sent a message to '${SOCKET}'!`
- );
- } catch (err) {
- console.error(err);
- if (this.debugging) console.groupEnd();
- }
- } else {
- if (this.debugging)
- console.warn(`[WebSockets+] '${SOCKET}' isn't a WebSocket!`);
- }
- if (this.debugging) console.groupEnd();
- }
-
- socketExists({ SOCKET }) {
- return Cast.toBoolean(this.sockets[Cast.toString(SOCKET)]);
+ } else {
+ if (this.debugging)
+ console.warn(`[WebSockets+] WebSocket '${id}' is not a WebSocket!`);
}
-
- socketConnected({ SOCKET }) {
- const socket = this.sockets[Cast.toString(SOCKET)];
-
- if (socket instanceof WebSocket) {
- return socket.readyState === WebSocket.OPEN;
- }
-
- return false;
+
+ if (this.debugging) console.groupEnd();
+
+ return;
+ }
+
+ sendMessage({ MESSAGE, SOCKET }) {
+ if (this.debugging) {
+ console.groupCollapsed("WebSockets+ Message Sending");
+
+ console.log(
+ `[WebSockets+] Attempting to send a message to '${SOCKET}'..`
+ );
}
-
- socketClosed({ SOCKET }) {
- const socket = this.sockets[Cast.toString(SOCKET)];
-
- if (socket instanceof WebSocket) {
- return socket.readyState === WebSocket.CLOSED;
+ SOCKET = Cast.toString(SOCKET);
+ const socket = this.sockets[SOCKET];
+
+ if (!socket) {
+ if (this.debugging) {
+ console.warn(`[WebSockets+] '${SOCKET}' doesn't exist!`);
+ console.groupEnd();
}
-
- return true;
- }
-
- websockets() {
- return JSON.stringify(Object.keys(this.sockets));
+ return;
}
-
- socketState({ SOCKET }) {
- const socket = this.sockets[Cast.toString(SOCKET)];
- if (socket instanceof WebSocket) {
- return this.WebSocketStates[socket.readyState] ?? "UNKNOWN";
+
+ if (socket instanceof WebSocket) {
+ try {
+ socket.send(MESSAGE);
+ if (this.debugging)
+ console.log(
+ `[WebSockets+] Successfully sent a message to '${SOCKET}'!`
+ );
+ } catch (err) {
+ console.error(err);
+ if (this.debugging) console.groupEnd();
}
- return "UNKNOWN";
- }
-
- socketLastMessage({ SOCKET }) {
- const socket = this.lastMessages[Cast.toString(SOCKET)];
- return socket ?? "";
- }
-
- socketCloseReason({ SOCKET }) {
- return this.socketCloseReasons[Cast.toString(SOCKET)] ?? "";
- }
-
- socketCloseCode({ SOCKET }) {
- return this.socketCloseCodes[Cast.toString(SOCKET)] ?? 0;
- }
-
- getSockets() {
- const Sockets = Object.keys(this.sockets);
- return Sockets.length > 0
- ? Sockets.map((socket) => {
- return {
- value: socket,
- text: socket,
- };
- })
- : [
- {
- value: Scratch.translate("None yet :("),
- text: Scratch.translate("None yet :("),
- },
- ];
- }
-
- /**
- * @param {{}} args
- * @param {VM.BlockUtility} util
- */
- socketMessage(args, util) {
- return util.thread.socketMessage ?? "";
- }
-
- socketOpensConnection() {
- return;
+ } else {
+ if (this.debugging)
+ console.warn(`[WebSockets+] '${SOCKET}' isn't a WebSocket!`);
}
-
- socketMessageReceived() {
- return;
+ if (this.debugging) console.groupEnd();
+ }
+
+ socketExists({ SOCKET }) {
+ return Cast.toBoolean(this.sockets[Cast.toString(SOCKET)]);
+ }
+
+ socketConnected({ SOCKET }) {
+ const socket = this.sockets[Cast.toString(SOCKET)];
+
+ if (socket instanceof WebSocket) {
+ return socket.readyState === WebSocket.OPEN;
}
-
- socketErrored() {
- return;
+
+ return false;
+ }
+
+ socketClosed({ SOCKET }) {
+ const socket = this.sockets[Cast.toString(SOCKET)];
+
+ if (socket instanceof WebSocket) {
+ return socket.readyState === WebSocket.CLOSED;
}
-
- socketClosedConnection() {
- return;
+
+ return true;
+ }
+
+ websockets() {
+ return JSON.stringify(Object.keys(this.sockets));
+ }
+
+ socketState({ SOCKET }) {
+ const socket = this.sockets[Cast.toString(SOCKET)];
+ if (socket instanceof WebSocket) {
+ return this.WebSocketStates[socket.readyState] ?? "UNKNOWN";
}
+ return "UNKNOWN";
+ }
+
+ socketLastMessage({ SOCKET }) {
+ const socket = this.lastMessages[Cast.toString(SOCKET)];
+ return socket ?? "";
+ }
+
+ socketCloseReason({ SOCKET }) {
+ return this.socketCloseReasons[Cast.toString(SOCKET)] ?? "";
+ }
+
+ socketCloseCode({ SOCKET }) {
+ return this.socketCloseCodes[Cast.toString(SOCKET)] ?? 0;
+ }
+
+ getSockets() {
+ const Sockets = Object.keys(this.sockets);
+ return Sockets.length > 0
+ ? Sockets.map((socket) => {
+ return {
+ value: socket,
+ text: socket,
+ };
+ })
+ : [
+ {
+ value: Scratch.translate("None yet :("),
+ text: Scratch.translate("None yet :("),
+ },
+ ];
+ }
+
+ /**
+ * @param {{}} args
+ * @param {VM.BlockUtility} util
+ */
+ socketMessage(args, util) {
+ return util.thread.socketMessage ?? "";
+ }
+
+ socketOpensConnection() {
+ return;
}
-
- Scratch.extensions.register(new WebsocketsPlusExt());
- })(Scratch);
+
+ socketMessageReceived() {
+ return;
+ }
+
+ socketErrored() {
+ return;
+ }
+
+ socketClosedConnection() {
+ return;
+ }
+ }
+
+ Scratch.extensions.register(new WebsocketsPlusExt());
+})(Scratch);
From 82cae42a2631be629abd111893b6cabe66d9d9bf Mon Sep 17 00:00:00 2001
From: Lemon <165233560+BludIsAnLemon@users.noreply.github.com>
Date: Thu, 13 Mar 2025 16:26:31 +0800
Subject: [PATCH 10/10] Changed name to WebSocket V2
---
extensions/Cheddarphanie/websockets-plus.js | 34 ++++++++++-----------
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/extensions/Cheddarphanie/websockets-plus.js b/extensions/Cheddarphanie/websockets-plus.js
index 1eab3c13a7..8a90f5712b 100644
--- a/extensions/Cheddarphanie/websockets-plus.js
+++ b/extensions/Cheddarphanie/websockets-plus.js
@@ -1,4 +1,4 @@
-// Name: WebSockets+
+// Name: WebSocket V2
// ID: lemonWebSocketsPlus
// Description: Connect to more than one WebSockets.
// By: Cheddarphanie
@@ -10,7 +10,7 @@
"use strict";
if (!Scratch.extensions.unsandboxed) {
- throw new Error("The WebSockets+ Extension must run unsandboxed.");
+ throw new Error("The WebSocket V2 Extension must run unsandboxed.");
}
const vm = Scratch.vm;
@@ -37,7 +37,7 @@
};
};
- class WebsocketsPlusExt {
+ class WebsocketV2Ext {
constructor() {
this.debugging = false;
@@ -79,7 +79,7 @@
getInfo() {
return {
id: "lemonWebSocketsPlus",
- name: Scratch.translate("WebSockets+"),
+ name: Scratch.translate("WebSocket V2"),
color1: "#307eff",
color2: "#2c5eb0",
blocks: [
@@ -364,10 +364,10 @@
}
}
- if (this.debugging) console.groupCollapsed("WebSockets+ Connecting");
+ if (this.debugging) console.groupCollapsed("WebSocket V2 Connecting");
if (this.debugging)
- console.log(`[WebSockets+] Attempting to connect to '${url}'..`);
+ console.log(`[WebSockets V2] Attempting to connect to '${url}'..`);
if (!this.fetchables[url])
this.fetchables[url] = await Scratch.canFetch(url);
@@ -375,7 +375,7 @@
if (!this.fetchables[url]) {
this.socketStatuses[id] = "failed to connect";
if (this.debugging) {
- console.log(`[Websockets+] Connection to '${url}' denied!`);
+ console.log(`[Websocket V2] Connection to '${url}' denied!`);
console.groupEnd();
}
return;
@@ -418,7 +418,7 @@
vm.refreshWorkspace();
if (this.debugging)
- console.log(`[WebSockets+] Successfully connected to '${url}'.`);
+ console.log(`[WebSocket V2] Successfully connected to '${url}'.`);
} catch (err) {
console.error(err);
this.socketStatuses[id] = "failed to connect";
@@ -433,11 +433,11 @@
const Reason = Cast.toString(R);
if (this.debugging)
- console.groupCollapsed("WebSockets+ Closing Connection");
+ console.groupCollapsed("WebSocket V2 Closing Connection");
if (this.debugging)
console.log(
- `[WebSockets+] Attemping to close connection with '${id}'..`
+ `[WebSocket V2] Attemping to close connection with '${id}'..`
);
const socket = this.sockets[id];
@@ -477,11 +477,11 @@
if (this.debugging)
console.log(
- `[WebSockets+] Successfully closed connection with '${id}'!`
+ `[WebSocket V2] Successfully closed connection with '${id}'!`
);
} else {
if (this.debugging)
- console.warn(`[WebSockets+] WebSocket '${id}' is not a WebSocket!`);
+ console.warn(`[WebSocket V2] WebSocket '${id}' is not a WebSocket!`);
}
if (this.debugging) console.groupEnd();
@@ -491,10 +491,10 @@
sendMessage({ MESSAGE, SOCKET }) {
if (this.debugging) {
- console.groupCollapsed("WebSockets+ Message Sending");
+ console.groupCollapsed("WebSocket V2 Message Sending");
console.log(
- `[WebSockets+] Attempting to send a message to '${SOCKET}'..`
+ `[WebSocket V2] Attempting to send a message to '${SOCKET}'..`
);
}
SOCKET = Cast.toString(SOCKET);
@@ -513,7 +513,7 @@
socket.send(MESSAGE);
if (this.debugging)
console.log(
- `[WebSockets+] Successfully sent a message to '${SOCKET}'!`
+ `[WebSocket V2] Successfully sent a message to '${SOCKET}'!`
);
} catch (err) {
console.error(err);
@@ -521,7 +521,7 @@
}
} else {
if (this.debugging)
- console.warn(`[WebSockets+] '${SOCKET}' isn't a WebSocket!`);
+ console.warn(`[WebSocket V2] '${SOCKET}' isn't a WebSocket!`);
}
if (this.debugging) console.groupEnd();
}
@@ -617,5 +617,5 @@
}
}
- Scratch.extensions.register(new WebsocketsPlusExt());
+ Scratch.extensions.register(new WebsocketV2Ext());
})(Scratch);