Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions xhs_cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ def cli(ctx, verbose: bool, cookie_source: str):

cli.add_command(creator.post)
cli.add_command(creator.my_notes)
cli.add_command(creator.my_notes_data)
cli.add_command(creator.delete)

# ─── Notification commands ──────────────────────────────────────────────────
Expand Down
7 changes: 7 additions & 0 deletions xhs_cli/client_mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,13 @@ def get_creator_note_list(self, tab: int = 0, page: int = 0) -> dict[str, Any]:
"page": page,
})

def get_creator_note_analyze_list(self, type: int = 0, page_size: int = 10, page_num: int = 1) -> dict[str, Any]:
return self._creator_get("/api/galaxy/creator/datacenter/note/analyze/list", {
"type": type,
"page_size": page_size,
"page_num": page_num,
})


class SocialEndpointsMixin:
"""Social graph and saved-content endpoints."""
Expand Down
20 changes: 20 additions & 0 deletions xhs_cli/commands/creator.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
maybe_print_structured,
print_info,
print_success,
render_creator_note_data,
render_creator_notes,
)
from ..note_refs import save_index_from_notes
Expand Down Expand Up @@ -105,6 +106,25 @@ def _my_notes_action(client):
)


@click.command("my-notes-data")
@click.option("--page", default=1, help="Page number (1-indexed)")
@click.option("--page-size", default=10, help="Page size")
@structured_output_options
@click.pass_context
def my_notes_data(ctx, page: int, page_size: int, as_json: bool, as_yaml: bool):
"""List your own published notes data."""
def _my_notes_data_action(client):
return client.get_creator_note_analyze_list(page_num=page, page_size=page_size)

handle_command(
ctx,
action=_my_notes_data_action,
render=render_creator_note_data,
as_json=as_json,
as_yaml=as_yaml,
)


@click.command("delete")
@click.argument("id_or_url")
@structured_output_options
Expand Down
1 change: 1 addition & 0 deletions xhs_cli/formatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from .formatter_renderers import ( # noqa: F401
render_comments,
render_creator_note_data,
render_creator_notes,
render_feed,
render_note,
Expand Down
18 changes: 18 additions & 0 deletions xhs_cli/formatter_normalizers.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,24 @@ def normalize_creator_notes(data: Any) -> list[dict[str, Any]]:
return normalized


def normalize_creator_note_data(data: Any) -> list[dict[str, Any]]:
notes = data if isinstance(data, list) else data.get("notes", data.get("note_list", data.get("note_infos", [])))
normalized = []
for note in notes:
normalized.append({
"title": note.get("title", "")[:40],
"note_id": note.get("id", note.get("note_id", "")),
"view_count": str(note.get("read_count", note.get("view_count", ""))),
"imp_count": str(note.get("imp_count", "")),
"liked_count": str(note.get("like_count", note.get("liked_count", ""))),
"collected_count": str(note.get("fav_count", note.get("collected_count", ""))),
"comment_count": str(note.get("comment_count", "")),
"share_count": str(note.get("share_count", "")),
"click_rate": f"{note['coverClickRate'] * 100:.1f}%" if "coverClickRate" in note else "-",
})
return normalized


def normalize_notifications(data: dict[str, Any]) -> list[dict[str, Any]]:
normalized = []
for message in data.get("message_list", []):
Expand Down
35 changes: 35 additions & 0 deletions xhs_cli/formatter_renderers.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

from .formatter_normalizers import (
normalize_comments,
normalize_creator_note_data,
normalize_creator_notes,
normalize_feed,
normalize_note_detail,
Expand Down Expand Up @@ -286,6 +287,40 @@ def render_creator_notes(data: Any) -> None:
console.print(table)


def render_creator_note_data(data: Any) -> None:
"""Render creator's note analyze data."""
notes = normalize_creator_note_data(data)
if not notes:
print_info("No data found")
return

table = Table(title="笔记分析数据", show_lines=True)
table.add_column("#", style="dim", width=3)
table.add_column("标题", width=30)
table.add_column("点击率", justify="right", width=8)
table.add_column("曝光", justify="right", width=8)
table.add_column("👁️", justify="right", width=8)
table.add_column("❤️", justify="right", width=6)
table.add_column("⭐", justify="right", width=6)
table.add_column("💬", justify="right", width=6)
table.add_column("🔗", justify="right", width=6)

for i, note in enumerate(notes, 1):
table.add_row(
str(i),
note["title"],
note["click_rate"],
note["imp_count"],
note["view_count"],
note["liked_count"],
note["collected_count"],
note["comment_count"],
note["share_count"],
)

console.print(table)


def render_notifications(data: dict[str, Any], notif_type: str) -> None:
"""Render notification messages."""
import time as _time
Expand Down