InsertLinks from Dropbox and YouTube

Ein Bekannter verschickt immer mal wieder Emails mit Info-Material an Interessenten und hat bisher die Dateien auch direkt an die entsprechende Email angehängt. Dabei entstanden schon einmal 20MB Pakete, die er durch seinen ländlichen DSL-Anschluss mühsam treiben musste. In Zeiten von DropBox und YouTube macht es aber da mehr Sinn, statt der Dateien einen Public-Link und statt Video-Dateien in Format-XY einen YouTube-Link zu verschicken, die Infos sind ja keine Staatsgeheimnisse. Zudem muss er keine übergroßen Emails verschicken und die Mailbox des Empfängers quillt nicht über.

Nur das einfügen dieser Links in eine Email ist etwas umständlich, die YoutTube-Links holt man sich von deren Seite und die öffentlichen Dropbox Links kann man sich über einen Rechts-Klick in einem Untermenü in die Zwischenablage kopieren lassen. Das dauert in Summe doch schon recht lange und wenn immer mal wieder neue Dateien hinzukommen, müssen vorbereitete Textbausteine (das gilt wohl auch für Text-Expander) auch erst mal gepflegt werden. Aus dieser Situation ist mir die Idee für ein InsertLink Skript gekommen, welches die Liste der Links selber erzeugt und zur Auswahl anbietet.

Die Voreinstellungen:

Startet man das Skript zum ersten Mal, möchte es die Public-ID der Dropbox, sowie den Namen des YouTube-Kanals wissen. Damit man sich nicht selber die ID aus der URL-kopieren muss, kopiert man sich einfach einen x-beliebigen Public-Link der Dropbox in die Zwischenablage und startet das Skript. Handelt es sich bei dem String in der Zwischenablage um einen Public-Link (http://dl.dropbox.com/u/…) bedient sich das Skript und trägt die Public-ID in die Voreinstellungen ein. Danach wird noch der YouTube Channel-Name abgefragt und fertig sind die Einstellungen.

Die Funktionsweise bei Dropbox:

Ich wollte das Ding jetzt nicht über das API auf die Drop-Box zugreifen lassen, das wäre für eine reine Datei-Liste echter Overkill und da sich der Download-Link neben dem Dateinamen nur durch eine bestimmte Public-ID unterscheidet reicht es dem Skript den Pfad der Datei und die ID zu geben. Für die Suche nach der Datei habe ich einen Pseudo-AppleScript-Datei-Browser entworfen, der über einfache Auswahllisten eine schnelle Navigationen durch die Untiefen des Public-Dropbox-Ordners erlaubt. Hat man eine oder mehrere Dateien gefunden, kann man diese Auswählen und die entsprechenden Public-Dropbox-Links werden vom Skript erzeugt (inkl. URL-Encoding der Sonderzeichen) und an der Cursor-Position eingefügt.

Die Funktionsweise bei YouTube:

Hier mache ich mir die Ausgabe eines XML-Feeds zu Nutze, das Skript braucht nur einen Benutzernamen und ruft sich die 25 aktuellsten Filme des Kanals (Titel und URL) als Atom-Feed ab, wenn man weiter zurückgehen möchte, lädt das Skript auch weitere ältere Filme in die Liste. Hier kann man dann auch einen oder mehrere Filme auswählen und die Titel werden nebst URL, an der aktuellen Cursor-Position eingefügt.


Für den visuellen Typen

Viele Worte und deshalb gibt es auch einen Film dazu ;-)

Aso und der Code

--25.03.2012 hubionmac.com
--Script for inserting Public-Dropbox links and Links to films of your Youtube-Channel into an email or any other text-field
--26.03.2012
-- removed properties from code, there do not help, only when you want to store real constant values… the path to you home dir isn't
-- changed typeThis handler, so it uses the clipboard instead, this kills your clipboard contents on every run, but it works 100%
-- tweaked the file-browser-handler a bit, so that the paths are 100% absolute without any ../ in it
-- set selection of lists to first item of list  per default
-- added intervall_passed handler and set the update intervall of the xml feed to 900sec (15min), so the script remembers the xml-feed for 15min and does not load it on every run
property plist : "com.hubionmac.hubis_insertlink"
set DropBoxPublicFolder to (POSIX path of (get path to "cusr") & "Dropbox/Public/")
set StandardPublicLinkURL to "http://dl.dropbox.com/u/"
set dropbox_public_ID to ""
set current_timestamp to do shell script "perl -e 'print time.\"\\n\";'"
-- GET THE DROPBOX ID
try
  set dropbox_public_ID to do shell script "defaults read " & plist & " 'Dropbox plublic ID'"
