QR-code в InDesign для ленивых

Простой jsx скрипт для получения QR-кода в InDesign с демонстрацией использования возможностей python непосредственно из InDesign

Поскольку в сеансе черной магии с последующим ее разоблачением заявлена демонстрация использования возможностей скриптового языка python, то без наличия установленного и правильно настроенного интерпретатора python скрипт не будет работать.

Проверить наличие установленного интерпретатора можно с помощью консоли в Windows или терминала в Mac OS, набрав простую команду «python» (без кавычек). Если при этом терминал не сообщил об отсутствии такой команды и запустил интерпретатор python, то интерпретатор установлен правильно. Выйти из интерпретатора можно не только закрытием окна терминала, но и с помощью команды «exit()» без кавычек. Если же интерпретатор не найден, то можно установить его. Бесплатно скачать python можно с официального сайта python.org или ActivePython.

Что такое QR можно узнать из Википедии.

Для печатных изданий QR-код — очень хороший способ предоставления различной информации, которую можно распознать современными мобильными телефонами с фотокамерами. Информация может содержать, например, ссылку на страницу в интернете, контактную информацию в виде vCard и прочие полезности.

Для получения QR-кода при помощи скрипта в InDesign есть два пути: генерировать код непосредственно в скрипте или воспользоваться внешним генератором кодов. Первый путь, несмотря на кажущуюся простоту не совсем прост, поскольку потребует от разработчика скрипта довольно специфичных знаний о кодировании двоичных данных. Второй путь быстрее, полезнее, интереснее. И для ленивых.

Для получения QR-кодов будет использоваться очень полезный сервис QR coder. Это очень хороший, быстрый (что важно) сервис получения кодов с полной поддержкой кириллицы (что тоже важно).

Для работы скрипта будет использоваться сервис постоянной ссылки на изображение вида

http://qrcoder.ru/code/?http%3A%2F%2Fadobescripts.wordpress.com&4&0

Сервис получает адрес ссылки «http%3A%2F%2Fadobescripts.wordpress.com&4&0» и генерирует картинку в формате gif, которую можно вставить на сайт или сохранить на диске.

Итого техзадание на скрипт: открыть ссылку с нужным параметром, получить и записать сгенерированный gif, поместить его в документ InDesign.

С некоторых пор ExtendScript поддерживает возможность работы с сокетами через объект типа Socket. В объекте этого типа при помощи запросов теоретически можно получить данные из сети. Но для этого нужно неплохо знать специальную магию HTTP запросов, которой не содержится в официальной документации по объекту Socket в ExtendScript. Я такими знаниями обладаю далеко не в полной мере, поэтому все попытки использовать Socket возвращали вместо ожидаемого кода страницу с ошибкой 500.

Ввиду неудовлетворительного поведения сокетов было принято решение в стиле «Если пальма не идет к Джохе, так Джоха пойдет к пальме». В данном случае такой подход означает, что нужно найти средство гарантированно получить требуемый код с сайта и сохранить его на диск, а уже потом поместить его в документ InDesign. И этим средством (по большей части в демонстрационных целях) стал python.

Для получения QR-кода с сайта был написан простой python-скрипт с использованием стандартной библиотеки urllib. С получением QR-кода с сайта скрипт справился отлично.

Была сделана корректировка техзадания. Теперь скрипт InDesign должен был получить данные для кодирования, передать их в скрипт на python, получить записаный gif и поместить его в документ.

Получение данных для кодирования было решено сделать при помощи самого простого диалогового окна типа prompt. Передачу данных было решено сделать при помощи простого текстового файла, в который скрипт InDesign будет записывать даные для кодирования, а скрипт python считывать и использовать. В принципе, данные можно передавать как параметры для скрипта python, но это могло несколько усложнить разработку и тестирование ввиду наличия разных кодировок в операционных системах. Такое решение я не стал бы рекомендовать, как постоянное, но для быстрой разработки скрипта для ленивых — вполне приемлимо.

