@@ -3,7 +3,7 @@ use crate::store::UpsertMessageParams;
33use anyhow:: { Context , Result } ;
44use chrono:: { DateTime , Utc } ;
55use grammers_client:: types:: { Media , Message as TgMessage , Peer } ;
6- use grammers_session:: defs:: { PeerId , PeerRef } ;
6+ use grammers_session:: defs:: { PeerAuth , PeerId , PeerRef } ;
77use grammers_session:: Session ;
88use grammers_tl_types as tl;
99use std:: collections:: HashSet ;
@@ -147,8 +147,14 @@ pub struct SyncResult {
147147
148148impl App {
149149 /// Try to resolve a chat ID to a PeerRef from the session cache (no API calls).
150- /// Returns None if the chat is not cached in the session.
151- fn resolve_peer_from_session ( & self , chat_id : i64 , kind : & str ) -> Option < PeerRef > {
150+ /// If the peer is not in the session cache but we have a stored access_hash, use that.
151+ /// Returns None if the chat is not cached and we have no stored access_hash.
152+ fn resolve_peer_from_session (
153+ & self ,
154+ chat_id : i64 ,
155+ kind : & str ,
156+ stored_access_hash : Option < i64 > ,
157+ ) -> Option < PeerRef > {
152158 // Try based on the known type first
153159 match kind {
154160 "channel" | "group" => {
@@ -160,6 +166,13 @@ impl App {
160166 auth : info. auth ( ) ,
161167 } ) ;
162168 }
169+ // Fallback to stored access_hash if available
170+ if let Some ( hash) = stored_access_hash {
171+ return Some ( PeerRef {
172+ id : channel_peer_id,
173+ auth : PeerAuth :: from_hash ( hash) ,
174+ } ) ;
175+ }
163176 }
164177 "user" => {
165178 let user_peer_id = PeerId :: user ( chat_id) ;
@@ -169,11 +182,18 @@ impl App {
169182 auth : info. auth ( ) ,
170183 } ) ;
171184 }
185+ // Fallback to stored access_hash if available
186+ if let Some ( hash) = stored_access_hash {
187+ return Some ( PeerRef {
188+ id : user_peer_id,
189+ auth : PeerAuth :: from_hash ( hash) ,
190+ } ) ;
191+ }
172192 }
173193 _ => { }
174194 }
175195
176- // Fallback: try all peer types
196+ // Fallback: try all peer types from session cache
177197 // Try as channel first (most common for groups)
178198 let channel_peer_id = PeerId :: channel ( chat_id) ;
179199 if let Some ( info) = self . tg . session . peer ( channel_peer_id) {
@@ -201,6 +221,22 @@ impl App {
201221 auth : info. auth ( ) ,
202222 } ) ;
203223 }
224+ // Small group chats don't need access_hash, so try with default auth
225+ if stored_access_hash. is_some ( ) {
226+ return Some ( PeerRef {
227+ id : chat_peer_id,
228+ auth : PeerAuth :: default ( ) ,
229+ } ) ;
230+ }
231+ }
232+
233+ // Last resort: try to construct from stored access_hash with best-guess peer type
234+ if let Some ( hash) = stored_access_hash {
235+ // Most likely a channel/group if we have an access_hash
236+ return Some ( PeerRef {
237+ id : channel_peer_id,
238+ auth : PeerAuth :: from_hash ( hash) ,
239+ } ) ;
204240 }
205241
206242 None
@@ -312,15 +348,19 @@ impl App {
312348 continue ;
313349 }
314350
315- // Try to resolve peer from session (no API call)
316- let peer_ref = match self . resolve_peer_from_session ( chat. id , & chat. kind ) {
351+ // Try to resolve peer from session or stored access_hash (no API call)
352+ let peer_ref = match self . resolve_peer_from_session (
353+ chat. id ,
354+ & chat. kind ,
355+ chat. access_hash ,
356+ ) {
317357 Some ( p) => p,
318358 None => {
319359 log:: debug!(
320- "Skipping chat {} ({}) - not in session cache" ,
321- chat. name,
322- chat. id
323- ) ;
360+ "Skipping chat {} ({}) - not in session cache and no stored access_hash " ,
361+ chat. name,
362+ chat. id
363+ ) ;
324364 continue ;
325365 }
326366 } ;
@@ -497,6 +537,7 @@ impl App {
497537 chat. username . as_deref ( ) ,
498538 Some ( ts) ,
499539 chat. is_forum ,
540+ chat. access_hash ,
500541 )
501542 . await ?;
502543 }
@@ -596,7 +637,7 @@ impl App {
596637 . context ( "Failed to fetch dialogs from Telegram" ) ?
597638 {
598639 let peer = dialog. peer ( ) ;
599- let ( kind, name, username, is_forum) = peer_info ( peer) ;
640+ let ( kind, name, username, is_forum, access_hash ) = peer_info ( peer) ;
600641 let id = peer. id ( ) . bare_id ( ) ;
601642
602643 // Skip ignored chats.
@@ -605,7 +646,15 @@ impl App {
605646 }
606647
607648 self . store
608- . upsert_chat ( id, & kind, & name, username. as_deref ( ) , None , is_forum)
649+ . upsert_chat (
650+ id,
651+ & kind,
652+ & name,
653+ username. as_deref ( ) ,
654+ None ,
655+ is_forum,
656+ access_hash,
657+ )
609658 . await ?;
610659 chats_stored += 1 ;
611660
@@ -796,7 +845,15 @@ impl App {
796845 // Update chat's last_message_ts
797846 if let Some ( ts) = latest_ts {
798847 self . store
799- . upsert_chat ( id, & kind, & name, username. as_deref ( ) , Some ( ts) , is_forum)
848+ . upsert_chat (
849+ id,
850+ & kind,
851+ & name,
852+ username. as_deref ( ) ,
853+ Some ( ts) ,
854+ is_forum,
855+ access_hash,
856+ )
800857 . await ?;
801858 }
802859
@@ -874,7 +931,7 @@ impl App {
874931
875932 let archived_peers = self . fetch_archived_dialogs ( ) . await ?;
876933 for peer in archived_peers {
877- let ( kind, name, username, is_forum) = peer_info ( & peer) ;
934+ let ( kind, name, username, is_forum, access_hash ) = peer_info ( & peer) ;
878935 let id = peer. id ( ) . bare_id ( ) ;
879936
880937 // Skip ignored chats.
@@ -883,7 +940,15 @@ impl App {
883940 }
884941
885942 self . store
886- . upsert_chat ( id, & kind, & name, username. as_deref ( ) , None , is_forum)
943+ . upsert_chat (
944+ id,
945+ & kind,
946+ & name,
947+ username. as_deref ( ) ,
948+ None ,
949+ is_forum,
950+ access_hash,
951+ )
887952 . await ?;
888953 chats_stored += 1 ;
889954
@@ -1013,7 +1078,15 @@ impl App {
10131078 // Update chat's last_message_ts
10141079 if let Some ( ts) = latest_ts {
10151080 self . store
1016- . upsert_chat ( id, & kind, & name, username. as_deref ( ) , Some ( ts) , is_forum)
1081+ . upsert_chat (
1082+ id,
1083+ & kind,
1084+ & name,
1085+ username. as_deref ( ) ,
1086+ Some ( ts) ,
1087+ is_forum,
1088+ access_hash,
1089+ )
10171090 . await ?;
10181091 }
10191092
@@ -1282,28 +1355,36 @@ impl App {
12821355 }
12831356}
12841357
1285- /// Returns (kind, name, username, is_forum)
1286- fn peer_info ( peer : & Peer ) -> ( String , String , Option < String > , bool ) {
1358+ /// Returns (kind, name, username, is_forum, access_hash )
1359+ fn peer_info ( peer : & Peer ) -> ( String , String , Option < String > , bool , Option < i64 > ) {
12871360 match peer {
12881361 Peer :: User ( user) => {
12891362 let name = user. full_name ( ) ;
12901363 let username = user. username ( ) . map ( |s| s. to_string ( ) ) ;
1291- ( "user" . to_string ( ) , name, username, false )
1364+ // Extract access_hash from User raw type
1365+ let access_hash = match & user. raw {
1366+ tl:: enums:: User :: User ( u) => u. access_hash ,
1367+ tl:: enums:: User :: Empty ( _) => None ,
1368+ } ;
1369+ ( "user" . to_string ( ) , name, username, false , access_hash)
12921370 }
12931371 Peer :: Group ( group) => {
12941372 let name = group. title ( ) . map ( |s| s. to_string ( ) ) . unwrap_or_default ( ) ;
12951373 let username = group. username ( ) . map ( |s| s. to_string ( ) ) ;
12961374 // Check if this is a forum group (megagroup with forum flag)
1297- let is_forum = match & group. raw {
1298- tl:: enums:: Chat :: Channel ( channel) => channel. forum ,
1299- _ => false ,
1375+ // Extract access_hash from Channel (megagroups are channels internally)
1376+ let ( is_forum, access_hash) = match & group. raw {
1377+ tl:: enums:: Chat :: Channel ( channel) => ( channel. forum , channel. access_hash ) ,
1378+ _ => ( false , None ) ,
13001379 } ;
1301- ( "group" . to_string ( ) , name, username, is_forum)
1380+ ( "group" . to_string ( ) , name, username, is_forum, access_hash )
13021381 }
13031382 Peer :: Channel ( channel) => {
13041383 let name = channel. title ( ) . to_string ( ) ;
13051384 let username = channel. username ( ) . map ( |s| s. to_string ( ) ) ;
1306- ( "channel" . to_string ( ) , name, username, false )
1385+ // Extract access_hash from Channel raw type (it's directly a tl::types::Channel)
1386+ let access_hash = channel. raw . access_hash ;
1387+ ( "channel" . to_string ( ) , name, username, false , access_hash)
13071388 }
13081389 }
13091390}
0 commit comments