defmodule SomethingErlang.AwfulApi.Client do @base_url "https://forums.somethingawful.com/" @user_agent "SomethingErlangClient/0.1" require Logger def thread_doc(id, page, user) do resp = new(user) |> get_thread(id, page) Logger.debug("Client reply in #{resp.private.time}ms ") :unicode.characters_to_binary(resp.body, :latin1) end def thread_lastseen_page(id, user) do resp = new(user) |> get_thread_newpost(id) %{status: 302, headers: headers} = resp {"location", redir_url} = List.keyfind(headers, "location", 0) [_, page] = Regex.run(~r/pagenumber=(\d+)/, redir_url) page |> String.to_integer() end def bookmarks_doc(page, user) do resp = new(user) |> get_bookmarks(page) :unicode.characters_to_binary(resp.body, :latin1) end defp get_thread(req, id, page) do url = "showthread.php" params = [threadid: id, pagenumber: page] Req.get!(req, url: url, params: params) end defp get_thread_newpost(req, id) do url = "showthread.php" params = [threadid: id, goto: "newpost"] Req.get!(req, url: url, params: params, follow_redirects: false) end defp get_bookmarks(req, page) do url = "bookmarkthreads.php" params = [pagenumber: page] Req.get!(req, url: url, params: params) end def login(username, password) do form = [action: "login", username: username, password: password] url = "account.php" new() |> Req.post!(url: url, form: form) |> extract_cookies() end defp extract_cookies(%Req.Response{} = response) do cookies = response.headers["set-cookie"] for cookie <- cookies, String.starts_with?(cookie, "bb"), into: %{} do cookie |> String.split(";", parts: 2) |> List.first() |> String.split("=") |> then(fn [k, v] -> {String.to_existing_atom(k), v} end) end end defp new(user) do Req.new( base_url: @base_url, user_agent: @user_agent, cache: true, headers: [cookie: [cookies(%{bbuserid: user.id, bbpassword: user.hash})]] ) |> Req.Request.append_request_steps( time: fn req -> Req.Request.put_private(req, :time, Time.utc_now()) end ) |> Req.Request.prepend_response_steps( time: fn {req, res} -> start = req.private.time diff = Time.diff(Time.utc_now(), start, :millisecond) {req, Req.Response.put_private(res, :time, diff)} end ) end defp new() do Req.new( base_url: @base_url, user_agent: @user_agent, redirect: false ) end defp cookies(args) when is_map(args) do Enum.map_join(args, "; ", fn {k, v} -> "#{k}=#{v}" end) end end