Merge pull request #72 from mxl/fix/shared-folders-chatlist-support

fix: add support for shared folders (DialogFilterChatlist) in folder operations
This commit is contained in:
Eugene Evstafev 2026-03-16 08:27:46 +00:00 committed by GitHub
commit 14d1235bc2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

138
main.py
View file

@ -37,6 +37,7 @@ from telethon.tl.types import (
InputPeerChat, InputPeerChat,
InputPeerChannel, InputPeerChannel,
DialogFilter, DialogFilter,
DialogFilterChatlist,
DialogFilterDefault, DialogFilterDefault,
TextWithEntities, TextWithEntities,
) )
@ -4123,6 +4124,21 @@ async def list_folders() -> str:
} }
folders.append(folder_data) folders.append(folder_data)
elif isinstance(f, DialogFilterChatlist):
# Shared folders use DialogFilterChatlist type
title = f.title
if isinstance(title, TextWithEntities):
title = title.text
folder_data = {
"id": f.id,
"title": title,
"emoticon": getattr(f, "emoticon", None),
"type": "shared",
"included_peers_count": len(getattr(f, "include_peers", [])),
"pinned_peers_count": len(getattr(f, "pinned_peers", [])),
}
folders.append(folder_data)
if not folders: if not folders:
return "No folders found. Create one with create_folder tool." return "No folders found. Create one with create_folder tool."
@ -4147,7 +4163,7 @@ async def get_folder(folder_id: int) -> str:
target_folder = None target_folder = None
for f in result.filters: for f in result.filters:
if isinstance(f, DialogFilter) and f.id == folder_id: if isinstance(f, (DialogFilter, DialogFilterChatlist)) and f.id == folder_id:
target_folder = f target_folder = f
break break
@ -4212,7 +4228,15 @@ async def get_folder(folder_id: int) -> str:
"id": target_folder.id, "id": target_folder.id,
"title": title, "title": title,
"emoticon": getattr(target_folder, "emoticon", None), "emoticon": getattr(target_folder, "emoticon", None),
"filters": { "included_chats": included_chats,
"excluded_chats": excluded_chats,
"pinned_chats": pinned_chats,
}
if isinstance(target_folder, DialogFilterChatlist):
folder_data["type"] = "shared"
else:
folder_data["filters"] = {
"contacts": getattr(target_folder, "contacts", False), "contacts": getattr(target_folder, "contacts", False),
"non_contacts": getattr(target_folder, "non_contacts", False), "non_contacts": getattr(target_folder, "non_contacts", False),
"groups": getattr(target_folder, "groups", False), "groups": getattr(target_folder, "groups", False),
@ -4221,11 +4245,7 @@ async def get_folder(folder_id: int) -> str:
"exclude_muted": getattr(target_folder, "exclude_muted", False), "exclude_muted": getattr(target_folder, "exclude_muted", False),
"exclude_read": getattr(target_folder, "exclude_read", False), "exclude_read": getattr(target_folder, "exclude_read", False),
"exclude_archived": getattr(target_folder, "exclude_archived", False), "exclude_archived": getattr(target_folder, "exclude_archived", False),
}, }
"included_chats": included_chats,
"excluded_chats": excluded_chats,
"pinned_chats": pinned_chats,
}
return json.dumps(folder_data, indent=2, default=json_serializer) return json.dumps(folder_data, indent=2, default=json_serializer)
except Exception as e: except Exception as e:
@ -4274,7 +4294,7 @@ async def create_folder(
existing_ids = set() existing_ids = set()
folder_count = 0 folder_count = 0
for f in result.filters: for f in result.filters:
if isinstance(f, DialogFilter): if isinstance(f, (DialogFilter, DialogFilterChatlist)):
existing_ids.add(f.id) existing_ids.add(f.id)
folder_count += 1 folder_count += 1
@ -4356,7 +4376,7 @@ async def add_chat_to_folder(
target_folder = None target_folder = None
for f in result.filters: for f in result.filters:
if isinstance(f, DialogFilter) and f.id == folder_id: if isinstance(f, (DialogFilter, DialogFilterChatlist)) and f.id == folder_id:
target_folder = f target_folder = f
break break
@ -4390,24 +4410,35 @@ async def add_chat_to_folder(
pinned_peers.append(peer) pinned_peers.append(peer)
# Update the folder (keep all original attributes) # Update the folder (keep all original attributes)
updated_filter = DialogFilter( if isinstance(target_folder, DialogFilterChatlist):
id=target_folder.id, updated_filter = DialogFilterChatlist(
title=target_folder.title, id=target_folder.id,
emoticon=getattr(target_folder, "emoticon", None), title=target_folder.title,
pinned_peers=pinned_peers, emoticon=getattr(target_folder, "emoticon", None),
include_peers=include_peers, pinned_peers=pinned_peers,
exclude_peers=list(getattr(target_folder, "exclude_peers", [])), include_peers=include_peers,
contacts=getattr(target_folder, "contacts", False), title_noanimate=getattr(target_folder, "title_noanimate", None),
non_contacts=getattr(target_folder, "non_contacts", False), color=getattr(target_folder, "color", None),
groups=getattr(target_folder, "groups", False), )
broadcasts=getattr(target_folder, "broadcasts", False), else:
bots=getattr(target_folder, "bots", False), updated_filter = DialogFilter(
exclude_muted=getattr(target_folder, "exclude_muted", False), id=target_folder.id,
exclude_read=getattr(target_folder, "exclude_read", False), title=target_folder.title,
exclude_archived=getattr(target_folder, "exclude_archived", False), emoticon=getattr(target_folder, "emoticon", None),
title_noanimate=getattr(target_folder, "title_noanimate", None), pinned_peers=pinned_peers,
color=getattr(target_folder, "color", None), include_peers=include_peers,
) exclude_peers=list(getattr(target_folder, "exclude_peers", [])),
contacts=getattr(target_folder, "contacts", False),
non_contacts=getattr(target_folder, "non_contacts", False),
groups=getattr(target_folder, "groups", False),
broadcasts=getattr(target_folder, "broadcasts", False),
bots=getattr(target_folder, "bots", False),
exclude_muted=getattr(target_folder, "exclude_muted", False),
exclude_read=getattr(target_folder, "exclude_read", False),
exclude_archived=getattr(target_folder, "exclude_archived", False),
title_noanimate=getattr(target_folder, "title_noanimate", None),
color=getattr(target_folder, "color", None),
)
await client( await client(
functions.messages.UpdateDialogFilterRequest(id=folder_id, filter=updated_filter) functions.messages.UpdateDialogFilterRequest(id=folder_id, filter=updated_filter)
@ -4446,7 +4477,7 @@ async def remove_chat_from_folder(folder_id: int, chat_id: Union[int, str]) -> s
target_folder = None target_folder = None
for f in result.filters: for f in result.filters:
if isinstance(f, DialogFilter) and f.id == folder_id: if isinstance(f, (DialogFilter, DialogFilterChatlist)) and f.id == folder_id:
target_folder = f target_folder = f
break break
@ -4485,24 +4516,35 @@ async def remove_chat_from_folder(folder_id: int, chat_id: Union[int, str]) -> s
return f"Chat {chat_id} was not in folder {folder_id}." return f"Chat {chat_id} was not in folder {folder_id}."
# Update the folder (keep all original attributes) # Update the folder (keep all original attributes)
updated_filter = DialogFilter( if isinstance(target_folder, DialogFilterChatlist):
id=target_folder.id, updated_filter = DialogFilterChatlist(
title=target_folder.title, id=target_folder.id,
emoticon=getattr(target_folder, "emoticon", None), title=target_folder.title,
pinned_peers=pinned_peers, emoticon=getattr(target_folder, "emoticon", None),
include_peers=include_peers, pinned_peers=pinned_peers,
exclude_peers=list(getattr(target_folder, "exclude_peers", [])), include_peers=include_peers,
contacts=getattr(target_folder, "contacts", False), title_noanimate=getattr(target_folder, "title_noanimate", None),
non_contacts=getattr(target_folder, "non_contacts", False), color=getattr(target_folder, "color", None),
groups=getattr(target_folder, "groups", False), )
broadcasts=getattr(target_folder, "broadcasts", False), else:
bots=getattr(target_folder, "bots", False), updated_filter = DialogFilter(
exclude_muted=getattr(target_folder, "exclude_muted", False), id=target_folder.id,
exclude_read=getattr(target_folder, "exclude_read", False), title=target_folder.title,
exclude_archived=getattr(target_folder, "exclude_archived", False), emoticon=getattr(target_folder, "emoticon", None),
title_noanimate=getattr(target_folder, "title_noanimate", None), pinned_peers=pinned_peers,
color=getattr(target_folder, "color", None), include_peers=include_peers,
) exclude_peers=list(getattr(target_folder, "exclude_peers", [])),
contacts=getattr(target_folder, "contacts", False),
non_contacts=getattr(target_folder, "non_contacts", False),
groups=getattr(target_folder, "groups", False),
broadcasts=getattr(target_folder, "broadcasts", False),
bots=getattr(target_folder, "bots", False),
exclude_muted=getattr(target_folder, "exclude_muted", False),
exclude_read=getattr(target_folder, "exclude_read", False),
exclude_archived=getattr(target_folder, "exclude_archived", False),
title_noanimate=getattr(target_folder, "title_noanimate", None),
color=getattr(target_folder, "color", None),
)
await client( await client(
functions.messages.UpdateDialogFilterRequest(id=folder_id, filter=updated_filter) functions.messages.UpdateDialogFilterRequest(id=folder_id, filter=updated_filter)
@ -4545,7 +4587,7 @@ async def delete_folder(folder_id: int) -> str:
folder_exists = False folder_exists = False
folder_title = None folder_title = None
for f in result.filters: for f in result.filters:
if isinstance(f, DialogFilter) and f.id == folder_id: if isinstance(f, (DialogFilter, DialogFilterChatlist)) and f.id == folder_id:
folder_exists = True folder_exists = True
# Handle title which can be str or TextWithEntities # Handle title which can be str or TextWithEntities
title = f.title title = f.title
@ -4584,7 +4626,7 @@ async def reorder_folders(folder_ids: List[int]) -> str:
existing_ids = set() existing_ids = set()
for f in result.filters: for f in result.filters:
if isinstance(f, DialogFilter): if isinstance(f, (DialogFilter, DialogFilterChatlist)):
existing_ids.add(f.id) existing_ids.add(f.id)
# Validate all provided IDs exist # Validate all provided IDs exist