alexlcdee před 8 roky
rodič
revize
72128d3201
4 změnil soubory, kde provedl 275 přidání a 182 odebrání
  1. 66 163
      src/App.ts
  2. 35 18
      src/Client.ts
  3. 173 0
      src/Conversation.ts
  4. 1 1
      src/tsconfig.json

+ 66 - 163
src/App.ts

@@ -1,9 +1,7 @@
-/**
- * Created by lcdee on 19.04.2017.
- */
 
 import {Client} from "./Client";
 import * as SocketIO from "socket.io";
+import {Conversation} from "./Conversation";
 
 export class App {
     private clients: ClientsContainer = new ClientsContainer(this);
@@ -27,26 +25,24 @@ export class App {
         console.log(`Server started at ${config.host}:${config.port}`);
     }
 
-    getClient(id: string): Client {
-        try {
-            return this.clients.get(id);
-        } catch (e) {
-            console.log(e.message);
-        }
+    getClient(id: string): Promise<Client> {
+        return new Promise((resolve, reject) => {
+            if (this.clients.get(id) !== undefined) {
+                resolve(this.clients.get(id));
+            } else {
+                this.apiCall('/user', {id: id, action: 'getinfo'}).then((response: string) => {
+                    let data = JSON.parse(response);
+                    this.clients[data.id] = new Client(this, data);
+                    resolve(this.clients.get(id));
+                }).catch(reject)
+            }
+        });
     }
 
     addClient(socket: SocketIO.Socket, data: {} = {}) {
         this.clients.add(socket, data);
     }
 
-    removeClient(id: string) {
-        try {
-            this.clients.remove(id);
-        } catch (e) {
-            console.log(e.message);
-        }
-    }
-
     addConversation(conversation: Conversation) {
         this.conversations[conversation.id] = conversation;
     }
@@ -55,26 +51,54 @@ export class App {
         delete this.conversations[id];
     }
 
-    apiCall(path: string, data: any, success: (data?: string) => void = () => {
-    }, fail: (err?: string) => void = () => {
-    }) {
-        let client = require('http').request({
-            host: 'galapsy.ru',
-            port: 80,
-            path: '/api' + path,
-            method: 'POST'
-        }, (response) => {
-            let responseMessage = '';
-            response.on('data', (chunk) => {
-                responseMessage += chunk;
-            }).on('end', () => {
-                success(responseMessage);
-            }).on('error', (err) => {
-                fail(err);
+    getConversation(id: number): Promise<Conversation> {
+        return new Promise((resolve, reject) => {
+            if (this.conversations.hasOwnProperty(id)) {
+                resolve(this.conversations[id]);
+            } else {
+                this.apiCall('/conversations', {action: 'get', id: id}).then((response: string) => {
+                    let data = JSON.parse(response);
+                    let conversation = new Conversation(this);
+                    conversation.duration = parseInt(data.duration);
+                    conversation.id = data.id;
+                    this.getClient(data.initiatorId).then(client => {
+                        conversation.initiator = client;
+                        this.getClient(data.recipientId).then(client => {
+                            conversation.recipient = client;
+                            if (data.isStarted == 1 && data.isFinished == 0) {
+                                conversation.state = Conversation.STATE_RUNNING;
+                            }
+                            this.conversations[id] = conversation;
+                            resolve(this.conversations[id]);
+                        });
+                    });
+                }).catch(err => {
+                    reject(err);
+                });
+            }
+        });
+    }
+
+    apiCall(path: string, data: any): Promise<string> {
+        return new Promise((resolve, reject) => {
+            let client = require('http').request({
+                host: 'galapsy.ru',
+                port: 80,
+                path: '/api' + path,
+                method: 'POST'
+            }, response => {
+                let responseMessage = '';
+                response.on('data', (chunk) => {
+                    responseMessage += chunk;
+                }).on('end', () => {
+                    resolve(responseMessage);
+                }).on('error', (err) => {
+                    reject(err);
+                });
             });
+            client.write(JSON.stringify(data));
+            client.end();
         });
-        client.write(JSON.stringify(data));
-        client.end();
     }
 }
 
@@ -98,12 +122,13 @@ class ClientsContainer {
 
     add(socket: SocketIO.Socket, data) {
         if (!this.clients.hasOwnProperty(data.id)) {
-            this.app.apiCall('/user', {id: data.id, action: 'getinfo'}, response => {
-                let data = JSON.parse(response);
-                this.clients[data.id] = new Client(this.app, data);
-                this.clients[data.id].addSocket(socket);
-                this.app.apiCall('/user', {id: data.id, action: 'setstatus', value: true});
-            });
+            this.app.apiCall('/user', {id: data.id, action: 'getinfo'})
+                .then((response: string) => {
+                    let data = JSON.parse(response);
+                    this.clients[data.id] = new Client(this.app, data);
+                    this.clients[data.id].addSocket(socket);
+                    this.app.apiCall('/user', {id: data.id, action: 'setstatus', value: true});
+                });
         } else {
             this.clients[data.id].addSocket(socket);
         }
@@ -113,132 +138,10 @@ class ClientsContainer {
         if (this.clients !== undefined && this.clients[id] !== undefined) {
             return this.clients[id];
         }
-        throw new Error(`Client ${id} not found`);
-    }
-
-    remove(id: string) {
-        if (this.clients !== undefined && this.clients[id] !== undefined) {
-            delete this.clients[id];
-        } else {
-            throw new Error(`Client ${id} not found`);
-        }
     }
 
 }
 
-export class Conversation {
-    private app: App;
-    private interval;
-    private syncInterval;
-
-    id: string;
-    initiator: Client;
-    recipient: Client;
-
-    duration: number = 0;
-
-    conversationState: (value?: number) => number;
-
-    static readonly STATE_INIT = 0;
-    static readonly STATE_RUNNING = 1;
-    static readonly STATE_STOPPED = 2;
-    static readonly STATE_PAUSED = 3;
-
-    constructor(app: App) {
-        let state;
-        this.app = app;
-        this.conversationState = (value?: number) => {
-            if (value !== undefined)
-                state = value;
-            return state;
-        };
-    }
-
-    init(success: (response) => void, fail: (err) => void) {
-        this.app.apiCall('/conversations', {'action': 'create'}, success, fail);
-    }
-
-    set state(value: number) {
-        if ([Conversation.STATE_INIT, Conversation.STATE_RUNNING, Conversation.STATE_PAUSED, Conversation.STATE_STOPPED].indexOf(value) === -1) {
-            throw new Error(`State ${value} not in list of possible values.`);
-        }
-        this.conversationState(value);
-        if (value === Conversation.STATE_INIT) {
-            this.app.conversations[this.id] = this;
-            this.initiator.conversations[this.id] = this;
-            this.recipient.conversations[this.id] = this;
-        }
-        if (value === Conversation.STATE_RUNNING) {
-            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.ceil(interval * this.recipient.coeficient);
-                this.recipient.payedTime += Math.ceil(interval * this.recipient.coeficient);
-                if (this.initiator.payedTime < 0) {
-                    this.state = Conversation.STATE_STOPPED;
-                }
-            }, 1000);
-            this.syncInterval = setInterval(() => {
-                this.initiator.send('chat-sync-timer', {
-                    conversationId: this.id,
-                    duration: this.duration
-                });
-                this.recipient.send('chat-sync-timer', {
-                    conversationId: this.id,
-                    duration: this.duration
-                });
-                this.app.apiCall('/conversations', {
-                    id: this.id,
-                    action: 'duration',
-                    duration: this.duration
-                });
-                this.app.apiCall('/user', {
-                    action: 'updatetime',
-                    id: this.initiator.id,
-                    value: this.initiator.payedTime
-                });
-                this.app.apiCall('/user', {
-                    action: 'updatetime',
-                    id: this.recipient.id,
-                    value: this.recipient.payedTime
-                });
-            }, 5000);
-            this.app.apiCall('/conversations', {id: this.id, action: 'start'});
-        }
-        if (value === Conversation.STATE_STOPPED || value === Conversation.STATE_PAUSED) {
-            clearInterval(this.interval);
-            clearInterval(this.syncInterval);
-        }
-        if (value === Conversation.STATE_STOPPED) {
-            delete this.initiator.conversations[this.id];
-            delete this.recipient.conversations[this.id];
-            delete this.app.conversations[this.id];
-            this.app.apiCall('/conversations', {id: this.id, action: 'stop', duration: this.duration});
-            this.app.apiCall('/user', {
-                action: 'updatetime',
-                id: this.initiator.id,
-                value: this.initiator.payedTime
-            });
-            this.app.apiCall('/user', {
-                action: 'updatetime', id:
-                this.recipient.id,
-                value: this.recipient.payedTime
-            });
-        }
-    }
-
-    get state() {
-        return this.conversationState();
-    }
-
-    newMessage(message) {
-        this.initiator.sendMessage({message: message, duration: this.duration});
-        this.recipient.sendMessage({message: message, duration: this.duration});
-    }
-}
 
 export interface AppConfigInterface {
     host?: string;

+ 35 - 18
src/Client.ts

@@ -1,9 +1,6 @@
-/**
- * Created by lcdee on 19.04.2017.
- */
 import {App} from "./App";
 import {MessagingClientData} from "./App";
-import {Conversation} from "./App";
+import {Conversation} from "./Conversation";
 import * as SocketIO from "socket.io";
 
 export class Client {
@@ -37,6 +34,14 @@ export class Client {
         this.isOnline = value;
     }
 
+    get name() {
+        return this.clientName;
+    }
+
+    get photo() {
+        return this.clientPhoto;
+    }
+
     get status(): boolean {
         return this.isOnline;
     }
@@ -50,7 +55,6 @@ export class Client {
         this.payedTime = parseInt(data.payedTime);
         this.timeToPay = data.timeToPay;
         this._coefficient = parseInt(data.coefficient);
-        console.log(this);
     }
 
     addSocket(socket: SocketIO.Socket) {
@@ -60,9 +64,9 @@ export class Client {
             this.sockets.splice(id, 1);
             if (this.sockets.length === 0) {
                 this.status = false;
-                this.app.removeClient(this.id);
                 for (let id in this.conversations) {
                     if (this.conversations.hasOwnProperty(id)) {
+                        console.log(`Pause ${id}`);
                         this.conversations[id].state = Conversation.STATE_PAUSED;
                     }
                 }
@@ -70,6 +74,7 @@ export class Client {
         });
         socket.on('chat-start-conversation', this.onStartConversation.bind(this));
         socket.on('chat-accept-conversation', this.onAcceptConversation.bind(this));
+        socket.on('chat-run-conversation', this.onRunConversation.bind(this));
         socket.on('chat-send-message', this.onSendMessage.bind(this));
     }
 
@@ -100,14 +105,15 @@ export class Client {
                 throw new Error(`You can't start conversation with yourself`);
             }
             let conversation = new Conversation(this.app);
-            conversation.initiator = this;
-            conversation.recipient = this.app.getClient(data.withPeer);
-            conversation.init(response => {
-                console.log(response);
-                try {
+            let recipientId = data.withPeer;
+            this.app.getClient(recipientId).then((recipient: Client) => {
+                conversation.initiator = this;
+                conversation.recipient = recipient;
+                conversation.init().then((response: string) => {
                     let data = JSON.parse(response);
                     conversation.id = data.id;
                     conversation.state = Conversation.STATE_INIT;
+                    this.conversations[conversation.id] = conversation
                     let responseData = {
                         userId: this.id,
                         senderId: this.id,
@@ -117,13 +123,9 @@ export class Client {
                         conversationId: conversation.id,
                     };
                     conversation.recipient.send('chat-start-conversation', JSON.parse(JSON.stringify(responseData)));
-                    responseData.userId = conversation.recipient.id;
+                    responseData.userId = recipientId;
                     conversation.initiator.send('chat-start-conversation', JSON.parse(JSON.stringify(responseData)));
-                } catch (e) {
-                    console.log(e);
-                }
-            }, err => {
-                console.log(`Error: ${err}`);
+                })
             });
         } catch (e) {
             this.sendError(e.message);
@@ -140,6 +142,21 @@ export class Client {
 
     private onSendMessage(...args) {
         let data = args[0];
-        this.app.conversations[data.conversation].newMessage(data.message);
+        this.app.getConversation(data.conversation).then((conversation: Conversation) => {
+            let to;
+            if (conversation.recipient.id == this.id) {
+                to = conversation.initiator.id;
+            } else {
+                to = conversation.recipient.id;
+            }
+            conversation.newMessage(data.message, this.id, to);
+        }).catch(err => console.log(err));
+    }
+
+    private onRunConversation(...args) {
+        let data = args[0];
+        this.app.getConversation(data.id).then(conversation => {
+            conversation.state = Conversation.STATE_RUNNING
+        });
     }
 }

+ 173 - 0
src/Conversation.ts

@@ -0,0 +1,173 @@
+import {App} from "./App";
+import {Client} from "./Client";
+
+export class Conversation {
+    private app: App;
+    private interval = null;
+    private syncInterval = null;
+
+    id: string;
+    initiator: Client;
+    recipient: Client;
+
+    duration: number = 0;
+
+    conversationState: (value?: number) => number;
+
+    static readonly STATE_INIT = 0;
+    static readonly STATE_RUNNING = 1;
+    static readonly STATE_STOPPED = 2;
+    static readonly STATE_PAUSED = 3;
+
+    constructor(app: App) {
+        let state;
+        this.app = app;
+        this.conversationState = (value?: number) => {
+            if (value !== undefined)
+                state = value;
+            return state;
+        };
+    }
+
+    init(): Promise<string> {
+        return this.app.apiCall('/conversations', {action: 'create'}).then(response => {
+            let data = JSON.parse(response);
+            return this.app.apiCall('/conversations', {
+                action: 'init',
+                id: data.id,
+                peers: [this.initiator.id, this.recipient.id]
+            });
+        });
+    }
+
+    set state(value: number) {
+        if ([Conversation.STATE_INIT, Conversation.STATE_RUNNING, Conversation.STATE_PAUSED, Conversation.STATE_STOPPED].indexOf(value) === -1) {
+            throw new Error(`State ${value} not in list of possible values.`);
+        }
+        if (value !== this.state) {
+            this.conversationState(value);
+            if (value === Conversation.STATE_INIT) {
+                this.app.conversations[this.id] = this;
+                this.initiator.conversations[this.id] = this;
+                this.recipient.conversations[this.id] = this;
+            }
+            if (value === Conversation.STATE_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.ceil(interval * this.recipient.coeficient);
+                        this.recipient.payedTime += Math.ceil(interval * this.recipient.coeficient);
+                        if (this.initiator.payedTime < 0) {
+                            this.state = Conversation.STATE_STOPPED;
+                        }
+                    }, 1000);
+                }
+                if (this.syncInterval === null) {
+                    this.syncInterval = setInterval(() => {
+                        this.initiator.send('chat-sync-timer', {
+                            conversationId: this.id,
+                            duration: this.duration
+                        });
+
+                        this.recipient.send('chat-sync-timer', {
+                            conversationId: this.id,
+                            duration: this.duration
+                        });
+
+                        this.app.apiCall('/conversations', {
+                            id: this.id,
+                            action: 'duration',
+                            duration: this.duration
+                        });
+
+                        this.app.apiCall('/user', {
+                            action: 'updatetime',
+                            id: this.initiator.id,
+                            value: this.initiator.payedTime
+                        });
+
+                        this.app.apiCall('/user', {
+                            action: 'updatetime',
+                            id: this.recipient.id,
+                            value: this.recipient.payedTime
+                        });
+                    }, 5000);
+                }
+
+                this.app.apiCall('/conversations', {id: this.id, action: 'start'});
+            }
+            if (value === Conversation.STATE_STOPPED || value === Conversation.STATE_PAUSED) {
+                clearInterval(this.interval);
+                this.interval = null;
+                clearInterval(this.syncInterval);
+                this.syncInterval = null;
+                this.initiator.send('chat-conversation-stop', {id: this.id});
+                this.recipient.send('chat-conversation-stop', {id: this.id});
+            }
+            if (value === Conversation.STATE_STOPPED) {
+                delete this.initiator.conversations[this.id];
+                delete this.recipient.conversations[this.id];
+                delete this.app.conversations[this.id];
+                this.app.apiCall('/conversations', {id: this.id, action: 'stop', duration: this.duration});
+                this.app.apiCall('/user', {
+                    action: 'updatetime',
+                    id: this.initiator.id,
+                    value: this.initiator.payedTime
+                });
+                this.app.apiCall('/user', {
+                    action: 'updatetime', id: this.recipient.id,
+                    value: this.recipient.payedTime
+                });
+            }
+        }
+    }
+
+    get state() {
+        return this.conversationState();
+    }
+
+    private getPeer(id): Client {
+        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.app.apiCall('/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(err => console.log(err));
+
+    }
+}

+ 1 - 1
src/tsconfig.json

@@ -1,7 +1,7 @@
 {
   "compilerOptions": {
     "module": "commonjs",
-    "target": "es5",
+    "target": "es6",
     "sourceMap": true,
     "outDir": "../build"
   },