{"action":"created","comment":{"url":"https://api.github.com/repos/runelite/runelite/pulls/comments/173350955","pull_request_review_id":102528764,"id":173350955,"diff_hunk":"@@ -0,0 +1,381 @@\n+/*\n+ * Copyright (c) 2018, TheLonelyDev <https://github.com/TheLonelyDev>\n+ * Copyright (c) 2018, Jeremy Plsek <https://github.com/jplsek>\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or without\n+ * modification, are permitted provided that the following conditions are met:\n+ *\n+ * 1. Redistributions of source code must retain the above copyright notice, this\n+ *    list of conditions and the following disclaimer.\n+ * 2. Redistributions in binary form must reproduce the above copyright notice,\n+ *    this list of conditions and the following disclaimer in the documentation\n+ *    and/or other materials provided with the distribution.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\n+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package net.runelite.client.plugins.bankvalue;\n+\n+import com.google.common.eventbus.Subscribe;\n+import com.google.inject.Provides;\n+import java.io.IOException;\n+import java.util.ArrayList;\n+import java.util.List;\n+import java.util.concurrent.Callable;\n+import java.util.concurrent.ExecutorService;\n+import java.util.concurrent.Executors;\n+import java.util.concurrent.RejectedExecutionException;\n+import java.util.concurrent.atomic.AtomicLong;\n+import javax.inject.Inject;\n+import lombok.Getter;\n+import lombok.Setter;\n+import lombok.extern.slf4j.Slf4j;\n+import net.runelite.api.Client;\n+import net.runelite.api.ItemComposition;\n+import net.runelite.api.events.ConfigChanged;\n+import net.runelite.api.events.MenuOptionClicked;\n+import net.runelite.api.events.WidgetHiddenChanged;\n+import net.runelite.api.queries.BankItemQuery;\n+import net.runelite.api.widgets.Widget;\n+import net.runelite.api.widgets.WidgetID;\n+import net.runelite.api.widgets.WidgetInfo;\n+import net.runelite.api.widgets.WidgetItem;\n+import net.runelite.client.config.ConfigManager;\n+import net.runelite.client.game.ItemManager;\n+import net.runelite.client.plugins.Plugin;\n+import net.runelite.client.plugins.PluginDescriptor;\n+import net.runelite.client.util.StackFormatter;\n+import net.runelite.http.api.item.ItemPrice;\n+import static net.runelite.api.ItemID.COINS;\n+\n+@PluginDescriptor(name = \"Bank Value\")\n+@Slf4j\n+public class BankValuePlugin extends Plugin\n+{\n+\tprivate static final float HIGH_ALCHEMY_CONSTANT = 0.6f;\n+\n+\t@Inject\n+\tprivate Client client;\n+\n+\t@Inject\n+\tprivate BankValueConfig config;\n+\n+\t@Inject\n+\tprivate ItemManager itemManager;\n+\n+\tprivate Thread bankThread = null;\n+\tprivate ExecutorService executor = null;\n+\n+\t// Only meant to be used to tell if the player is in the bank (or during shutdown)\n+\tprivate boolean bankActive = false;\n+\n+\tprivate String bankTitle = \"The Bank of Runescape\";\n+\n+\t@Provides\n+\tBankValueConfig getConfig(ConfigManager configManager)\n+\t{\n+\t\treturn configManager.getConfig(BankValueConfig.class);\n+\t}\n+\n+\t@Subscribe\n+\tpublic void onConfigChanged(ConfigChanged event)\n+\t{\n+\t\tif (!event.getGroup().equals(\"Bank Value\"))\n+\t\t{\n+\t\t\treturn;\n+\t\t}\n+\n+\t\t// When changing the configuration, just reset the call.\n+\t\t// Items should be cached so it should be relatively quick to recalculate.\n+\t\t// This is mostly to avoid wrong additions while looping and getting the prices while changing\n+\t\t// the config multiple times.\n+\t\tif ((event.getKey().equals(\"showGE\") || event.getKey().equals(\"showHA\")) && bankActive)\n+\t\t{\n+\t\t\tstopThreads();\n+\t\t\tresetBankTitle();\n+\t\t\tcalculateBankWithThread();\n+\t\t}\n+\t}\n+\n+\t@Override\n+\tprotected void shutDown()\n+\t{\n+\t\tstopThreads();\n+\t\tresetBankTitle();\n+\t}\n+\n+\t@Override\n+\tprotected void startUp()\n+\t{\n+\t\tWidget widgetBankTitleBar = client.getWidget(WidgetInfo.BANK_TITLE_BAR);\n+\n+\t\tif (widgetBankTitleBar == null || widgetBankTitleBar.isHidden())\n+\t\t{\n+\t\t\treturn;\n+\t\t}\n+\n+\t\tcalculateBankWithThread();\n+\t}\n+\n+\t@Subscribe\n+\tpublic void onMenuChanged(MenuOptionClicked event)\n+\t{\n+\t\tif (!bankActive)\n+\t\t{\n+\t\t\treturn;\n+\t\t}\n+\n+\t\tString strMenuOption = event.getMenuOption();\n+\n+\t\tif (strMenuOption.contains(\"Withdraw\") ||\n+\t\t\t\tstrMenuOption.contains(\"Deposit\") ||\n+\t\t\t\tstrMenuOption.contains(\"View tab\") ||\n+\t\t\t\tstrMenuOption.contains(\"View all\"))\n+\t\t{\n+\t\t\tstopThreads();\n+\t\t\tcalculateBankWithThread();\n+\t\t}\n+\t}\n+\n+\t@Subscribe\n+\tpublic void onWidgetHidden(WidgetHiddenChanged event)\n+\t{\n+\t\t// Below is several checks to hopefully get a bank opening/closing event.\n+\t\t// If there are better events to check for this, then this should be changed.\n+\t\t// Then we we can remove the sleep() in calculateBankThread()\n+\t\tWidget widget = event.getWidget();\n+\n+\t\tint group = WidgetInfo.TO_GROUP(widget.getId());\n+\n+\t\t// This seems to be the only event sent when closing the bank\n+\t\tif (bankActive && group == WidgetID.RESIZABLE_VIEWPORT_BOTTOM_LINE_GROUP_ID && event.isHidden())\n+\t\t{\n+\t\t\tlog.debug(\"Bank closing?\");\n+\t\t\tstopThreads();\n+\t\t\treturn;\n+\t\t}\n+\n+\t\t// This event gets called a lot, so check to also see if it's are already bankActive\n+\t\t// This still does not work great, because it still gets called twice, but the first time is just a dud.\n+\t\tif (!bankActive && group == WidgetID.BANK_GROUP_ID)\n+\t\t{\n+\t\t\tcalculateBankWithThread();\n+\t\t}\n+\t}\n+\n+\tprivate void stopThreads()\n+\t{\n+\t\tbankActive = false;\n+\t\tlog.debug(\"Bank value stopping\");\n+\n+\t\tif (executor != null)\n+\t\t{\n+\t\t\texecutor.shutdownNow();\n+\t\t}\n+\n+\t\tif (bankThread != null)\n+\t\t{\n+\t\t\tbankThread.interrupt();\n+\t\t}\n+\t}\n+\n+\tprivate void calculateBankWithThread()\n+\t{\n+\t\tbankActive = true;\n+\t\tlog.debug(\"Bank value running\");\n+\t\tbankThread = new Thread(this::calculateBank);\n+\t\tbankThread.start();\n+\t}\n+\n+\tclass ItemPriceAndAlch extends ItemPrice\n+\t{\n+\t\t@Getter\n+\t\t@Setter\n+\t\tprivate int highAlchPrice;\n+\n+\t\tItemPriceAndAlch(int gePrice, int highAlchPrice)\n+\t\t{\n+\t\t\tsetPrice(gePrice);\n+\t\t\tthis.highAlchPrice = highAlchPrice;\n+\t\t}\n+\t}\n+\n+\tprivate final Object rsItemLock = new Object();\n+\n+\t/**\n+\t * Grabs the GE price, calculates the high alch price, then multiplies the quantity\n+\t * @param item\n+\t * @return\n+\t */\n+\tprivate ItemPriceAndAlch getItemPrices(WidgetItem item)\n+\t{\n+\t\tif (COINS == item.getId())\n+\t\t{\n+\t\t\treturn new ItemPriceAndAlch(item.getQuantity(), item.getQuantity());\n+\t\t}\n+\n+\t\tItemComposition itemComposition;\n+\n+\t\t// Having this lock seems to not crash runescape. I'm not sure if it's because of this method call\n+\t\t// or if it's something else that this lock is slowing down. I believe it's because this is the only\n+\t\t// place that has a possibility of accessing runescape's code.\n+\t\tsynchronized (rsItemLock)\n+\t\t{\n+\t\t\titemComposition = itemManager.getItemComposition(item.getId());","path":"runelite-client/src/main/java/net/runelite/client/plugins/bankvalue/BankValuePlugin.java","position":234,"original_position":234,"commit_id":"27c266c420c017b650c3d8d8be971b04c9df58e0","original_commit_id":"27c266c420c017b650c3d8d8be971b04c9df58e0","user":{"login":"Adam-","id":309739,"avatar_url":"https://avatars2.githubusercontent.com/u/309739?v=4","gravatar_id":"","url":"https://api.github.com/users/Adam-","html_url":"https://github.com/Adam-","followers_url":"https://api.github.com/users/Adam-/followers","following_url":"https://api.github.com/users/Adam-/following{/other_user}","gists_url":"https://api.github.com/users/Adam-/gists{/gist_id}","starred_url":"https://api.github.com/users/Adam-/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Adam-/subscriptions","organizations_url":"https://api.github.com/users/Adam-/orgs","repos_url":"https://api.github.com/users/Adam-/repos","events_url":"https://api.github.com/users/Adam-/events{/privacy}","received_events_url":"https://api.github.com/users/Adam-/received_events","type":"User","site_admin":false},"body":"It is not safe to call this from any thread other than the game thread. I would gather all of these upfront.","created_at":"2018-03-09T02:24:47Z","updated_at":"2018-03-09T02:30:30Z","html_url":"https://github.com/runelite/runelite/pull/824#discussion_r173350955","pull_request_url":"https://api.github.com/repos/runelite/runelite/pulls/824","author_association":"OWNER","_links":{"self":{"href":"https://api.github.com/repos/runelite/runelite/pulls/comments/173350955"},"html":{"href":"https://github.com/runelite/runelite/pull/824#discussion_r173350955"},"pull_request":{"href":"https://api.github.com/repos/runelite/runelite/pulls/824"}}},"pull_request":{"url":"https://api.github.com/repos/runelite/runelite/pulls/824","id":172751675,"html_url":"https://github.com/runelite/runelite/pull/824","diff_url":"https://github.com/runelite/runelite/pull/824.diff","patch_url":"https://github.com/runelite/runelite/pull/824.patch","issue_url":"https://api.github.com/repos/runelite/runelite/issues/824","number":824,"state":"open","locked":false,"title":"Bank value plugin update","user":{"login":"jplsek","id":2388657,"avatar_url":"https://avatars1.githubusercontent.com/u/2388657?v=4","gravatar_id":"","url":"https://api.github.com/users/jplsek","html_url":"https://github.com/jplsek","followers_url":"https://api.github.com/users/jplsek/followers","following_url":"https://api.github.com/users/jplsek/following{/other_user}","gists_url":"https://api.github.com/users/jplsek/gists{/gist_id}","starred_url":"https://api.github.com/users/jplsek/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jplsek/subscriptions","organizations_url":"https://api.github.com/users/jplsek/orgs","repos_url":"https://api.github.com/users/jplsek/repos","events_url":"https://api.github.com/users/jplsek/events{/privacy}","received_events_url":"https://api.github.com/users/jplsek/received_events","type":"User","site_admin":false},"body":"This is an update to TheLonelyDev's Bank Value Plugin (for #349). This ended up being mostly a rewrite of the plugin.\r\n\r\nAt the moment, the part I dislike is that the detection of the bank being active. It also only works if the player is on tab 0. I managed to get it working for all tabs in another branch (and got rid of the sleep), but it's based on the number of tabs the player has, which is not dynamic. If I figure out a way to properly get the bank event, then the whole onWidgetHidden() would get replaced. (Or if someone else figures it out, go right ahead.)\r\n\r\nI'm confident in calculateBankWithThread() (and methods used inside) and cancelThread() to work well.\r\n\r\nExceptions are not logged since they get thrown when the bank closes during the calculation. If there is requests to still log them, I will update this branch.\r\n\r\nAny suggestions are welcome. Thanks.","created_at":"2018-03-05T00:24:04Z","updated_at":"2018-03-09T02:30:30Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b670fc06ee720df52fc73c5d998cb8d6af3e70ea","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":771846940,"url":"https://api.github.com/repos/runelite/runelite/labels/feature-request","name":"feature-request","color":"fbca04","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/runelite/runelite/pulls/824/commits","review_comments_url":"https://api.github.com/repos/runelite/runelite/pulls/824/comments","review_comment_url":"https://api.github.com/repos/runelite/runelite/pulls/comments{/number}","comments_url":"https://api.github.com/repos/runelite/runelite/issues/824/comments","statuses_url":"https://api.github.com/repos/runelite/runelite/statuses/27c266c420c017b650c3d8d8be971b04c9df58e0","head":{"label":"jplsek:bank-value-update","ref":"bank-value-update","sha":"27c266c420c017b650c3d8d8be971b04c9df58e0","user":{"login":"jplsek","id":2388657,"avatar_url":"https://avatars1.githubusercontent.com/u/2388657?v=4","gravatar_id":"","url":"https://api.github.com/users/jplsek","html_url":"https://github.com/jplsek","followers_url":"https://api.github.com/users/jplsek/followers","following_url":"https://api.github.com/users/jplsek/following{/other_user}","gists_url":"https://api.github.com/users/jplsek/gists{/gist_id}","starred_url":"https://api.github.com/users/jplsek/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jplsek/subscriptions","organizations_url":"https://api.github.com/users/jplsek/orgs","repos_url":"https://api.github.com/users/jplsek/repos","events_url":"https://api.github.com/users/jplsek/events{/privacy}","received_events_url":"https://api.github.com/users/jplsek/received_events","type":"User","site_admin":false},"repo":{"id":123662589,"name":"runelite","full_name":"jplsek/runelite","owner":{"login":"jplsek","id":2388657,"avatar_url":"https://avatars1.githubusercontent.com/u/2388657?v=4","gravatar_id":"","url":"https://api.github.com/users/jplsek","html_url":"https://github.com/jplsek","followers_url":"https://api.github.com/users/jplsek/followers","following_url":"https://api.github.com/users/jplsek/following{/other_user}","gists_url":"https://api.github.com/users/jplsek/gists{/gist_id}","starred_url":"https://api.github.com/users/jplsek/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jplsek/subscriptions","organizations_url":"https://api.github.com/users/jplsek/orgs","repos_url":"https://api.github.com/users/jplsek/repos","events_url":"https://api.github.com/users/jplsek/events{/privacy}","received_events_url":"https://api.github.com/users/jplsek/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/jplsek/runelite","description":"Open source Old School RuneScape client","fork":true,"url":"https://api.github.com/repos/jplsek/runelite","forks_url":"https://api.github.com/repos/jplsek/runelite/forks","keys_url":"https://api.github.com/repos/jplsek/runelite/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jplsek/runelite/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jplsek/runelite/teams","hooks_url":"https://api.github.com/repos/jplsek/runelite/hooks","issue_events_url":"https://api.github.com/repos/jplsek/runelite/issues/events{/number}","events_url":"https://api.github.com/repos/jplsek/runelite/events","assignees_url":"https://api.github.com/repos/jplsek/runelite/assignees{/user}","branches_url":"https://api.github.com/repos/jplsek/runelite/branches{/branch}","tags_url":"https://api.github.com/repos/jplsek/runelite/tags","blobs_url":"https://api.github.com/repos/jplsek/runelite/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jplsek/runelite/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jplsek/runelite/git/refs{/sha}","trees_url":"https://api.github.com/repos/jplsek/runelite/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jplsek/runelite/statuses/{sha}","languages_url":"https://api.github.com/repos/jplsek/runelite/languages","stargazers_url":"https://api.github.com/repos/jplsek/runelite/stargazers","contributors_url":"https://api.github.com/repos/jplsek/runelite/contributors","subscribers_url":"https://api.github.com/repos/jplsek/runelite/subscribers","subscription_url":"https://api.github.com/repos/jplsek/runelite/subscription","commits_url":"https://api.github.com/repos/jplsek/runelite/commits{/sha}","git_commits_url":"https://api.github.com/repos/jplsek/runelite/git/commits{/sha}","comments_url":"https://api.github.com/repos/jplsek/runelite/comments{/number}","issue_comment_url":"https://api.github.com/repos/jplsek/runelite/issues/comments{/number}","contents_url":"https://api.github.com/repos/jplsek/runelite/contents/{+path}","compare_url":"https://api.github.com/repos/jplsek/runelite/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jplsek/runelite/merges","archive_url":"https://api.github.com/repos/jplsek/runelite/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jplsek/runelite/downloads","issues_url":"https://api.github.com/repos/jplsek/runelite/issues{/number}","pulls_url":"https://api.github.com/repos/jplsek/runelite/pulls{/number}","milestones_url":"https://api.github.com/repos/jplsek/runelite/milestones{/number}","notifications_url":"https://api.github.com/repos/jplsek/runelite/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jplsek/runelite/labels{/name}","releases_url":"https://api.github.com/repos/jplsek/runelite/releases{/id}","deployments_url":"https://api.github.com/repos/jplsek/runelite/deployments","created_at":"2018-03-03T05:31:54Z","updated_at":"2018-03-03T05:31:59Z","pushed_at":"2018-03-08T21:57:10Z","git_url":"git://github.com/jplsek/runelite.git","ssh_url":"git@github.com:jplsek/runelite.git","clone_url":"https://github.com/jplsek/runelite.git","svn_url":"https://github.com/jplsek/runelite","homepage":"https://runelite.net","size":33927,"stargazers_count":0,"watchers_count":0,"language":"Java","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":"bsd-2-clause","name":"BSD 2-Clause \"Simplified\" License","spdx_id":"BSD-2-Clause","url":"https://api.github.com/licenses/bsd-2-clause"},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"runelite:master","ref":"master","sha":"e1d3f4a6a36442563f67cbc8b59781068980f0a5","user":{"login":"runelite","id":13814776,"avatar_url":"https://avatars1.githubusercontent.com/u/13814776?v=4","gravatar_id":"","url":"https://api.github.com/users/runelite","html_url":"https://github.com/runelite","followers_url":"https://api.github.com/users/runelite/followers","following_url":"https://api.github.com/users/runelite/following{/other_user}","gists_url":"https://api.github.com/users/runelite/gists{/gist_id}","starred_url":"https://api.github.com/users/runelite/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/runelite/subscriptions","organizations_url":"https://api.github.com/users/runelite/orgs","repos_url":"https://api.github.com/users/runelite/repos","events_url":"https://api.github.com/users/runelite/events{/privacy}","received_events_url":"https://api.github.com/users/runelite/received_events","type":"Organization","site_admin":false},"repo":{"id":57461213,"name":"runelite","full_name":"runelite/runelite","owner":{"login":"runelite","id":13814776,"avatar_url":"https://avatars1.githubusercontent.com/u/13814776?v=4","gravatar_id":"","url":"https://api.github.com/users/runelite","html_url":"https://github.com/runelite","followers_url":"https://api.github.com/users/runelite/followers","following_url":"https://api.github.com/users/runelite/following{/other_user}","gists_url":"https://api.github.com/users/runelite/gists{/gist_id}","starred_url":"https://api.github.com/users/runelite/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/runelite/subscriptions","organizations_url":"https://api.github.com/users/runelite/orgs","repos_url":"https://api.github.com/users/runelite/repos","events_url":"https://api.github.com/users/runelite/events{/privacy}","received_events_url":"https://api.github.com/users/runelite/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/runelite/runelite","description":"Open source Old School RuneScape client","fork":false,"url":"https://api.github.com/repos/runelite/runelite","forks_url":"https://api.github.com/repos/runelite/runelite/forks","keys_url":"https://api.github.com/repos/runelite/runelite/keys{/key_id}","collaborators_url":"https://api.github.com/repos/runelite/runelite/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/runelite/runelite/teams","hooks_url":"https://api.github.com/repos/runelite/runelite/hooks","issue_events_url":"https://api.github.com/repos/runelite/runelite/issues/events{/number}","events_url":"https://api.github.com/repos/runelite/runelite/events","assignees_url":"https://api.github.com/repos/runelite/runelite/assignees{/user}","branches_url":"https://api.github.com/repos/runelite/runelite/branches{/branch}","tags_url":"https://api.github.com/repos/runelite/runelite/tags","blobs_url":"https://api.github.com/repos/runelite/runelite/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/runelite/runelite/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/runelite/runelite/git/refs{/sha}","trees_url":"https://api.github.com/repos/runelite/runelite/git/trees{/sha}","statuses_url":"https://api.github.com/repos/runelite/runelite/statuses/{sha}","languages_url":"https://api.github.com/repos/runelite/runelite/languages","stargazers_url":"https://api.github.com/repos/runelite/runelite/stargazers","contributors_url":"https://api.github.com/repos/runelite/runelite/contributors","subscribers_url":"https://api.github.com/repos/runelite/runelite/subscribers","subscription_url":"https://api.github.com/repos/runelite/runelite/subscription","commits_url":"https://api.github.com/repos/runelite/runelite/commits{/sha}","git_commits_url":"https://api.github.com/repos/runelite/runelite/git/commits{/sha}","comments_url":"https://api.github.com/repos/runelite/runelite/comments{/number}","issue_comment_url":"https://api.github.com/repos/runelite/runelite/issues/comments{/number}","contents_url":"https://api.github.com/repos/runelite/runelite/contents/{+path}","compare_url":"https://api.github.com/repos/runelite/runelite/compare/{base}...{head}","merges_url":"https://api.github.com/repos/runelite/runelite/merges","archive_url":"https://api.github.com/repos/runelite/runelite/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/runelite/runelite/downloads","issues_url":"https://api.github.com/repos/runelite/runelite/issues{/number}","pulls_url":"https://api.github.com/repos/runelite/runelite/pulls{/number}","milestones_url":"https://api.github.com/repos/runelite/runelite/milestones{/number}","notifications_url":"https://api.github.com/repos/runelite/runelite/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/runelite/runelite/labels{/name}","releases_url":"https://api.github.com/repos/runelite/runelite/releases{/id}","deployments_url":"https://api.github.com/repos/runelite/runelite/deployments","created_at":"2016-04-30T20:48:02Z","updated_at":"2018-03-08T15:44:20Z","pushed_at":"2018-03-09T02:19:37Z","git_url":"git://github.com/runelite/runelite.git","ssh_url":"git@github.com:runelite/runelite.git","clone_url":"https://github.com/runelite/runelite.git","svn_url":"https://github.com/runelite/runelite","homepage":"https://runelite.net","size":33907,"stargazers_count":182,"watchers_count":182,"language":"Java","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":124,"mirror_url":null,"archived":false,"open_issues_count":178,"license":{"key":"bsd-2-clause","name":"BSD 2-Clause \"Simplified\" License","spdx_id":"BSD-2-Clause","url":"https://api.github.com/licenses/bsd-2-clause"},"forks":124,"open_issues":178,"watchers":182,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/runelite/runelite/pulls/824"},"html":{"href":"https://github.com/runelite/runelite/pull/824"},"issue":{"href":"https://api.github.com/repos/runelite/runelite/issues/824"},"comments":{"href":"https://api.github.com/repos/runelite/runelite/issues/824/comments"},"review_comments":{"href":"https://api.github.com/repos/runelite/runelite/pulls/824/comments"},"review_comment":{"href":"https://api.github.com/repos/runelite/runelite/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/runelite/runelite/pulls/824/commits"},"statuses":{"href":"https://api.github.com/repos/runelite/runelite/statuses/27c266c420c017b650c3d8d8be971b04c9df58e0"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"Adam-"}}