on error
  try
    set tcb to the clipboard as text
    if tcb starts with "http://dl.dropbox.com/u/" then
      set dropbox_public_ID to (characters ((count of every character of "http://dl.dropbox.com/u/") + 1) through -1 of tcb) as text
      set dropbox_public_ID to (characters 1 through ((offset of "/" in dropbox_public_ID) - 1) of dropbox_public_ID) as text
      do shell script "defaults write " & plist & " 'Dropbox plublic ID' " & dropbox_public_ID
      display alert dropbox_public_ID & " was saved as yout DropBox ID in the preferences." as informational giving up after 2
    else
      error
    end if
  on error
    display alert "I don't know your Dropbox Public ID yet, please copy a plublic Dropbox to the clipboard and restart the Script" as informational giving up after 5
  end try
end try
if dropbox_public_ID is not "" then
  -- GET THE YOUTUBE CHANNELNAME
  try
    set youtube_channelName to do shell script "defaults read " & plist & " 'Youtube channel name'"
  on error
    set youtube_channelName to text returned of (display dialog "I don't know your Youtube-Channel name yet, please enter it here." default answer "")
    if (youtube_channelName as text) ≠ "" and (youtube_channelName as text) ≠ "false" then
      do shell script "defaults write " & plist & " 'Youtube channel name' " & youtube_channelName
    end if
  end try
end if

if dropbox_public_ID is not "" and youtube_channelName is not "" then
  -- ASK WHAT TO INSERT (FileLink or YouTube Link)
  set thelist to {"DropBox (" & dropbox_public_ID & ")", "YouTube (" & youtube_channelName & ")", "--delete preferences--"}
  set theaction to word 1 of ((choose from list thelist with prompt "Insert Links from:" default items item 1 of thelist) as text)
  
  -- DROPBOX GET LINKS
  if theaction as text = "DropBox" then
    set DropBoxFiles to my getFileList(DropBoxPublicFolder, "", true)
    repeat with i from 1 to count of DropBoxFiles
      set item i of DropBoxFiles to (StandardPublicLinkURL & dropbox_public_ID & "/" & my URL_Encode(my remove_from_string_beginning(item i of DropBoxFiles as text, DropBoxPublicFolder)) as text)
    end repeat
    set AppleScript's text item delimiters to return
    set DropBoxFiles to DropBoxFiles as text
    set AppleScript's text item delimiters to ""
    my typeThis(DropBoxFiles)
    -- YOUTUBE GET LINKS
  else if theaction as text = "YouTube" then
    set youtubeinfo to my getYouTubeURL(youtube_channelName, 1, 25)
    set thestring to ""
    repeat with info in youtubeinfo
      set thestring to thestring & Video_Titel of info & ":" & return & Video_URL of info & return & return
    end repeat
    typeThis(thestring as text)
    --RESET/DELETE PREFERENCES
  else if theaction as text = "delete" then
    set myplist to quoted form of (POSIX path of (get path to "pref") & "com.hubionmac.hubis_insertlink.plist")
    do shell script "rm " & myplist
    display alert "Preferences have been removed." giving up after 2 as informational
  end if
end if

