{"action":"created","comment":{"url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/pulls/comments/209025864","pull_request_review_id":144958621,"id":209025864,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIwOTAyNTg2NA==","diff_hunk":"@@ -0,0 +1,176 @@\n+// Copyright 2018 Google LLC\n+//\n+// Licensed under the Apache License, Version 2.0 (the \"License\");\n+// you may not use this file except in compliance with the License.\n+// You may obtain a copy of the License at\n+//\n+//     https://www.apache.org/licenses/LICENSE-2.0\n+//\n+// Unless required by applicable law or agreed to in writing, software\n+// distributed under the License is distributed on an \"AS IS\" BASIS,\n+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+// See the License for the specific language governing permissions and\n+// limitations under the License.\n+\n+using System;\n+using System.Collections.Generic;\n+using System.IO;\n+using System.Linq;\n+using System.Net;\n+using System.Runtime.CompilerServices;\n+using System.Text;\n+using System.Threading;\n+using UnityEngine;\n+\n+[assembly: InternalsVisibleTo(\"GooglePlayInstant.Tests.Editor.QuickDeploy\")]\n+\n+namespace GooglePlayInstant.Editor.QuickDeploy\n+{\n+    /// <summary>\n+    /// A class representing a server that provides an endpoint to use for getting authorization code from Google's\n+    /// OAuth2 API's authorization page. On that page, the user grants the application to access their data on Google\n+    /// Cloud platform. The server attempt to open and start listening at a fixed port. The server announces\n+    /// its chosen endpoint with the CallbackEndpoint property. This server will run until it receives the first\n+    /// request, which it will process to retrieve the authorization response and handle the by invoking on the response\n+    /// the handler passed to the server during instatiation. The server will then stop listening for further requests.\n+    ///\n+    /// <see cref=\"https://developers.google.com/identity/protocols/OAuth2#installed\"/> for an overview of OAuth2\n+    /// protocol for installed applications that interact with Google APIs.\n+    /// </summary>\n+    public class OAuth2Server\n+    {\n+        private const string CloseTabText = \"You may close this tab.\";\n+        private const int ServerPort = 2806;\n+        private HttpListener _httpListener;\n+        private string _callbackEndpoint;\n+\n+        private readonly Action<KeyValuePair<string, string>> _onResponseAction;\n+\n+        /// <summary>\n+        /// An endpoint that on which the server is listening.\n+        /// </summary>\n+        public string CallbackEndpoint\n+        {\n+            get { return _callbackEndpoint; }\n+        }\n+\n+        /// <summary>\n+        /// An instance of a server that will run locally to retrieve authorization code. The server will stop running\n+        /// once the first response gets received.\n+        /// </summary>\n+        /// <param name=\"onResponseAction\">An action to be invoked on the key-value pair representing the first\n+        /// response that will be caught by the server. Note that that the invocation of this handler will not be done\n+        /// on the main thread, therefore the handler should only run operations that can be run on the main thread.\n+        /// </param>\n+        public OAuth2Server(Action<KeyValuePair<string, string>> onResponseAction)\n+        {\n+            _onResponseAction = onResponseAction;\n+        }\n+\n+        /// <summary>\n+        /// Starts this server to make it listen for requests containing authorization code or error data that are\n+        /// forwarded from google's OAuth2 authorization url.\n+        ///\n+        /// After a call to this method, the CallBackEndpoint property of this instance will provide the endpoint\n+        /// at which this server is listening.\n+        /// </summary>\n+        public void Start()\n+        {\n+            _callbackEndpoint = string.Format(\"http://localhost:{0}/{1}/\", ServerPort, Path.GetRandomFileName());\n+            _httpListener = new HttpListener();\n+            _httpListener.Prefixes.Add(_callbackEndpoint);\n+            _httpListener.Start();\n+\n+            // Server will only respond to the first request, therefore one new thread should handle it just fine.\n+            new Thread(() => { ProcessContext(_httpListener.GetContext()); }).Start();\n+        }\n+\n+        /// <summary>\n+        /// Processes the object as an HttpListenerContext instance and retrieves authorization response. Invokes the\n+        /// response handler action on the response, and responds to request with a string asking the user to close tab.\n+        /// </summary>\n+        private void ProcessContext(HttpListenerContext context)\n+        {\n+            var authorizationResponse = GetAuthorizationResponse(context.Request.Url);\n+            _onResponseAction(authorizationResponse);\n+            context.Response.KeepAlive = false;\n+            var responsebBytes = Encoding.UTF8.GetBytes(CloseTabText);\n+            var outputStream = context.Response.OutputStream;\n+            outputStream.Write(responsebBytes, 0, responsebBytes.Length);\n+            outputStream.Flush();\n+            outputStream.Close();\n+            context.Response.Close();\n+            Stop();\n+        }\n+\n+        /// <summary>\n+        /// Returns a key value pair corresponding to the authorization response sent from OAuth2 authorization page.\n+        /// Logs error message and throws ArgumentException if the uri contains invalid params.\n+        /// </summary>\n+        /// <param name=\"uri\">The uri of the incoming request</param>\n+        /// <exception cref=\"ArgumentException\">Exception thrown if the uri contains invalid params.</exception>\n+        internal static KeyValuePair<string, string> GetAuthorizationResponse(Uri uri)\n+        {\n+            if (!UriContainsValidQueryParams(uri))\n+            {\n+                const string errorMessage = \"Uri query contains invalid params\";\n+                Debug.LogError(errorMessage);\n+                throw new ArgumentException(errorMessage);\n+            }\n+\n+            return GetQueryParamsFromUri(uri).ToArray()[0];\n+        }\n+\n+        /// <summary>\n+        /// Inspect the URI and determine whether it contains valid params according to the following policies:\n+        ///   1. URI query must include \"code\" or \"error\" in param keys.\n+        ///   2. \"code\" and \"error\" cannot be present at the same time.\n+        ///   3. No other keys apart from \"code\", \"error\" are allowed.\n+        /// </summary>\n+        internal static bool UriContainsValidQueryParams(Uri uri)\n+        {\n+            var allowedQueries = new[] {\"code\", \"error\"};\n+            var queryParams = GetQueryParamsFromUri(uri);\n+\n+            Predicate<Dictionary<string, string>> codeOrErrorIsPresent = queryParamsDict =>\n+                queryParamsDict.ContainsKey(\"code\") || queryParamsDict.ContainsKey(\"error\");\n+\n+            Predicate<Dictionary<string, string>> notBothCodeAndErrorArePresent = queryParamsDict =>\n+                !(queryParamsDict.ContainsKey(\"error\") && queryParamsDict.ContainsKey(\"code\"));\n+\n+            Predicate<Dictionary<string, string>> noOtherKeysArePresent = queryParamsDict =>\n+                queryParamsDict.Where(kvp => !allowedQueries.Contains(kvp.Key)).ToArray().Length == 0;\n+            return codeOrErrorIsPresent(queryParams) && notBothCodeAndErrorArePresent(queryParams) &&\n+                   noOtherKeysArePresent(queryParams);\n+        }\n+\n+        /// <summary>\n+        /// Processes URI, extracts query params, puts them into a dictionary returns the dictionary.\n+        /// </summary>\n+        internal static Dictionary<string, string> GetQueryParamsFromUri(Uri uri)\n+        {\n+            var result = new Dictionary<string, string>();\n+            foreach (var pair in uri.Query.Substring(1).Split('&'))","path":"GooglePlayInstant/Editor/QuickDeploy/OAuth2Server.cs","position":153,"original_position":153,"commit_id":"b91d4bd3bc32ddc832aa9e12f19df8afc2b89621","original_commit_id":"b91d4bd3bc32ddc832aa9e12f19df8afc2b89621","user":{"login":"thanwah","id":38674020,"node_id":"MDQ6VXNlcjM4Njc0MDIw","avatar_url":"https://avatars2.githubusercontent.com/u/38674020?v=4","gravatar_id":"","url":"https://api.github.com/users/thanwah","html_url":"https://github.com/thanwah","followers_url":"https://api.github.com/users/thanwah/followers","following_url":"https://api.github.com/users/thanwah/following{/other_user}","gists_url":"https://api.github.com/users/thanwah/gists{/gist_id}","starred_url":"https://api.github.com/users/thanwah/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thanwah/subscriptions","organizations_url":"https://api.github.com/users/thanwah/orgs","repos_url":"https://api.github.com/users/thanwah/repos","events_url":"https://api.github.com/users/thanwah/events{/privacy}","received_events_url":"https://api.github.com/users/thanwah/received_events","type":"User","site_admin":false},"body":"Extract a variable and add a comment above that line:\r\n\r\n```\r\n// Uri's Query string always starts with \"?\" so skip the first character.\r\nvar query = uri.Query.Substring(1);\r\nforeach (var pair in query.Split('&'))\r\n```","created_at":"2018-08-09T18:03:35Z","updated_at":"2018-08-09T18:29:47Z","html_url":"https://github.com/jedouard98/play-instant-unity-plugin/pull/12#discussion_r209025864","pull_request_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/pulls/12","author_association":"COLLABORATOR","_links":{"self":{"href":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/pulls/comments/209025864"},"html":{"href":"https://github.com/jedouard98/play-instant-unity-plugin/pull/12#discussion_r209025864"},"pull_request":{"href":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/pulls/12"}}},"pull_request":{"url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/pulls/12","id":204241235,"node_id":"MDExOlB1bGxSZXF1ZXN0MjA0MjQxMjM1","html_url":"https://github.com/jedouard98/play-instant-unity-plugin/pull/12","diff_url":"https://github.com/jedouard98/play-instant-unity-plugin/pull/12.diff","patch_url":"https://github.com/jedouard98/play-instant-unity-plugin/pull/12.patch","issue_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/issues/12","number":12,"state":"open","locked":false,"title":"Implementing server for OAuth2 protocol","user":{"login":"heyaudace","id":18396695,"node_id":"MDQ6VXNlcjE4Mzk2Njk1","avatar_url":"https://avatars3.githubusercontent.com/u/18396695?v=4","gravatar_id":"","url":"https://api.github.com/users/heyaudace","html_url":"https://github.com/heyaudace","followers_url":"https://api.github.com/users/heyaudace/followers","following_url":"https://api.github.com/users/heyaudace/following{/other_user}","gists_url":"https://api.github.com/users/heyaudace/gists{/gist_id}","starred_url":"https://api.github.com/users/heyaudace/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/heyaudace/subscriptions","organizations_url":"https://api.github.com/users/heyaudace/orgs","repos_url":"https://api.github.com/users/heyaudace/repos","events_url":"https://api.github.com/users/heyaudace/events{/privacy}","received_events_url":"https://api.github.com/users/heyaudace/received_events","type":"User","site_admin":false},"body":"## Quick notes:\r\n* Server is instantiated by by passing in a handler, a delegate that will be invoked on the authorization response(auth_code or error) when the response becomes available.\r\n* Server picks an endpoint at random that it will be listening from.\r\n* The endpoint serves as redirect_uri for receiving authorization code.\r\n* This change does not affect the UI.","created_at":"2018-07-26T19:19:45Z","updated_at":"2018-08-09T18:29:47Z","closed_at":null,"merged_at":null,"merge_commit_sha":"1a4e300c83ef15afa45145aaf817f68294603bad","assignee":{"login":"heyaudace","id":18396695,"node_id":"MDQ6VXNlcjE4Mzk2Njk1","avatar_url":"https://avatars3.githubusercontent.com/u/18396695?v=4","gravatar_id":"","url":"https://api.github.com/users/heyaudace","html_url":"https://github.com/heyaudace","followers_url":"https://api.github.com/users/heyaudace/followers","following_url":"https://api.github.com/users/heyaudace/following{/other_user}","gists_url":"https://api.github.com/users/heyaudace/gists{/gist_id}","starred_url":"https://api.github.com/users/heyaudace/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/heyaudace/subscriptions","organizations_url":"https://api.github.com/users/heyaudace/orgs","repos_url":"https://api.github.com/users/heyaudace/repos","events_url":"https://api.github.com/users/heyaudace/events{/privacy}","received_events_url":"https://api.github.com/users/heyaudace/received_events","type":"User","site_admin":false},"assignees":[{"login":"heyaudace","id":18396695,"node_id":"MDQ6VXNlcjE4Mzk2Njk1","avatar_url":"https://avatars3.githubusercontent.com/u/18396695?v=4","gravatar_id":"","url":"https://api.github.com/users/heyaudace","html_url":"https://github.com/heyaudace","followers_url":"https://api.github.com/users/heyaudace/followers","following_url":"https://api.github.com/users/heyaudace/following{/other_user}","gists_url":"https://api.github.com/users/heyaudace/gists{/gist_id}","starred_url":"https://api.github.com/users/heyaudace/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/heyaudace/subscriptions","organizations_url":"https://api.github.com/users/heyaudace/orgs","repos_url":"https://api.github.com/users/heyaudace/repos","events_url":"https://api.github.com/users/heyaudace/events{/privacy}","received_events_url":"https://api.github.com/users/heyaudace/received_events","type":"User","site_admin":false}],"requested_reviewers":[{"login":"leegao","id":62580,"node_id":"MDQ6VXNlcjYyNTgw","avatar_url":"https://avatars3.githubusercontent.com/u/62580?v=4","gravatar_id":"","url":"https://api.github.com/users/leegao","html_url":"https://github.com/leegao","followers_url":"https://api.github.com/users/leegao/followers","following_url":"https://api.github.com/users/leegao/following{/other_user}","gists_url":"https://api.github.com/users/leegao/gists{/gist_id}","starred_url":"https://api.github.com/users/leegao/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/leegao/subscriptions","organizations_url":"https://api.github.com/users/leegao/orgs","repos_url":"https://api.github.com/users/leegao/repos","events_url":"https://api.github.com/users/leegao/events{/privacy}","received_events_url":"https://api.github.com/users/leegao/received_events","type":"User","site_admin":false},{"login":"jedouard98","id":20508605,"node_id":"MDQ6VXNlcjIwNTA4NjA1","avatar_url":"https://avatars0.githubusercontent.com/u/20508605?v=4","gravatar_id":"","url":"https://api.github.com/users/jedouard98","html_url":"https://github.com/jedouard98","followers_url":"https://api.github.com/users/jedouard98/followers","following_url":"https://api.github.com/users/jedouard98/following{/other_user}","gists_url":"https://api.github.com/users/jedouard98/gists{/gist_id}","starred_url":"https://api.github.com/users/jedouard98/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jedouard98/subscriptions","organizations_url":"https://api.github.com/users/jedouard98/orgs","repos_url":"https://api.github.com/users/jedouard98/repos","events_url":"https://api.github.com/users/jedouard98/events{/privacy}","received_events_url":"https://api.github.com/users/jedouard98/received_events","type":"User","site_admin":false},{"login":"lookscorrect","id":29439465,"node_id":"MDQ6VXNlcjI5NDM5NDY1","avatar_url":"https://avatars0.githubusercontent.com/u/29439465?v=4","gravatar_id":"","url":"https://api.github.com/users/lookscorrect","html_url":"https://github.com/lookscorrect","followers_url":"https://api.github.com/users/lookscorrect/followers","following_url":"https://api.github.com/users/lookscorrect/following{/other_user}","gists_url":"https://api.github.com/users/lookscorrect/gists{/gist_id}","starred_url":"https://api.github.com/users/lookscorrect/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lookscorrect/subscriptions","organizations_url":"https://api.github.com/users/lookscorrect/orgs","repos_url":"https://api.github.com/users/lookscorrect/repos","events_url":"https://api.github.com/users/lookscorrect/events{/privacy}","received_events_url":"https://api.github.com/users/lookscorrect/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/pulls/12/commits","review_comments_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/pulls/12/comments","review_comment_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/pulls/comments{/number}","comments_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/issues/12/comments","statuses_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/statuses/b91d4bd3bc32ddc832aa9e12f19df8afc2b89621","head":{"label":"jedouard98:oauth2_server","ref":"oauth2_server","sha":"b91d4bd3bc32ddc832aa9e12f19df8afc2b89621","user":{"login":"jedouard98","id":20508605,"node_id":"MDQ6VXNlcjIwNTA4NjA1","avatar_url":"https://avatars0.githubusercontent.com/u/20508605?v=4","gravatar_id":"","url":"https://api.github.com/users/jedouard98","html_url":"https://github.com/jedouard98","followers_url":"https://api.github.com/users/jedouard98/followers","following_url":"https://api.github.com/users/jedouard98/following{/other_user}","gists_url":"https://api.github.com/users/jedouard98/gists{/gist_id}","starred_url":"https://api.github.com/users/jedouard98/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jedouard98/subscriptions","organizations_url":"https://api.github.com/users/jedouard98/orgs","repos_url":"https://api.github.com/users/jedouard98/repos","events_url":"https://api.github.com/users/jedouard98/events{/privacy}","received_events_url":"https://api.github.com/users/jedouard98/received_events","type":"User","site_admin":false},"repo":{"id":139494930,"node_id":"MDEwOlJlcG9zaXRvcnkxMzk0OTQ5MzA=","name":"play-instant-unity-plugin","full_name":"jedouard98/play-instant-unity-plugin","owner":{"login":"jedouard98","id":20508605,"node_id":"MDQ6VXNlcjIwNTA4NjA1","avatar_url":"https://avatars0.githubusercontent.com/u/20508605?v=4","gravatar_id":"","url":"https://api.github.com/users/jedouard98","html_url":"https://github.com/jedouard98","followers_url":"https://api.github.com/users/jedouard98/followers","following_url":"https://api.github.com/users/jedouard98/following{/other_user}","gists_url":"https://api.github.com/users/jedouard98/gists{/gist_id}","starred_url":"https://api.github.com/users/jedouard98/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jedouard98/subscriptions","organizations_url":"https://api.github.com/users/jedouard98/orgs","repos_url":"https://api.github.com/users/jedouard98/repos","events_url":"https://api.github.com/users/jedouard98/events{/privacy}","received_events_url":"https://api.github.com/users/jedouard98/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/jedouard98/play-instant-unity-plugin","description":"The Google Play Instant Plugin for Unity Beta : Simplifies conversion of a Unity-based Android app into an instant app that can be deployed through Google Play Instant.","fork":true,"url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin","forks_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/forks","keys_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/teams","hooks_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/hooks","issue_events_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/issues/events{/number}","events_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/events","assignees_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/assignees{/user}","branches_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/branches{/branch}","tags_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/tags","blobs_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/git/refs{/sha}","trees_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/statuses/{sha}","languages_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/languages","stargazers_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/stargazers","contributors_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/contributors","subscribers_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/subscribers","subscription_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/subscription","commits_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/commits{/sha}","git_commits_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/git/commits{/sha}","comments_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/comments{/number}","issue_comment_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/issues/comments{/number}","contents_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/contents/{+path}","compare_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/merges","archive_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/downloads","issues_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/issues{/number}","pulls_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/pulls{/number}","milestones_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/milestones{/number}","notifications_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/labels{/name}","releases_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/releases{/id}","deployments_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/deployments","created_at":"2018-07-02T21:04:49Z","updated_at":"2018-08-08T23:30:24Z","pushed_at":"2018-08-09T16:23:06Z","git_url":"git://github.com/jedouard98/play-instant-unity-plugin.git","ssh_url":"git@github.com:jedouard98/play-instant-unity-plugin.git","clone_url":"https://github.com/jedouard98/play-instant-unity-plugin.git","svn_url":"https://github.com/jedouard98/play-instant-unity-plugin","homepage":"","size":283,"stargazers_count":1,"watchers_count":1,"language":"C#","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":5,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":0,"open_issues":5,"watchers":1,"default_branch":"master"}},"base":{"label":"jedouard98:master","ref":"master","sha":"a2dbfefddcb5389a7b9f28fa910beb89ced3f881","user":{"login":"jedouard98","id":20508605,"node_id":"MDQ6VXNlcjIwNTA4NjA1","avatar_url":"https://avatars0.githubusercontent.com/u/20508605?v=4","gravatar_id":"","url":"https://api.github.com/users/jedouard98","html_url":"https://github.com/jedouard98","followers_url":"https://api.github.com/users/jedouard98/followers","following_url":"https://api.github.com/users/jedouard98/following{/other_user}","gists_url":"https://api.github.com/users/jedouard98/gists{/gist_id}","starred_url":"https://api.github.com/users/jedouard98/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jedouard98/subscriptions","organizations_url":"https://api.github.com/users/jedouard98/orgs","repos_url":"https://api.github.com/users/jedouard98/repos","events_url":"https://api.github.com/users/jedouard98/events{/privacy}","received_events_url":"https://api.github.com/users/jedouard98/received_events","type":"User","site_admin":false},"repo":{"id":139494930,"node_id":"MDEwOlJlcG9zaXRvcnkxMzk0OTQ5MzA=","name":"play-instant-unity-plugin","full_name":"jedouard98/play-instant-unity-plugin","owner":{"login":"jedouard98","id":20508605,"node_id":"MDQ6VXNlcjIwNTA4NjA1","avatar_url":"https://avatars0.githubusercontent.com/u/20508605?v=4","gravatar_id":"","url":"https://api.github.com/users/jedouard98","html_url":"https://github.com/jedouard98","followers_url":"https://api.github.com/users/jedouard98/followers","following_url":"https://api.github.com/users/jedouard98/following{/other_user}","gists_url":"https://api.github.com/users/jedouard98/gists{/gist_id}","starred_url":"https://api.github.com/users/jedouard98/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jedouard98/subscriptions","organizations_url":"https://api.github.com/users/jedouard98/orgs","repos_url":"https://api.github.com/users/jedouard98/repos","events_url":"https://api.github.com/users/jedouard98/events{/privacy}","received_events_url":"https://api.github.com/users/jedouard98/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/jedouard98/play-instant-unity-plugin","description":"The Google Play Instant Plugin for Unity Beta : Simplifies conversion of a Unity-based Android app into an instant app that can be deployed through Google Play Instant.","fork":true,"url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin","forks_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/forks","keys_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/teams","hooks_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/hooks","issue_events_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/issues/events{/number}","events_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/events","assignees_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/assignees{/user}","branches_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/branches{/branch}","tags_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/tags","blobs_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/git/refs{/sha}","trees_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/statuses/{sha}","languages_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/languages","stargazers_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/stargazers","contributors_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/contributors","subscribers_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/subscribers","subscription_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/subscription","commits_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/commits{/sha}","git_commits_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/git/commits{/sha}","comments_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/comments{/number}","issue_comment_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/issues/comments{/number}","contents_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/contents/{+path}","compare_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/merges","archive_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/downloads","issues_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/issues{/number}","pulls_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/pulls{/number}","milestones_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/milestones{/number}","notifications_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/labels{/name}","releases_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/releases{/id}","deployments_url":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/deployments","created_at":"2018-07-02T21:04:49Z","updated_at":"2018-08-08T23:30:24Z","pushed_at":"2018-08-09T16:23:06Z","git_url":"git://github.com/jedouard98/play-instant-unity-plugin.git","ssh_url":"git@github.com:jedouard98/play-instant-unity-plugin.git","clone_url":"https://github.com/jedouard98/play-instant-unity-plugin.git","svn_url":"https://github.com/jedouard98/play-instant-unity-plugin","homepage":"","size":283,"stargazers_count":1,"watchers_count":1,"language":"C#","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":5,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":0,"open_issues":5,"watchers":1,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/pulls/12"},"html":{"href":"https://github.com/jedouard98/play-instant-unity-plugin/pull/12"},"issue":{"href":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/issues/12"},"comments":{"href":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/issues/12/comments"},"review_comments":{"href":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/pulls/12/comments"},"review_comment":{"href":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/pulls/12/commits"},"statuses":{"href":"https://api.github.com/repos/jedouard98/play-instant-unity-plugin/statuses/b91d4bd3bc32ddc832aa9e12f19df8afc2b89621"}},"author_association":"COLLABORATOR"}}
{"actor":{"display_login":"thanwah"}}