Commit Graph

32 Commits

Author SHA1 Message Date
Adrian Perez de Castro
b0cbf93b7e Use a callback in client:sync() to determine when to stop the loop
Instead of adding more and more possible conditions on which the while-loop
inside client:sync() could stop, support passing a callback function which is
used to determine when to stop the loop.

The old "so N iterations behaviour" can be achieved with something like:

  function iterate_n_times(n)
    return function ()
      n = n - 1
      return n == 0
    end
  end
  client:sync(iterate_n_times(10))

If no function is passed, the client:sync() function loops forever.
2016-07-05 01:09:51 +03:00
Adrian Perez de Castro
cadda45130 Handle "join" events properly
This handles the fact that when using the /sync endpoint, events for already
joined rooms are also in the "join" dictionary in the response. The firing of
the "joined" event is moved to client:_make_room() and done only the first
time that the room creation is requested.

This also fixes bogus behavior: previosly, when a message was sent to a room
there would be multiople places where the "joined" event would be fired, and
message events pushed multile times onto the room object, which would call
the event handlers more than once for each message. Ugh.
2016-07-05 01:03:23 +03:00
Adrian Perez de Castro
bad6e6ee16 Allow passing a room object to client:join_room()
This neatly allows to pass the room object passed to the "invited" event
directly to :join_room(). This way the user does not need to know that
rooms have a "room_id" attribute.
2016-07-05 01:01:34 +03:00
Adrian Perez de Castro
e51b67aef6 Fire "message" events for rooms which receive messages 2016-07-05 00:59:55 +03:00
Adrian Perez de Castro
f879cd68e6 Have matrix.client fire "left" events when leaving a room
This allows hooking to both room join and room leave events at the client
level, which apart from being more orthogonal, may be more convenient
sometimes.
2016-07-05 00:58:33 +03:00
Adrian Perez de Castro
a50931c3f6 Use room.client instead of room._client
This hints that the "client" attribute can be used from user code.
And it can.
2016-07-05 00:57:12 +03:00
Adrian Perez de Castro
51c8eda815 Fix conversion of http.headers in Lua 5.1 and LuaJIT
The __pairs metamethod was introduced in 5.2, so instead of using pairs()
on http.headers values, use its :each() method — which is what the __pairs
metamethod calls anyway.
2016-07-04 18:23:35 +03:00
Adrian Perez de Castro
0aa232965c Workaround LuaSocket's lax response validation
When receiving a HTTP response without a statusline, "nil" is returned as
reponse headers and status line values, but the response code will still
be "200 Success", which is quite not right as there wasn't ever a response
status code received. This patch adds a check for a status line, and returns
with an early error if needed.

This condition can be triggered by trying to speak plain HTTP to a
HTTPS-enabled server, e.g. using http://matrix.org:8448 instead of
https://matrix.org:8448 as homeserver URL.
2016-07-04 17:52:39 +03:00
Adrian Perez de Castro
fabb5330d1 First pass at client:sync()
For the moment only the amount of iterations, or processing events foerever,
can be specified. The timeout is not yet configurable.
2016-07-04 03:19:16 +03:00
Adrian Perez de Castro
02b3d880a6 Log the identifier of the batch of events being requested 2016-07-04 03:18:43 +03:00
Adrian Perez de Castro
9cd4e13310 Use xpcall() instead of pcall() to obtain tracebacks
Printing a traceback is much more help when debugging event handling.
2016-07-04 03:17:25 +03:00
Adrian Perez de Castro
c1492cd39a Add missing string format parameter when loggign property changes 2016-07-04 03:16:46 +03:00
Adrian Perez de Castro
b861b37dbb Fix typo "ince" -> "since" in api:sync() 2016-07-04 03:16:10 +03:00
Adrian Perez de Castro
7952f15053 eventable: Fix unhooking of handlers 2016-07-03 22:55:28 +03:00
Adrian Perez de Castro
4e9899dbb5 Simplify matrix.eventable for the common use cases
This removes the support for passing values to eventable.functions() and
eventable.object() which are bound to be passed to handlers. On top of
simplifying the code overall, this also avoids having three different
implementations of the fire() function.

