О проекте

Главная страницаПост
main screenchat screen

Lemmy это аналог таких сайтов как Reddit, Lobste.rs, Raddle, или Hacker News: вы подписываетесь на форумы, которые вас интересуют , размещаете ссылки и дискутируете, затем голосуете и комментируете их. Однако за кулисами всё совсем по-другому; любой может легко запустить сервер, и все эти серверы объединены (например электронная почта) и подключены к одной вселенной, именуемой Федиверс.

Для агрегатора ссылок это означает, что пользователь, зарегистрированный на одном сервере, может подписаться на форумы на любом другом сервере и может вести обсуждения с пользователями, зарегистрированными в другом месте.

Основная цель - создать легко размещаемую, децентрализованную альтернативу Reddit и другим агрегаторам ссылок, вне их корпоративного контроля и вмешательства.

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

Примечание: API-интерфейсы WebSocket и HTTP в настоящее время нестабильны

Почему назвали Lemmy (рус.Лемми)??

Содержит

Возможности

  • Открытое программное обеспечение, Лицензия AGPL.
  • Возможность самостоятельного размещения, простота развёртывания.
  • Понятый и удобный интерфейс для мобильных устройств.
    • Для регистрации требуется минимум: имя пользователя и пароль!
    • Поддержка аватара пользователя.
    • Обновление цепочек комментариев в реальном времени.
    • Полный подсчёт голосов (+/-) как в старом reddit.
    • Темы, включая светлые, темные и солнечные..
    • Эмодзи с поддержкой автозаполнения. Напечатайте :
    • Упоминание пользователя тегом @, Упоминание сообщества тегом !.
    • Интегрированная загрузка изображений как в сообщениях, так и в комментариях.
    • Сообщение может состоять из заголовка и любой комбинации собственного текста, URL-адреса или чего-либо еще.
    • Уведомления, ответы на комментарии и когда вас отметили.
    • Уведомления могут быть отправлены на электронную почту.
    • i18n / поддержка интернационализации.
    • RSS / Atom ленты для Все, Подписок, Входящих, Пользователь, and Сообщества.
  • Поддержка кросс-постинга.
    • Поиск похожих постов при создании новых. Отлично подходит для вопросов / ответов сообществ.
  • Возможности модерации.
    • Журналы (Логи) Публичной Модерации.
    • Можно прикреплять посты в топ сообщества.
    • Оба и администраторы сайта и модераторы сообщества, могут назначать других модераторов.
    • Можно блокировать, удалять и восстанавливать сообщения и комментарии.
    • Можно банить и разблокировать пользователей в сообществе и на сайте.
    • Можно передавать сайт и сообщества другим.
  • Можно полностью стереть ваши данные, удалив все посты и комментарии.
  • NSFW (аббр. Небезопасный/неподходящий для работы) пост / поддерживается сообществом.
  • Высокая производительность.
    • Сервер написан на rust.
    • Фронтэнд (клиентская сторона пользовательского интерфейса) всего ~80kB архив gzipp.
    • Фронтэнд (клиентская сторона пользовательского интерфейса) не использует javascript (только-чтение).
    • Поддерживается архитектура arm64 / устройства Raspberry Pi.

Цели

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

Вопросы

  • Как должно работать голосование? Должны ли мы вернуться к старому способу отображения подсчёта голосов вверх или вниз? Или просто счёт?
  • Определитесь с технологией, которая будет использоваться
    • Бэкэнд: Actix, Diesel.
    • Фронтэнд: inferno, typescript или bootstrap как сейчас.
  • Должен ли быть разрешены боты?
  • Должны быть комментарии / статистика голосований, или в духе чата, например как в flowchat?.
    • Двухпанельная модель - Правая панель для комментариев в реальном времени, левая часть для просмотра актуальной древовидной структуры.
    • Просмотр с мобильных устройств, разрешить переключаться между ними. По умолчанию?

Источники / Потенциальные библиотеки

Тренды / Лучшее / Лучший алгоритм Сортировки

Цели

  • В течение дня новые сообщения и комментарии должны быть вверху, чтобы за них можно было проголосовать.
  • Примерно через день или более того фактор времени должен исчезнуть.
  • Использовать логарифмическую шкалу, так как голоса имеют тенденцию к снежному кому, и поэтому первые 10 голосов так же важны, как и следующие сотни.

Реализации

Reddit

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

Hacker News

Хотя намного превосходит реализацию Reddit по снижению оценок с течением времени, Алгоритм ранжирования Hacker News всё же не использует логарифмическую шкалу для оценок.

Lemmy

Уравновешивает эффект снежного кома голосов с течением времени с помощью логарифмической шкалы. Сводит на нет неотъемлемое преимущество ранних комментариев, но при этом гарантирует, что голоса по-прежнему имеют значение в долгосрочной перспективе, не разрушая старые популярные комментарии.

Rank = ScaleFactor * log(Max(1, 3 + Score)) / (Time + 2)^Gravity

Score = Upvotes - Downvotes
Time = time since submission (in hours)
Gravity = Decay gravity, 1.8 is default
  • В Lemmy такой же алгоритм Классификатор как наверху, разделяя на два: Активный, и Лучший.
    • Активный использует голосование за публикацию и время последнего комментария (ограничено двумя днями).
    • Лучший использует голоса за публикацию и время опубликования.
  • Используйте Макс (1, балл), чтобы убедиться, что на все комментарии влияет замедление времени.
  • Прибавьте 3 балла, чтобы все, у кого меньше 3 голосов против, выглядили новыми. В противном случае все новые комментарии останутся нулевыми, внизу.
  • Знаки и абв оценки необходимы для работы с журналом отрицательных оценок.
  • Масштабный коэффициент 10k получает ранг в целочисленной форме.

График ранга за 24 часа, баллов 1, 5, 10, 100, 1000 с масштабным коэффициентом 10k.

Подсчёты Активных Пользователей

Lemmy также показывает количество * активных пользователей * для вашего сайта и его сообществ. Они подсчитываются в течение последнего дня, недели, месяца и полугодия и кэшируются при запуске lemmy и каждый час.

Активный пользователь - это тот, кто опубликовал или прокомментировал на вашем инстансе или сообществе в течение последнего заданного периода времени. При подсчете сайтов учитываются только локальные пользователи. В подсчет сообщества включены федеративные пользователи.

Путеводитель по Lemmy

Начните печатать...

  • @a_user_name для получения списка пользователей.
  • !a_community для получения списка сообществ.
  • :emoji для получения списка эмодзи.

Сортировка

Применяется как к сообщениям, так и к комментариям

ТипОписание
АктивностьСортировка на основе оценки подсчёта баллов со времени последнего комментария
ПопулярныеСортировка на основе оценки подсчёта баллов с даты создания поста.
НовыеНовинки.
Наиболее КомментируемыеПосты с наибольшим количеством комментариев.
Новые КомментарииПосты снаибольшим колличеством комментариев, Т.е. сортировка в стиле форума.
ЛучшиеС наивысшим количеством баллов заданный период времени.

Детали можно посмотреть по ссылке Посты и оценка комментариев в деталях.

Модерация / Администрирование

Все действия модераторов и администраторов над комментариями и постами пользователей осуществляются посредством нажатия на More 3-точечную иконку.

Сюда входят:

  • Добавление / Удаление модераторов и админов.
  • Удаление / Восстановление комментариев.
  • Банить / Разбанивать пользователей.

Все действия администратора в сообществах выполняются на боковой панели сообщества. На текущий момент возможно только Удаление / Восстановление сообществ.

Путеводитель по Markdown

НаберитеИли… Получите
*Курсив*_Курсив_Курсив
**Жирный**__Жирный__Жирный шрифт
# Заголовок 1Заголовок 1
=========

Заголовок 1

## Заголовок 2Заголовок 2
---------
Заголовок 2
[Ссылка](http://a.com)[Ссылка][1]

[1]: http://b.org
Ссылка
![Изображение](http://url/a.png)![Изображение][1]

[1]: http://url/b.jpg
Markdown
> Цитата
Цитата
* Списки
* Списки
* Списки
- Списки
- Списки
- Списки
* Списки
* Списки
* Списки
1. Один
2. Два
3. Три
1) Один
2) Два
3) Три
1. Один
2. Два
3. Три
Подчёркивания
---
Подчёркивания
***
Подчёркивания

`Инлайн код` с обратными кавычкамиИнлайн код с обратными кавычками
```
# блок кода
print '3 кавычки или'
отбить 'отступ 4 пробела'
```
····# блок кода
····отбить '3 кавычки или'
····отбить 'отступ 4 пробела'
# блок кода
print '3 кавычки или'
отбить 'отступ 4 пробела'
::: спрятать спойлер или материал nsfw
внести сюда
:::
спрятанный или nsfw материал

внести сюда

~подстрочный~ текстSome подстрочный текст
^надстрочный^ текстSome надстрочный текст

CommonMark Tutorial

Информация для администраторов

Информация для администраторов интсанса Lemmy и тех кто хочет запустить собственный сервер.

Установка

У Lemmy есть два основных метода установки: вручную с помощью Docker и автоматизированная с помощью Ansible. Мы рекомендуем использовать Ansible, потому что он упрощает установку, а также упрощает обновление.

Другие методы установки

В некоторых случаях может потребоваться использовать различные методы установки. Но мы этого не рекомендуем и не сможем оказать поддержку для них.

