Applescript to open .url files on OS X Firefox - macos

For reasons that only the developers can understand, Firefox will create and open .url files on Windows and .webloc files on OS X but won't allow the Windows version of Firefox to open .webloc files or the OS X version of Firefox to open .url files. (.url files open in Safari but that's not good enough for reasons that aren't worth going into here.) As part of my efforts to use either filetype on either system, I'm writing an applescript to open .url files on OS X Firefox.
on open the_droppings
set filePath to the_droppings
set fp to open for access filePath
set fileContents to read fp
close access fp
set secondLine to paragraph 2 of fileContents
set tid to AppleScript's text item delimiters
set AppleScript's text item delimiters to "="
set URLstring to last text item of secondLine
set AppleScript's text item delimiters to tid
tell application "Firefox"
activate
OpenURL URLstring
end tell
end open
I thought this would work but in the 3rd to last line it says "Expected end of line, etc. but found identifier." Why is this?
EDIT sakra's answer below mostly works but breaks on urls containing "=" such as: http://example.com?foo=a&bar=z

Firefox does not seem to feature an AppleScript dictionary at all. Therefore the term OpenURL within the tell app "Firefox" statement is interpreted as an AppleScript identifier and not as an AppleScript command. Two AppleScript identifiers in a row result in a syntax error.
As a work-around you can use the shell command open in combination with the standard AppleScript command do shell script:
on open the_droppings
set filePath to the_droppings
set fileContents to read filePath
set theOffset to offset of "URL=" in fileContents
set URLstring to text (theOffset + 4) through -1 of fileContents
do shell script "/usr/bin/open -a Firefox.app " & quoted form of URLstring
end open

