Current section

17 Versions

Jump to

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…