You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// Name: Messages 2FA codes// Description: Search for 2FA codes in your Messages, within the last 30 minutes// Ackowledgements: // - https://github.com/squatto/alfred-imessage-2fa/// - https://github.com/raycast/extensions/tree/main/extensions/imessage-2faimport"@johnlindquist/kit"importDatabasefrom'better-sqlite3';letpreferences={lookBackMinutes: 30,ignoreRead: false,}exporttypeTMessage={guid: string;message_date: string;// 2024-11-26 06:11:18sender: string;// e.g. amazon.de or +49123456789service: string;// e.g. SMStext: string;}constdb=newDatabase(home("Library/Messages/chat.db"));letoutput=awaitarg({placeholder: "Select a message or start typing to search",choices: async(input)=>{letstmt=db.prepare(dbQuery(input));letmessages=stmt.all()asTMessage[];returnmessages.map((m)=>({name: m.text,tag: extractCode(m.text)??"no code",description: `${m.message_date} • ${m.sender} • ${m.service}`,value: m.text,preview: `<div class="p-2 text-sm">${m.text}</div>`,}));},actions: [{name: "Copy Whole Message",flag: "copyWholeMessage",visible: true,shortcut: `${cmd}+c`,},]})if(flag.copyWholeMessage){clipboard.writeText(output)notify("Whole message copied to clipboard")}else{letcode=extractCode(output)if(code){clipboard.writeText(code)notify(`Code: ${code} copied to clipboard`)}else{clipboard.writeText(output)notify("No code found. Copied whole message to clipboard instead")}}// Helpers// ===functiondbQuery(qs: string=""){letbaseQuery=/* sql */` select message.guid, message.rowid, ifnull(handle.uncanonicalized_id, chat.chat_identifier) AS sender, message.service, datetime(message.date / 1000000000 + 978307200, 'unixepoch', 'localtime') AS message_date, message.text from message left join chat_message_join on chat_message_join.message_id = message.ROWID left join chat on chat.ROWID = chat_message_join.chat_id left join handle on message.handle_id = handle.ROWID where message.is_from_me = 0 and message.text is not null and length(message.text) > 0 and datetime(message.date / 1000000000 + strftime('%s', '2001-01-01'), 'unixepoch', 'localtime') >= datetime('now', '-${preferences.lookBackMinutes} minutes', 'localtime') `;if(preferences.ignoreRead)baseQuery+=" and message.is_read = 0";if(!qs){// search for codebaseQuery=/* sql */`${baseQuery} and ( -- Matches 3 alphanumeric (e.g., 'ABC') message.text glob '*[0-9A-Z][0-9A-Z][0-9A-Z]*' -- Matches 4 alphanumeric (e.g., 'ABCD') or message.text glob '*[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]*' -- Matches 5 alphanumeric (e.g., 'ABCDE') or message.text glob '*[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]*' -- Matches 6 alphanumeric (e.g., 'ABCDEF') or message.text glob '*[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]*' -- Matches format '123-456' or message.text glob '*[0-9][0-9][0-9]-[0-9][0-9][0-9]*' -- Matches 7 alphanumeric (e.g., 'ABCDEFG') or message.text glob '*[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]*' -- Matches 8 alphanumeric (e.g., 'ABCDEFGH') or message.text glob '*[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]*' )`;}else{// Search for textbaseQuery=/* sql */`${baseQuery} and message.text like '%${qs}%'`;}return`${baseQuery} \norder by message.date desc limit 100`.trim();}exportfunctionextractCode(original: string){// remove URLsconsturlRegex=newRegExp("\\b((https?|ftp|file):\\/\\/|www\\.)[-A-Z0-9+&@#\\/%?=~_|$!:,.;]*[A-Z0-9+&@#\\/%=~_|$]","ig");letmessage=original.replaceAll(urlRegex,"");if(message.trim()==="")return"";letm;letcode;// Look for specific patterns firstif((m=/^(\d{4,8})(\sisyour.*code)/.exec(message))!==null){// 4-8 digits followed by "is your [...] code"// examples:// "2773 is your Microsoft account verification code"code=m[1];}elseif((m=/(code\s*:|is\s*:|码|usecode|autoriza(?:ca|çã)o\s*:|c(?:o|ó)digo\s*:)\s*(\w{4,8})($|\s|\\R|\t|\b|\.|,)/i.exec(message))!==null){// "code:" OR "is:" OR "use code", optional whitespace, then 4-8 consecutive alphanumeric characters// examples:// "Your Airbnb verification code is: 1234."// "Your verification code is: 1234, use it to log in"// "Here is your authorization code:9384"// "【抖音】验证码9316,用于手机验证"// "Your healow verification code is : 7579."// "TRUSTED LOCATION PASSCODE: mifsuc"// "Código de Autorização: 12345678"code=m[2];}else{// more generic, brute force patterns// remove phone numbers// we couldn't do this before, because some auth codes resemble text shortcodes, which would be filtered by this regexconstphoneRegex=newRegExp(// https://stackoverflow.com/a/123666/(?:(?:\+?1\s*(?:[.-]\s*)?)?(?:\(\s*([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9])\s*\)|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\s*(?:[.-]\s*)?)?([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2})\s*(?:[.-]\s*)?([0-9]{4})(?:\s*(?:#|x\.?|ext\.?|extension)\s*(\d+))?/,"ig");constoriginalMessage=message;message=message.replaceAll(phoneRegex,"");if((m=/(^|\s|\\R|\t|\b|G-|:)(\d{5,8})($|\s|\\R|\t|\b|\.|,)/.exec(message))!==null){// 5-8 consecutive digits// examples:// "您的验证码是 199035,10分钟内有效,请勿泄露"// "登录验证码:627823,您正在尝试【登录】,10分钟内有效"// "【赛验】验证码 54538"// "Enter this code to log in:59678."// "G-315643 is your Google verification code"// "Enter the code 765432, and then click the button to log in."// "Your code is 45678!"// "Your code is:98765!"code=m[2];}elseif((m=/\b(?=[A-Z]*[0-9])(?=[0-9]*[A-Z])[0-9A-Z]{3,8}\b/.exec(message))!==null){// 3-8 character uppercase alphanumeric string, containing at least one letter and one number// examples:// "5WGU8G"// "Your code is: 5WGU8G"// "CWGUG8"// "CWGUG8 is your code"// "7645W453"code=m[0];}elseif((m=/(^|code:|is:|\b)\s*(\d{3})-(\d{3})($|\s|\\R|\t|\b|\.|,)/i.exec(message))!==null){// line beginning OR "code:" OR "is:" OR word boundary, optional whitespace, 3 consecutive digits, a hyphen, then 3 consecutive digits// but NOT a phone number (###-###-####)// examples:// "123-456"// "Your Stripe verification code is: 719-839."// and make sure it isn't a phone number// doesn't match: <first digits>-<second digits>-<4 consecutive digits>constfirst=m[2];constsecond=m[3];code=`${first}${second}`;}elseif((m=/(code|is):?\s*(\d{3,8})($|\s|\\R|\t|\b|\.|,)/i.exec(originalMessage))!==null){// "code" OR "is" followed by an optional ":" + optional whitespace, then 3-8 consecutive digits// examples:// "Please enter code 548 on Zocdoc."code=m[2];}else{// console.log("no code found in message");}}returncode;}
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
Screenshot-2024-11-26T10.18.44.mp4
Open messages-2fa in Script Kit
Beta Was this translation helpful? Give feedback.
All reactions