Node.js на узле Фидонета: автоматизация периодических публикаций

в 13:01, , рубрики: Fido, Fidonet, javascript, node.js, Node.js на узле Фидонета, nodejs, автоматизация, узел, метки: , , , , , ,

Node.js на узле Фидонета: автоматизация периодических публикацийНекоторые фидошники сталкиваются с необходимостью периодически публиковать в той или иной фидонетовской эхоконференции одно и то же сообщение (один и тот же текстовый файл) раз в несколько дней.

Например, модератору (или комодератору, в зависимости от распределения их обязанностей) приходится раз в неделю-другую класть в свою эхоконференцию её правила. Чуть другим (но всё же подобным) примером являются те фидошники, которые взяли на себя поддержку некоторого FAQ и также публикуют его в одной или нескольких тематически соответствующих эхоконференциях. (В эхе Fidonet.History её FAQ содержит своеобразную летопись истории Фидонета, выраженную в вопросах и ответах, в эхе SU.IP.Point — список узлов, набирающих новых пойнтов, в SU.FidoTech — разъяснение ряда технических терминов и алгоритмы нескольких полезных приёмов. В эхоконференциях, посвящённых тому или иному программному продукту, FAQ поясняет его настройку. И так далее.)

Если узел (или пойнт) работает беспрерывно на одном и том же компьютере, то такая публикация автоматизируется простым, бесхитростным способом: публикацию файла вписывают в список задач для демона cron (в UNIX-подобных системах) или его аналога в других системах.

Если же фидонетовская система работает не на одном и том же компьютере (есть ведь фидошники, которые с одного рабочего места на другое таскали с собою комплект фидонетовского софта некогда на дискете, а в новейшее время таскают на флэшке) или хотя бы работает не беспрерывно (а запускается фидошником время от времени, когда в нём рождается желание отправить, получить и почитать фидопочту), то регулярность публикаций обеспечивается иначе — не сервисом (демоном), а простой программою, которая проверяет, не прошло ли ещё столько дней со времени последней публикации файла, сколько необходимо для того, чтобы вдругорядь опубликовать его.

Сегодня мы рассмотрим, каким подспорьем может движок Node.js стать в исполнении этой задачи.

Прежде всего отметим, что значительная часть этой задачи ужé решена.

Для того, чтобы опубликовать файл, достаточно подать команду hpt post эхопроцессору HPT из комплекта программ Husky. (Аналогичные команды существуют и в некоторых других популярных фидонетовских эхопроцессорах.)

Для того, чтобы сохранить (запомнить) дату и время такой публикации, достаточно подать команду touch по отношению к некоторому файлу, обновив дату его последнего изменения. UNIX-подобные операционные системы обыкновенно содержат эту команду в готовом виде, а для Windows её можно скачать с сайта unxutils на SourceForge.

Стало быть, остаётся сочинить только такую команду, которая выполняла бы противоположную задачу — позволяла бы из командной строки считать возраст указанного файла, выраженный в днях, а также сравнить его с некоторым указанным возрастом. И для этой цели нам послужит вот какой JavaScript для Node.js:

var fs = require('fs');
var clog = console.log;

if (process.argv.length < 3) {
   clog('Usage:');
   clog('   node agedays "filename" [N]');
   clog('');
   clog('Parameters:');
   clog('   filename     -- name of the file which age (in days) is checked');
   clog('   N (optional) -- if file is N days old (or older),');
   clog('                   errorlevel 1 is set');
} else if (process.argv.length == 3) {
   try {
      var msec = (new Date()).getTime() -
         fs.statSync(process.argv[2]).mtime.getTime();
      var days = msec / 1000 / 60 / 60 / 24;
      clog('File "' + process.argv[2] + '" is ' + days + ' days old.');
   } catch(e) {
      clog('File "' + process.argv[2] + '" cannot be opened.');
   }
} else {
   try {
      var msec = (new Date()).getTime() -
         fs.statSync(process.argv[2]).mtime.getTime();
      var days = msec / 1000 / 60 / 60 / 24;
      if( days > (+process.argv[3]) ) {
         process.exit(1);
      } else {
         process.exit(0);
      }
   } catch(e) {
      clog('File "' + process.argv[2] + '" cannot be opened.');
      process.exit(2);
   }
}

Сохранив этот скрипт и назвав его agedays.js, мы получаем возможность запускать его для выяснения возраста файла и для сравнения этого возраста с заранее заданным числом. Вот пример таких действий в Windows над файлом areas.cfg:

[скриншот agedays]

Прибавив такое средство к двум ранее имевшимся (к эхопроцессору и touch), мы наконец получаем возможность составить бáтник (файл с командами операционной системы), который и будет выполнять задачу периодической публикации одного или нескольких файлов в Фидонете. Вот для примера тот батник, который употребляется на моём узле под Windows:

@echo off
:checkmonth
node agedays NodePostmonthly._flag 30
if errorlevel 1 goto monthly
goto checkweek

:monthly
utilsunxutilstouch NodePostmonthly._flag

hpt post -nf "Mithgol's Wishlist Robot" -s "Список желаемых функций Голдеда" -e "Ru.GoldEd" -z "Mithgol's NodePost" -o "FGHI Global Headlight Ignited" -f loc NodePostGED_Wish.txt

goto checkweek

:checkweek
node agedays NodePostweekly._flag 7
if errorlevel 1 goto weekly
goto end

:weekly
utilsunxutilstouch NodePostweekly._flag

hpt post -nf "Moderator of Ru.Fidonet.Yo" -s "*** Rules" -e "Ru.Fidonet.Yo" -z "Mithgol's NodePost" -o "FGHI Global Headlight Ignited" -f loc NodePostYoRulez.txt

hpt post -nf "Moderator of Ru.Russophobia" -s "*** Rules" -e "Ru.Russophobia" -z "Mithgol's NodePost" -o "FGHI Global Headlight Ignited" -f loc NodePostPhobRule.txt

hpt post -nf "Moderator of Ru.Russian.1916" -s "*** Rules" -e "Ru.Russian.1916" -z "Mithgol's NodePost" -o "FGHI Global Headlight Ignited" -f loc NodePostrule1916.txt

goto end

:end

Такой батник (в моём примере он называется NodePost.cmd) уместнее всего расположить в том же каталоге, что и HPT, и запускать оттуда же: это позволяет команде «hpt post» обнаружить файл конфигурации HPT в своём рабочем каталоге. Публикуемые батником файлы я сложил в подкаталоге, названном NodePost; там же расположены и файлы-флаги, единственное предназначение которых — быть трогаемыми командою touch и проверяемыми командою agedays.

Вы можете видеть в исходном коде, что этим батником обеспечивается ежемесячная (раз в тридцать дней) публикация одного файла в Ru.GoldED, а также еженедельная (раз в семь дней) рассылка трёх файлов с правилами по трём эхоконференциям Фидонета от официального имени модератора («Moderator of …»).

Строки-команды, начинающиеся со слов «hpt post», достаточно длинны и будут наверняка подвергнуты автоматическому переносу при показе их на Хабрахабре, но в действительности каждая такая команда записывается в одну строку. (Чтобы они не сливались с соседними командами после такого переноса, я для наглядности добавил по одной пустой строке сверху и снизу от каждой команды «hpt post».) После параметра «-nf» записывается то имя отправителя, под которым файл будет отослан в эхоконференцию, а после параметра «-e» — эхотаг этой эхоконференции. После параметров «-s», «-z» и «-o» записывается желаемый заголовок сообщения, его тиарлайн и ориджин. Параметр «-f loc» совершенно необходим для того, чтобы сообщение считалось «локальным» (созданным именно на этой фидонетовской станции) и в дальнейшем было упаковано эхопроцессором как исходящее на другие узлы Фидонета. Последним параметром является имя публикуемого файла.

(Если вместо популярного HPT вы пользуетесь в Фидонете другим эхопроцессором, то все эти сведения позволят вам легко заменить «hpt post» на вызов более подходящей вашему софту команды.)

Большинство элементов вышеизложенного решения (движок Node.js, скрипт agedays, команда touch, эхопроцессор HPT) являются к тому же полисистемными (кросс-платформенными), так что при переносе его с Windows на другую операционную систему вам придётся переписать только батник.

Скрипт agedays.js я выложил на Гитхабе под свободной лицензией MIT, и на этом рассказ мой окончен.

Автор: Mithgol


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js