Запуск python-скрипта в первоначальном варианте производился с помощью вызова команды execute() для файла скрипта. Этот метод в данном случае не годится совершенно, потому, что execute() выполняет ассоциированную с типом файла команду, а это совершенно не обязательно запуск выполнения. Поэтому более надежным (но одновременно и более сложным) является вызов нужной команды в терминале операционной системы. InDesign, к счастью, поддерживает выполнение не только ExtendScript, но и VBScript (для Windows) и AppleScript (для Mac). С помощью команды app.doScript() на обоих операционных системах можно запустить команду в терминале.

Возможно, что при выполнении запроса к сервису qr-кодов, файрволл запросит разрешение на сетевую активность InDesign (а не python). Это означает, что файрволл настроен хорошо и внимательно следит за системой. Для получения qr-кода следует разрешить InDesign доступ в сеть.

Следующий шаг, потребовавший нетривиального решения, это получение записанного gif-файла.  В принципе, можно заставить python при неудачном обращении к сервису генерации кодов возвращать ошибку, но это сложно и не нужно для такого простого скрипта.

Для проверки успешной генерации qr-кода был написан цикл while, где с периодичностью раз в 100 миллисекунд проверяется существование gif-файла. При превышении порога ожидания (по умолчанию 1000 миллисекунд — одна секунда), цикл прерывается и пользователю выводится сообщение об ошибке. Если в процессе выполнения цикла скрипт обнаруживает наличие gif-файла, цикл прекращается и gif помещается в активный документ.

Из метода помещения gif-файла в документ очевидно, что gif-файлы должны иметь уникальные имена — чтобы даже случайно не поместить в документ qr-код, созданный ранее. Поэтому в качестве имен файлов используется значение getTime(), которое равно количеству миллисекунд, прошедших с полуночи 1 января 1970 года GMT. Очень маловероятно, что пользователь запустит скрипт дважды на протяжении одной миллисекунды, потому имена файлов можно заведомо считать уникальными.

Запрос текста для qr-кода

Запрос текста для qr-кода

qr-код в документе

qr-код в документе

Тексты скриптов:

QR.jsx (скрипт InDesign):

#target "InDesign"

// Oleg Butrin https://adobescripts.wordpress.com

var pyscript = 'smartQR.py';
var wait = 100;
var maxwait = 1000;

// get active script path
function getScriptPath() {
	var result = null;
	try {
		result = app.activeScript.path;
	} catch(error) {}
	if (result === null) {
		result = File($.fileName).parent;
	}
	return result;
}

// main
function main() {
	//get active document
	try {
		doc = app.activeDocument;
	} catch (error) {
		alert(error);
		return false;
	}
	//check python script exists
	var pyfile = File(getScriptPath() + '/' + pyscript);
	if (!pyfile.exists) {
		return false;
	}
	//get text for qr
	var txt = '';
	// try to get selected text less 200 chars
	try {
		if (app.selection[0].contents.length < 200) {
			txt = app.selection[0].contents;
		}
	} catch (error) {}
	//prompt for qr text with selected as default
	var utext = prompt('QR text:', txt);
	if (!utext) {
		return false;
	}
	//set qr filename as current time
	filename = new Date().getTime() + '.gif';
	//set full name for qr file
	var qrfile = '';
	try {
		//if document saved, use document folder
		qrfile = doc.filePath + '/' + filename;
	} catch (error) {
		//if document never saved, use current user documents folder
		qrfile = Folder.myDocuments.fsName + '/' + filename;
	}
	//get data file and write data
	linkfile = File(getScriptPath() + '/' + 'link.txt');
	linkfile.encoding = 'utf-8';
	linkfile.open('w');
	linkfile.write([utext, qrfile].join('\t'));
	linkfile.close();
	// execute python script
	if ($.os.replace('Windows', '') != $.os) {
		var vbs = '' +
        'Set objShell = CreateObject("Shell.Application")\n' +
        'objShell.ShellExecute "python", """' + pyfile.fsName + '""", "", "", 0';
		app.doScript(vbs, ScriptLanguage.VISUAL_BASIC);
	}
	if ($.os.replace('Macintosh', '') != $.os) {
		app.doScript('do shell script "python \'' + pyfile.fsName + '\'"', ScriptLanguage.APPLESCRIPT_LANGUAGE);
	}
	//wait for qr gif
	waiting = 0;
	while (!File(qrfile).exists && waiting < maxwait) {
		$.sleep(wait);
		waiting += wait;
	}
	//place qr if qr gif exists
	if (File(qrfile).exists) {
		app.selection = [];
		doc.place(qrfile);
	} else {
		return false;
	}
	return true;
}
//run main
res = main();
if (!res) {
	alert('Something goes wrong!');
}