on getFileList(RootDir, subDir, firstRun)
  --24.03.2012 hubionmac.com
  --gives you some kind of file dialog in form of a simple applscript-list-dialog
  --returns a list of files (NOT Folders)
  --rootdir is absolute path of the file dialogs root
  --subdir is empty string only used in recursion
  --firstRun is used for recursion, too, should be true on first run 8-)
  if RootDir does not end with "/" then error "RootDir must end with \"/\"!"
  --check that we are still in inside RootDir
  set CurrentPath to quoted form of RootDir & subDir
  if ((do shell script "cd " & CurrentPath & ";pwd") as text) starts with ((characters 1 through -2 of RootDir) as text) then
    -- GET FOLDERS --
    try
      set CurrentFolders to {":::Folders:::"} & every paragraph of (do shell script "cd " & CurrentPath & ";ls -d */")
    on error --no directories here
      set CurrentFolders to {}
    end try
    -- GET FILES --
    try
      set CurrentFiles to every paragraph of (do shell script "cd " & CurrentPath & ";ls -1p | grep -v /\\$")
    on error --no visible files here
      set CurrentFiles to {}
    end try
    if CurrentFiles ≠ {} then set CurrentFiles to {":::Files:::"} & CurrentFiles
    if firstRun is true then
      set thefiles to choose from list CurrentFolders & CurrentFiles default items (item 1 of (CurrentFolders & CurrentFiles)) with multiple selections allowed
    else if firstRun is false then
      set thefiles to choose from list {".."} & CurrentFolders & CurrentFiles default items (item 1 of ({".."} & CurrentFolders & CurrentFiles)) with multiple selections allowed
    end if
    set myoutput to {}
    if thefiles ≠ false then
      repeat with thefile in thefiles
        if thefile as text = ".." then
          set myoutput to getFileList(RootDir, subDir & "../", false)
        else
          if thefile as text does not start with ":" then
            if thefile as text does not end with "/" then
              if subDir as text does not contain ".." then
                set myoutput to myoutput & {(RootDir & subDir & thefile) as text}
              else
                --removes .. from outputpaths so you always get a nice clean absolute path
                set cleanedpath to ((do shell script "cd " & quoted form of RootDir & subDir & ";pwd") & "/") as text
                set myoutput to myoutput & {(cleanedpath & thefile) as text}
              end if
            else
              set myoutput to getFileList(RootDir, subDir & thefile, false)
            end if
          end if
        end if
      end repeat
    end if
  else
    set myoutput to getFileList(RootDir, "", true)
  end if
  return myoutput
end getFileList

on remove_from_string_beginning(thestring, remove_these)
  repeat with remove_this in remove_these
    if thestring starts with (remove_this as text) then
      set thestring to (characters ((count of every character of (remove_this as text)) + 1) through -1 of thestring) as text
    end if
  end repeat
  return thestring
end remove_from_string_beginning

on URL_Encode(thestring)
  return do shell script "/usr/bin/python -c 'import sys, urllib; print urllib.quote(sys.argv[1])' " & quoted form of thestring
end URL_Encode

on typeThis(t)
  set the clipboard to t
  tell application (path to frontmost application as text)
    activate
    tell application "System Events"
      keystroke "v" using command down
    end tell
  end tell
  (**this did not work 100% on every link, so we use the clipboard instead
  set umlauts to {"ü", "ä", "ö", "Ä", "Ü", "Ö", "§", "´", "`"}
  set contains_umlauts to false
  repeat with umlaut in umlauts
    if t contains umlaut then
      set contains_umlauts to true
    end if
  end repeat
  
  tell application (path to frontmost application as text)
    activate
    tell application "System Events"
      if contains_umlauts = false then
        keystroke t
      else
        
        repeat with c in t
          if c is not in umlauts then
            keystroke c
          else
            if (ASCII number of c) = 159 then
              keystroke "u" using option down
              keystroke "u"
            else if (ASCII number of c) = 134 then
              keystroke "u" using option down
              keystroke "u" using shift down
            else if (ASCII number of c) = 138 then
              keystroke "u" using option down
              keystroke "a"
            else if (ASCII number of c) = 128 then
              keystroke "u" using option down
              keystroke "a" using shift down
            else if (ASCII number of c) = 154 then
              keystroke "u" using option down
              keystroke "o"
            else if (ASCII number of c) = 130 then
              keystroke "u" using option down
              keystroke "o" using shift down
            else if (ASCII number of c) = 164 then
              key code (20) using shift down
            else if (ASCII number of c) = 96 then
              key code (24) using {control down, shift down}
            else if (ASCII number of c) = 171 then
              key code (24) using control down
            end if
          end if
        end repeat
      end if
    end tell
  end tell**)
end typeThis



