{"action":"created","comment":{"url":"https://api.github.com/repos/2600hz/kazoo/pulls/comments/41181280","id":41181280,"diff_hunk":"@@ -0,0 +1,285 @@\n+%%%-------------------------------------------------------------------\n+%%% @copyright (C) 2013-2015, 2600Hz, INC\n+%%% @doc\n+%%%\n+%%% @end\n+%%% @contributors\n+%%%   SIPLABS, LLC (Vladimir Potapev)\n+%%%-------------------------------------------------------------------\n+-module(cb_fmc_devices).\n+\n+-export([init/0\n+    ,allowed_methods/0, allowed_methods/1\n+    ,resource_exists/0, resource_exists/1\n+    ,validate/1, validate/2\n+    ,read/1, read/2\n+    ,put/1\n+    ,post/2\n+    ,delete/2\n+]).\n+\n+-include(\"../crossbar.hrl\").\n+\n+-define(CB_LIST, <<\"fmc_devices/crossbar_listing\">>).\n+\n+%%%===================================================================\n+%%% API\n+%%%===================================================================\n+\n+%%--------------------------------------------------------------------\n+%% @public\n+%% @doc\n+%% Initializes the bindings this module will respond to.\n+%% @end\n+%%--------------------------------------------------------------------\n+-spec init() -> 'ok'.\n+init() ->\n+    _ = crossbar_bindings:bind(<<\"*.allowed_methods.fmc_devices\">>, ?MODULE, 'allowed_methods'),\n+    _ = crossbar_bindings:bind(<<\"*.resource_exists.fmc_devices\">>, ?MODULE, 'resource_exists'),\n+    _ = crossbar_bindings:bind(<<\"*.validate.fmc_devices\">>, ?MODULE, 'validate'),\n+    _ = crossbar_bindings:bind(<<\"*.execute.put.fmc_devices\">>, ?MODULE, 'put'),\n+    _ = crossbar_bindings:bind(<<\"*.execute.post.fmc_devices\">>, ?MODULE, 'post').\n+\n+%%--------------------------------------------------------------------\n+%% @public\n+%% @doc\n+%% Given the path tokens related to this module, what HTTP methods are\n+%% going to be responded to.\n+%% @end\n+%%--------------------------------------------------------------------\n+-spec allowed_methods() -> http_methods().\n+-spec allowed_methods(path_token()) -> http_methods().\n+allowed_methods() ->\n+    [?HTTP_GET, ?HTTP_PUT].\n+allowed_methods(_) ->\n+    [?HTTP_GET, ?HTTP_POST, ?HTTP_DELETE].\n+\n+%%--------------------------------------------------------------------\n+%% @public\n+%% @doc\n+%% Does the path point to a valid resource\n+%% Expected: /fmc_devices\n+%%           /fmc_devices/${fmc_device_id}\n+%% @end\n+%%--------------------------------------------------------------------\n+-spec resource_exists() -> 'true'.\n+-spec resource_exists(path_token()) -> 'true'.\n+resource_exists() -> 'true'.\n+resource_exists(_) -> 'true'.\n+\n+%%--------------------------------------------------------------------\n+%% @public\n+%% @doc\n+%% Check the request (request body, query string params, path tokens, etc)\n+%% and load necessary information.\n+%% /fmc_devices might load all FMC devices\n+%% /fmc_devices/${fmc_device_id} might interoperate with this FMC devices\n+%% Generally, use crossbar_doc to manipulate the cb_context{} record\n+%% @end\n+%%--------------------------------------------------------------------\n+-spec validate(cb_context:context()) -> cb_context:context().\n+-spec validate(cb_context:context(), path_token()) -> cb_context:context().\n+validate(Context) ->\n+    validate_fmc_devices(Context, cb_context:req_verb(Context)).\n+validate(Context, Id) ->\n+    validate_fmc_device(Context, Id, cb_context:req_verb(Context)).\n+\n+-spec validate_fmc_devices(cb_context:context(), http_method()) -> cb_context:context().\n+validate_fmc_devices(Context, ?HTTP_GET) ->\n+    read(Context);\n+validate_fmc_devices(Context, ?HTTP_PUT) ->\n+    OnSuccess = fun(C) -> on_successful_validation('undefined', C) end,\n+    cb_context:validate_request_data(<<\"fmc_device\">>, Context, OnSuccess).\n+\n+-spec validate_fmc_device(cb_context:context(), path_token(), http_method()) -> cb_context:context().\n+validate_fmc_device(Context, Id, ?HTTP_GET) ->\n+    case couch_mgr:open_cache_doc(?WH_FMC_DB, Id) of\n+        {'ok', Doc} ->\n+            AccountId = cb_context:account_id(Context),\n+            case wh_json:get_value(<<\"account_id\">>, Doc) of\n+                AccountId ->\n+                    Context1 = cb_context:set_doc(Context, Doc),\n+                    read(Context1, Id);\n+                _ ->\n+                    cb_context:add_validation_error(<<\"fmc\">>, <<\"not_found\">>, wh_json:from_list([{<<\"message\">>, <<\"FMC Device with this ID wasn't found\">>}]), Context)\n+            end;\n+        _ ->\n+            cb_context:add_validation_error(<<\"fmc\">>, <<\"not_found\">>, wh_json:from_list([{<<\"message\">>, <<\"FMC Device with this ID wasn't found\">>}]), Context)\n+    end;\n+validate_fmc_device(Context, Id, ?HTTP_POST) ->\n+    OnSuccess = fun(C) -> on_successful_validation(Id, C) end,\n+    cb_context:validate_request_data(<<\"fmc_device\">>, Context, OnSuccess);\n+validate_fmc_device(Context, Id, ?HTTP_DELETE) ->\n+    case couch_mgr:open_cache_doc(?WH_FMC_DB, Id) of\n+        {'ok', SavedDoc} ->\n+            AccountId = cb_context:account_id(Context),\n+            case wh_json:get_value(<<\"account_id\">>, SavedDoc) of\n+                AccountId ->\n+                    Context1 = cb_context:set_doc(Context, SavedDoc),\n+                    delete(Context1, Id);\n+                _ ->\n+                    cb_context:add_validation_error(<<\"fmc\">>, <<\"not_found\">>, wh_json:from_list([{<<\"message\">>, <<\"FMC Device with this ID wasn't found\">>}]), Context)\n+            end;\n+        _ ->\n+            cb_context:add_validation_error(<<\"fmc\">>, <<\"not_found\">>, wh_json:from_list([{<<\"message\">>, <<\"FMC Device with this ID wasn't found\">>}]), Context)\n+    end.\n+\n+%%--------------------------------------------------------------------\n+%% @private\n+%% @doc\n+%% Load an instance from the database\n+%% @end\n+%%--------------------------------------------------------------------\n+-spec read(cb_context:context()) -> cb_context:context().\n+read(Context) ->\n+    {'ok', JObjs} = couch_mgr:get_all_results(?WH_FMC_DB, ?CB_LIST),\n+    Doc = [wh_json:get_value(<<\"value\">>, JObj) || JObj <- JObjs],\n+    Doc1 = [JObj || JObj <- Doc, wh_json:get_value(<<\"account_id\">>, JObj) =:= cb_context:account_id(Context)],\n+    Doc2 = [wh_json:delete_keys([<<\"a_number\">>, <<\"account_id\">>], JObj) || JObj <- Doc1],\n+    Context1 = cb_context:set_doc(Context, Doc2),\n+    Context2 = cb_context:set_resp_data(Context1, Doc2),\n+    cb_context:set_resp_status(Context2, 'success').\n+\n+%%--------------------------------------------------------------------\n+%% @private\n+%% @doc\n+%% Load an instance from the database\n+%% @end\n+%%--------------------------------------------------------------------\n+-spec read(cb_context:context(), path_token()) -> cb_context:context().\n+read(Context, Id) ->\n+    {'ok', Doc} = couch_mgr:open_cache_doc(?WH_FMC_DB, Id),\n+    Doc1 = wh_doc:public_fields(Doc),\n+    Doc2 = wh_json:delete_keys([<<\"a_number\">>, <<\"account_id\">>], Doc1),\n+    Context1 = cb_context:set_doc(Context, Doc2),\n+    Context2 = cb_context:set_resp_data(Context1, Doc2),\n+    cb_context:set_resp_status(Context2, 'success').\n+\n+%%--------------------------------------------------------------------\n+%% @public\n+%% @doc\n+%% If the HTTP verb is PUT, execute the actual action, usually a db save.\n+%% @end\n+%%--------------------------------------------------------------------\n+-spec put(cb_context:context()) -> cb_context:context().\n+put(Context) ->\n+    Doc = wh_json:set_values([{<<\"pvt_type\">>, <<\"fmc_device\">>}\n+                              ,{<<\"account_id\">>, cb_context:account_id(Context)}]\n+                              ,cb_context:doc(Context)),\n+    DeviceId = wh_json:get_value(<<\"device_id\">>, Doc),\n+    {'ok', DeviceDoc} = couch_mgr:open_cache_doc(cb_context:account_db(Context), DeviceId),\n+    ANumber = wh_json:get_value([<<\"call_forward\">>, <<\"number\">>], DeviceDoc),\n+    Doc1 = wh_json:set_value(<<\"a_number\">>, ANumber, Doc),\n+    {'ok', ResultDoc} = couch_mgr:save_doc(?WH_FMC_DB, Doc1),\n+    ResultDoc1 = wh_doc:public_fields(ResultDoc),\n+    Context1 = cb_context:set_doc(Context, ResultDoc1),\n+    cb_context:set_resp_data(Context1, ResultDoc1).\n+\n+%%--------------------------------------------------------------------\n+%% @public\n+%% @doc\n+%% If the HTTP verb is POST, execute the actual action, usually a db save\n+%% (after a merge perhaps).\n+%% @end\n+%%--------------------------------------------------------------------\n+-spec post(cb_context:context(), path_token()) -> cb_context:context().\n+post(Context, Id) ->\n+    AccountId = cb_context:account_id(Context),\n+    Doc1 = wh_json:set_values([{<<\"_id\">>, Id}\n+        ,{<<\"pvt_type\">>, <<\"fmc_device\">>}\n+        ,{<<\"account_id\">>, AccountId}]\n+        ,cb_context:doc(Context)),\n+    DeviceId = wh_json:get_value(<<\"device_id\">>, Doc1),\n+    {'ok', DeviceDoc} = couch_mgr:open_cache_doc(cb_context:account_db(Context), DeviceId),\n+    ANumber = wh_json:get_value([<<\"call_forward\">>, <<\"number\">>], DeviceDoc),\n+    Doc2 = wh_json:set_value(<<\"a_number\">>, ANumber, Doc1),\n+    {'ok', ResultDoc} = couch_mgr:save_doc(?WH_FMC_DB, Doc2),\n+    ResultDoc1 = wh_doc:public_fields(ResultDoc),\n+    Context1 = cb_context:set_doc(Context, ResultDoc1),\n+    cb_context:set_resp_data(Context1, ResultDoc1).\n+\n+%%--------------------------------------------------------------------\n+%% @public\n+%% @doc\n+%% If the HTTP verb is DELETE, execute the actual action, usually a db delete\n+%% @end\n+%%--------------------------------------------------------------------\n+-spec delete(cb_context:context(), path_token()) -> cb_context:context().\n+delete(Context, Id) ->\n+    {'ok', _} = couch_mgr:del_doc(?WH_FMC_DB, Id),\n+    cb_context:set_resp_status(Context, 'success').\n+\n+%%--------------------------------------------------------------------\n+%% @private\n+%% @doc\n+%%\n+%% @end\n+%%--------------------------------------------------------------------\n+-spec on_successful_validation('undefined' | api_binary(), cb_context:context()) -> cb_context:context().\n+on_successful_validation('undefined', Context) ->\n+    FMCValue = wh_json:get_value(<<\"x_fmc_value\">>, cb_context:doc(Context)),\n+    DeviceId = wh_json:get_value(<<\"device_id\">>, cb_context:doc(Context)),\n+    case couch_mgr:open_cache_doc(cb_context:account_db(Context), DeviceId) of\n+        {'ok', DeviceDoc} ->\n+            Doc = wh_json:set_value(<<\"pvt_type\">>, <<\"fmc_device\">>, cb_context:doc(Context)),\n+            DeviceType = wh_json:get_value(<<\"device_type\">>, DeviceDoc),\n+            Number = wh_json:get_value([<<\"call_forward\">>, <<\"number\">>], DeviceDoc),\n+            case DeviceType of\n+                <<\"cellphone\">> ->\n+                    case is_existing_fmc(Number, FMCValue, 'undefined') of\n+                        'true' ->\n+                            cb_context:add_validation_error(<<\"fmc\">>, <<\"unique\">>, wh_json:from_list([{<<\"message\">>, <<\"FMC Device with this A-Number and FMC Value already exists\">>}]), Context);","path":"applications/crossbar/src/modules/cb_fmc_devices.erl","position":231,"original_position":231,"commit_id":"7492fcd266f35d205dd7296f1da1acc56f1204c2","original_commit_id":"7492fcd266f35d205dd7296f1da1acc56f1204c2","user":{"login":"fenollp","id":278727,"avatar_url":"https://avatars.githubusercontent.com/u/278727?v=3","gravatar_id":"","url":"https://api.github.com/users/fenollp","html_url":"https://github.com/fenollp","followers_url":"https://api.github.com/users/fenollp/followers","following_url":"https://api.github.com/users/fenollp/following{/other_user}","gists_url":"https://api.github.com/users/fenollp/gists{/gist_id}","starred_url":"https://api.github.com/users/fenollp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fenollp/subscriptions","organizations_url":"https://api.github.com/users/fenollp/orgs","repos_url":"https://api.github.com/users/fenollp/repos","events_url":"https://api.github.com/users/fenollp/events{/privacy}","received_events_url":"https://api.github.com/users/fenollp/received_events","type":"User","site_admin":false},"body":"Same for all these error responses, make a function that calls add_validation_error please","created_at":"2015-10-05T18:45:50Z","updated_at":"2015-10-05T18:45:50Z","html_url":"https://github.com/2600hz/kazoo/pull/1349#discussion_r41181280","pull_request_url":"https://api.github.com/repos/2600hz/kazoo/pulls/1349","_links":{"self":{"href":"https://api.github.com/repos/2600hz/kazoo/pulls/comments/41181280"},"html":{"href":"https://github.com/2600hz/kazoo/pull/1349#discussion_r41181280"},"pull_request":{"href":"https://api.github.com/repos/2600hz/kazoo/pulls/1349"}}},"pull_request":{"url":"https://api.github.com/repos/2600hz/kazoo/pulls/1349","id":46788757,"html_url":"https://github.com/2600hz/kazoo/pull/1349","diff_url":"https://github.com/2600hz/kazoo/pull/1349.diff","patch_url":"https://github.com/2600hz/kazoo/pull/1349.patch","issue_url":"https://api.github.com/repos/2600hz/kazoo/issues/1349","number":1349,"state":"open","locked":false,"title":"KAZOO-4259: FMC (Fixed Mobile Convergence) implementation","user":{"login":"siplabs","id":1489408,"avatar_url":"https://avatars.githubusercontent.com/u/1489408?v=3","gravatar_id":"","url":"https://api.github.com/users/siplabs","html_url":"https://github.com/siplabs","followers_url":"https://api.github.com/users/siplabs/followers","following_url":"https://api.github.com/users/siplabs/following{/other_user}","gists_url":"https://api.github.com/users/siplabs/gists{/gist_id}","starred_url":"https://api.github.com/users/siplabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/siplabs/subscriptions","organizations_url":"https://api.github.com/users/siplabs/orgs","repos_url":"https://api.github.com/users/siplabs/repos","events_url":"https://api.github.com/users/siplabs/events{/privacy}","received_events_url":"https://api.github.com/users/siplabs/received_events","type":"User","site_admin":false},"body":"Application for supporting Fixed Mobile Convergence features.","created_at":"2015-10-05T14:39:58Z","updated_at":"2015-10-05T18:45:50Z","closed_at":null,"merged_at":null,"merge_commit_sha":"8334620d7d3f496f01aecdb6c215c9e2eba40c9b","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/2600hz/kazoo/pulls/1349/commits","review_comments_url":"https://api.github.com/repos/2600hz/kazoo/pulls/1349/comments","review_comment_url":"https://api.github.com/repos/2600hz/kazoo/pulls/comments{/number}","comments_url":"https://api.github.com/repos/2600hz/kazoo/issues/1349/comments","statuses_url":"https://api.github.com/repos/2600hz/kazoo/statuses/7492fcd266f35d205dd7296f1da1acc56f1204c2","head":{"label":"siplabs:KAZOO-4259","ref":"KAZOO-4259","sha":"7492fcd266f35d205dd7296f1da1acc56f1204c2","user":{"login":"siplabs","id":1489408,"avatar_url":"https://avatars.githubusercontent.com/u/1489408?v=3","gravatar_id":"","url":"https://api.github.com/users/siplabs","html_url":"https://github.com/siplabs","followers_url":"https://api.github.com/users/siplabs/followers","following_url":"https://api.github.com/users/siplabs/following{/other_user}","gists_url":"https://api.github.com/users/siplabs/gists{/gist_id}","starred_url":"https://api.github.com/users/siplabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/siplabs/subscriptions","organizations_url":"https://api.github.com/users/siplabs/orgs","repos_url":"https://api.github.com/users/siplabs/repos","events_url":"https://api.github.com/users/siplabs/events{/privacy}","received_events_url":"https://api.github.com/users/siplabs/received_events","type":"User","site_admin":false},"repo":{"id":18828051,"name":"kazoo","full_name":"siplabs/kazoo","owner":{"login":"siplabs","id":1489408,"avatar_url":"https://avatars.githubusercontent.com/u/1489408?v=3","gravatar_id":"","url":"https://api.github.com/users/siplabs","html_url":"https://github.com/siplabs","followers_url":"https://api.github.com/users/siplabs/followers","following_url":"https://api.github.com/users/siplabs/following{/other_user}","gists_url":"https://api.github.com/users/siplabs/gists{/gist_id}","starred_url":"https://api.github.com/users/siplabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/siplabs/subscriptions","organizations_url":"https://api.github.com/users/siplabs/orgs","repos_url":"https://api.github.com/users/siplabs/repos","events_url":"https://api.github.com/users/siplabs/events{/privacy}","received_events_url":"https://api.github.com/users/siplabs/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/siplabs/kazoo","description":"","fork":true,"url":"https://api.github.com/repos/siplabs/kazoo","forks_url":"https://api.github.com/repos/siplabs/kazoo/forks","keys_url":"https://api.github.com/repos/siplabs/kazoo/keys{/key_id}","collaborators_url":"https://api.github.com/repos/siplabs/kazoo/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/siplabs/kazoo/teams","hooks_url":"https://api.github.com/repos/siplabs/kazoo/hooks","issue_events_url":"https://api.github.com/repos/siplabs/kazoo/issues/events{/number}","events_url":"https://api.github.com/repos/siplabs/kazoo/events","assignees_url":"https://api.github.com/repos/siplabs/kazoo/assignees{/user}","branches_url":"https://api.github.com/repos/siplabs/kazoo/branches{/branch}","tags_url":"https://api.github.com/repos/siplabs/kazoo/tags","blobs_url":"https://api.github.com/repos/siplabs/kazoo/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/siplabs/kazoo/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/siplabs/kazoo/git/refs{/sha}","trees_url":"https://api.github.com/repos/siplabs/kazoo/git/trees{/sha}","statuses_url":"https://api.github.com/repos/siplabs/kazoo/statuses/{sha}","languages_url":"https://api.github.com/repos/siplabs/kazoo/languages","stargazers_url":"https://api.github.com/repos/siplabs/kazoo/stargazers","contributors_url":"https://api.github.com/repos/siplabs/kazoo/contributors","subscribers_url":"https://api.github.com/repos/siplabs/kazoo/subscribers","subscription_url":"https://api.github.com/repos/siplabs/kazoo/subscription","commits_url":"https://api.github.com/repos/siplabs/kazoo/commits{/sha}","git_commits_url":"https://api.github.com/repos/siplabs/kazoo/git/commits{/sha}","comments_url":"https://api.github.com/repos/siplabs/kazoo/comments{/number}","issue_comment_url":"https://api.github.com/repos/siplabs/kazoo/issues/comments{/number}","contents_url":"https://api.github.com/repos/siplabs/kazoo/contents/{+path}","compare_url":"https://api.github.com/repos/siplabs/kazoo/compare/{base}...{head}","merges_url":"https://api.github.com/repos/siplabs/kazoo/merges","archive_url":"https://api.github.com/repos/siplabs/kazoo/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/siplabs/kazoo/downloads","issues_url":"https://api.github.com/repos/siplabs/kazoo/issues{/number}","pulls_url":"https://api.github.com/repos/siplabs/kazoo/pulls{/number}","milestones_url":"https://api.github.com/repos/siplabs/kazoo/milestones{/number}","notifications_url":"https://api.github.com/repos/siplabs/kazoo/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/siplabs/kazoo/labels{/name}","releases_url":"https://api.github.com/repos/siplabs/kazoo/releases{/id}","created_at":"2014-04-16T05:33:28Z","updated_at":"2015-03-03T12:07:43Z","pushed_at":"2015-10-05T15:39:41Z","git_url":"git://github.com/siplabs/kazoo.git","ssh_url":"git@github.com:siplabs/kazoo.git","clone_url":"https://github.com/siplabs/kazoo.git","svn_url":"https://github.com/siplabs/kazoo","homepage":"","size":325043,"stargazers_count":0,"watchers_count":0,"language":"Erlang","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"2600hz:master","ref":"master","sha":"e59d435df87aee441f693efec6ef6d6818ed13ee","user":{"login":"2600hz","id":408801,"avatar_url":"https://avatars.githubusercontent.com/u/408801?v=3","gravatar_id":"","url":"https://api.github.com/users/2600hz","html_url":"https://github.com/2600hz","followers_url":"https://api.github.com/users/2600hz/followers","following_url":"https://api.github.com/users/2600hz/following{/other_user}","gists_url":"https://api.github.com/users/2600hz/gists{/gist_id}","starred_url":"https://api.github.com/users/2600hz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/2600hz/subscriptions","organizations_url":"https://api.github.com/users/2600hz/orgs","repos_url":"https://api.github.com/users/2600hz/repos","events_url":"https://api.github.com/users/2600hz/events{/privacy}","received_events_url":"https://api.github.com/users/2600hz/received_events","type":"Organization","site_admin":false},"repo":{"id":2966241,"name":"kazoo","full_name":"2600hz/kazoo","owner":{"login":"2600hz","id":408801,"avatar_url":"https://avatars.githubusercontent.com/u/408801?v=3","gravatar_id":"","url":"https://api.github.com/users/2600hz","html_url":"https://github.com/2600hz","followers_url":"https://api.github.com/users/2600hz/followers","following_url":"https://api.github.com/users/2600hz/following{/other_user}","gists_url":"https://api.github.com/users/2600hz/gists{/gist_id}","starred_url":"https://api.github.com/users/2600hz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/2600hz/subscriptions","organizations_url":"https://api.github.com/users/2600hz/orgs","repos_url":"https://api.github.com/users/2600hz/repos","events_url":"https://api.github.com/users/2600hz/events{/privacy}","received_events_url":"https://api.github.com/users/2600hz/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/2600hz/kazoo","description":"","fork":false,"url":"https://api.github.com/repos/2600hz/kazoo","forks_url":"https://api.github.com/repos/2600hz/kazoo/forks","keys_url":"https://api.github.com/repos/2600hz/kazoo/keys{/key_id}","collaborators_url":"https://api.github.com/repos/2600hz/kazoo/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/2600hz/kazoo/teams","hooks_url":"https://api.github.com/repos/2600hz/kazoo/hooks","issue_events_url":"https://api.github.com/repos/2600hz/kazoo/issues/events{/number}","events_url":"https://api.github.com/repos/2600hz/kazoo/events","assignees_url":"https://api.github.com/repos/2600hz/kazoo/assignees{/user}","branches_url":"https://api.github.com/repos/2600hz/kazoo/branches{/branch}","tags_url":"https://api.github.com/repos/2600hz/kazoo/tags","blobs_url":"https://api.github.com/repos/2600hz/kazoo/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/2600hz/kazoo/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/2600hz/kazoo/git/refs{/sha}","trees_url":"https://api.github.com/repos/2600hz/kazoo/git/trees{/sha}","statuses_url":"https://api.github.com/repos/2600hz/kazoo/statuses/{sha}","languages_url":"https://api.github.com/repos/2600hz/kazoo/languages","stargazers_url":"https://api.github.com/repos/2600hz/kazoo/stargazers","contributors_url":"https://api.github.com/repos/2600hz/kazoo/contributors","subscribers_url":"https://api.github.com/repos/2600hz/kazoo/subscribers","subscription_url":"https://api.github.com/repos/2600hz/kazoo/subscription","commits_url":"https://api.github.com/repos/2600hz/kazoo/commits{/sha}","git_commits_url":"https://api.github.com/repos/2600hz/kazoo/git/commits{/sha}","comments_url":"https://api.github.com/repos/2600hz/kazoo/comments{/number}","issue_comment_url":"https://api.github.com/repos/2600hz/kazoo/issues/comments{/number}","contents_url":"https://api.github.com/repos/2600hz/kazoo/contents/{+path}","compare_url":"https://api.github.com/repos/2600hz/kazoo/compare/{base}...{head}","merges_url":"https://api.github.com/repos/2600hz/kazoo/merges","archive_url":"https://api.github.com/repos/2600hz/kazoo/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/2600hz/kazoo/downloads","issues_url":"https://api.github.com/repos/2600hz/kazoo/issues{/number}","pulls_url":"https://api.github.com/repos/2600hz/kazoo/pulls{/number}","milestones_url":"https://api.github.com/repos/2600hz/kazoo/milestones{/number}","notifications_url":"https://api.github.com/repos/2600hz/kazoo/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/2600hz/kazoo/labels{/name}","releases_url":"https://api.github.com/repos/2600hz/kazoo/releases{/id}","created_at":"2011-12-12T18:08:02Z","updated_at":"2015-10-05T16:43:10Z","pushed_at":"2015-10-05T17:22:59Z","git_url":"git://github.com/2600hz/kazoo.git","ssh_url":"git@github.com:2600hz/kazoo.git","clone_url":"https://github.com/2600hz/kazoo.git","svn_url":"https://github.com/2600hz/kazoo","homepage":"","size":557930,"stargazers_count":291,"watchers_count":291,"language":"Erlang","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":149,"mirror_url":null,"open_issues_count":26,"forks":149,"open_issues":26,"watchers":291,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/2600hz/kazoo/pulls/1349"},"html":{"href":"https://github.com/2600hz/kazoo/pull/1349"},"issue":{"href":"https://api.github.com/repos/2600hz/kazoo/issues/1349"},"comments":{"href":"https://api.github.com/repos/2600hz/kazoo/issues/1349/comments"},"review_comments":{"href":"https://api.github.com/repos/2600hz/kazoo/pulls/1349/comments"},"review_comment":{"href":"https://api.github.com/repos/2600hz/kazoo/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/2600hz/kazoo/pulls/1349/commits"},"statuses":{"href":"https://api.github.com/repos/2600hz/kazoo/statuses/7492fcd266f35d205dd7296f1da1acc56f1204c2"}}}}