Skip to content

Commit a07d552

Browse files
committed
update github-urllink
1 parent fb36c49 commit a07d552

File tree

3 files changed

+195
-1
lines changed

3 files changed

+195
-1
lines changed

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ test-unit: pytest
9898
.PHONY: test
9999
test: check-python-version lint pytest
100100

101+
.PHONY: format
102+
format:
103+
yapf -q $(SOURCE_GLOB)
104+
101105
.PHONY: check-python-version
102106
check-python-version:
103107
./scripts/check_python_version.py

src/wechaty/user/url_link.py

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,190 @@
77
Optional,
88
Type
99
)
10+
from urllib3 import get_host
1011
from wechaty_puppet import UrlLinkPayload, get_logger
1112

1213
from wechaty.utils.link import get_url_metadata
1314

15+
from __future__ import annotations
16+
from dataclasses import dataclass
17+
from typing import Dict, List
18+
from abc import abstractmethod
19+
from github import Github
20+
from github.Repository import Repository
21+
22+
from github.PullRequest import PullRequest
23+
from github.PullRequestComment import PullRequestComment
24+
25+
from github.Issue import Issue
26+
from github.IssueComment import IssueComment
27+
28+
from wechaty_puppet.schemas.url_link import UrlLinkPayload
1429

1530

1631
log = get_logger('UrlLink')
1732

1833

