|
7 | 7 | Optional,
|
8 | 8 | Type
|
9 | 9 | )
|
| 10 | +from urllib3 import get_host |
10 | 11 | from wechaty_puppet import UrlLinkPayload, get_logger
|
11 | 12 |
|
12 | 13 | from wechaty.utils.link import get_url_metadata
|
13 | 14 |
|
| 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 |
14 | 29 |
|
15 | 30 |
|
16 | 31 | log = get_logger('UrlLink')
|
17 | 32 |
|
18 | 33 |
|
| 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 | + |
19 | 194 | class UrlLink:
|
20 | 195 | """
|
21 | 196 | url_link object which handle the url_link content
|
|
0 commit comments