Initial commit

This commit is contained in:
Adam Millerchip 2018-11-30 15:36:39 +09:00
commit 39d9292f1c
11 changed files with 225 additions and 0 deletions

5
.formatter.exs Normal file
View file

@ -0,0 +1,5 @@
# Used by "mix format"
[
inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}"],
locals_without_parens: [plug: 1, plug: 2]
]

24
.gitignore vendored Normal file
View file

@ -0,0 +1,24 @@
# The directory Mix will write compiled artifacts to.
/_build/
# If you run "mix test --cover", coverage assets end up here.
/cover/
# The directory Mix downloads your dependencies sources to.
/deps/
# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/
# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch
# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump
# Also ignore archive artifacts (built via "mix archive.build").
*.ez
# Ignore package tarball (built via "mix hex.build").
advent-*.tar

3
README.md Normal file
View file

@ -0,0 +1,3 @@
# Advent
An Example Clova Skill written in Elixir

31
config/config.exs Normal file
View file

@ -0,0 +1,31 @@
# This file is responsible for configuring your application
# and its dependencies with the aid of the Mix.Config module.
use Mix.Config
config :advent, force_signature_valid: Mix.env() !== :prod
# This configuration is loaded before any dependency and is restricted
# to this project. If another project depends on this project, this
# file won't be loaded nor affect the parent project. For this reason,
# if you want to provide default values for your application for
# 3rd-party users, it should be done in your "mix.exs" file.
# You can configure your application as:
#
# config :advent, key: :value
#
# and access this configuration in your application as:
#
# Application.get_env(:advent, :key)
#
# You can also configure a 3rd-party app:
#
# config :logger, level: :info
#
# It is also possible to import configuration files, relative to this
# directory. For example, you can emulate configuration per environment
# by uncommenting the line below and defining dev.exs, test.exs and such.
# Configuration from the imported file will override the ones defined
# here (which is why it is important to import them last).
#
# import_config "#{Mix.env()}.exs"

58
lib/advent.ex Normal file
View file

@ -0,0 +1,58 @@
defmodule Advent do
use Clova
def handle_launch(_req, resp) do
resp
|> add_speech("今日は#{say_date(today())}です")
|> add_speech(days_to_christmas() |> say_days_to_christmas())
|> add_speech(prompt_for_another())
end
def handle_intent("different_day", req, resp) do
with potential_date when not is_nil(potential_date) <- get_slot(req, "date"),
{:ok, date} <- Date.from_iso8601(potential_date) do
resp
|> add_speech("#{say_date(date)}まで計算しますか?")
|> put_session_attributes(%{"date" => date})
|> add_reprompt("#{date.month}#{date.day}日まで計算したい場合、「はい」と言ってください。")
|> add_reprompt(prompt_for_another())
else
_ -> add_speech(resp, "それは日付だと思いますがもっとわかりやすく言ってくださいね")
end
end
def handle_intent("Clova.YesIntent", req, resp) do
with %{"date" => iso_date} <- get_session_attributes(req),
{:ok, date} <- Date.from_iso8601(iso_date) do
resp
|> add_speech(say_days_to(date))
|> add_speech(prompt_for_another())
else
_ -> end_session(resp)
end
end
def handle_intent(_name, _req, resp), do: end_session(resp)
defp prompt_for_another(), do: "違う日まで計算したい場合、日付けを言ってください"
defp say_days_to_christmas(0), do: "クリスマスの日です!メリークリスマス!"
defp say_days_to_christmas(days) when days < 0, do: "クリスマスはもうすぎました。来年まで楽しみましょう。"
defp say_days_to_christmas(days), do: "クリスマスまであと#{days}日です!"
defp today, do: Timex.now("Asia/Tokyo") |> DateTime.to_date()
defp say_date(date), do: "#{date.year}#{date.month}#{date.day}"
defp days_to(date), do: Date.diff(date, today())
defp say_days_to(date), do: say_days_to(date, days_to(date))
defp say_days_to(date, 0), do: "#{say_date(date)}は今日です!"
defp say_days_to(date, days) when days < 0, do: "#{say_date(date)}から#{-days}日すぎました。"
defp say_days_to(date, days), do: "#{say_date(date)}まであと#{days}日です。"
defp days_to_christmas do
{:ok, xmas} = Date.new(today().year, 12, 25)
days_to(xmas)
end
end

19
lib/advent/application.ex Normal file
View file

@ -0,0 +1,19 @@
defmodule Advent.Application do
# See https://hexdocs.pm/elixir/Application.html
# for more information on OTP Applications
@moduledoc false
use Application
def start(_type, _args) do
# List all child processes to be supervised
children = [
{Plug.Adapters.Cowboy, scheme: :http, plug: Advent.Router, options: [port: 4000]}
]
# See https://hexdocs.pm/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :one_for_one, name: Advent.Supervisor]
Supervisor.start_link(children, opts)
end
end