Установка Docker

Убедитесь в наличии установленных docker и docker-compose (>=1.24.0) . В Ubunu, просто запустите apt install docker-compose docker.io. Далее,

# создайте папку для файлов lemmy. путь не имеет значения, размещайте файлы где угодно
mkdir /lemmy
cd /lemmy

# загрузите кнфигурацию по умолчанию
wget https://raw.githubusercontent.com/LemmyNet/lemmy/main/docker/prod/docker-compose.yml
wget https://raw.githubusercontent.com/LemmyNet/lemmy/main/docker/lemmy.hjson
wget https://raw.githubusercontent.com/LemmyNet/lemmy/main/docker/iframely.config.local.js

# Установите корректные разрешения для каталога pictrs
mkdir -p volumes/pictrs
sudo chown -R 991:991 volumes/pictrs

Откройте docker-compose.yml, и убедитесь в наличии LEMMY_EXTERNAL_HOST для lemmy-ui это позволит установить корректный host.

- LEMMY_INTERNAL_HOST=lemmy:8536
- LEMMY_EXTERNAL_HOST=your-domain.com
- LEMMY_HTTPS=false

Если хотите установить другой пароль для БД, вы также должны изменить его в docker-compose.yml перед первым запуском.

После этого, загляните Кофигурационный файл под названием lemmy.hjson, и настройте его, в частности hostname, и возможно пароль БД. Затем запустите:

docker-compose up -d

Вы можете войти в lemmy-ui через http://localhost:1235

Для того чтобы сделать Lemmy доступным в сети, вам необходимо настроить reverse proxy, например Nginx. Пример конфигурации nginx, could be setup with:

wget https://raw.githubusercontent.com/LemmyNet/lemmy/main/ansible/templates/nginx.conf
# Replace the {{ vars }}
# The default lemmy_port is 8536
# The default lemmy_ui_port is 1235
sudo mv nginx.conf /etc/nginx/sites-enabled/lemmy.conf

Вам также необходимо настроить TLS, например с Let's Encrypt. После этого перезапустите Nginx для подгрузки конфигурации.

Обновление

Для обновления до новой версии, вы можете изменить версию вручнуюy в docker-compose.yml. Как альтернатива, получите последнюю версию из нашего репозитария git:

wget https://raw.githubusercontent.com/LemmyNet/lemmy/main/docker/prod/docker-compose.yml
docker-compose up -d

Установка Ansible

Это то же самое, что и установка Docker, за исключением того, что Ansible обрабатывает всё это автоматически. Он также выполняет некоторые дополнительные действия, такие как настройка TLS и электронной почты для вашего экземпляра Lemmy.

Прежде всего вам нужны установка Ansible на ваш локальный компьютер. Вам также необходимо будет установить Docker SDK для Python используя pip install docker (больше информации в документации Ansible).

Затем запустите следующую команду на вашем локальном компьютере:

git clone https://github.com/LemmyNet/lemmy.git
cd lemmy/ansible/
cp inventory.example inventory
nano inventory # enter your server, domain, contact email
# If the command below fails, you may need to comment out this line
# In the ansible.cfg file:
# interpreter_python=/usr/bin/python3
ansible-playbook lemmy.yml --become

Для обновления до новой версии, просто запустите следующее в локальном репозитарии Lemmy:

git pull origin main
cd ansible
ansible-playbook lemmy.yml --become

Другие методы установки

Отказ от ответственности: эти методы установки не рекомендуются разработчиками Lemmy. Если у вас возникнут проблемы, вам нужно решать их самостоятельно или спросить соответствующих авторов. Если вы заметили какие-либо ошибки Lemmy в установленном таким образом экземпляре, укажите это в отчете об ошибке.

Установка Lemmy без Docker

Изначальная инструкция по установке Lemmy, не полагаясь на Docker.

https://lemmy.ca/post/1066

Установка на Amazon Web Services (AWS)

Здесь содержатся необходимые определения инфраструктуры для развертывания Lemmy в AWS используя их Cloud Development Kit.

https://github.com/jetbridge/lemmy-cdk

Конфигурация

Конфигурация основана на файле config.hjson. Этот файл также содержит документацию по всем доступным параметрам. В инструкциях по установке рассказывается, как изменить настройки по умолчанию.

Файл config.hjson находится в config/config.hjson. Чтобы изменить расположение по умолчанию, вы можете установить переменную среды LEMMY_CONFIG_LOCATION.

Дополнительная переменная среды LEMMY_DATABASE_URL доступна, который можно использовать со строкой подключения PostgreSQL, например postgres://lemmy:password@lemmy_db:5432/lemmy, передача всех деталей подключения сразу.

Если контейнер Docker не используется, вручную создайте базу данных, указанную выше, выполнив следующие команды:

cd server
./db-init.sh

Federation

Lemmy использует протокол ActivityPub (стандарт W3C) для обеспечения федерации между различными серверами (часто называемыми инстансами). Это очень похоже на то, как работает электронная почта. Например, если вы используете gmail.com, то вы можете отправлять письма не только другим пользователям gmail.com, но и yahoo.com, yandex.ru и так далее. Для этого в электронной почте используется протокол SMTP, поэтому ActivityPub можно рассматривать как «SMTP для социальных сетей». Количество различных действий, возможных в социальных сетях (публикация, комментарий, лайк, публикация и т. Д.), Означает, что ActivityPub намного сложнее, чем SMTP.

Как и в случае с электронной почтой, федерация ActivityPub происходит только между серверами. Итак, если вы зарегистрированы на enterprise.lemmy.ml, вы подключаетесь только к API enterprise.lemmy.ml, в то время как сервер берет на себя отправку и прием данных от других экземпляров (например voyager.lemmy.ml). Большим преимуществом этого подхода является то, что обычному пользователю не нужно ничего делать, чтобы использовать федерацию. Фактически, если вы используете Lemmy, вы, вероятно, уже используете его. Один из способов подтвердить это - зайти в сообщество или в профиль пользователя. Если ты на enterprise.lemmy.ml и вы видите пользователя вроде @nutomic@voyager.lemmy.ml, или такое сообщество, как !main@ds9.lemmy.ml, тогда они федерированы, то есть они используют инстанс, отличный от вашего.

Один из способов воспользоваться преимуществами федерации - открыть другой инстанст, например ds9.lemmy.ml, и просмотреть его. Если вы видите интересное сообщество, сообщение или пользователя, с которым хотите взаимодействовать, просто скопируйте его URL и вставьте его в поиск своего собственного экземпляра. Ваш инстанс будет подключаться к другому (при условии, что это разрешено списком разрешений / блокировок) и напрямую отображать удаленный контент для вас, чтобы вы могли следить за сообществом или комментировать сообщение. Вот несколько примеров рабочих примеров:

  • !main@lemmy.ml (Сообщество)
  • @nutomic@lemmy.ml (Пользователь)
  • https://lemmy.ml/c/programming (Сообщество)
  • https://lemmy.ml/u/nutomic (Пользователь)
  • https://lemmy.ml/post/123 (Пост)
  • https://lemmy.ml/comment/321 (Комментарий)

Вы можете увидеть список связанных экземпляров, перейдя по ссылке «Инстансы» внизу любой страницы Lemmy.

Получение сообществ

При первом поиске сообщества сначала выбирается 20 сообщений. Только если хотя бы один пользователь на вашем экземпляре подписывается на удаленное сообщество, сообщество будет отправлять обновления на ваш экземпляр. Обновления включают:

  • Новые сообщения, комментарии
  • Голосования
  • Публикации, редактирования и удаление комментариев
  • Действия модераторов

Вы можете скопировать URL-адрес сообщества из адресной строки браузера и вставить его в поле поиска. Подождите несколько секунд, пост появится внизу. На данный момент нет индикатора загрузки для поиска, поэтому подождите несколько секунд, если он показывает «нет результатов».

Получение постов

Вставьте URL-адрес публикации в поле поиска вашего экземпляра Lemmy. Подождите несколько секунд, пока не появится сообщение. Это также приведёт к получению профиля сообщества и профиля создателя сообщения.

Получение сообщений

Если вы найдете интересный комментарий под сообщением на другом инстансе, вы можете найти под комментарием в трехточечном меню символ ссылки. Скопируйте эту ссылку. Это выглядит как https://lemmy.ml/post/56382/ comment/40796. Удалите часть post/XXX и поместите её в строку поиска. В этом примере выполните поиск по запросу https://lemmy.ml/comment/40796. Этот комментарий, все родительские комментарии, пользователи и сообщество, а также соответствующая публикация извлекаются из удаленного экземпляра, если они не известны локально.

Родственные комментарии не загружаются! Если вам нужно больше комментариев к более старым сообщениям, вам нужно найти каждый из них, как описано выше.

Решения проблем

Различные проблемы, которые могут возникнуть на новом инстансе и способы их решения.

Многие функции Lemmy зависят от правильной конфигурации reverse proxy. Убедитесь, что ваш, эквивалентен нашему конфигурационному файлу nginx.

Главное

Журналы

При возникновении проблем с интерфейсом проверьте браузерную консоль для любых сообщениях об ошибки.

Для журналов сервера запустите docker-compose logs -f lemmy в вашей инсталяционной папке. Вы также можете запустить docker-compose logs -f lemmy lemmy-ui pictrs для получения журнала от различных сервисов.

