Skip to content

Commit

Permalink
Merge pull request #211 from LordTocs/hackathon
Browse files Browse the repository at this point in the history
Hackathon Entry!
  • Loading branch information
LordTocs authored Nov 4, 2024
2 parents 89041bb + ff175a3 commit 14b3e64
Show file tree
Hide file tree
Showing 278 changed files with 28,018 additions and 510 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
user*/
/dist
/release
/release-satellite
dist-electron/
backup_04.zip

Expand Down
2 changes: 2 additions & 0 deletions libs/castmate-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"devDependencies": {
"@electron/rebuild": "^3.6.0",
"@types/better-sqlite3": "^7.6.11",
"@types/cors": "^2.8.17",
"@types/express": "^4.17.21",
"@types/http-proxy": "^1.17.14",
"@types/lodash": "^4.14.192",
Expand All @@ -32,6 +33,7 @@
"better-sqlite3": "^11.1.2",
"castmate-schema": "workspace:^",
"chokidar": "^3.5.3",
"cors": "^2.8.5",
"electron": "29.4.5",
"electron-updater": "6.1.8",
"express": "^4.18.2",
Expand Down
4 changes: 4 additions & 0 deletions libs/castmate-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,7 @@ export * from "./info/info-manager"
export * from "./util/time-utils"

export * from "./viewer-data/viewer-data"

export * from "./satellite/satellite-service"
export * from "./satellite/satellite-resource"
export * from "./satellite/satellite-media"
4 changes: 4 additions & 0 deletions libs/castmate-core/src/io/file-system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ export async function writeSecretYAML<T = any>(data: T, ...paths: string[]) {
}

export async function initializeFileSystem() {
ipcMain.handle(`filesystem_getUserFolder`, () => {
return activeProjectDirectory
})

ipcMain.handle(`filesystem_getFolderInput`, async (event: IpcMainInvokeEvent, existing: string | undefined) => {
const window = BrowserWindow.fromWebContents(event.sender)

Expand Down
20 changes: 20 additions & 0 deletions libs/castmate-core/src/media/media-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,26 @@ export const MediaManager = Service(
await this.copyMedia(localPath, mediaPath)
})

defineIPCFunc("media", "validateRemoteMediaPath", async (mediaPath: string) => {
try {
const realFile = await fs.realpath(mediaPath)

const tempFolder = await fs.realpath(app.getPath("temp"))
const mediaFolder = await fs.realpath(resolveProjectPath("./media"))

if (realFile.indexOf(tempFolder) == 0) {
return realFile
}
if (realFile.indexOf(mediaFolder) == 0) {
return realFile
}
return undefined
} catch (err) {
//Special case, could be TTS generated file in the temp path
return undefined
}
})

const router = express.Router()
router.use(express.static(mediaPath))
WebService.getInstance().addRootRouter("/media/default", router)
Expand Down
21 changes: 21 additions & 0 deletions libs/castmate-core/src/plugins/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,27 @@ export function definePlugin(spec: PluginSpec, initter: () => void) {
)
}

interface SatellitePluginSpec {
id: string
name: string
description?: string
icon?: string
color?: Color
version?: SemanticVersion
}

export function defineSatellitePlugin(spec: SatellitePluginSpec, initter: () => void) {
return new Plugin(
{
icon: "mdi mdi-puzzle",
color: "#fefefe",
version: "0.0.0",
...spec,
},
initter
)
}

export function defineRendererCallable<T extends (...args: any[]) => any>(name: string, func: T) {
if (!initingPlugin) throw new Error()

Expand Down
10 changes: 6 additions & 4 deletions libs/castmate-core/src/pubsub/pubsub-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ import { ReactiveEffect, autoRerun } from "../reactivity/reactivity"

const logger = usePluginLogger("pubsub")

const baseURL = "https://api.spellcast.gg/"

const baseURL = import.meta.env.VITE_CASTMATE_URL
/**
* PubSubManager connects to the azure-pubsub allowing realtime events from the cloud.
*/
Expand All @@ -28,7 +27,7 @@ export const PubSubManager = Service(
private onConnect = new EventList()
private onBeforeDisconnect = new EventList()

constructor() {}
constructor(private mode: "satellite" | "castmate") {}

setToken(token: string | undefined) {
logger.log("Cloud PubSub Received Auth Token")
Expand Down Expand Up @@ -93,7 +92,9 @@ export const PubSubManager = Service(
logger.log("Starting Cloud PubSub Connection")
this.connecting = true

const negotiationResp = await axios.get("/pubsub/negotiate", {
const negotiationUrl = this.mode == "castmate" ? "/pubsub/negotiate" : "/pubsub/satellite/negotiate"

const negotiationResp = await axios.get(negotiationUrl, {
baseURL,
headers: {
Authorization: `Bearer ${this.token}`,
Expand Down Expand Up @@ -170,6 +171,7 @@ export const PubSubManager = Service(
}

private checkEvents() {
logger.log("Checking Pubsbu Events")
if (this.onMessage.handlerCount == 0) {
this.stop()
} else {
Expand Down
8 changes: 8 additions & 0 deletions libs/castmate-core/src/resources/resource-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ interface ResourceEntry<T extends ResourceBase = any> {
constructor: ResourceConstructor<T>
storage: ResourceStorage<T>
ipcFuncs: string[]
satelliteFuncs: string[]
}

export async function createResource<T extends ResourceBase>(constructor: ResourceConstructor<T>, ...args: any[]) {
Expand Down Expand Up @@ -128,6 +129,7 @@ export const ResourceRegistry = Service(
constructor,
storage: constructor.storage,
ipcFuncs: [],
satelliteFuncs: []
})

rendererAddResourceType(constructor.storage.name)
Expand Down Expand Up @@ -155,6 +157,12 @@ export const ResourceRegistry = Service(
resourceType.ipcFuncs.push(name as string)
}

exposeSatelliteFunction<T extends ResourceBase>(constructor: ResourceConstructor<T>, name: keyof T) {
const resourceType = this.getResourceType(constructor.storage.name)
if (!resourceType) return
resourceType.satelliteFuncs.push(name as string)
}

getResourceType<T extends ResourceBase>(typeName: string) {
return this.resourceTypes.find((rt) => rt.typeName == typeName) as ResourceEntry<T>
}
Expand Down
76 changes: 76 additions & 0 deletions libs/castmate-core/src/satellite/satellite-media.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { Service } from "../util/service"
import { createDelayedResolver, DelayedResolver, hashString } from "castmate-schema"
import path from "path"
import { ensureDirectory, resolveProjectPath } from "../io/file-system"
import fs from "fs"
import { defineCallableIPC, defineIPCFunc } from "../util/electron"
import { usePluginLogger } from "../logging/logging"
import { SatelliteService } from "./satellite-service"
import { app } from "electron"

function createCacheName(remoteId: string, mediaFile: string) {
const ext = path.extname(mediaFile)
const hash = hashString(`${remoteId}${mediaFile}`)

return `media_${hash}${ext}`
}

const rendererStartMediaRequest = defineCallableIPC<(mediaFile: string, cacheName: string, cacheFile: string) => any>(
"satellite",
"startMediaRequest"
)

const logger = usePluginLogger("media-cache")

export const SatelliteMedia = Service(
class {
private pendingRequests = new Map<
string,
{
resolver: DelayedResolver<string>
}
>()

constructor() {}

async initialize() {
//await ensureDirectory(resolveProjectPath("mediaCache"))

defineIPCFunc("satellite", "mediaRequestDone", (mediaFile: string, cacheName: string) => {
const request = this.pendingRequests.get(mediaFile)
if (!request) return

const cachedFile = path.join(app.getPath("temp"), cacheName)

if (!fs.existsSync(cachedFile)) request.resolver.reject(new Error("Media Failed Request"))

request.resolver.resolve(cachedFile)
})
}

async getMediaFile(mediaFile: string) {
const connectionId = SatelliteService.getInstance().getCastMateConnection()
if (!connectionId) throw new Error("Not Connected")
const remoteId = SatelliteService.getInstance().getConnection(connectionId)?.remoteId
if (!remoteId) throw new Error("Not Connected")

const cacheName = createCacheName(remoteId, mediaFile)

const cachedFile = path.join(app.getPath("temp"), cacheName)

if (fs.existsSync(cachedFile)) {
return cachedFile
} else {
logger.log("Media missing from cache, requesting...")
const resolver = createDelayedResolver<string>()
this.pendingRequests.set(mediaFile, {
resolver,
})

rendererStartMediaRequest(mediaFile, cacheName, cachedFile)

return await resolver.promise
}
}
}
)
Loading

0 comments on commit 14b3e64

Please sign in to comment.