From 53017cdffe33bf6f04fa7fcf0620442f44f35523 Mon Sep 17 00:00:00 2001 From: Kian-Meng Ang Date: Tue, 25 May 2021 22:01:07 +0800 Subject: [PATCH] Misc doc changes Besides other documentation changes, this commit ensures the generated HTML doc for HexDocs.pm will become the main reference doc for this Elixir library which leverage on latest features of ExDoc. --- .gitignore | 29 ++++++++++++-- LICENSE => LICENSE.md | 0 README.md | 53 ++++++++++++++++---------- lib/recaptcha.ex | 11 +++--- lib/recaptcha/config.ex | 4 +- lib/recaptcha/http.ex | 27 ++++++------- lib/recaptcha/http/mock_http_client.ex | 2 +- lib/recaptcha/response.ex | 2 +- lib/recaptcha/template.ex | 12 +++--- mix.exs | 27 ++++++++++--- mix.lock | 11 +++--- 11 files changed, 115 insertions(+), 63 deletions(-) rename LICENSE => LICENSE.md (100%) diff --git a/.gitignore b/.gitignore index bd69ce7..13c16d9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,26 @@ -/_build +# 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 third-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 -/deps -/doc -/cover + +# Also ignore archive artifacts (built via "mix archive.build"). +*.ez + +# Ignore package tarball (built via "mix hex.build"). +recaptcha-*.tar + +# Temporary files for e.g. tests. +/tmp/ diff --git a/LICENSE b/LICENSE.md similarity index 100% rename from LICENSE rename to LICENSE.md diff --git a/README.md b/README.md index 08fc10f..83dcabc 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,11 @@ [![Build Status](https://travis-ci.org/samueljseay/recaptcha.svg?branch=master)](https://travis-ci.org/samueljseay/recaptcha) [![Coverage Status](https://coveralls.io/repos/github/samueljseay/recaptcha/badge.svg?branch=master)](https://coveralls.io/github/samueljseay/recaptcha) -[![Hex.pm](https://img.shields.io/badge/Hex-v2.1.1-green.svg)](https://hexdocs.pm/recaptcha) +[![Module Version](https://img.shields.io/hexpm/v/recaptcha.svg)](https://hex.pm/packages/recaptcha) +[![Hex Docs](https://img.shields.io/badge/hex-docs-lightgreen.svg)](https://hexdocs.pm/recaptcha/) +[![Total Download](https://img.shields.io/hexpm/dt/recaptcha.svg)](https://hex.pm/packages/recaptcha) +[![License](https://img.shields.io/hexpm/l/recaptcha.svg)](https://github.com/samueljseay/recaptcha/blob/master/LICENSE) +[![Last Updated](https://img.shields.io/github/last-commit/samueljseay/recaptcha.svg)](https://github.com/samueljseay/recaptcha/commits/master) A simple Elixir package for implementing [reCAPTCHA] in Elixir applications. @@ -20,7 +24,7 @@ if you have any problems with migrating. ## Installation -1. Add recaptcha to your `mix.exs` dependencies +Add `:recaptcha` to your `mix.exs` dependencies: ```elixir defp deps do @@ -30,24 +34,26 @@ if you have any problems with migrating. end ``` -2. List `:recaptcha` as an application dependency +List `:recaptcha` as an application dependency: ```elixir def application do - [ extra_applications: [:recaptcha] ] + [ + extra_applications: [:recaptcha] + ] end ``` -3. Run `mix do deps.get, compile` +Run `mix do deps.get, compile` ## Config By default the public and private keys are loaded via the `RECAPTCHA_PUBLIC_KEY` and `RECAPTCHA_PRIVATE_KEY` environment variables. ```elixir - config :recaptcha, - public_key: {:system, "RECAPTCHA_PUBLIC_KEY"}, - secret: {:system, "RECAPTCHA_PRIVATE_KEY"} +config :recaptcha, + public_key: {:system, "RECAPTCHA_PUBLIC_KEY"}, + secret: {:system, "RECAPTCHA_PRIVATE_KEY"} ``` ### JSON Decoding @@ -55,7 +61,7 @@ By default the public and private keys are loaded via the `RECAPTCHA_PUBLIC_KEY` By default `reCaptcha` will use `Jason` to decode JSON responses, this can be changed as such: ```elixir - config :recaptcha, :json_library, Poison +config :recaptcha, :json_library, Poison ``` ## Usage @@ -64,7 +70,8 @@ By default `reCaptcha` will use `Jason` to decode JSON responses, this can be ch Use `raw` (if you're using Phoenix.HTML) and `Recaptcha.Template.display/1` methods to render the captcha widget. -For recaptcha with checkbox +For recaptcha with checkbox: + ```html
... @@ -73,7 +80,8 @@ For recaptcha with checkbox
``` -For invisible recaptcha +For invisible recaptcha: + ```html
... @@ -84,7 +92,7 @@ For invisible recaptcha To change the position of the invisible recaptcha, use an option badge. See https://developers.google.com/recaptcha/docs/invisible on the date-badge. -Since recaptcha loads Javascript code asynchronously, you cannot immediately submit the captcha form. +Since recaptcha loads JavaScript code asynchronously, you cannot immediately submit the captcha form. If you have logic that needs to know if the captcha code has already been loaded (for example disabling submit button until fully loaded), it is possible to pass in a JS-callback that will be called once the captcha has finished loading. This can be done as follows: @@ -117,12 +125,12 @@ Option | Action Recaptcha provides the `verify/2` method. Below is an example using a Phoenix controller action: ```elixir - def create(conn, params) do - case Recaptcha.verify(params["g-recaptcha-response"]) do - {:ok, response} -> do_something - {:error, errors} -> handle_error - end +def create(conn, params) do + case Recaptcha.verify(params["g-recaptcha-response"]) do + {:ok, response} -> do_something + {:error, errors} -> handle_error end +end ``` `verify` method sends a `POST` request to the reCAPTCHA API and returns 2 possible values: @@ -144,14 +152,14 @@ Option | Action In order to test your endpoints you should set the secret key to the following value in order to receive a positive result from all queries to the Recaptcha engine. -``` +```elixir config :recaptcha, secret: "6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe" ``` Setting up tests without network access can be done also. When configured as such a positive or negative result can be generated locally. -``` +```elixir config :recaptcha, http_client: Recaptcha.Http.MockClient, secret: "6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe" @@ -167,6 +175,9 @@ config :recaptcha, Check out [CONTRIBUTING.md](/CONTRIBUTING.md) if you want to help. -## License +## Copyright and License + +Copyright (c) 2016 Samuel Seay -[MIT License](http://www.opensource.org/licenses/MIT). +This library is released under the MIT License. See the [LICENSE.md](./LICENSE.md) file +for further details. diff --git a/lib/recaptcha.ex b/lib/recaptcha.ex index 38c1f89..41661b4 100644 --- a/lib/recaptcha.ex +++ b/lib/recaptcha.ex @@ -1,9 +1,9 @@ defmodule Recaptcha do @moduledoc """ - A module for verifying reCAPTCHA version 2.0 response strings. + A module for verifying reCAPTCHA version 2.0 response strings. - See the [documentation](https://developers.google.com/recaptcha/docs/verify) - for more details. + See the [documentation](https://developers.google.com/recaptcha/docs/verify) + for more details. """ alias Recaptcha.{Config, Http, Response} @@ -20,9 +20,10 @@ defmodule Recaptcha do provided in application config) * `:remote_ip` - the IP address of the user (optional and not set by default) - ## Example + ## Examples + + {:ok, api_response} = Recaptcha.verify("response_string") - {:ok, api_response} = Recaptcha.verify("response_string") """ @spec verify(String.t(), Keyword.t()) :: {:ok, Response.t()} | {:error, [atom]} diff --git a/lib/recaptcha/config.ex b/lib/recaptcha/config.ex index 3a6b0d7..a7b73bf 100644 --- a/lib/recaptcha/config.ex +++ b/lib/recaptcha/config.ex @@ -1,10 +1,10 @@ defmodule Recaptcha.Config do @moduledoc """ - Provides application/system environment variable lookup at runtime + Provides application/system environment variable lookup at runtime. """ @doc """ - Returns the requested variable + Returns the requested variable. """ @spec get_env(atom, atom, any) :: any def get_env(application, key, default \\ nil) do diff --git a/lib/recaptcha/http.ex b/lib/recaptcha/http.ex index 6699fd6..f2734d9 100644 --- a/lib/recaptcha/http.ex +++ b/lib/recaptcha/http.ex @@ -1,6 +1,6 @@ defmodule Recaptcha.Http do @moduledoc """ - Responsible for managing HTTP requests to the reCAPTCHA API + Responsible for managing HTTP requests to the reCAPTCHA API. """ alias Recaptcha.Config @@ -22,18 +22,19 @@ defmodule Recaptcha.Http do * `:timeout` - the timeout for the request (defaults to 5000ms) - ## Example - - {:ok, %{ - "success" => success, - "challenge_ts" => ts, - "hostname" => host, - "error-codes" => errors - }} = Recaptcha.Http.request_verification(%{ - secret: "secret", - response: "response", - remote_ip: "remote_ip" - }) + ## Examples + + {:ok, %{ + "success" => success, + "challenge_ts" => ts, + "hostname" => host, + "error-codes" => errors + }} = Recaptcha.Http.request_verification(%{ + secret: "secret", + response: "response", + remote_ip: "remote_ip" + }) + """ @spec request_verification(binary, Keyword.t) :: {:ok, map} | {:error, [atom]} def request_verification(body, options \\ []) do diff --git a/lib/recaptcha/http/mock_http_client.ex b/lib/recaptcha/http/mock_http_client.ex index 81b88a1..4158700 100644 --- a/lib/recaptcha/http/mock_http_client.ex +++ b/lib/recaptcha/http/mock_http_client.ex @@ -1,6 +1,6 @@ defmodule Recaptcha.Http.MockClient do @moduledoc """ - A mock HTTP client used for testing. + A mock HTTP client used for testing. """ alias Recaptcha.Http diff --git a/lib/recaptcha/response.ex b/lib/recaptcha/response.ex index 72ac4e0..2d190a1 100644 --- a/lib/recaptcha/response.ex +++ b/lib/recaptcha/response.ex @@ -1,6 +1,6 @@ defmodule Recaptcha.Response do @moduledoc """ - A struct representing the successful recaptcha response from the reCAPTCHA API. + A struct representing the successful recaptcha response from the reCAPTCHA API. """ defstruct challenge_ts: "", hostname: "" diff --git a/lib/recaptcha/template.ex b/lib/recaptcha/template.ex index 3e5d477..5725bc6 100644 --- a/lib/recaptcha/template.ex +++ b/lib/recaptcha/template.ex @@ -1,11 +1,11 @@ defmodule Recaptcha.Template do @moduledoc """ - Responsible for rendering boilerplate recaptcha HTML code, supports noscript fallback. + Responsible for rendering boilerplate recaptcha HTML code, supports noscript fallback. - [Some](https://developers.google.com/recaptcha/docs/display#explicit_render) - functionality is not currently supported. + [Some](https://developers.google.com/recaptcha/docs/display#explicit_render) + functionality is not currently supported. - In future this module may be separated out into a Phoenix specific library. + In future this module may be separated out into a Phoenix specific library. """ require Elixir.EEx alias Recaptcha.Config @@ -15,9 +15,9 @@ defmodule Recaptcha.Template do ]) @doc """ - Returns a string with reCAPTCHA code + Returns a string with reCAPTCHA code. - To convert the string to html code, use Phoenix.HTML.Raw/1 method + To convert the string to html code, use `Phoenix.HTML.Raw/1` method. """ def display(options \\ []) do public_key = diff --git a/mix.exs b/mix.exs index 395ad93..7f10dcc 100644 --- a/mix.exs +++ b/mix.exs @@ -1,14 +1,17 @@ defmodule Recaptcha.Mixfile do use Mix.Project + @source_url "https://github.com/samueljseay/recaptcha" + @version "3.0.0" + def project do [ app: :recaptcha, - version: "3.0.0", + version: @version, elixir: "~> 1.6", - description: description(), deps: deps(), package: package(), + docs: docs(), build_embedded: Mix.env() == :prod, start_permanent: Mix.env() == :prod, @@ -35,8 +38,6 @@ defmodule Recaptcha.Mixfile do defp description do """ - A simple reCaptcha package for Elixir applications, provides verification - and templates for rendering forms with the reCaptcha widget """ end @@ -45,7 +46,7 @@ defmodule Recaptcha.Mixfile do {:httpoison, ">= 0.12.0"}, {:jason, "~> 1.1.0", optional: true}, {:credo, "~> 1.0", only: [:dev, :test], runtime: false}, - {:ex_doc, ">= 0.0.0", only: :dev}, + {:ex_doc, ">= 0.0.0", only: :dev, runtime: false}, {:dialyxir, "~> 0.5", only: [:dev]}, {:excoveralls, "~> 0.7.1", only: :test} ] @@ -53,10 +54,26 @@ defmodule Recaptcha.Mixfile do defp package do [ + description: "A simple reCaptcha package for Elixir applications, provides verification " + <> "and templates for rendering forms with the reCaptcha widget.", files: ["lib", "mix.exs", "README.md", "LICENSE"], maintainers: ["Samuel Seay", "Nikita Sobolev", "Michael JustMikey"], licenses: ["MIT"], links: %{"GitHub" => "https://github.com/samueljseay/recaptcha"} ] end + + defp docs do + [ + extras: [ + "CONTRIBUTING.md", + "LICENSE.md": [title: "License"], + "README.md": [title: "Overview"] + ], + main: "readme", + source_url: @source_url, + source_ref: @version, + formatters: ["html"] + ] + end end diff --git a/mix.lock b/mix.lock index 3b5f3b5..73ed202 100644 --- a/mix.lock +++ b/mix.lock @@ -3,8 +3,8 @@ "certifi": {:hex, :certifi, "2.5.2", "b7cfeae9d2ed395695dd8201c57a2d019c0c43ecaf8b8bcb9320b40d6662f340", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm", "3b3b5f36493004ac3455966991eaf6e768ce9884693d9968055aeeeb1e575040"}, "credo": {:hex, :credo, "1.4.0", "92339d4cbadd1e88b5ee43d427b639b68a11071b6f73854e33638e30a0ea11f5", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "1fd3b70dce216574ce3c18bdf510b57e7c4c85c2ec9cad4bff854abaf7e58658"}, "dialyxir": {:hex, :dialyxir, "0.5.1", "b331b091720fd93e878137add264bac4f644e1ddae07a70bf7062c7862c4b952", [:mix], [], "hexpm", "6c32a70ed5d452c6650916555b1f96c79af5fc4bf286997f8b15f213de786f73"}, - "earmark_parser": {:hex, :earmark_parser, "1.4.10", "6603d7a603b9c18d3d20db69921527f82ef09990885ed7525003c7fe7dc86c56", [:mix], [], "hexpm", "8e2d5370b732385db2c9b22215c3f59c84ac7dda7ed7e544d7c459496ae519c0"}, - "ex_doc": {:hex, :ex_doc, "0.22.2", "03a2a58bdd2ba0d83d004507c4ee113b9c521956938298eba16e55cc4aba4a6c", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "cf60e1b3e2efe317095b6bb79651f83a2c1b3edcb4d319c421d7fcda8b3aff26"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.13", "0c98163e7d04a15feb62000e1a891489feb29f3d10cb57d4f845c405852bbef8", [:mix], [], "hexpm", "d602c26af3a0af43d2f2645613f65841657ad6efc9f0e361c3b6c06b578214ba"}, + "ex_doc": {:hex, :ex_doc, "0.24.2", "e4c26603830c1a2286dae45f4412a4d1980e1e89dc779fcd0181ed1d5a05c8d9", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "e134e1d9e821b8d9e4244687fb2ace58d479b67b282de5158333b0d57c6fb7da"}, "excoveralls": {:hex, :excoveralls, "0.7.5", "339e433e5d3bce09400dc8de7b9040741a409c93917849916c136a0f51fdc183", [:mix], [{:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "36422936691b6a8a728fe42c528e7b2719b2fde1a56d19fc7e3de31cb2271017"}, "exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm", "32e95820a97cffea67830e91514a2ad53b888850442d6d395f53a1ac60c82e07"}, "hackney": {:hex, :hackney, "1.16.0", "5096ac8e823e3a441477b2d187e30dd3fff1a82991a806b2003845ce72ce2d84", [:rebar3], [{:certifi, "2.5.2", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.1", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.0", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.6", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "3bf0bebbd5d3092a3543b783bf065165fa5d3ad4b899b836810e513064134e18"}, @@ -12,11 +12,12 @@ "idna": {:hex, :idna, "6.0.1", "1d038fb2e7668ce41fbf681d2c45902e52b3cb9e9c77b55334353b222c2ee50c", [:rebar3], [{:unicode_util_compat, "0.5.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a02c8a1c4fd601215bb0b0324c8a6986749f807ce35f25449ec9e69758708122"}, "jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fdf843bca858203ae1de16da2ee206f53416bbda5dc8c9e78f43243de4bc3afe"}, "jsx": {:hex, :jsx, "2.8.3", "a05252d381885240744d955fbe3cf810504eb2567164824e19303ea59eef62cf", [:mix, :rebar3], [], "hexpm", "fc3499fed7a726995aa659143a248534adc754ebd16ccd437cd93b649a95091f"}, - "makeup": {:hex, :makeup, "1.0.3", "e339e2f766d12e7260e6672dd4047405963c5ec99661abdc432e6ec67d29ef95", [:mix], [{:nimble_parsec, "~> 0.5", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "2e9b4996d11832947731f7608fed7ad2f9443011b3b479ae288011265cdd3dad"}, - "makeup_elixir": {:hex, :makeup_elixir, "0.14.1", "4f0e96847c63c17841d42c08107405a005a2680eb9c7ccadfd757bd31dabccfb", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f2438b1a80eaec9ede832b5c41cd4f373b38fd7aa33e3b22d9db79e640cbde11"}, + "makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"}, + "makeup_elixir": {:hex, :makeup_elixir, "0.15.1", "b5888c880d17d1cc3e598f05cdb5b5a91b7b17ac4eaf5f297cb697663a1094dd", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "db68c173234b07ab2a07f645a5acdc117b9f99d69ebf521821d89690ae6c6ec8"}, + "makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"}, "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"}, - "nimble_parsec": {:hex, :nimble_parsec, "0.6.0", "32111b3bf39137144abd7ba1cce0914533b2d16ef35e8abc5ec8be6122944263", [:mix], [], "hexpm", "27eac315a94909d4dc68bc07a4a83e06c8379237c5ea528a9acff4ca1c873c52"}, + "nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"}, "parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm", "17ef63abde837ad30680ea7f857dd9e7ced9476cdd7b0394432af4bfc241b960"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.5.0", "8516502659002cec19e244ebd90d312183064be95025a319a6c7e89f4bccd65b", [:rebar3], [], "hexpm", "d48d002e15f5cc105a696cf2f1bbb3fc72b4b770a184d8420c8db20da2674b38"},