Если этого недостаточно, попробуйте изменить строку RUST_LOG=error в docker-compose.yml на RUST_LOG=info или RUST_LOG=verbose, затем сделайте docker-compose restart lemmy.

Создание пользователя с правами администратора не работает

Убедитесь, что websocket работает правильно, проверив консоль браузера на наличие ошибок. В nginx для этого важны следующие заголовки:

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

Ошибка ограничения скорости, когда на сайт заходят множество пользователей

Убедитесь, что заголовки X-Real-IP и X-Forwarded-For отправляются в Lemmy посредством reverse proxy. В противном случае он будет считать все действия в соответствии с ограничением скорости IP-адреса обратного прокси-сервера. В nginx это должно выглядеть так:

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

Федерация

Другие инстансы не могут получать локальные объекты (сообщество, пост и т.д.)

Ваш reverse proxy (например nginx) должен пересылать запросы с заголовком Accept: application/activity+json в бэкэнд. Это обрабатывается следующими строками:

set $proxpass "http://0.0.0.0:{{ lemmy_ui_port }}";
if ($http_accept = "application/activity+json") {
set $proxpass "http://0.0.0.0:{{ lemmy_port }}";
}
if ($http_accept = "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"") {
set $proxpass "http://0.0.0.0:{{ lemmy_port }}";
}
proxy_pass $proxpass;

Вы можете проверить, что он работает правильно, выполнив следующие команды, все они должны возвращать действительный JSON:

curl -H "Accept: application/activity+json" https://your-instance.com/u/some-local-user
curl -H "Accept: application/activity+json" https://your-instance.com/c/some-local-community
curl -H "Accept: application/activity+json" https://your-instance.com/post/123 # the id of a local post
curl -H "Accept: application/activity+json" https://your-instance.com/comment/123 # the id of a local comment

Получение удаленных объектов работает, но публикации/комментирование в удаленных сообществах не успешны.

Проверьте это федерация разрешена в обоих случаях.

Также убедитесь, что на вашем сервере установлено точное время. Действия подписываются меткой времени и будут отброшены, если она отключена более чем на 10 секунд.

Резервное копирование и восстановление

Docker и Ansible

При использовании docker или ansible, должен быть создан каталог volumes , содержащий обе базы данных, и все изображения. Скопируйте этот каталог в новый инстанс для восстановления ваших данных.

Инкрементное резервное копирование базы данных

Для инкрементного резервного копирование БД в .sql файл, вы можете запустить:

docker-compose exec postgres pg_dumpall -c -U lemmy >  lemmy_dump_`date +%Y-%m-%d"_"%H_%M_%S`.sql

Пример сценария резервного копирования

#!/bin/sh
# DB Backup
ssh MY_USER@MY_IP "docker-compose exec postgres pg_dumpall -c -U lemmy" >  ~/BACKUP_LOCATION/INSTANCE_NAME_dump_`date +%Y-%m-%d"_"%H_%M_%S`.sql

# Volumes folder Backup
rsync -avP -zz --rsync-path="sudo rsync" MY_USER@MY_IP:/LEMMY_LOCATION/volumes ~/BACKUP_LOCATION/FOLDERNAME

Восстановление БД

Если вам необходимо восстановить из pg_dumpall файла, для начала необходимо очистить уже существующую БД

# Сбросьте существующую БД
docker exec -i FOLDERNAME_postgres_1 psql -U lemmy -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"

# Восстановите БД из резервного .sql 
cat db_dump.sql  |  docker exec -i FOLDERNAME_postgres_1 psql -U lemmy # restores the db

# Возможно при импортировании БД, вам понадобится установить новый пароль, отличающийся от предыдущего.
docker exec -i FOLDERNAME_postgres_1 psql -U lemmy -c "alter user lemmy with password 'bleh'"

Изменение вашего доменного имени

Если вы еще не федерируетесь, вы можете изменить свое доменное имя в БД. Внимание: не делайте этого после начала федерирования, иначе сломаете процесс федерации.

Зайдите в psql вашего docker :

docker-compose exec postgres psql -U lemmy

-- Post
update post set ap_id = replace (ap_id, 'old_domain', 'new_domain');
update post set url = replace (url, 'old_domain', 'new_domain');
update post set body = replace (body, 'old_domain', 'new_domain');
update post set thumbnail_url = replace (thumbnail_url, 'old_domain', 'new_domain');

-- Comments
update comment set ap_id = replace (ap_id, 'old_domain', 'new_domain');
update comment set content = replace (content, 'old_domain', 'new_domain');

-- User
update user_ set actor_id = replace (actor_id, 'old_domain', 'new_domain');
update user_ set inbox_url = replace (inbox_url, 'old_domain', 'new_domain');
update user_ set shared_inbox_url = replace (shared_inbox_url, 'old_domain', 'new_domain');
update user_ set avatar = replace (avatar, 'old_domain', 'new_domain');

-- Community
update community set actor_id = replace (actor_id, 'old_domain', 'new_domain');
update community set followers_url = replace (followers_url, 'old_domain', 'new_domain');
update community set inbox_url = replace (inbox_url, 'old_domain', 'new_domain');
update community set shared_inbox_url = replace (shared_inbox_url, 'old_domain', 'new_domain');

Больше информации

  • https://stackoverflow.com/questions/24718706/backup-restore-a-dockerized-postgresql-database

Federation

Обзор Федерации

Этот документ предназначен для всех, кто хочет знать, как работает федерация Lemmy, не вдаваясь в технические подробности. Он предназначен для предоставления общего принципа работы федерации ActivityPub в Lemmy. Если вы сами реализуете ActivityPub и хотите быть совместимым с Lemmy, прочтите наши ActivityPub API outline.

Соглашения документации

Чтобы не усложнять, иногда вы можете увидеть вещи в формате Create/Note или Delete/Event или Undo/Follow. То, что перед косой чертой - это Activity, а то, что после косой черты - это объект внутри Activity в свойстве object. Итак, это следует читать следующим образом:

  • Create / Note: действие Create, содержащее Note в поле object.
  • Delete / Event: действие Delete, содержащее Event в поле object
  • Undo / Follow: действие Undo, содержащее Follow в поле object

В Lemmy мы используем определенные термины для обозначения элементов ActivityPub. По сути, это наши конкретные реализации хорошо известных концепций ActivityPub:

  • Сообщество: Group
  • Пользователь: Person
  • Пост: Page
  • Комментарий: Note

Этот документ состоит из трех основных разделов:

  • Философия федерации излагает общую модель того, как это должно быть федеративным
  • Действия пользователя описывает, какие действия может предпринять Пользователь для взаимодействия
  • Активность сообщества описывает, что Сообщество делает в ответ на определенные действия Пользователя.

Философия федерации

Основным действующим лицом в «Lemmy» является Сообщество. Каждое сообщество находится в единственном экземпляре и состоит из списка сообщений и списка подписчиков. Основное взаимодействие заключается в том, что Пользователь отправляет пост или комментарий, связанный с публикацией или комментарием в сообществе, который затем аннонсируется об этом всем подписчикам.

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

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

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

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

Наша реализация федерации уже завершена, но на данном этапе, мы не совсем сосредоточились на соблюдении спецификации ActivityPub. В связи с этим, Lemmy, пока, несовместима с реализациями, которые должны давать возможность отправлять и получать рабочую активность. Это то, что мы планируем исправить в ближайшем будущем. Проверить #698 обзор наших несоответствий.

Действия пользователя

Следовать за сообществом

На каждой странице сообщества есть кнопка «Подписаться». Нажатие на нее запускает действие Follow, которое будет отправлено пользователем в почтовый ящик сообщества. Сообщество автоматически ответит на почтовый ящик пользователя действием Accept/Follow. Он также добавит пользователя в свой список подписчиков и предоставит пользователю информацию о сообщениях и комментариях в Сообществе.

Отписаться от Сообщества

После подписки на сообщество кнопка «Подписаться» заменяется на «Отписаться». При нажатии на нее в почтовый ящик Сообщества отправляется действие Accept/Follow. Сообщество удаляет пользователя из списка подписчиков и больше не отправляет ему никаких действий.

Создать пост

Когда пользователь создает новое сообщение в определённом сообществе, оно отправляется как Create/Page в входящие Сообщества.

Создать комментарий

Когда новый комментарий создается для сообщения, идентификатор сообщения и родительский идентификатор комментария (если он существует) указывается в поле in_reply_to. Это позволяет привязать его к нужному посту и построить дерево комментариев. Затем он отправляется во входящие сообщения сообщества как Create/Note

Экземпляр-источник также сканирует комментарий на предмет упоминания любого пользователя и отправляет Create/Note этим Пользователям.

Редактировать Пост

Изменение содержания существующей публикации. Может быть выполнено только создавшим его пользователем.

Редактировать комментарий

Изменение содержания существующего комментария. Может быть выполнено только создавшим его пользователем.

Нравится и Не нравится

Пользователям могут нравится или не нравится любые сообщения или комментарии. Они отправляются Like/Page, Dislike/Note и т.д. в ящик Сообщества.

Удаление

Создатель сообщения, комментария или сообщества может его удалить. Об этом сообщается подписчикам сообщества. Затем элемент скрывается от всех пользователей.

Удаления

Модераторы могут удалять сообщения и комментарии из своих сообществ. Администраторы могут удалять любые сообщения или комментарии со всего сайта. Сообщества также могут быть удалены администраторами. Затем элемент скрывается от всех пользователей.

