日本語で書かれた記事を海外のトモダチに英語で伝えたい

# はじめに
- [Nerves Newsletter](https://embedded-elixir.com/page/newsletter/)[^1]という全編英語のニュースレターに日本語の記事が取り上げられていました
    - https://translate.google.com/translate?hl=en&sl=ja&u=$url
    - こんな感じです
- そうだ！　海外のトモダチにJapanには[Nerves](https://www.nerves-project.org/)の記事がありますよ〜 をGoogle translateにURLをくっつけた一覧でお伝えしたいと@kikuyuta 先生が発案されました
- 一覧にするならタイトルも日本語→英語にしておきたいところです
- そうだ！ Googleスプレッドシートの`=googletranslate(A2, "ja", "en")`みたいなことをすればいいや！
    - この技は@zacky1972 先生に教えてもらいました
    - https://support.google.com/docs/answer/3093331?hl=ja
- これらをやってみました〜　ということを記事にしてみました
- この記事は2021/06/26(土) 00:00 〜 2021/06/28(月) 23:59開催の[autoracex #34](https://autoracex.connpass.com/event/217443/)という純粋なもくもく会での成果です

[^1]: [Nerves Newsletter](https://embedded-elixir.com/page/newsletter/)の[申し込みフォーム](https://www.nerves-project.org/#subForm)

# 作ってみる
- https://qiita.com/settings/tokens/new からアクセストークンをつくります
    - `read_qiita`
- QIITA_READ環境変数をセットします
- Elixir 1.12をインストールしておきます

## ソースコードを書く

```elixir:links.exs
# Elixir 1.12 !!!
# usage:
# set QIITA_READ
# $ elixir links.exs
# $ cat output.tsv | pbcopy
# paste Google spread sheet

Mix.install([
  {:httpoison, "~> 1.8"},
  {:jason, "~> 1.2"},
  {:timex, "~> 3.7"},
  {:nimble_csv, "~> 1.1"}
])

defmodule Qiita.Api do
  @token System.get_env("QIITA_READ")
  @headers [
    Authorization: "Bearer #{@token}",
    Accept: "Application/json; Charset=utf-8",
    "Content-Type": "application/json"
  ]
  @options [timeout: 50_000, recv_timeout: 50_000]
  @base_url "https://qiita.com/api/v2"
  @per_page 100

  def items(tags) when is_list(tags) do
    query(tags)
    |> do_items()
  end

  def items(query) when is_bitstring(query) do
    %{"query" => query}
    |> URI.encode_query()
    |> do_items()
  end

  defp do_items(query) do
    total_count(query) |> max_page() |> do_items(query)
  end

  defp do_items(0, _query), do: []

  defp do_items(max_page, query) do
    1..max_page
    |> Enum.reduce([], fn page, acc ->
      "#{@base_url}/items?#{query}&per_page=#{@per_page}&page=#{page}"
      |> HTTPoison.get!(@headers, @options)
      |> Map.get(:body)
      |> Jason.decode()
      |> handle_json_decode()
      |> then(& acc ++ &1)
    end)
  end

  defp query(tags) do
    %{"query" => tags |> Enum.map(&"tag:#{&1}") |> Enum.join(" ")}
    |> URI.encode_query()
  end

  defp total_count(query) do
    "#{@base_url}/items?#{query}&per_page=1"
    |> HTTPoison.get!(@headers, @options)
    |> Map.get(:headers)
    |> Enum.filter(fn {key, _} -> key == "Total-Count" end)
    |> Enum.at(0)
    |> elem(1)
    |> String.to_integer()
  end

  defp max_page(total_count) when rem(total_count, @per_page) == 0 do
    div(total_count, @per_page)
    |> min(100)
  end

  defp max_page(total_count) do
    (div(total_count, @per_page) + 1)
    |> min(100)
  end

  defp handle_json_decode({:error, _}), do: []

  defp handle_json_decode({:ok, map}) do
    Enum.map(
      map,
      &Map.take(&1, [
        "title",
        "likes_count",
        "updated_at",
        "created_at",
        "url",
        "user",
        "tags",
        "private"
      ])
    )
    |> Enum.map(fn %{
                     "user" => %{"id" => user_id},
                     "updated_at" => updated_at,
                     "created_at" => created_at,
                     "tags" => tags
                   } = item ->
      updated_at = Timex.parse!(updated_at, "{ISO:Extended}") |> Timex.to_datetime()
      created_at = Timex.parse!(created_at, "{ISO:Extended}") |> Timex.to_datetime()
      tags = Enum.map(tags, &Map.get(&1, "name"))

      item
      |> Map.delete("user")
      |> Map.delete("tags")
      |> Map.merge(%{
        "user_id" => user_id,
        "updated_at" => updated_at,
        "created_at" => created_at,
        "tags" => tags
      })
    end)
    |> Enum.reject(&Map.get(&1, "private"))
  end
end


# Run

items =
  Qiita.Api.items("Nerves")
  |> Enum.with_index(2)
  |> Enum.map(fn {%{"title" => title, "likes_count" => likes_count, "url" => url, "user_id" => user_id}, index} ->
    [title, "=googletranslate(A#{index}, \"ja\", \"en\")", user_id, likes_count, "https://translate.google.com/translate?hl=en&sl=ja&u=#{url}"]
  end)


NimbleCSV.define(MyParser, separator: "\t")

MyParser.dump_to_iodata([~w(title googletranslate user_id likes_count url)] ++ items)
|> IO.iodata_to_binary()
|> then(& File.write("output.tsv", &1))
```

## Run

```
$ elixir links.exs
```

- `output.tsv`の内容をGoogleスプレッドシートにはりましょう
- そうするとこんな感じの一覧が得られます :tada::tada::tada:

![スクリーンショット 2021-06-24 21.23.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131808/ebc40a18-29b2-ac2e-4d56-754d132410ac.png)

# Wrapping up :lgtm::lgtm::lgtm::lgtm:
- [Nerves](https://www.nerves-project.org/)は[Elixir](https://elixir-lang.org/)でIoTを楽しめる、[**ナウでヤングでcoolな**](https://www.slideshare.net/takasehideki/elixiriotcoolnerves-236780506)なすごいヤツです
- 気になる方はぜひ[Nerves JP](https://join.slack.com/t/nerves-jp/shared_invite/enQtNzc0NTM1OTA5MzQ1LTg5NTAyYThiYzRlNDRmNDIwM2ZlZTJiZDc1MmE5NTFjYzA5OTE4ZTM5OWQxODFhZjY1NWJmZTc4NThkMjQ1Yjk)に**ご参加(れっつじょいなす)**してください
    - https://join.slack.com/t/nerves-jp/shared_invite/enQtNzc0NTM1OTA5MzQ1LTg5NTAyYThiYzRlNDRmNDIwM2ZlZTJiZDc1MmE5NTFjYzA5OTE4ZTM5OWQxODFhZjY1NWJmZTc4NThkMjQ1Yjk
- 愉快なfolksがあたなの訪れを待っています:rocket::rocket::rocket:


![https___qiita-user-contents.imgix.net_https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F240349%2F5ef22bb9-f357-778c-1bff-b018cce54948.png_ixlib=rb-1.2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131808/efe3084e-4891-9aa2-0ee3-e053c990ba4c.png)