In the existing code, the only case in which a handler argument is fixed
is for objects which pass themselves. This use case is covered by
eventable.object(), so the removed code was not realy ever used.
2016-07-03 22:21:33 +03:00
Adrian Perez de Castro
03c1091742 Allow skipping the automatic sync on login/registration
This removes the currently unused "limit" parameter from
client:login_with_password() and client:register_with_password(), and adds a
new "no_sync" parameter. When the flag is set, the call to client:_sync() is
skipped. This can be useful for small scripts which do not need to do a sync
after login, yet they would rather user the higher level "matrix.client"
instead of the low level "matrix.api". For example, a simple script to send
a message to an already-known room given its ID could skip the sync in order
to be faster, without needing to revert to using "matrix.api".
2016-07-03 15:06:25 +03:00
Adrian Perez de Castro
bd811c859e Rename matrix.factory.* -> matrix.httpclient.*
The old name didn't really make much sense after all...
2016-07-01 05:10:22 +03:00
Adrian Perez de Castro
e128366f7f Use eventables in matrix.client, implement a chunk of functionality
Yeah, I know: commits should have been smaller and all that. Yadda-yadda.
2016-07-01 05:05:50 +03:00
Adrian Perez de Castro
fc99710658 Improvements to matrix.eventable
* Support debug-logging to stderr by defining the MATRIX_EVENTABLE_DEBUG_LOG
  environment variable.
* Support for unhooking handlers from events.
* Simplify the low-level interface: eventable.functions() now returns the
  created functions directly, cutting down on an intermediate table.
* A new eventable.object() allows adding :hook(), :unhook() and :fire()
  methods to any table. Firing events always sends the table itself as first
  event parameter when firing any event.
2016-07-01 04:55:16 +03:00
Adrian Perez de Castro
99fbf8eb28 First pass at an event-based notification facilty
The matrix.eventable module/function returns a table with a pair of functions
which can be used to connect event handlers to events, and to generate them.
Basic usage is as follows:

  obj = eventable()
  obj.hook("event-name", print)  -- Handle the event with "print"
  obj.fire("event-name", "Hello, world")  -- Prints "Hello, world"

This initial implementation has the following limitations:

* Event handlers are always invoked in the same order in which they have been
  connected using the .hook() function.
* Individual event handlers cannot be disconnected. Only disconnecting all
  handlers for en event at once is possible via .hook("event", nil).
2016-06-30 00:24:24 +03:00
Adrian Perez de Castro
5a23cb5b85 Use the /sync endpoing instead /initialSync
The /initialSync endpoint is deprecated. This renames the api:initial_sync()
method to api:sync(), and uses the new endpoint.
2016-06-30 00:12:55 +03:00
Adrian Perez de Castro
0a58777f42 Use MATRIX_API_DEBUG_LOG environment variable
The new name indicates in a clearer way that it enables logging of matrix.api
operations.
2016-06-30 00:11:18 +03:00
Adrian Perez de Castro
9fb0bed7c0 Use "[api]" as log prefix instead of "[http]"
The old prefix could be confusing if the homeserver URL used the https://
scheme, and the new one better conveys that it is matrix.api who is doing
the logging.
2016-06-30 00:09:56 +03:00
Adrian Perez de Castro
daa8bfe923 Implement a LuaSocket/LuaSec-based HTTP client
Note that LuaSec is actually optional, and will be loaded on-demand when the
first request using the https:// scheme is issued.
2016-06-28 23:47:51 +03:00
Adrian Perez de Castro
58ff794d92 Improve loading of HTTP client factories
This introduces a get_http_factory() function which will try to load
a HTTP client library according to the following logic:

1. If the MATRIX_API_HTTP_CLIENT environment variable is defined, it is
   taken as the name of a HTTP client library.
2. Otherwise, if the function paramter is non-nil it is used as the name
   of the HTTP client library to load.
3. Otherwise, the available HTTP client libraries are tried in order,
   and the first one which can be require()'d successfully will be
   used. For now this has only the "chttp" client.
2016-06-28 23:44:20 +03:00
Adrian Perez de Castro
cf14c37e58 Log the HTTP client being used with each request 2016-06-28 23:22:21 +03:00
Adrian Perez de Castro
28477c4db7 Always stringigy returned HTTP status code for logging
This avoids the potential issue in which the status code would be "nil" or
"false", which HTTP client libraries may choose to signal an error condition.
2016-06-28 23:21:04 +03:00
Adrian Perez de Castro
724d7cdd54 Simplify HTTP client API
* The :quote and :unquote methods are now plain functions and no longer
  receive the "self" parameter. This allows to directly use the utility
  functions provided by the HTTP client library.
* Renamed CqHttpClient to plain "httclient". The variable itself is local
  to the script so it does not need to be unique.
2016-06-28 23:20:50 +03:00
Adrian Perez de Castro
a1cf21b839 Implement room:update_room_{topic,aliases,name} 2016-06-23 04:17:15 +03:00
Adrian Perez de Castro
56a57f2e89 Add __tostring metamethods to prototypes
This is nice to have, and aids with debugging and interactive usage.
2016-06-23 04:07:01 +03:00
Adrian Perez de Castro
cafb8724e3 Import rough implementation of matrix.client 2016-06-23 03:54:48 +03:00
Adrian Perez de Castro
6528727cff Initial import: low-level API wrapper 2016-06-23 03:49:04 +03:00