# Fetches room history in a room up to a given point in time (`limit`).
# This is an example of using the messages stream.
[access_token, room_id, limitStr] = System.argv
{limit, _} = Integer.parse(limitStr)
{:ok, client_pid} = Polyjuice.Client.start_link(
"http://localhost:8008",
access_token: access_token,
sync: false
)
client = Polyjuice.Client.get_client(client_pid)
# Get a minimal sync that just contains room messages. We need to get a sync so
# we have a previous batch.
# FIXME: only include results from the selected room
sync_filter = Polyjuice.Client.Filter.include_timeline_types(["m.room.message"])
|> Polyjuice.Client.Filter.include_state_types([])
|> Polyjuice.Client.Filter.include_presence_types([])
|> Polyjuice.Client.Filter.include_ephemeral_types([])
{:ok, initial_sync} = Polyjuice.Client.sync(client, set_presence: :offline, filter: sync_filter)
timeline = initial_sync |> Map.get("rooms", %{}) |> Map.get("join", %{})
|> Map.get(room_id, %{}) |> Map.get("timeline")
if timeline do
prev_batch = Map.get(timeline, "prev_batch")
# we will process events from latest to earliest, so reverse the events we
# get from the sync
events = Map.get(timeline, "events") |> Enum.reverse()
if events && events != [] do
# Create a stream of events. `stream_messages` gives a stream of message
# batches as given by `GET /rooms/{roomid}/messages`.
event_stream = if prev_batch do
Polyjuice.Client.Room.stream_messages(
client, room_id, prev_batch, :backward
)
# Fetch the "chunk" property from each batch, which is a list of events
# in that batch (from latest to earliest, since the direction is
# `:backward`).
|> Stream.map(&Map.get(&1, "chunk", []))
# Concatenate the events from the stream of batches to get a single
# stream of events.
|> Stream.concat()
# Prepend the events that we got from the sync.
|> (&Stream.concat(events, &1)).()
else
events
end
# Traverse the stream, and take messages until we get to one earlier than
# our limit.
event_stream |> Stream.take_while(&(Map.get(&1, "origin_server_ts", 0) >= limit))
# Reverse the stream so that we go from earliest to latest
|> Enum.reverse()
# Format the event
|> Enum.each(&IO.puts("#{Map.get(&1, "sender")}> #{Map.get(&1, "content") |> Map.get("body")}"))
else
IO.puts("No messages")
end
else
IO.puts("Unknown room #{room_id}")
end