Timeline Wrangler
As the Community App Store has been offline for a while making the Timeline Manager² app unavailable, and seen several people that want to maintain their notification timeline on a occasional basis I’ve tried to make a HomeyScript that can do exactly that.
How to use:
The only thing you need is an Homey Pro (any version, besides Homey (Cloud)) and the app HomeyScript.
When you have that app installed you can go to the Web GUI => Scripts and click on “New HomeyScript” on the bottom-left of the page.
A new script will get created and you can give it a name (not mandatory, just easier to find it back later on), “Timeline Wrangler” is a good example
Then all you need to do is copy and paste the entire script below (118 lines) into the top field, and press the “Save” button.
How to activate the script:
You can activate this script with the “Test” button or from any flow however you want, just pre-specify the code’s settings in the top of the code to whatever you want and activate the script.
Alternatively you can also use the “Code” flowcard of HomeyScript in Advanced Flows, it will return a [string]
what it has done.
Example Flow(s):
Changelog:
- v1.4 (August 10, 2024):
- Fixed: Fix for empty name categories
- v1.3 (October 2, 2023):
- Fixed: Fix for nameless categories
- v1.2 (October 2, 2023):
- Added: “Contains Text” filter
- v1.1 (October 1, 2023):
- Fixed: how hours are looked at
- v1.0 (October 1, 2023):
- Initial release
Disclaimer:
Use this script on your own discretion, if the “deleteNotifications” setting is true, it will delete the notifications it mentions.
Please do keep the thread clean, any non related replies will get deleted!
If you have (general) questions about HomeyScript or the used Web API, then this is not the thread for that.
The Script:
// Timeline Wrangler v1.4
// ==================== User Settings ====================
const deleteNotifications = false; // If "true" = actually removes notifications, if "false" = display only
const daysOld = 5; // 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 = 1000; // The maximum amount of notifications that stay, anything more will get deleted
const containsText = ''; // 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 = false; // If "true" it will only remove from the specified categories below
// Separate categories by comma ( , )
const categories = [
'homey:manager:apps',
'homey:manager:backup',
'homey:manager:energy',
'homey:manager:experiments',
'homey:manager:flow',
'homey:manager:presence',
'homey:manager:safety',
'homey:manager:updates',
'homey:manager:users',
'homey:manager:zigbee',
];
// ==================== 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') && owners[key].uriObj.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).';
}
return 'No notifications were (actually) removed';