Легенда об искушении: как использовать Python для автоматизации iOS

7988aac0cdc647c0847be792a7845feb.jpgЧасто нам приходится совершать со своим iPhone монотонные и довольно скучные манипуляции, которые заставляют нас с завистью смотреть на десктопы с их безграничными возможностями настройки, скриптинга и автоматизации действий. Да что там десктопы — даже на пользователей Android с их вездесущим Tasker«ом, с помощью которого можно запрограммировать смартфон на что угодно. В iOS существование подобных приложений невозможно, но у нас есть небольшая лазейка.

В этой статье я хочу рассказать о Pythonista — среде разработки на языке Python (версии 2.7.5) для iOS, которая позволяет в том числе писать полноценные приложения с графическим интерфейсом. Однако мы будем использовать ее для несколько иных целей — для создания простых подсобных скриптов, которые будут автоматизировать рутинные операции.6215d0ca16564d979adb581d5e1d3914.png

Pythonista включает в себя множество предустановленных библиотек, в том числе те, что помогут нам получить доступ к функциональности iOS. Как пример можно привести clipboard, позволяющий читать и писать в буфер обмена, contacts для работы с адресной книгой, keychain, location и другие.

Кроме встроенных, нам также понадобятся сторонние Python-модули. Для Pythonista существует два аналога всем известного pip. Это pipista 2.0 и Pypi. Чтобы установить пакет с помощью первого, необходимо сохранить скрипт в корневой каталог и выполнить такую команду:

import pipista pipista.pypi_install ('Name_of_library') У этой библиотечки есть также функции pypi_download (), pypi_search () и pypi_versions (), что позволяет считать ее полноценной заменой pip. Второй установщик требует более четких запросов. Например, необходимо указать версию пакета — это удобно, если по какой-то причине не хочешь использовать последнюю версию. from Pypi import Installer Installer ('Name_of_library', 'Version').install () У этого установщика также есть дополнительные функции.826316f105524593aa9e6c301444f558.png

Для этого есть две возможности: *Pythonista Shortcut* и *Launch Center Pro*. В первом случае все просто: достаточно зайти с девайса на сайт, ввести имя скрипта и аргументы, нажать на кнопку Create Shortcut, затем сохранить эту страницу на рабочий стол, используя стандартные функции Safari.

Вторая программа куда интересней. Чтобы запустить скрипт из нее, необходимо создать событие и в поле *URL* прописать вот такую строчку: «pythonista://script_name? action=run&args=», где script_name — имя скрипта с учетом иерархии каталогов, а после args= необходимо перечислить аргументы (если они есть). Также присутствует возможность запуска по времени или с определенной регулярностью.

Есть и возможность упаковать скрипт в полноценное iOS-приложение. Для этого достаточно скачать [архив](goo.gl/jsQK0b) с проектом XCode с официального сайта и заменить стандартный скрипт с Hello, world на свой. После этого можно собрать этот проект в XCode и запустить на симуляторе, а если есть аккаунт разработчика Apple, то и на гаджете.

ea971ab74708447dbb3cb965d865d41b.png

Pythonista включает в себя всю необходимую документацию, так что для ее изучения не потребуется подключаться к интернету.

Встроенный редактор Pythonista достаточно развит, имеет подсветку синтаксиса, автодополнение и дополнительные клавиши на клавиатуре. Более того, его тоже можно заскриптовать.

Напишем несколько скриптов, дабы облегчить жизнь нам и нашим близким. Возможно, некоторые из них (или все) для кого-то покажутся бесполезными, но зато они дают представление о том, что можно сделать с помощью Pythonista, и могут выступать в качестве некой базы для твоих экспериментов. Всего скриптов девять, и они очень разнообразны.9b00cee25892401ab9f2223052516f56.png

Быстрая отправка твита Начнем с вездесущего Twitter. Не очень удобно открывать приложение или переходить на сайт для того, чтобы просто отправить твит. Поэтому мы напишем скрипт, который будет твитить то, что находится в буфере обмена (не забудь установить библиотеку tweepy). import tweepy import clipboard