Об удалении сообщается всем подписчикам Сообщества, поэтому они вступают в силу и там. Исключение составляют случаи, когда администратор удаляет элемент из Сообщества, размещенного в другом экземпляре. В этом случае удаление вступает в силу только локально.

Отмена предыдущего действия

Мы ничего не удаляем из нашей базы данных, просто скрываем это от пользователей. Удаленные или удаленные Сообщества/Сообщения/Комментарии имеют кнопку «восстановить». Эта кнопка Undo генерирует восстановление оригинала удалённой активности как объекта, такого как Undo/Remove/Post или Undo/Delete/Community.

Нажатие кнопки "нравится" за публикацию/комментарий, за которую уже проголосовали (или кнопку "не нравится" для публикации/комментария, за которую уже проголосовали), также генерирует сообщение как Undo. В этом случае Undo/Like/Post или Undo/Dislike/Comment.

Создать личное сообщение

В профилях пользователей есть кнопка «Отправить сообщение», которая открывает диалоговое окно, позволяющее отправить личное сообщение этому пользователю. Отправляется как Create/Note во Входящие пользователя. Личные сообщения могут быть адресованы только одному,конкретному Пользователю.

Редактирование личного сообщения

Update/Note изменяет текст предыдущего отправленного сообщения.

Удалить личное сообщение

Delete/Note удаляет личное сообщение.

Восстановить личное сообщение

Undo/Delete/Note возвращает удалённое личное сообщение.

Активность Сообщества

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

Подтверждение подписки

Если Сообщество получает Follow активность, это автоматически активирует ответ Accept/Follow. И добавляет Пользователя в список подписавшихся.

Не следовать

Однажды получив Undo/Follow, Сообщество удаляет Пользователя из списка подписчиков.

Уведомление

Если Сообщество получает какие-либо действия, связанные с публикациями или комментариями (Создать, Обновить, Нравится, Не нравится, Удалить, Убрать, Отменить), оно Уведомляет об этом своих подписчикам. В связи с этим, Уведомление создаётся как действие , и принимается как объект активности. Таким образом, следующие экземпляры будут в курсе любых действий в сообществах, за которыми они следят.

Удалить Сообщество

Если создатель или администратор удаляет Сообщество, это отправляет Delete/Group всем его подписчикам.

Источники ActivityPub

Официальные документы

Пояснения

Примеры и Библиотеки

Протокол Федерации в Lemmy

Протокол Lemmy (или протокол Lemmy Federation) - это строгое подмножество протокола ActivityPub. Любое отклонение от протокола ActivityPub является ошибкой в Lemmy или в этой документации (или в обоих).

Этот документ предназначен для разработчиков, знакомых с протоколами ActivityPub и ActivityStreams. Он дает подробное описание моделей акторов, объектов и действий, используемых Lemmy.

Прежде чем читать это, взгляните на наш Обзор федерации, чтобы получить представление о том, как федерация Lemmy работает на высшем уровне.

Lemmy еще не во всех отношениях следует спецификации ActivityPub. Например, мы не устанавливаем допустимый контекст, указывающий на наши поля контекста. Мы также игнорируем такие поля, как «inbox», «outbox» или «endpoints» для удалённых участников и предполагаем, что все принадлежит Lemmy. Для обзора девиаций прочтите #698. Они будут исправлены в ближайшее время.

Lemmy также не очень гибкий, когда речь идет о входящих действиях и объектах. Они должны быть в точности идентичны приведенным ниже примерам. Такие вещи, как наличие массива вместо одного значения или идентификатора объекта вместо полного объекта, приведут к ошибке.

В следующих таблицах «обязательный» означает, будет ли Lemmy принимать входящие действия без этого поля. Сам Lemmy всегда будет включать все непустые поля.

Аннотация

{
    "@context": [
        "https://www.w3.org/ns/activitystreams",
        {
            "moderators": "as:moderators",
            "sc": "http://schema.org#",
            "stickied": "as:stickied",
            "sensitive": "as:sensitive",
            "pt": "https://join.lemmy.ml#",
            "comments_enabled": {
                "type": "sc:Boolean",
                "id": "pt:commentsEnabled"
            }
        },
        "https://w3id.org/security/v1"
    ]
}

Аннотация одинакова для всех действий и объектов.

Акторы

Сообщество

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

Отправляет действия пользователю: Accept/Follow, Announce

:Получает действия от пользователя: Follow, Undo/Follow, Create, Update, Like, Dislike, Remove (только администратор/модератор), Delete (только создатель), Undo (только для собственных действий)

{
    "@context": ...,
    "id": "https://enterprise.lemmy.ml/c/main",
    "type": "Group",
    "preferredUsername": "main",
    "name": "The Main Community",
    "sensitive": false,
    "content": "Welcome to the default community!",
    "mediaType": "text/html",
    "source": {
        "content": "Welcome to the default community!",
        "mediaType": "text/markdown"
    },
    "icon": {
        "type": "Image",
        "url": "https://enterprise.lemmy.ml/pictrs/image/Z8pFFb21cl.png"
    },
    "image": {
        "type": "Image",
        "url": "https://enterprise.lemmy.ml/pictrs/image/Wt8zoMcCmE.jpg"
    },
    "inbox": "https://enterprise.lemmy.ml/c/main/inbox",
    "outbox": "https://enterprise.lemmy.ml/c/main/outbox",
    "followers": "https://enterprise.lemmy.ml/c/main/followers",
    "moderators": "https://enterprise.lemmy.ml/c/main/moderators",
    "endpoints": {
        "sharedInbox": "https://enterprise.lemmy.ml/inbox"
    },
    "published": "2020-10-06T17:27:43.282386+00:00",
    "updated": "2020-10-08T11:57:50.545821+00:00",
    "publicKey": {
        "id": "https://enterprise.lemmy.ml/c/main#main-key",
        "owner": "https://enterprise.lemmy.ml/c/main",
        "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9JJ7Ybp/H7iXeLkWFepg\ny4PHyIXY1TO9rK3lIBmAjNnkNywyGXMgUiiVhGyN9yU7Km8aWayQsNHOkPL7wMZK\nnY2Q+CTQv49kprEdcDVPGABi6EbCSOcRFVaUjjvRHf9Olod2QP/9OtX0oIFKN2KN\nPIUjeKK5tw4EWB8N1i5HOuOjuTcl2BXSemCQLAlXerLjT8xCarGi21xHPaQvAuns\nHt8ye7fUZKPRT10kwDMapjQ9Tsd+9HeBvNa4SDjJX1ONskNh2j4bqHHs2WUymLpX\n1cgf2jmaXAsz6jD9u0wfrLPelPJog8RSuvOzDPrtwX6uyQOl5NK00RlBZwj7bMDx\nzwIDAQAB\n-----END PUBLIC KEY-----\n"
    }
}
Имя в полеОбязательноОписание
preferredUsernameдаИмя актора
nameдаНазвание сообщества
sensitiveдаПравда указывает на то, что все сообщения в сообществе NSFW
attributedToдаСначала создатель сообщества, затем все остальные модераторы
contentнетТекст для боковой панели сообщества, обычно содержащий описание и правила
iconнетЗначок, отображаемый рядом с названием сообщества
imageнетИзображение баннера, отображаемое вверху страницы сообщества
inboxнетURL-адрес папки входящих сообщений ActivityPub
outboxнетURL-адрес исходящего сообщения ActivityPub, содержит только до 20 последних сообщений, без комментариев, голосов или других действий
followersнетURL-адрес коллекции подписчиков, содержит только количество подписчиков, без ссылок на отдельных подписчиков
endpointsнетСодержит URL общего почтового ящика
publishedнетДата и время, когда сообщество было впервые создано
updatedнетДата и время последнего изменения сообщества
publicKeyдаОткрытый ключ, используемый для проверки подписей этого актора

Исходящие Сообщения Сообщества

{
    "@context": ...,
    "items": [
      ...
    ],
    "totalItems": 3,
    "id": "https://enterprise.lemmy.ml/c/main/outbox",
    "type": "OrderedCollection"
}

Исходящие содержат только Create/Post мероприятия на данный момент.

Подписчики Сообщества

{
  "totalItems": 2,
  "@context": ...,
  "id": "https://enterprise.lemmy.ml/c/main/followers",
  "type": "Collection"
}

Коллекция подписчиков используется только для отображения количества подписчиков. Идентификаторы участников не включены, чтобы защитить конфиденциальность пользователей.

Модераторы Сообщества

{
    "items": [
        "https://enterprise.lemmy.ml/u/picard",
        "https://enterprise.lemmy.ml/u/riker"
    ],
    "totalItems": 2,
    "@context": ...,
    "id": "https://enterprise.lemmy.ml/c/main/moderators",
    "type": "OrderedCollection"
}

Пользователь

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

Отправляет действия в Сообщество: Follow, Undo/Follow, Create, Update, Like, Dislike, Remove (только администратор/модератор), Delete (только создатель), Undo (только для собственных действий)

Получает действия от сообщества: Accept/Follow, Announce

Отправляет и получает действия от/для других пользователей: Create/Note, Update/Note, Delete/Note, Undo/Delete/Note (все, что связано с личными сообщениями)