34+
class UrlLinkParser:
35+
# valid host-name of one parser
36+
host_names: List[str] = []
37+
38+
@classmethod
39+
def can_parser(cls, url: str) -> bool:
40+
if not cls.host_names:
41+
raise ValueError(f"please set valid host-names for parser, eg: ['github']")
42+
43+
_, host_name, _ = get_host(url)
44+
return host_name in cls.host_names
45+
46+
@abstractmethod
47+
def parse(self, url: str) -> UrlLinkPayload:
48+
raise NotImplementedError("<parse> method must be overried by sub-class of <UrlLinkParser>")
49+
50+
51+
class GithubUrlLinkParser(UrlLinkParser):
52+
"""Parse Urllink by url"""
53+
54+
host_names: List[str] = ['github']
55+
56+
def __init__(self, token: Optional[str] = None):
57+
self._github = Github(login_or_token=token)
58+
self._repositories: Dict[str, Repository] = {}
59+
60+
@staticmethod
61+
def can_parser(url: str) -> bool:
62+
"""the source of url
63+
64+
Args:
65+
url (str): github urllink
66+
67+
Returns:
68+
bool: wheter is github based urll
69+
"""
70+
_, host_name, _ = get_host(url)
71+
return host_name
72+
73+
def parse(self, url: str) -> UrlLinkPayload:
74+
"""parse url-link as payload
75+
76+
Args:
77+
url (str): the url-of link
78+
79+
Returns:
80+
UrlLinkPayload: the instance of final url-link payload
81+
"""
82+
pass
83+
84+
def get_repo(self, repo_name: str) -> Repository:
85+
"""get Repository instance which can fetch the issue/pull-request info
86+
87+
Args:
88+
repo_name (str): the full name of repo, eg: wechaty/python-wechaty
89+
90+
Returns:
91+
Repository: the repository instance
92+
"""
93+
if repo_name in self._repositories:
94+
return self._repositories[repo_name]
95+
96+
repo = self._github.get_repo(repo_name)
97+
self._repositories[repo_name] = repo
98+
return repo
99+
100+
def get_pr_payload(self, repo_name: str, pr_id: int) -> UrlLinkPayload:
101+
"""get pull-request main-body info
102+
103+
Args:
104+
repo_name (str): the full name of repo
105+
pr_id (int): the is of pull-request
106+
107+
Returns:
108+
UrlLinkPayload: the UrlLink payload
109+
"""
110+
repo: Repository = self.get_repo(repo_name)
111+
pull_request: PullRequest = repo.get_pull(pr_id)
112+
payload = UrlLinkPayload(
113+
url=pull_request.html_url,
114+
title=pull_request.title,
115+
description=pull_request.body,
116+
thumbnailUrl=pull_request.user.avatar_url
117+
)
118+
return payload
119+
120+
def get_pr_comment_payload(self, repo_name: str, pr_id: int, comment_id: int, comment_type: str = 'issue') -> UrlLinkPayload:
121+
"""get comment of pull-request, which can be issue or review comment
122+
123+
Args:
124+
repo_name (str): the full name of repo
125+
pr_id (int): the id of pr
126+
comment_id (int): the id of target comment
127+
comment_type (str, optional): issue/review. Defaults to 'issue'.
128+
129+
Returns:
130+
UrlLinkPayload: _description_
131+
"""
132+
repo: Repository = self.get_repo(repo_name)
133+
pull_request: PullRequest = repo.get_pull(pr_id)
134+
if comment_type == 'issue':
135+
comment: PullRequestComment = pull_request.get_issue_comment(comment_id)
136+
else:
137+
comment: PullRequestComment = pull_request.get_review_comment(comment_id)
138+
139+
payload = UrlLinkPayload(
140+
url=comment.html_url,
141+
title=pull_request.title,
142+
description=comment.body,
143+
thumbnailUrl=comment.user.avatar_url
144+
)
145+
return payload
146+
147+
def get_issue_payload(self, repo_name: str, issue_id: int) -> UrlLinkPayload:
148+
"""get the issue body
149+
150+
Args:
151+
repo_name (str): the full name of repo
152+
issue_id (int): the id of issue
153+
154+
Returns:
155+
UrlLinkPayload: the UrlLink payload instance
156+
"""
157+
repo: Repository = self.get_repo(repo_name)
158+
issue: Issue = repo.get_issue(issue_id)
159+
payload = UrlLinkPayload(
160+
url=issue.html_url,
161+
title=issue.title,
162+
description=issue.body,
163+
thumbnailUrl=issue.user.avatar_url
164+
)
165+
return payload
166+
167+
def get_issue_comment_payload(self, repo_name: str, issue_id: int, comment_id: int) -> UrlLinkPayload:
168+
"""the issue comment payload
169+
170+
Args:
171+
repo_name (str): the full-name of repo
172+
issue_id (int): the id of target issue
173+
comment_id (int): the comment id of the specific issue
174+
175+
Returns:
176+
UrlLinkPayload: the UrlLink payload instance
177+
"""
178+
repo: Repository = self.get_repo(repo_name)
179+
issue: Issue = repo.get_issue(issue_id)
180+
comment: IssueComment = issue.get_comment(comment_id)
181+
182+
payload = UrlLinkPayload(
183+
url=comment.html_url,
184+
title=issue.title,
185+
description=comment.body,
186+
thumbnailUrl=comment.user.avatar_url
187+
)
188+
return payload
189+
190+
191+
192+
193+
19194
class UrlLink:
20195
"""
21196
url_link object which handle the url_link content

tests/url_link_test.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
"""unit test for urllink"""
22
from __future__ import annotations
33

4-
from wechaty.user.url_link import UrlLink
4+
from unittest import TestCase
5+
from wechaty.user.url_link import UrlLink, GithubUrlLinkParser
56

67

8+
9+
10+
class TestUrlLink(TestCase):
11+
def setUp(self) -> None:
12+
self.sample_issue_link = 'https://github.com/wechaty/python-wechaty/issues/339'
13+
self.sample_issue_comment_link = 'https://github.com/wechaty/python-wechaty/issues/339'
14+
715
def test_create():
816
"""unit test for creating"""
917
UrlLink.create(
@@ -12,3 +20,10 @@ def test_create():
1220
thumbnail_url='thu',
1321
description='simple desc'
1422
)
23+
24+
25+
def test_github_payload():
26+
parser = GithubUrlLinkParser()
27+
28+
29+

0 commit comments

Comments
 (0)