How Do I Execute DropBox Copy Public Link? (now Copy Dropbox Link)

I'm building a KM macro for SnagIT that results in showing the image file in Finder.
###I need to execute the DropBox context menu "Copy Public Link".
I've searched everywhere and can't find a way to do this.
I thought about assigning a shortcut key to "Copy Public Link", but I don't see it exposed anywhere.

To do it manually:
Select the file in the Finder
Right-click on the file and select "Copy Public Link"

EDIT: Tue, Aug 4, 2015 at 4:37 PM

Also, is there a better way to pause KM until the Save As window/action has completed?
I thought I had it with the "Pause until Save button does not exist", but this seems to fail in some (unknown) cases.

Any ideas/suggestions?
TIA.

###Here's my macro:

1 Like

There are two ways to do it.

If it is a public folder, then I believe you can just apply a bit of string manipulation to create a suitable URL for the file.

Examples: Dropbox public link (AppleScript) and Dropbox Magic: Use AppleScript to Automatically Generate a Public URL

Alternatively, it looks like you can use the Dropbox API with a generated token as described here:
How to get Dropbox Shared Link URL via AppleScript or other scripting language?.

I believe the Dropbox public folder method has been removed from the Dropbox API. You have to use the API to generate the proper url. Therefore, only the second method you have above will currently work.

Thanks, Peter. Neither of those articles showed up in my seaches.

Thanks for your feedback.

Let me ask you guys: Is there a way to use a completely different approach?
What about using AppleScript to have the Finder execute the "Copy Public Link" context menu item? Is this possible? If so, how?

Many thanks for all of your ideas.

Its possible if you can get your mouse over the icon. It's possible the Finder has enough AppleScript support to allow this, but it is well beyond what I would try to do with AppleScript.

Plus it would be a lot of UI interaction. The script solution, while tedious to set up, will produce a much better end result I suspect.

Hey JM,

Well.. It's possible but a PIA.

Scripting the contextual-menu with System Events is broken in list-view but seems to work in icon-view. Nevertheless if you want to install the Dropbox toolbar-button it's pretty easy.

This won't be quite right, because the parameters depend upon where you put the Dropbox button in the toolbar. (This is tested on 10.10.4 β€” different versions of OSX can have subtle or not so subtle variations.)

tell application "System Events"
  tell application process "Finder"
    set frontWin to (first window whose role is "AXWindow")
    tell frontWin
      tell menu button 1 of group 6 of toolbar 1
        click
        tell menu 1
          click menu item "Copy Public Link"
        end tell
      end tell
    end tell
  end tell
end tell

However it's pretty pointless to use Dropbox's UI for this, because the result can be easily duplicated.

[EDIT: DropBox broke the ability to create a public link this way in late 2017 β€” ccs]

Here's what a public link copied from the Finder using Copy-Public-Link looks like (I've changed the user-number):

https://dl.dropboxusercontent.com/u/00000000/Developers/Stairways_Software/Keyboard%20Maestro%20ScreenShot%20Issue.mp4

Here's what a link from the Dropbox site looks like:

https://www.dropbox.com/sc/7x9xe87mjhedxwd/AAAHb_1v_IfHSUYcOyfph19va

So, if you're giving the link to someone else the scripted method is going to be better, because it anonymizes the link just like the latter example.

If you don't care who sees your static user number the job is simple to do with basic AppleScript.

You replace dbBaseURL with your address by getting copying a public link once with the Dropbox UI, and you're ready to go to town.

------------------------------------------------------------
# Auth: Christopher Stone
# dCre: 2013/04/29 23:22
# dMod: 2015/08/05 23:58
# Appl: Finder & Script-Runner
# Task: Copy Public Dropbox URLs from selected files to the Clipboard.
# Libs: None
# Tags: @Applescript, @Dropbox, @Public, @URL, @Clipboard
# Test: Mavericks, Yosemite.
------------------------------------------------------------