smartQR.py (python):

#!/usr/bin/python
#coding: UTF-8

# Oleg Butrin https://adobescripts.wordpress.com

import os
import sys
import urllib
import codecs
import re

def main():
    # read data file
    fileObj = codecs.open('link.txt', 'r', 'UTF-8')
    txt = fileObj.read()  # Returns a Unicode string from the UTF-8 bytes in the file
    fileObj.close()
    # prepare data
    fstr = re.compile('\t([^\t]+)$', re.U)
    qrdata = re.sub(fstr, '', txt)
    qrfile = re.sub(fstr, ur'\1', txt.replace(qrdata, ''))
    # get qr
    qrtext = urllib.quote_plus(qrdata.encode('cp1251'))
    u = urllib.urlopen(u'http://qrcoder.ru/code/?%s&10&0' % qrtext)
    data = u.read()
    # write qr
    with open(qrfile, 'wb') as gif:
        gif.write(data)

if __name__ == '__main__':
    os.chdir(sys.path[0])
    main()

Скачать скрипты.

1 комментарий на “QR-code в InDesign для ленивых

  1. Andrew

    Идея интересная. Но я обошелся без Питона. Если заменить иф-ы, в которых определяются системы, на следующие:

    if ($.os.replace(‘Windows’, ») != $.os) {
    var vbs = » +
    ‘Set Http = CreateObject(«Microsoft.XMLHTTP»)\n’ +
    ‘Http.Open «GET», «http://qrcoder.ru/code/?’ + utext + ‘&10&0», True\n’ +
    ‘Http.Send\n’ +
    ‘MsgBox «Press Ok»\n’ +
    ‘pagestatus = Http.status\n’ +
    ‘if pagestatus»200″ then\n’ +
    ‘ URLGet=»Error: » & pagestatus\n’ +
    ‘else\n’ +
    ‘ xdata = Http.responseBody\n’ +
    ‘ Set oStream = CreateObject(«ADODB.Stream»)\n’ +
    ‘ oStream.Open\n’ +
    ‘ oStream.Type = 1\n’ +
    ‘ oStream.Write(xdata)\n’ +
    ‘ oStream.SaveToFile(«‘ + qrfile + ‘»)\n’ +
    ‘end if\n’
    app.doScript(vbs, ScriptLanguage.VISUAL_BASIC);
    }
    if ($.os.replace(‘Macintosh’, ») != $.os) {
    app.doScript(‘do shell script («curl -A/—user-agent ‘ + «\\\»http://qrcoder.ru/code/?» + utext + «&10&0\\\» » + ‘ >> ‘ + qrfile + ‘»)’, ScriptLanguage.APPLESCRIPT_LANGUAGE);
    }

    Как видим под Маком вообще все просто — скрипт на питоне заменен на одну команду curl. Под Windows несколько сложнее. Но все равно если почистить все, что теперь оказалось не нужным получается лучше.

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход /  Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход /  Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход /  Изменить )

Connecting to %s