Built motion from commit 3e059bc2.|2.5.32
[motion2.git] / server / config / seedDB / voiceExtensions.js
index 76bdc68..82428ad 100644 (file)
@@ -7,318 +7,318 @@ var logger = require('../logger')('app');
 var DBPromise = require('bluebird');
 
 var applications = {
-    '600': [{
-        app: 'Set',
-        appdata: 'CDR(type)=internal',
-    }, {
-        app: 'Answer'
-    }, {
-        app: 'Playback',
-        appdata: 'demo-echotest',
-        isApp: true
-    }, {
-        app: 'Echo',
-        isApp: true
-    }, {
-        app: 'Playback',
-        appdata: 'demo-echodone',
-        isApp: true
-    }, {
-        app: 'Hangup'
-    }],
-    '6000': [{
-        app: 'Set',
-        appdata: 'CDR(type)=internal'
-    }, {
-        app: 'Answer'
-    }, {
-        app: 'Queue',
-        appdata: 'Support,xX,,,300,,,,,',
-        appType: 'queue',
-        isApp: true
-    }, {
-        app: 'Hangup'
-    }],
-    '6001': [{
-        app: 'Set',
-        appdata: 'CDR(type)=internal'
-    }, {
-        app: 'Answer'
-    }, {
-        app: 'Queue',
-        appdata: 'Sales,xX,,,300,,,,,',
-        appType: 'queue',
-        isApp: true
-    }, {
-        app: 'Hangup'
-    }],
-    '6666': [{
-        app: 'Set',
-        appdata: 'CDR(type)=internal'
-    }, {
-        app: 'AGI',
-        appdata: 'agi://127.0.0.1/square,AutoAttendant',
-        appType: 'agi',
-        isApp: true
-    }, {
-        app: 'Hangup'
-    }],
-    '6667': [{
-        app: 'Set',
-        appdata: 'CDR(type)=internal'
-    }, {
-        app: 'AGI',
-        appdata: 'agi://127.0.0.1/square,Orders',
-        appType: 'agi',
-        isApp: true
-    }, {
-        app: 'Hangup'
-    }],
-    '6668': [{
-        app: 'Set',
-        appdata: 'CDR(type)=internal'
-    }, {
-        app: 'AGI',
-        appdata: 'agi://127.0.0.1/square,CSI',
-        appType: 'agi',
-        isApp: true
-    }, {
-        app: 'Hangup'
-    }],
-    '6669': [{
-        app: 'Set',
-        appdata: 'CDR(type)=internal'
-    }, {
-        app: 'AGI',
-        appdata: 'agi://127.0.0.1/square,Survey',
-        appType: 'agi',
-        isApp: true
-    }, {
-        app: 'Hangup'
-    }],
-    '6670': [{
-        app: 'Set',
-        appdata: 'CDR(type)=internal'
-    }, {
-        app: 'AGI',
-        appdata: 'agi://127.0.0.1/square,AgentManagement',
-        appType: 'agi',
-        isApp: true
-    }, {
-        app: 'Hangup'
-    }],
-    'xcally-motion-dialer': [{
-        app: 'Set',
-        appdata: 'CDR(type)=dialer'
-    }, {
-        app: 'Set',
-        appdata: 'CALLERID(all)=${XMD-CALLERID}'
-    }, {
-        app: 'GotoIf',
-        appdata: '$["${XMD-AMD}" != "NONE" ]?5:11'
-    }, {
-        app: 'Answer',
-        appdata: ''
-    }, {
-        app: 'Background',
-        appdata: 'silence/1'
-    }, {
-        app: 'AMD',
-        appdata: '${XMD-AMDINITIALSILENCE},${XMD-AMDGREETING},${XMD-AMDAFTERGREETINGSILENCE},${XMD-AMDTOTALANALYSISTIME},${XMD-AMDMINWORDLENGTH},${XMD-AMDBETWEENWORDSSILENCE},${XMD-AMDMAXIMUMNUMBEROFWORDS},${XMD-AMDSILENCETHRESHOLD},${XMD-AMDMAXIMUMWORDLENGTH}'
-    }, {
-        app: 'GotoIf',
-        appdata: '$["${AMDSTATUS}" == "HUMAN" ]?11:9'
-    }, {
-        app: 'GotoIf',
-        appdata: '$["${AMDSTATUS}" == "NOTSURE" ]?11:10'
-    }, {
-        app: 'GotoIf',
-        appdata: '$["${AMDSTATUS}" == "MACHINE" ]?14:11'
-    }, {
-        app: 'Execif',
-        appdata: '$["${XMD-AGI}" != "NONE" ]?AGI(${XMD-AGI})'
-    }, {
-        app: 'Execif',
-        appdata: '$["${XMD-QUEUE}" != "NONE" ]?QUEUE(${XMD-QUEUE})'
-    }, {
-        app: 'Execif',
-        appdata: '$["${XMD-AGIAFTER}" != "NONE" ]?AGI(${XMD-AGIAFTER})'
-    }, {
-        app: 'Hangup'
-    }],
-    'xcally-motion-fax': [{
-        app: 'Set',
-        appdata: 'CDR(type)=outbound-fax'
-    }, {
-        app: 'Wait',
-        appdata: '6'
-    }, {
-        app: 'Set',
-        appdata: 'FAXOPT(ecm)=${XMF-ECM}'
-    }, {
-        app: 'Set',
-        appdata: 'FAXOPT(headerinfo)=${XMF-HEADERINFO}'
-    }, {
-        app: 'Set',
-        appdata: 'FAXOPT(localstationid)=${XMF-LOCALSTATIONID}'
-    }, {
-        app: 'Set',
-        appdata: 'FAXOPT(maxrate)=${XMF-MAXRATE}'
-    }, {
-        app: 'Set',
-        appdata: 'FAXOPT(minrate)=${XMF-MINRATE}'
-    }, {
-        app: 'Set',
-        appdata: 'FAXOPT(modem)=${XMF-MODEM}'
-    }, {
-        app: 'Set',
-        appdata: 'FAXOPT(t38timeout)=${XMF-T38TIMEOUT}'
-    }, {
-        app: 'SendFax',
-        appdata: '${XMF-PATH},d'
-    }],
-    'xcally-motion-preview': [{
-        app: 'Set',
-        appdata: 'CDR(type)=dialer'
-    }, {
-        app: 'Set',
-        appdata: 'CALLERID(all)=${XMD-CALLERID}'
-    }, {
-        app: 'Execif',
-        appdata: '$["${XMD-AGI}" != "NONE" ]?AGI(${XMD-AGI})'
-    }, {
-        app: 'Dial',
-        appdata: '${XMD-DIALCHANNEL},${XMD-DIALTIMEOUT},${XMD-DIALOPTIONS},${XMD-DIALURL}'
-    }, {
-        app: 'Execif',
-        appdata: '$["${XMD-AGIAFTER}" != "NONE" ]?AGI(${XMD-AGIAFTER})'
-    }, {
-        app: 'Hangup'
-    }],
-    '_.': [{
-        app: 'Set',
-        appdata: 'CDR(type)=outbound'
-    }, {
-        app: 'Set',
-        appdata: 'XCALLY-MOTION-ANSWER=0'
-    }, {
-        app: 'Set',
-        appdata: 'XCALLY-MOTION-PROGRESS=0'
-    }, {
-        app: 'Set',
-        appdata: 'MONITOR_OPTIONS=ab'
-    }, {
-        app: 'Set',
-        outboundrouteid: true
-    }, {
-        app: 'Set',
-        appdata: '_XCALLY_MIXMONITOR_UNIQUEID=${UNIQUEID}'
-    }, {
-        app: 'Set',
-        appdata: '_XCALLY_MIXMONITOR_FORMAT=wav'
-    }, {
-        app: 'Playback',
-        appdata: 'demo-congrats',
-        appType: 'custom',
-        isApp: true
-    }, {
-        app: 'Hangup'
-    }],
-    '_X.': [{
-        app: 'Set',
-        appdata: 'CDR(type)=inbound'
-    }, {
-        app: 'Answer'
-    }, {
-        app: 'Playback',
-        appdata: 'demo-congrats',
-        isApp: true
-    }, {
-        app: 'Hangup'
-    }],
-    'h': [{
-        app: 'Hangup'
-    }],
-    'failed': [{
-        app: 'Hangup'
-    }],
+  '600': [{
+    app: 'Set',
+    appdata: 'CDR(type)=internal',
+  }, {
+    app: 'Answer'
+  }, {
+    app: 'Playback',
+    appdata: 'demo-echotest',
+    isApp: true
+  }, {
+    app: 'Echo',
+    isApp: true
+  }, {
+    app: 'Playback',
+    appdata: 'demo-echodone',
+    isApp: true
+  }, {
+    app: 'Hangup'
+  }],
+  '6000': [{
+    app: 'Set',
+    appdata: 'CDR(type)=internal'
+  }, {
+    app: 'Answer'
+  }, {
+    app: 'Queue',
+    appdata: 'Support,xX,,,300,,,,,',
+    appType: 'queue',
+    isApp: true
+  }, {
+    app: 'Hangup'
+  }],
+  '6001': [{
+    app: 'Set',
+    appdata: 'CDR(type)=internal'
+  }, {
+    app: 'Answer'
+  }, {
+    app: 'Queue',
+    appdata: 'Sales,xX,,,300,,,,,',
+    appType: 'queue',
+    isApp: true
+  }, {
+    app: 'Hangup'
+  }],
+  '6666': [{
+    app: 'Set',
+    appdata: 'CDR(type)=internal'
+  }, {
+    app: 'AGI',
+    appdata: 'agi://127.0.0.1/square,AutoAttendant',
+    appType: 'agi',
+    isApp: true
+  }, {
+    app: 'Hangup'
+  }],
+  '6667': [{
+    app: 'Set',
+    appdata: 'CDR(type)=internal'
+  }, {
+    app: 'AGI',
+    appdata: 'agi://127.0.0.1/square,Orders',
+    appType: 'agi',
+    isApp: true
+  }, {
+    app: 'Hangup'
+  }],
+  '6668': [{
+    app: 'Set',
+    appdata: 'CDR(type)=internal'
+  }, {
+    app: 'AGI',
+    appdata: 'agi://127.0.0.1/square,CSI',
+    appType: 'agi',
+    isApp: true
+  }, {
+    app: 'Hangup'
+  }],
+  '6669': [{
+    app: 'Set',
+    appdata: 'CDR(type)=internal'
+  }, {
+    app: 'AGI',
+    appdata: 'agi://127.0.0.1/square,Survey',
+    appType: 'agi',
+    isApp: true
+  }, {
+    app: 'Hangup'
+  }],
+  '6670': [{
+    app: 'Set',
+    appdata: 'CDR(type)=internal'
+  }, {
+    app: 'AGI',
+    appdata: 'agi://127.0.0.1/square,AgentManagement',
+    appType: 'agi',
+    isApp: true
+  }, {
+    app: 'Hangup'
+  }],
+  'xcally-motion-dialer': [{
+    app: 'Set',
+    appdata: 'CDR(type)=dialer'
+  }, {
+    app: 'Set',
+    appdata: 'CALLERID(all)=${XMD-CALLERID}'
+  }, {
+    app: 'GotoIf',
+    appdata: '$["${XMD-AMD}" != "NONE" ]?5:11'
+  }, {
+    app: 'Answer',
+    appdata: ''
+  }, {
+    app: 'Background',
+    appdata: 'silence/1'
+  }, {
+    app: 'AMD',
+    appdata: '${XMD-AMDINITIALSILENCE},${XMD-AMDGREETING},${XMD-AMDAFTERGREETINGSILENCE},${XMD-AMDTOTALANALYSISTIME},${XMD-AMDMINWORDLENGTH},${XMD-AMDBETWEENWORDSSILENCE},${XMD-AMDMAXIMUMNUMBEROFWORDS},${XMD-AMDSILENCETHRESHOLD},${XMD-AMDMAXIMUMWORDLENGTH}'
+  }, {
+    app: 'GotoIf',
+    appdata: '$["${AMDSTATUS}" == "HUMAN" ]?11:9'
+  }, {
+    app: 'GotoIf',
+    appdata: '$["${AMDSTATUS}" == "NOTSURE" ]?11:10'
+  }, {
+    app: 'GotoIf',
+    appdata: '$["${AMDSTATUS}" == "MACHINE" ]?14:11'
+  }, {
+    app: 'Execif',
+    appdata: '$["${XMD-AGI}" != "NONE" ]?AGI(${XMD-AGI})'
+  }, {
+    app: 'Execif',
+    appdata: '$["${XMD-QUEUE}" != "NONE" ]?QUEUE(${XMD-QUEUE})'
+  }, {
+    app: 'Execif',
+    appdata: '$["${XMD-AGIAFTER}" != "NONE" ]?AGI(${XMD-AGIAFTER})'
+  }, {
+    app: 'Hangup'
+  }],
+  'xcally-motion-fax': [{
+    app: 'Set',
+    appdata: 'CDR(type)=outbound-fax'
+  }, {
+    app: 'Wait',
+    appdata: '6'
+  }, {
+    app: 'Set',
+    appdata: 'FAXOPT(ecm)=${XMF-ECM}'
+  }, {
+    app: 'Set',
+    appdata: 'FAXOPT(headerinfo)=${XMF-HEADERINFO}'
+  }, {
+    app: 'Set',
+    appdata: 'FAXOPT(localstationid)=${XMF-LOCALSTATIONID}'
+  }, {
+    app: 'Set',
+    appdata: 'FAXOPT(maxrate)=${XMF-MAXRATE}'
+  }, {
+    app: 'Set',
+    appdata: 'FAXOPT(minrate)=${XMF-MINRATE}'
+  }, {
+    app: 'Set',
+    appdata: 'FAXOPT(modem)=${XMF-MODEM}'
+  }, {
+    app: 'Set',
+    appdata: 'FAXOPT(t38timeout)=${XMF-T38TIMEOUT}'
+  }, {
+    app: 'SendFax',
+    appdata: '${XMF-PATH},d'
+  }],
+  'xcally-motion-preview': [{
+    app: 'Set',
+    appdata: 'CDR(type)=dialer'
+  }, {
+    app: 'Set',
+    appdata: 'CALLERID(all)=${XMD-CALLERID}'
+  }, {
+    app: 'Execif',
+    appdata: '$["${XMD-AGI}" != "NONE" ]?AGI(${XMD-AGI})'
+  }, {
+    app: 'Dial',
+    appdata: '${XMD-DIALCHANNEL},${XMD-DIALTIMEOUT},${XMD-DIALOPTIONS},${XMD-DIALURL}'
+  }, {
+    app: 'Execif',
+    appdata: '$["${XMD-AGIAFTER}" != "NONE" ]?AGI(${XMD-AGIAFTER})'
+  }, {
+    app: 'Hangup'
+  }],
+  '_.': [{
+    app: 'Set',
+    appdata: 'CDR(type)=outbound'
+  }, {
+    app: 'Set',
+    appdata: 'XCALLY-MOTION-ANSWER=0'
+  }, {
+    app: 'Set',
+    appdata: 'XCALLY-MOTION-PROGRESS=0'
+  }, {
+    app: 'Set',
+    appdata: 'MONITOR_OPTIONS=ab'
+  }, {
+    app: 'Set',
+    outboundrouteid: true
+  }, {
+    app: 'Set',
+    appdata: '_XCALLY_MIXMONITOR_UNIQUEID=${UNIQUEID}'
+  }, {
+    app: 'Set',
+    appdata: '_XCALLY_MIXMONITOR_FORMAT=wav'
+  }, {
+    app: 'Playback',
+    appdata: 'demo-congrats',
+    appType: 'custom',
+    isApp: true
+  }, {
+    app: 'Hangup'
+  }],
+  '_X.': [{
+    app: 'Set',
+    appdata: 'CDR(type)=inbound'
+  }, {
+    app: 'Answer'
+  }, {
+    app: 'Playback',
+    appdata: 'demo-congrats',
+    isApp: true
+  }, {
+    app: 'Hangup'
+  }],
+  'h': [{
+    app: 'Hangup'
+  }],
+  'failed': [{
+    app: 'Hangup'
+  }],
 };
 
 var voiceExtensions = [{
-    type: 'internal',
-    context: 'from-sip',
-    exten: '600',
-    description: 'echo test demo auto generated'
+  type: 'internal',
+  context: 'from-sip',
+  exten: '600',
+  description: 'echo test demo auto generated'
 }, {
-    type: 'internal',
-    context: 'from-sip',
-    exten: '6000',
-    description: 'forward to Support queue auto generated'
+  type: 'internal',
+  context: 'from-sip',
+  exten: '6000',
+  description: 'forward to Support queue auto generated'
 }, {
-    type: 'internal',
-    context: 'from-sip',
-    exten: '6001',
-    description: 'forward to Sales queue auto generated'
+  type: 'internal',
+  context: 'from-sip',
+  exten: '6001',
+  description: 'forward to Sales queue auto generated'
 }, {
-    type: 'internal',
-    context: 'from-sip',
-    exten: '6666',
-    description: 'forward to Auto Attendant IVR auto generated'
+  type: 'internal',
+  context: 'from-sip',
+  exten: '6666',
+  description: 'forward to Auto Attendant IVR auto generated'
 }, {
-    type: 'internal',
-    context: 'from-sip',
-    exten: '6667',
-    description: 'forward to Orders IVR auto generated'
+  type: 'internal',
+  context: 'from-sip',
+  exten: '6667',
+  description: 'forward to Orders IVR auto generated'
 }, {
-    type: 'internal',
-    context: 'from-sip',
-    exten: '6668',
-    description: 'forward to CSI IVR auto generated'
+  type: 'internal',
+  context: 'from-sip',
+  exten: '6668',
+  description: 'forward to CSI IVR auto generated'
 }, {
-    type: 'internal',
-    context: 'from-sip',
-    exten: '6669',
-    description: 'forward to Survey IVR auto generated'
+  type: 'internal',
+  context: 'from-sip',
+  exten: '6669',
+  description: 'forward to Survey IVR auto generated'
 }, {
-    type: 'internal',
-    context: 'from-sip',
-    exten: '6670',
-    description: 'forward to Agent Management IVR auto generated'
+  type: 'internal',
+  context: 'from-sip',
+  exten: '6670',
+  description: 'forward to Agent Management IVR auto generated'
 }, {
-    type: 'system',
-    context: 'from-sip',
-    exten: 'xcally-motion-dialer',
-    description: 'dialer extensions auto generated'
+  type: 'system',
+  context: 'from-sip',
+  exten: 'xcally-motion-dialer',
+  description: 'dialer extensions auto generated'
 }, {
-    type: 'system',
-    context: 'from-sip',
-    exten: 'xcally-motion-fax',
-    description: 'fax extensions auto generated'
+  type: 'system',
+  context: 'from-sip',
+  exten: 'xcally-motion-fax',
+  description: 'fax extensions auto generated'
 }, {
-    type: 'system',
-    context: 'from-sip',
-    exten: 'xcally-motion-preview',
-    description: 'dialer extensions auto generated'
+  type: 'system',
+  context: 'from-sip',
+  exten: 'xcally-motion-preview',
+  description: 'dialer extensions auto generated'
 }, {
-    type: 'outbound',
-    context: 'from-sip',
-    exten: '_.',
-    description: 'demo outbound calls auto generated'
+  type: 'outbound',
+  context: 'from-sip',
+  exten: '_.',
+  description: 'demo outbound calls auto generated'
 }, {
-    type: 'inbound',
-    context: 'from-voip-provider',
-    exten: '_X.',
-    description: 'catch all inbound calls auto generated'
+  type: 'inbound',
+  context: 'from-voip-provider',
+  exten: '_X.',
+  description: 'catch all inbound calls auto generated'
 }, {
-    type: 'system',
-    context: 'from-sip',
-    exten: 'h',
-    description: 'catch hangup event auto generated'
+  type: 'system',
+  context: 'from-sip',
+  exten: 'h',
+  description: 'catch hangup event auto generated'
 }, {
-    type: 'system',
-    context: 'from-sip',
-    exten: 'failed',
-    description: 'catch failed event auto generated'
+  type: 'system',
+  context: 'from-sip',
+  exten: 'failed',
+  description: 'catch failed event auto generated'
 }];
 
 var applicationsAlways = {
@@ -329,81 +329,82 @@ var applicationsAlways = {
     app: 'Return'
   }],
   '_[x][c][a][l][l][y][Q][u][e][u][e][E][x][t][e][n][s][i][o][n].': [{
-    app: 'Progress'
-  },
-  {
-    app: 'Queue',
-    appdata: '${EXTEN:20},xX'
-  }]
+      app: 'Progress'
+    },
+    {
+      app: 'Queue',
+      appdata: '${EXTEN:20},xX'
+    }
+  ]
 };
 
 var voiceExtensionsAlways = [{
-    type: 'system',
-    context: 'xcally-mixmonitor-context',
-    exten: 's'
+  type: 'system',
+  context: 'xcally-mixmonitor-context',
+  exten: 's'
 }, {
-    type: 'system',
-    context: 'from-sip',
-    exten: '_[x][c][a][l][l][y][Q][u][e][u][e][E][x][t][e][n][s][i][o][n].'
+  type: 'system',
+  context: 'from-sip',
+  exten: '_[x][c][a][l][l][y][Q][u][e][u][e][E][x][t][e][n][s][i][o][n].'
 }];
 
 function createExtensions(voiceExtensions, applications) {
-    return db.VoiceExtension
-        .bulkCreate(voiceExtensions, {
-            ignoreDuplicates: true,
-            individualHooks: true
-        })
-        .then(function(entities) {
-            for (var i = 0; i < entities.length; i += 1) {
-                if (applications[entities[i].exten]) {
-                    for (var j = 0; j < applications[entities[i].exten].length; j += 1) {
+  return db.VoiceExtension
+    .bulkCreate(voiceExtensions, {
+      ignoreDuplicates: true,
+      individualHooks: true
+    })
+    .then(function(entities) {
+      for (var i = 0; i < entities.length; i += 1) {
+        if (applications[entities[i].exten]) {
+          for (var j = 0; j < applications[entities[i].exten].length; j += 1) {
 
-                        // NOTE: only for outbound route with outboundrouteid
-                        if (applications[entities[i].exten][j].outboundrouteid) {
-                            applications[entities[i].exten][j].appdata = 'outboundrouteid=' + entities[i].id;
-                            delete applications[entities[i].exten][j].outboundrouteid;
-                        }
+            // NOTE: only for outbound route with outboundrouteid
+            if (applications[entities[i].exten][j].outboundrouteid) {
+              applications[entities[i].exten][j].appdata = 'outboundrouteid=' + entities[i].id;
+              delete applications[entities[i].exten][j].outboundrouteid;
+            }
 
-                        applications[entities[i].exten][j] = _.defaults(applications[entities[i].exten][j], {
-                            isApp: false,
-                            appType: 'custom',
-                            type: entities[i].type,
-                            context: entities[i].context,
-                            exten: entities[i].exten,
-                            priority: parseInt(entities[i].priority, 10) + 1 + j,
-                            description: entities[i].description,
-                            VoiceExtensionId: entities[i].id
-                        });
+            applications[entities[i].exten][j] = _.defaults(applications[entities[i].exten][j], {
+              isApp: false,
+              appType: 'custom',
+              type: entities[i].type,
+              context: entities[i].context,
+              exten: entities[i].exten,
+              priority: parseInt(entities[i].priority, 10) + 1 + j,
+              description: entities[i].description,
+              VoiceExtensionId: entities[i].id
+            });
 
-                        db.VoiceExtension.create(applications[entities[i].exten][j]);
-                    }
-                }
+            db.VoiceExtension.create(applications[entities[i].exten][j]);
+          }
+        }
 
-            }
-        })
-        .then(function() {
-            logger.info('Voice Extensions have been created');
-        })
-        .catch(function(err) {
-            logger.error('Can\'t create Voice Extensions', err);
-        });
+      }
+    })
+    .then(function() {
+      logger.info('Voice Extensions have been created');
+    })
+    .catch(function(err) {
+      logger.error('Can\'t create Voice Extensions', err);
+    });
 }
 
 exports.create = function() {
-    createExtensions(voiceExtensions, applications);
+  createExtensions(voiceExtensions, applications);
 };
 
 exports.createAlways = function() {
-    return db.VoiceExtension
-        .destroy({
-            where: {
-                $or : voiceExtensionsAlways
-            }
-        })
-        .then(function() {
-            createExtensions(voiceExtensionsAlways, applicationsAlways);
-        })
-        .catch(function(err) {
-            logger.error('Can\'t create Voice Extensions', err);
-        });
-};
+  return db.VoiceExtension
+    .destroy({
+      where: {
+        $or: voiceExtensionsAlways
+      }
+    })
+    .then(function() {
+      createExtensions(voiceExtensionsAlways, applicationsAlways);
+    })
+    .catch(function(err) {
+      logger.error('Can\'t create Voice Extensions', err);
+    });
+};
\ No newline at end of file