Telegram Web K with changes to work inside I2P
https://web.telegram.i2p/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
262 lines
8.7 KiB
262 lines
8.7 KiB
/* |
|
* https://github.com/morethanwords/tweb |
|
* Copyright (C) 2019-2021 Eduard Kuzmenko |
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE |
|
* |
|
* Originally from: |
|
* https://github.com/zhukov/webogram |
|
* Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com> |
|
* https://github.com/zhukov/webogram/blob/master/LICENSE |
|
*/ |
|
|
|
import tsNow from '../../helpers/tsNow'; |
|
import {InputNotifyPeer, InputPeerNotifySettings, NotifyPeer, PeerNotifySettings, Update} from '../../layer'; |
|
import {MUTE_UNTIL} from '../mtproto/mtproto_config'; |
|
import throttle from '../../helpers/schedulers/throttle'; |
|
import convertInputKeyToKey from '../../helpers/string/convertInputKeyToKey'; |
|
import {AppManager} from './manager'; |
|
import ctx from '../../environment/ctx'; |
|
import assumeType from '../../helpers/assumeType'; |
|
|
|
type ImSadAboutIt = Promise<PeerNotifySettings> | PeerNotifySettings; |
|
export class AppNotificationsManager extends AppManager { |
|
private peerSettings = { |
|
notifyPeer: {} as {[peerId: PeerId]: ImSadAboutIt}, |
|
notifyUsers: null as ImSadAboutIt, |
|
notifyChats: null as ImSadAboutIt, |
|
notifyBroadcasts: null as ImSadAboutIt |
|
}; |
|
// private exceptions: {[peerId: string]: PeerNotifySettings} = {}; |
|
|
|
private getNotifyPeerTypePromise: Promise<any>; |
|
|
|
private checkMuteUntilTimeout: number; |
|
private checkMuteUntilThrottled: () => void; |
|
|
|
private notifyContactsSignUp: Promise<boolean>; |
|
|
|
protected after() { |
|
this.checkMuteUntilThrottled = throttle(this.checkMuteUntil, 1000, false); |
|
|
|
this.apiUpdatesManager.addMultipleEventsListeners({ |
|
updateNotifySettings: (update) => { |
|
const peerId = update.peer._ === 'notifyPeer' && this.appPeersManager.getPeerId(update.peer.peer); |
|
const key = update.peer._ !== 'notifyPeer' ? update.peer._ : undefined; |
|
this.savePeerSettings({ |
|
key, |
|
peerId, |
|
settings: update.notify_settings |
|
}); |
|
this.rootScope.dispatchEvent('notify_settings', update); |
|
} |
|
}); |
|
|
|
return this.appStateManager.getState().then((state) => { |
|
if(state.notifySettings) { |
|
for(const key in state.notifySettings) { |
|
assumeType<Exclude<NotifyPeer['_'], 'notifyPeer'>>(key); |
|
this.savePeerSettings({ |
|
key, |
|
settings: state.notifySettings[key] |
|
}); |
|
} |
|
} |
|
}); |
|
} |
|
|
|
public getNotifySettings(peer: InputNotifyPeer): ImSadAboutIt { |
|
let key: any = convertInputKeyToKey(peer._); |
|
let obj: any = this.peerSettings[key as NotifyPeer['_']]; |
|
|
|
let peerId: PeerId; |
|
if(peer._ === 'inputNotifyPeer') { |
|
peerId = key = this.appPeersManager.getPeerId(peer.peer); |
|
obj = obj[key]; |
|
} |
|
|
|
if(obj) { |
|
return obj; |
|
} |
|
|
|
return (obj || this.peerSettings)[key] = this.apiManager.invokeApi('account.getNotifySettings', {peer}) |
|
.then((settings) => { |
|
this.savePeerSettings({ |
|
key, |
|
peerId, |
|
settings |
|
}); |
|
|
|
return settings; |
|
}); |
|
} |
|
|
|
public getNotifyPeerTypeSettings() { |
|
if(this.getNotifyPeerTypePromise) return this.getNotifyPeerTypePromise; |
|
|
|
const promises = (['inputNotifyBroadcasts', 'inputNotifyUsers', 'inputNotifyChats'] as Exclude<InputNotifyPeer['_'], 'inputNotifyPeer'>[]) |
|
.map((inputKey) => { |
|
return this.getNotifySettings({_: inputKey}); |
|
}); |
|
|
|
return this.getNotifyPeerTypePromise = Promise.all(promises); |
|
} |
|
|
|
public updateNotifySettings(peer: InputNotifyPeer, settings: InputPeerNotifySettings) { |
|
// this.savePeerSettings(peerId, settings); |
|
|
|
/* const inputSettings: InputPeerNotifySettings = copy(settings) as any; |
|
inputSettings._ = 'inputPeerNotifySettings'; */ |
|
|
|
return this.apiManager.invokeApi('account.updateNotifySettings', { |
|
peer, |
|
settings |
|
}).then((value) => { |
|
if(value) { |
|
this.apiUpdatesManager.processLocalUpdate({ |
|
_: 'updateNotifySettings', |
|
peer: { |
|
...peer as any, |
|
_: convertInputKeyToKey(peer._) |
|
}, |
|
notify_settings: { // ! WOW, IT WORKS ! |
|
...settings, |
|
_: 'peerNotifySettings' |
|
} |
|
}); |
|
} |
|
}); |
|
} |
|
|
|
// public getNotifyExceptions() { |
|
// apiManager.invokeApi('account.getNotifyExceptions', {compare_sound: true}) |
|
// .then((updates) => { |
|
// apiUpdatesManager.processUpdateMessage(updates); |
|
// }); |
|
// } |
|
|
|
public getContactSignUpNotification() { |
|
if(this.notifyContactsSignUp) return this.notifyContactsSignUp; |
|
return this.notifyContactsSignUp = this.apiManager.invokeApi('account.getContactSignUpNotification'); |
|
} |
|
|
|
public setContactSignUpNotification(silent: boolean) { |
|
this.apiManager.invokeApi('account.setContactSignUpNotification', {silent}) |
|
.then((value) => { |
|
this.notifyContactsSignUp = Promise.resolve(!silent); |
|
}); |
|
} |
|
|
|
private checkMuteUntil = () => { |
|
if(this.checkMuteUntilTimeout !== undefined) { |
|
clearTimeout(this.checkMuteUntilTimeout); |
|
this.checkMuteUntilTimeout = undefined; |
|
} |
|
|
|
const timestamp = tsNow(true); |
|
let closestMuteUntil = MUTE_UNTIL; |
|
for(const peerId in this.peerSettings.notifyPeer) { |
|
const peerNotifySettings = this.peerSettings.notifyPeer[peerId]; |
|
if(peerNotifySettings instanceof Promise) { |
|
continue; |
|
} |
|
|
|
const muteUntil = peerNotifySettings.mute_until; |
|
if(!muteUntil) { |
|
continue; |
|
} |
|
|
|
if(muteUntil <= timestamp) { |
|
// ! do not delete it because peer's unique settings will be overwritten in getPeerLocalSettings with type's settings |
|
peerNotifySettings.mute_until = 0; |
|
|
|
this.apiUpdatesManager.saveUpdate({ |
|
_: 'updateNotifySettings', |
|
peer: { |
|
_: 'notifyPeer', |
|
peer: this.appPeersManager.getOutputPeer(peerId.toPeerId()) |
|
}, |
|
notify_settings: peerNotifySettings |
|
}); |
|
} else if(muteUntil < closestMuteUntil) { |
|
closestMuteUntil = muteUntil; |
|
} |
|
} |
|
|
|
const timeout = Math.min(1800e3, (closestMuteUntil - timestamp) * 1000); |
|
this.checkMuteUntilTimeout = ctx.setTimeout(this.checkMuteUntil, timeout); |
|
}; |
|
|
|
public savePeerSettings({key, peerId, settings}: { |
|
key?: Exclude<NotifyPeer['_'], 'notifyPeer'>, |
|
peerId?: PeerId, |
|
settings: PeerNotifySettings |
|
}) { |
|
let obj: any; |
|
if(peerId) { |
|
key = peerId as any; |
|
obj = this.peerSettings['notifyPeer']; |
|
} |
|
|
|
(obj || this.peerSettings)[key] = settings; |
|
|
|
if(!peerId) { |
|
this.rootScope.dispatchEvent('notify_peer_type_settings', {key, settings}); |
|
this.appStateManager.getState().then((state) => { |
|
const notifySettings = state.notifySettings; |
|
notifySettings[key] = settings; |
|
this.appStateManager.pushToState('notifySettings', notifySettings); |
|
}); |
|
} else { |
|
this.checkMuteUntilThrottled(); |
|
} |
|
|
|
// rootScope.broadcast('notify_settings', {peerId: peerId}); |
|
} |
|
|
|
public isMuted(peerNotifySettings: PeerNotifySettings) { |
|
return peerNotifySettings._ === 'peerNotifySettings' && |
|
(peerNotifySettings.silent || (peerNotifySettings.mute_until !== undefined && (peerNotifySettings.mute_until * 1000) > tsNow())); |
|
} |
|
|
|
private getPeerMuted(peerId: PeerId) { |
|
const ret = this.getNotifySettings({_: 'inputNotifyPeer', peer: this.appPeersManager.getInputPeerById(peerId)}); |
|
return (ret instanceof Promise ? ret : Promise.resolve(ret)) |
|
.then((peerNotifySettings) => this.isMuted(peerNotifySettings)); |
|
} |
|
|
|
private getPeerLocalSettings(peerId: PeerId, respectType = true): PeerNotifySettings { |
|
const n: PeerNotifySettings = { |
|
_: 'peerNotifySettings' |
|
}; |
|
|
|
const notifySettings = this.peerSettings['notifyPeer'][peerId]; |
|
// if(!notifySettings || (notifySettings instanceof Promise)) return false; |
|
if(notifySettings && !(notifySettings instanceof Promise)) { |
|
Object.assign(n, notifySettings); |
|
} |
|
|
|
if(respectType) { |
|
const inputNotify = this.appPeersManager.getInputNotifyPeerById(peerId, true); |
|
const key = convertInputKeyToKey(inputNotify._); |
|
const typeNotifySettings = this.peerSettings[key as NotifyPeer['_']]; |
|
if(typeNotifySettings && !(typeNotifySettings instanceof Promise)) { |
|
for(const i in typeNotifySettings) { |
|
// @ts-ignore |
|
if(n[i] === undefined) { |
|
// @ts-ignore |
|
n[i] = typeNotifySettings[i]; |
|
} |
|
} |
|
} |
|
} |
|
|
|
return n; |
|
} |
|
|
|
public isPeerLocalMuted(peerId: PeerId, respectType = true) { |
|
if(peerId === this.appPeersManager.peerId) return false; |
|
|
|
const notifySettings = this.getPeerLocalSettings(peerId, respectType); |
|
return this.isMuted(notifySettings); |
|
} |
|
}
|
|
|