~fnux/telegram-tl-elixir

710f3658f44f17df6f3e89730073938839c00738 — Timothée Floure 5 years ago b8ed41e
Fix parsing of "messages" : get_dialogs
2 files changed, 42 insertions(+), 21 deletions(-)

M lib/tl/parse.ex
M lib/tl/schema.ex
M lib/tl/parse.ex => lib/tl/parse.ex +22 -9
@@ 211,18 211,31 @@ defmodule TL.Parse do
    unbox(:vector, value, count, [], type)
  end

  defp unbox(_, _, _, _, type \\ :unknow) # header
  defp unbox(_, _, _, _, type \\ :from_schema) # header
  defp unbox(:vector, tail, 0, output, _), do: {output, tail}
  defp unbox(:vector, data, count, output, type) do
    unless type == :unknow do
      {map, tail} = dispatch(:vector, type, data)
      unbox(:vector, tail, count - 1, (output ++ [map]), type)
    else
      container = :binary.part(data, 0, 4) |> deserialize(:int)
      content = :binary.part(data, 4, byte_size(data) - 4)
      {map, tail} = dispatch(:vector, container, content)
    # The `message` predicate exists in both the TL and API schemas --'
    # This part is somewhat ugly but I suppose I still have to discover  a lot
    # of special cases... Will figure out later.
    case type do
      :message -> # Workaround for get_dialogs
        container = :binary.part(data, 0, 4) |> deserialize(:int)
        {status, _} = Schema.search "id", Integer.to_string(container)
        if status == :match do
          unbox(:vector, data, count, output, :from_schema)
        else # status == :nothing
          {map, tail} = dispatch(:vector, type, data)
          unbox(:vector, tail, count - 1, (output ++ [map]), type)
        end
      :from_schema -> # Search for the container in the schema
        container = :binary.part(data, 0, 4) |> deserialize(:int)
        content = :binary.part(data, 4, byte_size(data) - 4)
        {map, tail} = dispatch(:vector, container, content)

      unbox(:vector, tail, count - 1, (output ++ [map]))
        unbox(:vector, tail, count - 1, (output ++ [map]))
      _ ->
        {map, tail} = dispatch(:vector, type, data)
        unbox(:vector, tail, count - 1, (output ++ [map]), type)
    end
  end


M lib/tl/schema.ex => lib/tl/schema.ex +20 -12
@@ 34,24 34,32 @@ defmodule TL.Schema do
  end

  @doc """
  Search descriptors in the schema(s)

    * `key`
    * `container`
  """
  def search(key, container) do
    {tl_match, tl_value} = search(key, container, :tl)
    # If a match was found in the tl schema, return it. If not, search in
    # the api schema.
    if tl_match == :match do
      {:match, tl_value}
    else
      {api_match, api_value} = search(key, container, :api)
      if api_match == :match, do: {:match, api_value}, else: {:nothing, nil}
    end
  end

  @doc """
    Search the schema(s).

    * `key` - example : `"predicate"`
    * `content` - example : `"ping"`
    * `schema` - schema to search into, either `:tl`, `:api` or `:both` (default).
    * `schema` - schema to search into, either `:tl` or `:api`.
  """
  def search(key, content, schema \\ :both) do
  def search(key, content, schema) do
    case schema do
      :both ->
        {tl_match, tl_value} = search(key, content, :tl)
        # If a match was found in the tl schema, return it. If not, search in
        # the api schema.
          if tl_match == :match do
            {:match, tl_value}
          else
            {api_match, api_value} = search(key, content, :api)
            if api_match == :match, do: {:match, api_value}, else: {:nothing, nil}
          end
      :tl -> search_schema(key, content, tl())
      :api -> search_schema(key, content, api())
      _ -> {:err, nil}