From a742593ebe64067b0e1eb4c66f93d6897b12e6a4 Mon Sep 17 00:00:00 2001 From: goldbuick Date: Sat, 4 Jan 2025 04:31:22 -0500 Subject: [PATCH] functional twitch chat integration --- cafe/app.tsx | 8 +-- zss/device/api.ts | 33 +++++++++++- zss/device/chat.ts | 3 +- zss/firmware/loader.ts | 45 ++++++++++------ zss/firmware/loader/parsefile.ts | 90 +++++++++++++++++-------------- zss/firmware/loader/textloader.ts | 5 +- zss/memory/loader.ts | 2 - 7 files changed, 120 insertions(+), 66 deletions(-) diff --git a/cafe/app.tsx b/cafe/app.tsx index 2dc294441..78862a01c 100644 --- a/cafe/app.tsx +++ b/cafe/app.tsx @@ -57,7 +57,9 @@ window.addEventListener('paste', (event) => { // read files from clipboardData const files = [...event.clipboardData.files] - files.forEach((file) => vm_loader('app', 'file', file, registerreadplayer())) + files.forEach((file) => + vm_loader('app', 'file', file.name, file, registerreadplayer()), + ) }) window.addEventListener('drop', (event) => { @@ -72,7 +74,7 @@ window.addEventListener('drop', (event) => { if (item.kind === 'file') { const file = item.getAsFile() if (ispresent(file)) { - vm_loader('app', 'file', file, registerreadplayer()) + vm_loader('app', 'file', file.name, file, registerreadplayer()) } } }) @@ -80,7 +82,7 @@ window.addEventListener('drop', (event) => { // Use DataTransfer interface to access the file(s) const files = [...(event.dataTransfer?.files ?? [])] files.forEach((file) => - vm_loader('app', 'file', file, registerreadplayer()), + vm_loader('app', 'file', file.name, file, registerreadplayer()), ) } }) diff --git a/zss/device/api.ts b/zss/device/api.ts index 0c6985ff0..1766a0dad 100644 --- a/zss/device/api.ts +++ b/zss/device/api.ts @@ -294,8 +294,39 @@ export function vm_flush(sender: string, tag: string, player: string) { export function vm_loader( sender: string, event: string, + filename: string, content: any, player: string, ) { - hub.emit('vm:loader', sender, [event, content], player) + function createtextreader() { + return { + filename, + cursor: 0, + lines: content.split('\n'), + } + } + function createbinaryreader() { + return { + filename, + cursor: 0, + bytes: content, + dataview: new DataView(content.buffer), + } + } + let withcontent: any + switch (event) { + case 'file': + withcontent = content + break + case 'chat': + withcontent = createtextreader() + break + case 'text': + withcontent = createtextreader() + break + case 'binary': + withcontent = createbinaryreader() + break + } + hub.emit('vm:loader', sender, [event, withcontent], player) } diff --git a/zss/device/chat.ts b/zss/device/chat.ts index ac7fe18f6..06dab4437 100644 --- a/zss/device/chat.ts +++ b/zss/device/chat.ts @@ -27,7 +27,8 @@ const chat = createdevice('chat', [], (message) => { vm_loader( chat.name(), 'chat', - `${user}: ${text}`, + message.data, + `${user}:${text}`, registerreadplayer(), ) }) diff --git a/zss/firmware/loader.ts b/zss/firmware/loader.ts index 77bc27842..05b4db5d4 100644 --- a/zss/firmware/loader.ts +++ b/zss/firmware/loader.ts @@ -2,30 +2,43 @@ import { maptostring } from 'zss/chip' import { tape_info } from 'zss/device/api' import { createfirmware } from 'zss/firmware' import { createsid } from 'zss/mapping/guid' -import { ispresent } from 'zss/mapping/types' import { MEMORY_LABEL, memoryensuresoftwarebook } from 'zss/memory' +import { memoryloadercontent, memoryloaderevent } from 'zss/memory/loader' +import { BINARY_READER, TEXT_READER } from 'zss/memory/types' import { ARG_TYPE, readargs } from 'zss/words/reader' -import { NAME } from 'zss/words/types' import { binaryloader } from './loader/binaryloader' import { textloader } from './loader/textloader' export const LOADER_FIRMWARE = createfirmware({ get(chip, name) { - // check loader flags - - // const binaryfile = memoryreadbinaryfile(chip.id()) - // if (ispresent(binaryfile)) { - // switch (NAME(name)) { - // case 'filename': - // // name of binary file - // return [ispresent(binaryfile.filename), binaryfile.filename] - // case 'cursor': - // // return where we are in the binary file ? - // return [ispresent(binaryfile.cursor), binaryfile.cursor] - // } - // } - + const type = memoryloaderevent(chip.id()) + switch (type) { + case 'chat': { + const textreader: TEXT_READER = memoryloadercontent(chip.id()) + switch (name) { + case 'filename': + return [true, textreader.filename] + case 'cursor': + return [true, textreader.cursor] + case 'lines': + return [true, textreader.lines.length] + } + break + } + case 'binary': { + const binaryreader: BINARY_READER = memoryloadercontent(chip.id()) + switch (name) { + case 'filename': + return [true, binaryreader.filename] + case 'cursor': + return [true, binaryreader.cursor] + case 'bytes': + return [true, binaryreader.bytes.length] + } + break + } + } return [false, undefined] }, }) diff --git a/zss/firmware/loader/parsefile.ts b/zss/firmware/loader/parsefile.ts index 0e4bd6fad..08ad51081 100644 --- a/zss/firmware/loader/parsefile.ts +++ b/zss/firmware/loader/parsefile.ts @@ -1,15 +1,7 @@ import JSZip from 'jszip' import mime from 'mime/lite' -import { api_error, tape_info } from 'zss/device/api' +import { api_error, tape_info, vm_loader } from 'zss/device/api' import { ispresent } from 'zss/mapping/types' -import { MEMORY_LABEL, memoryensuresoftwarebook } from 'zss/memory' -import { bookreadcodepagewithtype, bookwritecodepage } from 'zss/memory/book' -import { - codepagereadname, - codepagereadtype, - codepagereadtypetostring, - createcodepage, -} from 'zss/memory/codepage' import { NAME } from 'zss/words/types' export function mimetypeofbytesread(filename: string, filebytes: Uint8Array) { @@ -35,38 +27,7 @@ export function mimetypeofbytesread(filename: string, filebytes: Uint8Array) { return mime.getType(filename) ?? 'application/octet-stream' } -// create codepage from source text -function createcodepagefromtext(text: string) { - const codepage = createcodepage(text, {}) - const pagename = codepagereadname(codepage) - const pagetype = codepagereadtypetostring(codepage) - - const mainbook = memoryensuresoftwarebook(MEMORY_LABEL.MAIN) - if (!ispresent(mainbook)) { - return - } - - // only create if target doesn't already exist - const codepagetype = codepagereadtype(codepage) - const maybepage = bookreadcodepagewithtype(mainbook, codepagetype, pagename) - - if (ispresent(maybepage)) { - tape_info( - 'memory', - `${mainbook.name} already has a [${pagetype}] named ${pagename}`, - ) - } else { - bookwritecodepage(mainbook, codepage) - tape_info('memory', `created [${pagetype}] ${pagename} in ${mainbook.name}`) - } -} - // various handlers -export async function parsetextfile(file: File) { - const text = await file.text() - createcodepagefromtext(text) -} - export async function parsezipfile( file: File, onreadfile: (zipfile: File) => void, @@ -108,3 +69,52 @@ export async function parsebinaryfile( api_error('memory', 'crash', err.message) } } + +export function parsewebfile(player: string, file: File | undefined) { + function handlefiletype(type: string) { + if (!ispresent(file)) { + return + } + switch (type) { + case 'text/plain': + file + .text() + .then((content) => + vm_loader('parsefile', 'text', file.name, content, player), + ) + .catch((err) => api_error('fileloader', 'crash', err.message)) + break + case 'application/zip': + parsezipfile(file, (ifile) => parsewebfile(player, ifile)).catch( + (err) => api_error('fileloader', 'crash', err.message), + ) + break + case 'application/octet-stream': + parsebinaryfile(file, (fileext, binaryfile) => + vm_loader('parsefile', 'binary', fileext, binaryfile, player), + ).catch((err) => api_error('memory', 'crash', err.message)) + break + default: + file + .arrayBuffer() + .then((arraybuffer) => { + const type = mimetypeofbytesread( + file.name, + new Uint8Array(arraybuffer), + ) + if (type) { + handlefiletype(type) + } else { + return api_error( + 'memory', + 'loadfile', + `unsupported file ${file.name}`, + ) + } + }) + .catch((err) => api_error('memory', 'crash', err.message)) + return + } + } + handlefiletype(file?.type ?? '') +} diff --git a/zss/firmware/loader/textloader.ts b/zss/firmware/loader/textloader.ts index bd0816606..07769899e 100644 --- a/zss/firmware/loader/textloader.ts +++ b/zss/firmware/loader/textloader.ts @@ -28,14 +28,13 @@ export const textloader: FIRMWARE_COMMAND = (chip, words) => { ) break default: { - const [pattern, iii] = readargs(words, ii, [ARG_TYPE.STRING]) // we have pattern + names for captures const line = textreader.lines[textreader.cursor] ?? '' - const regex = new RegExp(pattern, 'i') + const regex = new RegExp(kind, 'i') const result = regex.exec(line) if (ispresent(result)) { let m = 1 - for (let i = iii; i < words.length; ) { + for (let i = ii; i < words.length; ) { // read next name to set const [name, next] = readargs(words, i, [ARG_TYPE.STRING]) // set entry diff --git a/zss/memory/loader.ts b/zss/memory/loader.ts index d2e9ca452..3875b6c1e 100644 --- a/zss/memory/loader.ts +++ b/zss/memory/loader.ts @@ -1,4 +1,3 @@ -import { tape_info } from 'zss/device/api' import { createsid } from 'zss/mapping/guid' import { ispresent } from 'zss/mapping/types' @@ -45,6 +44,5 @@ export function memoryloader(event: string, content: any) { EVENT_BY_ID[id] = event CONTENT_BY_ID[id] = content memoryloaderstart(id, loaders[i].code) - tape_info('memory', 'starting loader', mainbook.timestamp, id) } }