{"action":"created","comment":{"url":"https://api.github.com/repos/Weasyl/weasyl/pulls/comments/70172527","id":70172527,"diff_hunk":"@@ -0,0 +1,536 @@\n+# This Python file uses the following encoding: utf-8\n+import unittest\n+import pytest\n+import py\n+import bcrypt\n+import arrow\n+import web\n+import os\n+import json\n+\n+import db_utils\n+from weasyl import login, macro\n+from weasyl import define as d\n+from weasyl.error import WeasylError\n+\n+\n+\"\"\"\n+Section containing functions used within this suite of tests.\n+\"\"\"\n+# Main test account\n+raw_password = \"0123456789\"\n+class TestFunctions():\n+    def generateTokenString(self, size):\n+        import random\n+        import string\n+        return \"\".join(random.SystemRandom().choice(string.ascii_letters + string.digits) for i in range(size))\n+\n+class Bag(object):\n+    def __init__(self, **kw):\n+        for kv in kw.items():\n+            setattr(self, *kv)\n+\n+\"\"\"\n+Test section for: login.py::def signin(userid):\n+\"\"\"\n+def testSignin_VerifyLoginRecordIsUpdated():\n+    user = db_utils.create_user(return_user_definition=True)\n+    d.engine.execute(\"UPDATE login SET last_login = -1 WHERE userid = %(id)s\", id=user['id'])\n+    # login.signin(user_id) -will- raise an AttributeError when d.web.ctx.weasyl_session\n+    #   tries to execute itself; so catch/handle; it's a test environment issue\n+    with pytest.raises(AttributeError) as err:\n+        login.signin(user['id'])\n+    print str(err)\n+    last_login = d.engine.scalar(\"SELECT last_login FROM login WHERE userid = %(id)s\", id=user['id'])\n+    assert last_login > -1\n+\n+\"\"\"\n+Test section for: login.py::def authenticate_bcrypt(username, password, session=True):\n+\"\"\"\n+def testAuthenticateBcrypt_NoUsernameProvided():\n+    result = login.authenticate_bcrypt(username='', password='password')\n+    assert result == (0, 'invalid')\n+\n+def testAuthenticateBcrypt_NoPasswordProvided():\n+    user_name = \"NoPasswordProvided\"\n+    result = login.authenticate_bcrypt(username=user_name, password='')\n+    assert result == (0, 'invalid')\n+\n+def testAuthenticateBcrypt_InvalidUsernameProvided():\n+    user_name = \"InvalidUsernameProvided\"\n+    result = login.authenticate_bcrypt(username=user_name, password=raw_password)\n+    assert result == (0, 'invalid')\n+\n+def testAuthenticateBcrypt_VerifyLoginFailsForAllUsersIfIncorrectPasswordProvided():\n+    random_password = \"ThisIsARandomPassword\"\n+    user = db_utils.create_user(password=random_password, return_user_definition=True)\n+    another_random_password = \"ThisIsNotTheSamePassword\"\n+    result = login.authenticate_bcrypt(username=user['name'], password=another_random_password)\n+    assert result == (0, 'invalid')\n+\n+def testAuthenticateBcrypt_LoginFailsForModsWithInvalidAuthentication(tmpdir, monkeypatch):\n+    # Set the temporary directory for the log file\n+    monkeypatch.setenv(macro.MACRO_SYS_LOG_PATH, tmpdir + \"/\")\n+    log_path = '%s%s.%s.log' % (macro.MACRO_SYS_LOG_PATH, 'login.fail', d.get_timestamp())\n+    mod_userid = 2061\n+    user_id = db_utils.create_user(username='ikani', password=raw_password, user_id=mod_userid)\n+    # Ensure we are actually writing to the file by counting the file's lines\n+    prerun_loglines = 0\n+    # The file might not exist; this is fine; ignore\n+    try:\n+        with open(log_path, 'r') as log:\n+            for line in log:\n+                prerun_loglines += 1\n+            log.close()\n+    except IOError:\n+        pass\n+    postrun_loglines = 0\n+    # Item under test\n+    result = login.authenticate_bcrypt(username='ikani', password='FakePassword')\n+    # Verify we are writing to the log file as expected\n+    last_line = ''\n+    with open(log_path, 'r') as log:\n+        for line in log:\n+            postrun_loglines += 1\n+        last_line = line\n+        log.close()\n+    last_line_dict = json.loads(last_line)\n+    assert postrun_loglines > prerun_loglines\n+    assert last_line_dict['userid'] == mod_userid\n+    assert result == (0, 'invalid')\n+\n+def testAuthenticateBcrypt_LoginFailsForBannedUsers():\n+    user = db_utils.create_user(password=raw_password, return_user_definition=True)\n+    d.engine.execute(\"UPDATE login SET settings = 'b' WHERE userid = %(id)s\", id=user['id'])\n+    result = login.authenticate_bcrypt(username=user['name'], password=raw_password)\n+    assert result == (user['id'], 'banned')\n+\n+def testAuthenticateBcrypt_LoginFailsForSuspendedUsersWithActiveDuration():\n+    user = db_utils.create_user(password=raw_password, return_user_definition=True)\n+    d.engine.execute(\"UPDATE login SET settings = 's' WHERE userid = %(id)s\", id=user['id'])\n+    release_date = d.convert_unixdate(31, 12, 2030)\n+    d.engine.execute(\"INSERT INTO suspension VALUES (%(id)s, %(reason)s, %(rel)s)\",\n+                     id=user['id'], reason='test', rel=release_date)\n+    result = login.authenticate_bcrypt(username=user['name'], password=raw_password, session=False)\n+    assert result == (user['id'], 'suspended')\n+\n+def testAuthenticateBcrypt_LoginSucceedsForSuspendedUsersWithExpiredDuration():\n+    user = db_utils.create_user(password=raw_password, return_user_definition=True)\n+    d.engine.execute(\"UPDATE login SET settings = 's' WHERE userid = %(id)s\", id=user['id'])\n+    release_date = d.convert_unixdate(31, 12, 2015)\n+    d.engine.execute(\"INSERT INTO suspension VALUES (%(id)s, %(reason)s, %(rel)s)\",\n+                     id=user['id'], reason='test', rel=release_date)\n+    result = login.authenticate_bcrypt(username=user['name'], password=raw_password, session=False)\n+    assert result == (user['id'], None)\n+\n+def testAuthenticateBcrypt_LoginSucceedsForValidUserAndPasswordWithUnicodeFailure():\n+    user = db_utils.create_user(password=raw_password, return_user_definition=True)\n+    # This hash decodes to \"password\"\n+    old_2a_bcrypt_hash = \"$2a$12$qReI924/8pAsoHu6aRTX2ejyujAZ/9FiOOtrjczBIwf8wqXAJ22N.\"\n+    d.engine.execute(\"UPDATE authbcrypt SET hashsum = %(hash)s WHERE userid = %(id)s\",\n+                     hash=old_2a_bcrypt_hash, id=user['id'])\n+    result = login.authenticate_bcrypt(user['name'], u\"passwordé\", session=False)\n+    assert result == (user['id'], 'unicode-failure')\n+\n+def testAuthenticateBcrypt_LoginSucceedsForValidUserAndPassword():\n+    user = db_utils.create_user(password=raw_password, return_user_definition=True)\n+    result = login.authenticate_bcrypt(username=user['name'], password=raw_password, session=False)\n+    assert result == (user['id'], None)\n+\n+\"\"\"\n+Test section for functions:\n+a) login.py::def password_secure(password):\n+b) login.py::def passhash(password):\n+\"\"\"\n+def test_password_secure__verify_it_functions_as_expected():\n+    # Length too short (len < login._PASSWORD)\n+    test_string = \"\"\n+    for i in range(0, login._PASSWORD):\n+        assert not login.password_secure(test_string)\n+        test_string = test_string + 'a'\n+\n+    # Acceptable length (len >= 10)\n+    for i in range(login._PASSWORD, login._PASSWORD + 3):\n+        test_string = test_string + 'a'\n+        assert login.password_secure(test_string)\n+\n+def test_passhash__verify_it_functions_as_expected():","path":"weasyl/test/test_login.py","position":157,"original_position":157,"commit_id":"7cf63e869e9e3b65fb48253d1a7808ccadbaa84f","original_commit_id":"7cf63e869e9e3b65fb48253d1a7808ccadbaa84f","user":{"login":"charmander","id":1889843,"avatar_url":"https://avatars.githubusercontent.com/u/1889843?v=3","gravatar_id":"","url":"https://api.github.com/users/charmander","html_url":"https://github.com/charmander","followers_url":"https://api.github.com/users/charmander/followers","following_url":"https://api.github.com/users/charmander/following{/other_user}","gists_url":"https://api.github.com/users/charmander/gists{/gist_id}","starred_url":"https://api.github.com/users/charmander/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/charmander/subscriptions","organizations_url":"https://api.github.com/users/charmander/orgs","repos_url":"https://api.github.com/users/charmander/repos","events_url":"https://api.github.com/users/charmander/events{/privacy}","received_events_url":"https://api.github.com/users/charmander/received_events","type":"User","site_admin":false},"body":"Just call it `test_passhash()`.","created_at":"2016-07-09T21:59:04Z","updated_at":"2016-07-09T21:59:04Z","html_url":"https://github.com/Weasyl/weasyl/pull/92#discussion_r70172527","pull_request_url":"https://api.github.com/repos/Weasyl/weasyl/pulls/92","_links":{"self":{"href":"https://api.github.com/repos/Weasyl/weasyl/pulls/comments/70172527"},"html":{"href":"https://github.com/Weasyl/weasyl/pull/92#discussion_r70172527"},"pull_request":{"href":"https://api.github.com/repos/Weasyl/weasyl/pulls/92"}}},"pull_request":{"url":"https://api.github.com/repos/Weasyl/weasyl/pulls/92","id":76079335,"html_url":"https://github.com/Weasyl/weasyl/pull/92","diff_url":"https://github.com/Weasyl/weasyl/pull/92.diff","patch_url":"https://github.com/Weasyl/weasyl/pull/92.patch","issue_url":"https://api.github.com/repos/Weasyl/weasyl/issues/92","number":92,"state":"open","locked":false,"title":"Enhance Unit Tests","user":{"login":"kfkitsune","id":19718911,"avatar_url":"https://avatars.githubusercontent.com/u/19718911?v=3","gravatar_id":"","url":"https://api.github.com/users/kfkitsune","html_url":"https://github.com/kfkitsune","followers_url":"https://api.github.com/users/kfkitsune/followers","following_url":"https://api.github.com/users/kfkitsune/following{/other_user}","gists_url":"https://api.github.com/users/kfkitsune/gists{/gist_id}","starred_url":"https://api.github.com/users/kfkitsune/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kfkitsune/subscriptions","organizations_url":"https://api.github.com/users/kfkitsune/orgs","repos_url":"https://api.github.com/users/kfkitsune/repos","events_url":"https://api.github.com/users/kfkitsune/events{/privacy}","received_events_url":"https://api.github.com/users/kfkitsune/received_events","type":"User","site_admin":false},"body":"TODO:\r\n\r\n- [x] Enhance ``weasyl/login.py``'s unit tests (renames ``weasyl/test/test_utilities.py`` to ``weasyl/test/test_login.py``; GH detects this as a delete/create.)\r\n- [x] Fixes ``weasyl/login.py:def sessionid(userid)``. The table ``usersession`` does not exist; substituted in the ``sessions`` table for this query. This was detected during creation of the unit tests.\r\n- [x] Figure out how to actually use PyTest to make a temporary directory to set ``macro.MACRO_SYS_LOG_PATH`` to. Currently the tests use a hackish workaround to ensure that the file is being written to as expected.\r\n- [x] Write tests for ``weasyl/useralias.py`` (coverage before: 0%)\r\n- [x] Write tests for ``weasyl/resetpassword.py`` (coverage before: 0%)\r\n- [x] Fixes ``resetpassword.py:def force(userid, form)``; function previously attempted to use a ``userid`` within the ``form``object, however the code calling this from ``weasyl/controllers/user.py`` does not include a ``userid`` attribute within the passed form object. Detected during creation of the unit tests.\r\n\r\n----\r\n\r\nThis PR is ready for merging. I might work on additional unit tests later.\r\n\r\n","created_at":"2016-07-03T02:39:21Z","updated_at":"2016-07-09T21:59:04Z","closed_at":null,"merged_at":null,"merge_commit_sha":"10acad66f827059221aa0c2f33ac31b7212ab513","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/Weasyl/weasyl/pulls/92/commits","review_comments_url":"https://api.github.com/repos/Weasyl/weasyl/pulls/92/comments","review_comment_url":"https://api.github.com/repos/Weasyl/weasyl/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Weasyl/weasyl/issues/92/comments","statuses_url":"https://api.github.com/repos/Weasyl/weasyl/statuses/7cf63e869e9e3b65fb48253d1a7808ccadbaa84f","head":{"label":"kfkitsune:add-more-unittests","ref":"add-more-unittests","sha":"7cf63e869e9e3b65fb48253d1a7808ccadbaa84f","user":{"login":"kfkitsune","id":19718911,"avatar_url":"https://avatars.githubusercontent.com/u/19718911?v=3","gravatar_id":"","url":"https://api.github.com/users/kfkitsune","html_url":"https://github.com/kfkitsune","followers_url":"https://api.github.com/users/kfkitsune/followers","following_url":"https://api.github.com/users/kfkitsune/following{/other_user}","gists_url":"https://api.github.com/users/kfkitsune/gists{/gist_id}","starred_url":"https://api.github.com/users/kfkitsune/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kfkitsune/subscriptions","organizations_url":"https://api.github.com/users/kfkitsune/orgs","repos_url":"https://api.github.com/users/kfkitsune/repos","events_url":"https://api.github.com/users/kfkitsune/events{/privacy}","received_events_url":"https://api.github.com/users/kfkitsune/received_events","type":"User","site_admin":false},"repo":{"id":60300859,"name":"weasyl","full_name":"kfkitsune/weasyl","owner":{"login":"kfkitsune","id":19718911,"avatar_url":"https://avatars.githubusercontent.com/u/19718911?v=3","gravatar_id":"","url":"https://api.github.com/users/kfkitsune","html_url":"https://github.com/kfkitsune","followers_url":"https://api.github.com/users/kfkitsune/followers","following_url":"https://api.github.com/users/kfkitsune/following{/other_user}","gists_url":"https://api.github.com/users/kfkitsune/gists{/gist_id}","starred_url":"https://api.github.com/users/kfkitsune/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kfkitsune/subscriptions","organizations_url":"https://api.github.com/users/kfkitsune/orgs","repos_url":"https://api.github.com/users/kfkitsune/repos","events_url":"https://api.github.com/users/kfkitsune/events{/privacy}","received_events_url":"https://api.github.com/users/kfkitsune/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/kfkitsune/weasyl","description":"The website.","fork":true,"url":"https://api.github.com/repos/kfkitsune/weasyl","forks_url":"https://api.github.com/repos/kfkitsune/weasyl/forks","keys_url":"https://api.github.com/repos/kfkitsune/weasyl/keys{/key_id}","collaborators_url":"https://api.github.com/repos/kfkitsune/weasyl/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/kfkitsune/weasyl/teams","hooks_url":"https://api.github.com/repos/kfkitsune/weasyl/hooks","issue_events_url":"https://api.github.com/repos/kfkitsune/weasyl/issues/events{/number}","events_url":"https://api.github.com/repos/kfkitsune/weasyl/events","assignees_url":"https://api.github.com/repos/kfkitsune/weasyl/assignees{/user}","branches_url":"https://api.github.com/repos/kfkitsune/weasyl/branches{/branch}","tags_url":"https://api.github.com/repos/kfkitsune/weasyl/tags","blobs_url":"https://api.github.com/repos/kfkitsune/weasyl/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/kfkitsune/weasyl/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/kfkitsune/weasyl/git/refs{/sha}","trees_url":"https://api.github.com/repos/kfkitsune/weasyl/git/trees{/sha}","statuses_url":"https://api.github.com/repos/kfkitsune/weasyl/statuses/{sha}","languages_url":"https://api.github.com/repos/kfkitsune/weasyl/languages","stargazers_url":"https://api.github.com/repos/kfkitsune/weasyl/stargazers","contributors_url":"https://api.github.com/repos/kfkitsune/weasyl/contributors","subscribers_url":"https://api.github.com/repos/kfkitsune/weasyl/subscribers","subscription_url":"https://api.github.com/repos/kfkitsune/weasyl/subscription","commits_url":"https://api.github.com/repos/kfkitsune/weasyl/commits{/sha}","git_commits_url":"https://api.github.com/repos/kfkitsune/weasyl/git/commits{/sha}","comments_url":"https://api.github.com/repos/kfkitsune/weasyl/comments{/number}","issue_comment_url":"https://api.github.com/repos/kfkitsune/weasyl/issues/comments{/number}","contents_url":"https://api.github.com/repos/kfkitsune/weasyl/contents/{+path}","compare_url":"https://api.github.com/repos/kfkitsune/weasyl/compare/{base}...{head}","merges_url":"https://api.github.com/repos/kfkitsune/weasyl/merges","archive_url":"https://api.github.com/repos/kfkitsune/weasyl/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/kfkitsune/weasyl/downloads","issues_url":"https://api.github.com/repos/kfkitsune/weasyl/issues{/number}","pulls_url":"https://api.github.com/repos/kfkitsune/weasyl/pulls{/number}","milestones_url":"https://api.github.com/repos/kfkitsune/weasyl/milestones{/number}","notifications_url":"https://api.github.com/repos/kfkitsune/weasyl/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/kfkitsune/weasyl/labels{/name}","releases_url":"https://api.github.com/repos/kfkitsune/weasyl/releases{/id}","deployments_url":"https://api.github.com/repos/kfkitsune/weasyl/deployments","created_at":"2016-06-02T22:13:26Z","updated_at":"2016-06-02T22:13:27Z","pushed_at":"2016-07-09T18:38:19Z","git_url":"git://github.com/kfkitsune/weasyl.git","ssh_url":"git@github.com:kfkitsune/weasyl.git","clone_url":"https://github.com/kfkitsune/weasyl.git","svn_url":"https://github.com/kfkitsune/weasyl","homepage":"https://www.weasyl.com/","size":3116,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","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":"Weasyl:master","ref":"master","sha":"3d8974809fda3ec091f065d7124d7f63487e7cec","user":{"login":"Weasyl","id":2838769,"avatar_url":"https://avatars.githubusercontent.com/u/2838769?v=3","gravatar_id":"","url":"https://api.github.com/users/Weasyl","html_url":"https://github.com/Weasyl","followers_url":"https://api.github.com/users/Weasyl/followers","following_url":"https://api.github.com/users/Weasyl/following{/other_user}","gists_url":"https://api.github.com/users/Weasyl/gists{/gist_id}","starred_url":"https://api.github.com/users/Weasyl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Weasyl/subscriptions","organizations_url":"https://api.github.com/users/Weasyl/orgs","repos_url":"https://api.github.com/users/Weasyl/repos","events_url":"https://api.github.com/users/Weasyl/events{/privacy}","received_events_url":"https://api.github.com/users/Weasyl/received_events","type":"Organization","site_admin":false},"repo":{"id":58244355,"name":"weasyl","full_name":"Weasyl/weasyl","owner":{"login":"Weasyl","id":2838769,"avatar_url":"https://avatars.githubusercontent.com/u/2838769?v=3","gravatar_id":"","url":"https://api.github.com/users/Weasyl","html_url":"https://github.com/Weasyl","followers_url":"https://api.github.com/users/Weasyl/followers","following_url":"https://api.github.com/users/Weasyl/following{/other_user}","gists_url":"https://api.github.com/users/Weasyl/gists{/gist_id}","starred_url":"https://api.github.com/users/Weasyl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Weasyl/subscriptions","organizations_url":"https://api.github.com/users/Weasyl/orgs","repos_url":"https://api.github.com/users/Weasyl/repos","events_url":"https://api.github.com/users/Weasyl/events{/privacy}","received_events_url":"https://api.github.com/users/Weasyl/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Weasyl/weasyl","description":"The website.","fork":false,"url":"https://api.github.com/repos/Weasyl/weasyl","forks_url":"https://api.github.com/repos/Weasyl/weasyl/forks","keys_url":"https://api.github.com/repos/Weasyl/weasyl/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Weasyl/weasyl/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Weasyl/weasyl/teams","hooks_url":"https://api.github.com/repos/Weasyl/weasyl/hooks","issue_events_url":"https://api.github.com/repos/Weasyl/weasyl/issues/events{/number}","events_url":"https://api.github.com/repos/Weasyl/weasyl/events","assignees_url":"https://api.github.com/repos/Weasyl/weasyl/assignees{/user}","branches_url":"https://api.github.com/repos/Weasyl/weasyl/branches{/branch}","tags_url":"https://api.github.com/repos/Weasyl/weasyl/tags","blobs_url":"https://api.github.com/repos/Weasyl/weasyl/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Weasyl/weasyl/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Weasyl/weasyl/git/refs{/sha}","trees_url":"https://api.github.com/repos/Weasyl/weasyl/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Weasyl/weasyl/statuses/{sha}","languages_url":"https://api.github.com/repos/Weasyl/weasyl/languages","stargazers_url":"https://api.github.com/repos/Weasyl/weasyl/stargazers","contributors_url":"https://api.github.com/repos/Weasyl/weasyl/contributors","subscribers_url":"https://api.github.com/repos/Weasyl/weasyl/subscribers","subscription_url":"https://api.github.com/repos/Weasyl/weasyl/subscription","commits_url":"https://api.github.com/repos/Weasyl/weasyl/commits{/sha}","git_commits_url":"https://api.github.com/repos/Weasyl/weasyl/git/commits{/sha}","comments_url":"https://api.github.com/repos/Weasyl/weasyl/comments{/number}","issue_comment_url":"https://api.github.com/repos/Weasyl/weasyl/issues/comments{/number}","contents_url":"https://api.github.com/repos/Weasyl/weasyl/contents/{+path}","compare_url":"https://api.github.com/repos/Weasyl/weasyl/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Weasyl/weasyl/merges","archive_url":"https://api.github.com/repos/Weasyl/weasyl/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Weasyl/weasyl/downloads","issues_url":"https://api.github.com/repos/Weasyl/weasyl/issues{/number}","pulls_url":"https://api.github.com/repos/Weasyl/weasyl/pulls{/number}","milestones_url":"https://api.github.com/repos/Weasyl/weasyl/milestones{/number}","notifications_url":"https://api.github.com/repos/Weasyl/weasyl/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Weasyl/weasyl/labels{/name}","releases_url":"https://api.github.com/repos/Weasyl/weasyl/releases{/id}","deployments_url":"https://api.github.com/repos/Weasyl/weasyl/deployments","created_at":"2016-05-07T01:53:26Z","updated_at":"2016-07-02T22:11:44Z","pushed_at":"2016-07-09T18:38:19Z","git_url":"git://github.com/Weasyl/weasyl.git","ssh_url":"git@github.com:Weasyl/weasyl.git","clone_url":"https://github.com/Weasyl/weasyl.git","svn_url":"https://github.com/Weasyl/weasyl","homepage":"https://www.weasyl.com/","size":3417,"stargazers_count":53,"watchers_count":53,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":14,"mirror_url":null,"open_issues_count":34,"forks":14,"open_issues":34,"watchers":53,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Weasyl/weasyl/pulls/92"},"html":{"href":"https://github.com/Weasyl/weasyl/pull/92"},"issue":{"href":"https://api.github.com/repos/Weasyl/weasyl/issues/92"},"comments":{"href":"https://api.github.com/repos/Weasyl/weasyl/issues/92/comments"},"review_comments":{"href":"https://api.github.com/repos/Weasyl/weasyl/pulls/92/comments"},"review_comment":{"href":"https://api.github.com/repos/Weasyl/weasyl/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Weasyl/weasyl/pulls/92/commits"},"statuses":{"href":"https://api.github.com/repos/Weasyl/weasyl/statuses/7cf63e869e9e3b65fb48253d1a7808ccadbaa84f"}}}}
{"actor":{"display_login":"charmander"}}