? Editing: Post:21.body Save Delete Cancel
Initial sync in progress...

Newest topics

Follow in NewsfeedFollowing
+ Start new topic
Loading...
stickied

Title

Body
^1 ^2 added ━ started by user_name
More topics

 

Follow in NewsfeedFollowing

Исходники Infonesy

А где же можно пощупать, потыкать, почитать спеки?

^1 ^2 pozya posted on Jul 07, 2017
Please sign innew comment
Sign in as...
Submit comment
You are running out of your allowed space, please contact the site's admin at unknown to raise your limit.
user_nameadded ^1 ^2
Reply
Body
balancer73on Jul 08, 2017 ^1 ^2
Reply

В плане практического кода у меня дело обстоит так. Есть собственный фреймворк (BORS©, страница с ним сейчас недоступна, т.к. лежит на упавшем сервере :D), который пилю лет 15, а корни которого уходят в ~1998-й год. У него есть довольно стандартизированная объектная модель, которой я унифицированно пользуюсь во всех проектах. Поэтому, естественно, что я взял этот подход за программную базу и при написании своих драйверов для Infonesy. Имена полей (и иногда формат) не совпадают с тем, что используется в Infonesy. Но унификация BORS-объектов позволяет работать с ними однообразно. Т.е., например, экспорт в файловый транспорт будет принимать любой BORS-объект и экспортировать его одним методом:

$zeroblog_storage = \Infonesy\Drivers\ZeroBlogStorage::factory(ZERO_DATA_DIR.'/'.$zero_blog_id);

$exporter = new \Infonesy\Transport\ObjectExporter($infonesy_push_dir);

$user = new \Infonesy\Drivers\ZeroBlog('1PniNzyi8fygvwyBaLpA9oBDVWZ5fXuJUw');
$user->set('title', 'Balancer');

$user->set('email_md5', md5('balancer@balancer.ru'));

foreach($zeroblog_storage->load_array(\Infonesy\Drivers\ZeroBlog::class, []) as $post)

{
    $post->set('infonesy_user', $user);

    $exporter->export_md($post);

}

$exporter->export($post->infonesy_container());

$exporter->export($user);

А export_md() выглядит сейчас так:

    function export_md($object)
    {
        $container = $object->infonesy_container();

        $user = $object->infonesy_user();

        $node = $object->infonesy_node();

        $data = [
            'Title' => $object->title(),

            'UUID' => $object->infonesy_uuid(),

//            'Node' => $object->infonesy_node_uuid(),

//            'TopicUUID' : ru.balancer.tt-rss.digest.201304
            'Author' => [

                'Title'        => $user->title(),

                'EmailMD5'    => $user->email_md5(),

                'UUID'        => $user->infonesy_uuid()],

            'Date' => date('r', $object->create_time()),

            'Type' => $object->infonesy_type(),

        ];
        if($mt = $object->modify_time())

            $data['Modify'] = date('r', $mt);
//        $file = trim(preg_replace('![^\w\-]+!', '.', $object->class_name().'-'.$object->id()), '.').'.md';

        $file = $object->infonesy_uuid().'.md';

        $yaml = \Symfony\Component\Yaml\Yaml::dump($data);
        \B2\Files::put_lock("{$this->dir}/$file", "---\n"

            . trim($yaml)
            . "\n---\n\n"
            . '# '.$object->title()."\n\n"

            . $object->source()

        );
    }
balancer73on Jul 08, 2017 ^1 ^2
Reply

А вот тестовый контент-файл для блога, экспорт из ZeroBlog:

---
Title: 'Вторник, 7 мая'
UUID: zeronet.1MaQ4W5D6G52TpBfPACU9k9QcB1DxvHZ5v.post_47
Author:
    Title: Balancer
    EmailMD5: b00aed2adf22fd02381d0bb6bb6a8483
    UUID: zeronet.1PniNzyi8fygvwyBaLpA9oBDVWZ5fXuJUw
Date: 'Wed, 10 May 2017 05:36:19 +0300'
Type: Blog
---

# Вторник, 7 мая

![Popov-Radio.jpg (0x0)](data/img/post_47_Popov-Radio.jpg)

Тут ещё нет ContainerUUID (блог), нет обработки изображений (нужно или отправить аттачем в этот же репо, или через IPFS). Нет, соответственно, ещё и инфо по блогу в отдельном файле.

balancer73on Jul 08, 2017 ^1 ^2
Reply

Что ещё. Имена файлов для простоты поиска у меня совпадают сейчас с UUID.

Полезно добавить в метаданные ещё URL'ы оригинальных объектов. Это будет и прямым указанием, где искать данные в случае каких-то непоняток, и какой-никакой а взнос источнику за то, что он отдал свои данные.

balancer73on Jul 08, 2017 ^1 ^2
Reply

Пример информационного JSON для сообщения в примере выше (т.е. в ZeroTalk это ниже :) — ранее):

