Скрипт Automator, загружающий изображения на Habrastorage

    Однажды мне надоело тыкать закладку Habrastorage в браузере. И я сделал вот что…

    image


    Вот за что я люблю MacOS — за Automator и AppleScript.
    Запускаем Automator, выбираем тип — Служба.
    image
    В выпадающих меню выбираем, чтобы служба работала только на графических файлах в финдере:
    image
    Слева в поиске находим действие «Run Apple Script» и перетаскиваем его в рабочую область:
    image
    Пишем небольшой скрипт:
    image

    on run
    	tell application "Finder" 
    		return POSIX path of (selection as alias)
    	end tell
    end run
    

    Состоит он, по сути, из двух строчек:
    tell application «Finder» — вызываем приложение Finder
    return POSIX path of (selection as alias) — скрипт возвращает адрес выделенного файла в POSIX стиле(если просто попросить path — то он отдаст адрес с разделителями-двоеточиями).
    Теперь сбоку находим «Run shell script» и тоже перетаскиваем его в рабочую область. Выбираем в меню «Передать ввод: как аргументы» В этом случае то, что вернет верхний скрипт передатся не на стандартный ввод, а как будто мы запустили этот скрипт с параметром(у нас это путь к файлу)
    image
    Пишем в него вот что:
    curl -F "Filedata=@$1" "http://habrastorage.org/uploadController/?username=vvzvlad&userkey=7a25d94cde460365b6f7ce137675c623ec"  | json_pp | grep url | awk -F '"' '{print $4}'
    

    Эту строчку я нашел вот в этом комментарии. Первая часть — это загрузка методом POST в параметре Filedata нашего файла. $1 — это как раз тот аргумент, который передает верхний скрипт — адрес файла. Тоесть, у меня это выглядит вот так:
     curl -F "Filedata=@/Users/vvzvlad/Documents/REVIEWS/alpha\ mio/foto/003.jpg" "http://habrastorage.org/uploadController/?username=vvzvlad&userkey=7a25d94cde460365b6f7ce137675c623ec"
    

    Как получить магическую строку userkey описано вот тут. Надо зайти на адрес habrahabr.ru/whoami но не просто так, а с реферером habrastorage. Проще всего это сделать так: заходим на habrastorage.org, смотрим исходный код, находим строчку(она у меня 13), и тыкаем на нее.
    image
    Получаем вот такую строчку, которую и копируем себе в скрипт:
    image
    Остальная часть строки:
    | json_pp | grep url | awk -F '"' '{print $4}'
    

    Это разбор JSON-ответа, чтобы выдрать из него то, что нас интересует — урл загруженной картинки.
    Теперь мы получили адрес, но нам его надо вы еще как-то отдать пользователю. Например, скопировать в буфер обмена. Добавляем в редакторе еще один блок Apple скрипта:
    image
    В нем у нас такой скрипт:
    on run {input}
    	set the clipboard to "<img src=\"" & input & "\" alt=\"image\"/>"
    	display notification input with title "Habrastorage" subtitle "Картинка загружена"
    end run
    

    on run {input} — получаем от предыдущего скрипта строчку с адресом
    set the clipboard to "<img src=\"" & input & "\" alt=\«image\»/>" — копируем ее в буфер обмена, заодно оборачивая в тег img
    display notification input with title «Habrastorage» subtitle «Картинка загружена» и показываем уведомление, чтобы пользователь понял что картинка уже загружена, и ее можно вставлять в текст.
    Все, скрипт работает, можно загружать файлы сразу из Finder, не трогая лишний раз глючный Flash и не открывая вкладку браузера.

    Материалы:
    AppleScript для новичков

    Сам скрипт живет тут.
    Его надо распаковать и положить в папку /Users/User/Library/Services/, не забыв вставить внутрь свою строчку.

    P.S. Я понимаю что он не очень оптимален, и можно сделать все в одном Apple Script. Но я не понял, как правильно передать аргумент внутрь do shell script, а так же, как там экранировать символы.

    P.P.S. В статье все изображения загружены с помощью этого скрипта.
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 37

      +3
      Один вопрос: надеюсь, вы не указали свой настоящий userkey в этой статье?
        +1
        Нет конечно. А где он кроме хабрасторежда используется?
          +2
          Наверное, нигде, но просто это неаккуратно как-то. :)
        0
        Это превосходно, спасибо.
          0
          Спасибо за статью. Это очень полезно. А если кому-то интересно, могу найти как запускать (например psi+) с параметрами из любой папки «аля portable».
            0
            О! было бы шикарно
          0
          Спасибо! Не знал вообще о таких возможностях в системе — теперь будет повод поиграться с этим! :)
            +3
            Очень круто, спасибо! :) Кстати, прямо сейчас колдуем над HS.
              +1
              Только не сломайте! :)
                0
                Это хорошо. А почИните возможность прямой загрузки из браузера по FileAPI файлов размером более 10КБ?

                Напомню, что ещё летом интересовался возможностью загрузки, чтобы не использовать Flash, сделал, но обнаружился баг, выражающийся в том, что в файле картинки остаются строчки-разделители вида:

                ....
                -----------------------------57648741364
                Content-Disposition: form-data; name="Filedata"; filename="5e7kqHg.jpg"
                Content-Type: image/jpeg
                
                яШяа.....
                

                Картинка, конечно, ломается, файл не отображается.
                Ссылка на свежий пример такой загрузки, из которой взята одна из таких строчек: habrastorage.org/storage3/296/126/089/296126089e3e540d19ddc04616d9226b.jpg (30 КБ). Если файл — меньше 10КБ, то загружается всё нормально (хотя иногда, редко бывают ошибки).

                Техподдержка Хабра тогда ответила, что надо пользоваться немного другим поддоменом. Я его протестировал — обнаружилось, что только Хром на нём стал работать нормально, у Firefox и старой Оперы — те же ошибки. Поэтому в скрипт не стал внедрять поддержку только для Хрома. Прочие способы (не браузеры), как и описываемый в статье, видимо, нормально работают, потому что не разбивают изображение при закачке на секции, а все браузеры (не тестировал Safari) — разбивают, но серверная часть сайта этого не учитывает (надо просто выкусывать разделители). И странным образом учитывает только Хром на другом поддомене, несмотря на то, что тоже отправляет файл с разделителями секций.

                Почему на другом поддомене неудобно? Токен надо брать на habrastorage.org в одном фрейме, потом загрузку по FileAPI надо делать на другом (насколько помню, legacy.habrastorage.org), показывать — снова на первом, потому что там юзер опознан и отображается приветствие. Мне кажется, что что-то недоделано в плане реализации закачки по FileAPI. Но далее техподдержка не отвечала, потому что был ответ один: информация принята, а работы по этому механизму не велись.

                Если сейчас в этом направлении ведутся работы — сделайте, пожалуйста поддержку файлов больше 10К. И лучше на основном домене, или создайте, пожалуйста, опознавание юзера на домене legacy…. Окажу посильную помощь в налаживании закачки файлов через браузеры.

                Сейчас заливка картинок перетаскиванием в окно до 10 КБ в 3 браузерах выполнена в юзерскрипте HabrAjax (надо зайти на домен habrastorage.org и затащить картинку в окно).

                Пример затащенного малого файла в Firefox:
                  0
                  Подтверждаю, проблема есть даже во флешевом загрузчике — из десятка файлов несколько оказываются битыми, заливаю заново тот же файл, все нормально.
                0

                Что-то не хочет он работать у меня =(
                  +1
                  Хм, вот так заработало.
                  image
                  0
                  Жду, когда дропбокс заблокирует файлик за хотлинкинг:)
                    0
                    Это же не картинка, его качали только те, кому он нужен.
                    0
                    Эх, всё бы отдал, если бы загружало на яндекс.фотки.
                      0
                      Разве там нет API?
                        0
                        Есть, но там надо делать запрос на Oauth, получать ключ, я так с этим и не разобрался, да и времени нету.
                          0
                          А потом с этим ключом можно работать неограниченно долго?
                            0
                            Сейчас глянул — время жизни токена не менее года.
                              0
                              Интересная задачка…
                            0
                            Вот готовое api на питоне. Обернуть его в вызов шелла, и передавать параметр.
                          0
                          Я смог реализовать эту задачку, но нужно время чтобы оформить это топиком. Предварительно могу выслать вам инструкцию о том, как это всё собрать.
                            0
                            Да в принципе я уже всё сам сделал, но завязано на одного юзера, получил вручную oauth токен и делаю запросы через api-fotki.yandex.ru/post/?oauth_token=token

                            Получилось гораздо проще, чем думал.
                              0
                              Как вы смогли получить oauth-токен без регистрации приложения или вы как то его зарегистрировали? Я просто прочитал api.yandex.ru/fotki/doc/overview/authorization.xml и там в секции по oauth написано про регистрацию приложения… Поэтому сделал все на Fimp-токене.

                              И второй вопрос — смогли ли вы сделать, чтобы когда выбираешь несколько картинок — чтобы они все отправлялись?
                                +1
                                Всё. Смог реализовать загрузку подряд несколько картинок (когда выбрано несколько файлов). Собственно вот предварительный AppleScript, который можно загрузить в Automator.

                                image

                                Нужно только заменить токен на свой. И заменить mylogin в адресе.

                                Исходник
                                on run
                                	set TOKEN to "2d1da421fdd3404318e81c0a0442105e"
                                	set ALBUM to "http://api-fotki.yandex.ru/api/users/mylogin/photos/"
                                	
                                	tell application "Finder"
                                		set selectedFiles to (get selection)
                                		
                                		if (count of selectedFiles) > 0 then
                                			repeat with i from 1 to the count of selectedFiles
                                				set filePath to POSIX path of (item i of selectedFiles as alias)
                                				set responseCode to do shell script "curl -sL -w %{http_code} --header \"Authorization: FimpToken realm=\"fotki.yandex.ru\", token=" & TOKEN & "\" -F \"image=@" & filePath & "\" --request POST " & ALBUM & " -o /dev/null"
                                				if (responseCode is not "201") then
                                					display alert "Произошла ошибка:" message "Не удалось загрузить: " & filePath
                                				end if
                                				
                                			end repeat
                                			
                                			display notification "Загрузка картинок завершена" with title "fotki.yandex.ru"
                                		end if
                                		
                                	end tell
                                end run
                                



                                Чтобы получить токен, нужно скачать реализацию RSA от Yandex download.yandex.ru/api-fotki/c-yamrsa.tar.gz затем распаковать и сделать make encrypt

                                Затем в этой же папке создать shell-скрипт
                                #!/bin/sh
                                
                                ### config
                                
                                USERNAME=mylogin
                                PASSWORD=mypassword
                                
                                CURRENT_DIR=$(pwd)
                                
                                PATH_TO_ENCRYPT="$CURRENT_DIR/encrypt"
                                
                                ### yandex.magic
                                
                                YAMRSA_CODE=0
                                
                                while [ $YAMRSA_CODE -ne 200 ]; do
                                  echo "Get new public RSA key from Yandex..."
                                  YAMRSA_CODE=$(curl -sL -w %{http_code} http://auth.mobile.yandex.ru/yamrsa/key/ -o yamrsa.txt)
                                  sleep 2
                                done;
                                
                                KEY=$(cat yamrsa.txt | grep key | awk -F "<key>" '{print $2}' | awk -F "</key>" '{print $1}')
                                REQUEST_ID=$(cat yamrsa.txt | grep request_id | awk -F "<request_id>" '{print $2}' | awk -F "</request_id>" '{print $1}')
                                CREDENTIAL=$($PATH_TO_ENCRYPT $KEY "<credentials login=\"$USERNAME\" password=\"$PASSWORD\"/>")
                                
                                echo "RSA: $KEY"
                                echo "REQUEST_ID: $REQUEST_ID"
                                echo "CREDENTIAL: $CREDENTIAL"
                                
                                TOKEN_CODE=502
                                
                                while [ $TOKEN_CODE -eq 502 ]; do
                                  echo "Get new token from Yandex..."
                                  TOKEN_CODE=$(curl -sL -w %{http_code} -d request_id=$REQUEST_ID --data-urlencode credentials=$CREDENTIAL --request POST http://auth.mobile.yandex.ru/yamrsa/token/ -o token.txt)
                                  sleep 2
                                done;
                                
                                TOKEN=$(cat token.txt | grep token | awk -F "<token>" '{print $2}' | awk -F "</token>" '{print $1}')
                                
                                echo "TOKEN: $TOKEN"
                                



                                Во shell скрипте нужно mylogin заменить на свой логин и mypassword соответсвенно тоже. Результатом выполнения скрипта будет строчка:

                                TOKEN is 2d1da421fdd3404318e81c0a0442105e

                                Срок действия токена не менее года.
                                  +1
                                  Чтобы загружать фотки не в общую коллекцию, нужно предварительно создать, например запароленный альбом (или выбрать имеющийся) и посмотреть его URL в браузере. Например вот: fotki.yandex.ru/users/mylogin/album/200491/

                                  Теперь чтобы AppleScript мог загружать фотки в этот альбом, необходимо строку:

                                  set ALBUM to "http://api-fotki.yandex.ru/api/users/mylogin/photos/"

                                  заменить на:

                                  set ALBUM to "http://api-fotki.yandex.ru/api/users/mylogin/album/200491/photos/"
                                    0
                                    Вы уж как-то слишком все усложнили.
                            +1
                            –1
                            все уже /whoami не работает)
                              +2
                              Всё работает. Читайте внимательнее.
                              Делай раз
                              Делай два
                              Делай три:
                                0
                                Большое спасибо!
                              0
                              У меня курл не срабатывает :( в итоге копирует в буфер пустую строку
                                0
                                А в консоли?
                                  0
                                  В консоли пробовал запускать, ничего вообще не возвращается, логин и ключ нашел правильные
                                    0
                                    Должно что-то возвращаться. Если вот так:
                                     curl -F "Filedata=@Адрес файла" "http://habrastorage.org/uploadController/?username=&userkey="
                                    

                              Only users with full accounts can post comments. Log in, please.