Current section
17 Versions
Jump to
Current section
17 Versions
Compare versions
9
files changed
+63
additions
-203
deletions
| @@ -21,7 +21,7 @@ Add Twittex to your list of dependencies in `mix.exs`: | |
| 21 21 | |
| 22 22 | ```elixir |
| 23 23 | def deps do |
| 24 | - [{:twittex, "~> 0.1"}] |
| 24 | + [{:twittex, "~> 0.2"}] |
| 25 25 | end |
| 26 26 | ``` |
| @@ -3,30 +3,32 @@ | |
| 3 3 | {<<"description">>,<<"Twitter client library for Elixir">>}. |
| 4 4 | {<<"elixir">>,<<"~> 1.3">>}. |
| 5 5 | {<<"files">>, |
| 6 | - [<<"lib/twittex.ex">>,<<"lib/twittex/aggregator.ex">>, |
| 7 | - <<"lib/twittex/aggregator/tag.ex">>,<<"lib/twittex/api.ex">>, |
| 8 | - <<"lib/twittex/client.ex">>,<<"lib/twittex/client/base.ex">>, |
| 9 | - <<"lib/twittex/client/stream.ex">>,<<"mix.exs">>,<<"README.md">>, |
| 10 | - <<"LICENSE">>]}. |
| 6 | + [<<"lib/twittex.ex">>,<<"lib/twittex/api.ex">>,<<"lib/twittex/client.ex">>, |
| 7 | + <<"lib/twittex/client/base.ex">>,<<"lib/twittex/client/stream.ex">>, |
| 8 | + <<"mix.exs">>,<<"README.md">>,<<"LICENSE">>]}. |
| 11 9 | {<<"licenses">>,[<<"MIT">>]}. |
| 12 10 | {<<"links">>,[{<<"github">>,<<"https://github.com/almightycouch/twittex">>}]}. |
| 13 11 | {<<"maintainers">>,[<<"Mario Flach">>]}. |
| 14 12 | {<<"name">>,<<"twittex">>}. |
| 15 13 | {<<"requirements">>, |
| 16 | - [[{<<"app">>,<<"oauth2">>}, |
| 17 | - {<<"name">>,<<"oauth2">>}, |
| 14 | + [[{<<"app">>,<<"poison">>}, |
| 15 | + {<<"name">>,<<"poison">>}, |
| 18 16 | {<<"optional">>,false}, |
| 19 | - {<<"requirement">>,<<"~> 0.6">>}], |
| 17 | + {<<"requirement">>,<<"~> 3.0">>}], |
| 20 18 | [{<<"app">>,<<"httpoison">>}, |
| 21 19 | {<<"name">>,<<"httpoison">>}, |
| 22 20 | {<<"optional">>,false}, |
| 23 | - {<<"requirement">>,<<"~> 0.9">>}], |
| 21 | + {<<"requirement">>,<<"~> 0.10">>}], |
| 22 | + [{<<"app">>,<<"oauth2">>}, |
| 23 | + {<<"name">>,<<"oauth2">>}, |
| 24 | + {<<"optional">>,false}, |
| 25 | + {<<"requirement">>,<<"~> 0.8">>}], |
| 24 26 | [{<<"app">>,<<"oauther">>}, |
| 25 27 | {<<"name">>,<<"oauther">>}, |
| 26 28 | {<<"optional">>,false}, |
| 27 | - {<<"requirement">>,<<"~> 1.0">>}], |
| 29 | + {<<"requirement">>,<<"~> 1.1">>}], |
| 28 30 | [{<<"app">>,<<"gen_stage">>}, |
| 29 31 | {<<"name">>,<<"gen_stage">>}, |
| 30 32 | {<<"optional">>,false}, |
| 31 | - {<<"requirement">>,<<"~> 0.5">>}]]}. |
| 32 | - {<<"version">>,<<"0.2.0">>}. |
| 33 | + {<<"requirement">>,<<"~> 0.8">>}]]}. |
| 34 | + {<<"version">>,<<"0.2.1">>}. |
| @@ -1,128 +0,0 @@ | |
| 1 | - defmodule Twittex.Aggregator do |
| 2 | - @moduledoc """ |
| 3 | - A behaviour module for implementing stream aggregators. |
| 4 | - |
| 5 | - ## Example |
| 6 | - |
| 7 | - To create a stream aggregator, create a new module and `use Twittex.Aggregator` as follow: |
| 8 | - |
| 9 | - defmodule TagAggregator do |
| 10 | - use Twittex.Aggregator |
| 11 | - |
| 12 | - def map(stream) do |
| 13 | - stream |
| 14 | - |> Stream.flat_map(& &1["entities"]["hashtags"]) |
| 15 | - |> Stream.map(& &1["text"]) |
| 16 | - end |
| 17 | - |
| 18 | - def reduce(tag, acc) do |
| 19 | - Map.update(acc, tag, 1, & &1 + 1) |
| 20 | - end |
| 21 | - end |
| 22 | - |
| 23 | - And this is how you may use it: |
| 24 | - |
| 25 | - iex> "#elixir-lang" |> TagAggregator.new |> TagAggregator.run |
| 26 | - """ |
| 27 | - |
| 28 | - @type accumulator :: %{} |
| 29 | - |
| 30 | - @callback map(Stream.t) :: Stream.t |
| 31 | - |
| 32 | - @callback reduce(any, accumulator) :: accumulator |
| 33 | - |
| 34 | - defmacro __using__(_options) do |
| 35 | - quote do |
| 36 | - def new(query, options \\ []), do: |
| 37 | - Twittex.Aggregator.new(__MODULE__, query, options) |
| 38 | - |
| 39 | - def next(stream, duration \\ 1, duration_unit \\ :seconds), do: |
| 40 | - Twittex.Aggregator.next(__MODULE__, stream, duration, duration_unit) |
| 41 | - |
| 42 | - def run(stream, max \\ 10, frame_duration \\ 1, duration_unit \\ :seconds), do: |
| 43 | - Twittex.Aggregator.run(__MODULE__, stream, &print_tag/1, &sort_tag/1, max, frame_duration, duration_unit) |
| 44 | - |
| 45 | - def sort_tag(tag) do |
| 46 | - Twittex.Aggregator.sort_tag(tag) |
| 47 | - end |
| 48 | - |
| 49 | - def print_tag(tag) do |
| 50 | - Twittex.Aggregator.print_tag(tag) |
| 51 | - end |
| 52 | - |
| 53 | - defoverridable [sort_tag: 1, print_tag: 1] |
| 54 | - end |
| 55 | - end |
| 56 | - |
| 57 | - @doc """ |
| 58 | - Returns a new stream of tags matching the given `query`. |
| 59 | - |
| 60 | - See `Twittex.Client.stream/2` for more detailed information. |
| 61 | - """ |
| 62 | - @spec new(module, String.t, Keyword.t) :: Stream.t |
| 63 | - def new(aggregator, query, options \\ []) do |
| 64 | - query |
| 65 | - |> Twittex.Client.stream!(options) |
| 66 | - |> aggregator.map() |
| 67 | - end |
| 68 | - |
| 69 | - @doc """ |
| 70 | - Returns the next batch of tweets from the `stream`. |
| 71 | - """ |
| 72 | - @spec next(module, Stream.t, Integer.t, System.time_unit) :: %{} |
| 73 | - def next(aggregator, stream, duration \\ 1, duration_unit \\ :seconds) do |
| 74 | - timestamp = now(duration_unit) |
| 75 | - Enum.reduce_while stream, %{}, fn tag, acc -> |
| 76 | - acc = aggregator.reduce(tag, acc) |
| 77 | - unless now(duration_unit) > timestamp + duration do |
| 78 | - {:cont, acc} |
| 79 | - else |
| 80 | - {:halt, acc} |
| 81 | - end |
| 82 | - end |
| 83 | - end |
| 84 | - |
| 85 | - @doc """ |
| 86 | - Runs the given `stream`. |
| 87 | - """ |
| 88 | - @spec run(module, Stream.t, (any -> :ok), (any -> any), Integer.t, Integer.t, System.time_unit) :: :ok |
| 89 | - def run(aggregator, stream, print_fun \\ nil, sort_fun \\ nil, max \\ 10, frame_duration \\ 1, duration_unit \\ :seconds) do |
| 90 | - {print_fun, sort_fun} = |
| 91 | - unless print_fun do |
| 92 | - {&print_tag/1, &sort_tag/1} |
| 93 | - else |
| 94 | - {print_fun, sort_fun || &sort_tag/1} |
| 95 | - end |
| 96 | - |
| 97 | - Stream.iterate(%{}, &accumulate_next(aggregator, stream, &1, frame_duration, duration_unit)) |
| 98 | - |> Stream.each(&print_top(&1, print_fun, sort_fun, max)) |
| 99 | - |> Stream.run() |
| 100 | - end |
| 101 | - |
| 102 | - @doc false |
| 103 | - def sort_tag(tag) do |
| 104 | - elem(tag, 1) |
| 105 | - end |
| 106 | - |
| 107 | - @doc false |
| 108 | - def print_tag({tag, count}) do |
| 109 | - IO.puts("#{count} #{IO.ANSI.bright}##{tag}#{IO.ANSI.reset}") |
| 110 | - end |
| 111 | - |
| 112 | - defp now(duration_unit) do |
| 113 | - System.system_time(duration_unit) |
| 114 | - end |
| 115 | - |
| 116 | - defp accumulate_next(aggregator, stream, acc, duration, duration_unit) do |
| 117 | - Map.merge(acc, next(aggregator, stream, duration, duration_unit), fn _k, v1, v2 -> v1 + v2 end) |
| 118 | - end |
| 119 | - |
| 120 | - defp print_top(acc, print_fun, sort_fun, max) do |
| 121 | - IEx.Helpers.clear() |
| 122 | - acc |
| 123 | - |> Enum.to_list |
| 124 | - |> Enum.sort_by(sort_fun, &>=/2) |
| 125 | - |> Enum.slice(0, max) |
| 126 | - |> Enum.each(print_fun) |
| 127 | - end |
| 128 | - end |
| @@ -1,16 +0,0 @@ | |
| 1 | - defmodule Twittex.Aggregator.Tag do |
| 2 | - @moduledoc false |
| 3 | - |
| 4 | - use Twittex.Aggregator |
| 5 | - |
| 6 | - def map(stream) do |
| 7 | - stream |
| 8 | - |> Stream.flat_map(& &1["entities"]["hashtags"]) |
| 9 | - |> Stream.map(& &1["text"]) |
| 10 | - end |
| 11 | - |
| 12 | - def reduce(tag, acc) do |
| 13 | - Map.update(acc, tag, 1, & &1 + 1) |
| 14 | - end |
| 15 | - end |
| 16 | - |
| @@ -123,10 +123,13 @@ defmodule Twittex.API do | |
| 123 123 | |
| 124 124 | # request bearer token |
| 125 125 | case OAuth2.Client.get_token(client, [], [], options) do |
| 126 | - {:ok, %OAuth2.AccessToken{other_params: %{"errors" => [%{"message" => error}|_]}}} -> |
| 127 | - {:error, %OAuth2.Error{reason: error}} |
| 128 | - {:ok, %OAuth2.AccessToken{access_token: access_token}} -> |
| 129 | - {:ok, OAuth2.AccessToken.new(access_token, client)} |
| 126 | + {:ok, %OAuth2.Client{token: token}} -> |
| 127 | + token = |
| 128 | + token |
| 129 | + |> Map.fetch!(:access_token) |
| 130 | + |> Poison.decode!() |
| 131 | + |> OAuth2.AccessToken.new() |
| 132 | + {:ok, token} |
| 130 133 | {:error, error} -> |
| 131 134 | {:error, error} |
| 132 135 | end |
| @@ -148,7 +151,7 @@ defmodule Twittex.API do | |
| 148 151 | # make url absolute |
| 149 152 | url = |
| 150 153 | unless URI.parse(url).scheme do |
| 151 | - url = @api_url <> "/#{@api_version}" <> url |
| 154 | + @api_url <> "/#{@api_version}" <> url |
| 152 155 | else |
| 153 156 | url |
| 154 157 | end |
Loading more files…