26
lib/advent/router.ex Normal file
View file

@ -0,0 +1,26 @@
defmodule Advent.Router do
use Plug.Router
use Plug.ErrorHandler
plug Plug.Logger
plug Clova.SkillPlug,
dispatch_to: Advent,
app_id: "com.example.advent",
json_module: Poison,
force_signature_valid: Application.get_env(:advent, :force_signature_valid, false)
plug :match
plug :dispatch
post "/clova" do
send_resp(conn)
end
match("/clova", do: send_resp(conn, :method_not_allowed, ""))
match(_, do: send_resp(conn, :not_found, ""))
def handle_errors(conn, %{kind: :error, reason: reason}) do
send_resp(conn, conn.status, Exception.message(reason))
end
end

31
mix.exs Normal file
View file

@ -0,0 +1,31 @@
defmodule Advent.MixProject do
use Mix.Project
def project do
[
app: :advent,
version: "0.1.0",
elixir: "~> 1.7",
start_permanent: Mix.env() == :prod,
deps: deps()
]
end
# Run "mix help compile.app" to learn about applications.
def application do
[
extra_applications: [:logger],
mod: {Advent.Application, []}
]
end
# Run "mix help deps" to learn about dependencies.
defp deps do
[
{:clova, "~> 0.5.0"},
{:plug_cowboy, "~> 2.0"},
{:poison, "~> 3.1"},
{:timex, "~> 3.4.2"}
]
end
end

23
mix.lock Normal file
View file

@ -0,0 +1,23 @@
%{
"certifi": {:hex, :certifi, "2.4.2", "75424ff0f3baaccfd34b1214184b6ef616d89e420b258bb0a5ea7d7bc628f7f0", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"},
"clova": {:hex, :clova, "0.5.0", "899ddfda81fcc2a10d0cceb571f8f429d4c0ca152b8c83cc33769b1b28a631c9", [:mix], [{:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
"combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm"},
"cowboy": {:hex, :cowboy, "2.6.0", "dc1ff5354c89e36a3e3ef8d10433396dcff0dcbb1d4223b58c64c2d51a6d88d9", [:rebar3], [{:cowlib, "~> 2.7.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
"cowlib": {:hex, :cowlib, "2.7.0", "3ef16e77562f9855a2605900cedb15c1462d76fb1be6a32fc3ae91973ee543d2", [:rebar3], [], "hexpm"},
"gettext": {:hex, :gettext, "0.16.1", "e2130b25eebcbe02bb343b119a07ae2c7e28bd4b146c4a154da2ffb2b3507af2", [:mix], [], "hexpm"},
"hackney": {:hex, :hackney, "1.14.3", "b5f6f5dcc4f1fba340762738759209e21914516df6be440d85772542d4a5e412", [:rebar3], [{:certifi, "2.4.2", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.4", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
"idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"},
"mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm"},
"mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"},
"parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm"},
"plug": {:hex, :plug, "1.7.1", "8516d565fb84a6a8b2ca722e74e2cd25ca0fc9d64f364ec9dbec09d33eb78ccd", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}], "hexpm"},
"plug_cowboy": {:hex, :plug_cowboy, "2.0.0", "ab0c92728f2ba43c544cce85f0f220d8d30fc0c90eaa1e6203683ab039655062", [:mix], [{:cowboy, "~> 2.5", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
"plug_crypto": {:hex, :plug_crypto, "1.0.0", "18e49317d3fa343f24620ed22795ec29d4a5e602d52d1513ccea0b07d8ea7d4d", [:mix], [], "hexpm"},
"poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm"},
"ranch": {:hex, :ranch, "1.7.0", "9583f47160ca62af7f8d5db11454068eaa32b56eeadf984d4f46e61a076df5f2", [:rebar3], [], "hexpm"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.4", "f0eafff810d2041e93f915ef59899c923f4568f4585904d010387ed74988e77b", [:make, :mix, :rebar3], [], "hexpm"},
"timex": {:hex, :timex, "3.4.2", "d74649c93ad0e12ce5b17cf5e11fbd1fb1b24a3d114643e86dba194b64439547", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm"},
"tzdata": {:hex, :tzdata, "0.5.19", "7962a3997bf06303b7d1772988ede22260f3dae1bf897408ebdac2b4435f4e6a", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"},
}

4
test/advent_test.exs Normal file
View file

@ -0,0 +1,4 @@
defmodule AdventTest do
use ExUnit.Case
doctest Advent
end

1
test/test_helper.exs Normal file
View file

@ -0,0 +1 @@
ExUnit.start()