EDIT: download my script in an app here: http://www.mediafire.com/?v77bv9gl9e7oj40
This works even better:
on open the_droppings
set filePath to the_droppings
set fileContents to read filePath
set theOffsetA to offset of "URL=" in fileContents
set theOffsetB to offset of "IDList=" in fileContents
set URLstring to text (theOffsetA + 4) through (theOffsetB - 3) of fileContents
do shell script "/usr/bin/open -a Firefox.app " & quoted form of URLstring
end open
It reads the URL= line to the next line ( IDList ) minus 3 steps ( to ignore the \r\n ) and sends it to firefox. Works like a charm for me.
I however have seen url files with weird layout ( example: http://forums.mozillazine.org/viewtopic.php?p=2619487 ), which I'm not sure of if it would work there. But I checked a lot of my url files and they dont have that, so atleast it works fine for me. Let me know if you run into troubles with this script. For the moment I'm setting it as default app to open URL files, instead of Safari!
To be able of opening url files with an applescript file, it needs to have the proper doctypes and identifier set in its plist, like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleAllowMixedLocalizations</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>url</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeName</key>
<string>URL File</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>URL</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
</array>
<key>CFBundleExecutable</key>
<string>droplet</string>
<key>CFBundleIdentifier</key>
<string>filehandler.url.mozilla.firefox</string>
<key>CFBundleIconFile</key>
<string>droplet</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>FirefoxURLHandler</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>dplt</string>
<key>LSMinimumSystemVersionByArchitecture</key>
<dict>
<key>x86_64</key>
<string>10.6</string>
</dict>
</dict>
</plist>

I know it's not apple script, but I did this to open them on Linux, but it has the problem that if and when the terminal closes, it kills the browser. I opened another question about this, but this may help.
#!/bin/bash
#bash -c "cat $1 | grep URL | cut -d'=' -f2 | xargs firefox &"
echo OpenWinURL in firefox
echo Closing this window will close your firefox.
echo Try opening firefox before opening a OpenWinURL
#echo Copyright 2021 Aaron Peterson GPL V2 or later
#echo The ampersand doesn't work after firefox
#echo "$1"
#
jobs -l
cat "$1" | grep -m 1 URL= | cut -d'=' -f2- | xargs -0 -i firefox {} #&
jobs -l
disown -h -a
jobs -l
#read -n 1 -p "Input Selection:" mainmenuinput
#echo testing
#wait 1000
#
#| head -n 1
#| cut -d'=' -f2 | xargs firefox &

Related

Run a Terminal command on open location AppleScript

I want to run a command in terminal when a custom url is called.
Example :
I want to open a terminal and run echo "hello myapp://hello" when someone opens myapp://hello in browser or when some one executes open "myapp://hello"
I am new to apple script so I searched a lot but was unable to conclude with a working code snippet.
I tried :
on open location this_URL
display alert this_URL
tell application "Terminal"
reopen
do script "echo 'hello " & this_URL & "'"
activate
end tell
end open location
Updated the Info.plist as:
.....
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>myapp</string>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string>
</array>
</dict>
</array>
....
This code just opens a terminal but doesn't runs the echo command.
Standalone parts of code :
on open location this_URL
display alert this_URL
end open location
and
tell application "Terminal"
reopen
do script "echo 'hello " & this_URL & "'"
activate
end tell
Works perfectly.
But the combination doesn't work....
Please tell me some workaround.
Thanks in advance
I think this is problem with authorization.
I don't know why but when we add CFBundleURLTypes in plist then macOS prevents us to send events to terminal.
So here is a workaround :
Make 2 apps instead of one as follows
App 1 : url handler
So this will handle the incoming url copy it to clipboard and initiate the 2nd app.
Its applescript will be as follows :
on open location this_URL
set the clipboard to this_URL
tell application "/path/to/app2.app" to activate
end open location
Add CFBundleURLTypes to its plist
App 2 : Terminal handler
It will read the url from clipboard and then run it on terminal.
Its applescript will be as follows :
tell application "Terminal"
set this_URL to ( the clipboard as text )
do script "echo 'hello " & this_URL & "'"
activate
end tell
set the clipboard to ""

How to rename files as they are added to a folder?

I created an Automator workflow that renames iOS Simulator Screenshots as they are added to the Desktop folder. But for the workflow to work, I need to run it myself manually. Is there a way to make the workflow watches the Desktop folder continuously and renames screenshots as they are added like a background service?
This is the workflow I created :
Screenshot of the Workflow
I find automator to be a a bit clunky at times, so I suggest you do this with a standard AppleScript Folder Action. Copy the following script into Script Editor.app, modify the prefixes as needed, then save it in ~/Library/Scripts/Folder Action Scripts.
property old_prefix : "Simulator Screen Shot - "
property new_prefix : "some text "
on adding folder items to this_folder after receiving these_items
repeat with this_item in these_items
set item_path to POSIX path of this_item
tell application "System Events"
set this_disk_item to disk item item_path
tell this_disk_item
if its name begins with old_prefix then
set its_extention to its name extension
set its_name to its displayed name
set new_file_name to new_prefix & (text ((length of old_prefix) + 1) through -1 of its_name)
if new_file_name ≠ its displayed name and new_file_name ≠ "" then
set name of this_disk_item to new_file_name & "." & its_extention
end if
end if
end tell
end tell
end repeat
end adding folder items to
Use Spotlight to open the app "Folder Actions Setup", add your desktop as a folder on the left side, and on the right, select and attach the script you just saved to that folder. It should 'just work'.
The way I would do it is to use an application called launchd to open the automator script how ever often you need (e.g. every few seconds). This website describes how to set it up. Basically you have to first save your automator script as an application into a certain folder (e.g. Documents), then write a short xml script which tells launchd which file to open and how often to do it.
Below is a sample script:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.NAME.test</string>
<key>Program</key>
<string>/Users/USERNAME/Documents/test.app/Contents/MacOS/Application Stub</string>
<key>StartInterval</key>
<integer>5</integer>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
Open a new "Plain text" TextEdit document and paste in the above. Replace the Label (com.NAME.test) with whatever you want; I usually just put my name in there, followed by the name of the script. Next change the line under Program to the location of your ".app" file you saved earlier, remembering to change USERNAME to your username. Keep in mind that the /Contents/MacOS/Application Stub needs to be right after the ".app" part so that the script will start your application. Then change the line under StartInterval to the number of seconds you want the script to wait before it runs again.
After you're done editing the script, save it to "/Users/USERNAME/Library/LaunchAgents/com.NAME.test.plist," of course changing USERNAME to your username and com.NAME.test to the Label used in the xml script. If it asks if you want to save it with the ".plist" extension, choose yes. Once the file's saved, open up Terminal (/Applications/Utilities/Terminal.app) and type in the command launchctl load /Users/USERNAME/Library/LaunchAgents/com.NAME.test.plist, changing the file name to the filepath of your ".plist" file. Use unload instead of load to stop the script from running.
For me a gear icon kept appearing in the menu bar every time the script ran, so I found on this and this website that you can stop it by adding "Run Shell Script" to the very top of your Automator script, then typing in the box killall ScriptMonitor || true.

Need help reprogramming a short batch program to macOS bash

I've written a batch program (long time ago now) to backup my data from one external drive to another. It scans the drive, makes a directory file of all the folders in it, and counts the number of lines (and thus folders). From there it reads from that file, one line at a time, and copies the contents of each folder in the list in the directory file to the other drive, only copying what was new or modified from the last time it copied, and if something was on the backup drive, that had been deleted from the source drive, it left it there. It just kept adding, not deleting. This was intentional, don't worry.
Here is the script:
#echo off
set /p Drive=The Archive Drive Letter:
cls
set /p Drive2=The Archive II Drive Letter:
dir %Drive%:\ /B >directory
#setlocal enableextensions enabledelayedexpansion
set lines=0
:the
set location=directory
set /a "lines = lines + 1"
set curr=1
for /F "delims=" %%a in ('type %location%') do (
for %%b in (!lines!) do (
if !curr!==%%b set foldername=%%a
)
set /a "curr = curr + 1"
)
xcopy "%drive%:\%foldername%" "%Drive2%:\THE ARCHIVE Backup\%foldername%\" /S /M /Y
timeout -t 2
goto :the
endlocal
I need help with making an identical program to run under MacOS bash.
I have experimented with the equivalent commands and researched how things are done in bash, but I have very limited experience with using MacOS.
I appreciate that some things are done differently under bash, such as drive naming. In my batch script above, I have a call for a user variable to confirm the drive letters, but that was only a failsafe in case drive letters change (as they do). However under MacOS drives are called via names, which I won't be changing so that part of the code I'm happy to remove.
In my specific case,
The source drive is located at "/Volumes/The ARCHIVE"
The destination drive is located at "/Volumes/The ARCHIVE II"
Any help is much appreciated, and I'm happy to take on any ideas that may improve my somewhat messy approach to things.
Thanks!
Edit:
I ran the command (with the -n switch), and after having some difficulties with the “bad interpreter” error, which I’ve solved, I’m returned a list of all my files on the source drive. I assume this will return to none after one backup, and only subsequent changes on the source drive??
Also, I’m returned a line that says “total size is 528045001932” I assume this is in bytes, and therefore when converted to gigabytes comes to 528GB, or 491GB (depends on 1024 vs 1000 bytes per kilobyte). Only thing is, my total amount of data on the source drive is more than that. Does that mean that rsync has missed some data, or has it skipped some of it because it found matches on the destination drive?
Just use rsync. You could set a cron job to run a bash script that rsync's one directory to another.
just save the following as something like copier.sh
#!/bin/bash
rsync -rv /Volumes/ARCH /Volumes/ARCH2
then add the file to crontab.
Check the man pages for rsync and crontab if you need help
EDIT:
I forget MacOS prefers you to use launchd now. You should read up on how to use launchd but I'll give you an example that may or may not work.
Create a plist file called something like com.directoryCopier.plist and place it in the /Library/LaunchDaemons directory. The file should look something like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.directoryCopier</string>
<key>ProgramArguments</key>
<array>
<string>/Users/Path/To/copier.sh</string>
</array>
<key>StartInterval</key>
<integer>86400</integer>
<key>StandardErrorPath</key>
<string>/tmp/copier.err</string>
<key>StandardOutPath</key>
<string>/tmp/copier.out</string>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
Start the service by rebooting or by entering the command
sudo launchctl load /Library/LaunchDaemons/com.directoryCopier.plist
You can read more here
https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html
I probably left some stuff out but I'm sure someone will correct me.
Good luck

Run Python Script at OS X Startup

I am very new to python as well as MAC OSX. For my academic project I need to download a bunch of tweets from twitter using twitter streaming API. I need to download atleast 5000000 tweets. So I have written a python script and placed it in start-up. "System Preference -> Users and Groups -> Login items" and added my script there. But I see that the script is not executed when I login to the system ! Please help me resolve this issue.
Adapt the following accordingly, name it something like myscript_launcher.plist, and put it in either one of three locations: /System/Library/LaunchAgents, /System/Library/LaunchDaemons, /Users/<username>/Library/LaunchAgents.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>my.python.script.name</string>
<key>ProgramArguments</key>
<array>
<string>/path/to/python</string>
<string>/path/to/python/script.py</string>
</array>
<key>StandardErrorPath</key>
<string>/var/log/python_script.error</string>
<key>KeepAlive</key>
<true/>
</dict>
</plist>
Also, let's assume you put the plist file in ~/Library/LaunchAgents. You can start and stop it with the launchctl. To start, use launchctl load ~/Library/LaunchAgents/myscript_launcher.plist. To stop it, do the same but use the unload argument
You need to create a shell file that launches your python code. Tell the shell script to start at log in.
example
#!/bin/bash
python username/Desktop/startupscripts/file.py
save the file with the .sh extension.
add the .sh file to
"System Preference -> Users and Groups -> Login items", the .sh script will call the python file.
This is what you should have in the shell file. I'm assume this is the path to the file, if it isn't modify it.
#!/bin/bash
python /Users/username/moviebuzz-api/flask/bin/streaming_movies.py
nothing else.
Here's the full solution I am using on Mojave:
Plist: ~/Library/LaunchAgents/play.with.mpv.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Disabled</key>
<false/>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/Users/e/Library/Python/3.7/bin:/usr/local/bin</string>
</dict>
<key>KeepAlive</key>
<true/>
<key>Label</key>
<string>play.with.mpv</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/python3</string>
<string>/Users/e/Library/Python/3.7/bin/play-with-mpv</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>StandardErrorPath</key>
<string>/tmp/play.with.mpv.stderr</string>
<key>StandardOutPath</key>
<string>/tmp/play.with.mpv.stdout</string>
</dict>
</plist>
Mind the PATH to python3 - find it with which python3 and the play-with-mpv python script!
Load plist:
launchctl load ~/Library/LaunchAgents/play.with.mpv.plist
If your video is dropping frames as hell, create mpv config in ~/.config/mpv/mpv.conf and put there this:
video-sync=display-resample
if that do doesn't help, try this instead
opengl-early-flush=no
But I see that the script is not executed when I login to the system !
The problem is, .py files are usually opened by some text editor by default. In order to execute the script as Login Items, you need to make the script to be opened by Terminal.app (or anything execute the script) by default.
After that, you cat set the script as Login Items in the way you posted.
How to set Terminal.app as default:
Put a #! line on the top of the script:
#!/usr/bin/env python3
print("hello world")
Add execute permission to the script:
chmod u+x script.py
Change the file extension .py to .command (to associate the file with Terminal.app):
mv script.py script.command
At this point, you should be able to run the script by double clicking on Finder.
If you can not, try the following:
Right click on the script file on Finder.
Select Get Info
Click the dropdown of Open with: option.
Select Terminal.app
By the way, the above applies to not only python, but other scripts such as bash.
For example of bash, change !# like so:
#!/usr/bin/env bash

Run applescript in Automator

I need to start and stop a small server with automator but my knoledge is very limited. I can't manage to set the path where the file is and I don't know how to stop the server.
So far I have this:
on run
set r to display dialog "Start or stop the NINJAM server ?" buttons {"Stop", "Start"}
if button returned of r is "Start" then
#tell application "Terminal"
# activate
do shell script "cd \"/Applications/ MUSIC/ Utilities/Audio IP/NINJAM/NINJAM/NinjamOSXServer ./ninjamsrv Server.cfg\""
#end tell
else
do shell script "Stop"
end if
end run
Any help is really apprectated. Thanks in advance.
NOTE that I'm using my own path here -- I put the ninjam server folder in the top level of my Applications folder.
I had to create a 'term' file, which is a text file with this in it:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>WindowSettings</key>
<array>
<dict>
<key>ExecutionString</key>
<string>cd /Applications/NinjamOSXServer/;./ninjamsrv config.cfg</string>
</dict>
</array>
</dict>
</plist>
I saved this as LaunchNinjamSrvr.term and put it in the same folder as the ninjamsrvr. Then the script to use is:
set r to display dialog "Start or stop the NINJAM server ?" buttons {"Stop", "Start"}
if button returned of r is "Start" then
do shell script "open /Applications/NinjamOSXServer/LaunchNinjamSrvr.term"
else
do shell script "killall -INT -v ninjamsrv"
end if
[Occurs to me that I should give some explanation. Directly using the full path with the " config.cfg" parameter makes 'do shell script' choke. Splitting into two commands (but still using do shell script), like you see in the .term file, works to launch ninjamsrv, but makes the script editor (I use Smile) freeze. So that is (presumably -- I didn't want to test it by other means [script app, etc.]) a problem, and why I resorted to using the .term file. It used to be that you could, from the File menu in Terminal (as I recall), save a .term file directly, but that seems to have fallen by the way-side. So, at this point, I have a template that I use and just paste commands into the appropriate line. (But see http://discussions.apple.com/thread/3139585?start=0&tstart=0 -- wherein the technique of exporting Terminal Preference file is explained). I'm being a bit lazy in that the new form is .terminal, not .term ... anyway ...
So now all that is left is doing the actual AS script. 'open' is a basic command line command which is just like opening or double-clicking in the Finder. If, for some reason your file opens in the wrong app or doesn't open, you might need to map it to Terminal.app (in the get info window) and/or change the extension to the more up--to-date '.terminal'.
killall is like kill, designed to kill processes in various ways. I chose -INT because this is essentially like doing a control-c to interrupt the process.]

Resources