Skip to content

Commit

Permalink
github: improve GraphQL support in comment and user handling
Browse files Browse the repository at this point in the history
  • Loading branch information
snarfed committed Jul 6, 2018
1 parent 24da46f commit bd10cf4
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 15 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ Changelog
* `get_activities()` and `get_comment()` now return `ValueError` instead of `AssertionError` on malformed `activity_id` and `comment_id` args, respectively.
* `get_activities()` bug fix for issues/PRs with no body text.
* Switch from GraphQL to REST API for creating comments and reactions, since GraphQL hits authorization errors on many org repos. ([snarfed/bridgy#824](https://github.com/snarfed/bridgy/issues/824))
* Improve GraphQL support for comments and users.
* Atom:
* Shorten and ellipsize feed title when necessary ([#144](https://github.com/snarfed/granary/issues/144)).
Expand Down
44 changes: 30 additions & 14 deletions granary/github.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@
REST_API_MARKDOWN = REST_API_BASE + '/markdown'
REST_API_NOTIFICATIONS = REST_API_BASE + '/notifications?all=true&participating=true'
GRAPHQL_BASE = 'https://api.github.com/graphql'
GRAPHQL_USER_FIELDS = 'id avatarUrl bio company createdAt location login name websiteUrl' # not email, it requires an additional oauth scope
GRAPHQL_BOT_FIELDS = 'id avatarUrl createdAt login url'
GRAPHQL_ORG_FIELDS = 'id avatarUrl description location login name url websiteUrl'
GRAPHQL_USER_FIELDS = 'id avatarUrl bio company createdAt location login name url websiteUrl' # not email, it requires an additional oauth scope
GRAPHQL_USER = """
query {
user(login: "%(login)s") {
Expand Down Expand Up @@ -113,7 +115,14 @@
GRAPHQL_COMMENT = """
query {
node(id:"%(id)s") {
... on IssueComment {body}
... on IssueComment {
id url body createdAt
author {
... on Bot {""" + GRAPHQL_BOT_FIELDS + """}
... on Organization {""" + GRAPHQL_ORG_FIELDS + """}
... on User {""" + GRAPHQL_USER_FIELDS + """}
}
}
}
}
"""
Expand Down Expand Up @@ -399,16 +408,20 @@ def get_comment(self, comment_id, **kwargs):
"""Fetches and returns a comment.
Args:
comment_id: string comment id, of the form REPO-OWNER_REPO-NAME_ID,
e.g. snarfed:bridgy:456789
comment_id: string comment id (either REST or GraphQL), of the form
REPO-OWNER_REPO-NAME_ID, e.g. snarfed:bridgy:456789
Returns: dict, an ActivityStreams comment object
"""
parts = tuple(comment_id.split(':'))
if len(parts) != 3:
raise ValueError('GitHub comment ids must be of the form USER:REPO:COMMENT_ID')

comment = self.rest(REST_API_COMMENT % parts).json()
if util.is_int(parts[2]): # REST API id
comment = self.rest(REST_API_COMMENT % parts).json()
else: # GraphQL node id
comment = self.graphql(GRAPHQL_COMMENT, {'id': parts[2]})['node']

return self.comment_to_object(comment)

def render_markdown(self, markdown, owner, repo):
Expand Down Expand Up @@ -808,26 +821,29 @@ def user_to_actor(cls, user):
return actor

username = user.get('login')
bio = user.get('bio')
desc = user.get('bio') or user.get('description')

actor.update({
# TODO: orgs, bots
'objectType': 'person',
'displayName': user.get('name') or username,
'username': username,
'email': user.get('email'),
'description': bio,
'summary': bio,
'image': {'url': user.get('avatarUrl') or user.get('avatar_url')},
'description': desc,
'summary': desc,
'image': {'url': user.get('avatarUrl') or user.get('avatar_url') or user.get('url')},
'location': {'displayName': user.get('location')},
})

# extract web site links. extract_links uniquifies and preserves order
urls = sum((util.extract_links(user.get(field)) for field in
('websiteUrl', # GraphQL
'blog', # REST
'bio', # both
)), [])
urls = sum((util.extract_links(user.get(field)) for field in (
'websiteUrl', # GraphQL
'blog', # REST
'bio', # both
'html_url', # REST
'url', # both
)), [])
urls = [u for u in urls if util.domain_from_link(u) != 'api.github.com']
if urls:
actor['url'] = urls[0]
if len(urls) > 1:
Expand Down
13 changes: 12 additions & 1 deletion granary/test/test_github.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from granary import github
from granary.github import (
GRAPHQL_BASE,
GRAPHQL_COMMENT,
REACTIONS_REST_CHARS,
REST_API_COMMENT,
REST_API_COMMENT_REACTIONS,
Expand Down Expand Up @@ -87,6 +88,7 @@ def tag_uri(name):
'urls': [
{'value': 'https://snarfed.org/'},
{'value': 'https://brid.gy/'},
{'value': 'https://github.com/snarfed'},
],
'username': 'snarfed',
'email': 'github@ryanb.org',
Expand Down Expand Up @@ -613,11 +615,20 @@ def test_issue_to_object_minimal(self):
def test_issue_to_object_empty(self):
self.assert_equals({}, self.gh.issue_to_object({}))

def test_get_comment(self):
def test_get_comment_rest(self):
self.expect_rest(REST_API_COMMENT % ('foo', 'bar', 123), COMMENT_REST)
self.mox.ReplayAll()
self.assert_equals(COMMENT_OBJ, self.gh.get_comment('foo:bar:123'))

def test_get_comment_graphql(self):
self.expect_graphql(json={'query': GRAPHQL_COMMENT % {'id': 'abc'}},
response={'node': COMMENT_GRAPHQL})
self.mox.ReplayAll()

obj = copy.deepcopy(COMMENT_OBJ)
obj['id'] = 'tag:github.com:foo:bar:MDEwOlNQ=='
self.assert_equals(obj, self.gh.get_comment('foo:bar:abc'))

def test_get_activities_bad_comment_id(self):
for bad in 'no_colons', 'one:colon', 'fo:ur:col:ons':
with self.assertRaises(ValueError):
Expand Down

0 comments on commit bd10cf4

Please sign in to comment.