{
    "@context": ...,
    "id": "https://enterprise.lemmy.ml/u/picard",
    "type": "Person",
    "preferredUsername": "picard",
    "name": "Jean-Luc Picard",
    "content": "The user bio",
    "mediaType": "text/html",
    "source": {
        "content": "The user bio",
        "mediaType": "text/markdown"
    },
    "icon": {
        "type": "Image",
        "url": "https://enterprise.lemmy.ml/pictrs/image/DS3q0colRA.jpg"
    },
    "image": {
        "type": "Image",
        "url": "https://enterprise.lemmy.ml/pictrs/image/XenaYI5hTn.png"
    },
    "inbox": "https://enterprise.lemmy.ml/u/picard/inbox",
    "endpoints": {
        "sharedInbox": "https://enterprise.lemmy.ml/inbox"
    },
    "published": "2020-10-06T17:27:43.234391+00:00",
    "updated": "2020-10-08T11:27:17.905625+00:00",
    "publicKey": {
        "id": "https://enterprise.lemmy.ml/u/picard#main-key",
        "owner": "https://enterprise.lemmy.ml/u/picard",
        "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyH9iH83+idw/T4QpuRSY\n5YgQ/T5pJCNxvQWb6qcCu3gEVigfbreqZKJpOih4YT36wu4GjPfoIkbWJXcfcEzq\nMEQoYbPStuwnklpN2zj3lRIPfGLht9CAlENLWikTUoW5kZLyU6UQtOGdT2b1hDuK\nsUEn67In6qYx6pal8fUbO6X3O2BKzGeofnXgHCu7QNIuH4RPzkWsLhvwqEJYP0zG\nodao2j+qmhKFsI4oNOUCGkdJejO7q+9gdoNxAtNNKilIOwUFBYXeZJb+XGlzo0X+\n70jdJ/xQCPlPlItU4pD/0FwPLtuReoOpMzLi20oDsPXJBvn+/NJaxqDINuywcN5p\n4wIDAQAB\n-----END PUBLIC KEY-----\n"
    }
}
Имя в полеОбязательноОписание
preferredUsernameдаИмя Актора
nameнетОтображаемое имя пользователя
contentнетБИО пользователя
iconнетАватар пользователя, отображаемый рядом с именем пользователя
imageнетБаннер пользователя, отображаемый в верхней части профиля
inboxнетURL-адрес папки входящих сообщений ActivityPub
endpointsнетСодержит URL общего почтового ящика
publishedнетДата и время, когда пользователь зарегистрировался
updatedнетДата и время последнего изменения профиля пользователя
publicKeyдаОткрытый ключ используется для проверки подписей из этого актора

Входящие Пользователя

{
    "items": [],
    "totalItems": 0,
    "@context": ...,
    "id": "http://lemmy-alpha:8541/u/lemmy_alpha/outbox",
    "type": "OrderedCollection"
}

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

Объект

Пост

Страница с заголовком и необязательным URL-адресом и текстовым содержимым. URL-адрес часто ведет к изображению и в этом случае включается эскиз. Каждый пост принадлежит ровно одному сообществу.

{
    "@context": ...,
    "id": "https://voyager.lemmy.ml/post/29",
    "type": "Page",
    "attributedTo": "https://voyager.lemmy.ml/u/picard",
    "to": [
      "https://voyager.lemmy.ml/c/main",
      "https://www.w3.org/ns/activitystreams#Public"
    ],
    "name": "Test thumbnail 2",
    "content": "blub blub",
    "mediaType": "text/html",
    "source": {
        "content": "blub blub",
        "mediaType": "text/markdown"
    },
    "url": "https://voyager.lemmy.ml:/pictrs/image/fzGwCsq7BJ.jpg",
    "image": {
        "type": "Image",
        "url": "https://voyager.lemmy.ml/pictrs/image/UejwBqrJM2.jpg"
    },
    "commentsEnabled": true,
    "sensitive": false,
    "stickied": false,
    "published": "2020-09-24T17:42:50.396237+00:00",
    "updated": "2020-09-24T18:31:14.158618+00:00"
}
Имя в полеОбязательноОписание
attributedToдаИдентификатор пользователя, который создал этот пост
toдаИдентификатор сообщества, в котором оно было опубликовано
nameдаЗаголовок сообщения
contentнетТело сообщения
urlнетПроизвольная ссылка, которой нужно поделиться
imageнетМиниатюра для url, присутствует только в том случае, если это ссылка на изображение
commentsEnabledдаЗначение false означает, что публикация заблокирована и комментарии к ней добавить нельзя
sensitiveдаTrue отмечает сообщение как NSFW, размывает миниатюру и скрывает ее от пользователей с отключенной настройкой NSFW
stickiedдаTrue означает, что оно отображается в верхней части сообщества
publishedнетДата и время создания сообщения
updatedнетДата и время, когда сообщение было отредактировано (отсутствует, если оно никогда не редактировалось)

Комментарий

Ответ на сообщение или ответ на другой комментарий. Содержит только текст (включая ссылки на других пользователей или сообщества). Lemmy отображает комментарии в виде древовидной структуры.

{
    "@context": ...,
    "id": "https://enterprise.lemmy.ml/comment/95",
    "type": "Note",
    "attributedTo": "https://enterprise.lemmy.ml/u/picard",
    "to": "https://www.w3.org/ns/activitystreams#Public",
    "content": "mmmk",
    "mediaType": "text/html",
    "source": {
        "content": "mmmk",
        "mediaType": "text/markdown"
    },
    "inReplyTo": [
        "https://enterprise.lemmy.ml/post/38",
        "https://voyager.lemmy.ml/comment/73"
    ],
    "published": "2020-10-06T17:53:22.174836+00:00",
    "updated": "2020-10-06T17:53:22.174836+00:00"
}
Имя в полеОбязательноОписание
attributedToдаИдентификатор пользователя, создавшего комментарий
toдаСообщество, в котором был сделан комментарий
contentдаТекст комментария
inReplyToдаИдентификатор поста, в которой был сделан этот комментарий, и родительского комментария. Если это комментарий верхнего уровня, inReplyTo содержит только сообщение
publishedнетДата и время создания комментария
updatedнетДата и время, когда комментарий был отредактирован (отсутствует, если он никогда не редактировался)

Личное сообщение

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

{
    "@context": ...,
    "id": "https://enterprise.lemmy.ml/private_message/34",
    "type": "Note",
    "attributedTo": "https://enterprise.lemmy.ml/u/picard",
    "to": "https://voyager.lemmy.ml/u/janeway",
    "content": "test",
    "source": {
        "content": "test",
        "mediaType": "text/markdown"
    },
    "mediaType": "text/markdown",
    "published": "2020-10-08T19:10:46.542820+00:00",
    "updated": "2020-10-08T20:13:52.547156+00:00"
}
Имя в полеОбязательноОписание
attributedToИдентификатор пользователя, создавшего это личное сообщение
toИдентификатор получателя
contentдаТекст личного сообщения
publishedнетДата и время создания сообщения
updatedнетДата и время, когда сообщение было отредактировано (отсутствует, если оно никогда не редактировалось)

Виды активности

Пользователь в Сообществе

Следовать

Когда пользователь нажимает "Подписаться" в сообществе, Follow отправляется. Сообщество автоматически отвечает Accept/Follow.

{
    "@context": ...,
    "id": "https://enterprise.lemmy.ml/activities/follow/2e4784b7-4edf-4fa1-a352-674d5d5f8891",
    "type": "Follow",
    "actor": "https://enterprise.lemmy.ml/u/picard",
    "to": "https://ds9.lemmy.ml/c/main",
    "object": "https://ds9.lemmy.ml/c/main"
}
Имя в полеОбязательноОписание
actorдаПользователь, отправляющий запрос на отслеживание
objectдаСообщество, за которым нужно следить

Отписаться

Нажатие на кнопку отказа от подписки в сообществе вызывает отправку сообщения Undo/Follow. Сообщество удаляет пользователя из списка подписчиков после его получения.

{
    "@context": ...,
    "id": "http://lemmy-alpha:8541/activities/undo/2c624a77-a003-4ed7-91cb-d502eb01b8e8",
    "type": "Undo",
    "actor": "http://lemmy-alpha:8541/u/lemmy_alpha",
    "to": "http://lemmy-beta:8551/c/main",
    "object": {
        "@context": ...,
        "id": "http://lemmy-alpha:8541/activities/follow/f0d732e7-b1e7-4857-a5e0-9dc83c3f7ee8",
        "type": "Follow",
        "actor": "http://lemmy-alpha:8541/u/lemmy_alpha",
        "object": "http://lemmy-beta:8551/c/main"
    }
}

Создать или Обновить Сообщение

Когда пользователь создает новый пост, он отправляется в соответствующее сообщество. Редактирование ранее созданного сообщения вызывает почти идентичную активность, за исключением type являющейся Update. Мы пока не поддерживаем упоминания в сообщениях.

{
    "@context": ...,
    "id": "https://enterprise.lemmy.ml/activities/create/6e11174f-501a-4531-ac03-818739bfd07d",
    "type": "Create",
    "actor": "https://enterprise.lemmy.ml/u/riker",
    "to": "https://www.w3.org/ns/activitystreams#Public",
    "cc": [
      "https://ds9.lemmy.ml/c/main/"
    ],
    "object": ...
}
Имя в полеОбязательноОписание
typeдалибо Create или Update
ccдаСообщество, в котором пишется пост
objectдаПост создается

