Skip to main content
Glama

mcp-google-sheets

find-attachment-by-row-id.ts9.19 kB
import { createAction, Property } from '@activepieces/pieces-framework'; import { httpClient, HttpMethod, HttpRequest } from '@activepieces/pieces-common'; import { smartsheetAuth } from '../../index'; import { smartsheetCommon } from '../common'; export const findAttachmentByRowId = createAction({ auth: smartsheetAuth, name: 'find_attachment_by_row_id', displayName: 'List Row Attachments', description: 'Get all attachments for a specific row in a Smartsheet, including row and discussion-level attachments with comprehensive pagination and filtering options', props: { sheet_id: smartsheetCommon.sheet_id(), row_id: smartsheetCommon.row_id, // Pagination options include_all: Property.Checkbox({ displayName: 'Include All Results', description: 'If true, include all results without pagination (overrides page and page size)', required: false, defaultValue: false, }), page: Property.Number({ displayName: 'Page Number', description: 'Which page to return (defaults to 1, ignored if "Include All Results" is true)', required: false, defaultValue: 1, }), page_size: Property.Number({ displayName: 'Page Size', description: 'Maximum number of items to return per page (defaults to 100, max 10000, ignored if "Include All Results" is true)', required: false, defaultValue: 100, }), // Filtering options attachment_type_filter: Property.StaticMultiSelectDropdown({ displayName: 'Filter by Attachment Type', description: 'Only return attachments of specific types (leave empty for all types)', required: false, options: { options: [ { label: 'Files', value: 'FILE' }, { label: 'URLs/Links', value: 'LINK' }, { label: 'Box.com', value: 'BOX_COM' }, { label: 'Dropbox', value: 'DROPBOX' }, { label: 'Egnyte', value: 'EGNYTE' }, { label: 'Evernote', value: 'EVERNOTE' }, { label: 'Google Drive', value: 'GOOGLE_DRIVE' }, { label: 'OneDrive', value: 'ONEDRIVE' }, { label: 'Trello', value: 'TRELLO' }, ], }, }), parent_type_filter: Property.StaticMultiSelectDropdown({ displayName: 'Filter by Parent Type', description: 'Only return attachments from specific parent types (leave empty for all)', required: false, options: { options: [ { label: 'Row Attachments', value: 'ROW' }, { label: 'Comment Attachments', value: 'COMMENT' }, { label: 'Sheet Attachments', value: 'SHEET' }, { label: 'Proof Attachments', value: 'PROOF' }, ], }, }), min_file_size_kb: Property.Number({ displayName: 'Minimum File Size (KB)', description: 'Only return files with size greater than or equal to this value (applies to FILE type only)', required: false, }), max_file_size_kb: Property.Number({ displayName: 'Maximum File Size (KB)', description: 'Only return files with size less than or equal to this value (applies to FILE type only)', required: false, }), }, async run(context) { const { sheet_id, row_id, include_all, page, page_size, attachment_type_filter, parent_type_filter, min_file_size_kb, max_file_size_kb, } = context.propsValue; // Build query parameters const queryParams: any = {}; if (include_all) { queryParams.includeAll = true; } else { if (page && page > 1) { queryParams.page = page; } if (page_size && page_size !== 100) { queryParams.pageSize = Math.min(page_size, 10000); // Cap at API limit } } const apiUrl = `${smartsheetCommon.baseUrl}/sheets/${sheet_id}/rows/${row_id}/attachments`; try { const request: HttpRequest = { method: HttpMethod.GET, url: apiUrl, headers: { 'Authorization': `Bearer ${context.auth}`, 'Content-Type': 'application/json', }, queryParams, }; const response = await httpClient.sendRequest(request); const attachmentData = response.body; // Apply client-side filters let filteredAttachments = attachmentData.data || []; // Filter by attachment type if (attachment_type_filter && attachment_type_filter.length > 0) { filteredAttachments = filteredAttachments.filter((attachment: any) => attachment_type_filter.includes(attachment.attachmentType) ); } // Filter by parent type if (parent_type_filter && parent_type_filter.length > 0) { filteredAttachments = filteredAttachments.filter((attachment: any) => parent_type_filter.includes(attachment.parentType) ); } // Filter by file size (only applies to FILE type) if (min_file_size_kb !== undefined || max_file_size_kb !== undefined) { filteredAttachments = filteredAttachments.filter((attachment: any) => { if (attachment.attachmentType !== 'FILE' || !attachment.sizeInKb) { return true; } const size = attachment.sizeInKb; if (min_file_size_kb !== undefined && size < min_file_size_kb) { return false; } if (max_file_size_kb !== undefined && size > max_file_size_kb) { return false; } return true; }); } // Organize attachments by type for better analysis const attachmentsByType: any = {}; const attachmentsByParent: any = {}; let totalFileSize = 0; filteredAttachments.forEach((attachment: any) => { // Group by attachment type if (!attachmentsByType[attachment.attachmentType]) { attachmentsByType[attachment.attachmentType] = []; } attachmentsByType[attachment.attachmentType].push(attachment); // Group by parent type if (!attachmentsByParent[attachment.parentType]) { attachmentsByParent[attachment.parentType] = []; } attachmentsByParent[attachment.parentType].push(attachment); // Calculate total file size for files if (attachment.attachmentType === 'FILE' && attachment.sizeInKb) { totalFileSize += attachment.sizeInKb; } }); return { success: true, // Pagination info pagination: { page_number: attachmentData.pageNumber, page_size: attachmentData.pageSize, total_pages: attachmentData.totalPages, total_count: attachmentData.totalCount, filtered_count: filteredAttachments.length, }, // Main results attachments: filteredAttachments, // Organized results attachments_by_type: attachmentsByType, attachments_by_parent: attachmentsByParent, // Summary statistics summary: { total_attachments: filteredAttachments.length, files_count: (attachmentsByType.FILE || []).length, links_count: (attachmentsByType.LINK || []).length, cloud_storage_count: filteredAttachments.length - (attachmentsByType.FILE || []).length - (attachmentsByType.LINK || []).length, row_attachments: (attachmentsByParent.ROW || []).length, comment_attachments: (attachmentsByParent.COMMENT || []).length, total_file_size_kb: totalFileSize, total_file_size_mb: Math.round(totalFileSize / 1024 * 100) / 100, }, // Download info for files download_info: filteredAttachments .filter((att: any) => att.attachmentType === 'FILE' && att.url) .map((att: any) => ({ attachment_id: att.id, name: att.name, download_url: att.url, url_expires_in_millis: att.urlExpiresInMillis, url_expires_at: att.urlExpiresInMillis ? new Date(Date.now() + att.urlExpiresInMillis).toISOString() : null, size_kb: att.sizeInKb, })), // Applied filters info filters_applied: { attachment_types: attachment_type_filter || [], parent_types: parent_type_filter || [], min_file_size_kb: min_file_size_kb, max_file_size_kb: max_file_size_kb, }, // Row and sheet info row_id: row_id, sheet_id: sheet_id, }; } catch (error: any) { if (error.response?.status === 400) { const errorBody = error.response.data; throw new Error(`Bad Request: ${errorBody.message || 'Invalid request parameters'}`); } else if (error.response?.status === 403) { throw new Error('Insufficient permissions to access attachments for this row'); } else if (error.response?.status === 404) { throw new Error('Sheet or row not found, or you do not have access to it'); } else if (error.response?.status === 429) { throw new Error('Rate limit exceeded. Please try again later.'); } throw new Error(`Failed to retrieve attachments: ${error.message}`); } }, });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/activepieces/activepieces'

If you have feedback or need assistance with the MCP directory API, please join our Discord server