| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- import {Interfaces} from "./Interfaces";
- import ConversationStateInterface = Interfaces.ConversationState;
- export module Conversations {
- import ClientInterface = Interfaces.ClientInterface;
- import ConversationInterface = Interfaces.ConversationInterface;
- export class NullManager implements Interfaces.ConversationsManagerInterface {
- get(id: string): Promise<Interfaces.ConversationInterface> {
- return undefined;
- }
- add(conversation: Interfaces.ConversationInterface) {
- }
- remove(id: string) {
- }
- create(initiator: Interfaces.ClientInterface, recipient: Interfaces.ClientInterface): Promise<Interfaces.ConversationInterface> {
- return undefined;
- }
- }
- export class DefaultManager implements Interfaces.ConversationsManagerInterface {
- private apiConnector: Interfaces.ApiConnectorInterface;
- private logger: Interfaces.LoggerInterface;
- private clientsManager: Interfaces.ClientsManagerInterface;
- private conversations: { [id: string]: Interfaces.ConversationInterface } = {};
- constructor(apiConnector: Interfaces.ApiConnectorInterface, clientsManager: Interfaces.ClientsManagerInterface, logger: Interfaces.LoggerInterface) {
- this.apiConnector = apiConnector;
- this.clientsManager = clientsManager;
- this.logger = logger;
- }
- get(id: string): Promise<ConversationInterface> {
- this.logger.debug(`Get conversation with ID=${id}`);
- return new Promise((resolve, reject) => {
- if (this.conversations.hasOwnProperty(id)) {
- this.logger.debug(`Conversation with ID=${id} is already in list`);
- resolve(this.conversations[id]);
- } else {
- this.logger.debug(`Load conversation with ID=${id} by API call`);
- this.apiConnector.execute('/conversations', {action: 'get', id: id})
- .then((response: string) => {
- let data = JSON.parse(response);
- Promise.all([this.clientsManager.get(data.initiatorId), this.clientsManager.get(data.recipientId)])
- .then((values: [ClientInterface, ClientInterface]) => {
- let initiator = values[0];
- let recipient = values[1];
- let conversation = new Conversation(this.apiConnector, initiator, recipient, this.logger, data.id);
- conversation.duration = parseInt(data.duration);
- if (data.isStarted == 1 && data.isFinished == 0) {
- conversation.state = Interfaces.ConversationState.RUNNING();
- }
- this.add(conversation);
- resolve(this.conversations[id]);
- }).catch(reject);
- }).catch(reject);
- }
- });
- }
- create(initiator: Interfaces.ClientInterface, recipient: Interfaces.ClientInterface): Promise<Interfaces.ConversationInterface> {
- this.logger.debug(`Create new conversation`);
- return new Promise((resolve, reject) => {
- return this.apiConnector.execute('/conversations', {action: 'create'})
- .then(response => {
- let data = JSON.parse(response);
- return this.apiConnector.execute('/conversations', {
- action: 'init',
- id: data.id,
- peers: [initiator.id, recipient.id]
- });
- })
- .then(response => {
- let data = JSON.parse(response);
- let conversation = new Conversation(this.apiConnector, initiator, recipient, this.logger, data.id);
- this.add(conversation);
- resolve(conversation);
- })
- .catch(reject);
- });
- }
- add(conversation: Interfaces.ConversationInterface) {
- this.logger.debug(`Add conversation with ID=${conversation.id}`);
- this.conversations[conversation.id] = conversation;
- }
- remove(id: string) {
- this.logger.debug(`Delete conversation with ID=${id}`);
- delete this.conversations[id];
- }
- }
- export class Conversation implements Interfaces.ConversationInterface {
- private interval = null;
- private syncInterval = null;
- private _id: string;
- duration: number = 0;
- private conversationState: (value?: Interfaces.ConversationState) => ConversationStateInterface;
- private apiConnector: Interfaces.ApiConnectorInterface;
- private initiator: Interfaces.ClientInterface;
- private recipient: Interfaces.ClientInterface;
- private logger: Interfaces.LoggerInterface;
- constructor(apiConnector: Interfaces.ApiConnectorInterface, initiator: Interfaces.ClientInterface, recipient: Interfaces.ClientInterface, logger: Interfaces.LoggerInterface, id: string) {
- this.apiConnector = apiConnector;
- this.initiator = initiator;
- this.recipient = recipient;
- this.logger = logger;
- this._id = id;
- let state = Interfaces.ConversationState.INIT();
- this.conversationState = (value?: ConversationStateInterface) => {
- if (value !== undefined)
- state = value;
- return state;
- };
- this.state = ConversationStateInterface.INIT();
- }
- getInitiator(): Interfaces.ClientInterface {
- return this.initiator;
- }
- getRecipient(): Interfaces.ClientInterface {
- return this.recipient;
- }
- get id(): string {
- return this._id;
- }
- get state() {
- return this.conversationState();
- }
- set state(state: Interfaces.ConversationState) {
- if (!this.state.isEqualsTo(state)) {
- if (state.isEqualsTo(ConversationStateInterface.INIT())) {
- }
- if (state.isEqualsTo(ConversationStateInterface.RUNNING())) {
- this.setRunning();
- }
- if (state.isEqualsTo(ConversationStateInterface.PAUSED())) {
- this.setPaused();
- }
- if (state.isEqualsTo(ConversationStateInterface.STOPPED())) {
- this.setStopped();
- }
- this.conversationState(state);
- } else {
- this.logger.debug(`Conversation state already set to "${state.toString()}"`);
- }
- }
- private setRunning() {
- this.logger.debug(`Set conversation with ID=${this.id} running`);
- if (this.interval === null) {
- let lastIntervalTick = Date.now();
- this.interval = setInterval(() => {
- let now = Date.now();
- let interval = (now - lastIntervalTick) / 1000;
- this.duration += interval;
- lastIntervalTick = now;
- this.initiator.payedTime -= Math.round(interval * this.recipient.coefficient);
- this.recipient.payedTime += Math.round(interval * this.recipient.coefficient);
- if (this.initiator.payedTime < 0) {
- this.logger.debug(`User with ID=${this.initiator.id} is ran out of money`);
- this.state = ConversationStateInterface.STOPPED();
- }
- }, 1000);
- }
- if (this.syncInterval === null) {
- this.syncInterval = setInterval(() => {
- this.sync();
- }, 5000);
- }
- this.apiConnector.execute('/conversations', {id: this.id, action: 'start'});
- }
- private sync() {
- this.initiator.send('chat-sync-timer', {
- conversationId: this.id,
- duration: Math.round(this.duration)
- });
- this.recipient.send('chat-sync-timer', {
- conversationId: this.id,
- duration: Math.round(this.duration)
- });
- this.apiConnector.execute('/conversations', {
- id: this.id,
- action: 'duration',
- duration: Math.round(this.duration)
- });
- this.apiConnector.execute('/user', {
- action: 'updatetime',
- id: this.initiator.id,
- value: Math.round(this.initiator.payedTime)
- });
- this.apiConnector.execute('/user', {
- action: 'updatetime',
- id: this.recipient.id,
- value: Math.round(this.recipient.payedTime)
- });
- }
- private setPaused() {
- this.logger.debug(`Set conversation with ID=${this.id} paused`);
- clearInterval(this.interval);
- this.interval = null;
- clearInterval(this.syncInterval);
- this.syncInterval = null;
- this.initiator.send('chat-conversation-pause', {id: this.id});
- this.recipient.send('chat-conversation-pause', {id: this.id});
- }
- private setStopped() {
- this.logger.debug(`Set conversation with ID=${this.id} stopped`);
- clearInterval(this.interval);
- this.interval = null;
- clearInterval(this.syncInterval);
- this.syncInterval = null;
- delete this.initiator.conversations[this.id];
- delete this.recipient.conversations[this.id];
- this.apiConnector.execute('/conversations', {id: this.id, action: 'stop', duration: Math.round(this.duration)});
- this.apiConnector.execute('/user', {
- action: 'updatetime',
- id: this.initiator.id,
- value: this.initiator.payedTime
- });
- this.apiConnector.execute('/user', {
- action: 'updatetime',
- id: this.recipient.id,
- value: this.recipient.payedTime
- });
- this.initiator.send('chat-conversation-stop', {id: this.id});
- this.recipient.send('chat-conversation-stop', {id: this.id});
- }
- private getPeer(id): Interfaces.ClientInterface {
- let peers = [this.initiator, this.recipient];
- for (let i in peers) {
- if (peers.hasOwnProperty(i) && parseInt(peers[i].id) === parseInt(id)) {
- return peers[i];
- }
- }
- }
- newMessage(message, from, to) {
- this.logger.debug(`New message to conversation with ID=${this.id}`);
- if (this.state.isEqualsTo(Interfaces.ConversationState.RUNNING())) {
- this.apiConnector.execute('/messages', {
- action: 'send',
- conversationId: this.id,
- senderId: from,
- recipientId: to,
- text: message
- }).then(response => {
- let data = JSON.parse(response);
- if (data.isSent) {
- let sender = this.getPeer(data.senderId);
- let recipient = this.getPeer(data.recipientId);
- let messageData = {
- message: data.text,
- conversationId: this.id,
- sender: {
- name: sender.name,
- photo: sender.photo
- },
- recipient: {
- name: recipient.name,
- photo: recipient.photo
- }
- };
- this.initiator.sendMessage(messageData);
- this.recipient.sendMessage(messageData);
- }
- }).catch(this.logger.error);
- }
- }
- }
- }
|