Live video on the AT Protocol
1import { app, dialog, ipcMain } from "electron";
2import { parseArgs } from "node:util";
3import "source-map-support/register";
4import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
5import getEnv from "./env";
6import makeNode from "./node";
7import runTests, { allTestNames } from "./tests/test-runner";
8import initUpdater from "./updater";
9import { makeWindow } from "./window";
10
11// Handle creating/removing shortcuts on Windows when installing/uninstalling.
12if (require("electron-squirrel-startup")) {
13 app.quit();
14} else {
15 const { values: args, positionals } = parseArgs({
16 options: {
17 path: {
18 type: "string",
19 default: "",
20 },
21 "self-test": {
22 type: "boolean",
23 },
24 "self-test-duration": {
25 type: "string",
26 default: "300000",
27 },
28 "tests-to-run": {
29 type: "string",
30 default: allTestNames.join(","),
31 },
32 },
33 });
34 const env = getEnv();
35 console.log(
36 "starting with: ",
37 JSON.stringify({ args, positionals, env }, null, 2),
38 );
39
40 app.on("ready", async () => {
41 let privateKey: `0x${string}`;
42 if (process.env.AQD_ADMIN_ACCOUNT_KEY) {
43 privateKey = process.env.AQD_ADMIN_ACCOUNT_KEY as `0x${string}`;
44 } else {
45 privateKey = generatePrivateKey();
46 }
47 ipcMain.handle("getPrivateKey", () => privateKey);
48 const account = privateKeyToAccount(privateKey);
49 const env = {
50 SP_ADMIN_ACCOUNT: account.address.toLowerCase(),
51 SP_ALLOWED_STREAMS: account.address.toLowerCase(),
52 };
53 if (args["self-test"]) {
54 app.on("window-all-closed", () => {
55 // need to override this to prevent the app from quitting
56 });
57 const success = await runTests(
58 args["tests-to-run"].split(","),
59 args["self-test-duration"],
60 privateKey,
61 );
62 console.log("tests finished");
63 if (!success) {
64 app.exit(1);
65 } else {
66 app.exit(0);
67 }
68 } else {
69 try {
70 await start(env);
71 } catch (e) {
72 console.error(e);
73 const dialogOpts: Electron.MessageBoxOptions = {
74 type: "info",
75 buttons: ["Quit Streamplace"],
76 title: "Error on Bootup",
77 message:
78 "Please report to the Streamplace developers at git.stream.place!",
79 detail: e.message + "\n" + e.stack,
80 };
81
82 await dialog.showMessageBox(dialogOpts);
83 app.quit();
84 }
85 }
86 });
87
88 const start = async (env: { [k: string]: string }): Promise<void> => {
89 app.on("window-all-closed", () => {
90 if (process.platform !== "darwin") {
91 app.quit();
92 }
93 });
94 const { skipNode, nodeFrontend, noUpdate } = getEnv();
95 if (!noUpdate) {
96 initUpdater();
97 }
98 let loadAddr;
99 if (!skipNode) {
100 const { addr } = await makeNode({ env, autoQuit: true });
101 loadAddr = addr;
102 }
103 const mainWindow = await makeWindow();
104
105 let startPath;
106 if (nodeFrontend) {
107 startPath = `${loadAddr}${args.path}`;
108 } else {
109 startPath = `http://127.0.0.1:38081${args.path}`;
110 }
111 console.log(`opening ${startPath}`);
112 mainWindow.loadURL(startPath);
113 };
114
115 // This method will be called when Electron has finished
116 // initialization and is ready to create browser windows.
117 // Some APIs can only be used after this event occurs.
118
119 // Quit when all windows are closed, except on macOS. There, it's common
120 // for applications and their menu bar to stay active until the user quits
121 // explicitly with Cmd + Q.
122
123 app.on("activate", () => {
124 // On OS X it's common to re-create a window in the app when the
125 // dock icon is clicked and there are no other windows open.
126 // if (BrowserWindow.getAllWindows().length === 0) {
127 // }
128 });
129
130 // In this file you can include the rest of your app's specific main process
131 // code. You can also put them in separate files and import them here.
132}