pyfb-kit 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyfb_kit/__init__.py +11 -0
- pyfb_kit/client/__init__.py +7 -0
- pyfb_kit/client/asycn.py +3 -0
- pyfb_kit/client/sync.py +228 -0
- pyfb_kit/models/__init__.py +10 -0
- pyfb_kit/models/accounts.py +9 -0
- pyfb_kit/models/comments.py +48 -0
- pyfb_kit/models/posts.py +66 -0
- pyfb_kit/py.typed +0 -0
- pyfb_kit/types/__init__.py +0 -0
- pyfb_kit/types/graph_api.py +12 -0
- pyfb_kit-0.1.0.dist-info/METADATA +126 -0
- pyfb_kit-0.1.0.dist-info/RECORD +14 -0
- pyfb_kit-0.1.0.dist-info/WHEEL +4 -0
pyfb_kit/__init__.py
ADDED
pyfb_kit/client/asycn.py
ADDED
pyfb_kit/client/sync.py
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
from typing import Any, cast
|
|
2
|
+
from collections.abc import Iterator
|
|
3
|
+
|
|
4
|
+
import facebook
|
|
5
|
+
from facebook import GraphAPI
|
|
6
|
+
|
|
7
|
+
from ..models import (
|
|
8
|
+
Account,
|
|
9
|
+
Post,
|
|
10
|
+
Comment
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
from ..types.graph_api import (
|
|
14
|
+
Response,
|
|
15
|
+
Data,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
class Client:
|
|
19
|
+
"""
|
|
20
|
+
Synchronous client for interacting with the Facebook Graph API.
|
|
21
|
+
|
|
22
|
+
Provides methods to manage Facebook pages, posts, and comments.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __init__(self, user_access_token: str):
|
|
26
|
+
"""
|
|
27
|
+
Initialize the client with a user access token.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
user_access_token: A valid Facebook user access token with appropriate permissions
|
|
31
|
+
"""
|
|
32
|
+
self._user_access_token: str = user_access_token
|
|
33
|
+
|
|
34
|
+
def _get_data(
|
|
35
|
+
self,
|
|
36
|
+
graph: facebook.GraphAPI,
|
|
37
|
+
id: str,
|
|
38
|
+
connection_name: str,
|
|
39
|
+
**kwargs: Any
|
|
40
|
+
) -> Data:
|
|
41
|
+
"""
|
|
42
|
+
Internal method to retrieve paginated data from the Facebook Graph API.
|
|
43
|
+
|
|
44
|
+
This method handles pagination automatically by following the cursors in the response
|
|
45
|
+
and concatenating all pages to produce a single data response.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
graph: An initialized GraphAPI instance
|
|
49
|
+
id: The ID of the object to query (e.g., user ID, page ID, post ID)
|
|
50
|
+
connection_name: The connection name to query (e.g., "posts", "comments", "accounts")
|
|
51
|
+
**kwargs: Additional parameters to pass to the Graph API call
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
A list of raw Facebook Graph API objects extracted from the 'data' field
|
|
55
|
+
"""
|
|
56
|
+
all_data: Data = []
|
|
57
|
+
|
|
58
|
+
while True:
|
|
59
|
+
# Request the current page
|
|
60
|
+
res = graph.get_connections( # pyright: ignore
|
|
61
|
+
id,
|
|
62
|
+
connection_name,
|
|
63
|
+
**kwargs
|
|
64
|
+
)
|
|
65
|
+
res = cast(Response, res)
|
|
66
|
+
|
|
67
|
+
current_data: Data = res.get("data") # pyright: ignore
|
|
68
|
+
|
|
69
|
+
if current_data:
|
|
70
|
+
all_data.extend(current_data)
|
|
71
|
+
|
|
72
|
+
# Check for the next page cursor ('after')
|
|
73
|
+
# Facebook Structure: {'paging': {'cursors': {'after': '...'}}}
|
|
74
|
+
try:
|
|
75
|
+
paging = res.get("paging", None)
|
|
76
|
+
if not paging: break
|
|
77
|
+
|
|
78
|
+
cursors = paging.get("cursors")
|
|
79
|
+
if not cursors: break
|
|
80
|
+
|
|
81
|
+
after = cursors.get("after")
|
|
82
|
+
if not after: break
|
|
83
|
+
|
|
84
|
+
# Update kwargs with the 'after' cursor for the next iteration
|
|
85
|
+
kwargs["after"] = after
|
|
86
|
+
|
|
87
|
+
except (AttributeError, TypeError):
|
|
88
|
+
# If the response structure is unexpected, stop pagination
|
|
89
|
+
break
|
|
90
|
+
|
|
91
|
+
return all_data
|
|
92
|
+
|
|
93
|
+
def get_accounts(self) -> list[Account]:
|
|
94
|
+
"""
|
|
95
|
+
Retrieve all Facebook accounts/pages associated with the authenticated user.
|
|
96
|
+
|
|
97
|
+
This method fetches all Facebook pages that the user has access to, along with
|
|
98
|
+
their access tokens and other metadata.
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
A list of Account objects representing the Facebook pages accessible to the user
|
|
102
|
+
"""
|
|
103
|
+
accounts: Data = self._get_data(
|
|
104
|
+
graph=GraphAPI(self._user_access_token),
|
|
105
|
+
id="me",
|
|
106
|
+
connection_name="accounts"
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
return [
|
|
110
|
+
Account.model_validate(acc)
|
|
111
|
+
for acc in accounts
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
def get_posts(self, account: Account) -> list[Post]:
|
|
115
|
+
"""
|
|
116
|
+
Retrieve all posts from a specific Facebook page/account.
|
|
117
|
+
|
|
118
|
+
This method fetches all posts from the given Facebook page, including their
|
|
119
|
+
content, creation time, and attachments.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
account: Account object containing the access token and ID for the Facebook page
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
A list of Post objects representing the posts on the Facebook page
|
|
126
|
+
"""
|
|
127
|
+
posts: Data = self._get_data(
|
|
128
|
+
graph=GraphAPI(account.access_token),
|
|
129
|
+
id=account.id,
|
|
130
|
+
connection_name="posts",
|
|
131
|
+
fields="id,message,created_time,attachments{media,type,subattachments}",
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
return [
|
|
135
|
+
Post.model_validate(p)
|
|
136
|
+
for p in posts
|
|
137
|
+
]
|
|
138
|
+
|
|
139
|
+
def get_comments(self, account: Account, post: Post) -> list[Comment]:
|
|
140
|
+
"""
|
|
141
|
+
Retrieve all comments for a given post using the account's access token.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
account: Account object containing the access token for the Facebook page
|
|
145
|
+
post: Post object containing the post information
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
A list of Comment objects representing the comments on the post
|
|
149
|
+
"""
|
|
150
|
+
comments: Data = self._get_data(
|
|
151
|
+
graph=GraphAPI(account.access_token),
|
|
152
|
+
id=post.id,
|
|
153
|
+
connection_name="comments",
|
|
154
|
+
fields="id,from,message,created_time,like_count,parent"
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
return [
|
|
158
|
+
Comment.model_validate(comment)
|
|
159
|
+
for comment in comments
|
|
160
|
+
]
|
|
161
|
+
|
|
162
|
+
def put_comment(self, account: Account, post: Post, message: str) -> None:
|
|
163
|
+
"""
|
|
164
|
+
Post a direct comment on a post using the account's access token.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
account: Account object containing the access token for the Facebook page
|
|
168
|
+
post: Post object containing the post information
|
|
169
|
+
message: The message content for the comment
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
None
|
|
173
|
+
"""
|
|
174
|
+
graph = GraphAPI(account.access_token)
|
|
175
|
+
|
|
176
|
+
# Use the Facebook Graph API to post a comment on the specific post
|
|
177
|
+
_ = graph.put_object( # pyright: ignore
|
|
178
|
+
parent_object=post.id,
|
|
179
|
+
connection_name="comments",
|
|
180
|
+
message=message
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
def reply_comment(self, account: Account, comment: Comment, reply_message: str) -> None:
|
|
184
|
+
"""
|
|
185
|
+
Reply to a specific comment using the account's access token.
|
|
186
|
+
This creates a reply to the given comment.
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
account: Account object containing the access token for the Facebook page
|
|
190
|
+
comment: Comment object representing the comment to reply to
|
|
191
|
+
reply_message: The message content for the reply
|
|
192
|
+
|
|
193
|
+
Returns:
|
|
194
|
+
None
|
|
195
|
+
"""
|
|
196
|
+
graph = GraphAPI(account.access_token)
|
|
197
|
+
|
|
198
|
+
# Use the Facebook Graph API to reply to the specific comment
|
|
199
|
+
_ = graph.put_object( # pyright: ignore
|
|
200
|
+
parent_object=comment.id,
|
|
201
|
+
connection_name="comments",
|
|
202
|
+
message=reply_message
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
def get_comment_replies(self, account: Account, comment: Comment) -> list[Comment]:
|
|
206
|
+
"""
|
|
207
|
+
Retrieve all replies to a specific comment using the account's access token.
|
|
208
|
+
|
|
209
|
+
Args:
|
|
210
|
+
account: Account object containing the access token for the Facebook page
|
|
211
|
+
comment: Comment object representing the parent comment whose replies are to be retrieved
|
|
212
|
+
|
|
213
|
+
Returns:
|
|
214
|
+
A list of Comment objects representing the replies to the given comment
|
|
215
|
+
"""
|
|
216
|
+
replies: Data = self._get_data(
|
|
217
|
+
graph=GraphAPI(account.access_token),
|
|
218
|
+
id=comment.id,
|
|
219
|
+
connection_name="comments",
|
|
220
|
+
fields="id,from,message,created_time,like_count,parent"
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
return [
|
|
224
|
+
Comment.model_validate(reply)
|
|
225
|
+
for reply in replies
|
|
226
|
+
]
|
|
227
|
+
|
|
228
|
+
# TODO: Add hide/unhide comments methods
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
from pydantic import BaseModel, Field
|
|
2
|
+
|
|
3
|
+
class Account(BaseModel):
|
|
4
|
+
access_token: str = Field(description="The access token needed to do operation using this account")
|
|
5
|
+
id: str = Field(description="The ID of the account")
|
|
6
|
+
name: str = Field(description="The name of the account")
|
|
7
|
+
tasks: list[str] = Field(description="The roles of CURRENT USER for this account")
|
|
8
|
+
|
|
9
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
from pydantic import BaseModel, Field, model_validator
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class From(BaseModel):
|
|
7
|
+
id: str = Field(..., description="ID of the user who made the comment")
|
|
8
|
+
name: str = Field(..., description="Name of the user who made the comment")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Comment(BaseModel):
|
|
12
|
+
"""
|
|
13
|
+
Normalized DTO for a Facebook comment.
|
|
14
|
+
|
|
15
|
+
IMPORTANT:
|
|
16
|
+
This model expects the raw input to include comment data from the
|
|
17
|
+
Facebook Graph API. When querying comments, you MUST request the following
|
|
18
|
+
fields for validation and normalization to work correctly:
|
|
19
|
+
|
|
20
|
+
...get_connections(
|
|
21
|
+
post_id,
|
|
22
|
+
"comments",
|
|
23
|
+
fields="id,from,message,created_time,like_count,parent"
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
If required fields are missing from the response, validation will fail.
|
|
27
|
+
"""
|
|
28
|
+
id: str = Field(..., description="Unique identifier of the Facebook comment")
|
|
29
|
+
message: str = Field(..., description="Text content of the comment")
|
|
30
|
+
created_time: datetime = Field(..., description="Timestamp when the comment was created (ISO-8601)")
|
|
31
|
+
from_info: From = Field(..., alias="from", description="Information about the user who made the comment")
|
|
32
|
+
like_count: int = Field(default=0, description="Number of likes on the comment")
|
|
33
|
+
parent_id: str | None = Field(None, description="ID of the parent comment if this is a reply, otherwise None")
|
|
34
|
+
|
|
35
|
+
@model_validator(mode="before")
|
|
36
|
+
@classmethod
|
|
37
|
+
def extract_facebook_payload(cls, raw: dict[str, Any]):
|
|
38
|
+
return {
|
|
39
|
+
"id": raw["id"],
|
|
40
|
+
"message": raw["message"],
|
|
41
|
+
"created_time": raw["created_time"],
|
|
42
|
+
"from": {
|
|
43
|
+
"id": raw["from"]["id"],
|
|
44
|
+
"name": raw["from"]["name"]
|
|
45
|
+
},
|
|
46
|
+
"like_count": raw.get("like_count", 0),
|
|
47
|
+
"parent_id": raw.get("parent", {}).get("id") if raw.get("parent") else None
|
|
48
|
+
}
|
pyfb_kit/models/posts.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
from pydantic import BaseModel, Field, model_validator
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Image(BaseModel):
|
|
7
|
+
src: str = Field(..., description="Direct URL to the image hosted by Facebook")
|
|
8
|
+
width: int = Field(..., description="Width of the image in pixels")
|
|
9
|
+
height: int = Field(..., description="Height of the image in pixels")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Attachments(BaseModel):
|
|
13
|
+
images: list[Image] | None = Field(None, description="List of images attached to the post, if any")
|
|
14
|
+
# TODO: Add other attachment types here (videos, links, etc.)
|
|
15
|
+
|
|
16
|
+
class Post(BaseModel):
|
|
17
|
+
"""
|
|
18
|
+
Normalized DTO for a Facebook Page post.
|
|
19
|
+
|
|
20
|
+
IMPORTANT:
|
|
21
|
+
This model expects the raw input to include attachment data from the
|
|
22
|
+
Facebook Graph API. When querying posts, you MUST request the following
|
|
23
|
+
fields for validation and normalization to work correctly:
|
|
24
|
+
|
|
25
|
+
...get_connections(
|
|
26
|
+
account_id,
|
|
27
|
+
"posts",
|
|
28
|
+
fields="id,message,created_time,attachments{media,type,subattachments}"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
If `attachments` or `attachments.media.image` are missing from the
|
|
32
|
+
response, `attachments.images` will be set to None.
|
|
33
|
+
"""
|
|
34
|
+
id: str = Field(..., description="Unique identifier of the Facebook post")
|
|
35
|
+
created_time: datetime = Field(..., description="Timestamp when the post was created (ISO-8601)")
|
|
36
|
+
message: str | None = Field(None, description="Text content of the post")
|
|
37
|
+
attachments: Attachments | None = Field(None, description="Normalized attachments associated with the post")
|
|
38
|
+
|
|
39
|
+
@model_validator(mode="before")
|
|
40
|
+
@classmethod
|
|
41
|
+
def extract_facebook_payload(cls, raw: dict[str, Any]):
|
|
42
|
+
images: list[Image] = []
|
|
43
|
+
|
|
44
|
+
for att in raw.get("attachments", {}).get("data", []):
|
|
45
|
+
if att.get("type") != "photo":
|
|
46
|
+
continue
|
|
47
|
+
|
|
48
|
+
image = att.get("media", {}).get("image")
|
|
49
|
+
if not image:
|
|
50
|
+
continue
|
|
51
|
+
|
|
52
|
+
images.append(
|
|
53
|
+
Image(
|
|
54
|
+
src=image["src"],
|
|
55
|
+
width=image["width"],
|
|
56
|
+
height=image["height"],
|
|
57
|
+
)
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
"id": raw["id"],
|
|
62
|
+
"created_time": raw["created_time"],
|
|
63
|
+
"message": raw.get("message"),
|
|
64
|
+
"attachments": {"images": images} if images else None,
|
|
65
|
+
}
|
|
66
|
+
|
pyfb_kit/py.typed
ADDED
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from typing import Annotated, Any
|
|
2
|
+
|
|
3
|
+
type Response = Annotated[
|
|
4
|
+
dict[str, Any],
|
|
5
|
+
"Raw Facebook Graph API response object returned by get_connections()."
|
|
6
|
+
]
|
|
7
|
+
|
|
8
|
+
type Data = Annotated[
|
|
9
|
+
list[dict[str, Any]],
|
|
10
|
+
"List of raw Facebook Graph API objects extracted from the 'data' field."
|
|
11
|
+
]
|
|
12
|
+
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: pyfb-kit
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A wrapper for the facebook-sdk which provides an ergonomic way to manage common interactions using the facebook-sdk
|
|
5
|
+
Author: NovaH00
|
|
6
|
+
Author-email: NovaH00 <trantay2006super@gmail.com>
|
|
7
|
+
Requires-Dist: facebook-sdk>=3.1.0
|
|
8
|
+
Requires-Dist: pydantic>=2.12.5
|
|
9
|
+
Requires-Python: >=3.14
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
|
|
12
|
+
# PyFB-kit
|
|
13
|
+
|
|
14
|
+
A Python wrapper for the Facebook Graph API that provides convenient abstractions for managing and moderating Facebook pages and comments.
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
Install the package using pip:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install pyfb-kit
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Or using uv (recommended):
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
uv add pyfb-kit
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Prerequisites
|
|
31
|
+
|
|
32
|
+
Before using this library, you need to obtain a long-lived user access token with the appropriate permissions:
|
|
33
|
+
|
|
34
|
+
1. Create a Facebook developer application at [developers.facebook.com/apps](https://developers.facebook.com/apps/)
|
|
35
|
+
2. Add the following permissions to your application:
|
|
36
|
+
- `pages_manage_engagement`
|
|
37
|
+
- `pages_read_engagement`
|
|
38
|
+
- `pages_read_user_content`
|
|
39
|
+
- `pages_show_list`
|
|
40
|
+
3. Generate a short-lived user access token via the Graph API Explorer with the above permissions
|
|
41
|
+
4. Exchange it for a long-lived token (valid for up to 60 days) using the following request:
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
import requests
|
|
45
|
+
|
|
46
|
+
params = {
|
|
47
|
+
"grant_type": "fb_exchange_token",
|
|
48
|
+
"client_id": "<YOUR_APP_ID>",
|
|
49
|
+
"fb_exchange_token": "<SHORT_LIVED_TOKEN>",
|
|
50
|
+
"client_secret": "<YOUR_APP_SECRET>",
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
response = requests.get("https://graph.facebook.com/v24.0/oauth/access_token", params=params)
|
|
54
|
+
long_lived_token = response.json()["access_token"]
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Usage
|
|
58
|
+
|
|
59
|
+
### Basic Setup
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
from pyfb_kit import Client, Account, Post, Comment
|
|
63
|
+
|
|
64
|
+
# Initialize the client with your user access token
|
|
65
|
+
client = Client(user_access_token="your_long_lived_token_here")
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Managing Accounts
|
|
69
|
+
|
|
70
|
+
Retrieve all Facebook pages associated with your account:
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
# Get all accessible accounts/pages
|
|
74
|
+
accounts = client.get_accounts()
|
|
75
|
+
|
|
76
|
+
# Print account information
|
|
77
|
+
for account in accounts:
|
|
78
|
+
print(f"Page Name: {account.name}, ID: {account.id}")
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Working with Posts
|
|
82
|
+
|
|
83
|
+
Fetch posts from a specific page:
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
# Get posts from a specific account
|
|
87
|
+
first_account = accounts[0]
|
|
88
|
+
posts = client.get_posts(first_account)
|
|
89
|
+
|
|
90
|
+
# Print post information
|
|
91
|
+
for post in posts:
|
|
92
|
+
print(f"Post ID: {post.id}, Message: {post.message[:50]}...")
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Comment Management
|
|
96
|
+
|
|
97
|
+
Interact with comments on posts:
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
# Get comments from a specific post
|
|
101
|
+
first_post = posts[0]
|
|
102
|
+
comments = client.get_comments(first_account, first_post)
|
|
103
|
+
|
|
104
|
+
# Print comment information
|
|
105
|
+
for comment in comments:
|
|
106
|
+
print(f"Comment by {comment.from_info.name}: {comment.message[:50]}...")
|
|
107
|
+
|
|
108
|
+
# Post a new comment on a post
|
|
109
|
+
client.put_comment(first_account, first_post, "This is a new comment!")
|
|
110
|
+
|
|
111
|
+
# Reply to an existing comment
|
|
112
|
+
first_comment = comments[0]
|
|
113
|
+
client.reply_comment(first_account, first_comment, "Thanks for your comment!")
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Advanced Comment Operations
|
|
117
|
+
|
|
118
|
+
Retrieve replies to a specific comment:
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
# Get all replies to a specific comment
|
|
122
|
+
replies = client.get_comment_replies(first_account, first_comment)
|
|
123
|
+
|
|
124
|
+
for reply in replies:
|
|
125
|
+
print(f"Reply by {reply.from_info.name}: {reply.message[:50]}...")
|
|
126
|
+
```
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
pyfb_kit/__init__.py,sha256=v7lFI6Mb6Sa_VXfgpExmc0AfyguTcCI3ldT6YoREiLs,174
|
|
2
|
+
pyfb_kit/client/__init__.py,sha256=gAPxpaGxWbB1savJ0hgnqodL8OLrHIXeuEuxCVIOL4Y,103
|
|
3
|
+
pyfb_kit/client/asycn.py,sha256=rJyax5qi43mPodi1UvFBaG_rOn1Sww_zRIo9wfvCPC8,29
|
|
4
|
+
pyfb_kit/client/sync.py,sha256=48yDTglkeWBnY_ihR2Ywfc7QhitYaHqhBO_XEwRq_No,7446
|
|
5
|
+
pyfb_kit/models/__init__.py,sha256=cZjzAGN8h2SPySmlFuoWJ0Er0GYeH7bfxovZsU-SXj4,144
|
|
6
|
+
pyfb_kit/models/accounts.py,sha256=gyGombDFCw89oQHnA2gOQ9YldgpNjkYcE7-kKqdAMzY,376
|
|
7
|
+
pyfb_kit/models/comments.py,sha256=tqDaF51T1TVBIw1hzHhWpybWE7zbgNXFvGi1e1qBzNE,1923
|
|
8
|
+
pyfb_kit/models/posts.py,sha256=_JOsUf9DfiZsQpi_QQ6PLdNY0FULRIqb3V0l_qaTCjI,2356
|
|
9
|
+
pyfb_kit/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
pyfb_kit/types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
+
pyfb_kit/types/graph_api.py,sha256=iejbzc_5QjcyKmayFOK8mtE0zSEbYiPL358hxtC5Nkg,291
|
|
12
|
+
pyfb_kit-0.1.0.dist-info/WHEEL,sha256=xDCZ-UyfvkGuEHPeI7BcJzYKIZzdqN8A8o1M5Om8IyA,79
|
|
13
|
+
pyfb_kit-0.1.0.dist-info/METADATA,sha256=2xWO7RfYgiT_O6axjX_ap0rYbA6A-rlxsgZKtzPYTOo,3258
|
|
14
|
+
pyfb_kit-0.1.0.dist-info/RECORD,,
|