hello slack

pull/337/head
connor rigby 2017-07-24 14:36:26 -07:00
parent 96e1b700e9
commit 79521805f1
7 changed files with 160 additions and 10 deletions

1
file.fw 100644
View File

@ -0,0 +1 @@
hello world

View File

@ -74,16 +74,18 @@ defmodule Farmbot.HTTP do
end
end
def download_file(ctx, url, path) do
case get(ctx, url, "", [], file: path) do
def download_file(ctx, url, path, payload \\ "", headers \\ [])
def download_file(ctx, url, path, payload, headers) do
case get(ctx, url, payload, headers, file: path) do
{:ok, %Response{status_code: code}} when is_2xx(code) -> {:ok, path}
{:ok, %Response{} = resp} -> {:error, resp}
{:error, reason} -> {:error, reason}
end
end
def download_file!(ctx, url, path) do
case download_file(ctx, url, path) do
def download_file!(ctx, url, path, payload \\ "", headers \\ [])
def download_file!(ctx, url, path, payload, headers) do
case download_file(ctx, url, path, payload, headers) do
{:ok, path} -> path
{:error, reason} -> raise Error, reason
end
@ -204,10 +206,12 @@ defmodule Farmbot.HTTP do
def handle_info(%AsyncChunk{chunk: chunk, id: ref}, state) do
case state.requests[ref] do
%Buffer{} = buffer ->
Process.cancel_timer(buffer.timeout)
timeout = Process.send_after(self(), {:timeout, ref}, 30_000)
maybe_log_progress(buffer)
maybe_stream_to_file(buffer.file, buffer.status_code, chunk)
HTTPoison.stream_next(%AsyncResponse{id: ref})
{:noreply, %{state | requests: %{state.requests | ref => %{buffer | data: buffer.data <> chunk}}}}
{:noreply, %{state | requests: %{state.requests | ref => %{buffer | data: buffer.data <> chunk, timeout: timeout}}}}
nil -> {:noreply, state}
end
end
@ -300,11 +304,12 @@ defmodule Farmbot.HTTP do
defp do_normal_request({method, url, body, headers, opts, from}, file, state) do
case HTTPoison.request(method, url, body, headers, opts) do
{:ok, %HTTPoison.Response{status_code: code, headers: resp_headers}} when code in @redirect_status_codes ->
{:ok, %HTTPoison.Response{status_code: code, headers: resp_headers} = resp} when code in @redirect_status_codes ->
redir = Enum.find_value(resp_headers, fn({header, val}) -> if header == "Location", do: val, else: false end)
if redir do
do_normal_request({method, redir, body, headers, opts, from}, file, state)
else
debug_log("Failed to redirect: #{inspect resp}")
GenServer.reply(from, {:error, :no_server_for_redirect})
{:noreply, state}
end
@ -360,10 +365,18 @@ defmodule Farmbot.HTTP do
defp finish_request(%Buffer{status_code: status_code} = buffer, state) when status_code in @redirect_status_codes do
debug_log "#{inspect Tuple.delete_at(buffer.from, 0)} Trying to redirect: (#{status_code})"
redir = Enum.find_value(buffer.headers, fn({header, val}) -> if header == "Location", do: val, else: false end)
redir = Enum.find_value(buffer.headers,
fn({header, val}) ->
case header do
"Location" -> val
"location" -> val
_ -> false
end
end)
if redir do
do_redirect_request(buffer, redir, state)
else
debug_log("Failed to redirect: #{inspect buffer}")
GenServer.reply(buffer.from, {:error, :no_server_for_redirect})
{:noreply, state}
end

View File

@ -280,7 +280,12 @@ defmodule Farmbot.System.Network do
else
def maybe_setup_rollbar(_), do: Logger.info ">> Not Setting up rollbar!"
def maybe_setup_rollbar(_) do
Logger.info ">> Not Setting up rollbar!"
Logger.info ">> Setting up slack updater"
Farmbot.System.NervesCommon.Updates.Slack.start_link(Farmbot.Context.new())
:ok
end
end

View File

