Add config and improve stopping
This commit is contained in:
parent
57a5ee8164
commit
0d913d73d7
|
@ -10,7 +10,6 @@ __pycache__
|
||||||
/*.egg-info
|
/*.egg-info
|
||||||
/.eggs
|
/.eggs
|
||||||
|
|
||||||
node_modules
|
|
||||||
profiles
|
profiles
|
||||||
|
|
||||||
/config.yaml
|
/config.yaml
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
/node_modules
|
||||||
|
/config.json
|
|
@ -0,0 +1,7 @@
|
||||||
|
### Listen config
|
||||||
|
If `type` is `unix`, `path` is the path where to create the socket.
|
||||||
|
|
||||||
|
If `type` is `tcp`, `port` and `host` are the host/port where to listen.
|
||||||
|
|
||||||
|
### Profile directory
|
||||||
|
The `profile_dir` specifies which directory to put chromium user data directories.
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"listen": {
|
||||||
|
"type": "unix",
|
||||||
|
"path": "/var/run/mautrix-amp/puppet.sock"
|
||||||
|
},
|
||||||
|
"profile_dir": "./profiles"
|
||||||
|
}
|
|
@ -21,10 +21,10 @@ import Client from "./client.js"
|
||||||
import { promisify } from "./util.js"
|
import { promisify } from "./util.js"
|
||||||
|
|
||||||
export default class PuppetAPI {
|
export default class PuppetAPI {
|
||||||
path = "/var/run/mautrix-amp/puppet.sock"
|
constructor(listenConfig) {
|
||||||
|
this.listenConfig = listenConfig
|
||||||
constructor() {
|
|
||||||
this.server = net.createServer(this.acceptConnection)
|
this.server = net.createServer(this.acceptConnection)
|
||||||
|
this.connections = []
|
||||||
this.puppets = new Map()
|
this.puppets = new Map()
|
||||||
this.clients = new Map()
|
this.clients = new Map()
|
||||||
this.connIDSequence = 0
|
this.connIDSequence = 0
|
||||||
|
@ -38,25 +38,41 @@ export default class PuppetAPI {
|
||||||
acceptConnection = sock => {
|
acceptConnection = sock => {
|
||||||
if (this.stopped) {
|
if (this.stopped) {
|
||||||
sock.end()
|
sock.end()
|
||||||
|
sock.destroy()
|
||||||
} else {
|
} else {
|
||||||
new Client(this, sock, ++this.connIDSequence).start()
|
const connID = this.connIDSequence++
|
||||||
|
this.connections[connID] = sock
|
||||||
|
new Client(this, sock, connID).start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async startUnix(socketPath) {
|
||||||
|
try {
|
||||||
|
await fs.promises.access(path.dirname(socketPath))
|
||||||
|
} catch (err) {
|
||||||
|
await fs.promises.mkdir(path.dirname(socketPath), 0o700)
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await fs.promises.unlink(socketPath)
|
||||||
|
} catch (err) {}
|
||||||
|
await promisify(cb => this.server.listen(socketPath, cb))
|
||||||
|
await fs.promises.chmod(socketPath, 0o700)
|
||||||
|
this.log("Now listening at", socketPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
async startTCP(port, host) {
|
||||||
|
await promisify(cb => this.server.listen(port, host, cb))
|
||||||
|
this.log(`Now listening at ${host || ""}:${port}`)
|
||||||
|
}
|
||||||
|
|
||||||
async start() {
|
async start() {
|
||||||
this.log("Starting server")
|
this.log("Starting server")
|
||||||
|
|
||||||
try {
|
if (this.listenConfig.type === "unix") {
|
||||||
await fs.promises.access(path.dirname(this.path))
|
await this.startUnix(this.listenConfig.path)
|
||||||
} catch (err) {
|
} else if (this.listenConfig.type === "tcp") {
|
||||||
await fs.promises.mkdir(path.dirname(this.path), 0o700)
|
await this.startTCP(this.listenConfig.port, this.listenConfig.host)
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
await fs.promises.unlink(this.path)
|
|
||||||
} catch (err) {}
|
|
||||||
await promisify(cb => this.server.listen(this.path, cb))
|
|
||||||
await fs.promises.chmod(this.path, 0o700)
|
|
||||||
this.log("Now listening at", this.path)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async stop() {
|
async stop() {
|
||||||
|
@ -64,12 +80,18 @@ export default class PuppetAPI {
|
||||||
for (const client of this.clients.values()) {
|
for (const client of this.clients.values()) {
|
||||||
await client.stop("Server is shutting down")
|
await client.stop("Server is shutting down")
|
||||||
}
|
}
|
||||||
|
for (const socket of this.connections) {
|
||||||
|
socket.end()
|
||||||
|
socket.destroy()
|
||||||
|
}
|
||||||
this.log("Stopping server")
|
this.log("Stopping server")
|
||||||
await promisify(cb => this.server.close(cb))
|
await promisify(cb => this.server.close(cb))
|
||||||
try {
|
if (this.listenConfig.type === "unix") {
|
||||||
await fs.promises.unlink(this.path)
|
try {
|
||||||
} catch (err) {}
|
await fs.promises.unlink(this.listenConfig.path)
|
||||||
this.log("Server stopped")
|
} catch (err) {}
|
||||||
|
}
|
||||||
|
this.log("Stopping puppets")
|
||||||
for (const puppet of this.puppets.values()) {
|
for (const puppet of this.puppets.values()) {
|
||||||
await puppet.stop()
|
await puppet.stop()
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,7 +119,7 @@ export default class Client {
|
||||||
return { started: false, is_logged_in: await this.puppet.isLoggedIn() }
|
return { started: false, is_logged_in: await this.puppet.isLoggedIn() }
|
||||||
}
|
}
|
||||||
this.log("Opening new puppeteer for", this.userID)
|
this.log("Opening new puppeteer for", this.userID)
|
||||||
this.puppet = new MessagesPuppeteer(this.userID, `./profiles/${this.userID}`, this)
|
this.puppet = new MessagesPuppeteer(this.userID, this)
|
||||||
this.manager.puppets.set(this.userID, this.puppet)
|
this.manager.puppets.set(this.userID, this.puppet)
|
||||||
await this.puppet.start(!!req.debug)
|
await this.puppet.start(!!req.debug)
|
||||||
return { started: true, is_logged_in: await this.puppet.isLoggedIn() }
|
return { started: true, is_logged_in: await this.puppet.isLoggedIn() }
|
||||||
|
@ -196,6 +196,7 @@ export default class Client {
|
||||||
handler = {
|
handler = {
|
||||||
start: this.handleStart,
|
start: this.handleStart,
|
||||||
stop: this.handleStop,
|
stop: this.handleStop,
|
||||||
|
disconnect: () => this.stop(),
|
||||||
login: () => this.puppet.waitForLogin(),
|
login: () => this.puppet.waitForLogin(),
|
||||||
send: req => this.puppet.sendMessage(req.chat_id, req.text),
|
send: req => this.puppet.sendMessage(req.chat_id, req.text),
|
||||||
get_chats: () => this.puppet.getRecentChats(),
|
get_chats: () => this.puppet.getRecentChats(),
|
||||||
|
|
|
@ -14,10 +14,20 @@
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
import process from "process"
|
import process from "process"
|
||||||
|
import fs from "fs"
|
||||||
|
|
||||||
import PuppetAPI from "./api.js"
|
import PuppetAPI from "./api.js"
|
||||||
|
import MessagesPuppeteer from "./puppet.js"
|
||||||
|
|
||||||
const api = new PuppetAPI()
|
let path = process.argv[process.argv.length - 1]
|
||||||
|
if (!path.endsWith(".json")) {
|
||||||
|
path = "config.json"
|
||||||
|
}
|
||||||
|
console.log("Reading config from", path)
|
||||||
|
const config = JSON.parse(fs.readFileSync(path).toString())
|
||||||
|
MessagesPuppeteer.profileDir = config.profile_dir
|
||||||
|
|
||||||
|
const api = new PuppetAPI(config.listen)
|
||||||
|
|
||||||
function stop() {
|
function stop() {
|
||||||
api.stop().then(() => process.exit(0), err => {
|
api.stop().then(() => process.exit(0), err => {
|
||||||
|
|
|
@ -23,15 +23,16 @@ import TaskQueue from "./taskqueue.js"
|
||||||
import { sleep } from "./util.js"
|
import { sleep } from "./util.js"
|
||||||
|
|
||||||
export default class MessagesPuppeteer {
|
export default class MessagesPuppeteer {
|
||||||
|
static profileDir = "./profiles"
|
||||||
url = "https://messages.google.com/web/"
|
url = "https://messages.google.com/web/"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {string} id
|
* @param {string} id
|
||||||
* @param {string} profilePath
|
|
||||||
* @param {?Client} [client]
|
* @param {?Client} [client]
|
||||||
*/
|
*/
|
||||||
constructor(id, profilePath, client = null) {
|
constructor(id, client = null) {
|
||||||
|
let profilePath = path.join(MessagesPuppeteer.profileDir, id)
|
||||||
if (!profilePath.startsWith("/")) {
|
if (!profilePath.startsWith("/")) {
|
||||||
profilePath = path.join(process.cwd(), profilePath)
|
profilePath = path.join(process.cwd(), profilePath)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue