Store stuff temporarily in global inbox and let it automatically move to the right database when the time has come

Hi there,

after closing a database I often have something I want to add to it, within minutes. Pretty annoying. Sure, I could use the global inbox but in my case that’s the best place to never see things again. I also tried to use groups in the global inbox to collect stuff in order to move it to the closed database’s inbox next time it is open. That was the plan.

In the end I wrote a Reminder Script that moves things automatically when the database is available. Big help. But this Script only gets triggered every hour. I adapted it to a Triggered Script and attached it to the parent group of the groups that hold stuff for inboxes which are not open at that time and to every database’s inbox. Now if I open a database and go to its inbox stuff from the global inbox group is right there. Nice! :smiley:

To help me attach the script to all inboxes (and to future ones) and create the groups … another script.

I then realized that this setup is perfect for me - if I keep up with creating groups and attaching the Triggered Script to new inboxes… :roll_eyes:

So I wrote yet another script, one that gets triggered when Keyboard Maestro sees a new file in my database folder (but you could use a macOS folder action (and I think Hazel) as well). This one creates a group for the new database in the global inbox and attaches the Trigger Script to the database’s inbox without any action from my side. :sunglasses:

While testing I deleted a lot of groups from the global inbox whose databases didn’t exist anymore. Ok, one more script, this time triggered when a file is removed from the database folder: If the group in the global inbox is empty it gets deleted when the database is gone.

It’s a second inbox structure that can be used when a database is not open, and when it is open again it takes maximal one hour until the Reminder Script moves the stuff into the real inbox - or it’s earlier triggered by clicking on the database’s inbox.

Once set up there’s nothing more to do, everything will be in its place when the time has come.

It might seem a little bit overkill. But if you know the situation of “Where should I store this? I just closed this database!” or you don’t want to open it just to add one record then you should really try those scripts.

It works well and helps a lot (at least me), but use a testdatabase first!

Reminder Script:

-- Reminder Script, moves all children to the database's incoming group (if it is available). I've set it to run every hour  

on performReminder(theRecord)  
	tell application id "DNtp"  
		try  
			set theChildGroups to (every child of theRecord whose type is group)  
			set theDatabases to databases  
			
			repeat with thisChildGroup in theChildGroups  
				if (count of child of thisChildGroup) > 0 then  
					
					set theName to name of thisChildGroup  
					set theDatabaseName to (characters 17 thru -1 in theName) as string -- adjust to your group name (I use "Zwischeneingang" & space & [DATABASENAME])  
					
					repeat with thisDatabase in theDatabases  
						set thisDatabaseName to name of thisDatabase  
						if (theDatabaseName as string) = (thisDatabaseName as string) then  
							move record (every child of thisChildGroup) to incoming group of thisDatabase  
						end if  
					end repeat  
					
				end if  
			end repeat  
			
		on error error_message number error_number  
			if the error_number is not -128 then display alert "DEVONthink" message error_message as warning  
		end try  
	end tell  
end performReminder  

Triggered Script:

-- Triggered Script, moves all children to the database's incoming group (if it is available). I attached it to the deputy incoming group's parent group and to every database's incoming group  

on triggered(theRecord)  
	tell application id "DNtp"  
		try  
			set theGroup to (get record with uuid "") -- set the UUID of the deputy incoming group's parent group (I used the UUID instead of "theRecord" as this script is attached to every incoming group)  
			set theChildGroups to (every child of theGroup whose type is group)  
			set theDatabases to databases  
			
			repeat with thisChildGroup in theChildGroups  
				if (count of child of thisChildGroup) > 0 then  
					
					set theName to name of thisChildGroup  
					set theDatabaseName to (characters 17 thru -1 in theName) as string -- adjust to your group name (I use "Zwischeneingang" & space & [DATABASENAME])  
					
					repeat with thisDatabase in theDatabases  
						set thisDatabaseName to name of thisDatabase  
						if (theDatabaseName as string) = (thisDatabaseName as string) then  
							move record (every child of thisChildGroup) to incoming group of thisDatabase  
						end if  
					end repeat  
					
				end if  
			end repeat  
			
		on error error_message number error_number  
			if the error_number is not -128 then display alert "DEVONthink" message error_message as warning  
		end try  
	end tell  
end triggered  

Helper Script for existing databases (attaches the Trigger Script and creates the group in global inbox):

