Skip to content

Commit

Permalink
Add menu, checkVersion, and scroll speakers
Browse files Browse the repository at this point in the history
  • Loading branch information
rakusan2 committed Nov 8, 2021
1 parent 53467a1 commit 239f91e
Show file tree
Hide file tree
Showing 16 changed files with 924 additions and 36 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,10 @@ OBS will hide the background
| **OBS-CWD** | | String | Location from where to launch OBS |
| **OBS-Profile** | | String | Sets OBS Profile |
| **OBS-Scene** | | String | Sets OBS Scene
| **OBS-Minimize** | | Switch | Sets OBS minimize on start to true
| **Cert** | | String | File path to SSL Certificate or directory with both SSL |ertificate and Key
| **Key** | | String | File path to SSL Key
| **OBS-Minimize** | obs-min | Switch | Sets OBS minimize on start to true
| **ssl** | | String | File path to SSL directory with both SSL certificate and Key
| **ssl-cert** | | String | File path to SSL Certificate
| **ssl-key** | | String | File path to SSL Key
| **UDP** | u | Switch | Starts UDP socket on port 8889
| **UDP** | u | Number | Starts UDP socket on assigned port
| **UDP-Interface** | | String | Sets which Interface will be used by UDP. (Can be Network Adapter Name or an IP address used by a Network Adapter)
Expand Down
3 changes: 1 addition & 2 deletions server/src/broadcast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ let send: null | ((msg: Buffer, port: number, dest?: string) => void) = null

if (udp != null) {
const { port, broadcast, user = [], interface: if_addr = getInterfaceAddress() } = udp
const int = networkInterfaces()
console.log(`Starting UDP Socket on port ${port} of ${if_addr}`)
if (broadcast) console.log('Socket broadcasting to ' + broadcast)
const soc = createSocket('udp4')
Expand Down Expand Up @@ -71,7 +70,7 @@ if (udp != null) {
}

if (tcp != null) {
const { port = 8891, interface: if_addr = getInterfaceAddress() } = tcp
const { port, interface: if_addr = getInterfaceAddress() } = tcp
console.log(`Starting TCP Socket on port ${port} of ${if_addr}`)
let clients: { client: Socket, users?: string[] }[] = []
let timer: NodeJS.Timeout | null = null
Expand Down
151 changes: 147 additions & 4 deletions server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,28 @@ import parameters from './preLoad'
import createServer from './webServer'
import { Socket } from 'socket.io'
import { openOBS, open, getRandomStr64, isStringArray } from './tools'
import { IUser, IKeyVal, IResponseFn, IResponseInit, ISetting, ISettings } from './types'
import { IUser, IKeyVal, IResponseFn, IResponseInit, ISetting, ISettings, GithubReleaseResponse, VersionCheckStatus, GithubAsset } from './types'
import { Settings } from './settings'
import './broadcast'
import { get } from 'https'
import { platform } from 'os'
import { writeFile } from 'fs/promises'
import { readFileSync } from 'fs'

const { oneID, obs, open: openLoc } = parameters

console.log('parameters', parameters)

let lastVersion = 'v0.0.0'

try {
const pkgFile = readFileSync('./package.json', 'utf8')
const pkg = JSON.parse(pkgFile) as { version: string, name: string }
lastVersion = 'v' + pkg.version
} catch { }

console.log('Version:', lastVersion)

const users: { [id: string]: IUser } = {}
const sockets: IKeyVal<Socket[]> = {}

Expand All @@ -16,7 +32,7 @@ const io = createServer(address => {

if (openLoc != null) {
const openVal = openLoc
open(address, openVal === '' ? undefined : { app: { name: openVal } }).catch(() => console.log('Can not Open'))
open(address, typeof openVal !== 'string' ? undefined : { app: { name: openVal } }).catch(() => console.log('Can not Open'))
}
if (obs != null) {
openOBS(obs).catch(err => console.error(err, 'Unable to launch OBS\nPlease pass in the path to the OBS executable or install OBS\nhttps://obsproject.com/download\n'))
Expand Down Expand Up @@ -66,7 +82,7 @@ io.on('connection', socket => {
logUserCount()

lastTimestamp = Date.now()
fn({ ok: true, id: userID, settings: user.data, serverTime: Date.now(), idLock: oneID != null })
fn({ ok: true, id: userID, settings: user.data, serverTime: Date.now(), idLock: oneID != null, version: lastVersion })
} catch (err: any) {
console.log({ init: { err } })
if (typeof err == 'string') {
Expand All @@ -85,7 +101,7 @@ io.on('connection', socket => {
lastTimestamp = Date.now()
let { keysNotSet, keysSet } = user.set(settings)
fn({ ok: true, keysNotSet })
if(keysNotSet.length > 0) console.warn({ keysNotSet })
if (keysNotSet.length > 0) console.warn({ keysNotSet })
if (Object.keys(keysSet).length > 0) {
sockets[user.id].forEach(soc => {
if (socket !== soc) {
Expand All @@ -108,8 +124,103 @@ io.on('connection', socket => {
fn({ ok: false, err: 'Invalid Keys' })
}
})
.on('checkVersion', (_msg: any, fn: IResponseFn<VersionCheckStatus>) => {
if (!isCheckingVersion) checkVersion()
switch (versionStatus) {
case VersionStatus.checking:
fn({ ok: true, version: lastVersion, status: 'Checking' })
break
case VersionStatus.downloading:
fn({ ok: true, version: lastVersion, status: 'Downloading' })
break
case VersionStatus.err:
fn({ ok: false, err: 'Version Check Error' })
break
case VersionStatus.newest:
fn({ ok: true, version: lastVersion, status: 'Newest' })
break
case VersionStatus.noPlatform:
fn({ ok: false, err: 'Unknown Platform' })
break
case VersionStatus.noRelease:
fn({ ok: true, version: lastVersion, status: 'Release Not Found' })
break
}
})
})

let lastCheck = 0
let isCheckingVersion = false
let versionStatus = VersionStatus.newest

const enum VersionStatus {
checking,
downloading,
newest,
noPlatform,
noRelease,
err
}

async function checkVersion() {
const timestamp = Date.now()
if (timestamp - lastCheck < 1000) {
return
}
isCheckingVersion = true
lastCheck = Date.now()
try {
versionStatus = VersionStatus.checking
const data = await getP<GithubReleaseResponse[]>('https://api.github.com/repos/rakusan2/Toastmasters-Timer-Overlay/releases?per_page=4')
if (typeof data === 'string') {
isCheckingVersion = false
console.warn('Unable to parse GitHub Data')
isCheckingVersion = false
versionStatus = VersionStatus.err
return
}
const obj = data.find(a => !a.prerelease && !a.draft)
if (obj == null) {
console.warn('Unable to find release version')
isCheckingVersion = false
versionStatus = VersionStatus.noRelease
return
}
if (obj.tag_name === lastVersion) {
isCheckingVersion = false
versionStatus = VersionStatus.newest
return
}

let assetID = 0
let asset: GithubAsset | undefined
const os = platform()
let platformStr: string = ''
if (os === 'win32') platformStr = 'timer-overlay-win.exe'
else if (os === 'linux') platformStr = 'timer-overlay-linux'
else if (os === 'darwin') platformStr = 'timer-overlay-macos'

asset = obj.assets.find(a => a.name === platformStr)

if (asset == null) {
isCheckingVersion = false
versionStatus = VersionStatus.noPlatform
return
}
versionStatus = VersionStatus.downloading
const assetBin = await getP<Buffer>('https://api.github.com/repos/rakusan2/Toastmasters-Timer-Overlay/releases/assets/' + assetID, true)
await writeFile(platformStr, assetBin)

} catch (err) {
console.warn(err)
versionStatus = VersionStatus.err
isCheckingVersion = false
return
}
isCheckingVersion = false
versionStatus = VersionStatus.newest
}

function initUser(id?: string | null) {
if (typeof oneID === 'string') {
id = oneID
Expand All @@ -133,3 +244,35 @@ function getID() {
users[id] = { settings: {}, lastMessageAt: Date.now() }
return id
}

function getP<T>(uri: string, bin: true): Promise<Buffer>
function getP<T>(uri: string, bin?: false): Promise<T | string>
function getP(uri: string, bin = false) {
return new Promise<any>((res, rej) => {
const req = get(uri, socket => {
const result: Buffer[] = []
let len = 0
socket.on('data', (data: Buffer) => {
result.push(data)
len += data.length
}).on('close', () => {
const status = socket.statusCode ?? 0
const binary = Buffer.concat(result, len)
const str = binary.toString('utf8')
if (status >= 200 || status < 300) {
if (bin) {
res(binary)
return
}
try {
const parsed = JSON.parse(str)
res(parsed)
} catch {
res(str)
}
} else rej(str)
})
})
req.on('error', rej)
})
}
82 changes: 82 additions & 0 deletions server/src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface IResponseInit extends ISettings {
id: string
idLock: boolean
serverTime: number
version: string
}
export interface ISettings {
settings: {
Expand Down Expand Up @@ -54,4 +55,85 @@ export interface IParamOptions {
keyword?: string
alias?: string | string[]
callback: IFun
}

export interface VersionCheckStatus {
status: string
version: string
}

interface GithubReleaseResponse {
url: string;
assets_url: string;
upload_url: string;
html_url: string;
id: number;
author: GithubAuthor;
node_id: string;
tag_name: string;
target_commitish: string;
name: string;
draft: boolean;
prerelease: boolean;
created_at: Date;
published_at: Date;
assets: GithubAsset[];
tarball_url: string;
zipball_url: string;
body: string;
}
interface GithubAsset {
url: string;
id: number;
node_id: string;
name: string;
label?: any;
uploader: GithubUploader;
content_type: string;
state: string;
size: number;
download_count: number;
created_at: Date;
updated_at: Date;
browser_download_url: string;
}
interface GithubUploader {
login: string;
id: number;
node_id: string;
avatar_url: string;
gravatar_id: string;
url: string;
html_url: string;
followers_url: string;
following_url: string;
gists_url: string;
starred_url: string;
subscriptions_url: string;
organizations_url: string;
repos_url: string;
events_url: string;
received_events_url: string;
type: string;
site_admin: boolean;
}
interface GithubAuthor {
login: string;
id: number;
node_id: string;
avatar_url: string;
gravatar_id: string;
url: string;
html_url: string;
followers_url: string;
following_url: string;
gists_url: string;
starred_url: string;
subscriptions_url: string;
organizations_url: string;
repos_url: string;
events_url: string;
received_events_url: string;
type: string;
site_admin: boolean;
}
6 changes: 3 additions & 3 deletions server/src/webServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { IServeHandler } from './serverTypes'

const { cache, port, sslConfig } = parameters

const dir = __dirname.split(/\\|\//).slice(0,-2)
const dir = __dirname.split(/\\|\//).slice(0, -2)
const webDir = dir.join('/') + "/web"
console.log('Web: ' + webDir)

Expand All @@ -19,7 +19,7 @@ const handlerConfig: IServeHandler = {
]
}

if (cache) {
if (cache != null) {
handlerConfig.headers = [
{
source: '*',
Expand Down Expand Up @@ -49,7 +49,7 @@ export default function startServer(afterStart?: (address: string) => any) {
}

server.listen(port, () => {
const address = `http://localhost:${port}`
const address = `${sslConfig != null ? 'https' : 'http'}://localhost:${port}`
console.log(`listening at ${address} with cache set to ${cache ?? 'DISABLED'}`)

if (afterStart != null) afterStart(address)
Expand Down
Loading

0 comments on commit 239f91e

Please sign in to comment.