@@ -141,24 +141,53 @@ def drive_ensure_property_tab_folder(service, root_folder_id: str, prop: str, ta
141141 tab_id = drive_find_or_create_folder (service , prop_id , tab )
142142 return tab_id
143143
144- def drive_list_folder_files (service , folder_id : str ) -> List [Dict ]:
144+ def drive_list_folder_files (service , folder_id : str , recursive : bool = False ) -> List [Dict ]:
145145 """
146- List non-trashed files (id,name,mimeType) directly under folder_id.
147- We rely on filename extension for filtering by tab .
146+ List non-trashed files (id,name,mimeType) under folder_id.
147+ If recursive=True, also walk all subfolders .
148148 """
149- items = []
150- page_token = None
151- while True :
149+ items : List [Dict ] = []
150+ stack = [folder_id ]
151+ seen_folders = set ()
152+
153+ while stack :
154+ fid = stack .pop ()
155+ if fid in seen_folders :
156+ continue
157+ seen_folders .add (fid )
158+
152159 res = service .files ().list (
153- q = f"'{ folder_id } ' in parents and trashed=false" ,
160+ q = f"'{ fid } ' in parents and trashed=false" ,
154161 fields = "nextPageToken, files(id,name,mimeType)" ,
155- pageSize = 1000 ,
156- pageToken = page_token
162+ pageSize = 1000
157163 ).execute ()
158- items .extend (res .get ("files" , []))
164+
165+ for f in res .get ("files" , []):
166+ mime = f .get ("mimeType" , "" )
167+ if mime == "application/vnd.google-apps.folder" :
168+ if recursive :
169+ stack .append (f ["id" ])
170+ else :
171+ items .append (f )
172+
173+ # handle pagination (rare with 1000 pageSize, but safe)
159174 page_token = res .get ("nextPageToken" )
160- if not page_token :
161- break
175+ while page_token :
176+ res = service .files ().list (
177+ q = f"'{ fid } ' in parents and trashed=false" ,
178+ fields = "nextPageToken, files(id,name,mimeType)" ,
179+ pageSize = 1000 ,
180+ pageToken = page_token
181+ ).execute ()
182+ for f in res .get ("files" , []):
183+ mime = f .get ("mimeType" , "" )
184+ if mime == "application/vnd.google-apps.folder" :
185+ if recursive :
186+ stack .append (f ["id" ])
187+ else :
188+ items .append (f )
189+ page_token = res .get ("nextPageToken" )
190+
162191 return items
163192
164193def drive_upload_bytes (service , folder_id : str , filename : str , data : bytes ) -> str :
@@ -557,7 +586,6 @@ def auto_import_uploads():
557586
558587 print (f"auto_import_uploads: done, { imported } table(s) updated." )
559588 return imported
560-
561589#==================================================#
562590
563591# Run-once warm-up
@@ -590,7 +618,6 @@ def _startup_once():
590618 if not _startup_done :
591619 _run_startup_tasks ()
592620
593-
594621####################################### ========== ROUTES ==========#####################################
595622
596623#########################################################
@@ -1038,7 +1065,7 @@ def property_detail(property_name, tab):
10381065 upload_message = "Invalid Drive folder link or ID."
10391066 else :
10401067 service = get_drive_service ()
1041- files = drive_list_folder_files (service , folder_id )
1068+ files = drive_list_folder_files (service , folder_id , recursive = True )
10421069 imported = 0
10431070 with sqlite3 .connect (DB_NAME ) as conn :
10441071 c = conn .cursor ()
0 commit comments