Nextcloud script with preprocessor template

Script windmill

by dieriba.pro916 ยท 10/10/2025

  • Submitted by dieriba.pro916 Bun
    Created 214 days ago
    1
    import * as wmill from "windmill-client";
    2
    import createClient, { type Middleware } from "openapi-fetch";
    3
    
    
    4
    // Nextcloud webhook payload types
    5
    export interface NextcloudWebhookPayload {
    6
      event: NextcloudEvent;
    7
      user: NextcloudUser;
    8
      time: number; // UNIX timestamp in seconds
    9
    }
    10
    
    
    11
    export interface NextcloudEvent {
    12
      node: NextcloudNode;
    13
      class: string; // e.g. "OCP\\Files\\Events\\Node\\NodeWrittenEvent"
    14
    }
    15
    
    
    16
    export interface NextcloudNode {
    17
      id: number;
    18
      path: string;
    19
      // optional fields you may see in other events
    20
      storage?: string;
    21
      size?: number;
    22
      name?: string;
    23
    }
    24
    
    
    25
    export interface NextcloudUser {
    26
      uid: string;
    27
      displayName?: string;
    28
    }
    29
    
    
    30
    /**
    31
     * Nextcloud Trigger Preprocessor
    32
     * 
    33
     * This function runs BEFORE the main function.
    34
     * 
    35
     * It processes raw Nextcloud webhook trigger data before passing it to `main()`.
    36
     * Supports the available Nextcloud events:
    37
     * - FormSubmittedEvent: Form submissions from Nextcloud Forms
    38
     * - NodeWrittenEvent: File/folder operations (create, update, delete)
    39
     * 
    40
     * The returned object determines `main()` parameters based on event type.
    41
     * 
    42
     * @param event - Nextcloud trigger data and details
    43
     * @returns Processed data for `main()`
    44
     */
    45
    export async function preprocessor(
    46
      event: {
    47
        kind: 'nextcloud',
    48
        headers: Record<string, string>,
    49
        payload: NextcloudWebhookPayload,
    50
      },
    51
    ) {
    52
      if (event.kind === 'nextcloud') {
    53
        const payload = event.payload;
    54
    
    
    55
        const baseEvent = {
    56
          eventType: payload.event.class,
    57
          userId: payload.user.uid,
    58
          timestamp: new Date(payload.time * 1000).toISOString(), // Convert UNIX timestamp to ISO
    59
          headers: event.headers || {},
    60
        };
    61
    
    
    62
        // Extract event type from class name
    63
        const eventTypeMatch = payload.event.class.match(/(\w+)Event$/);
    64
        const eventType = eventTypeMatch ? eventTypeMatch[1] : 'Unknown';
    65
    
    
    66
        // Handle specific Nextcloud event types
    67
        switch (eventType) {
    68
          case 'FormSubmitted':
    69
            return {
    70
              ...baseEvent,
    71
              category: 'form',
    72
              user: {
    73
                uid: payload.user.uid,
    74
                displayName: payload.user.displayName || ''
    75
              },
    76
              rawPayload: payload
    77
            };
    78
            
    79
          case 'NodeWritten':
    80
            return {
    81
              ...baseEvent,
    82
              category: 'file',
    83
              user: {
    84
                uid: payload.user.uid,
    85
                displayName: payload.user.displayName || ''
    86
              },
    87
              node: {
    88
                id: payload.event.node.id,
    89
                path: payload.event.node.path,
    90
                storage: payload.event.node.storage,
    91
                size: payload.event.node.size,
    92
                name: payload.event.node.name
    93
              },
    94
              rawPayload: payload
    95
            };
    96
            
    97
          default:
    98
            return {
    99
              ...baseEvent,
    100
              category: 'other',
    101
              eventClass: payload.event.class,
    102
              data: payload.event,
    103
              rawPayload: payload
    104
            };
    105
        }
    106
      }
    107
    
    
    108
      throw new Error(`Expected nextcloud trigger kind, got: ${event.kind}`);
    109
    }
    110
    
    
    111
    /**
    112
     * Main Function - Handles processed Nextcloud events
    113
     * 
    114
     * Called AFTER `preprocessor()`, with its return values.
    115
     * 
    116
     * This example demonstrates integrating with Nextcloud APIs using openapi-fetch
    117
     * and windmill-client, following the official Nextcloud Hub example patterns.
    118
     * 
    119
     * @param eventType - Type of Nextcloud event class name
    120
     * @param category - Event category ('form', 'file', or 'other')
    121
     * @param userId - ID of the user who triggered the event
    122
     * @param user - User information
    123
     * @param node - Node information (for file events)
    124
     * @param eventClass - Full event class name (for other events)
    125
     * @param data - Generic event data (for other events)
    126
     * @param timestamp - Event timestamp
    127
     * @param rawPayload - Raw event payload from Nextcloud
    128
     * @param nextcloud_resource - Nextcloud resource containing server URL and credentials
    129
     */
    130
    export async function main(
    131
      eventType: string,
    132
      category: string,
    133
      userId?: string,
    134
      user?: {
    135
        uid: string;
    136
        displayName: string;
    137
      },
    138
      node?: {
    139
        id?: number;
    140
        path?: string;
    141
        storage?: string;
    142
        size?: number;
    143
        name?: string;
    144
      },
    145
      eventClass?: string,
    146
      data?: any,
    147
      timestamp?: string,
    148
      rawPayload?: NextcloudWebhookPayload,
    149
      nextcloud_resource?: string
    150
    ) {
    151
    
    
    152
      const resource = await wmill.getResource(nextcloud_resource)
    153
      const client = createClient({ baseUrl: resource.baseUrl });
    154
      
    155
      console.log(`Processing Nextcloud event: ${eventType}`);
    156
      console.log(`Category: ${category}`);
    157
      console.log(`User: ${user?.uid} (${user?.displayName})`);
    158
      console.log(`Timestamp: ${timestamp}`);
    159
    
    
    160
      try {
    161
        // Add authentication middleware
    162
        const authMiddleware: Middleware = {
    163
          async onRequest({ request }: { request: Request }) {
    164
            // Add Basic Authentication header
    165
            request.headers.set(
    166
              "Authorization",
    167
              `Basic ${btoa(resource.username + ':' + resource.password)}`
    168
            );
    169
    
    
    170
            // Add required Nextcloud headers
    171
            request.headers.set("OCS-APIRequest", "true");
    172
            request.headers.set("Content-Type", "application/json");
    173
            request.headers.set("Accept", "application/json");
    174
    
    
    175
            return request;
    176
          },
    177
        };
    178
    
    
    179
        client.use(authMiddleware);
    180
        console.log(`Connected to Nextcloud at: ${resource.baseUrl}`);
    181
      } catch (error) {
    182
        console.error('Failed to setup Nextcloud API client:', error);
    183
        return { success: false, error: 'Failed to configure Nextcloud API' };
    184
      }
    185
    
    
    186
      // Handle specific event types
    187
      switch (category) {
    188
        case 'form':
    189
          console.log(`Form event processed: ${eventType}`);
    190
          break;
    191
    
    
    192
        case 'file':
    193
          console.log(`File event: ${node?.path} (ID: ${node?.id})`);
    194
          console.log(`Node details:`, {
    195
            path: node?.path,
    196
            size: node?.size,
    197
            storage: node?.storage,
    198
            name: node?.name
    199
          });
    200
          break;
    201
    
    
    202
        case 'other':
    203
          console.log(`Other event type: ${eventClass}`);
    204
          console.log('Event data:', data);
    205
    
    
    206
          if (client && userId) {
    207
            try {
    208
              // Example: Log unknown events (adjust endpoint based on your Nextcloud setup)
    209
              console.log('Logging unknown event to system');
    210
            } catch (error) {
    211
              console.error('Failed to log unknown event:', error);
    212
            }
    213
          }
    214
          break;
    215
      }
    216
    
    
    217
      // Return event summary
    218
      return {
    219
        success: true,
    220
        eventType,
    221
        category,
    222
        userId,
    223
        timestamp,
    224
        processed: true,
    225
        message: `Successfully processed ${eventType} event`,
    226
        eventDetails: {
    227
          user: user || null,
    228
          node: node || null,
    229
          data: data || null,
    230
          eventClass: eventClass || null
    231
        }
    232
      };
    233
    }