Find and delete/replace all timestamps

I’ve tried as many combinations as I could piece together from other posts but haven’t had an luck.

I want to set up an action that will search the whole currently open draft and find the timestamps at the beginning of each line and delete it (or replace with nothing).

The timestamps are all the same format but each line is different numbers depending on the time:
2023-08-21 07:45:00.123456+1000

I added a new action with 1 step ‘Script’ in various ways using:
%Y-%m-%d %H:%M:%S.%6%z

Which I got from https://strftime.net/ but nothing has worked so far.

If anyone can point me in the right direction I’d be super grateful (I have a subscription with the extra options, maybe I am trying to do it wrong).

strftime is a tool to convert a date object into a string. It, unfortunately, does not do anything related to finding existing date strings.

Could you share some example lines from the data you are working with? It might be easier to suggest solutions. For example, if there is always a separator character, and the dates are always at the beginning of the line, it might be easiest to split the lines and remove the text. If not, regular expressions are probably needed and could be used either via find and replace or in a scripted action.

Try this action.

Take a look at the details and you should see that it runs this code.

draft.saveVersion();
draft.content = draft.content.replaceAll(/^\d{4}-\d\d-\d\d \d\d:\d\d:\d\d\.\d{6}.\d{4} /gm, "")
draft.update();
  • First line explicitly saves a version so you can easily restore.
  • Second line uses a regular expression to do the replacement (as Greg noted might be a good option above).
  • Third line updates the draft with the replaced content.

Hope that helps.

1 Like

I tried sylumers code but couldn’t get it to work.

The dates are all at the beginning of each line and are in this format:

0000-00-00 00:00:00.000000+1000

Year-Month-Day Hour:Minutes:Seconds.Microseconds+1000

The +1000 remains the same on every line.

If I use regular expressions in the advanced find and replace do I just need the ^\d (etc) part? I tried a few date variations from the link to NSRegularExpressions to build a search string but no luck.

Sorry to be a pain, trying to get my head around it. My iOS has its heart hacked out so it could just be the ninjas have disabled actions, as it appears my Drafts app is a beta version - so they may have mucked around with the underlying ActionKit, EditorKit, StyledUI, DraftsUI or OperationKit.

Can you share a few lines in a code block (between triple backticks on this forum) I can paste into a draft and test with. It looks like a full pattern match that should work from what you shared.

Can you explain what you mean by this? I am running the Drafts beta, but I don’t fully understand what you are saying about the OS.

It is possible that the OP tried running your regex in the Find and Replace dialog - where I don’t think he needs the leading / or the ending /gm that are needed in the action script you provided.

I wouldn’t expect that to have given the result described, though I must admit by ‘running the code’, I was assuming that was running the action and not any other use of the information posted.

@sylumer Here is a snippet, I also realised not every line is a timestamp which may make it harder to achieve? Doing by hand takes so much longer.


2023-08-06 09:24:39.264787+1000 0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] Found 0 blocked tasks: (
)
2023-08-06 09:24:39.264876+1000 0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] Enqueueing eligible task <TRIFetchMultipleExperimentNotificationsTask:(null)> [tid:881]
2023-08-06 09:24:39.264905+1000 0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] enqueued follow-up task <TRIFetchMultipleExperimentNotificationsTask:(null)> [tid:881] after execution of [tid:879]
2023-08-06 09:24:39.265111+1000 0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] adding task to task queue: <private>
2023-08-06 09:24:39.265437+1000 0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] adding task with 0 dependencies to task queue: <private>
2023-08-06 09:24:39.266367+1000 0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] Found 3 dependency-free tasks to consider starting for capability 26: <private>
2023-08-06 09:24:39.266371+1000 0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] Partitioning task group into runnable/blocked for capabilities 26
2023-08-06 09:24:39.266424+1000 0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] Found 3 runnable tasks: (
    "[tid:882]",
    "[tid:880]",
    "[tid:881]"
)
2023-08-06 09:24:39.266428+1000 0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] Found 0 blocked tasks: (
)
2023-08-06 09:24:39.266489+1000 0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] Enqueueing eligible task <TRISelectRolloutNotificationListTask:(null)> [tid:882]
2023-08-06 09:24:39.266549+1000 0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] enqueued follow-up task <TRISelectRolloutNotificationListTask:(null)> [tid:882] after execution of [tid:879]
2023-08-06 09:24:39.266830+1000 0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] Found 3 dependency-free tasks to consider starting for capability 26: <private>
2023-08-06 09:24:39.266833+1000 0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] Partitioning task group into runnable/blocked for capabilities 26
2023-08-06 09:24:39.266876+1000 0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] Found 3 runnable tasks: (
    "[tid:882]",
    "[tid:880]",
    "[tid:881]"
)
2023-08-06 09:24:39.266880+1000 0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] Found 0 blocked tasks: (
)
2023-08-06 09:24:39.266949+1000 0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] Starting <TRIRetargetAllTask:0x******b80> [tid:880] with tags {}
2023-08-06 09:24:39.283604+1000 0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] Using persisted experiment opt-out: '0'
2023-08-06 09:24:39.284002+1000 0x36e1     Info        0x0                  495    0    triald: (Trial) [com.apple.trial:_] Logging log event: <private>
2023-08-06 09:24:39.284059+1000 0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] <TRIRetargetAllTask:0x******b80> [tid:880] finished with status COMPLETED