# Ключи Twitter-приложения consumer_key = »----------» consumer_secret = »----------» access_key=»----------» access_secret=»----------»

# Представляемся системе auth = tweepy.OAuthHandler (consumer_key, consumer_secret) auth.set_access_token (access_key, access_secret) api=tweepy.API (auth)

# Публикуем твит text = clipboard.get () if len (text)<=140 and len(text)>0: api.update_status (text) Скрипт подключается к аккаунту, используя имеющиеся ключи. Их можно получить на официальном сайте Twitter. Чтобы получить все ключи, нужно создать приложение, затем перейти на вкладку Keys and Access Tokens и нажать на кнопку Create my access token. Таким образом мы получим четыре необходимых нам ключа. Чтобы скрипт смог постить сообщения, необходимо дать приложению такие права на вкладке Permissions.Во всем остальном функциональность крайне проста. Скрипт берет строку из буфера обмена, проверяет, соответствует ли строка формату твита (не более 140 символов), и постит ее.

Быстрое сохранение в Instapaper Теперь о не менее популярном сервисе Instapaper, позволяющем сохранять страницы для офлайн-чтения. Следующий трехстрочный скрипт добавляет страницу из буфера обмена прямо в установленный на девайсе клиент сервиса. import webbrowser, clipboard addnew='x-callback-instapaper://x-callback-url/add? url='+clipboard.get () webbrowser.open (addnew) Cкрипт использует так называемые x-callback-url — мини-API приложений, которые можно вызывать через встроенный браузер. На официальном сайте этой фичи есть список приложений, поддерживающих эту возможность. Структура x-callback-url-запросов такая: x-callback-Имя_Приложения://x-callback-url/Функция? Параметр= Генератор паролей Да, именно генератор паролей. Есть куча приложений со схожей функциональностью, но мы сделаем свой. Просто потому, что хотим :).

import random, string, clipboard pass = '' for x in range (random.randrange (8,12)): pass += random.choice (string.ascii_letters + string.digits) clipboard.set (pass) Данный скрипт поможет создать пароль с высокой устойчивостью к подбору (с включением чисел и букв). Идея алгоритма крайне проста: в пустую строчку добавляется случайное (от 8 до 11) число символов из вышеупомянутого набора. Далее пароль помещается в буфер обмена.Отправка текущего местоположения на email Иногда проще нажать на кнопку и отправить собеседнику свой адрес, чем объяснить, где ты. import smtplib, location, time from email.mime.text import MIMEText

# SMTP-сервер server = «адрес_сервера» user_passwd = «пароль» port = 22 user_name = «отправитель@мэйл» send_name='получатель@мэйл'

# Выполняем подключение и регистрацию s = smtplib.SMTP (server, port) s.ehlo () s.starttls () s.ehlo () s.login (user_name, user_passwd)

# Получаем координаты location.start_updates () time.sleep (10) location.stop_updates () loc = location.get_location () addr = location.reverse_geocode (loc)[0]

# Формируем и отправляем письмо Text = 'Я нахожусь по адресу: ' + addr['Country'] + ', город ' + addr['City']+', ' + addr['Name'] letter = MIMEText (Text,'html','utf-8') letter['Subject']= 'Текущая геолокация' letter['To']=send_name letter=letter.as_string () s.sendmail (user_name, send_name, letter) s.close Скрипт состоит из двух частей: первая — это работа с почтовым сервером, вторая — получение текущего адреса и отправка письма. Остановимся на второй поподробнее. Дело в том, что функции «получить текущее местоположение» в библиотеке location нет, но есть две функции, позволяющие получить список часто посещаемых мест. Так как создание списка длится всего десять секунд (time.sleep (10)), то в нем будет всего один объект с текущим адресом. Этот объект — словарь. Получим необходимые значения по ключам и занесем красивую фразу в строку Text, которую мы потом и отправим.8f7d45b8018d4b18ad82480bd7e60ad9.png

Отправка фотографии на сервер по FTP Уже известная нам библиотека clipboard позволяет работать не только с текстом, но и с изображениями. Это открывает нам новые возможности. Как насчет скрипта, который позволяет сохранить фотографию из буфера обмена на FTP-сервер? import ftplib, clipboard