-- Attach Triggered Script to current database and create group in global inbox (the group must be inside a parent group, otherwise the other scripts won't work)  

property newGroupNameBeginning : "Zwischeneingang"  

tell application id "DNtp"  
	try  
		set attached script of incoming group of current database to "" -- set the POSIX path of the Triggered Script  
		
		set newGroupName to newGroupNameBeginning & space & (name of current database)  
		set newGroup to create record with {name:newGroupName, type:group} in display group selector  
		
	on error error_message number error_number  
		if the error_number is not -128 then display alert "DEVONthink" message error_message as warning  
	end try  
end tell  

“OnAdd” new database - Attach Triggered Script and create new group in global inbox (this script needs Keyboard Maestro, macOS folder actions or another app that watches your database folder. I think Hazel could do this too)

-- "OnAdd" new database → create new deputy incoming group and attach the Triggered Script to the database's incoming group  

-- This script can be used manually, but the whole point is that it runs automatically, e.g. with Keyboard Maestro (that's what I do). Or with a macOS folder action, in this case the Finder part is unnecessary (see https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/reference/ASLR_folder_actions.html). I think Hazel could do this too.  

delay 30 -- (now and then I rename a new database..)  

tell application "Finder"  
	try  
		-- Get name of new database  
		set latestAdded to item -1 of (sort (get files of (POSIX file "/DEVONthink Datenbanken/" as alias)) by creation date) as alias -- set the POSIX path of your database folder  
		set theName to name of latestAdded  
		set theDatabaseName to my Basename(theName)  
		
	on error error_message number error_number  
		if the error_number is not -128 then display alert "Finder" message error_message as warning  
	end try  
end tell  


tell application id "DNtp"  
	try  
		-- Create deputy incoming group  
		set theGroup to (get record with uuid "") -- set the UUID of the parent group  
		set newGroupName to "Zwischeneingang " & theDatabaseName  
		set newGroup to create record with {name:newGroupName, type:group} in theGroup  
		
		-- Attach Triggered Script  
		set theDatabase to database named theDatabaseName  
		set attached script of incoming group of theDatabase to "" -- set the POSIX path of the Triggered Script, (e.g. "/Users/USER/Library/Application Scripts/com.devon-technologies.think3/Triggered Scripts/Zwischeneingänge leeren.scpt")  
		
		#-- Rename incoming group (optionally)	 
		#set name of incoming group of theDatabase to "Eingang [" & theDatabaseName & "]"  
		
	on error error_message number error_number  
		if the error_number is not -128 then display alert "DEVONthink" message error_message as warning  
	end try  
end tell  


on Basename(filename)  
	set revName to reverse of characters of filename as string  
	set revNameWithoutExtension to characters ((character offset of "." in revName) + 1) thru -1 in revName as string  
	set theBasename to reverse of characters of revNameWithoutExtension as string  
end Basename  

“OnDelete” database - Delete group from gobal inbox if it’s empty (this script needs Keyboard Maestro, macOS folder actions or another app that watches your database folder. I think Hazel could do this too)

-- "OnDelete" database → delete deputy incoming group (if it's empty)  

-- This script can be used manually, but the whole point is that it runs automatically, e.g. with Keyboard Maestro (that's what I do). Or with a macOS folder action, in this case the Finder part is unnecessary (see https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/reference/ASLR_folder_actions.html). I think Hazel could do this too)  

tell application "Finder"  
	try  
		-- Get names of all databases in the folder  
		set theDatabaseNames to name of files of folder (POSIX file "/DEVONthink Datenbanken" as alias) -- set the POSIX path of your database folder  
		
	on error error_message number error_number  
		if the error_number is not -128 then display alert "Finder" message error_message as warning  
	end try  
end tell  


tell application id "DNtp"  
	try  
		-- Get all deputy incoming groups  
		set theGroup to (get record with uuid "") -- set the UUID of the parent group  
		set theChildGroups to (every child of theGroup whose type is group)  
		
		-- Compare names and delete the matching one if it's empty  
		repeat with thisChildGroup in theChildGroups  
			set thisChildGroupName to name of thisChildGroup  
			set thisChildGroupDatabaseName to my Remove_From_String(thisChildGroupName, "Zwischeneingang ") -- adjust to your group name  
			if (thisChildGroupDatabaseName & ".dtBase2") is not in theDatabaseNames then  
				if (count of child of thisChildGroup) = 0 then  
					delete record thisChildGroup  
				else  
					open window for record thisChildGroup  
					activate  
				end if  
			end if  
		end repeat  
		
	on error error_message number error_number  
		if the error_number is not -128 then display alert "DEVONthink" message error_message as warning  
	end try  
end tell  


on Remove_From_String(theText, CharOrString)  
	local ASTID, theText, CharOrString, lst  
	set ASTID to AppleScript's text item delimiters  
	try  
		considering case  
			if theText does not contain CharOrString then ¬  
				return theText  
			set AppleScript's text item delimiters to CharOrString  
			set lst to theText's text items  
		end considering  
		set AppleScript's text item delimiters to ASTID  
		return lst as text  
	on error eMsg number eNum  
		set AppleScript's text item delimiters to ASTID  
		error "Can't RemoveFromString: " & eMsg number eNum  
	end try  
end Remove_From_String
1 Like

I just use an hourly smart rule to move items from a group in the global inbox to the right database and file it.

1 Like

Didn’t try a Smart Rule as some time ago I couldn’t figure out how to move groups and records without having the group’s contents replicated outside of them.

How should a Smart Rule that moves groups and records and that uses the built-in move command look like? Or do you use AppleScript for this? (something I didn’t try, don’t know why…)

The “Move” action of smart rules is actually identical to using e.g. drag & drop or the “Move To” submenu in contextual menus. But in case of groups this might indeed not work as expected as smart rules can’t exclude the children of subgroups. I just use the smart rule to move & file recently taken notes.

That keeps me from trying Smart Rule for this again. Thanks!

This is planned for upcoming releases.

1 Like

This might be seen as unforgivable thread necromancy, but this script just came up in the Lawyers using DT thread…

May I ask how you are getting the smart rule to determine the “right database” to file it? Is it based on tags? Something more automated? Thanks!

I don’t follow the “never see things again”
I use the Global Inbox, but move entries out frequently (“inbox zero”)

automatically move

Moving to a different inbox isn’t a solution for me

groups in the global inbox to collect stuff

That works until the target database is opened

In some cases the destination is hardwired, in some I use the Classify action and in other cases I use the File action to create a hierarchy year > month > day.