(hopefully that comes up in a code block)

By beta I mean:
(//edited the links to the screenshots out as I thought github strips the binary the ratninjas have injected into every file I create but it shows up as being binary, sorry!)

I’m a captive of Stealth Developer Mode :roll_eyes:. I know the real Drafts code signing trust level isn’t 0 :wink:

@Bjb I first tried it in actions (in 1 step). I also tried variations in the search and replace with regularexpression selected from the drop down.

I didn’t download the action as it had other code added in the ‘allow link to switch apps’ preview screen and I wasn’t sure if that was normally on them when they’re created or the :rat: :ninja: added it as part of their app modification (stuff about groupDisposition, discoverabilityTitle, there was a groupUUID and another UUID). So I just copied the snippets in.

I’d be super grateful for any advice, tips, links on how to achieve it (if it is even possible to do).

I tried the regular expression and the action in Drafts (beta version of Drafts), and it gave the results below, which look correct to me.

Expand for results
0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] Found 0 blocked tasks: (
)
0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] Enqueueing eligible task <TRIFetchMultipleExperimentNotificationsTask:(null)> [tid:881]
0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] enqueued follow-up task <TRIFetchMultipleExperimentNotificationsTask:(null)> [tid:881] after execution of [tid:879]
0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] adding task to task queue: <private>
0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] adding task with 0 dependencies to task queue: <private>
0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] Found 3 dependency-free tasks to consider starting for capability 26: <private>
0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] Partitioning task group into runnable/blocked for capabilities 26
0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] Found 3 runnable tasks: (
    "[tid:882]",
    "[tid:880]",
    "[tid:881]"
)
0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] Found 0 blocked tasks: (
)
0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] Enqueueing eligible task <TRISelectRolloutNotificationListTask:(null)> [tid:882]
0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] enqueued follow-up task <TRISelectRolloutNotificationListTask:(null)> [tid:882] after execution of [tid:879]
0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] Found 3 dependency-free tasks to consider starting for capability 26: <private>
0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] Partitioning task group into runnable/blocked for capabilities 26
0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] Found 3 runnable tasks: (
    "[tid:882]",
    "[tid:880]",
    "[tid:881]"
)
0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] Found 0 blocked tasks: (
)
0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] Starting <TRIRetargetAllTask:0x******b80> [tid:880] with tags {}
0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] Using persisted experiment opt-out: '0'
0x36e1     Info        0x0                  495    0    triald: (Trial) [com.apple.trial:_] Logging log event: <private>
0x36e1     Default     0x0                  495    7    triald: (TrialServer) [com.apple.triald:server] <TRIRetargetAllTask:0x******b80> [tid:880] finished with status COMPLETED

Looking at your notes on GitHub, “Stealthy Developer Mode” is a hack of app betas. I’m pretty sure that puts you in the camp of firmly unsupported use.

Okay, so I think you are pretty safe from “rat ninja” (BTW plurals for Japanese words like ninja would generally not have an “s”) - the only one I’ve come across is from TMNT and I’m pretty sure he’s not on this forum :wink:

The details you are describing are part of the action - you would be able to note this by exporting and URL decoding your own actions in Drafts. Many objects in computing get a UUID to ensure uniqueness.

My advice is…

  • Use the App Store version of Drafts - don’t use exploits.
  • Use the action that has been shared with you - I’m pretty sure it does what you asked for.
  • Confirm the regex works using a regex tool and your sample data - regex101 is a good one.

Thanks so much I will give it a try.

I did download Drafts from the AppStore, I also have the subscription version through Apple. I haven’t ever had any involvement with beta anything but theres still an active exploit allowing whoever they are to do what they do - because nothing we do will get rid of it. Aside from paying a ton of $ for a cyber security expert, we’re stuck waiting for a researcher to take up the challenge and find the hole to plug.

*grin about the ninja plural, maybe I should rename them the MacGyverRats since everything is a mashup of versions of every OS ever created!

if this is a one-time issue (clean this file with this date mess starting each line), a simple way is straight JavaScript testing of each line. Split text into an array of lines, then:

for ( t of lineArr) { // gets each line into t
if (new Date(t.substr(0,32)!=“Invalid Date”) { t = t.substr(33);}
// new Date(t) makes a Date object from the t.substr(0,32) but is ‘Invalid Date’ for strings
}

then rebuild your draft.

that should do it (the values of 32 & 33 may not be right). I checked the entire line (timestamp + extra string), and a (" " + timestamp); they will generate a Date object, but an ‘Invalid Date’; I also checked (0x36e1) and also invalid.

1 Like

Thanks folks, sylumers script works a treat!!

I have one other thing to figure out, I have tried a bazillion ways from scouring the internet but I can’t get anything to work.

I’d like to be able to use an action to find and replace UUIDs which are always the same length.

Also those 0x123ab45c formats (some are different lengths but all start with 0x).

But instead of the whole thing to leave the last 3 characters.

So ABC123DE-12AB-34CD-56EF-ABC123DE would become XXXXXXXX-XXXX-XXXX-XXXX-XXXXX3DE

and 0x123ab45c would become 0x*****45c

These would need to be run separately I guess, I could have one for each format type as I suppose it would rely on the same formula structure?

I am not sure if this is even possible to do?

For the UUIDs I tried different ways like this:

draft.saveVersion();
draft.content = draft.content.replaceAll(/^\[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{9}$ /g, "XXXXXXXX-XXXX-XXXX-XXXX-XXXXX")
draft.update();

I’m probably way off track though! I’d be grateful for any advice if anyone has some time.

Try this code.

draft.saveVersion();
draft.content = draft.content.replaceAll(/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{5}([0-9a-fA-F]{3})/gm, "XXXXXXXX-XXXX-XXXX-XXXX-XXXXX$1");
draft.content = draft.content.replaceAll(/0x[0-9a-fA-F]{5}([0-9a-fA-F]{3})/gm, "0x*****$1");
draft.update()

sylumer!!! you’re the bestest EVER!!! :smile: :smile: :smile:
:trophy: :tada: :woman_cartwheeling: :raised_hands:

head to toes you’re a legend mate! thank you soo much! :raised_hands:

Hello, mechiu again, I have run into the issue that the following will replace anything that matches, as well as if it has additional characters.

draft.saveVersion();
draft.content = draft.content.replaceAll(/0x[0-9a-fA-F]{5}([0-9a-fA-F]{3})/gm, "0x*****$1");
draft.update()

I had a look at other posts and tried matching first but I get an error with this:

let match = draft.content.match(/0x[0-9a-fA-F]{6}([0-9a-fA-F]{3});
if (match) {
draft.content = draft.content.replaceAll(0x******$1);
}

Is anyone able to point out where I’m going wrong?

Can you provide an example set of content to demonstrate the undesired behaviour?

All I can think is that it will currently match longer Hex strings being expressed in the same notation. If there were always a space after then that could be used in the original replace within the match and the substitution parameters. If it varied, then perhaps using a word boundary token would allow the required flexibility?

This line is a good example, one is 0x143e1fb80 {9} another is 0xbd5e1be7791c20c8 {16}.

I’ve been learning new ways to use the advanced find and replace a fair bit but it uses a different regex flavor (swift?) to the actions regex which is javascript? I know with the advanced option I can specify the end with \b, so if it doesn’t match it ignores it. I’m still trying to master actions because they’re much quicker unless there is a way to save advanced search & replace?

The majority always have a space after it but can sometimes have “ or / or > at the end.

2023-10-07 08:48:00.865969+1000 0x10f0 Default 0x0 405 0 dmd: [com.apple.dmd:Policy] Updating existing registration <DMDPolicyRegistration: 0x143e1fb80> (entity: PolicyRegistration; id: 0xbd5e1be7791c20c8 <x-coredata://FFFFEEEE-DDDD-CCCC-BBBB-321B75BD99F0/PolicyRegistration/p1>; data: <fault>) with identifier dmf.policy.monitor.app

I don’t think so, but there may be a feature request for it.

You have described it in the scenario using “or” …. have you looked at the OR operator (pipe, “|”) in regex for doing this?

Not commenting on the regex code, but just in terms of the Javascript, you might need to clarify some basics of replace functions.

If you only want to replace the first occurrence of something, you can use replace, instead of replaceAll.

The error you are likely getting with the match code you posted is that the regex is not closed (no end / before the parenthesis), but also that’s not value code for replacement. Here’s a few examples, just using a placeholder regular expression:

// replace only first match
draft.content = draft.content.replace(/REGEX/, "REPLACEMENT")

// replace all occurrences of matches
// note the `g` global flag on the regex
draft.content = draft.content.replace(/REGEX/g, "REPLACEMENT")