Создать или Обновить Комментарий

Ответ на сообщение или другой комментарий. Может содержать упоминания других пользователей. Редактирование ранее созданного сообщения вызывает почти идентичную активность, за исключением type являющейся Update.

{
    "@context": ...,
    "id": "https://enterprise.lemmy.ml/activities/create/6f52d685-489d-4989-a988-4faedaed1a70",
    "type": "Create",
    "actor": "https://enterprise.lemmy.ml/u/riker",
    "to": "https://www.w3.org/ns/activitystreams#Public",
    "tag": [{
        "type": "Mention",
        "name": "@sisko@ds9.lemmy.ml",
        "href": "https://ds9.lemmy.ml/u/sisko"
    }],
    "cc": [
        "https://ds9.lemmy.ml/c/main/",
        "https://ds9.lemmy.ml/u/sisko"
    ],
    "object": ...
}
Имя в полеОбязательноОписание
tagнетСписок пользователей, упомянутых в комментарии (например @user@example.com)
ccдаСообщество, в котором создается публикация, пользователь, которому отвечает (создатель родительской публикации / комментария), а также любые упомянутые пользователи
objectдаСоздаваемый комментарий

Понравилось Сообщение или Комментарий

Голосоывание за публикацию или комментарий.

{
    "@context": ...,
    "id": "https://enterprise.lemmy.ml/activities/like/8f3f48dd-587d-4624-af3d-59605b7abad3",
    "type": "Like",
    "actor": "https://enterprise.lemmy.ml/u/riker",
    "to": "https://www.w3.org/ns/activitystreams#Public",
    "cc": [
        "https://ds9.lemmy.ml/c/main/"
    ],
    "object": "https://enterprise.lemmy.ml/p/123"
}
Имя в полеОбязательноОписание
ccдаИдентификатор сообщества, в котором размещён пост/комментарий
objectдаЗа публикацию или комментарий проголосовали

Сообщение или Комментарий не нравится

Голос против публикации или комментария.

{
    "@context": ...,
    "id": "https://enterprise.lemmy.ml/activities/dislike/fd2b8e1d-719d-4269-bf6b-2cadeebba849",
    "type": "Dislike",
    "actor": "https://enterprise.lemmy.ml/u/riker",
    "to": "https://www.w3.org/ns/activitystreams#Public",
    "cc": [
      "https://ds9.lemmy.ml/c/main/"
    ],
    "object": "https://enterprise.lemmy.ml/p/123"
}
Имя в полеОбязательноОписание
ccдаИдентификатор сообщества, в котором размещён пост/комментарий
objectдаЗа публикацию или комментарий проголосовали

Удалить Пост или Комментарий

Удаляет ранее созданный пост или комментарий. Это может сделать только первоначальный создатель этого сообщения/комментария.

{
    "@context": ...,
    "id": "https://enterprise.lemmy.ml/activities/delete/f1b5d57c-80f8-4e03-a615-688d552e946c",
    "type": "Delete",
    "actor": "https://enterprise.lemmy.ml/u/riker",
    "to": "https://www.w3.org/ns/activitystreams#Public",
    "cc": [
        "https://enterprise.lemmy.ml/c/main/"
    ],
    "object": "https://enterprise.lemmy.ml/post/32"
}
Имя в полеОбязательноОписание
ccдаИдентификатор сообщества, в котором размещён пост/комментарий
objectдаИдентификатор удаляемой записи или комментария

Убрать Пост или Комментарий

Убирает пост или комментарий. Это может быть сделано только модератором сообщества или администратором инстанса, где размещено сообщество.

{
    "@context": ...,
    "id": "https://ds9.lemmy.ml/activities/remove/aab93b8e-3688-4ea3-8212-d00d29519218",
    "type": "Remove",
    "actor": "https://ds9.lemmy.ml/u/sisko",
    "to": "https://www.w3.org/ns/activitystreams#Public",
    "cc": [
        "https://ds9.lemmy.ml/c/main/"
    ],
    "object": "https://enterprise.lemmy.ml/comment/32"
}
Имя в полеОбязательноОписание
ccдаИдентификатор сообщества, в котором размещён пост/комментарий
objectдаИдентификатор удаляемой записи или комментария

Отмена

Отменяет предыдущее действие, может быть выполнено только actor object. В случае Like или Dislike подсчет голосов возвращается обратно. В случае Delete или Remove пост/комментарий восстанавливается. object создается заново, так как идентификатор действия и другие поля отличаются.

{
    "@context": ...,
    "id": "https://ds9.lemmy.ml/activities/undo/70ca5fb2-e280-4fd0-a593-334b7f8a5916",
    "type": "Undo",
    "actor": "https://ds9.lemmy.ml/u/sisko",
    "to": "https://www.w3.org/ns/activitystreams#Public",
    "cc": [
        "https://ds9.lemmy.ml/c/main/"
    ],
    "object": ...
}
Имя в полеОбязательноОписание
objectдаЛюбая Like, Dislike, Delete или Remove активности как описано выше

Добавить Модератора

Добавление нового модератора (зарегистрированного на ds9.lemmy.ml) в сообществе !main@enterprise.lemmy.ml. Должно быть отправлено существующим модератором сообщества.

{
    "@context": ...,
    "id": "https://enterprise.lemmy.ml/activities/add/531471b1-3601-4053-b834-d26718da2a06",
    "type": "Add",
    "cc": [
        "https://enterprise.lemmy.ml/c/main"
    ],
    "to": "https://www.w3.org/ns/activitystreams#Public",
    "object": "https://ds9.lemmy.ml/u/sisko",
    "actor": "https://enterprise.lemmy.ml/u/picard",
    "target": "https://enterprise.lemmy.ml/c/main/moderators"
}

Убрать Модератора

Удаление существующего модератора из сообщества. Должено быть отправлено существующим модератором сообщества.

{
    "@context": ...,
    "id": "https://enterprise.lemmy.ml/activities/remove/63b9a5b2-d3f8-4371-a7eb-711c7928b3c0",
    "type": "Remove",
    "object": "https://ds9.lemmy.ml/u/sisko",
    "to": "https://www.w3.org/ns/activitystreams#Public",
    "actor": "https://enterprise.lemmy.ml/u/picard",
    "cc": [
        "https://enterprise.lemmy.ml/c/main"
    ],
    "target": "https://enterprise.lemmy.ml/c/main/moderators"
}

Сообщество для Пользователя

Принятие Подписки

Автоматически отправляется сообществом в ответ на Follow. В то же время сообщество добавляет этого пользователя в свой список подписчиков.

{
    "@context": ...,
    "id": "https://ds9.lemmy.ml/activities/accept/5314bf7c-dab8-4b01-baf2-9be11a6a812e",
    "type": "Accept",
    "actor": "https://ds9.lemmy.ml/c/main",
    "to": "https://enterprise.lemmy.ml/u/picard",
    "object": {
        "@context": ...,
        "id": "https://enterprise.lemmy.ml/activities/follow/2e4784b7-4edf-4fa1-a352-674d5d5f8891",
        "type": "Follow",
        "object": "https://ds9.lemmy.ml/c/main",
        "actor": "https://enterprise.lemmy.ml/u/picard"
    }
}
Имя в полеОбязательноОписание
actorдаТо же сообщество, что и в Follow активность
toнетИдентификатор пользователя, отправившего Follow
objectдаРанее отправленные Follow активность

Публикация

Когда сообщество получает сообщение или комментарий, оно помещает его в Announce и отправляет его всем подписчикам.

{
  "@context": ...,
  "id": "https://ds9.lemmy.ml/activities/announce/b98382e8-6cb1-469e-aa1f-65c5d2c31cc4",
  "type": "Announce",
  "actor": "https://ds9.lemmy.ml/c/main",
  "to": "https://www.w3.org/ns/activitystreams#Public",
  "cc": [
    "https://ds9.lemmy.ml/c/main/followers"
  ],
  "object": ...
}
Имя в полеОбязательноОписание
objectдаЛюбая из Create, Update, Like, Dislike, Delete Remove или Undo активности описанная в Пользователь в Сообществе секции

Убрать или Удалить Сообщество

Администратор инстанса или модератор могут удалять сообщества.

{
  "@context": ...,
  "id": "http://ds9.lemmy.ml/activities/remove/e4ca7688-af9d-48b7-864f-765e7f9f3591",
  "type": "Remove",
  "actor": "http://ds9.lemmy.ml/c/some_community",
  "cc": [
    "http://ds9.lemmy.ml/c/some_community/followers"
  ],
  "to": "https://www.w3.org/ns/activitystreams#Public",
  "object": "http://ds9.lemmy.ml/c/some_community"
}
Имя в полеОбязательноОписание
typeдаЛибо Remove или Delete

Восстановить Убранное или Удалённое Сообщество

Отменяет убранное сообщество или удалённое.

{
  "@context": ...,
  "id": "http://ds9.lemmy.ml/activities/like/0703668c-8b09-4a85-aa7a-f93621936901",
  "type": "Undo",
  "actor": "http://ds9.lemmy.ml/c/some_community",
  "to": "https://www.w3.org/ns/activitystreams#Public",
  "cc": [
    "http://ds9.lemmy.ml/c/testcom/followers"
  ],
  "object": {
    "@context": ...,
    "id": "http://ds9.lemmy.ml/activities/remove/1062b5e0-07e8-44fc-868c-854209935bdd",
    "type": "Remove",
    "actor": "http://ds9.lemmy.ml/c/some_community",
    "object": "http://ds9.lemmy.ml/c/testcom",
    "to": "https://www.w3.org/ns/activitystreams#Public",
    "cc": [
      "http://ds9.lemmy.ml/c/testcom/followers"
    ]
  }
}