@ -0,0 +1,130 @@
defmodule Farmbot.System.NervesCommon.Updates.Slack do
@moduledoc """
Development module for auto flashing fw updates.
"""
require Logger
use GenServer
alias Farmbot.{Context, HTTP, DebugLog}
use DebugLog
defmodule RTMSocket do
def start_link(url, cb) do
pid = spawn(__MODULE__, :socket_init, [url, cb])
{:ok, pid}
end
def socket_init("wss://" <> url, cb) do
[domain | rest] = String.split(url, "/")
domain
|> Socket.Web.connect!(secure: true, path: "/" <> Enum.join(rest, "/"))
|> socket_loop(cb)
end
def socket_init("ws://" <> url, cb) do
[domain | rest] = String.split(url, "/")
domain
|> Socket.Web.connect!(secure: false, path: "/" <> Enum.join(rest, "/"))
|> socket_loop(cb)
end
defp socket_loop(socket, cb) do
case socket |> Socket.Web.recv! do
{:text, data} -> data |> Poison.decode! |> handle_data(socket, cb)
{:ping, _} -> Socket.Web.send!(socket, {:pong, ""})
end
receive do
{:stop, _reason} ->
term_msg = %{
type: "message",
id: 2,
channel: "C58DCU4A3",
text: ":farmbot-genesis: #{node()} Disconnected!"
} |> Poison.encode!
Socket.Web.send!(socket, {:text, term_msg})
Socket.Web.close(socket)
data ->
Socket.Web.send!(socket, {:text, Poison.encode!(data)})
socket_loop(socket, cb)
after 500 -> socket_loop(socket, cb)
end
end
defp handle_data(%{"type" => "hello"}, socket, _) do
Logger.info ">> is connected to slack!", type: :success
msg = %{
type: "message",
id: 1,
channel: "C58DCU4A3",
text: ":farmbot-genesis: #{node()} Connected!"
} |> Poison.encode!()
Socket.Web.send!(socket, {:text, msg})
end
defp handle_data(msg, _socket, cb), do: send(cb, {:socket, msg})
end
@token System.get_env("SLACK_TOKEN")
def start_link(%Context{} = context, opts \\ []) do
GenServer.start_link(__MODULE__, {context, @token}, opts)
end
def init({_, nil}) do
:ignore
end
def init({context, token}) do
debug_log "Using token: #{token}"
url = "https://slack.com/api/rtm.connect"
payload = {:multipart, [{"token", token}]}
headers = [{'User-Agent', 'Farmbot HTTP Adapter'}]
case HTTP.post(context, url, payload, headers) do
{:ok, %{status_code: 200, body: body}} ->
{:ok, rtm_socket} =
body
|> Poison.decode!
|> ensure_good_login
|> Map.get("url")
|> RTMSocket.start_link(self())
{:ok, %{rtm_socket: rtm_socket, context: context, token: token}}
err ->
debug_log "Failed to get RTM Auth: #{inspect err}"
:ignore
end
end
defp ensure_good_login(%{"ok" => true} = msg), do: msg
defp ensure_good_login(msg) do
raise("failed to auth: #{inspect msg}")
end
def handle_info({:socket, %{"channel" => "C41SHHGQ5",
"file" => %{"url_private_download" => dl_url,
"name" => name,
"channels" => ["C41SHHGQ5"],
}
}
} = msg, state)
do
if Path.extname(name) == ".fw" do
Logger.info ">> is downloading and applying an immage from slack!", type: :busy
path = HTTP.download_file!(state.context, dl_url, "/tmp/#{name}", [], [{'Authorization', 'Bearer #{state.token}'}])
Farmbot.System.Updates.setup_post_update()
Nerves.Firmware.upgrade_and_finalize(path)
Farmbot.System.reboot()
{:stop, :normal, state}
else
{:noreply, state}
end
end
def handle_info({:socket, _msg}, state) do
{:noreply, state}
end
def terminate(reason, state) do
send state.rtm_socket, {:stop, reason}
end
end

View File

@ -19,7 +19,6 @@ defmodule Mix.Tasks.Farmbot.Slack do
commit = Mix.Project.config[:commit]
fw_file = Path.join(["images", "#{Mix.env()}", "#{target}",
(if signed?, do: "#{otp_app}-signed.fw", else: "#{otp_app}.fw")])
# fw_file = "/tmp/hello.txt"
unless File.exists?(fw_file) do
Mix.raise "Could not find firmware: #{fw_file}"
@ -34,7 +33,6 @@ defmodule Mix.Tasks.Farmbot.Slack do
url = "https://slack.com/api/files.upload"
form_data = %{
"file" => "replace_me",
:file => fw_file,
"token" => token,
"channels" => "embedded-systems",

View File

@ -110,6 +110,7 @@ defmodule Farmbot.Mixfile do
:timex, # Timex needs to start AFTER farmbot, so we can set up its dirs,
:inets,
:ssl,
:socket,
:redix,
:eex,
:httpoison
@ -143,6 +144,7 @@ defmodule Farmbot.Mixfile do
{:exjsx, "~> 3.2", override: true},
{:rsa, "~> 0.0.1"},
{:httpoison, "~> 0.12"},
{:socket, "~> 0.3"},
# {:hackney, path: "../hackney", override: true},
# MQTT stuff

View File

@ -63,6 +63,7 @@
"redix": {:hex, :redix, "0.5.1", "2bf874a186cc759791b8defdd0bfaa752784716bd48241f6aa972a20e7f95745", [:mix], [{:connection, "~> 1.0", [hex: :connection, optional: false]}]},
"rollbax": {:hex, :rollbax, "0.8.2", "204a47a83fe32745def19ea0307b297395c00315fb85f30dfda04d5009b5ecb9", [:mix], [{:hackney, "~> 1.1", [hex: :hackney, repo: "hexpm", optional: false]}, {:poison, "~> 1.4 or ~> 2.0 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"},
"rsa": {:hex, :rsa, "0.0.1", "a63069f88ce342ffdf8448b7cdef4b39ba7dee3c1510644a39385c7e63ba246f", [:mix], []},
"socket": {:hex, :socket, "0.3.12", "4a6543815136503fee67eff0932da1742fad83f84c49130c854114153cc549a6", [:mix], []},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], []},
"syslog": {:hex, :syslog, "1.0.2", "9cf72c0986675a170c03b210e49700845a0f7b61e96d302a3ba0df82963daf60", [:rebar], []},
"system_registry": {:hex, :system_registry, "0.1.2", "b6dba36c575786f1848e18a1155a2b6bd82f607f0ae9dc88185d6b7dc3fcdf60", [:mix], []},