on getYouTubeURL(theChannel, thestartIndex, maxResults)
  set theurl to "'http://gdata.youtube.com/feeds/api/videos?max-results=" & maxResults & "&start-index=" & thestartIndex & "&author=" & theChannel & "'" --list info
  set thexmlfile to (path to "temp") & "youtubefeed.xml" as text
  set thexmlfile_ to quoted form of POSIX path of thexmlfile
  if intervall_passed(plist, "lastrun", "900") is true or ((do shell script ("if test -e '" & thexmlfile_ & "' ; then echo 1 ; else echo 0 ; fi") as text) as integer as boolean) is false then
    do shell script "curl " & theurl & ">" & thexmlfile_
  end if
  set thetitles to {}
  set thetitles_ to {}
  set theurls to {}
  set theindex to 0
  tell application "System Events"
    tell contents of XML file thexmlfile
      set thetotalcount to value of XML element "openSearch:totalResults" of XML element 1
      repeat with i from 1 to count of XML elements of XML element 1
        set theelement to XML element i of XML element 1
        if name of theelement is "entry" then
          set theindex to theindex + 1
          set thetitles to thetitles & ((value of XML element "title" of theelement) & " ##" & theindex as text)
          set thetitles_ to thetitles_ & ((value of XML element "title" of theelement))
          set thelink to (value of XML attribute "href" of XML element "link" of theelement)
          set theurls to theurls & (characters 1 through ((offset of "&" in thelink) - 1) of thelink as text)
        end if
      end repeat
    end tell
  end tell
  if thetotalcount > (thestartIndex + maxResults) then
    set thevideos to choose from list (thetitles & {"--update--", "--more--"}) default items item 1 of (thetitles & {"--update--", "--more--"}) with multiple selections allowed
  else
    set thevideos to choose from list (thetitles & {"--update--"}) default items item 1 of (thetitles & {"--update--"}) with multiple selections allowed
  end if
  set myoutput to {}
  if thevideos ≠ false then
    repeat with thevideo in thevideos
      if thevideo as text = "--more--" then
        set myoutput to my getYouTubeURL(theChannel, maxResults + 1, maxResults)
      else if thevideo as text = "--update--" then
        do shell script "curl " & theurl & ">" & thexmlfile_
        set myoutput to my getYouTubeURL(theChannel, 1, maxResults)
      else
        set theurlindex to last word of (thevideo as text) as integer
        set myoutput to myoutput & {{Video_Titel:item theurlindex of thetitles_ as text, Video_URL:item theurlindex of theurls as text}}
      end if
    end repeat
  end if
  return myoutput
end getYouTubeURL


on getRecord(xmlFile, i)
  set myRecord to {}
  tell application "System Events"
    tell contents of XML file xmlFile
      set theXMLDB to the name of XML element 1 --similar to the previous handler
      tell XML element i of XML element theXMLDB
        set myRecord to {(value of XML element "studentID"), (value of XML element "lastName"), (value of XML element "firstName"), (value of XML element "emailAddress")}
      end tell
      
    end tell
  end tell
  return (myRecord) --pass the list back to the main handler to be put in the table
end getRecord


to intervall_passed(plist, valuename, trigger_intervall)
  --input a plist like "com.hubionmac.testapp
  --input a valuename like "lastrun"
  --input a trigger_intervall like 1000
  --and the handler returns true if the stored EPOG-timestamp from the plist is older than 1000 seconds
  --if true the EPOC-Timtestamp in the plist is updated
  set current_EPOC to do shell script "perl -e 'print time.\"\\n\";'"
  try
    set last_EPOC to (do shell script "defaults read " & plist & " " & quoted form of valuename)
  on error
    set last_EPOC to "0"
  end try
  set EPOCDiff to do shell script "echo " & current_EPOC & "-" & last_EPOC & "|bc"
  set mystatus to ((do shell script "if test " & EPOCDiff & " -gt " & trigger_intervall & ";then echo 1 ; else echo 0  ; fi") as integer) as boolean
  if mystatus is true then
    --update stored epoc-timestamp
    do shell script "defaults write " & plist & " " & quoted form of valuename & " " & current_EPOC
  end if
  return mystatus
end intervall_passed

									

2 thoughts on “InsertLinks from Dropbox and YouTube

  1. […] Für seinen Mac habe ich ihm dafür mal ein AppleScript geschrieben, das auch zusätzlich die Links zu den Videos seines YouTube-Kanals bereit hält.Soweit […]

Leave a Reply