Имя в полеОбязательноОписание
object.typeдаЛибо Remove или Delete

От Пользователя к Пользователю

Создать или Обновить личное сообщение

Создание нового личного сообщения между двумя пользователями.

{
    "@context": ...,
    "id": "https://ds9.lemmy.ml/activities/create/202daf0a-1489-45df-8d2e-c8a3173fed36",
    "type": "Create",
    "actor": "https://ds9.lemmy.ml/u/sisko",
    "to": "https://enterprise.lemmy.ml/u/riker/inbox",
    "object": ...
}
Имя в полеОбязательноОписание
typeдаЛибо Create или Update
objectдаЛичное сообщение

Удалить Личное Сообщение

Удаляет предыдущее личное сообщение.

{
    "@context": ...,
    "id": "https://ds9.lemmy.ml/activities/delete/2de5a5f3-bf26-4949-a7f5-bf52edfca909",
    "type": "Delete",
    "actor": "https://ds9.lemmy.ml/u/sisko",
    "to": "https://enterprise.lemmy.ml/u/riker/inbox",
    "object": "https://ds9.lemmy.ml/private_message/341"
}

Отмена Удаления Личного Сообщения

Восстанавливает ранее удалённое личное сообщение. Объект создается заново, так как идентификатор действия и другие поля отличаются.

{
    "@context": ...,
    "id": "https://ds9.lemmy.ml/activities/undo/b24bc56d-5db1-41dd-be06-3f1db8757842",
    "type": "Undo",
    "actor": "https://ds9.lemmy.ml/u/sisko",
    "to": "https://enterprise.lemmy.ml/u/riker/inbox",
    "object": ...
}

Клиентская разработка

Тематическое руководство

Пользователи Lemmy Bootstrap v4, и не много настраиваемых классов css, поэтому любая тема, совместимая с bootstrap v4, должна работать нормально.

Создание

  • Используйте такой инструмент, как bootstrap.build для создания темы начальной загрузки v4. Экспортируйте bootstrap.min.css как только вы закончите, сохраните _variables.scss тоже.

Тестирование

  • Чтобы протестировать тему, вы можете использовать веб-инструменты своего браузера или плагин, например stylus, для копирования и вставки темы при просмотре Lemmy.

Добавление

  1. Ответвление lemmy-ui.
  2. Скопируйте {my-theme-name}.min.css в src/assets/css/themes. (Вы также можете скопировать в _variables.scss если хотите).
  3. Перейдите в src/shared/utils.ts и добавьте {my-theme-name} в список тем.
  4. Протестируйте локально
  5. Сделайте запрос pull request с этими изменениями в Github

Справочник по API

Lemmy имеет два взаимосвязанных API:

На этой странице описаны общие для них концепции.

Основное использование

Запрос и ответ строк В формате JSON (анг.язык).

Типы данных

Типы Lemmy

Низкоуровневые типы

  • ? обозначает параметр, который может быть опущен в запросах и отсутствовать в ответах. Это будет типа SomeType.
  • [SomeType] список, содержащий объекты типа SomeType.
  • Времена и даты временной метки в строках ISO 8601 (анг.язык) формата. Временные метки будут в формате UTC, ваш клиент должен выполнить преобразование UTC в локальный формат.

Скоростные лимиты по умолчанию

Их можно редактировать в вашем lemmy.hjson файле, скопировав соответствующий раздел из defaults.hjson (анг.язык).

  • 3 в час за регистрацию и создание сообщества.
  • 6 в час за размещение изображений.
  • 6 за 10 минут на создание поста.
  • 180 действий в минуту для постголосования и создания комментариев.

Все остальное не ограничено по скорости.

Смотри также: ограничение скорости для пользовательских интерфейсов (анг.язык).

WebSocket API

Lemmy WebSocket API 2.0 documentation

HTTP API

Creating a Custom Frontend

The backend and frontend are completely decoupled, and run in independent Docker containers. They only communicate over the Lemmy API, which makes it quite easy to write alternative frontends.

This creates a lot of potential for custom frontends, which could change much of the design and user experience of Lemmy. For example, it would be possible to create a frontend in the style of a traditional forum like phpBB, or a question-and-answer site like stackoverflow. All without having to think about database queries, authentification or ActivityPub, which you essentially get for free.

Development

You can use any language to create a custom frontend. The easiest option would be forking our official frontend, lemmy-lite, or the lemmy-frontend-example. In any case, the principle is the same: bind to LEMMY_EXTERNAL_HOST (default: localhost:8536) and handle requests using the Lemmy API at LEMMY_INTERNAL_HOST (default: lemmy:8536). Also use LEMMY_HTTPS to generate links with the correct protocol.

The next step is building a Docker image from your frontend. If you forked an existing project, it should already include a Dockerfile and instructions to build it. Otherwise, try searching for your language on dockerhub, official images usually have build instructions in their readme. Build a Docker image with a tag, then look for the following section in docker/dev/docker-compose.yml:

  lemmy-ui:
    image: dessalines/lemmy-ui:v0.8.10
    ports:
      - "1235:1234"
    restart: always
    environment:
      - LEMMY_INTERNAL_HOST=lemmy:8536
      - LEMMY_EXTERNAL_HOST=localhost:8536
      - LEMMY_HTTPS=false
    depends_on: 
      - lemmy

All you need to do is replace the value for image with the tag of your own Docker image (and possibly the environment variables if you need different ones). Then run ./docker_update.sh, and after compilation, your frontend will be available on http://localhost:1235. You can also make the same change to docker/federation/docker-compose.yml and run ./start-local-instances.bash to test federation with your frontend.

Deploy with Docker

After building the Docker image, you need to push it to a Docker registry (such as dockerhub). Then update the docker-compose.yml on your server, replacing the image for lemmy-ui, just as described above. Run docker-compose.yml, and after a short wait, your instance will use the new frontend.

Note, if your instance is deployed with Ansible, it will override docker-compose.yml with every run, reverting back to the default frontend. In that case you should copy the ansible/ folder from this project to your own repository, and adjust docker-compose.yml directly in the repo.

It is also possible to use multiple frontends for the same Lemmy instance, either using subdomains or subfolders. To do that, don't edit the lemmy-ui section in docker-compose.yml, but duplicate it, adjusting the name, image and port so they are distinct for each. Then edit your nginx config to pass requests to the appropriate frontend, depending on the subdomain or path.

Translations

You can add the lemmy-translations repository to your project as a git submodule. That way you can take advantage of same translations used in the official frontend, and you will also receive new translations contributed via weblate.

Rate limiting

Lemmy does rate limiting for many actions based on the client IP. But if you make any API calls on the server side (eg in the case of server-side rendering, or javascript pre-rendering), Lemmy will take the IP of the Docker container. Meaning that all requests come from the same IP, and get rate limited much earlier. To avoid this problem, you need to pass the headers X-REAL-IP and X-FORWARDED-FOR on to Lemmy (the headers are set by our nginx config).

Here is an example snipped for NodeJS:

function setForwardedHeaders(
  headers: IncomingHttpHeaders
): { [key: string]: string } {
  let out = {
    host: headers.host,
  };
  if (headers['x-real-ip']) {
    out['x-real-ip'] = headers['x-real-ip'];
  }
  if (headers['x-forwarded-for']) {
    out['x-forwarded-for'] = headers['x-forwarded-for'];
  }

  return out;
}

let headers = setForwardedHeaders(req.headers);
let client = new LemmyHttp(httpUri, headers);

Contributing

Information about contributing to Lemmy, whether it is translating, testing, designing or programming.

Issue tracking / Repositories

Translating

Check out Lemmy's Weblate for translations. You can also help by translating this documentation.

Architecture

Front end

  • The front end is written in typescript, using a react-like framework called inferno. All UI elements are reusable .tsx components.
  • The front end repository is lemmy-ui.
  • The routes are at src/shared/routes.ts.
  • The components are located in src/shared/components.

Back end

  • The back end is written in rust, using diesel, and actix.
  • The server source code is split into main sections in src. These include:
    • db - The low level database actions.
      • Database additions are done using diesel migrations. Run diesel migration generate xxxxx to add new things.
    • api - The high level user interactions (things like CreateComment)
    • routes - The server endpoints .
    • apub - The activitypub conversions.
    • websocket - Creates the websocket server.

Linting / Formatting

  • Every front and back end commit is automatically formatted then linted using husky, and lint-staged.
  • Rust with cargo fmt and cargo clippy.
  • Typescript with prettier and eslint.

Docker Development

Dependencies

Debian-based distro

sudo apt install git docker-compose
sudo systemctl start docker
git clone https://github.com/LemmyNet/lemmy

Arch-based distro

sudo pacman -S git docker-compose
sudo systemctl start docker
git clone https://github.com/LemmyNet/lemmy

Running

cd docker/dev
./docker_update.sh

and go to http://localhost:1235.

*Note: many features (like docs and pictures) will not work without using an nginx profile like that in ansible/templates/nginx.conf.

To speed up the Docker compile, add the following to /etc/docker/daemon.json and restart Docker.

{
  "features": {
    "buildkit": true
  }
}

If the build is still too slow, you will have to use a local build instead.

Local Development

Install build requirements

Install Rust using the recommended option on rust-lang.org (rustup).

Debian-based distro

sudo apt install git cargo libssl-dev pkg-config libpq-dev yarn curl gnupg2 espeak
# install yarn
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt update && sudo apt install yarn

Arch-based distro

sudo pacman -S git cargo libssl-dev pkg-config libpq-dev yarn curl gnupg2 espeak
# install yarn (stable)
curl -o- -L https://yarnpkg.com/install.sh | bash

macOS

Install Homebrew if you don't already have it installed.

Finally, install Node and Yarn.

brew install node yarn

Get the back end source code

git clone https://github.com/LemmyNet/lemmy.git
# or alternatively from gitea
# git clone https://yerbamate.ml/LemmyNet/lemmy.git

Build the backend (Rust)

cargo build
# for development, use `cargo check` instead)

Get the front end source code

git clone https://github.com/LemmyNet/lemmy-ui.git --recurse-submodules

Setup postgresql

Debian-based disto

sudo apt install postgresql
sudo systemctl start postgresql

# Either execute db-init.sh, or manually initialize the postgres database:
sudo -u postgres psql -c "create user lemmy with password 'password' superuser;" -U postgres
sudo -u postgres psql -c 'create database lemmy with owner lemmy;' -U postgres
export LEMMY_DATABASE_URL=postgres://lemmy:password@localhost:5432/lemmy

Arch-based distro

sudo pacman -S postgresql
sudo systemctl start postgresql

# Either execute db-init.sh, or manually initialize the postgres database:
sudo -u postgres psql -c "create user lemmy with password 'password' superuser;" -U postgres
sudo -u postgres psql -c 'create database lemmy with owner lemmy;' -U postgres
export LEMMY_DATABASE_URL=postgres://lemmy:password@localhost:5432/lemmy

macOS

brew install postgresql
brew services start postgresql
/usr/local/opt/postgres/bin/createuser -s postgres

# Either execute db-init.sh, or manually initialize the postgres database:
psql -c "create user lemmy with password 'password' superuser;" -U postgres
psql -c 'create database lemmy with owner lemmy;' -U postgres
export LEMMY_DATABASE_URL=postgres://lemmy:password@localhost:5432/lemmy

Run a local development instance

cd lemmy
cargo run

Then open localhost:1235 in your browser. To reload back-end changes, you will have to rerun cargo run. You can use cargo check as a faster way to find compilation errors.

To do front end development:

cd lemmy-ui
yarn
yarn dev

and go to localhost:1234. Front end saves should rebuild the project.

Note that this setup doesn't include image uploads. If you want to test those, you should use the Docker development.

Тесты

Rust

После установки local development dependencies, запустите следующую команду:

psql -U lemmy -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"
./test.sh

Федерация

Установите Local development dependencies, и добавьте следующую строку /etc/hosts:

127.0.0.1       lemmy-alpha
127.0.0.1       lemmy-beta
127.0.0.1       lemmy-gamma
127.0.0.1       lemmy-delta
127.0.0.1       lemmy-epsilon

Затем используйте следующий скрипт для запуска тестов:

cd api_tests
./run-federation-test.bash

Federation Development

Running locally

Install the dependencies as described in Docker development. Then run the following

cd docker/federation
./start-local-instances.bash

The federation test sets up 5 instances:

InstanceUsernameLocationNotes
lemmy-alphalemmy_alpha127.0.0.1:8540federated with all other instances
lemmy-betalemmy_beta127.0.0.1:8550federated with all other instances
lemmy-gammalemmy_gamma127.0.0.1:8560federated with all other instances
lemmy-deltalemmy_delta127.0.0.1:8570only allows federation with lemmy-beta
lemmy-epsilonlemmy_epsilon127.0.0.1:8580uses blocklist, has lemmy-alpha blocked

You can log into each using the instance name, and lemmy as the password, IE (lemmy_alpha, lemmy).

To start federation between instances, visit one of them and search for a user, community or post, like this. Note that the Lemmy backend runs on a different port than the frontend, so you have to increment the port number from the URL bar by one.

  • !main@lemmy-alpha:8541
  • http://lemmy-beta:8551/post/3
  • @lemmy-gamma@lemmy-gamma:8561

Firefox containers are a good way to test them interacting.

Running on a server

Note that federation is currently in alpha. Only use it for testing, not on any production server, and be aware that turning on federation may break your instance.

Follow the normal installation instructions, either with Ansible or manually. Then replace the line image: dessalines/lemmy:v0.x.x in /lemmy/docker-compose.yml with image: dessalines/lemmy:federation. Add and configure this federation block to your lemmy.hjson.

Afterwards, and whenever you want to update to the latest version, run these commands on the server:

cd /lemmy/
sudo docker-compose pull
sudo docker-compose up -d

Security Model

  • HTTP signature verify: This ensures that activity really comes from the activity that it claims
  • check_is_apub_valid : Makes sure its in our allowed instances list
  • Lower level checks: To make sure that the user that creates/updates/removes a post is actually on the same instance as that post

For the last point, note that we are not checking whether the actor that sends the create activity for a post is actually identical to the post's creator, or that the user that removes a post is a mod/admin. These things are checked by the API code, and its the responsibility of each instance to check user permissions. This does not leave any attack vector, as a normal instance user cant do actions that violate the API rules. The only one who could do that is the admin (and the software deployed by the admin). But the admin can do anything on the instance, including send activities from other user accounts. So we wouldnt actually gain any security by checking mod permissions or similar.

Code of Conduct

  • We are committed to providing a friendly, safe and welcoming environment for all, regardless of level of experience, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, nationality, or other similar characteristic.
  • Please avoid using overtly sexual aliases or other nicknames that might detract from a friendly, safe and welcoming environment for all.
  • Please be kind and courteous. There’s no need to be mean or rude.
  • Respect that people have differences of opinion and that every design or implementation choice carries a trade-off and numerous costs. There is seldom a right answer.
  • Please keep unstructured critique to a minimum. If you have solid ideas you want to experiment with, make a fork and see how it works.
  • We will exclude you from interaction if you insult, demean or harass anyone. That is not welcome behavior. We interpret the term “harassment” as including the definition in the Citizen Code of Conduct; if you have any lack of clarity about what might be included in that concept, please read their definition. In particular, we don’t tolerate behavior that excludes people in socially marginalized groups.
  • Private harassment is also unacceptable. No matter who you are, if you feel you have been or are being harassed or made uncomfortable by a community member, please contact one of the channel ops or any of the Lemmy moderation team immediately. Whether you’re a regular contributor or a newcomer, we care about making this community a safe place for you and we’ve got your back.
  • Likewise any spamming, trolling, flaming, baiting or other attention-stealing behavior is not welcome.

Message the Moderation Team on Mastodon

Email The Moderation Team

Moderation

These are the policies for upholding our community’s standards of conduct. If you feel that a thread needs moderation, please contact the Lemmy moderation team .

  1. Remarks that violate the Lemmy standards of conduct, including hateful, hurtful, oppressive, or exclusionary remarks, are not allowed. (Cursing is allowed, but never targeting another user, and never in a hateful manner.)
  2. Remarks that moderators find inappropriate, whether listed in the code of conduct or not, are also not allowed.
  3. Moderators will first respond to such remarks with a warning, at the same time the offending content will likely be removed whenever possible.
  4. If the warning is unheeded, the user will be “kicked,” i.e., kicked out of the communication channel to cool off.
  5. If the user comes back and continues to make trouble, they will be banned, i.e., indefinitely excluded.
  6. Moderators may choose at their discretion to un-ban the user if it was a first offense and they offer the offended party a genuine apology.
  7. If a moderator bans someone and you think it was unjustified, please take it up with that moderator, or with a different moderator, in private. Complaints about bans in-channel are not allowed.
  8. Moderators are held to a higher standard than other community members. If a moderator creates an inappropriate situation, they should expect less leeway than others.

In the Lemmy community we strive to go the extra step to look out for each other. Don’t just aim to be technically unimpeachable, try to be your best self. In particular, avoid flirting with offensive or sensitive issues, particularly if they’re off-topic; this all too often leads to unnecessary fights, hurt feelings, and damaged trust; worse, it can drive people away from the community entirely.

And if someone takes issue with something you said or did, resist the urge to be defensive. Just stop doing what it was they complained about and apologize. Even if you feel you were misinterpreted or unfairly accused, chances are good there was something you could’ve communicated better — remember that it’s your responsibility to make others comfortable. Everyone wants to get along and we are all here first and foremost because we want to talk about cool technology. You will find that people will be eager to assume good intent and forgive as long as you earn their trust.

The enforcement policies listed above apply to all official Lemmy venues; including git repositories under github.com/LemmyNet and yerbamate.ml/LemmyNet, the Matrix channel; lemmy.ml and other instances under that domain. For other projects adopting the Lemmy Code of Conduct, please contact the maintainers of those projects for enforcement. If you wish to use this code of conduct for your own project, consider explicitly mentioning your moderation policy or making a copy with your own moderation policy so as to avoid confusion.

Adapted from the Rust Code of Conduct, which is based on the Node.js Policy on Trolling as well as the Contributor Covenant v1.3.0.