# Получаем изображение и сохраняем в виде файла a=clipboard.get_image () filename='out.jpg' a.save (filename)

# Подключаемся к серверу и заливаем картинку con=ftplib.FTP ('Host','Login','Password') f=open (filename,'rb') send=con.storbinary (filename, f) con.close () Скрипт можно немного изменить, написав в первых двух строчках import ftplib, photos a=photos.get_image () Тогда на сервер отправится не скопированная, а последняя отснятая фотография. А если заменить первые две строчки на эти: import ftplib, photos a=photos.capture_image () то iOS предложит сделать фотографию.Работа с удаленным сервером по SSH У многих из нас есть удаленные серверы. У кого-то это домашний медиапроигрыватель или файлопомойка, другие рулят серверами на Amazon. Как управлять ими с iPhone или iPad? Можно скачать какой-нибудь FTP-клиент, но это не вариант, если необходимо регулярно выполнять одинаковые задачи, например делать бэкап. Стивен Миллард (Stephen Millard) написал [скрипт](goo.gl/Tt14cC), позволяющий выполнять удаленные команды через SSH. В упрощенном виде (без проверки на правильность введенных данных и вывод логов) он выглядит так: import paramiko import console

# Адрес, логин и имя исполняемой команды strComputer = 'адрес' strUser = 'логин' strPwd = 'пароль' strCommand = 'имя_команды'

# Подключаемся к серверу client = paramiko.SSHClient () client.set_missing_host_key_policy (paramiko.AutoAddPolicy ()) client.connect (hostname=strComputer, username=strUser, password=strPwd)

# Выполняем команду stdin, stdout, stderr = client.exec_command (strCommand) print stdout.read ()

client.close () Для выполнения набора команд достаточно скопировать строчку «stdin, stdout, stderr = client.exec_command (strCommand)» несколько раз с различными командами (либо перечислить все команды через точку с запятой. — Прим. ред.).c790563a8fe348adabd0780b97118a28.png

Сокращаем ссылки при помощи goo.gl Нередко приходится прибегать к сокращалкам ссылок. Но каждый раз заходить на сайт, копировать, вставлять — это как-то скучно. К счастью, существует API goo.gl. import googl, clipboard

client = googl.Googl («ключ») result = client.shorten (clipboard.get ()) clipboard.set (result['id']) Cкрипт получает URL из буфера обмена, конвертирует его и помещает обратно в буфер. Перед запуском скрипта необходимо получить API Access Key. Для этого заходим на страницу API, нажимаем Add project и в списке доступных сервисов включаем URL Shortener API. Далее в левом меню выбираем вкладку APIs & auth, подменю Credentials и жмем кнопку Create new Key, далее Browser Key. После получения ключа вставляем его в скрипт.Обрати внимание, что в ходе исполнения скрипта переменной result присваивается словарь вида {'kind': 'urlshortener#url', 'id': ShortLink', u’longUrl': 'LongLink'}. Так как нам необходима только короткая ссылка, в буфер обмена заносится значение по ключу 'id'.

Очистка записной книжки Пройдясь по поисковым системам, мы найдем всего два способа очистки записной книжки: удаление по одному контакту либо синхронизация с пустым списком контактов на компе. Нет, так неинтересно. import contacts a = contacts.get_all_people () for i in a: contacts.remove_person (i) contacts.save () Просто пробегаемся по списку контактов. Главное — не забыть сохранить сделанные изменения (последняя строка).Импорт друзей из ВК в записную книжку Наконец, самый сложный и длинный скрипт — импорт номеров телефонов из «ВКонтакте» в записную книжку. Как и у всех остальных, у «ВКонтакте» есть API. Для питона существует несколько библиотек для работы с ним. Самая известная и самая простая в использовании — библиотека со скромным именем vk. import vk, datetime, contacts

