{"action":"created","comment":{"url":"https://api.github.com/repos/ppy/osu-framework/pulls/comments/181598818","pull_request_review_id":112253023,"id":181598818,"diff_hunk":"@@ -0,0 +1,200 @@\n+﻿// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.\n+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE\n+\n+using System;\n+using System.Collections.Generic;\n+using System.Linq;\n+using osu.Framework.Input.Bindings;\n+using osu.Framework.Logging;\n+using osu.Framework.MathUtils;\n+using osu.Framework.Platform;\n+using osu.Framework.Statistics;\n+using osu.Framework.Threading;\n+using OpenTK.Input;\n+\n+namespace osu.Framework.Input.Handlers.Joystick\n+{\n+    public class OpenTKJoystickHandler : InputHandler\n+    {\n+        private ScheduledDelegate scheduled;\n+\n+        private int mostSeenDevices;\n+        private List<JoystickDevice> devices = new List<JoystickDevice>();\n+\n+        public override bool Initialize(GameHost host)\n+        {\n+            Enabled.ValueChanged += enabled =>\n+            {\n+                if (enabled)\n+                {\n+                    host.InputThread.Scheduler.Add(scheduled = new ScheduledDelegate(delegate\n+                    {\n+                        refreshDevices();\n+\n+                        foreach (var device in devices)\n+                        {\n+                            if (device.State.Equals(device.LastState))\n+                                continue;\n+\n+                            if (device.LastState != null)\n+                            {\n+                                PendingStates.Enqueue(new InputState { Joystick = new OpenTKJoystickState(device) });\n+                                FrameStatistics.Increment(StatisticsCounterType.JoystickEvents);\n+                            }\n+                        }\n+                    }, 0, 0));\n+                }\n+                else\n+                {\n+                    scheduled?.Cancel();\n+                    devices.Clear();\n+                }\n+            };\n+\n+            Enabled.TriggerChange();\n+\n+            return true;\n+        }\n+\n+        private void refreshDevices()\n+        {\n+            var newDevices = new List<JoystickDevice>();\n+\n+            // Update devices and add them to newDevices if still connected\n+            foreach (var dev in devices)\n+            {\n+                dev.Refresh();\n+\n+                if (dev.State.IsConnected)\n+                    newDevices.Add(dev);\n+                else\n+                    mostSeenDevices--;\n+            }\n+\n+            // Find any newly-connected devices\n+            while (true)\n+            {\n+                var newDevice = new JoystickDevice(mostSeenDevices);\n+                if (!newDevice.Capabilities.IsConnected)\n+                    break;\n+\n+                Logger.Log($\"Connected joystick device: {newDevice.Guid}\", level: LogLevel.Important);\n+\n+                newDevices.Add(newDevice);\n+                mostSeenDevices++;\n+            }\n+\n+            devices = newDevices;\n+        }\n+\n+        public override bool IsActive => true;\n+        public override int Priority => 0;\n+\n+        private class OpenTKJoystickState : JoystickState\n+        {\n+            /// <summary>\n+            /// Arbitrary amount of axes supported by the osu!framework.\n+            /// We can raise this to 64 (max supported by OpenTK) with appropriate implementation in <see cref=\"InputKey\"/> if needed.\n+            /// </summary>\n+            private const int max_axes = 10;\n+\n+            /// <summary>\n+            /// Arbitrary amount of buttons supported by the osu!framework.\n+            /// We can raise this to 64 (max supported by OpenTK) with appropriate implementation in <see cref=\"InputKey\"/> if needed.\n+            /// </summary>\n+            private const int max_buttons = 20;\n+\n+            /// <summary>\n+            /// OpenTK only supports 4 hats.\n+            /// </summary>\n+            private const int max_hats = 4;\n+\n+            private const float dead_zone = 0.1f;\n+\n+            public OpenTKJoystickState(JoystickDevice device)\n+            {\n+                Axes = Enumerable.Range(0, max_axes).Select(i => device.State.GetAxis(i))\n+                                 // To not break compatibility if more axes are added in the future, pad axes to 64 elements\n+                                 .Concat(Enumerable.Repeat(0f, 64 - max_axes))\n+                                 // Convert each hat to a pair of axes\n+                                 .Concat(Enumerable.Range(0, max_hats).Select(i => device.State.GetHat(JoystickHat.Hat0 + i)).SelectMany(hatToAxes))\n+                                 .ToList();\n+\n+                var buttons = Enumerable.Range(0, max_buttons).Where(i => device.State.GetButton(i) == ButtonState.Pressed).Select(i => (JoystickButton)i).ToList();\n+\n+                for (int i = 0; i < Axes.Count; i++)\n+                {\n+                    if (Precision.AlmostEquals(Axes[i], 0, dead_zone))\n+                        continue;\n+                    buttons.Add((Axes[i] < 0 ? JoystickButton.AxisNegative1 : JoystickButton.AxisPositive1) + i);\n+                }\n+\n+                Buttons = buttons;\n+            }\n+\n+            private float[] hatToAxes(JoystickHatState hatState)\n+            {\n+                float xAxis = 0;\n+                float yAxis = 0;\n+\n+                if (hatState.IsLeft)\n+                    xAxis = -1;\n+                else if (hatState.IsRight)\n+                    xAxis = 1;\n+                if (hatState.IsDown)","path":"osu.Framework/Input/Handlers/Joystick/OpenTKJoystickHandler.cs","position":144,"original_position":144,"commit_id":"10b825525fb0250d89e398c769c76b70b19f4fcf","original_commit_id":"2320c266d62cabee84c8235c00b315ed5f188a9a","user":{"login":"smoogipoo","id":1329837,"avatar_url":"https://avatars0.githubusercontent.com/u/1329837?v=4","gravatar_id":"","url":"https://api.github.com/users/smoogipoo","html_url":"https://github.com/smoogipoo","followers_url":"https://api.github.com/users/smoogipoo/followers","following_url":"https://api.github.com/users/smoogipoo/following{/other_user}","gists_url":"https://api.github.com/users/smoogipoo/gists{/gist_id}","starred_url":"https://api.github.com/users/smoogipoo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/smoogipoo/subscriptions","organizations_url":"https://api.github.com/users/smoogipoo/orgs","repos_url":"https://api.github.com/users/smoogipoo/repos","events_url":"https://api.github.com/users/smoogipoo/events{/privacy}","received_events_url":"https://api.github.com/users/smoogipoo/received_events","type":"User","site_admin":false},"body":"What do you mean? ","created_at":"2018-04-15T22:06:04Z","updated_at":"2018-04-15T22:06:05Z","html_url":"https://github.com/ppy/osu-framework/pull/1494#discussion_r181598818","pull_request_url":"https://api.github.com/repos/ppy/osu-framework/pulls/1494","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/ppy/osu-framework/pulls/comments/181598818"},"html":{"href":"https://github.com/ppy/osu-framework/pull/1494#discussion_r181598818"},"pull_request":{"href":"https://api.github.com/repos/ppy/osu-framework/pulls/1494"}},"in_reply_to_id":181590393},"pull_request":{"url":"https://api.github.com/repos/ppy/osu-framework/pulls/1494","id":179070128,"html_url":"https://github.com/ppy/osu-framework/pull/1494","diff_url":"https://github.com/ppy/osu-framework/pull/1494.diff","patch_url":"https://github.com/ppy/osu-framework/pull/1494.patch","issue_url":"https://api.github.com/repos/ppy/osu-framework/issues/1494","number":1494,"state":"open","locked":false,"title":"Implement joystick input","user":{"login":"smoogipoo","id":1329837,"avatar_url":"https://avatars0.githubusercontent.com/u/1329837?v=4","gravatar_id":"","url":"https://api.github.com/users/smoogipoo","html_url":"https://github.com/smoogipoo","followers_url":"https://api.github.com/users/smoogipoo/followers","following_url":"https://api.github.com/users/smoogipoo/following{/other_user}","gists_url":"https://api.github.com/users/smoogipoo/gists{/gist_id}","starred_url":"https://api.github.com/users/smoogipoo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/smoogipoo/subscriptions","organizations_url":"https://api.github.com/users/smoogipoo/orgs","repos_url":"https://api.github.com/users/smoogipoo/repos","events_url":"https://api.github.com/users/smoogipoo/events{/privacy}","received_events_url":"https://api.github.com/users/smoogipoo/received_events","type":"User","site_admin":false},"body":"Axes + buttons are implemented.\r\n\r\n`IJoystickState` provices:\r\n* `Buttons`: All the pressed buttons. These include axes as buttons, which is what mania/taiko/catch(?)/osu are all going to use.\r\n* `Axes`: The raw values of all axes.\r\n* `AxisDelta()`: To get the delta for one axis.\r\n\r\nCurrently supports 20 buttons + 10 axes. We can increase this later if needed but it's already a very extreme use-case.\r\n\r\n~Hats not implemented (I don't have a controller to test these with anyway).~\r\n\r\nTested on my FP7 EMP controller.\r\n\r\nSupports keybindings (see changes in `InputKey`).","created_at":"2018-04-03T11:33:12Z","updated_at":"2018-04-15T22:06:05Z","closed_at":null,"merged_at":null,"merge_commit_sha":"18001022506a8d65c9b05beeee80b3ff41cb18d0","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":756682583,"url":"https://api.github.com/repos/ppy/osu-framework/labels/input","name":"input","color":"0b16ba","default":false}],"milestone":{"url":"https://api.github.com/repos/ppy/osu-framework/milestones/11","html_url":"https://github.com/ppy/osu-framework/milestone/11","labels_url":"https://api.github.com/repos/ppy/osu-framework/milestones/11/labels","id":3205636,"number":11,"title":"April 2018","description":"","creator":{"login":"peppy","id":191335,"avatar_url":"https://avatars3.githubusercontent.com/u/191335?v=4","gravatar_id":"","url":"https://api.github.com/users/peppy","html_url":"https://github.com/peppy","followers_url":"https://api.github.com/users/peppy/followers","following_url":"https://api.github.com/users/peppy/following{/other_user}","gists_url":"https://api.github.com/users/peppy/gists{/gist_id}","starred_url":"https://api.github.com/users/peppy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/peppy/subscriptions","organizations_url":"https://api.github.com/users/peppy/orgs","repos_url":"https://api.github.com/users/peppy/repos","events_url":"https://api.github.com/users/peppy/events{/privacy}","received_events_url":"https://api.github.com/users/peppy/received_events","type":"User","site_admin":false},"open_issues":10,"closed_issues":13,"state":"open","created_at":"2018-03-21T08:07:28Z","updated_at":"2018-04-15T18:26:58Z","due_on":"2018-04-30T07:00:00Z","closed_at":null},"commits_url":"https://api.github.com/repos/ppy/osu-framework/pulls/1494/commits","review_comments_url":"https://api.github.com/repos/ppy/osu-framework/pulls/1494/comments","review_comment_url":"https://api.github.com/repos/ppy/osu-framework/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ppy/osu-framework/issues/1494/comments","statuses_url":"https://api.github.com/repos/ppy/osu-framework/statuses/10b825525fb0250d89e398c769c76b70b19f4fcf","head":{"label":"smoogipoo:joystick","ref":"joystick","sha":"10b825525fb0250d89e398c769c76b70b19f4fcf","user":{"login":"smoogipoo","id":1329837,"avatar_url":"https://avatars0.githubusercontent.com/u/1329837?v=4","gravatar_id":"","url":"https://api.github.com/users/smoogipoo","html_url":"https://github.com/smoogipoo","followers_url":"https://api.github.com/users/smoogipoo/followers","following_url":"https://api.github.com/users/smoogipoo/following{/other_user}","gists_url":"https://api.github.com/users/smoogipoo/gists{/gist_id}","starred_url":"https://api.github.com/users/smoogipoo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/smoogipoo/subscriptions","organizations_url":"https://api.github.com/users/smoogipoo/orgs","repos_url":"https://api.github.com/users/smoogipoo/repos","events_url":"https://api.github.com/users/smoogipoo/events{/privacy}","received_events_url":"https://api.github.com/users/smoogipoo/received_events","type":"User","site_admin":false},"repo":{"id":67277282,"name":"osu-framework","full_name":"smoogipoo/osu-framework","owner":{"login":"smoogipoo","id":1329837,"avatar_url":"https://avatars0.githubusercontent.com/u/1329837?v=4","gravatar_id":"","url":"https://api.github.com/users/smoogipoo","html_url":"https://github.com/smoogipoo","followers_url":"https://api.github.com/users/smoogipoo/followers","following_url":"https://api.github.com/users/smoogipoo/following{/other_user}","gists_url":"https://api.github.com/users/smoogipoo/gists{/gist_id}","starred_url":"https://api.github.com/users/smoogipoo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/smoogipoo/subscriptions","organizations_url":"https://api.github.com/users/smoogipoo/orgs","repos_url":"https://api.github.com/users/smoogipoo/repos","events_url":"https://api.github.com/users/smoogipoo/events{/privacy}","received_events_url":"https://api.github.com/users/smoogipoo/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/smoogipoo/osu-framework","description":"A game framework written with osu! in mind.","fork":true,"url":"https://api.github.com/repos/smoogipoo/osu-framework","forks_url":"https://api.github.com/repos/smoogipoo/osu-framework/forks","keys_url":"https://api.github.com/repos/smoogipoo/osu-framework/keys{/key_id}","collaborators_url":"https://api.github.com/repos/smoogipoo/osu-framework/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/smoogipoo/osu-framework/teams","hooks_url":"https://api.github.com/repos/smoogipoo/osu-framework/hooks","issue_events_url":"https://api.github.com/repos/smoogipoo/osu-framework/issues/events{/number}","events_url":"https://api.github.com/repos/smoogipoo/osu-framework/events","assignees_url":"https://api.github.com/repos/smoogipoo/osu-framework/assignees{/user}","branches_url":"https://api.github.com/repos/smoogipoo/osu-framework/branches{/branch}","tags_url":"https://api.github.com/repos/smoogipoo/osu-framework/tags","blobs_url":"https://api.github.com/repos/smoogipoo/osu-framework/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/smoogipoo/osu-framework/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/smoogipoo/osu-framework/git/refs{/sha}","trees_url":"https://api.github.com/repos/smoogipoo/osu-framework/git/trees{/sha}","statuses_url":"https://api.github.com/repos/smoogipoo/osu-framework/statuses/{sha}","languages_url":"https://api.github.com/repos/smoogipoo/osu-framework/languages","stargazers_url":"https://api.github.com/repos/smoogipoo/osu-framework/stargazers","contributors_url":"https://api.github.com/repos/smoogipoo/osu-framework/contributors","subscribers_url":"https://api.github.com/repos/smoogipoo/osu-framework/subscribers","subscription_url":"https://api.github.com/repos/smoogipoo/osu-framework/subscription","commits_url":"https://api.github.com/repos/smoogipoo/osu-framework/commits{/sha}","git_commits_url":"https://api.github.com/repos/smoogipoo/osu-framework/git/commits{/sha}","comments_url":"https://api.github.com/repos/smoogipoo/osu-framework/comments{/number}","issue_comment_url":"https://api.github.com/repos/smoogipoo/osu-framework/issues/comments{/number}","contents_url":"https://api.github.com/repos/smoogipoo/osu-framework/contents/{+path}","compare_url":"https://api.github.com/repos/smoogipoo/osu-framework/compare/{base}...{head}","merges_url":"https://api.github.com/repos/smoogipoo/osu-framework/merges","archive_url":"https://api.github.com/repos/smoogipoo/osu-framework/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/smoogipoo/osu-framework/downloads","issues_url":"https://api.github.com/repos/smoogipoo/osu-framework/issues{/number}","pulls_url":"https://api.github.com/repos/smoogipoo/osu-framework/pulls{/number}","milestones_url":"https://api.github.com/repos/smoogipoo/osu-framework/milestones{/number}","notifications_url":"https://api.github.com/repos/smoogipoo/osu-framework/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/smoogipoo/osu-framework/labels{/name}","releases_url":"https://api.github.com/repos/smoogipoo/osu-framework/releases{/id}","deployments_url":"https://api.github.com/repos/smoogipoo/osu-framework/deployments","created_at":"2016-09-03T07:26:53Z","updated_at":"2018-04-13T11:28:57Z","pushed_at":"2018-04-15T17:40:53Z","git_url":"git://github.com/smoogipoo/osu-framework.git","ssh_url":"git@github.com:smoogipoo/osu-framework.git","clone_url":"https://github.com/smoogipoo/osu-framework.git","svn_url":"https://github.com/smoogipoo/osu-framework","homepage":"","size":24863,"stargazers_count":0,"watchers_count":0,"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":0,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit"},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"ppy:master","ref":"master","sha":"f155804739b8bf6e8e04cbdbadca88618d325a32","user":{"login":"ppy","id":995763,"avatar_url":"https://avatars1.githubusercontent.com/u/995763?v=4","gravatar_id":"","url":"https://api.github.com/users/ppy","html_url":"https://github.com/ppy","followers_url":"https://api.github.com/users/ppy/followers","following_url":"https://api.github.com/users/ppy/following{/other_user}","gists_url":"https://api.github.com/users/ppy/gists{/gist_id}","starred_url":"https://api.github.com/users/ppy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ppy/subscriptions","organizations_url":"https://api.github.com/users/ppy/orgs","repos_url":"https://api.github.com/users/ppy/repos","events_url":"https://api.github.com/users/ppy/events{/privacy}","received_events_url":"https://api.github.com/users/ppy/received_events","type":"Organization","site_admin":false},"repo":{"id":66614524,"name":"osu-framework","full_name":"ppy/osu-framework","owner":{"login":"ppy","id":995763,"avatar_url":"https://avatars1.githubusercontent.com/u/995763?v=4","gravatar_id":"","url":"https://api.github.com/users/ppy","html_url":"https://github.com/ppy","followers_url":"https://api.github.com/users/ppy/followers","following_url":"https://api.github.com/users/ppy/following{/other_user}","gists_url":"https://api.github.com/users/ppy/gists{/gist_id}","starred_url":"https://api.github.com/users/ppy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ppy/subscriptions","organizations_url":"https://api.github.com/users/ppy/orgs","repos_url":"https://api.github.com/users/ppy/repos","events_url":"https://api.github.com/users/ppy/events{/privacy}","received_events_url":"https://api.github.com/users/ppy/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ppy/osu-framework","description":"A game framework written with osu! in mind.","fork":false,"url":"https://api.github.com/repos/ppy/osu-framework","forks_url":"https://api.github.com/repos/ppy/osu-framework/forks","keys_url":"https://api.github.com/repos/ppy/osu-framework/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ppy/osu-framework/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ppy/osu-framework/teams","hooks_url":"https://api.github.com/repos/ppy/osu-framework/hooks","issue_events_url":"https://api.github.com/repos/ppy/osu-framework/issues/events{/number}","events_url":"https://api.github.com/repos/ppy/osu-framework/events","assignees_url":"https://api.github.com/repos/ppy/osu-framework/assignees{/user}","branches_url":"https://api.github.com/repos/ppy/osu-framework/branches{/branch}","tags_url":"https://api.github.com/repos/ppy/osu-framework/tags","blobs_url":"https://api.github.com/repos/ppy/osu-framework/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ppy/osu-framework/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ppy/osu-framework/git/refs{/sha}","trees_url":"https://api.github.com/repos/ppy/osu-framework/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ppy/osu-framework/statuses/{sha}","languages_url":"https://api.github.com/repos/ppy/osu-framework/languages","stargazers_url":"https://api.github.com/repos/ppy/osu-framework/stargazers","contributors_url":"https://api.github.com/repos/ppy/osu-framework/contributors","subscribers_url":"https://api.github.com/repos/ppy/osu-framework/subscribers","subscription_url":"https://api.github.com/repos/ppy/osu-framework/subscription","commits_url":"https://api.github.com/repos/ppy/osu-framework/commits{/sha}","git_commits_url":"https://api.github.com/repos/ppy/osu-framework/git/commits{/sha}","comments_url":"https://api.github.com/repos/ppy/osu-framework/comments{/number}","issue_comment_url":"https://api.github.com/repos/ppy/osu-framework/issues/comments{/number}","contents_url":"https://api.github.com/repos/ppy/osu-framework/contents/{+path}","compare_url":"https://api.github.com/repos/ppy/osu-framework/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ppy/osu-framework/merges","archive_url":"https://api.github.com/repos/ppy/osu-framework/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ppy/osu-framework/downloads","issues_url":"https://api.github.com/repos/ppy/osu-framework/issues{/number}","pulls_url":"https://api.github.com/repos/ppy/osu-framework/pulls{/number}","milestones_url":"https://api.github.com/repos/ppy/osu-framework/milestones{/number}","notifications_url":"https://api.github.com/repos/ppy/osu-framework/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ppy/osu-framework/labels{/name}","releases_url":"https://api.github.com/repos/ppy/osu-framework/releases{/id}","deployments_url":"https://api.github.com/repos/ppy/osu-framework/deployments","created_at":"2016-08-26T03:45:35Z","updated_at":"2018-04-15T20:46:47Z","pushed_at":"2018-04-15T18:24:11Z","git_url":"git://github.com/ppy/osu-framework.git","ssh_url":"git@github.com:ppy/osu-framework.git","clone_url":"https://github.com/ppy/osu-framework.git","svn_url":"https://github.com/ppy/osu-framework","homepage":"","size":26760,"stargazers_count":228,"watchers_count":228,"language":"C#","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":119,"mirror_url":null,"archived":false,"open_issues_count":74,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit"},"forks":119,"open_issues":74,"watchers":228,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/ppy/osu-framework/pulls/1494"},"html":{"href":"https://github.com/ppy/osu-framework/pull/1494"},"issue":{"href":"https://api.github.com/repos/ppy/osu-framework/issues/1494"},"comments":{"href":"https://api.github.com/repos/ppy/osu-framework/issues/1494/comments"},"review_comments":{"href":"https://api.github.com/repos/ppy/osu-framework/pulls/1494/comments"},"review_comment":{"href":"https://api.github.com/repos/ppy/osu-framework/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ppy/osu-framework/pulls/1494/commits"},"statuses":{"href":"https://api.github.com/repos/ppy/osu-framework/statuses/10b825525fb0250d89e398c769c76b70b19f4fcf"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"smoogipoo"}}