Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
vendors:cisco:uc:ece:interactive-api-scripts [2024/05/28 09:20] – removed - external edit (Unknown date) 127.0.0.1vendors:cisco:uc:ece:interactive-api-scripts [2024/06/05 16:06] (current) – [ECE Purge Attachments by Queue ID and day range] gerardorourke
Line 1: Line 1:
 +====== ECE Interactive API ======
 +
 +===== Retrieve Activities for Date X ======
 +note - this is a draft version - and currently doesn't loop through the pages / pagination.
 +So this needs to be done!
 +
 +<code python>
 +# Author Gerry O'Rourke
 +# Date: 29/03/2023
 +# Version: 0.10
 +
 +import datetime
 +import requests # used for http requests
 +import sys # used for sys.exit
 +import urllib3 # 
 +urllib3.disable_warnings() #Surpress cert warnings
 +import json
 +import os #check / creating folders
 +import argparse
 +
 +eceUsername = 'eceapi_agent_tst'
 +ecePassword = '12345'
 +eceHost = 'ecewebserver.mydomain.com'
 +rootFolder = 'C:/ECE-Export-Activities/LAB/'
 +
 +
 +def getArguments():
 +  global myDate
 +  parser = argparse.ArgumentParser()
 +  parser.add_argument('-d', '--date',
 +                      type=lambda d: datetime.datetime.strptime(d, '%Y-%m-%d').date(),
 +                      help='Set a start date')
 +  parser.parse_args(["-d", "2023-01-01"])
 +  args = parser.parse_args()
 +  if args.date:
 +    myDate = (args.date)
 +    print('From Date set using arguments. From Date set to: ' + myDate.strftime('%Y-%m-%d'))
 +  else:
 +    myDate = datetime.date.today() - datetime.timedelta(days=1)
 +    print('No date argument set. From Date set to yesterday: ' + myDate.strftime('%Y-%m-%d'))
 +
 +
 +def loginEce():
 +  #Attempt to Login
 +  loginUrl = 'https://' + eceHost + '/system/ws/v12/authentication/user/login?forceLogin=yes'
 +  loginUser='{"userName":"' + eceUsername + '","password":"' + ecePassword + '"}'
 +  loginHeaders={"Content-Type":"application/json"}
 +  print('Attemping to login...')
 +  response = requests.post(url=loginUrl,verify=False, headers=loginHeaders, data=loginUser)
 +
 +  #Store Response Values
 +  responseHeaders = (response.headers)
 +  responseStatusCode = (response.status_code)
 +  responseBody = (response.text)
 +
 +  if (responseStatusCode == 204):
 +    #Get the X-egain-session Header value returned after successful (204) login.
 +    responseToken = (responseHeaders['X-egain-session'])
 +  
 +    #ECE defaults to returning XML unless you set the Accept header to application/json
 +    #Here we are also setting the X-egain-session header (which we got when we logged in), which is needed for all requests.
 +    #Note the user we logged in - must have the correct roles for the specific API calls
 + #we create a global variable here - so we can use it in other functions.
 +    global eceHeaders
 +    eceHeaders={"Accept":"application/json","X-egain-session":responseToken} 
 +    print ('Login Successful!, X-egain-session value is: ',responseToken)
 +  else:
 +    print ('Login Failed!, Status Code: ',responseStatusCode)
 +    sys.exit(1)
 +  
 +
 +def logoutEce():
 +  logoutUrl = 'https://' + eceHost + '/system/ws/v12/authentication/user/logout'
 +  response = requests.delete(url=logoutUrl,verify=False, headers=eceHeaders)
 +  #Store Response Values
 +  responseStatusCode = (response.status_code)
 +  responseText = response.text
 +  if (responseStatusCode == 204):
 +    print ('Logged out successfully.')
 +  else:
 +    print('Failed to logout successfully. This is what was returned: ' + response.text)
 +
 +
 +def listActivities(fromDate):
 +  toDate =  fromDate + datetime.timedelta(days=1)
 +  fromDateString = (fromDate.strftime('%Y-%m-%d'))
 +  toDateString = (toDate.strftime('%Y-%m-%d'))
 +
 +  listActivitiesUrl = 'https://' + eceHost + '/system/ws/v12/interaction/activity?lastModifiedDate=[' + fromDateString + 'T00:00:00.000Z,' + toDateString + 'T00:00:00.000Z]'
 +  #Attempt to get Activity Id
 +  response = requests.get(url=listActivitiesUrl,verify=False, headers=eceHeaders)
 +
 +  #Store Response Values
 +  responseStatusCode = (response.status_code)
 +  responseText = response.text
 +
 +  if (responseStatusCode == 200):
 +    try: 
 +      print('successful Retrieved Json File')
 +      activityDict =  json.loads(responseText)
 +      #print (activityDict.keys())
 +      #activityId_0 = str(activityDict['activity'][0]['id']) #Get activity id[0]
 +      #print(activityId_0)
 +      myFolder = rootFolder + fromDate.strftime('%Y%m%d')
 +      # Check whether the specified path exists or not
 +      isExist = os.path.exists(myFolder)
 +      if not isExist:
 +      # Create a new directory because it does not exist
 +        os.makedirs(myFolder)
 +        print('The new directory: "' + myFolder + '" is created.')
 +      fileName = 'activities_' + fromDate.strftime('%Y%m%d') + '.json'
 +      filePath = myFolder + '/' + fileName
 +      #Save the activity as a text file
 +      text_file = open(filePath, "w", encoding="utf-8")
 +      text_file.write(responseText)
 +      text_file.close()
 +      print('File: ' + filePath + ' written.')
 +      #Loop through the file and get each Activity id
 +      for id in activityDict['activity']:
 + #print(id ['id'])
 +        activityId = str(id ['id'])
 +        getActivity(activityId,fromDate)
 +      print('All activies completed.')
 +    except Exception as e:
 +      print('Error in listActivities Function. error:' + e)
 +      logoutEce()
 +      sys.exit(2)
 +  else:
 +    print('Failed to list Activities for the specified Date.')
 +
 +
 +def getActivity(id,date):
 +  print('Attempting to retrieve Activity Id: ' + id + '...')
 +  activityUrl = 'https://' + eceHost + '/system/ws/v12/interaction/activity/' + id + '?$attribute=all'
 +  #Attempt to get Activity Id
 +  response = requests.get(url=activityUrl,verify=False, headers=eceHeaders)
 +
 +  #Store Response Values
 +  responseStatusCode = (response.status_code)
 +  responseText = response.text
 +
 +  #print (activityDict.keys())
 +  #print (activityDict['activity'][0]['case']['id'])
 +  
 +  if (responseStatusCode == 200):
 +    try: 
 +      activityDict =  json.loads(responseText)
 +      caseId = str(activityDict['activity'][0]['case']['id']) #Get the Case Id
 +      fileName = 'activityId-' + id + '-caseId-' + caseId + '_' + date.strftime('%Y%m%d') + '.json'
 +      myFolder = rootFolder + date.strftime('%Y%m%d')
 +      filePath = myFolder + '/' + fileName
 +      #Check whether the specified path exists or not
 +      isExist = os.path.exists(myFolder)
 +      if not isExist:
 +        # Create a new directory because it does not exist
 +        os.makedirs(myFolder)
 +        print('The new directory: "' + myFolder + '" is created.')
 +
 +      #Save the activity as a text file
 +      text_file = open(filePath, "w", encoding="utf-8")
 +      text_file.write(responseText)
 +      text_file.close()
 +      print ('File: ' + filePath + ' written.')
 +    except Exception as e:
 +      print('Error in getActivity function. error: ' + e)
 +      logoutEce()
 +      sys.exit(2)
 +  else:
 +    print('Failed to retrieve Activity')
 +
 +#get the Command line parameters
 +getArguments()
 +
 +#Login
 +loginEce()
 +
 +#list and retrieve activities for the specific date
 +listActivities(myDate)
 +
 +#Logout
 +logoutEce()
 +</code>
 +
 +
 +===== Masking an activity or deleting attachments from an activity=====
 +
 +  *https://pubhub.devnetcloud.com/media/enterprise-chat-and-email/docs/guides/interaction-api-developer-guide/d3/d8b/class_mask_activity_page.html#interaction-mask-activity-page
 +
 +  *https://pubhub.devnetcloud.com/media/enterprise-chat-and-email/docs/guides/interaction-api-developer-guide/d7/de2/class_edit_completed_activity_examples.html#edit-completed-activity-example3
 +
 +  *https://pubhub.devnetcloud.com/media/enterprise-chat-and-email/docs/guides/interaction-api-developer-guide/de/d80/classadministration_1_1pages_1_1user_1_1_delete_completed_activity_attachments_page.html#interaction-delete-completed-activity-attachments-page
 +
 +===Permissions for Masking an activity===
 +**All of the following are required:**
 +
 +  *User must have 'Edit' action on 'Activity' resource or 'Manage Utilities' action on 'Utilities' resource.
 +  *The activity must either belong to the user's home department, or to a department in which the user is a foreign user.
 +
 +In PCCE - the above permissions are added to the specific user the following: ECE → User → Relationships:
 +  *Manage Completed Activity
 +
 +==== Example Code to Mask or delete an attachment in an ECE Activity ====
 +<code python>
 +# Author Gerry O'Rourke
 +# Date: 06/09/2023
 +# Version: 2.0
 +
 +import requests  # used for http requests
 +import sys  # used for sys.exit
 +import urllib3  #
 +
 +urllib3.disable_warnings()  # Surpress cert warnings
 +import json
 +import os  # check / creating folders
 +import time
 +
 +eceUsername = 'eceapi_agent_tst'
 +ecePassword = 'BaNaNa5!'
 +eceHost = 'ece-webserver.mydomain.com'
 +
 +def loginEce():
 +    # Attempt to Login
 +    loginUrl = 'https://' + eceHost + '/system/ws/v12/authentication/user/login?forceLogin=yes'
 +    loginUser = '{"userName":"' + eceUsername + '","password":"' + ecePassword + '"}'
 +    loginHeaders = {"Content-Type": "application/json"}
 +    print('Attemping to login...')
 +    response = requests.post(url=loginUrl, verify=False, headers=loginHeaders, data=loginUser)
 +
 +    # Store Response Values
 +    responseHeaders = (response.headers)
 +    responseStatusCode = (response.status_code)
 +    responseBody = (response.text)
 +
 +    if (responseStatusCode == 204):
 +        # Get the X-egain-session Header value returned after successful (204) login.
 +        global responseToken
 +        responseToken = (responseHeaders['X-egain-session'])
 +
 +        # ECE defaults to returning XML unless you set the Accept header to application/json
 +        # Here we are also setting the X-egain-session header (which we got when we logged in), which is needed for all requests.
 +        # Note the user we logged in - must have the correct roles for the specific API calls
 +        # we create a global variable here - so we can use it in other functions.
 +        global eceHeaders
 +        eceHeaders = {"Accept": "application/json", "X-egain-session": responseToken}
 +        print('Login Successful!, X-egain-session value is: ', responseToken)
 +    else:
 +        print('Login Failed!, Status Code: ', responseStatusCode)
 +        sys.exit(1)
 +
 +
 +def logoutEce():
 +    logoutUrl = 'https://' + eceHost + '/system/ws/v12/authentication/user/logout'
 +    response = requests.delete(url=logoutUrl, verify=False, headers=eceHeaders)
 +    # Store Response Values
 +    responseStatusCode = (response.status_code)
 +    responseText = response.text
 +    if (responseStatusCode == 204):
 +        print('Logged out successfully.')
 +    else:
 +        print('Failed to logout successfully. This is what was returned: ' + response.text)
 +
 +
 +def getActivity(id):
 +    global caseId
 +    global lastModifiedDate
 +    global activityAttachmentsCount
 +    print('Attempting to retrieve Activity Id: ' + id + '.')
 +    activityUrl = 'https://' + eceHost + '/system/ws/v12/interaction/activity/' + id
 +    # Attempt to get Activity Id
 +    response = requests.get(url=activityUrl, verify=False, headers=eceHeaders)
 +
 +    # Store Response Values
 +    responseStatusCode = (response.status_code)
 +    responseText = response.text
 +
 +    if (responseStatusCode == 200):
 +        try:
 +            activityDict = json.loads(responseText)
 +            caseId = str(activityDict['activity'][0]['case']['id'])  # Get the Case Id
 +            # print('CaseID: ' + caseId)
 +            lastModifiedDate = str(activityDict['activity'][0]['lastModified']['date'])  # Get the lastModified date
 +            # print('Last Modified Date: ' + lastModifiedDate)
 +            activityAttachmentsCount = str(activityDict['activity'][0]['attachments']['count'])  # Get the Case Id
 +            # print('Activity Attachments Count: ' + activityAttachmentsCount)
 +            #maskActivity(id, lastModifiedDate)
 +
 +        except Exception as e:
 +            print('Error in getActivity function. error: ' + e)
 +            logoutEce()
 +            sys.exit(2)
 +
 +    else:
 +        print('Failed to retrieve Activity')
 +
 +
 +def maskActivity(id, date):
 +    maskActivityUrl = 'https://' + eceHost + '/system/ws/v12/interaction/activity'
 +    maskActivityHeaders = {"Content-Type": "application/xml", "X-egain-session": responseToken}
 +    maskActivityBody = '<?xml version="1.0" encoding="UTF-8"?><activities xmlns="http://bindings.egain.com/ws/model/v12/gen/interaction/activity" xmlns:ns2="http://bindings.egain.com/ws/model/v12/gen/common"><activity id="' + id + '"><lastModified date="' + date + '" /><payload><email><contents><content><ns2:type>html</ns2:type><ns2:value>&lt;b&gt;Contents are removed.&lt;/b&gt;</ns2:value></content></contents></email></payload></activity></activities>'
 +
 +    print('Attempting to Mask Activity Id: ' + id + '.')
 +    response = requests.put(url=maskActivityUrl, verify=False, headers=maskActivityHeaders, data=maskActivityBody)
 +
 +    # Store Response Values
 +    responseHeaders = (response.headers)
 +    responseStatusCode = (response.status_code)
 +    responseBody = (response.text)
 +
 +    if (responseStatusCode == 204):
 +        print('Successfully Masked Activity ID: ' + id)
 +        confirm = input('\nDo you want to Review another Activity ID?. Enter "y" to confirm? ')
 +        if (confirm == 'y' or confirm == 'Y'):
 +            enterActivityId()
 +        else:
 +            print('Exiting now...')
 +            logoutEce()
 +
 +    else:
 +        print('----- ERROR, Unable to Mask Activity -----')
 +        print('Status Code: ' + str(responseStatusCode))
 +        print('Response Body: ' + responseBody)
 +        logoutEce()
 +
 +
 +def deleteAttachments(id):
 +    deleteAttachmentsUrl = 'https://' + eceHost + '/system/ws/v12/interaction/activity/' +id + '/attachment'
 +    deleteAttachmentsHeaders = {"X-egain-session": responseToken}
 +
 +    print('Attempting to delete ALL attachments from Activity Id: ' + id + '.')
 +    response = requests.delete(url=deleteAttachmentsUrl, verify=False, headers=deleteAttachmentsHeaders)
 +
 +    # Store Response Values
 +    responseHeaders = (response.headers)
 +    responseStatusCode = (response.status_code)
 +    responseBody = (response.text)
 +
 +    if (responseStatusCode == 204):
 +        print('Successfully Deleted Attachments from Activity ID: ' + id)
 +        confirm = input('\nDo you want to review another Activity ID?. Enter "y" to confirm? ')
 +        if (confirm == 'y' or confirm == 'Y'):
 +            enterActivityId()
 +        else:
 +            print('Exiting now...')
 +            logoutEce()
 +
 +    else:
 +        print('----- ERROR, Unable to Delete Attachments -----')
 +        print('Status Code: ' + str(responseStatusCode))
 +        print('Response Body: ' + responseBody)
 +        logoutEce()
 +
 +
 +def enterActivityId():
 +    global activityId
 +    activityId = input('\nEnter your Activity Id or enter "exit": ')
 +    if (activityId == 'exit'):
 +        print('exiting...')
 +        logoutEce()
 +    elif (activityId.isnumeric()):
 +        getActivity(str(activityId))
 +        print('Retrieved the Activity ID successfully.')
 +        print('\nActivity ID: ' + activityId)
 +        print('Case ID:' + caseId)
 +        print('Attachment Count:' + activityAttachmentsCount)
 +        if (int(activityAttachmentsCount)>0):
 +            print('This activity has one or more attachments!')
 +            print('----------------------')
 +            print('1. Mask Activity')
 +            print('2. Delete Attachments')
 +            print('9. Exit')
 +            print('----------------------')
 +            confirm = input('\nEnter Menu option [1], [2] or [9]?')
 +            if (confirm == '1'):
 +                maskActivity(activityId, lastModifiedDate)
 +            elif (confirm == '2'):
 +                 deleteAttachments(activityId)
 +            else:
 +                    logoutEce()
 +        else:
 +            print('This activity has NO attachments!')
 +            print('----------------------')
 +            print('1. Mask Activity')
 +            print('9. Exit')
 +            print('----------------------')
 +            confirm = input('\nEnter Menu option [1] or [9]?')
 +            if (confirm == '1'):
 +                maskActivity(activityId, lastModifiedDate)
 +            else:
 +                    logoutEce()
 +    else:
 +        print('Entered Activity ID is not a number or the word "exit".')
 +        print('Please try again.')
 +        time.sleep(2)
 +        enterActivityId()
 +
 +os.system('cls')
 +print('****** WARNING - Masking an activity is not reversable! ******')
 +print('Proceed with caution !!!')
 +print('\n')
 +
 +# Login
 +loginEce()
 +
 +# Enter the Activity Id to Mask
 +enterActivityId()
 +</code>
 +
 +==== Sample output of the above script ====
 +{{:vendors:cisco:uc:ece:ece-mask-or-delete-attachements.png?600|}}
 +
 +
 +===== Backup (draft version) of script to purge attachments =====
 +
 +<code python>
 +# Author Gerry O'Rourke
 +# Date: 07/09/2023
 +# Version: 0.10
 +
 +import datetime
 +import requests # used for http requests
 +import sys # used for sys.exit
 +import urllib3 # 
 +urllib3.disable_warnings() #Surpress cert warnings
 +import json
 +import os #check / creating folders
 +import argparse
 +
 +eceUsername = 'eirsupport1'
 +ecePassword = 'Pa$$w0rd
 +eceHost = 'ece-webserver.mydomain.com'
 +rootFolder = 'C:/eirScripts/ECE-Purge-Activities-Attachments-by-Queue/LAB/'
 +activityIdsSearched = []
 +activityIdsWithAttachments = []
 +
 +def getArguments():
 +  global endDate
 +  global startDate
 +  global silentMode
 +  global queueIds
 +  parser = argparse.ArgumentParser()
 +  parser.add_argument('-d', '--days', type=int, help='sets the end date, e.g. -d 180, sets the end dat as 180 days ago')
 +  parser.add_argument('-r', '--dayrange', type=int, default=1, help='by default we only purge a single day, the if we '
 +                                                                    'want to purge more, enter day range')
 +  parser.add_argument('-s', '--silent', action='store_true')
 +  parser.add_argument('-q', '--queue', action='append', help='Queue IDs, for multiple queue ID enter -q before each one')
 +
 +  args = parser.parse_args()
 +  if args.days:
 +    #days = (args.days)
 +    endDate = datetime.date.today() - datetime.timedelta(days=args.days)
 +    print('End Date set to: ' + endDate.strftime('%Y-%m-%d'))
 +  elif args.days == 0:
 +    endDate = datetime.date.today()
 +    print('End Date set to: ' + endDate.strftime('%Y-%m-%d'))
 +  else:
 +    print('No date argument set. Enter the number of days from today, e.g. "-d 180", would purge data from 180 days '
 +          'ago.')
 +    exit(1)
 +
 +  if args.dayrange:
 +    startDate = endDate - datetime.timedelta(days=args.dayrange)
 +    print('Start Date set to: ' + startDate.strftime('%Y-%m-%d'))
 +
 +  if args.silent:
 +    print('Silent Mode set - the application will not prompt for input to continue')
 +    silentMode = true
 +  else:
 +    print('Silent Mode NOT set - do NOT use this mode if running as a scheduled task.')
 +
 +  if args.queue:
 +    queueIds = args.queue
 +    print('Queue ID list: ' + str(queueIds))
 +  else:
 +    print('No queue data set. This app could be used to purge all activities for a date range but that is too risky! '
 +          'Hence you must enter at least 1 queue you want to purge using the argument "-q".')
 +    exit(1)
 +
 +def loginEce():
 +  #Attempt to Login
 +  loginUrl = 'https://' + eceHost + '/system/ws/v12/authentication/user/login?forceLogin=yes'
 +  loginUser='{"userName":"' + eceUsername + '","password":"' + ecePassword + '"}'
 +  loginHeaders={"Content-Type":"application/json"}
 +  print('Attemping to login...')
 +  response = requests.post(url=loginUrl,verify=False, headers=loginHeaders, data=loginUser)
 +
 +  #Store Response Values
 +  responseHeaders = (response.headers)
 +  responseStatusCode = (response.status_code)
 +  responseBody = (response.text)
 +
 +  if (responseStatusCode == 204):
 +    #Get the X-egain-session Header value returned after successful (204) login.
 +    responseToken = (responseHeaders['X-egain-session'])
 +    global eceHeaders
 +    eceHeaders={"Accept":"application/json","X-egain-session":responseToken} 
 +    print ('Login Successful!, X-egain-session value is: ',responseToken)
 +  else:
 +    print ('Login Failed!, Status Code: ' + str(responseStatusCode))
 +    sys.exit(1)
 +
 +def logoutEce():
 +  logoutUrl = 'https://' + eceHost + '/system/ws/v12/authentication/user/logout'
 +  response = requests.delete(url=logoutUrl,verify=False, headers=eceHeaders)
 +  #Store Response Values
 +  responseStatusCode = (response.status_code)
 +  responseText = response.text
 +  if (responseStatusCode == 204):
 +    print ('Logged out successfully.')
 +  else:
 +    print('Logout Failed!, Status Code: ' + str(responseStatusCode))
 +    print('Error Response: ' + response.text)
 +
 +def listActivities(startDate,endDate,pageNum):
 +  global activityIdsSearched
 +  global activityIdsWithAttachments
 +  global activityCount
 +  global currentPageNum
 +  global pageSize
 +  startDateString = (startDate.strftime('%Y-%m-%d'))
 +  endDateString = (endDate.strftime('%Y-%m-%d'))
 +  currentPageNum = pageNum
 +  listActivitiesUrl = 'https://' + eceHost + '/system/ws/v12/interaction/activity?$pagenum=' + str(currentPageNum) + '&lastModifiedDate=[' + startDateString + 'T00:00:00.000Z,' + endDateString + 'T00:00:00.000Z]'
 +  print('listActivitiesUrl: ' + listActivitiesUrl)
 +
 +  #Attempt to Retrieve List of Activities
 +  response = requests.get(url=listActivitiesUrl,verify=False, headers=eceHeaders)
 +  responseStatusCode = (response.status_code)
 +  responseText = response.text
 +
 +  if (responseStatusCode == 200):
 +    try: 
 +      activityDict =  json.loads(responseText)
 +      activityCount = activityDict['paginationInfo']['count']
 +      #currentPageNum = activityDict['paginationInfo']['pagenum']
 +      pageSize = activityDict['paginationInfo']['pagesize']
 +      #Loop through the file and get each Activity id
 +      for id in activityDict['activity']:
 +        activityId = str(id ['id']) #get the Activity ID
 +        activityIdsSearched.append(activityId)
 +        activityAttachmentsCount = activityDict['activity'][0]['attachments']['count' # Get the Attachments Count
 +        if (activityAttachmentsCount > 0):
 +          activityIdsWithAttachments.append(activityId)
 +    except Exception as e:
 +      print('Error in listActivities Function. error:' + e)
 +      logoutEce()
 +      sys.exit(2)
 +  elif (currentPageNum == 1 and responseStatusCode == 204):
 +    print('No Activities Content for that date range')
 +  elif (responseStatusCode == 204):
 +    print('completed search.')
 +  else:
 +    print('Error - Failed to list Activities, response code: ' + str(responseStatusCode))
 +    logoutEce()
 +    sys.exit(2)
 +
 +#get the Command line parameters
 +getArguments()
 +loginEce()
 +listActivities(startDate, endDate,1)
 +print('Activity Count: ' + str(activityCount))
 +print('PageSize: ' + str(pageSize))
 +print('Current Page Num: ', currentPageNum)
 +
 +while ((currentPageNum * pageSize) < activityCount):
 +  currentPageNum += 1
 +  print('Current Page Num: ', currentPageNum)
 +  listActivities(startDate, endDate, currentPageNum)
 +
 +print('Number of Activities Scanned: ', len(activityIdsSearched))
 +print('Number of Activity IDs with attachments: ', len(activityIdsWithAttachments))
 +#print('Activity Ids Searched: ' + str(activityIdsSearched))
 +#print('Activity Ids with attachments: ' + str(activityIdsWithAttachments))
 +
 +#Login
 +#loginEce()
 +
 +#list and retrieve activities for the specific date
 +
 +#Logout
 +logoutEce()
 +</code>
 +
 +=====ECE Purge Attachments by Queue ID and day range=====
 +
 +<code python>
 +# Author Gerry O'Rourke
 +# Date: 14/09/2023
 +# Version: 1.0
 +
 +#import datetime
 +from datetime import datetime
 +from datetime import date
 +from datetime import timedelta
 +import requests # used for http requests
 +import sys # used for sys.exit and standard output
 +import urllib3 # 
 +urllib3.disable_warnings() #Surpress cert warnings
 +import json
 +import os #check / creating folders
 +import argparse
 +import logging
 +from logging.handlers import RotatingFileHandler
 +import smtplib
 +from email.mime.text import MIMEText
 +
 +#loglevel = logging.INFO
 +loglevel = logging.DEBUG
 +logging.basicConfig(handlers=[logging.StreamHandler(sys.stdout),
 +                    RotatingFileHandler('ece-purge-attachments.log', maxBytes=100000, backupCount=10)],
 +                    style='{',
 +                    format='{asctime} - {levelname:8s} - {message}',
 +                    level=loglevel)
 +eceUsername = 'eceapi_user'
 +ecePassword = 'Pa$$w0rd'
 +eceHost = 'ece-webserver.mydomain.com'
 +environment = 'LAB' # Do not have any spaces - set to 'LAB' or 'PROD'
 +rootFolder = 'C:/eirScripts/ECE-Purge-Activities-Attachments-by-Queue/LAB/'
 +activityIdsSearched = []
 +activityIdsWithAttachments = []
 +deletedActivityIds = []
 +errorCounter = 0
 +errorMessage = ''
 +startTime = datetime.now()
 +
 +message = ('---------- Starting! ----------')
 +logging.info(message)
 +message = ('startTime: ' + startTime.strftime("%d/%m/%Y %H:%M:%S"))
 +logging.info(message)
 +message = ('Arguments supplied: ' + str(sys.argv))
 +logging.info(message)
 +
 +def getArguments():
 +  global endDate
 +  global startDate
 +  global silentMode
 +  global queueIds
 +  global writeAccess
 +  global email
 +  global errorCounter
 +  global errorMessage
 +
 +  parser = argparse.ArgumentParser()
 +  parser.add_argument('-d', '--days', type=int, help='sets the end date, e.g. -d 180, sets the end dat as 180 days ago')
 +  parser.add_argument('-r', '--dayrange', type=int, default=1, help='by default we only purge a single day, the if we '
 +                                                                    'want to purge more, enter day range')
 +  parser.add_argument('-s', '--silent', action='store_true')
 +  parser.add_argument('-q', '--queue', action='append', help='Queue IDs, for multiple queue ID enter -q before each one')
 +  parser.add_argument('-w', '--write', action='store_true', help='Write Access. Write access must be set if you want to delete attachments')
 +  parser.add_argument('-e', '--email', action='store_true', help='Send an email at the end of the script to a summary')
 +
 +  args = parser.parse_args()
 +  if args.days:
 +    endDate = date.today() - timedelta(days=args.days)
 +    message = ('End Date set to: ' + endDate.strftime('%Y-%m-%d') + 'T23:59:59')
 +    logging.info(message)
 +  elif args.days == 0:
 +    endDate = date.today()
 +    message = ('End Date set to: ' + endDate.strftime('%Y-%m-%d')+ 'T23:59:59')
 +    logging.info(message)
 +  else:
 +    message = ('No date argument set. Enter the number of days from today, e.g. "-d 180", would purge data from 180 '
 +               'days ago.')
 +    logging.error(message)
 +    errorCounter = errorCounter + 1
 +    errorMessage = 'Arguments not set correctly - please check log file for more information.'
 +    sendEmail()
 +    exit(1)
 +
 +  if args.dayrange:
 +    startDate = endDate - timedelta(days=(args.dayrange-1))
 +    message = ('Start Date set to: ' + startDate.strftime('%Y-%m-%d') + 'T00:00:00')
 +    logging.info(message)
 +
 +  if args.silent:
 +    message = ('Silent Mode set - the application will not prompt for input to continue')
 +    logging.info(message)
 +    silentMode = True
 +  else:
 +    message = ('Silent Mode NOT set - do NOT use this mode if running as a scheduled task.')
 +    logging.info(message)
 +    silentMode = False
 +
 +  if args.write:
 +    message = ('Write mode enabled - the application will delete found attachements.')
 +    logging.info(message)
 +    writeAccess = True
 +  else:
 +    message = ('Read Only mode set - the application will NOT delete attachments.')
 +    logging.info(message)
 +    writeAccess = False
 +
 +  if args.email:
 +    message = ('email mode enabled - the application should send an email when completed.')
 +    logging.info(message)
 +    email = True
 +  else:
 +    message = ('email mode is NOT enabled - the application will NOT send an email when completed.')
 +    logging.info(message)
 +    email = False
 +
 +  if args.queue:
 +    queueIds = args.queue
 +    message = ('Queue ID list: ' + str(queueIds))
 +    logging.info(message)
 +  else:
 +    message = ('No queue data set. This app COULD (if we wanted to!) be used to purge all activities for a date range but that is too risky! '
 +          'Hence you must enter at least 1 queue you want to purge using the argument "-q".')
 +    logging.info(message)
 +    errorCounter = errorCounter + 1
 +    errorMessage = 'Arguments not set correctly - please check log file for more information.'
 +    exit(1)
 +
 +def loginEce():
 +  global errorCounter
 +  global errorMessage
 +  loginUrl = 'https://' + eceHost + '/system/ws/v12/authentication/user/login?forceLogin=yes'
 +  loginUser='{"userName":"' + eceUsername + '","password":"' + ecePassword + '"}'
 +  loginHeaders={"Content-Type":"application/json"}
 +  message = ('Attemping to login...')
 +  logging.info(message)
 +
 +  responseStatusCode = 0
 +  try:
 +    response = requests.post(url=loginUrl,verify=False, headers=loginHeaders, data=loginUser, timeout=5)
 +    responseHeaders = (response.headers)
 +    responseStatusCode = (response.status_code)
 +  except:
 +    message = ('Issue Calling Login URL.')
 +    logging.error(message)
 +
 +  if (responseStatusCode == 204):
 +    #Get the X-egain-session Header value returned after successful (204) login.
 +    global responseToken
 +    responseToken = (responseHeaders['X-egain-session'])
 +    global eceHeaders
 +    eceHeaders={"Accept":"application/json","X-egain-session":responseToken}
 +    message = ('Login Successful!, X-egain-session value is: ' + str(responseToken))
 +    logging.info(message)
 +  else:
 +    message = ('Login Failed!, Status Code: ' + str(responseStatusCode))
 +    logging.error(message)
 +    errorCounter = errorCounter + 1
 +    errorMessage = 'Failed to log into ECE successfully. Please check log file for more information.'
 +    sendEmail()
 +    sys.exit(1)
 +
 +def logoutEce():
 +  logoutUrl = 'https://' + eceHost + '/system/ws/v12/authentication/user/logout'
 +  responseStatusCode = 0
 +  try:
 +    response = requests.delete(url=logoutUrl,verify=False, headers=eceHeaders)
 +    responseStatusCode = (response.status_code)
 +    responseText = response.text
 +  except:
 +    message = ('Issue Calling Logout URL.')
 +    logging.error(message)
 +
 +  if (responseStatusCode == 204):
 +    message = ('Logged out successfully.')
 +    logging.info(message)
 +  else:
 +    message = ('Logout Failed!, Status Code: ' + str(responseStatusCode) + '\nError Response: ' + response.text)
 +    logging.error(message)
 +
 +def listActivities(startDate,endDate,pageNum,queueId):
 +  global activityIdsSearched
 +  global activityIdsWithAttachments
 +  global activityCount
 +  global currentPageNum
 +  global pageSize
 +  global retrievedData
 +  global errorCounter
 +
 +  startDateString = (startDate.strftime('%Y-%m-%d'))
 +  endDateString = (endDate.strftime('%Y-%m-%d'))
 +  currentPageNum = pageNum
 +  retrievedData = False
 +  listActivitiesUrl = 'https://' + eceHost + '/system/ws/v12/interaction/activity?type=email&queue=' + str(queueId) + '&$pagenum=' + str(currentPageNum) + '&lastModifiedDate=[' + startDateString + 'T00:00:00.000Z,' + endDateString + 'T23:59:59.999Z]'
 +  message = ('listActivitiesUrl: ' + listActivitiesUrl)
 +  logging.debug(message)
 +
 +  #Attempt to Retrieve List of Activities
 +  responseStatusCode = 0
 +  try:
 +    response = requests.get(url=listActivitiesUrl, verify=False, headers=eceHeaders, timeout=5)
 +    responseStatusCode = (response.status_code)
 +    responseText = response.text
 +  except:
 +    message = ('Issue Calling List Activity URL.')
 +    logging.error(message)
 +
 +  if (responseStatusCode == 200):
 +    try: 
 +      activityDict =  json.loads(responseText)
 +      activityCount = activityDict['paginationInfo']['count']
 +      #currentPageNum = activityDict['paginationInfo']['pagenum']
 +      pageSize = activityDict['paginationInfo']['pagesize']
 +      #Loop through the file and get each Activity id
 +      for id in activityDict['activity']:
 +        activityId = str(id ['id']) #get the Activity ID
 +        #print('activityId: ',activityId)
 +        activityIdsSearched.append(activityId)
 +        activityAttachmentsCount = id['attachments']['count' # Get the Attachments Count
 +        #print('activityAttachmentsCount: ', activityAttachmentsCount)
 +        if (activityAttachmentsCount > 0):
 +          activityIdsWithAttachments.append(activityId)
 +        retrievedData = True
 +    except Exception as e:
 +      message = ('Error in listActivities Function. error:' + str(e))
 +      logging.error(message)
 +      errorCounter = errorCounter + 1
 +  elif (currentPageNum == 1 and responseStatusCode == 204):
 +    message = ('No Activities Content for that date range')
 +    logging.info(message)
 +  elif (responseStatusCode == 204):
 +    message = ('Completed search.')
 +    logging.info(message)
 +  else:
 +    message = ('Failed to list Activities, statusCode: ' + str(responseStatusCode))
 +    logging.error(message)
 +    errorCounter = errorCounter + 1
 +
 +def deleteAttachments(id):
 +  deleteAttachmentsUrl = 'https://' + eceHost + '/system/ws/v12/interaction/activity/' + id + '/attachment'
 +  deleteAttachmentsHeaders = {"X-egain-session": responseToken}
 +  message=('Attempting to delete ALL attachments from Activity Id: ' + id + '.')
 +  logging.info(message)
 +
 +  responseStatusCode = 0
 +  try:
 +    response = requests.delete(url=deleteAttachmentsUrl, verify=False, headers=deleteAttachmentsHeaders)
 +    responseStatusCode = (response.status_code)
 +    responseBody = (response.text)
 +  except:
 +    message = ('Issue Calling Delete attachment URL.')
 +    logging.error(message)
 +    errorCounter = errorCounter + 1
 +
 +  if (responseStatusCode == 204):
 +    deletedActivityIds.append(activityId)
 +    message('Successfully Deleted Attachments from Activity ID: ' + id)
 +    logging.info(message)
 +  else:
 +    message = ('Unable to Delete Attachments, Status Code: ' + str(responseStatusCode) + ', Response Body: ' + responseBody)
 +    logging.error(message)
 +    errorCounter = errorCounter + 1
 +
 +def sendEmail():
 +  global activityIdsWithAttachments
 +  global activityIdsSearched
 +  global deletedActivityIds
 +  global errorCounter
 +  global errorMessage
 +  global environment
 +  global startTime
 +  global email
 +  global writeAccess
 +  global queueIds
 +  global endDate
 +  global startDate
 +
 +  if writeAccess==True:
 +    mode = 'Write Mode Enabled - will attempt to delete attachments'
 +  else:
 +    mode = 'Write Mode Disabled - will NOT attempt to delete attachments'
 +
 +  if (email==False):
 +    message = ('Not sending email as email argument not enmabled')
 +    logging.info(message)
 +    return #don't continue if email is not enabled.
 +
 +  endTime = datetime.now()
 +  message = ('Sending email now...')
 +  logging.info(message)
 +
 +  s = smtplib.SMTP('exchsmtphost2013.cld1.tld.int')
 +  sender = environment + '[email protected]'
 +  recipients = ['[email protected]', '[email protected]']
 +
 +  msg = MIMEText('\n\n--------------------------------------------------------------------'
 +        '\nEnvironment: ' + environment + ''
 +        '\nMode: ' + mode + ''
 +        '\nScript Start Time: ' + startTime.strftime("%d/%m/%Y %H:%M:%S") + '' 
 +        '\nScript End Time: ' + endTime.strftime("%d/%m/%Y %H:%M:%S") + ''
 +        '\nError Count: ' + str(errorCounter) + ''
 +        '\nError Message: ' + errorMessage + ''
 +        '\n--------------------------------------------------------------------'
 +        '\n\n--------------------------------------------------------------------'
 +        '\nQueue ID list: ' + str(queueIds) + ''
 +        '\nStart Date: ' + startDate.strftime('%Y-%m-%d') + 'T00:00:00'
 +        '\nEnd Date: ' + endDate.strftime('%Y-%m-%d') + 'T23:59:59'
 +        '\nNumber of Activities Scanned: ' + str(len(activityIdsSearched)) + ''
 +        '\nActivity Id Attachments Count: ' + str(len(activityIdsWithAttachments)) + ''
 +        '\nDeleted Activity Id Count: ' + str(len(deletedActivityIds)) + ''
 +        '\n--------------------------------------------------------------------\n\n\n\n')
 +  msg['Subject'] = environment + ' - ECE - Delete Attachment Script'
 +  msg['From'] = sender
 +  msg['To'] = ", ".join(recipients)
 +
 +  s.sendmail(sender, recipients, msg.as_string())
 +  s.quit()
 +
 +#get the Command line parameters
 +getArguments()
 +
 +#Login
 +loginEce()
 +
 +#Loop through queues provided
 +for queueId in queueIds:
 +  message = ('QueueId: ' + str(queueId))
 +  logging.info(message)
 +  listActivities(startDate, endDate,1,queueId)
 +  if (retrievedData):
 +    message = ('Activity Count: ' + str(activityCount))
 +    logging.info(message)
 +    message = ('PageSize: ' + str(pageSize))
 +    logging.info(message)
 +    message = ('Current Page Num: ' + str(currentPageNum))
 +    logging.info(message)
 +
 +    while ((currentPageNum * pageSize) < activityCount):
 +      currentPageNum += 1
 +      message = ('Current Page Num: ' + str(currentPageNum))
 +      logging.info(message)
 +      listActivities(startDate, endDate, currentPageNum,queueId)
 +
 +#print('Activity Ids Searched: ' + str(activityIdsSearched))
 +message = ('Activity Ids with attachments: ' + str(activityIdsWithAttachments))
 +logging.info(message)
 +message = ('Number of Activities Scanned: ' + str(len(activityIdsSearched)))
 +logging.info(message)
 +message = ('Number of Activity IDs with attachments: ' + str(len(activityIdsWithAttachments)))
 +logging.info(message)
 +
 +if (len(activityIdsWithAttachments)>0 and writeAccess and (silentMode==False)):
 +  confirm = input('\nAre you sure you want to delete these attachments?')
 +  if (confirm == 'y' or confirm == 'Y'):
 +    for activityIdWithAttachment in activityIdsWithAttachments:
 +      deleteAttachments(activityIdWithAttachment)
 +
 +if (len(activityIdsWithAttachments)>0 and writeAccess and (silentMode==True)):
 +  for activityIdWithAttachment in activityIdsWithAttachments:
 +    deleteAttachments(activityIdWithAttachment)
 +
 +message = ('Activity IDs Deleted: ' + str(deletedActivityIds))
 +logging.info(message)
 +message = ('Number of Activity IDs Deleted: ' + str(len(deletedActivityIds)))
 +logging.info(message)
 +
 +#Send Email
 +sendEmail()
 +
 +#Logout
 +logoutEce()
 +
 +endTime = datetime.now()
 +message = ('endTime: ' + endTime.strftime("%d/%m/%Y %H:%M:%S"))
 +logging.info(message)
 +message = ('---------- Finished! ----------')
 +logging.info(message)
 +</code>
 +
 +===== Retrieve Activity and Case ID info for Activities in specific Date Range and only for certain Queue IDs =====
 +
 +<code python>
 +# Author Gerry O'Rourke
 +# Date: 05/06/2024
 +# Version: 2.02
 +
 +# Example1
 +# 'ECE-Get-Activities_V2.0.py  -q 1015 -r 10'
 +# This will get Activities for yesterday (-d defaults to 1 and -r default to only get 1 days worth)
 +#
 +# Example2
 +# 'ECE-Get-Activities_V2.0.py  -d 0 -q 1015 -r 10'
 +# Get Activities for Queue ID 1015 from today (-d 0), and go back 10 days. i.e. the last 10 days including today.
 +
 +# Example3 'ECE-Get-Activities_V2.0.py  -d 1 -q 1015 -1 1023 -r 3'
 +# Get Activities for yesterday, the day before yesterday and the day before that, for queues 1015 AND 1023
 +# End date is "-d 1" - i.e. 1 day ago and range (-r) is 3 days   (-d 0)
 +
 +# Note this script should be improved - as the Case ID for each Activity can be retrieved from the Activity Search Response (and there is no need to get the Activity to find the Case ID)
 +
 +import time  # used when pausing script for X milliseconds
 +import json
 +import os  # check / creating folders
 +import argparse
 +import sys  # used for sys.exit and standard output
 +import requests  # used for http requests
 +import urllib3  #
 +from datetime import datetime
 +from datetime import date
 +from datetime import timedelta
 +import logging
 +from logging.handlers import RotatingFileHandler
 +
 +urllib3.disable_warnings()  # Suppress cert warnings
 +
 +# Initial Variables
 +loglevel = logging.DEBUG  # DEBUG, INFO
 +logging.basicConfig(handlers=[logging.StreamHandler(sys.stdout),
 +                              RotatingFileHandler('logs/ece-get-activities.log', maxBytes=10 * 1024 * 1024,
 +                                                  backupCount=10)],
 +                    style='{',
 +                    format='{asctime} - {levelname:8s} - {message}',
 +                    level=loglevel)
 +ece_username = 'my_username'
 +ece_password = 'my_pa$$w0rd'
 +ece_host = 'ece-webserver.mydomain.com'
 +environment = 'PRD'  # Do not have any spaces - set to 'LAB' or 'PROD'
 +delay = 333 / 1000  # Time to pause when retrieving HTTP Request loops - to reduce load on server, e.g. 200/1000 -> 4
 +# API Requests per second, 333/1000 -> 3 API requests per second, 500/100 => 2 API calls per second.
 +rootFolder = 'C:/eceScripts/ECE-Export-Activities/' + environment + '/'
 +activity_ids_searched = []
 +activity_ids_with_attachments = []
 +case_ids = []
 +case_ids_closed = []
 +error_counter = 0
 +error_message = ''
 +startTime = datetime.now()
 +
 +message = ('--------------- Starting! ---------------')
 +logging.info(message)
 +message = ('startTime: ' + startTime.strftime("%d/%m/%Y %H:%M:%S"))
 +logging.info(message)
 +message = ('Arguments supplied: ' + str(sys.argv))
 +logging.info(message)
 +
 +
 +def getArguments():
 +    global endDate
 +    global startDate
 +    global queueIds
 +    global retrieveActivities
 +    global writeActivitiesToFile
 +    global error_counter
 +    global error_message
 +
 +    parser = argparse.ArgumentParser()
 +    parser.add_argument('-d', '--days', type=int,
 +                        help='sets the end date, e.g. -d 180, sets the end dat as 180 days ago')
 +    parser.add_argument('-r', '--dayrange', type=int, default=1, help='by default only a single day')
 +    parser.add_argument('-q', '--queue', action='append',
 +                        help='Queue IDs, for multiple queue ID enter -q before each one')
 +    parser.add_argument('-a', '--activities', action='store_true',
 +                        help='Retrieve the Activities found (need to use this if we want to get Case info)')
 +    parser.add_argument('-w', '--write', action='store_true',
 +                        help='Write Activities out to file')
 +
 +    args = parser.parse_args()
 +    if args.days:
 +        endDate = date.today() - timedelta(days=args.days)
 +        message = ('End Date set to: ' + endDate.strftime('%Y-%m-%d') + 'T23:59:59')
 +        logging.info(message)
 +    elif args.days == 0:
 +        endDate = date.today()
 +        message = ('End Date set to: ' + endDate.strftime('%Y-%m-%d') + 'T23:59:59')
 +        logging.info(message)
 +    else:
 +        message = ('No date argument set. Enter the number of days from today, e.g. "-d 1", would be 1 day ago.')
 +        logging.error(message)
 +        error_counter = error_counter + 1
 +        error_message = 'Arguments not set correctly - please check log file for more information.'
 +        exit(1)
 +
 +    if args.dayrange:
 +        startDate = endDate - timedelta(days=(args.dayrange - 1))
 +        message = ('Start Date set to: ' + startDate.strftime('%Y-%m-%d') + 'T00:00:00')
 +        logging.info(message)
 +
 +    if args.queue:
 +        queueIds = args.queue
 +        message = ('Queue ID list: ' + str(queueIds))
 +        logging.info(message)
 +    else:
 +        message = (
 +            'No queue ID data set. This app COULD (if we wanted to!) be used to retrieve all activities for a date '
 +            'range but that is not what we want'
 +            'Hence you must enter at least 1 queue with the "-q" parameter. For multiple queues add a "-q" for in '
 +            'front of each queue ID.')
 +        logging.info(message)
 +        error_counter = error_counter + 1
 +        error_message = 'Arguments not set correctly - please check log file for more information.'
 +        exit(1)
 +
 +    if args.activities:
 +        retrieveActivities = True
 +    else:
 +        retrieveActivities = False
 +
 +    if args.write:
 +        writeActivitiesToFile = True
 +    else:
 +        writeActivitiesToFile = False
 +
 +
 +def loginEce():
 +    global error_counter
 +    global error_message
 +    login_url = 'https://' + ece_host + '/system/ws/v12/authentication/user/login?forceLogin=yes'
 +    loginUser = '{"userName":"' + ece_username + '","password":"' + ece_password + '"}'
 +    loginHeaders = {"Content-Type": "application/json"}
 +    message = ('Attempting to login...')
 +    logging.info(message)
 +
 +    responseStatusCode = 0
 +    try:
 +        response = requests.post(url=login_url, verify=False, headers=loginHeaders, data=loginUser, timeout=5)
 +        responseHeaders = (response.headers)
 +        responseStatusCode = (response.status_code)
 +    except:
 +        message = ('Issue Calling Login URL.')
 +        logging.error(message)
 +
 +    if (responseStatusCode == 204):
 +        # Get the X-egain-session Header value returned after successful (204) login.
 +        global responseToken
 +        responseToken = (responseHeaders['X-egain-session'])
 +        global eceHeaders
 +        eceHeaders = {"Accept": "application/json", "X-egain-session": responseToken}
 +        message = ('Login Successful!, X-egain-session value is: ' + str(responseToken))
 +        logging.info(message)
 +    else:
 +        message = ('Login Failed!, Status Code: ' + str(responseStatusCode))
 +        logging.error(message)
 +        error_counter = error_counter + 1
 +        error_message = 'Failed to log into ECE successfully. Please check log file for more information.'
 +        sys.exit(1)
 +
 +
 +def logoutEce():
 +    logoutUrl = 'https://' + ece_host + '/system/ws/v12/authentication/user/logout'
 +    responseStatusCode = 0
 +    try:
 +        response = requests.delete(url=logoutUrl, verify=False, headers=eceHeaders)
 +        responseStatusCode = (response.status_code)
 +        response_text = response.text
 +    except:
 +        message = ('Issue Calling Logout URL.')
 +        logging.error(message)
 +
 +    if (responseStatusCode == 204):
 +        message = ('Logged out successfully.')
 +        logging.info(message)
 +    else:
 +        message = ('Logout Failed!, Status Code: ' + str(responseStatusCode) + '\nError Response: ' + response_text)
 +        logging.error(message)
 +
 +
 +def listActivities(startDate, endDate, pageNum, queueId):
 +    global activity_ids_searched
 +    global activity_ids_with_attachments
 +    global activityCount
 +    global currentPageNum
 +    global pageSize
 +    global retrievedData
 +    global error_counter
 +
 +    startDateString = (startDate.strftime('%Y-%m-%d'))
 +    endDateString = (endDate.strftime('%Y-%m-%d'))
 +    currentPageNum = pageNum
 +    retrievedData = False
 +    listActivitiesUrl = 'https://' + ece_host + '/system/ws/v12/interaction/activity?type=email&queue=' + str(
 +        queueId) + '&$pagenum=' + str(
 +        currentPageNum) + '&lastModifiedDate=[' + startDateString + 'T00:00:00.000Z,' + endDateString + 'T23:59:59.999Z]'
 +    message = ('listActivitiesUrl: ' + listActivitiesUrl)
 +    logging.debug(message)
 +
 +    # Attempt to Retrieve List of Activities
 +    responseStatusCode = 0
 +    try:
 +        response = requests.get(url=listActivitiesUrl, verify=False, headers=eceHeaders, timeout=5)
 +        responseStatusCode = (response.status_code)
 +        responseText = response.text
 +    except:
 +        message = ('Issue Calling List Activity URL.')
 +        logging.error(message)
 +
 +    if (responseStatusCode == 200):
 +        try:
 +            activityDict = json.loads(responseText)
 +            activityCount = activityDict['paginationInfo']['count']
 +            # currentPageNum = activityDict['paginationInfo']['pagenum']
 +            pageSize = activityDict['paginationInfo']['pagesize']
 +            # Loop through the file and get each Activity id
 +            for id in activityDict['activity']:
 +                activityId = str(id['id'])  # get the Activity ID
 +                # print('activityId: ',activityId)
 +                activity_ids_searched.append(activityId)
 +                activityAttachmentsCount = id['attachments']['count' # Get the Attachments Count
 +                # print('activityAttachmentsCount: ', activityAttachmentsCount)
 +                if (activityAttachmentsCount > 0):
 +                    activity_ids_with_attachments.append(activityId)
 +                retrievedData = True
 +        except Exception as e:
 +            message = ('Error in listActivities Function. error:' + str(e))
 +            logging.error(message)
 +            error_counter = error_counter + 1
 +    elif (currentPageNum == 1 and responseStatusCode == 204):
 +        message = ('No Activities Content for that date range')
 +        logging.info(message)
 +    elif (responseStatusCode == 204):
 +        message = ('Completed search.')
 +        logging.info(message)
 +    else:
 +        message = ('Failed to list Activities, statusCode: ' + str(responseStatusCode))
 +        logging.error(message)
 +        error_counter = error_counter + 1
 +
 +
 +def getActivity(id, folder):
 +    message = ('Attempting to retrieve Activity Id: ' + id + '...')
 +    logging.debug(message)
 +    activityUrl = 'https://' + ece_host + '/system/ws/v12/interaction/activity/' + id + '?$attribute=all'
 +    # Attempt to get Activity Id
 +    response = requests.get(url=activityUrl, verify=False, headers=eceHeaders)
 +
 +    # Store Response Values
 +    responseStatusCode = (response.status_code)
 +    responseText = response.text
 +
 +    # print (activityDict.keys())
 +    # print (activityDict['activity'][0]['case']['id'])
 +
 +    if (responseStatusCode == 200):
 +        try:
 +            activityDict = json.loads(responseText)
 +            caseId = str(activityDict['activity'][0]['case']['id'])  # Get the Case Id
 +            if caseId not in case_ids:
 +                case_ids.append(caseId)
 +            if (writeActivitiesToFile):
 +                fileName = 'activityId-' + id + '-caseId-' + caseId + '.json'
 +                myFolder = rootFolder + folder
 +                filePath = myFolder + '/' + fileName
 +                # Check whether the specified path exists or not
 +                isExist = os.path.exists(myFolder)
 +                if not isExist:
 +                    # Create a new directory because it does not exist
 +                    os.makedirs(myFolder)
 +                    message = ('New directory: "' + myFolder + '" is created.')
 +                    logging.info(message)
 +                # Save the activity as a text file
 +                text_file = open(filePath, "w", encoding="utf-8")
 +                text_file.write(responseText)
 +                text_file.close()
 +                message = ('Saved Activity Id : ' + id + 'to file.')
 +                logging.debug(message)
 +        except Exception as e:
 +            message = ('Error in getActivity function. error: ' + str(e))
 +            logging.error(message)
 +            logoutEce()
 +            sys.exit(2)
 +    else:
 +        print('Failed to retrieve Activity')
 +
 +
 +def getCase(id):
 +    message = ('Attempting to retrieve Case Id: ' + id + '...')
 +    logging.debug(message)
 +    caseUrl = 'https://' + ece_host + '/system/ws/v12/interaction/case/' + id + '?$attribute=all'
 +    # Attempt to get Activity Id
 +    response = requests.get(url=caseUrl, verify=False, headers=eceHeaders)
 +
 +    # Store Response Values
 +    responseStatusCode = (response.status_code)
 +    responseText = response.text
 +
 +    if (responseStatusCode == 200):
 +        try:
 +            caseDict = json.loads(responseText)
 +            caseStatus = str(caseDict['case'][0]['status']['value'])  # Get the Case Id
 +            if (caseStatus == 'closed'):
 +                case_ids_closed.append(caseId)
 +            if (writeActivitiesToFile):
 +                fileName = 'caseId-' + id + '-' + caseStatus + '.json'
 +                myFolder = rootFolder + 'Cases'
 +                filePath = myFolder + '/' + fileName
 +                # Check whether the specified path exists or not
 +                isExist = os.path.exists(myFolder)
 +                if not isExist:
 +                    # Create a new directory because it does not exist
 +                    os.makedirs(myFolder)
 +                    message = ('New directory: "' + myFolder + '" is created.')
 +                    logging.info(message)
 +                # Save the activity as a text file
 +                text_file = open(filePath, "w", encoding="utf-8")
 +                text_file.write(responseText)
 +                text_file.close()
 +                message = ('Saved Case Id : ' + id + ' to file.')
 +                logging.debug(message)
 +        except Exception as e:
 +            message = ('Error in getCase function. error: ' + str(e))
 +            logging.error(message)
 +            logoutEce()
 +            sys.exit(2)
 +    else:
 +        print('Failed to retrieve Case')
 +
 +
 +# get the Command line parameters
 +getArguments()
 +
 +# Login
 +loginEce()
 +
 +# Loop through queues provided
 +for queueId in queueIds:
 +    message = ('QueueId: ' + str(queueId))
 +    logging.info(message)
 +    listActivities(startDate, endDate, 1, queueId)
 +    if (retrievedData):
 +        message = ('Activity Count: ' + str(activityCount))
 +        logging.info(message)
 +        message = ('PageSize: ' + str(pageSize))
 +        logging.info(message)
 +        message = ('Current Page Num: ' + str(currentPageNum))
 +        logging.debug(message)
 +
 +        while ((currentPageNum * pageSize) < activityCount):
 +            currentPageNum += 1
 +            message = ('Current Page Num: ' + str(currentPageNum))
 +            logging.debug(message)
 +            time.sleep(delay)
 +            listActivities(startDate, endDate, currentPageNum, queueId)
 +
 +message = ('Number of Activities Searched: ' + str(len(activity_ids_searched)))
 +logging.debug(message)
 +message = ('Number of Activity IDs with attachments: ' + str(len(activity_ids_with_attachments)))
 +logging.debug(message)
 +message = ('Activity Ids Searched: ' + str(activity_ids_searched))
 +logging.debug(message)
 +message = ('Activity Ids with attachments: ' + str(activity_ids_with_attachments))
 +logging.debug(message)
 +
 +if (retrieveActivities):
 +    message = ('Getting activityIds. This might take some time...')
 +    logging.info(message)
 +    for activityId in activity_ids_searched:
 +        message = ('Getting activityId: ' + str(activityId))
 +        logging.debug(message)
 +        time.sleep(delay)
 +        getActivity(activityId, 'Activities-All')
 +
 +    message = ('Number of case_ids: ' + str(len(case_ids)))
 +    logging.debug(message)
 +    message = ('case_ids: ' + str(case_ids))
 +    logging.debug(message)
 +
 +    message = ('Getting case_ids. This might take some time...')
 +    logging.info(message)
 +    for caseId in case_ids:
 +        message = ('Getting caseId: ' + str(caseId))
 +        logging.debug(message)
 +        time.sleep(delay)
 +        getCase(caseId)
 +
 +    message = ('Number of Closed case_ids: ' + str(len(case_ids_closed)))
 +    logging.debug(message)
 +    message = ('Closed case_ids: ' + str(case_ids_closed))
 +    logging.debug(message)
 +
 +# Logout
 +logoutEce()
 +
 +# Print Summary At the end
 +message = ('#########################################')
 +logging.info(message)
 +message = ('Filter StartDate: ' + startDate.strftime('%Y-%m-%d') + ' 00:00:00')
 +logging.info(message)
 +message = ('Filter EndDate: ' + endDate.strftime('%Y-%m-%d') + ' 23:59:59')
 +logging.info(message)
 +message = ('Number of Activities Searched: ' + str(len(activity_ids_searched)))
 +logging.info(message)
 +message = ('Number of Activity IDs with attachments: ' + str(len(activity_ids_with_attachments)))
 +logging.info(message)
 +
 +if (retrieveActivities):
 +    message = ('Number of case_ids: ' + str(len(case_ids)))
 +    logging.info(message)
 +    message = ('Number of Closed case_ids: ' + str(len(case_ids_closed)))
 +    logging.info(message)
 +
 +message = ('Activity Ids Searched: ' + str(activity_ids_searched))
 +logging.info(message)
 +message = ('Activity Ids with attachments: ' + str(activity_ids_with_attachments))
 +logging.info(message)
 +
 +if (retrieveActivities):
 +    message = ('case_ids: ' + str(case_ids))
 +    logging.info(message)
 +    message = ('Closed case_ids: ' + str(case_ids_closed))
 +    logging.info(message)
 +message = ('startTime: ' + startTime.strftime("%d/%m/%Y %H:%M:%S"))
 +logging.info(message)
 +endTime = datetime.now()
 +message = ('endTime: ' + endTime.strftime("%d/%m/%Y %H:%M:%S"))
 +logging.info(message)
 +duration = endTime - startTime
 +message = ('duration: ' + str(duration))
 +logging.info(message)
 +message = ('#########################################')
 +logging.info(message)
 +
 +message = ('--------------- Finished! ---------------')
 +logging.info(message)
 +</code>