# Функция для конвертации даты из формата ВК в формат iOS def convertdate (date): date = date.split ('.') if len (date) == 2: return datetime.datetime.combine (datetime.date (1604, int (date[1]), int (date[0])), datetime.time (0, 0)) else: return datetime.datetime.combine (datetime.date (int (date[2]), int (date[1]), int (date[0])), datetime.time (0, 0))

# Подключаемся к ВК и получаем список друзей vkapi = vk.API ('ID-приложения', 'логин', 'пароль') a = vkapi.friends.get (fields='contacts, bdate') a = a['items']

# Проходим по списку полученных контактов и импортируем их по одному for i in a: Temp = contacts.Person () Temp.last_name= i['last_name'] Temp.first_name = i['first_name'] if 'mobile_phone' in i.keys (): try: Temp.phone=[('mobile', i['mobile_phone'])] except: pass if 'home_phone' in i.keys (): try: Temp.phone.append (('home', i['home_phone'])) except: pass Temp.url = [('vk','http://vk.com/id'+str (i['id']))] if 'bdate' in i.keys (): Temp.birthday = convertdate (i['bdate']) contacts.add_person (Temp)

# Сохраняем контакты contacts.save () Как и в случае с твиттером, для скрипта необходимо создать «приложение» внутри «ВКонтакте». Чтобы сделать это, перейди на вкладку «Приложения» на сайте VK, потом на вкладку «Управление» и нажми кнопку «Создать приложение». На странице приложения перейди на вкладку «Настройки» и скопируй «ID Приложения». Вставь «ID Приложения», «Логин» и «Пароль» в скрипт.Разберемся, как работает этот скрипт. Сначала мы получаем список друзей. По умолчанию функция friends.get () возвращает словарь, состоящий из двух полей: count и items. Нас, несомненно, интересует второе, но так как мы хотим получить не только имена и фамилии, то передадим функции параметр fields, указывающий на то, что мы хотим узнать. Далее мы идем по списку словарей, где каждый словарь — это пользователь. При каждой итерации мы создаем переменную Temp типа Person и по очереди добавляем в нее поля.

В процессе прохода по контактам скрипт решает несколько проблем. Первая проблема возникает при экспорте телефонных номеров, ведь очень часто мы встречаем в ВК номера типа «кому надо — знают», «секрет» и подобные. Чтобы скрипт смог обработать подобные записи, не падая, используется оператор try. Вторая проблема возникла с несовпадением формата даты рождения. В полученном из ВК словаре она записана в виде строки формата DD.MM.YYYY, а в поле birthday необходимо заносить данные в формате datetime.datetime. Для этого и нужна функция convertdate в начале скрипта. Кроме того, дата рождения может быть не указана вовсе.

canvas — библиотека векторной графики; clipboard — работа с буфером обмена; console — функции, связанные с вводом и выводом текста; contacts — доступ к записной книжке; editor — работа с текстовым редактором Pythonista; keychain — доступ к API Keychain; linguistictagger — лингвистический анализ; location — геолокационные сервисы; motion — снятие показаний сенсора; notification — работа с уведомлениями; photos — работа с сохраненными фотографиями; scene — 2D-графика и анимация; sound — библиотека звуков; speech — конвертация текста в речь; ui — нативный GUI для iOS. 5d19da50858f495db37b81516527b527.png

Несмотря на большое число примеров, мы рассмотрели далеко не все возможности Pythonista. А ведь ее функционала хватает на очень многое. Например, в App Store уже выложено несколько приложений, созданных в этой программе. К тому же в скором времени создатель Pythonista обещает выпустить обновление с поддержкой iPhone 6 и 6+ и двумя новыми модулями для работы с напоминаниями и периферийными Bluetooth-устройствами. Официальный форум Pythonista: omz-forums.appspot.com/pythonistaДокументация по встроенным модулям: omz-software.com/pythonista/docs/ios/Большая статья о возможностях Pythonista: www.macstories.net/stories/automating-ios-how-pythonista-changed-my-workflow/Сборник Pythonista-скриптов: github.com/Pythonista-Tools/Pythonista-Toolsimage

Впервые опубликовано в журнале «Хакер» от 02/2015.Автор: Виктор Паперно

Подпишись на «Хакер»

© Habrahabr.ru