try
  
  set dbBaseURL to "https://dl.dropboxusercontent.com/u/00000000/" # User must supply.
  set dbPubStr to ((path to home folder as text) & "Dropbox:Public:")
  set AppleScript's text item delimiters to "/Dropbox/Public/"
  
  tell application "Finder"
    set _sel to selection as alias list
    
    if _sel β‰  {} then
      set hfsPath to item 1 of _sel as text
      
      if (hfsPath does not contain dbPubStr) or (hfsPath = dbPubStr) then
        error "Selection not in Public Dropbox folder."
      end if
      
      repeat with i in _sel
        set contents of i to (dbBaseURL & (text item 2 of (get i's URL)))
      end repeat
      
      set _sel to joinList(_sel, linefeed) of me & linefeed
      set the clipboard to _sel
      
    end if
    
  end tell
  
on error e number n
  stdErr(e, n, true, true) of me
end try

------------------------------------------------------------
on joinList(_list, _delimiter)
  set {oldTIDS, AppleScript's text item delimiters} to {AppleScript's text item delimiters, _delimiter}
  set joinedList to _list as string
  set AppleScript's text item delimiters to oldTIDS
  return joinedList
end joinList
------------------------------------------------------------
on stdErr(e, n, beepFlag, ddFlag)
  set e to e & return & return & "Num: " & n
  if beepFlag = true then
    beep
  end if
  if ddFlag = true then
    tell me
      set dDlg to display dialog e with title "ERROR!" buttons {"Cancel", "Copy", "OK"} default button "OK"
    end tell
    if button returned of dDlg = "Copy" then set the clipboard to e
  else
    return e
  end if
end stdErr
------------------------------------------------------------

-Chris

Chris, you are the champion of champions! :sunglasses:

Once again, you saved the day!

Your last script worked perfect! Well, almost perfect. My DropBox folder is setup in /Users/Shared/, not in Home. So the error msg threw me for a loop at first. :dizzy_face:

I made a couple of small changes, mostly for my benefit, the most important of which is changing the error msg (last line in the below code). My changes are noted by "##JM##".

You should publish your code at MacScripters so other AppleScript coders can easily find it.

set strDropBoxAcctNum to "1234567" -- Your DropBox Acct#  ##JM##

set dbBaseURL to "https://dl.dropboxusercontent.com/u/" & strDropBoxAcctNum & "/"  ##JM## 

--set dbPubStr to ((path to home folder as text) & "Dropbox:Public:")
set dbPubStr to ((path to users folder as text) & "Shared:Dropbox:Public:")  ##JM##

set AppleScript's text item delimiters to "/Dropbox/Public/"

tell application "Finder"
  set _sel to selection as alias list
  
  if _sel β‰  {} then
    set hfsPath to item 1 of _sel as text
    
    if (hfsPath does not contain dbPubStr) or (hfsPath = dbPubStr) then
      error "Selected file is not in the designated Public Folder:" & return & dbPubStr  ##JM##
    end if

If you want to do this and do not want to use your Dropbox β€œPublic” folder, the best way to be able to script it reliably is to set up https://github.com/andreafabrizi/Dropbox-Uploader on your system.

It is a bash script which requires about 10 minutes of initial setup, but once you have done that, it gives you a lot of functionality to interact with your Dropbox account via scripting (it does more than its name implies).

For example, if I had a file β€œfoo” in a folder β€œtxt” inside my Dropbox folder, I would do this to get to the share link:

dropbox_uploader.sh  share  txt/foo.txt | awk '{print $NF}'

No GUI scripting required. The Dropbox.app doesn’t even have to be running!

1 Like

Thanks for posting another solution.

The AppleScript solution posted by @ccstone just above is working really well for me, and also doesn't require GUI scripting nor the DB app.

That’s a much easier solution, assuming that you are OK using your
regular β€œPublic” folder on Dropbox.

I think that this the best approach in most cases.
It is easy to see and understand that EVERYTHING I put in my DB Public folder is, well, public.

While it may be convenient to have individual files that are public buried within your folder hierarchy, I think it can also be dangerous because it is hard to monitor.

I'm trying for a simple, non-script approach. I always put my shared documents in the same public folder and I'm ok with people seeing my static address.

The workflow I want is:

  1. Select file
  2. Copy file name and extension i.e. xxxxxxx.pdf
  3. append file name to **https://dl.dropboxusercontent.com/u/716207/share/**xxxxxxx.pdf to the clipboard
  4. Paste where needed

My attempted solution

How can I get the name and extension of the selected file on to the clipboard? I'm trying this with out luck:

Any tips on how to get the selected file name on to the clipboard?

I then need to figure out how to append it to my path, "https://dl.dropboxusercontent.com/u/716207/share/append-here"

Thanks for any help.

Still in my novitiate, I recently had to push my sled through this bog. This should both solve your problem, and indicate some things worth learning:
Add specified path to file name and save to system clipboard.kmmacros (3.8 KB)

A few things I didn't know that muddied my progress:

  • "path", in KM, is the entire path including what I thought of as the filename.
  • "parent path" in KM is the path not including what I thought of as the file name.
  • "base name" in KM is what I thought of as the file name not including what I thought of as the file name extension.
  • "extension" in KM is what I thought of as the file name extension.
  • All of the above can be easily saved to variables
  • Variable can be easily concatenated.
  • Variables can be easily searched and replaced.
  • RegEx is very helpful.
  • For good reasons, don't use the literal text "variable" in your KM variable's names.

HTH.

β€”Kirby.

2 Likes

@Kirby_Krieger Thanks not only helping create a working copy for me, but for helping me understand how things work. Seeing how you put it together and your notes sped up my learning. I think you are ready to move out of the novitiate.

2 Likes

==UPDATED==: 2019-06-20 20:08 GMT-5

  • Cleanup thread
  • Upload revised Script, Ver 2.5.3
    • Add file path verification
    • Revise to with with PF8
  • Now works with both Finder & PathFinder (PF8).

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Chris, unfortunately that is no longer true, ==as of 2017-09-01, Dropbox has eliminated use of the Public Folder==. And now, the "Copy Dropbox Link" does not seem to be able to be automated without UI scripting, because the root URL changes for every file. OTOH, if you know a better way -- I'm all for it. :wink:

So, based on your UI script, ==I've written a new one that uses the Dropbox button/menu item in the Finder.== Things seem to have changed since your script two years ago, and the Dropbox group is no longer in the same location. My script does not depend on group location.

AppleScript To Get New Dropbox Public Link (post 2017-09-01)

(this is NOT the same as the old Dropbox Public Folder link).

β€’ Since 2017-09-01 public links have been disabled for all DropBox users
β€’ So the prior methods of getting a Public Link not longer work.
β€’ This is based on the DropBox UI in the Finder Toolbar.

property ptyScriptName : "Get Dropbox Public Link of Selected Finder Item"
property ptyScriptVer : "2.5.3" -- CHG revealInFinder Handler for PF8
property ptyScriptDate : "2019-06-20"
property ptyScriptAuthor : "JMichaelTX" -- based on script by @ccstone

(*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PURPOSE:
  β€’ Get the Public Link for any DropBox item currently selected in the Finder
  β€’ Since  2017-09-01 public links have been disabled for all DropBox users
  β€’ So the prior methods of getting a Public Link not longer work.
  β€’ This is based on the DropBox UI in the Finder Toolbar.
  
RETURNS:
  β€’ URL of Public Dropbox item to the Clipboard
  β€’ URL is set with "dl=1" to auto-download 
      UNLESS the file kind contains a keyword in the property viewKWList; 
      THEN it is set to "dl=0"
  β€’ Script returns Markdown link of same

REQUIRED:
  1.  macOS 10.11.6+
  2.  Mac Applications
      β€’ Dropbox

REF:  The following were used in some way in the writing of this script.

  1.  https://www.dropbox.com/help/files-folders/public-folder
  2. Based on script by Chris Stone (@ccstone)
      https://forum.keyboardmaestro.com/t/how-do-i-execute-dropbox-copy-public-link/1772/7
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*)
use framework "Foundation"
use scripting additions

property LF : linefeed

try
  --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  set testPF to false
  
  set frontApp to path to frontmost application as text -- use for dialogs
  
  if ((frontApp contains "Path Finder") or testPF) then
    --- Reveal Item Selected in PF in the Finder ---
    -- (DropBox Menu works only in Finder)
    set fileAlias to revealPFItemInFinder()
  end if
  
  set maxWait to 2.0 -- sec
  set delayInt to 1.0E-3
  set elapsedTime to 0.0
  set cbTest to "WAITING"
  set the clipboard to cbTest
  
  tell application "Finder" to set finderSelectionList to selection as alias list
  if length of finderSelectionList = 0 then error "No files were selected in the Finder!"
  set fileAlias to item 1 of finderSelectionList
  
  set filePath to POSIX path of fileAlias
  if (filePath does not contain "/Dropbox/") then
    error "fItem MUST in the the Dropbox folders.  Invalid path:" & linefeed & filePath
  end if
  
  set oFile to info for fileAlias
  tell oFile
    set fileName to name
    set fileSize to size
    set fileKind to kind
  end tell
  
  set fileSize to (current application's NSByteCountFormatter's stringFromByteCount:fileSize countStyle:(current application's NSByteCountFormatterCountStyleDecimal)) as text
  
  tell application "System Events"
    tell application process "Finder"
      set frontWin to (first window whose role is "AXWindow")
      tell frontWin
        set dbGrp to first group of first toolbar whose help contains "Dropbox"
        
        # Alternate Method #
        (*
       IF you prefer speed over reliability, then use next statement instead of prior.
       Position of the Dropbox Group/Menu may vary by macOS and how you have configured the Finder.
        (uses < 0.01 sec less time in my testing, but YMMV)
        
      set dbGrp to group 5 of toolbar 1
    *)
        
        tell dbGrp
          tell menu button 1
            perform action "AXPress"
            
            tell menu 1
              
              --- Delay Until Menu Item Shows ---
              repeat until (exists menu item "Copy Dropbox Link")
                delay delayInt -- short delay needed to show menu
                set elapsedTime to elapsedTime + delayInt
                if (elapsedTime > maxWait) then error ("Max Time Exceeded Waiting for Dropbox Menu to show: " & elapsedTime)
              end repeat
              
              click menu item "Copy Dropbox Link" -- to the Clipboard
            end tell
          end tell -- menu button 1
        end tell -- dbGrp
        
      end tell -- frontWin
    end tell
  end tell
  
  --- Delay Until Link is on Clipboard ---
  (*
NOTE: You wouldn't think this is necessary, but in my testing
 I found it could take almost 1 sec for the Dropbox Mac 
 service to put the link on the clipboard.
*)
  set elapsedTime to 0.0
  set dbLink to "TBD"
  repeat until (dbLink starts with "http")
    delay delayInt -- short delay needed for DropBox Service
    try
      set dbLink to the clipboard as text
    on error
      set dbLink to "TBD"
    end try
    set elapsedTime to elapsedTime + delayInt
    if (elapsedTime > maxWait) then error ("Max Time Exceeded Waiting for Dropbox Link to be put on Clipboard: " & elapsedTime)
  end repeat
  
  
  if (my isFileTypeAVI(fileAlias) is false) then
    --- Change the DropBox Link to Auto-Download ---
    set dbLink to Β«event SATIRPLlΒ» "dl=0" given Β«class by  Β»:"dl=1", Β«class $in Β»:dbLink
    set mdTextPrefix to "Download: "
    
  else --- File Type is either Audio, Video, or Image ---
    set mdTextPrefix to "View/Download: "
  end if
  
  set the clipboard to dbLink as text
  
  --- Build & Return Markdown Link ---
  set mdLink to "[" & mdTextPrefix & fileName & " (" & fileSize & ")](" & dbLink & ")"
  set scriptResults to mdLink
  
  --~~~~~~~~~~~~~ END TRY ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  
on error errMsg number errNum
  
  if errNum = -128 then ## User Canceled
    set errMsg to "[USER_CANCELED]"
  end if
  
  set scriptResults to "[ERROR]" & return & errMsg & return & return Β¬
    & "SCRIPT: " & ptyScriptName & "   Ver: " & ptyScriptVer & return Β¬
    & "Error Number: " & errNum
end try
--~~~~~~~~~~~~~~~~END ON ERROR ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


return scriptResults

--~~~~~~~~~~~~~~~~~~ END OF MAIN SCRIPT ~~~~~~~~~~~~~~~~~

--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
on isFileTypeAVI(pFileAlias)
  --–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
  (*  VER: 1.0    2017-12-25
    PURPOSE:  Determine if file is any of these top level types:
                 Audio, Video (Movie), Image, PDF
    PARAMETERS:
      β€’ pFileAlias    | alias  | File to be evaluated for file type
    RETURNS:  true/false
    AUTHOR:  JMichaelTX (refactor of script by Shane Stanley)
  ## REQUIRES:  use framework "Foundation"
    REF:  @ShaneStanley, Late Night Software Forum, script
            http://forum.latenightsw.com/t/handler-to-determine-if-text-contains-item-in-list/893/2
  --–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
  *)
  tell current application's NSWorkspace's sharedWorkspace()
    set theUTI to its typeOfFile:(POSIX path of pFileAlias) |error|:(missing value)
    return (its |type|:theUTI conformsToType:"public.movie") Β¬
      or (its |type|:theUTI conformsToType:"public.audio") Β¬
      or (its |type|:theUTI conformsToType:"public.image") Β¬
      or (its |type|:theUTI conformsToType:"com.adobe.pdf")
  end tell
end isFileTypeAVI
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
on doesTextContainAnyListItem(pText, pList)
  --–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
  (*  VER: 1.0    2017-12-23
    PURPOSE:  Determine if string (text) contains any item in the List
    PARAMETERS:
      β€’ pText    |  text  | Text to search
      β€’ pList    | list  | List of text items to search for
       
    RETURNS:  true    IF any item in the list was found in the text
                false  IF NOT
                
    AUTHOR:  JMichaelTX
  --–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
  *)
  set foundItemBool to false
  repeat with aItem in pList
    if pText contains (contents of aItem) then
      set foundItemBool to true
      exit repeat
    end if
  end repeat
  return foundItemBool
end doesTextContainAnyListItem
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
on revealPFItemInFinder()
  --–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
  (*  VER: 2.1    2018-03-19
    PURPOSE:  Reveal Item in Finder that is Selected in Path Finder
         
    RETURNS:  alias of item selected in both Finder and Path Finder
                  
    AUTHOR:  JMichaelTX
  --–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
  *)
  local finWinName, pfWinName, fileList, itemPath, oItem
  
  --- GET THE ITEM SELECTED IN PATH FINDER ---
  
  tell application "Path Finder"
    set fileList to (get selection)
    if ((fileList is missing value) or ((count of fileList) β‰  1)) then error ("You must select only ONE file in Path Finder.")
    set oItem to item 1 of fileList
    set itemPath to POSIX path of oItem
    set pfWinName to name of container of oItem
  end tell
  
  set itemAlias to alias POSIX file itemPath
  
  --- REVEAL SAME ITEM IN FINDER ---
  
  tell application "Finder"
    activate -- to make sure reveal will be in frontmost window
    reveal itemAlias
    
    --- Now Wait for New Finder Window with Same Name as Path Finder ---
    
    tell application "System Events" to set currentAppName to name of first application process whose frontmost is true
    
    
    set maxWaitTime to 3.0
    set delayTime to 0.1
    set waitTime to 0
    
    repeat while currentAppName β‰  "Finder"
      delay delayTime
      tell application "System Events" to set currentAppName to name of first application process whose frontmost is true
      
      set waitTime to waitTime + delayTime
      if (waitTime > maxWaitTime) then error "Max wait time of " & maxWaitTime & " exceeded waiting for Finder Window of " & pfWinName
    end repeat
    
  end tell
  
  return itemAlias
  
end revealPFItemInFinder

1 Like

Hey JM,

The only other way I know of offhand is the Dropbox-Uploader shell script TJ posted above.

As far as I can see that project on GitHub is still active and working.

Unfortunately that critter is complex enough that I think mere mortals will walk on by...

I haven't bothered with it myself. However β€” since my old method has been dusted by Dropbox I may just give it a try.

-Chris

I think I fall into that category.

For my purposes, the new UI script seems to be working very well, very reliable. Of course, like all UI scripts, it is subject to breaking if changes are made to the Finder UI and/or the Dropbox UI. I tried to build in some future-proofing by searching for a UI group that contains "Dropbox" rather than hard-coding the group position.

For scripts/macros posted in this forum, I prefer to not use external software that requires download/install (Satimage.osax is an exception to this).

Your script works great @JMichaelTX ! Just put it in a KM Macro to email a dropbox link. Thanks!

1 Like

Just an FYI to anyone who has used dropbox_uploder.sh:

After a long time idle, the developer apparently made some updates a few months ago… but didn't increment the version number. :man_facepalming:

So… I just deleted my old version and installed the new version, and it fixed a few things that had broken. If you tried it and it didn't work for you, you might want to make sure you're using the most up-to-date version, and don't rely solely on the version number for that!

Just updated above post/script.