diff --git a/src/synclean/cli/commands.py b/src/synclean/cli/commands.py index 87c7653..3bca393 100644 --- a/src/synclean/cli/commands.py +++ b/src/synclean/cli/commands.py @@ -1,11 +1,8 @@ -from typing import Optional import click -from synclean.api.rooms import RoomAPI from synclean.api.synapse import SynapseApiClient -from synclean.api.users import UserAPI from synclean.config.settings import SettingsManager -from synclean.models.enums import RoomOrderBy, Direction, UserOrderBy -from synclean.models.pagination import PaginationParams, RoomPaginationParams, UserPaginationParams +from synclean.cli.room_commands import room +from synclean.cli.user_commands import user pass_api = click.make_pass_decorator(SynapseApiClient) @@ -18,163 +15,5 @@ def cli(ctx): ctx.obj = SynapseApiClient(config) -@cli.group() -def room(): - """Room commands.""" - pass - -@cli.group() -def user(): - """User commands.""" - pass - -@room.command("ls") -@click.option("--limit", "-l", default=100, help="Number of rooms to display per page.") -@click.option("--offset", "-o", default=0, help="Number of the room to start from.") -@click.option("--search", "-s", help="Search term to filter rooms by.") -@click.option("--order-by", "-O", - type=click.Choice(["name", "joined_members", "canonical_alias", "creator", "version",]), - default="name", help="Field to order result by.") -@click.option("--direction", "-d", - type=click.Choice(["f", "b"]), - default="b", help="Direction to order result by. (f=forward, b=backward)") -@pass_api -def room_ls( - api: SynapseApiClient, - limit: int, - offset: int, - search: Optional[str], - order_by: str, - direction: str -): - order_by_enum = RoomOrderBy(order_by) - direction_enum = Direction(direction) - - rooms_api = RoomAPI(api) - - while True: - pagination_params = RoomPaginationParams(limit, offset, order_by_enum, direction_enum, search) - - rooms = rooms_api.get_rooms_list(pagination_params) - if rooms: - for r in rooms.rooms: - click.echo(f"Name: {r.name}") - click.echo(f"ID: {r.room_id}") - click.echo(f"Joined Members: {r.joined_members}") - click.echo("=" * 50) - else: - click.echo("No rooms found.") - - offset += limit - - choice = input("Next page? (y/n): ") - if choice.lower() != "y": - break - -@room.command("show") -@click.argument("room_id") -@click.option("--media", is_flag=True, help="List media in the room") -@click.option("--rm-all", is_flag=True, help="Remove all media in the room") -@click.option("--rm", "remove_media_id", help="Remove media by ID") -@click.option("--avatar", is_flag=True, help="Show avatar URI") -@pass_api -def show_room( - api: SynapseApiClient, - room_id: str, - media: bool, - rm_all: bool, - remove_media_id: Optional[str], - avatar: bool -): - if room_id is None: - click.echo("You must specify a room ID.", err=True) - return - - - - if rm_all or remove_media_id: - if not media: - click.echo("You must specify --media to remove media.") - return - - room_api = RoomAPI(api) - room_details = room_api.get_room_details(room_id) - - if not room_details: - click.echo(f"Error: Room {room_id} not found.", err=True) - return - - if avatar: - if not room_details.avatar: - click.echo("Room has no avatar.") - return - click.echo(room_details.avatar) - # TODO: implement adding avatar to blacklist - - if rm_all: - if click.confirm("Are you sure you want to remove all media in this room?"): - # TODO: implement removing all media from the room - pass - - if remove_media_id: - if click.confirm(f"Are you sure you want to remove media {remove_media_id} from the room?"): - # TODO: implement removing media by ID - pass - - if not media: - click.echo(f"Room details: {room_id}") - click.echo("=" * 40) - click.echo(f"Name: {room_details.name}") - click.echo(f"Avatar: {room_details.avatar}") - click.echo(f"ID: {room_details.room_id}") - click.echo(f"Members: {room_details.joined_members} (Local: {room_details.joined_local_members})") - click.echo(f"Creator: {room_details.creator}") - click.echo(f"Encryption: {room_details.encryption}") - click.echo(f"Public: {room_details.public}") - click.echo(f"Guest Access: {room_details.guest_access}") - click.echo(f"History Visibility: {room_details.history_visibility}") - click.echo(f"State Events: {room_details.state_events}") - click.echo(f"Room Type: {room_details.room_type}") - else: - room_media = room_api.get_media_from_room(room_id) - if room_media: - for uri in room_media.all_uris: - click.echo(f"URI: {uri}") - -@user.command("ls") -@click.option("--limit", "-l", default=10, help="Number of users to list.") -@click.option("--offset", "-o", default=0, help="Number of the room to start from.") -@click.option("--search", "-s", help="Search term to filter by.") -@click.option("--order-by", "-O", - type=click.Choice(["user_id", "display_name", "media_length", "media_count"]), - default="media_length", help="Field to order result by.") -@click.option("--direction", "-d", - type=click.Choice(["f", "b"]), - default="b", help="Direction to order result by. (f=forward, b=backward)") -@pass_api -def user_ls( - api: SynapseApiClient, - limit: int, - offset: int, - search: Optional[str], - order_by: str, - direction: str -): - - order_by_enum = UserOrderBy(order_by) - direction_enum = Direction(direction) - - users_api = UserAPI(api) - - while True: - pagination_params = UserPaginationParams(limit, offset, order_by_enum, direction_enum, search) - - users = users_api.get_users_list_by_media(pagination_params) - - if users: - for u in users.users: - click.echo(f"Display name: {u.display_name}") - click.echo(f"Media count: {u.media_count}") - click.echo(f"Media length: {u.media_length_mb()}MB") - click.echo(f"User ID: {u.user_id}") - click.echo("=" * 40) +cli.add_command(room) +cli.add_command(user) \ No newline at end of file diff --git a/src/synclean/cli/room_commands.py b/src/synclean/cli/room_commands.py new file mode 100644 index 0000000..69ab5df --- /dev/null +++ b/src/synclean/cli/room_commands.py @@ -0,0 +1,136 @@ +from typing import Optional +import click +from synclean.api.rooms import RoomAPI +from synclean.api.synapse import SynapseApiClient +from synclean.models.enums import Direction, RoomOrderBy +from synclean.models.pagination import RoomPaginationParams +from synclean.service.room_service import RoomService + +pass_api = click.make_pass_decorator(SynapseApiClient) + + +room = click.Group(name="room", help="Room commands.") + + +@room.command("ls") +@click.option("--limit", "-l", default=10, help="Number of rooms to display per page.") +@click.option("--offset", "-o", default=0, help="Number of the room to start from.") +@click.option("--search", "-s", help="Search term to filter rooms by.") +@click.option("--order-by", "-O", + type=click.Choice(["name", "joined_members", "canonical_alias", "creator", "version",]), + default="name", help="Field to order result by.") +@click.option("--direction", "-d", + type=click.Choice(["f", "b"]), + default="b", help="Direction to order result by. (f=forward, b=backward)") +@pass_api +def room_ls( + api: SynapseApiClient, + limit: int, + offset: int, + search: Optional[str], + order_by: str, + direction: str +): + rooms_api = RoomAPI(api) + room_service = RoomService(rooms_api) + while True: + rooms_list = room_service.get_room_list(limit, offset, search, order_by, direction) + if rooms_list: + for i, r in enumerate(rooms_list): + click.echo(f"Room {i + 1}") + click.echo(f"Name: {r.name}") + click.echo(f"ID: {r.room_id}") + click.echo(f"Joined Members: {r.joined_members}") + click.echo("=" * 50) + + try: + choice = click.prompt("Enter room number to view details (or 'n' for next page, 'q' to quit", type=str) + if choice.lower() == 'q': + break + elif choice.lower() == 'n': + offset += limit + continue + else: + room_num = int(choice) + if 1 <= room_num <= len(rooms_list): + selected_room = rooms_list[room_num - 1] + room_service.get_room_details(selected_room.room_id) + break + else: + click.echo("Invalid room number. Try again.") + continue + except ValueError: + click.echo("Invalid input. Please enter a number or 'n' for next page, 'q' to quit.") + continue + else: + click.echo("No rooms found.") + break + + +@room.command("show") +@click.argument("room_id") +@click.option("--media", is_flag=True, help="List media in the room") +@click.option("--rm-all", is_flag=True, help="Remove all media in the room") +@click.option("--rm", "remove_media_id", help="Remove media by ID") +@click.option("--avatar", is_flag=True, help="Show avatar URI") +@pass_api +def show_room( + api: SynapseApiClient, + room_id: str, + media: bool, + rm_all: bool, + remove_media_id: Optional[str], + avatar: bool +): + if room_id is None: + click.echo("You must specify a room ID.", err=True) + return + + if rm_all or remove_media_id: + if not media: + click.echo("You must specify --media to remove media.") + return + + room_api = RoomAPI(api) + room_details = room_api.get_room_details(room_id) + + if not room_details: + click.echo(f"Error: Room {room_id} not found.", err=True) + return + + if avatar: + if not room_details.avatar: + click.echo("Room has no avatar.") + return + click.echo(room_details.avatar) + # TODO: implement adding avatar to blacklist + + if rm_all: + if click.confirm("Are you sure you want to remove all media in this room?"): + # TODO: implement removing all media from the room + pass + + if remove_media_id: + if click.confirm(f"Are you sure you want to remove media {remove_media_id} from the room?"): + # TODO: implement removing media by ID + pass + + if not media: + click.echo(f"Room details: {room_id}") + click.echo("=" * 40) + click.echo(f"Name: {room_details.name}") + click.echo(f"Avatar: {room_details.avatar}") + click.echo(f"ID: {room_details.room_id}") + click.echo(f"Members: {room_details.joined_members} (Local: {room_details.joined_local_members})") + click.echo(f"Creator: {room_details.creator}") + click.echo(f"Encryption: {room_details.encryption}") + click.echo(f"Public: {room_details.public}") + click.echo(f"Guest Access: {room_details.guest_access}") + click.echo(f"History Visibility: {room_details.history_visibility}") + click.echo(f"State Events: {room_details.state_events}") + click.echo(f"Room Type: {room_details.room_type}") + else: + room_media = room_api.get_media_from_room(room_id) + if room_media: + for uri in room_media.all_uris: + click.echo(f"URI: {uri}") \ No newline at end of file diff --git a/src/synclean/cli/user_commands.py b/src/synclean/cli/user_commands.py new file mode 100644 index 0000000..781ef7f --- /dev/null +++ b/src/synclean/cli/user_commands.py @@ -0,0 +1,56 @@ +from typing import Optional +import click +from synclean.api.synapse import SynapseApiClient +from synclean.api.users import UserAPI +from synclean.models.enums import UserOrderBy, Direction +from synclean.models.pagination import UserPaginationParams + +pass_api = click.make_pass_decorator(SynapseApiClient) + + +user = click.Group(name="user", help="User commands.") + + +@user.command("ls") +@click.option("--limit", "-l", default=10, help="Number of users to list.") +@click.option("--offset", "-o", default=0, help="Number of the room to start from.") +@click.option("--search", "-s", help="Search term to filter by.") +@click.option("--order-by", "-O", + type=click.Choice(["user_id", "display_name", "media_length", "media_count"]), + default="media_length", help="Field to order result by.") +@click.option("--direction", "-d", + type=click.Choice(["f", "b"]), + default="b", help="Direction to order result by. (f=forward, b=backward)") +@pass_api +def user_ls( + api: SynapseApiClient, + limit: int, + offset: int, + search: Optional[str], + order_by: str, + direction: str +): + + order_by_enum = UserOrderBy(order_by) + direction_enum = Direction(direction) + + users_api = UserAPI(api) + + while True: + pagination_params = UserPaginationParams(limit, offset, order_by_enum, direction_enum, search) + + users = users_api.get_users_list_by_media(pagination_params) + + if users: + for u in users.users: + click.echo(f"Display name: {u.display_name}") + click.echo(f"Media count: {u.media_count}") + click.echo(f"Media length: {u.media_length_mb()}MB") + click.echo(f"User ID: {u.user_id}") + click.echo("=" * 40) + else: + click.echo("No users found.") + + offset += limit + if not click.confirm("Show more users?", default=True): + break \ No newline at end of file