mirror of
https://github.com/chatmail/core.git
synced 2026-04-05 23:22:11 +03:00
235 lines
5.9 KiB
TypeScript
235 lines
5.9 KiB
TypeScript
/* eslint-disable camelcase */
|
|
|
|
import binding from './binding'
|
|
import { EventId2EventName } from './constants'
|
|
import { EventEmitter } from 'events'
|
|
import { existsSync } from 'fs'
|
|
import rawDebug from 'debug'
|
|
import { tmpdir } from 'os'
|
|
import { join } from 'path'
|
|
import { Context } from './context'
|
|
const debug = rawDebug('deltachat:node:index')
|
|
|
|
const noop = function () {}
|
|
interface NativeAccount {}
|
|
|
|
/**
|
|
* Wrapper around dcn_account_t*
|
|
*/
|
|
export class AccountManager extends EventEmitter {
|
|
dcn_accounts: NativeAccount
|
|
accountDir: string
|
|
jsonRpcStarted = false
|
|
|
|
constructor(cwd: string, writable = true) {
|
|
super()
|
|
debug('DeltaChat constructor')
|
|
|
|
this.accountDir = cwd
|
|
this.dcn_accounts = binding.dcn_accounts_new(
|
|
this.accountDir,
|
|
writable ? 1 : 0
|
|
)
|
|
}
|
|
|
|
getAllAccountIds() {
|
|
return binding.dcn_accounts_get_all(this.dcn_accounts)
|
|
}
|
|
|
|
selectAccount(account_id: number) {
|
|
return binding.dcn_accounts_select_account(this.dcn_accounts, account_id)
|
|
}
|
|
|
|
selectedAccount(): number {
|
|
return binding.dcn_accounts_get_selected_account(this.dcn_accounts)
|
|
}
|
|
|
|
addAccount(): number {
|
|
return binding.dcn_accounts_add_account(this.dcn_accounts)
|
|
}
|
|
|
|
addClosedAccount(): number {
|
|
return binding.dcn_accounts_add_closed_account(this.dcn_accounts)
|
|
}
|
|
|
|
removeAccount(account_id: number) {
|
|
return binding.dcn_accounts_remove_account(this.dcn_accounts, account_id)
|
|
}
|
|
|
|
accountContext(account_id: number) {
|
|
const native_context = binding.dcn_accounts_get_account(
|
|
this.dcn_accounts,
|
|
account_id
|
|
)
|
|
if (native_context === null) {
|
|
throw new Error(
|
|
`could not get context with id ${account_id}, does it even exist? please check your ids`
|
|
)
|
|
}
|
|
return new Context(this, native_context, account_id)
|
|
}
|
|
|
|
migrateAccount(dbfile: string): number {
|
|
return binding.dcn_accounts_migrate_account(this.dcn_accounts, dbfile)
|
|
}
|
|
|
|
close() {
|
|
this.stopIO()
|
|
debug('unrefing context')
|
|
binding.dcn_accounts_unref(this.dcn_accounts)
|
|
debug('Unref end')
|
|
}
|
|
|
|
emit(
|
|
event: string | symbol,
|
|
account_id: number,
|
|
data1: any,
|
|
data2: any
|
|
): boolean {
|
|
super.emit('ALL', event, account_id, data1, data2)
|
|
return super.emit(event, account_id, data1, data2)
|
|
}
|
|
|
|
handleCoreEvent(
|
|
eventId: number,
|
|
accountId: number,
|
|
data1: number,
|
|
data2: number | string
|
|
) {
|
|
const eventString = EventId2EventName[eventId]
|
|
debug('event', eventString, accountId, data1, data2)
|
|
debug(eventString, data1, data2)
|
|
if (!this.emit) {
|
|
console.log('Received an event but EventEmitter is already destroyed.')
|
|
console.log(eventString, data1, data2)
|
|
return
|
|
}
|
|
this.emit(eventString, accountId, data1, data2)
|
|
}
|
|
|
|
startEvents() {
|
|
if (this.dcn_accounts === null) {
|
|
throw new Error('dcn_account is null')
|
|
}
|
|
binding.dcn_accounts_start_event_handler(
|
|
this.dcn_accounts,
|
|
this.handleCoreEvent.bind(this)
|
|
)
|
|
debug('Started event handler')
|
|
}
|
|
|
|
startJsonRpcHandler(callback: ((response: string) => void) | null) {
|
|
if (this.dcn_accounts === null) {
|
|
throw new Error('dcn_account is null')
|
|
}
|
|
if (!callback) {
|
|
throw new Error('no callback set')
|
|
}
|
|
if (this.jsonRpcStarted) {
|
|
throw new Error('jsonrpc was started already')
|
|
}
|
|
|
|
binding.dcn_accounts_start_jsonrpc(this.dcn_accounts, callback.bind(this))
|
|
debug('Started JSON-RPC handler')
|
|
this.jsonRpcStarted = true
|
|
}
|
|
|
|
jsonRpcRequest(message: string) {
|
|
if (!this.jsonRpcStarted) {
|
|
throw new Error(
|
|
'jsonrpc is not active, start it with startJsonRpcHandler first'
|
|
)
|
|
}
|
|
binding.dcn_json_rpc_request(this.dcn_accounts, message)
|
|
}
|
|
|
|
startIO() {
|
|
binding.dcn_accounts_start_io(this.dcn_accounts)
|
|
}
|
|
|
|
stopIO() {
|
|
binding.dcn_accounts_stop_io(this.dcn_accounts)
|
|
}
|
|
|
|
static maybeValidAddr(addr: string) {
|
|
debug('DeltaChat.maybeValidAddr')
|
|
if (addr === null) return false
|
|
return Boolean(binding.dcn_maybe_valid_addr(addr))
|
|
}
|
|
|
|
static parseGetInfo(info: string) {
|
|
debug('static _getInfo')
|
|
const result: { [key: string]: string } = {}
|
|
|
|
const regex = /^(\w+)=(.*)$/i
|
|
info
|
|
.split('\n')
|
|
.filter(Boolean)
|
|
.forEach((line) => {
|
|
const match = regex.exec(line)
|
|
if (match) {
|
|
result[match[1]] = match[2]
|
|
}
|
|
})
|
|
|
|
return result
|
|
}
|
|
|
|
static newTemporary() {
|
|
let directory = null
|
|
while (true) {
|
|
const randomString = Math.random().toString(36).substring(2, 5)
|
|
directory = join(tmpdir(), 'deltachat-' + randomString)
|
|
if (!existsSync(directory)) break
|
|
}
|
|
const dc = new AccountManager(directory)
|
|
const accountId = dc.addAccount()
|
|
const context = dc.accountContext(accountId)
|
|
return { dc, context, accountId, directory }
|
|
}
|
|
|
|
static getSystemInfo() {
|
|
debug('DeltaChat.getSystemInfo')
|
|
const { dc, context } = AccountManager.newTemporary()
|
|
const info = AccountManager.parseGetInfo(
|
|
binding.dcn_get_info(context.dcn_context)
|
|
)
|
|
const {
|
|
deltachat_core_version,
|
|
sqlite_version,
|
|
sqlite_thread_safe,
|
|
libetpan_version,
|
|
openssl_version,
|
|
compile_date,
|
|
arch,
|
|
} = info
|
|
const result = {
|
|
deltachat_core_version,
|
|
sqlite_version,
|
|
sqlite_thread_safe,
|
|
libetpan_version,
|
|
openssl_version,
|
|
compile_date,
|
|
arch,
|
|
}
|
|
context.unref()
|
|
dc.close()
|
|
return result
|
|
}
|
|
|
|
/** get information about the provider
|
|
*
|
|
* This function creates a temporary context to be standalone,
|
|
* if possible use `Context.getProviderFromEmail` instead. (otherwise potential proxy settings are not used)
|
|
* @deprecated
|
|
*/
|
|
static getProviderFromEmail(email: string) {
|
|
debug('DeltaChat.getProviderFromEmail')
|
|
const { dc, context } = AccountManager.newTemporary()
|
|
const provider = context.getProviderFromEmail(email)
|
|
context.unref()
|
|
dc.close()
|
|
return provider
|
|
}
|
|
}
|