-
Notifications
You must be signed in to change notification settings - Fork 1
/
browser.js
137 lines (122 loc) · 4.91 KB
/
browser.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
(async () => {
require('dotenv').config()
const puppeteer = require("puppeteer-core").default
const fs = require("fs")
const express = require('express')
const { execSync } = require("node:child_process")
const { createClient } = require("redis");
const utils = require("./utils.js")
const client = await createClient({
url: `redis://:${process.env.REDIS_PASSWORD}@${process.env.REDIS_HOST || "127.0.0.1"}:${process.env.REDIS_PORT || 6379}`
})
.on('error', err => console.log('Redis Client Error', err))
.connect();
const app = express()
console.log("[browser] [Info] Launching Brower")
var bopts = {
args: [
'--use-fake-ui-for-media-stream',
'--use-fake-device-for-media-stream',
`--use-file-for-fake-audio-capture=${__dirname}/.stream.wav`,
'--allow-file-access',
],
headless: false,
executablePath: process.env.CHROME_EXECUTABLE_PATH || "/chrome/chrome",
ignoreDefaultArgs: ['--mute-audio'],
}
if (process.env.CHROME_ON_SERVER) {
console.log("Running on a server.")
bopts.args.push("'--no-sandbox")
bopts.args.push("--disable-setuid-sandbox")
bopts.headless = true
}
await client.set('queue', "[]");
if (await client.exists("currentChannel")) await client.del('currentChannel');
if (await client.exists("currentSong")) await client.del('currentSong');
await client.set('songEnd', 0);
global.clearId = 0
const browser = await puppeteer.launch(bopts);
if (fs.existsSync(`${__dirname}/.stream.wav`)) fs.rmSync(`${__dirname}/.stream.wav`)
console.log("[browser] [Info] Logging in.")
const page = await browser.newPage();
await page.goto(`https://${process.env.SLACK_ORG}.slack.com/sign_in_with_password`, { waitUntil: 'domcontentloaded' });
await page.type('#email', process.env.SLACK_EMAIL);
await page.type('#password', process.env.SLACK_PASSWORD);
await Promise.all([
page.waitForNavigation(),
page.click("#signin_btn"),
page.waitForNavigation(),
]);
const page2 = await browser.newPage()
await page.close()
async function quitNow() {
await client.del("currentChannel")
try {
clearTimeout(global.clearId)
} catch (e) { }
try {
await page2.waitForSelector("#huddle_mini_player_leave_button", { visible: true, timeout: 2000 })
} catch (e) { }
try {
await page2.click(`#huddle_mini_player_leave_button`)
} catch (e) { }
}
async function loadSong({ channel, title, author, url, user }, cb) {
const event = await utils.ongoingEvent()
const rightChannel = await utils.isCalendarChannel(channel)
if (event && !rightChannel) return cb({ success: false, error: "Another channel has already booked Orpheaux." })
if (!event && await client.exists("currentChannel") && await client.get("currentChannel") != channel) return cb({ success: false, error: "A channel is already using Orpheaux." })
if (!event) await client.set("currentChannel", channel)
if (page2.url() != `https://app.slack.com/client/${process.env.SLACK_ID}/${channel}`) await page2.goto(`https://app.slack.com/client/${process.env.SLACK_ID}/${channel}`)
await client.set("currentSong", JSON.stringify({
title, author, url, user
}))
try {
await page2.click(`#huddle_mini_player_leave_button`)
} catch (e) {
}
await page2.waitForSelector('[data-qa="huddle_channel_header_button__start_button"]', { visible: true })
console.log("[browser] [Info] Reloading song and joining huddle.")
await page2.click(`[data-qa="huddle_channel_header_button__start_button"]`)
cb({ success: true })
}
async function setQuit() {
try {
clearTimeout(global.clearId)
} catch (e) {
}
var id = setTimeout(async function () {
try {
await page2.waitForSelector("#huddle_mini_player_leave_button", { visible: true, timeout: 2000 })
} catch (e) { }
try {
await page2.click(`#huddle_mini_player_leave_button`)
} catch (e) { }
}, await client.get("songEnd"))
global.clearId = id
}
app.post('/stop', async (req, res) => {
await quitNow()
res.json({ success: true })
})
app.post('/play', async (req, res) => {
const { file, channel, title, author, url, user } = req.query
console.log(`[stream] [info] Playing ${file}`)
if (fs.existsSync(`${__dirname}/.stream.wav`)) fs.rmSync(`${__dirname}/.stream.wav`)
fs.copyFileSync(`${file}`, `${__dirname}/.stream.wav`)
await client.set("songEnd", parseInt(execSync(`mediainfo --Inform="Audio;%Duration%" .stream.wav`).toString().replaceAll("\n", "").trim()))
await loadSong({ channel, title, author, url, user }, function (json) {
res.json(json)
})
await setQuit()
})
app.listen(process.env.BROWSER_PORT, () => {
console.log(`Orpheaux-ng listening on port ${process.env.BROWSER_PORT}`)
})
process.on("SIGINT", async () => {
try {
await page2.click(`#huddle_mini_player_leave_button`)
} catch (e) { }
process.exit();
});
})();