[HomeyScript] Timeline Wrangler

Not sure if it is ‘too much’, but I’d like to share my interactive timeline cleanup, which uses this Telegram app, to be able to select pre-defined phrases as answer, or by entering a phrase to match certain timeline entries.
The timeline entries which contain the answer text , are to be deleted.

  • Impression of the Telegram question + answer system, via app settings:

  • The flow asks a question via Telegram, and it comes with selectable answers
    Screenshot from 2023-10-30 19-35-29

  • And the same for a free-to-answer question:
    Screenshot from 2023-10-30 19-41-43

  • Feedback
    Screenshot from 2023-10-30 19-36-29


  • Code used in the Homeyscript flow cards:
Click me
// DEL timeline msgs ALL matching | Argument = searchphrase - Timeline_Wrangler v1.3p

// ==================== User Settings ====================
const deleteNotifications = true; // If "true": actually removes notifications, if "false": display only
const daysOld = 0; // Amount of days that need to have past before a notification is deemed old
const hoursOld = 0; // Amount of hours that need to have past before a notification is deemed old
const maximumNotifications = 250; // The maximum amount of notifications that stay, anything more will get deleted
const containsText = args[0]; // Only deletes notifications that contains the specified text, Empty ( '' ) = not used
const showCategories = false; // If "true" it will show all timeline categories you have and had in the past
const useCategory = true; // If "true" it will only remove from the specified categories below

// Separate categories by comma ( , )
const categories = [
  'homey:manager:flow',
  'homey:manager:presence',
  'homey:manager:apps',
  'homey:manager:updates',
  'homey:manager:zigbee',
  'homey:manager:energy',
  'homey:manager:backup',
  'homey:manager:users',
  'homey:app:com.athom.flowchecker',
  'homey:manager:security',
  'homey:app:nl.qluster-it.DeviceCapabilities',
  'homey:app:net.i-dev.betterlogic',
  'homey:app:com.spkes.telegramNotifications',
  'homey:manager:safety',
  'homey:app:nl.nielsdeklerk.log',
  'homey:manager:experiments',
];

// ==================== Don't change anything below here ====================
const removedNotifications = [];
const notificationCategories = [];
let amountNotifications = 0;
let amountKept = 0;

if (showCategories) {
  await Homey.notifications.getOwners()
    .then(owners => {
      log(Object.keys(owners).length, 'Timeline Categorie(s):');
      Object.keys(owners).forEach(key => {
        if (owners[key].uriObj.hasOwnProperty('name')) {
          log('-', owners[key].uriObj.name, (owners[key].uriObj.name.length <= 5) ? '\t\t\t|' : (owners[key].uriObj.name.length <= 12) ? '\t\t|' : '\t|', '\'' + key + '\'');
        }
        else {
          log('- Unkown Name', '\t\t|', '\'' + key + '\'');
        }
      });
      log('\n');
    })
    .catch(err => {
      log(err);
      return 'Getting categories failed';
    });
}

await Homey.notifications.getNotifications()
  .then(notifications => {
    amountNotifications = Object.keys(notifications).length;
    log(amountNotifications, 'Timeline Notification(s):');

    Object.keys(notifications).forEach(key => {
      const currentDate = new Date();
      const dateCreated = new Date(notifications[key].dateCreated);
      const timeDifference = (currentDate - dateCreated) / 1000;
      const daysDifference = Math.floor(timeDifference / 86400);
      const hours = Math.floor((timeDifference % 86400) / 3600);
      const hoursDifference = Math.floor(timeDifference / 3600);
      const minutes = Math.floor((timeDifference % 3600) / 60);

      if (
        ((containsText.length > 0 && notifications[key].excerpt.toLowerCase().includes(containsText.toLowerCase()))
        && (daysDifference >= daysOld && hoursDifference >= hoursOld))
        || maximumNotifications < amountKept
      ) {
        log('- Removing:', notifications[key].id, '  |', notifications[key].ownerUri, '|', notifications[key].excerpt, '(' + notifications[key].dateCreated + ' - ' + daysDifference + ' day(s), ' + hours + ' hour(s) and ' + minutes + ' minute(s) old)');

        if (deleteNotifications) {
          Homey.notifications.deleteNotification({id: notifications[key].id});
          removedNotifications.push(notifications[key].id);
        }
      }
      else if (
        ((containsText.length === 0 && useCategory)
        && (categories.includes(notifications[key].ownerUri))
        && (daysDifference >= daysOld && hoursDifference >= hoursOld))
        || maximumNotifications < amountKept
      ) {
        log('- Removing:', notifications[key].id, '  |', notifications[key].ownerUri, '|', notifications[key].excerpt, '(' + notifications[key].dateCreated + ' - ' + daysDifference + ' day(s), ' + hours + ' hour(s) and ' + minutes + ' minute(s) old)');

        if (deleteNotifications) {
          Homey.notifications.deleteNotification({id: notifications[key].id});
          removedNotifications.push(notifications[key].id);
        }
      }
      else if (
        ((containsText.length === 0 && !useCategory)
        && (daysDifference >= daysOld && hoursDifference >= hoursOld))
        || maximumNotifications < amountKept
      ) {
        log('- Removing:', notifications[key].id, '  |', notifications[key].ownerUri, '|', notifications[key].excerpt, '(' + notifications[key].dateCreated + ' - ' + daysDifference + ' day(s), ' + hours + ' hour(s) and ' + minutes + ' minute(s) old)');

        if (deleteNotifications) {
          Homey.notifications.deleteNotification({id: notifications[key].id});
          removedNotifications.push(notifications[key].id);
        }
      }
      else {
        log('- Keeping: ', notifications[key].id, '  |', notifications[key].ownerUri, '|', notifications[key].excerpt, '(' + notifications[key].dateCreated + ' - ' + daysDifference + ' day(s), ' + hours + ' hour(s) and ' + minutes + ' minute(s) old)');
        amountKept++;
      }
    });
  })
  .catch(err => {
    log(err);
    return 'Script failed';
  });

if (removedNotifications.length > 0) {
  return 'Removed ' + removedNotifications.length + ' out of ' + amountNotifications + ' notification(s).\nUsed Argument: ' + args[0];
}

return 'No notifications were (actually) removed. \nUsed Argument: ' + args[0];