замена рекомендаций в ридере

в новом интерфейсе ридера возможности рекомендовать записи уже нет, но в API она пока ещё работает. Однако вполне вероятно, что скоро её в ридере не будет вообще. Исполненный этих мрачных предчувствий, я решил построить свой «шаринг», с блекджеком WebDAV и incron.

выбор технологии обусловила моя нездоровая (?) любовь к статическим файлам, которые лежат себе мирно на диске и ведут себя предсказуемо, в отличие от некоторых. Например, скопировав себе всю историю своих рекомендаций, я разбил её на отдельные файлики, каждый из которых содержит один xml-элемент entry из потока, а имя файла соответствует названию записи. Ну и для удобства обращения с 11к файлов я разбил их на папки по месяцам, и установил временем модификации файла момент, когда я рекомендовал эту запись.

такой способ хранения прямо-таки напрашивается на создание потока простой конкатенацией. Нужно только как-то добавить очередной файл в нужный каталог и склеить двадцать последних файлов с префиксом. Для добавления можно использовать встроенную в модный nginx поддержку WebDAV, с которой мне давно хотелось поиграться. А запускать скрипт по изменению в файловой системе может ещё более модный incron.

к сожалению, на виртуальном сервере incron работал не идеально, поэтому на ровном месте пришлось хорошо побиться лбом о стену. Однако удалось добиться того, чтобы при загрузке файла в каталог или его удалении запускался нужный скрипт. Встроенная защита от рекурсии почему-то не работала, пришлось полагаться на старый добрый lock-файл. На всякий случай приведу здесь единственную строчку конфигурации incron:

inbox IN_DELETE,IN_MOVED_TO new-entry.bash

со скриптом тоже внезапно пришлось повозиться — «спасибо» башу за удобство работы с файлами, в имени которых есть пробелы. Вообще-то, сначала я собирался избежать этой проблемы, написав скрипт на питоне, но не хотелось возиться в нём с сортировкой файлов по времени создания. Хорошо, что задача довольно простая: скопировать самый свежий файл из «входящих» в правильный каталог на хранение, удалить самый старый файл во «входящих», подклеить к префиксу все файлы во «входящих»:

ls -t inbox | head -n 1 | xargs -I{} cp "inbox/{}" `date +"entries/%Y-%m/"`
ls -t inbox | tail -n 1 | xargs -I{} rm "inbox/{}"

cat prefix > index.tmp
echo "<updated>" `date --utc --rfc-3339=s | tr ' ' T` "</updated>" >> index.tmp
echo >> index.tmp
ls -t inbox | xargs -I{} cat "inbox/{}" >> index.tmp
echo "</feed>" >> index.tmp

rm index.atom
mv index.tmp index.atom

ну и ещё одни грабли ждали меня при попытке использовать WebDAV. Я помнил, что яваскрипт работает на www.google.com, а моё хранилище — на совсем другом домене, но собирался обойти кроссдоменное ограничение классической отправкой формы в ифрейм. Не тут-то было: обычные html-формы не умеют метод PUT, его можно использовать только в XMLHttpRequest — но он споткнётся о другой домен. Хорошо, что есть postMessage, и что я полностью контролирую свой сервер: маленький прокси меня выручил.

<!doctype html>
<title>proxy</title>
<script>
window.onmessage = function(event) {
    if (!event.origin.match(/^https?:..www.google.com/)) return;
    var url = encodeURIComponent(event.data.name.replace(/\//g, '-'));
    var x = new XMLHttpRequest();
    x.open('PUT', 'http://shared.arty.name/inbox/' + url);
    x.send(event.data.content);
}
</script>

в итоге, когда я нажимаю в ридере кнопку «рекомендовать», происходит вот что:

по-моему, здорово! : ) Сыровато ещё, нужны доделки, но уже работает, да как затейливо! : )

Артемий Трегубенко,
, , ,

comments powered by Disqus