{
    "UUID": "ru.balancer.board.topic.59529",
    "Node": "ru.balancer.board",
    "Title": "Фрегаты проекта 11356",
    "Date": "Mon, 07 Oct 2002 16:26:00 +0400",
    "Modify": "Sat, 08 Jul 2017 13:50:42 +0300",
    "Type": "Topic",
    "ForumUUID": "ru.balancer.board.forum.25",
    "Keywords": [
        11356,
        "Адмирал Григорович",
        "Адмирал Макаров",
        "Адмирал Эссен",
        "флот",
        "фрегат",
        "калибр"
    ],
    "Posts": [
        "ru.balancer.board.post.220003",
        "ru.balancer.board.post.220004",
...
        "ru.balancer.board.post.5167569"
    ]
}

Тут поля уже, в общем, понятны из предыдущего описания.

  • Keywords — это теги.
  • Posts — вспомогательный список с UUID всех сообщений. У меня сейчас не используется, но может использоваться форумом приёмником для запроса старых сообщений. Например, когда поднимается древний топик, которого нет в репозитории. В этом случае в репозиторий упадёт только новое сообщение. А старые могут появится по запросу форума-приёмника, если у него их нет.
balancer73on Jul 08, 2017 ^1 ^2
Reply

Пример контентного файла с содержимым постинга:

---
UUID: ru.balancer.board.post.5167561
Node: ru.balancer.board
TopicUUID: ru.balancer.board.topic.59529
Title: 'Фрегаты проекта 11356 [Otstoiy#08.07.17 13:50]'
Author:
    Title: Otstoiy
    EmailMD5: d18e85d1931a4a816b55bce70043fb7c
    UUID: ru.balancer.board.user.109686
Date: 'Sat, 08 Jul 2017 13:50:27 +0300'
Modify: 'Sat, 08 Jul 2017 13:50:27 +0300'
Type: Post
Markup: lcml
AnswerTo: ru.balancer.board.post.5167549
---

тащторанга-01> ... Только не надо заводить шарманку ...

Согласен, не надо заводить шарманку. Давно пора заводить дело с реальными посадками.

Поля:

  • UUID — уникальный глобальный идентификатор объекта. Как правило состоит из UUID ноды-источника и идентификатора внутри ноды.
  • Node — UUID ноды.
  • TopicUUID — UUID топика сообщения с более подробной информацией. Думаю, для унификации нужно переделывать в абстрактный ContainerUUID. Потому что в общем случае это может быть сообщение не в форуме, а в блоге. Сам топик находится в форуме, сейчас там используется ForumUUID, а может быть единообразно с ContainerUUID. Аналогично форум может быть внутри другого форума или категории...
  • Title — заголовок сообщения, может отсутствовать.
  • Author — информация об авторе. Имя, UUID пользователя, MD5 от E-Mail как универсальный идентификатор в системе.
  • Date, Modify — даты создания и последнего изменения сообщения.
  • Type — тип записи (Post, News, Blog...)
  • Markup — язык разметки (формально стандартом является Markdown, но реально пока ходят и BBCode, и моя древняя BBCode-like разметка, LCML)
  • AnswerTo — указание, на какое сообщение отвечают нашим. Актуально для форумов с привязкой сообщений/деревьями.

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

Аналогично с топиками и отсутствющими форумами — пока нет информации о форуме, топик падает в форум-карантин.

balancer73on Jul 08, 2017 ^1 ^2
Reply

pozya: А может начнем со стабилизации спеков протокола? :) Мне вот интересно написать парочку драйверов, но где описание протокола?

«Стандартизированный внутри меня» пока только файловый транспорт. Плюсы:

  • Можно использовать любые средства синхронизации (Syncthing, Rslsync, Rsync/Lsyncd, ZeroNet), в том числе без предварительной договорённости (например, реально работающий Rslsync: B62TG4N5HIF5IRGVKCCFUCRG3SG5VBZYU, ~30+Мб)
  • Одновременно осуществляется и передача обновлений и хранение архива с последними обновлениями
  • Обработчик может принимать простым скриптом изменения в реальном времени через inotifywatch
  • Простая архитектура, можно использовать человекочитаемый синтаксис, можно разбирать репозиторий с данными вручную.

Каждый объект хранится в отдельном файле. Форматов хранения два:

  • Чистый JSON
  • Markdown с метаданными в хедере (YAML в начале файла, отчерченный тройными минусами до и после)

В принципе, драйверам всё равно, какой формат читать, они идентичны по сути, для удобства контентные файлы я сохраняю в Markdown, все остальные — в форматированный JSON.

Тут начинается частично согласованный, частично ещё нет. (В следующих постах)

pozyaon Jul 08, 2017 ^1 ^2
Reply

А может начнем со стабилизации спеков протокола? :) Мне вот интересно написать парочку драйверов, но где описание протокола?

balancer73on Jul 08, 2017 ^1 ^2
Reply
balancer73on Jul 08, 2017 ^1 ^2
Reply

В законченном виде пока нигде :) Есть обрывки вялотекущих пакетов:

А так, корневой репо, где, по идее, должны быть ссылки на всё остальное, тут:

Центральный репо со ссылками на код, с примерами и т.п. должен быть тут:

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

This page is a snapshot of ZeroNet. Start your own ZeroNet for complete experience. Learn More