Import rough implementation of matrix.client

This commit is contained in:
Adrian Perez de Castro
2016-06-23 03:54:48 +03:00
parent 6528727cff
commit cafb8724e3

174
matrix/client.lua Normal file
View File

@@ -0,0 +1,174 @@
#! /usr/bin/env lua
--
-- client.lua
-- Copyright (C) 2016 Adrian Perez <aperez@igalia.com>
--
-- Distributed under terms of the MIT license.
--
local User = {}
User.__index = User
setmetatable(User, { __call = function (self, client, user_id)
return setmetatable({ user_id = user_id, _client = client }, User)
end })
function User:get_display_name()
return self._client._api:get_display_name(self.user_id)
end
function User:set_display_name(display_name)
return self._client._api:set_display_name(self.user_id, display_name)
end
function User:get_avatar_url()
local mxc_url = self._client._api:get_avatar_url(self.user_id)
return self._client._api:get_download_url(mxc_url)
end
function User:set_avatar_url(avatar_url)
return self._client._api:set_avatar_url(self.user_id, avatar_url)
end
local Room = {}
Room.__index = Room
setmetatable(Room, { __call = function (self, client, room_id)
return setmetatable({
room_id = room_id,
aliases = {},
events = {},
_client = client,
}, Room)
end })
function Room:send_text(text)
return self._client._api:send_message(self.room_id, text)
end
function Room:send_emote(text)
return self._client._api:send_emote(self.room_id, text)
end
function Room:send_notice(text)
return self._client._api:send_notice(self.room_id, text)
end
function Room:invite_user(user_id)
-- XXX: Do we really want to pcall(), or should error propagate?
return pcall(self._client._api.invite_user,
self._client._api, self.room_id, user_id)
end
function Room:kick_user(user_id)
-- XXX: Do we really want to pcall(), or should error propagate?
return pcall(self._client._api.kick_user,
self._client._api, self.room_id, user_id)
end
function Room:ban_user(user_id)
-- XXX: Do we really want to pcall(), or should error propagate?
return pcall(self._client._api.ban_user,
self._client._api, self.room_id, user_id)
end
function Room:leave()
-- XXX: Maybe this should use pcall()?
self._client._api:leave_room(self.room_id)
self._client.rooms[self.room_id] = nil
end
local Client = {}
Client.__index = Client
setmetatable(Client, { __call = function (self, base_url, token, http_factory)
local c = setmetatable({
rooms = {}, -- Indexed by room_id
_api = require("matrix.api")(base_url, token, http_factory),
}, Client)
-- Do an initial sync if a token was provided on construction.
if token then
c:_sync()
end
return c
end })
function Client:register_with_password(username, password, limit)
return self:_logged_in(self._api:register("m.login.password",
{ user = username, password = password }), limit)
end
function Client:login_with_password(username, password, limit)
return self:_logged_in(self._api:login("m.login.password",
{ user = username, password = password }), limit)
end
function Client:_logged_in(response, limit)
self.user_id = response.user_id
self.homeserver = response.home_server
self.token = response.access_token
self._api.token = response.access_token
self:_sync(limit)
return self.token
end
function Client:logout()
return self._api:logout()
end
function Client:get_user()
return self.user_id and User(self, self.user_id) or nil
end
function Client:create_room(alias, public, invite)
local response = self._api:create_room {
alias = alias,
public = public,
invite = invite,
}
return self:_make_room(response.room_id)
end
function Client:join_room(room_id_or_alias)
local response = self._api:join_room(room_id_or_alias)
return self:_make_room(response.room_id or room_id_or_alias)
end
function Client:_make_room(room_id)
local room = Room(self, room_id)
self.rooms[room_id] = room
return room
end
function Client:_sync(limit)
local response = self._api:initial_sync(limit)
self._end = response._end
for _, room in ipairs(response.rooms) do
local current_room = self:_make_room(room.room_id)
for _, chunk in ipairs(room.messages.chunk) do
table.insert(current_room.events, chunk)
end
for _, state_event in ipairs(room.state) do
self:_process_state_event(state_event, current_room)
end
end
end
function Client:_process_state_event(event, room)
local event_type = event.type
if not event_type then
return -- Ignore event
end
if event_type == "m.room.name" then
room.name = event.content.name
elseif event_type == "m.room.topic" then
room.topic = event.content.topic
elseif event_type == "m.room.aliases" then
room.aliases = event.content.aliases
end
end
return { room = Room, user = User, client = Client }