package driveroot import ( "strings" "github.com/ultisuite/ulti-backend/internal/nextcloud" ) // NormalizeMountBackend maps stored backend_type to a provider family. func NormalizeMountBackend(backendType string) string { switch strings.TrimSpace(strings.ToLower(backendType)) { case "googledrive", "google": return "google" case "onedrive", "microsoft": return "microsoft" default: return strings.TrimSpace(strings.ToLower(backendType)) } } func isGoogleWorkspaceNativeMime(mimeType string) bool { switch strings.TrimSpace(mimeType) { case "application/vnd.google-apps.document", "application/vnd.google-apps.spreadsheet", "application/vnd.google-apps.presentation": return true default: return false } } func isMicrosoftOfficeMime(mimeType, name string) bool { mime := strings.ToLower(strings.TrimSpace(mimeType)) switch mime { case "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "application/msword", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.presentationml.presentation", "application/vnd.ms-powerpoint": return true } ext := "" if dot := strings.LastIndex(name, "."); dot >= 0 { ext = strings.ToLower(name[dot+1:]) } switch ext { case "doc", "docx", "xls", "xlsx", "ppt", "pptx": return true default: return false } } func providerIDFromETag(etag string) string { id := strings.Trim(strings.TrimSpace(etag), "\"") if id == "" { return "" } // Google Drive file ids are alphanumeric plus _ and -. for _, r := range id { if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') || (r >= '0' && r <= '9') || r == '_' || r == '-' { continue } return "" } if len(id) < 10 { return "" } return id } // GoogleWorkspaceWebURL builds a browser editor URL for native Google Workspace files. func GoogleWorkspaceWebURL(mimeType, fileID string) string { fileID = strings.TrimSpace(fileID) if fileID == "" { return "" } switch strings.TrimSpace(mimeType) { case "application/vnd.google-apps.document": return "https://docs.google.com/document/d/" + fileID + "/edit" case "application/vnd.google-apps.spreadsheet": return "https://docs.google.com/spreadsheets/d/" + fileID + "/edit" case "application/vnd.google-apps.presentation": return "https://docs.google.com/presentation/d/" + fileID + "/edit" default: return "" } } func shouldOpenMountExternally(backend, mimeType, name string) bool { backend = NormalizeMountBackend(backend) if backend == "google" && isGoogleWorkspaceNativeMime(mimeType) { return true } if backend == "microsoft" && isMicrosoftOfficeMime(mimeType, name) { return true } return false } // EnrichMountCloudNative marks mount files that should open in the provider's web editor. func EnrichMountCloudNative(file *nextcloud.FileInfo, mountBackend string) { if file == nil || file.Type == "directory" { return } backend := NormalizeMountBackend(mountBackend) if backend == "" { return } file.MountBackend = backend if !shouldOpenMountExternally(backend, file.MimeType, file.Name) { return } file.OpenExternally = true if backend == "google" && isGoogleWorkspaceNativeMime(file.MimeType) { if id := providerIDFromETag(file.ETag); id != "" { file.ExternalURL = GoogleWorkspaceWebURL(file.MimeType, id) } } } func EnrichMountCloudNativeFiles(files []nextcloud.FileInfo, mountBackend string) []nextcloud.FileInfo { for i := range files { EnrichMountCloudNative(&files[i], mountBackend) } return files }