Skip to content

Commit 381972a

Browse files
committed
update: implement support for Forgejo comments and reactions
1 parent ac4c629 commit 381972a

File tree

1 file changed

+193
-0
lines changed

1 file changed

+193
-0
lines changed

ogr/services/forgejo/comments.py

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
# Copyright Contributors to the Packit project.
2+
# SPDX-License-Identifier: MIT
3+
4+
import datetime
5+
from typing import Any
6+
7+
from ogr.abstract import Comment, CommitComment, IssueComment, PRComment, Reaction
8+
9+
10+
class ForgejoReaction(Reaction):
11+
_raw_reaction: dict
12+
13+
def __init__(
14+
self,
15+
raw_reaction: dict,
16+
forgejo_client: Any,
17+
repository: str,
18+
issue_number: int,
19+
) -> None:
20+
"""
21+
Initializes a ForgejoReaction.
22+
23+
Args:
24+
raw_reaction (dict): The raw reaction data from the API.
25+
forgejo_client (Any): The Forgejo client instance.
26+
repository (str): Repository identifier (e.g., "owner/repo").
27+
issue_number (int): The issue number associated with the comment.
28+
"""
29+
self._raw_reaction = raw_reaction
30+
self._forgejo_client = forgejo_client
31+
self._repository = repository
32+
self._issue_number = issue_number
33+
self._id = raw_reaction.get("id")
34+
self._content = raw_reaction.get("content")
35+
self._user_login = raw_reaction.get("user", {}).get("login")
36+
37+
def __str__(self) -> str:
38+
return "Forgejo" + super().__str__()
39+
40+
def delete(self) -> None:
41+
"""
42+
Deletes the reaction from Forgejo using the stored client context.
43+
"""
44+
url = (
45+
f"{self._forgejo_client.forgejo_url}/api/v1/repos/"
46+
f"{self._repository}/issues/{self._issue_number}/reactions/{self._id}"
47+
)
48+
self._forgejo_client._make_request("DELETE", url)
49+
50+
@property
51+
def content(self) -> str:
52+
return self._content
53+
54+
@property
55+
def user_login(self) -> str:
56+
return self._user_login
57+
58+
@property
59+
def id(self) -> int:
60+
return self._id
61+
62+
63+
class ForgejoComment(Comment):
64+
def __init__(
65+
self,
66+
raw_comment: dict,
67+
forgejo_client: Any,
68+
repository: str,
69+
issue_number: int,
70+
) -> None:
71+
"""
72+
Initializes a ForgejoComment.
73+
74+
Args:
75+
raw_comment (dict): The raw comment data.
76+
forgejo_client (Any): The Forgejo client instance.
77+
repository (str): Repository identifier (e.g., "owner/repo").
78+
issue_number (int): The issue number associated with the comment.
79+
"""
80+
self._forgejo_client = forgejo_client
81+
self._repository = repository
82+
self._issue_number = issue_number
83+
self._from_raw_comment(raw_comment)
84+
85+
def _from_raw_comment(self, raw_comment: dict) -> None:
86+
"""
87+
Initializes comment attributes from the raw API data.
88+
"""
89+
self._raw_comment = raw_comment
90+
self._id = raw_comment.get("id")
91+
self._author = raw_comment.get("user", {}).get("login")
92+
created_at = raw_comment.get("created_at")
93+
self._created = (
94+
datetime.datetime.fromisoformat(created_at.replace("Z", "+00:00"))
95+
if created_at
96+
else None
97+
)
98+
updated_at = raw_comment.get("updated_at")
99+
self._edited = (
100+
datetime.datetime.fromisoformat(updated_at.replace("Z", "+00:00"))
101+
if updated_at
102+
else None
103+
)
104+
105+
@property
106+
def body(self) -> str:
107+
return self._raw_comment.get("body")
108+
109+
@body.setter
110+
def body(self, new_body: str) -> None:
111+
"""
112+
Updates the comment body in Forgejo.
113+
"""
114+
url = (
115+
f"{self._forgejo_client.forgejo_url}/api/v1/repos/"
116+
f"{self._repository}/issues/{self._issue_number}/comments/{self._id}"
117+
)
118+
data = {"body": new_body}
119+
self._forgejo_client._make_request("PATCH", url, data)
120+
self._raw_comment["body"] = new_body
121+
122+
@property
123+
def edited(self) -> datetime.datetime:
124+
return self._edited
125+
126+
def get_reactions(self) -> list[Reaction]:
127+
"""
128+
Retrieves all reactions for this comment.
129+
"""
130+
url = (
131+
f"{self._forgejo_client.forgejo_url}/api/v1/repos/"
132+
f"{self._repository}/issues/{self._issue_number}/comments/{self._id}/reactions"
133+
)
134+
reactions_data = self._forgejo_client._make_request("GET", url)
135+
return [
136+
ForgejoReaction(
137+
r,
138+
self._forgejo_client,
139+
self._repository,
140+
self._issue_number,
141+
)
142+
for r in reactions_data
143+
]
144+
145+
def add_reaction(self, reaction: str) -> ForgejoReaction:
146+
"""
147+
Adds a reaction to the comment.
148+
149+
Args:
150+
reaction (str): The reaction content (e.g., "+1", "heart").
151+
152+
Returns:
153+
ForgejoReaction: The created reaction object.
154+
"""
155+
url = (
156+
f"{self._forgejo_client.forgejo_url}/api/v1/repos/"
157+
f"{self._repository}/issues/{self._issue_number}/comments/{self._id}/reactions"
158+
)
159+
data = {"content": reaction}
160+
reaction_data = self._forgejo_client._make_request("POST", url, data)
161+
return ForgejoReaction(
162+
reaction_data,
163+
self._forgejo_client,
164+
self._repository,
165+
self._issue_number,
166+
)
167+
168+
@property
169+
def id(self) -> int:
170+
return self._id
171+
172+
@property
173+
def author(self) -> str:
174+
return self._author
175+
176+
@property
177+
def created(self) -> datetime.datetime:
178+
return self._created
179+
180+
181+
class ForgejoIssueComment(ForgejoComment, IssueComment):
182+
def __str__(self) -> str:
183+
return "Forgejo" + super().__str__()
184+
185+
186+
class ForgejoPRComment(ForgejoComment, PRComment):
187+
def __str__(self) -> str:
188+
return "Forgejo" + super().__str__()
189+
190+
191+
class ForgejoCommitComment(ForgejoComment, CommitComment):
192+
def __str__(self) -> str:
193+
return "Forgejo" + super().__str__()

0 commit comments

Comments
 (0)