summary refs log tree commit diff
path: root/webclient/components
diff options
context:
space:
mode:
Diffstat (limited to 'webclient/components')
-rw-r--r--webclient/components/matrix/matrix-service.js307
1 files changed, 307 insertions, 0 deletions
diff --git a/webclient/components/matrix/matrix-service.js b/webclient/components/matrix/matrix-service.js
new file mode 100644
index 0000000000..bbfffe75e7
--- /dev/null
+++ b/webclient/components/matrix/matrix-service.js
@@ -0,0 +1,307 @@
+'use strict';
+
+angular.module('matrixService', [])
+.factory('matrixService', ['$http', '$q', function($http, $q) {
+        
+   /* 
+    * Permanent storage of user information
+    * The config contains:
+    *    - homeserver url
+    *    - Identity server url
+    *    - user_id
+    *    - access_token
+    *    - version: the version of this cache
+    */    
+    var config;
+    
+    // Current version of permanent storage
+    var configVersion = 0;
+    var prefixPath = "/matrix/client/api/v1";
+    var MAPPING_PREFIX = "alias_for_";
+
+    var doRequest = function(method, path, params, data) {
+        // Inject the access token
+        if (!params) {
+            params = {};
+        }
+        params.access_token = config.access_token;
+        
+        return doBaseRequest(config.homeserver, method, path, params, data, undefined);
+    };
+
+    var doBaseRequest = function(baseUrl, method, path, params, data, headers) {
+        if (path.indexOf(prefixPath) !== 0) {
+            path = prefixPath + path;
+        }
+        // Do not directly return the $http instance but return a promise
+        // with enriched or cleaned information
+        var deferred = $q.defer();
+        $http({
+            method: method,
+            url: baseUrl + path,
+            params: params,
+            data: data,
+            headers: headers
+        })
+        .success(function(data, status, headers, config) {
+            // @TODO: We could detect a bad access token here and make an automatic logout
+            deferred.resolve(data, status, headers, config);
+        })
+        .error(function(data, status, headers, config) {
+            // Enrich the error callback with an human readable error reason
+            var reason = data.error;
+            if (!data.error) {
+                reason = JSON.stringify(data);
+            }
+            deferred.reject(reason, data, status, headers, config);
+        });
+
+        return deferred.promise;
+    };
+
+
+    return {
+        /****** Home server API ******/
+        prefix: prefixPath,
+
+        // Register an user
+        register: function(user_name, password) {
+            // The REST path spec
+            var path = "/register";
+
+            return doRequest("POST", path, undefined, {
+                 user_id: user_name,
+                 password: password
+            });
+        },
+
+        // Create a room
+        create: function(room_id, visibility) {
+            // The REST path spec
+            var path = "/rooms";
+
+            return doRequest("POST", path, undefined, {
+                visibility: visibility,
+                room_alias_name: room_id
+            });
+        },
+
+        // List all rooms joined or been invited to
+        rooms: function(from, to, limit) {
+            // The REST path spec
+            var path = "/im/sync";
+
+            return doRequest("GET", path);
+        },
+
+        // Joins a room
+        join: function(room_id) {
+            // The REST path spec
+            var path = "/rooms/$room_id/members/$user_id/state";
+
+            // Like the cmd client, escape room ids
+            room_id = encodeURIComponent(room_id);
+
+            // Customize it
+            path = path.replace("$room_id", room_id);
+            path = path.replace("$user_id", config.user_id);
+
+            return doRequest("PUT", path, undefined, {
+                 membership: "join"
+            });
+        },
+
+        // Invite a user to a room
+        invite: function(room_id, user_id) {
+            // The REST path spec
+            var path = "/rooms/$room_id/members/$user_id/state";
+
+            // Like the cmd client, escape room ids
+            room_id = encodeURIComponent(room_id);
+
+            // Customize it
+            path = path.replace("$room_id", room_id);
+            path = path.replace("$user_id", user_id);
+
+            return doRequest("PUT", path, undefined, {
+                 membership: "invite"
+            });
+        },
+
+        // Leaves a room
+        leave: function(room_id) {
+            // The REST path spec
+            var path = "/rooms/$room_id/members/$user_id/state";
+
+            // Like the cmd client, escape room ids
+            room_id = encodeURIComponent(room_id);
+
+            // Customize it
+            path = path.replace("$room_id", room_id);
+            path = path.replace("$user_id", config.user_id);
+
+            return doRequest("DELETE", path, undefined, undefined);
+        },
+
+        sendMessage: function(room_id, msg_id, content) {
+            // The REST path spec
+            var path = "/rooms/$room_id/messages/$from/$msg_id";
+
+            if (!msg_id) {
+                msg_id = "m" + new Date().getTime();
+            }
+
+            // Like the cmd client, escape room ids
+            room_id = encodeURIComponent(room_id);            
+
+            // Customize it
+            path = path.replace("$room_id", room_id);
+            path = path.replace("$from", config.user_id);
+            path = path.replace("$msg_id", msg_id);
+
+            return doRequest("PUT", path, undefined, content);
+        },
+
+        // Send a text message
+        sendTextMessage: function(room_id, body, msg_id) {
+            var content = {
+                 msgtype: "m.text",
+                 body: body
+            };
+
+            return this.sendMessage(room_id, msg_id, content);
+        },
+
+        // Send an emote message
+        sendEmoteMessage: function(room_id, body, msg_id) {
+            var content = {
+                 msgtype: "m.emote",
+                 body: body
+            };
+
+            return this.sendMessage(room_id, msg_id, content);
+        },
+
+        // get a snapshot of the members in a room.
+        getMemberList: function(room_id) {
+            // Like the cmd client, escape room ids
+            room_id = encodeURIComponent(room_id);
+
+            var path = "/rooms/$room_id/members/list";
+            path = path.replace("$room_id", room_id);
+            return doRequest("GET", path);
+        },
+
+        // get a list of public rooms on your home server
+        publicRooms: function() {
+            var path = "/public/rooms"
+            return doRequest("GET", path);
+        },
+        
+        // get a display name for this user ID
+        getDisplayName: function(userId) {
+            return this.getProfileInfo(userId, "displayname");
+        },
+
+        // get the profile picture url for this user ID
+        getProfilePictureUrl: function(userId) {
+            return this.getProfileInfo(userId, "avatar_url");
+        },
+
+        // update your display name
+        setDisplayName: function(newName) {
+            var content = {
+                displayname: newName
+            };
+            return this.setProfileInfo(content, "displayname");
+        },
+
+        // update your profile picture url
+        setProfilePictureUrl: function(newUrl) {
+            var content = {
+                avatar_url: newUrl
+            };
+            return this.setProfileInfo(content, "avatar_url");
+        },
+
+        setProfileInfo: function(data, info_segment) {
+            var path = "/profile/$user/" + info_segment;
+            path = path.replace("$user", config.user_id);
+            return doRequest("PUT", path, undefined, data);
+        },
+
+        getProfileInfo: function(userId, info_segment) {
+            var path = "/profile/$user_id/" + info_segment;
+            path = path.replace("$user_id", userId);
+            return doRequest("GET", path);
+        },
+        
+        login: function(userId, password) {
+            // TODO We should be checking to make sure the client can support
+            // logging in to this HS, else use the fallback.
+            var path = "/login";
+            var data = {
+                "type": "m.login.password",
+                "user": userId,
+                "password": password  
+            };
+            return doRequest("POST", path, undefined, data);
+        },
+
+        // hit the Identity Server for a 3PID request.
+        linkEmail: function(email) {
+            var path = "/matrix/identity/api/v1/validate/email/requestToken"
+            var data = "clientSecret=abc123&email=" + encodeURIComponent(email);
+            var headers = {};
+            headers["Content-Type"] = "application/x-www-form-urlencoded";
+            return doBaseRequest(config.identityServer, "POST", path, {}, data, headers); 
+        },
+
+        authEmail: function(userId, tokenId, code) {
+            var path = "/matrix/identity/api/v1/validate/email/submitToken";
+            var data = "token="+code+"&mxId="+encodeURIComponent(userId)+"&tokenId="+tokenId;
+            var headers = {};
+            headers["Content-Type"] = "application/x-www-form-urlencoded";
+            return doBaseRequest(config.identityServer, "POST", path, {}, data, headers); 
+        },
+        
+        /****** Permanent storage of user information ******/
+        
+        // Returns the current config
+        config: function() {
+            if (!config) {
+                config = localStorage.getItem("config");
+                if (config) {
+                    config = JSON.parse(config);
+
+                    // Reset the cache if the version loaded is not the expected one
+                    if (configVersion !== config.version) {
+                        config = undefined;
+                        this.saveConfig();
+                    }
+                }
+            }
+            return config;
+        },
+        
+        // Set a new config (Use saveConfig to actually store it permanently)
+        setConfig: function(newConfig) {
+            config = newConfig;
+        },
+        
+        // Commits config into permanent storage
+        saveConfig: function() {
+            config.version = configVersion;
+            localStorage.setItem("config", JSON.stringify(config));
+        },
+        
+        createRoomIdToAliasMapping: function(roomId, alias) {
+            localStorage.setItem(MAPPING_PREFIX+roomId, alias);
+        },
+        
+        getRoomIdToAliasMapping: function(roomId) {
+            return localStorage.getItem(MAPPING_PREFIX+roomId);
+        }
+
+    };
+}]);