feat: follow pull requests from mobile Search (Closes #1307)
This commit is contained in:
1 parent
41c28cc70a
commit
7131792ded
23 files changed
+271
-83
No files matched your search
+19
-4
@@ -10,6 +10,7 @@ from src.state_encryption import PrivateStateCipher, PrivateStateEncryptionError
|
||||
|
||||
_REPOSITORY = re.compile(r"^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$")
|
||||
_STATES = {"open", "closed"}
|
||||
_KINDS = {"issue", "pull"}
|
||||
|
||||
|
||||
class FollowingStore:
|
||||
@@ -74,6 +75,9 @@ class FollowingStore:
|
||||
number = raw.get("number")
|
||||
if not isinstance(number, int) or isinstance(number, bool) or number < 1:
|
||||
raise ValueError("number is invalid")
|
||||
kind = raw.get("kind", "issue")
|
||||
if kind not in _KINDS:
|
||||
raise ValueError("kind is invalid")
|
||||
title = raw.get("title")
|
||||
if not isinstance(title, str) or not title.strip() or len(title.strip()) > 300:
|
||||
raise ValueError("title is invalid")
|
||||
@@ -95,6 +99,7 @@ class FollowingStore:
|
||||
raise ValueError("last seen update is invalid")
|
||||
return {
|
||||
"repository": repository,
|
||||
"kind": kind,
|
||||
"number": number,
|
||||
"title": title.strip(),
|
||||
"state": state,
|
||||
@@ -117,8 +122,8 @@ class FollowingStore:
|
||||
return {"revision": snapshot["revision"], "items": changed + unchanged}
|
||||
|
||||
@staticmethod
|
||||
def _identity(item: dict) -> tuple[str, int]:
|
||||
return item["repository"].lower(), item["number"]
|
||||
def _identity(item: dict) -> tuple[str, str, int]:
|
||||
return item.get("kind", "issue"), item["repository"].lower(), item["number"]
|
||||
|
||||
def get(self, login: str) -> dict:
|
||||
login = self._login(login)
|
||||
@@ -226,10 +231,20 @@ class FollowingStore:
|
||||
)
|
||||
return self._present({"revision": revision, "items": items})
|
||||
|
||||
def acknowledge(self, login: str, repository: str, number: int, updated_at: str) -> dict:
|
||||
def acknowledge(
|
||||
self,
|
||||
login: str,
|
||||
repository: str,
|
||||
number: int,
|
||||
updated_at: str,
|
||||
*,
|
||||
kind: str = "issue",
|
||||
) -> dict:
|
||||
"""Mark only the exact upstream revision successfully opened by the operator."""
|
||||
login = self._login(login)
|
||||
identity = (str(repository).lower(), number)
|
||||
if kind not in _KINDS:
|
||||
raise ValueError("kind is invalid")
|
||||
identity = (kind, str(repository).lower(), number)
|
||||
with self._connect() as connection:
|
||||
connection.execute("BEGIN IMMEDIATE")
|
||||
row = connection.execute(
|
||||
|
||||
+7
-4
@@ -2623,11 +2623,12 @@ async def get_following(response: Response):
|
||||
async def refresh_item(item: dict) -> dict:
|
||||
async with semaphore:
|
||||
preview = await asyncio.wait_for(
|
||||
gitea_proxy.work_preview(item["repository"], "issue", item["number"]),
|
||||
gitea_proxy.work_preview(item["repository"], item["kind"], item["number"]),
|
||||
timeout=GLOBAL_SEARCH_TIMEOUT_SECONDS,
|
||||
)
|
||||
return store._normalize_item({
|
||||
"repository": item["repository"],
|
||||
"kind": item["kind"],
|
||||
"number": item["number"],
|
||||
"title": preview.get("title", ""),
|
||||
"state": preview.get("state", ""),
|
||||
@@ -2658,6 +2659,7 @@ async def acknowledge_following_revision(
|
||||
owner: str,
|
||||
repo: str,
|
||||
number: int = PathParam(gt=0),
|
||||
kind: Literal["issue", "pull"] = Query(default="issue"),
|
||||
):
|
||||
login = await _confirmed_login()
|
||||
try:
|
||||
@@ -2667,6 +2669,7 @@ async def acknowledge_following_revision(
|
||||
f"{owner}/{repo}",
|
||||
number,
|
||||
payload.updated_at,
|
||||
kind=kind,
|
||||
)
|
||||
except ValueError as exc:
|
||||
raise HTTPException(status_code=422, detail=str(exc)) from exc
|
||||
@@ -3743,9 +3746,8 @@ async def _search_preview_subscription_target(
|
||||
repository = f"{owner}/{repo}"
|
||||
preview = await gitea_proxy.work_preview(repository, kind, number)
|
||||
if (
|
||||
kind != "issue"
|
||||
or preview.get("repository") != repository
|
||||
or preview.get("kind") != "issue"
|
||||
preview.get("repository") != repository
|
||||
or preview.get("kind") != kind
|
||||
or preview.get("number") != number
|
||||
or preview.get("state") not in ({"open", "closed"} if allow_closed else {"open"})
|
||||
):
|
||||
@@ -3797,6 +3799,7 @@ async def mutate_global_search_preview_subscription(
|
||||
store = _following_store()
|
||||
following_item = {
|
||||
"repository": repository,
|
||||
"kind": kind,
|
||||
"number": number,
|
||||
"title": preview.get("title", ""),
|
||||
"state": preview.get("state", ""),
|
||||
|
||||
Reference in new issue
Block a user