LINUX.ORG.RU

Избранные сообщения temak

Будущее личных вычислительных систем

Форум — Talks

Хочу рассказать о своём видении некоторой «ментальной модели» – того, как пользователь настоящего и будущего выстраивает и будет выстраивать взаимодействие с программной средой.

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

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

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

Весь этот зоопарк устройств обусловлен спектром ФИЗИЧЕСКИХ различий. Что-то экономичное и компактное, что-то большое и мощное, а что-то привязано к конкретному рабочем месту – под физически разные контексты необходимы физически разные устройства, что обусловлено объективными ограничениями нашего материального мира и доступных нам технологий.

А вот голова у пользователя – одна. И в этой голове совсем нет необходимости, и одни только проблемы от того, что у вас есть, скажем, восемь разных «мест», в которых лежат разные данные, установлены разные программы, выполнен вход в разные сервисы, применены различные персональные настройки и так далее.

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

Вот этот «перенос данных в облака» — он как раз про это — про то, чтобы отвязать ваше личное информационное пространство от физической коробки.

Но я хочу поговорить не про корпоративные попытки сделать вас рабом системы, которая хранит все ваши данные на своих серверах. А про что-то противоположное.


Итак, у моих данных есть некоторый «дом по умолчанию». В моём случае это ноутбук. Это решение сегодняшнего дня, но оно меня устраивает не всецело. В идеале, таким решением должен быть смартфон как более компактный и лёгкий девайс.

А если говорить точнее, то между моим ноутбуком и смартфоном не должно быть никакой разницы.

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

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

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

После этого разница для меня как пользователя только в том, что десктоп мощный и стационарный, а лаптоп – переносимый, но не такой мощный.


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

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

А как было сказано выше — между моим ноутбуком и смартфоном не должно быть никакой разницы. Следовательно, я работаю с чужой машины точно так же, как если бы я сидел дома за своим ноутбуком.


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

В такой модели «владение данными» и «обработка данных» отвязаны от «владения железом» и от административных издержек, с ним связанных.

Также такой подход можно назвать термином Zero Effort, который я придумал только что. Суть этого подхода состоит в том, что мы решительно устраняем любые издержки на какой-либо процесс… концептуально меняя парадигму софта и работы с ним. То самое: «Идеальный прибор — когда прибора нет, а функции его выполняются.»

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

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

Каждое из этих решений вполне подходит под концепцию Zero Effort:

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

P.S.

4 указанных примера на мой взгляд являются реальными инновациями и движением вперёд согласно духу времени и потребностям людей. А вот изобретение очередной оконной системы, звукового сервера и переписывание очередной библиотеки на Раст — никак таковыми не являются.

syncthing был реализован на Go, и это никак ему не помешало.

 , , ,

wandrien
()

Проблема с подключением Hamachi

Форум — Admin

Проблема заключается в том, что через время пропадает соединение на короткое время и требует аутентификацию с паролем, переустановка не помогла. Что может быть? Использую Haguichi.

Перемещено hobbit из general

 ,

fonera
()

Libreboot, IntelMe, блобы говорите. Тем временем автомобили стали ультрашпионить

Форум — Talks

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

Вот статья на опеннете https://www.opennet.ru/opennews/art.shtml?num=59725

Современные машины оснащены датчиками, камерами и микрофонами, фиксирующими каждое движение пользователя. Собираемая информация также охватывает действия водителя, используемые сервисы, мобильные приложения и данные из сторонних систем, таких как Sirius XM и Google Maps. Среди прочего, автомобильные системы могут собирать показатели здоровья водителя, данные о прослушиваемых музыкальных композициях, сведения о том, где и с какой скоростью осуществляется движение. Более того, Nissan и Kia упоминают в политике конфиденциальности возможность сбора данных о сексуальной активности, а ещё шесть производителей допускают сбор генетической информации. На основе собранной информации делаются выводы об интересах, предпочтениях, интеллекте и способностях водителя.

И все это еще и может быть передано кому угодно фактически.

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

И разумеется все эти канбасы и дата контрол модули проприетарные и зашифрованные и если чего не так легко окирпичить автомобиль.

https://www.opennet.ru/openforum/vsluhforumID3/131444.html#173

https://www.toyota.com/privacyvts кликаешь на «collect & use» и удивляйся: On a Regular and Continuous Basis, We Collect and Use Your: Account Information, Vehicle Information, Location Data, Remote Data, Driving Data, Profile Data, Interior Image Data, Exterior Image Data, Facial Geometric Features,Vehicle Health Data, Multimedia Screen Data, Voice Recordings, Voice Recognition Recordings

и ключике от машины не отдадут пока не подпишешся что согласен, так же как и с мобилами, - типа «согласен со всеми зондами», т.к. хочу игруху. Еще прув? Смотрите на головной юнит, там иконка есть показывающая переодически активность телеметрии (иногда по несколько раз в день а иногда молчит, когда ездишь не лихо)

Жесть, просто жесть

 , ,

praseodim
()

Выпуск P2P VPN 0.11.2

Новости — Интернет
Группа Интернет

Состоялся выпуск P2P VPN 0.11.2 - реализации децентрализованной виртуальной частной сети, работающей по принципу Peer-To-Peer, при котором участники подключены друг к другу, а не через центральный сервер. Участники сети могут находить друг друга через BitTorrent-трекер или BitTorrent DHT, либо через других участников сети.

Список изменений:

  • Добавлена возможность использования приложения в headless режиме (без графического интерфейса).
  • Добавлена возможность генерации файла доступа, экспорта закрытых ключей сети и создания новой сети с данными, сохраненными в формате ini, без использования графического интерфейса.
  • Исправлена ошибка: кнопка закрытия в заголовке окна «добавить в черный список» (Ban peer) должна работать как кнопка НЕТ.
  • Исправлен код, который мог приводить к утечке дескриптора при работе с файлами.
  • Доступна функция ограничения скорости приема трафика.

>>> Подробности

 , , , ,

Skullnet
()

Удаление графического ключа смартфона

Форум — Desktop

Проблема такая есть смартфон (Vivo V17 NEO прошивка стоковая не рутированный, без USB Debagging без custom recovery стоит графический 4 значный ключ, вопрос в том можно ли его как-то разлочить из под линукса (смартфон находится в режиме MTP)? Снятие ключа nethunter’ом не предлагать!!! Короче говоря нужен или хард ресет или доступ к фс смартфона.

 

stoneghost
()

Имеет ли смысл разбивать HDD с TRIM на быстрый и медленный разделы?

Форум — Linux-hardware

Раньше до появления TRIM в HDD логика была понятная: блоки с меньшими адресами располагались в начале диска и потому линейная скорость была выше. Скорость в конце диска могла упасть в несколько раз. Был смысл делить диск на два раздела: с относительно быстро доступными данными и с более медленными. Небольшой хаос вносили переназначенные блоки.

Потом придумали SMR, за ней логично добавили TRIM. Какие последствия это имеет?

Значит ли это, что контроллер HDD теперь сам решает, в какую область писать данные, независимо от логических адресов? Если да, то насколько независимо?

Не получится ли так, что сначала заполнив второй, якобы медленный раздел, я получу замедление работы с первым?

 ,

newbie24
()

«Серый ip» и товарищ майор

Форум — Admin

А как определяется привязка ip к сайту в случае https ? Т е если кто-то написал гадость, то идет запрос к прову, кто в данным момент сидел на какой-то странице ? Но ведь результатов может быть несколько ?

Перемещено hobbit из general

 

bdfy1
()

Что за мода такая на «Скопировать»

Форум — Talks

Firefox 110, на оффтопике.

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

Помянем?

Опуская вопросы того, как такие вещи именовать правильно с точки зрения семантики, всё таки во многом стоит вопрос пользовательского опыта. Я почему вообще заметил — потому что в какой-то момент эту кнопку просто потерял. Потом вот нашёл, потому что она стала другой. Ну допустим. Зачем мне в системе разные наименования в разных местах?

Ну и на засыпку — на онтопике также? С графикой нет ничего под рукой.

 

Dispetcher14
()

Как хранить ключ от GPG?

Форум — General

Как и где храните ключ от GPG? А если пользуетесь Алойэ Вера, тьфу, VeraCrypt, то всё равно же ключ в какой-то момент нужно будет переносить на новый комп, поэтому его всё равно нужно куда-то бэкапить, хранить, и чтобы безопасно.

 , ,

CrM3
()

Грохнул папку ./home

Форум — Admin

Со всеми потрохами, ей было 6 лет, как и серверу у которого uptime такой же. Просто дико rm -rf / home...

 ,

gobot
()

Смазка для вентиляторов (ПМС-100\200)

Форум — Linux-hardware

Закончилось масло для тримера, которое использовалось для смазки кулеров (ну и триммера) — оно всем устраивало. Если заказывать аналогичное, то оно несколько неадекватно по цене и ждать минимум неделю.

Из того, что можно пойти и купить:

  • «специализированное» в шприцах, по совсем неадекватной цене в DNS;
  • масло EURO Clean EUR A-06 для смазки бритвенных станков и тримеров, с несколько неоднозначными комментариями о качестве тары и какое-то количество о качестве самого масла в том же DNS;
  • «дешманское» масло марок ПМС-100 и ПМС-200 в радиомагазине.

Собственно возник вопрос о густоте ПМС-100 — оно по старому видео на Ютубе уже кажется гуще масла для тримеров, а тут упоминались, как подходящие для смазки, ещё более густые ПМС-200 и ПМС-400. Оно только кажется, что ПМС-100 гуще масла для тримеров или нет?

 

luiswoo
()

Fooyin 0.6.1

Новости — Open Source
Fooyin 0.6.1
Группа Open Source

fooyin – это аудиопроигрыватель, созданный на Qt6 в стиле Foobar2000. На данный момент нативно доступен только на Linux. Плеер доступен по лицензии GNU GPL 3.

fooyin предлагает большое количество индивидуальных настроек для управления и воспроизведения музыкальной коллекции. Его можно расширить с помощью плагинов и языка FooScript. Воспроизведение звука поддерживается FFmpeg наряду с несколькими вариантами вывода, включая ALSA и PipeWire.

( читать дальше... )

>>> Подробности

 ,

ConLenov
()

Как лоровцы сохраняют контейнеры Docker?

Форум — General

Здесь можете пофлудить об опыте работы с docker, podman, а также выразить своё неудовольствие этим программным решением.

Моя проблема: Контейнер с изменениями после отключения (podman stop ID, или обычном CTRL+C) при следующем включении (podman start ID, podman attach ID) запускается как неизменённый.

Что я делаю: Запускаю образ local-ai: podman run -p 8080:8080 --name local-ai -ti localai/localai:latest-aio-gpu-intel-f32. Образ запущенный в контейнере начинает работу: сразу же начинает скачивание ИИ моделей. После скачивания предлагает перейти в веб-интерфейс. Но! Вот мне надо выключить комп или попросту завершить «работу», как сохранить загруженные модели?

К тому же, подумал забить на это и настроить веб-интерфейс для podman.

Решение проблемы: Чтобы остановить — podman stop local-ai, чтобы потом продолжить — podman start local-ai. Всё сохранится! То есть подставить указанный --name.

Вывод: Докер — шляпа

Перемещено leave из talks

 , ,

temak
()

Протестировал Strip Poker Night at the Inventory

Галерея — Скриншоты

Strip Poker Night at the Inventory  — это open source стрип покер на раздевание под лицензией MIT. Игра активно развивается, есть большое количество контента, например персонажей.

По сути это веб-приложение, но его можно использовать offline.

Для этого необходимо

1) скачать сами исходники этой игры здесь;

2) подтянуть зависимости с помощью скрипта prepare-online.sh в директории исходников, путем его запуска(sh prepare-online.sh). Также необходимо поставить nodejs для работы;

Конкретно в данном случае тестировалось на версии

$ node --version
v22.6.0

3) скачать паки персонажей здесь;

4) распаковать паки персонажей в директорию исходников;

5) запустить скрипт start_offline.sh(./start_offline.sh) в директории исходников;

6) перейти в браузере на http://127.0.0.1:8080 или на http://192.168.10.193:8080 для запуска собственно самой игры.

Запускалось это все в локально браузере surf. Почему-то при попытке запуска в Google Chrome часть ресурсов не прогружалась при запуске offline, хотя с online-версией таких проблем не возникало.

Адресной строкой в браузере surf служит dmenu, поэтому адрес выглядит именно так. Для табов используется tabbed.

 , , ,

vbcnthfkmnth123
()

Shared папка с Windows 10 на Virt Manager

Форум — Desktop

Недавно было высказано мнение, что Virtualbox фуфло и нет никакого смысла в нем даже для запуска Windows в качестве гостя.

Я задумался, и решил пропробовать поднять Windows 10 гость через Virt Manager.

И уперся в казалось бы, простейший вопрос - как создать shared папку? Кто использует винду на KVM, подскажите, как вы делаете.

ИТАК, РЕШЕНИЕ!!! Со встроенной в qemu самбой. Есть в треде, но там пропущен один пункт и оно не работает. Здесь - полное.

  1. Создаем виртуальную машину с Win10 в Virt Manager, все по дефолту.

  2. Удаляем сетевую карту (дефолтную) из оборудования.

  3. Включаем редактирование XML в настройках Virt Manager, переходим на вкладку XML и добавляем:

В тег <domain>

xmlns:qemu="http://libvirt.org/schemas/domain/qemu/1.0"

И одновременно с этим - именно одновременно! Иначе никакие изменения сохраняться не будут! Меняем /path/to/folder на свой путь.

В конец перед </domain>

  <qemu:commandline>
    <qemu:arg value="-net"/>
    <qemu:arg value="nic"/>
    <qemu:arg value="-net"/>
    <qemu:arg value="user,smb=/path/to/folder>
  </qemu:commandline>
  1. Теперь сетевая карта и QXL устройство окажутся на одном слоте PCI, устраняем этот конфликт. Находим кусок и заменяем slot=«0x01» на slot=«0x03», как в примере ниже.
<video>
  <model type="qxl" ram="65536" vram="65536" vgamem="16384" heads="1" primary="yes"/>
  <alias name="video0"/>
  <address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x0"/>
</video>
  1. В файле /etc/libvirt/qemu.conf
security_default_confied = 0
seccomp_sandbox = 0
security_driver = "none"
  1. Перезапуск systemctl libvirtd restart

7.После этого в винде:

Проводник -> Этот компьютер -> Подключить сетевой диск

на адрес

\\10.0.2.4\qemu

ВАЖНО!!! Чтобы был доступ не только на чтение, qemu должен иметь права на работу с расшаренной папкой. А через Virt Manager он запускается по умолчанию не от имени текущего пользователя! (В отличие от прямого запуска qemu_system из консоли, как многие тут любят, и с чем проблемы нет).

Исправляем это в /etc/libvirt/qemu.conf

user = "username"
group = "groupname"

где username, groupname это ваш текущий пользователь и группа, которому принадлежит расшариваемая папка!

Плюс к этому - есть способ через Virtio FS, расписан тут (linux.org.ru). Подключает папку как локальный диск, без всякой самбы, и с высокой производительностью. Но - там какие-то заморочки с правами на запись, я пока не разобрался, и в этом случае перестает работать Выключить -> Сохранить (состояние виртуалки).

Вот ссылка на источник, из которого брался процесс настройки для этого случая

https://libvirt.org/kbase/virtiofs.html

А кто неосилятор - тот может запустить системную самбу, вместо встроенной в Qemu и порадоваться красивому костылизму.

 ,

James_Holden
()

выбор системы инициализации

Форум — General

насмотрелся видео, начитался статей о том, какой systemd плохой, и полез с arch на artix, а вот статей о том, какую альтернативу выбрать - не нашел.

ладно, полез на ютуб смотреть сравнения, но все варьировалось от дистрибутива, да и многие уже утеряли свою актуальность. опять ладно, начал тестировать на виртуальной машине, из за кривизны ручек какого то объективного сравнения у меня не получилось, но лидировал s6, потом пребегнул к нейросети, которая конечно пыталась убедить меня остаться на systemd, но все таки сказала что s6 будет быстрее, но как она сказала, не стабильный. и вот уже какую неделю я скитаюсь по статьям и видео, так и не могу найти оптимального для себя варианта, а желательно самого быстрого, можно даже не сильно стабильного варианта.

изменено: накатил s6, стало даже хуже. вернулся к systemd)

 

scandalist
()

UEFI смартфон: поддержка UEFI на ARM смартфоне

Форум — Mobile

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

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

Соответственно, приглашаю отписаться знающих, и только про осуществление(я) UEFI на обычном ARM смартфоне: x86-е не предлагать!

 , , , ,

temak
()

Общая папка на убунту в qemu

Форум — General

Имеется убунту лтс и установленной в qemu w10. Как сделать общую папку для данной связки?

 ,

samreg058
()

Зацените и протестриуйте бота, которого написал ChatGPT

Форум — Development

Прочитал я намедни, такую новость 8-летний ребёнок без опыта программирования создал чат-бота за 45 минут, ролик стал вирусным. Ясно, что кликбейт, ЛПП и прочие нехорошие слова… Но я решил проверить на что же способен ChatGPT. Признаюсь, я его использую для написания простых скриптов на 300-500 строчек кода. Сегодня я решил проверить правда или миф сия кликбейтная новость… и она оказалась правдой (частично).

Я до этого не писал ботов для Телеграм. Да, я знаю Python, знаю какие библиотеки для это используются, так как сидя в чате про Python с соевыми омега-обрыганами и школьниками, постоянно вижу вопросы про aiogram.

Началось все с такого задания:

Напиши мне на Python чат-бота. Алгоритм работы такой. Сторонний пользователь пишет сообщение и оно отправляется в чат к владельцу бота. Если владелец бота отвечает на конкретное сообщение то бот его пересылает лицу которое его отправило, если просто отвечает то сообщение отправляется последнему написавшему

На что он мне родил такой код:

import telebot
from collections import defaultdict

# Токен вашего бота
API_TOKEN = 'YOUR_API_TOKEN_HERE'

bot = telebot.TeleBot(API_TOKEN)

# Хранилище сообщений (user_id -> last_message)
user_last_message = {}
# Хранилище последних сообщений каждого пользователя, отправленных владельцу
message_store = defaultdict(list)

# ID владельца бота
OWNER_ID = 'YOUR_OWNER_ID_HERE'

@bot.message_handler(func=lambda message: True)
def handle_message(message):
    user_id = message.from_user.id
    if user_id == OWNER_ID:
        # Ответ от владельца
        if message.reply_to_message:
            # Если владелец отвечает на конкретное сообщение
            original_message_id = message.reply_to_message.message_id
            for uid, msg_list in message_store.items():
                for msg in msg_list:
                    if msg.message_id == original_message_id:
                        bot.send_message(uid, f"Ответ на ваше сообщение: {message.text}")
                        return
        else:
            # Если владелец отвечает без привязки
            if user_last_message:
                last_user_id = max(user_last_message, key=user_last_message.get)
                bot.send_message(last_user_id, f"Ответ от владельца: {message.text}")
    else:
        # Сообщение от пользователя
        bot.send_message(OWNER_ID, f"Сообщение от {message.from_user.username} (id: {user_id}): {message.text}")
        user_last_message[user_id] = message.message_id
        message_store[user_id].append(message)

bot.polling()

Устроил ли он меня? - Нет. Я люблю асинхронщину:

Используй какую нибудь асинхронную библиотек, храни данные в sqlite. Владельцу добавь кнопки типа заблокировать, очистить диалог (есть ли у бота возможность очищать диалог?). Напиши Dockerfile и docker-compose для запуска. 

Был высран такой код:

import asyncio
import aiosqlite
from aiogram import Bot, Dispatcher, types
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
from aiogram.utils.keyboard import InlineKeyboardBuilder
from aiogram.filters import Text, Command
from aiogram.fsm.storage.memory import MemoryStorage

# Токен вашего бота
API_TOKEN = 'YOUR_API_TOKEN_HERE'

# ID владельца бота
OWNER_ID = 'YOUR_OWNER_ID_HERE'

# Инициализация бота и диспетчера
bot = Bot(token=API_TOKEN)
dp = Dispatcher(storage=MemoryStorage())

# Подключение к базе данных
async def init_db():
    async with aiosqlite.connect('bot.db') as db:
        await db.execute('''CREATE TABLE IF NOT EXISTS users
                            (user_id INTEGER PRIMARY KEY, blocked INTEGER DEFAULT 0)''')
        await db.execute('''CREATE TABLE IF NOT EXISTS messages
                            (user_id INTEGER, message_id INTEGER, content TEXT)''')
        await db.commit()

# Кнопки управления
def owner_keyboard(user_id):
    builder = InlineKeyboardBuilder()
    builder.add(
        InlineKeyboardButton(text="Заблокировать", callback_data=f"block_{user_id}"),
        InlineKeyboardButton(text="Очистить диалог", callback_data=f"clear_{user_id}")
    )
    return builder.as_markup()

# Обработчик сообщений от пользователя
@dp.message(Command(commands=['start']))
async def start(message: types.Message):
    await message.answer("Привет! Отправь мне сообщение, и я перешлю его владельцу.")

@dp.message()
async def forward_to_owner(message: types.Message):
    user_id = message.from_user.id
    async with aiosqlite.connect('bot.db') as db:
        async with db.execute("SELECT blocked FROM users WHERE user_id = ?", (user_id,)) as cursor:
            row = await cursor.fetchone()
            if row and row[0] == 1:
                await message.answer("Вы заблокированы.")
                return
        
        await db.execute("INSERT INTO messages (user_id, message_id, content) VALUES (?, ?, ?)", 
                         (user_id, message.message_id, message.text))
        await db.commit()

    # Пересылка сообщения владельцу
    keyboard = owner_keyboard(user_id)
    await bot.send_message(OWNER_ID, f"Сообщение от {message.from_user.username} (id: {user_id}): {message.text}", reply_markup=keyboard)

# Обработчик сообщений от владельца
@dp.message(lambda message: message.from_user.id == int(OWNER_ID))
async def handle_owner_reply(message: types.Message):
    if message.reply_to_message:
        # Если ответ на конкретное сообщение
        original_message = message.reply_to_message.text.split("(id: ")[-1].rstrip('):')
        target_user_id = int(original_message)
        await bot.send_message(target_user_id, f"Ответ от владельца: {message.text}")
    else:
        async with aiosqlite.connect('bot.db') as db:
            async with db.execute("SELECT user_id FROM messages ORDER BY rowid DESC LIMIT 1") as cursor:
                row = await cursor.fetchone()
                if row:
                    last_user_id = row[0]
                    await bot.send_message(last_user_id, f"Ответ от владельца: {message.text}")

# Обработчик кнопок
@dp.callback_query(Text(startswith="block_"))
async def block_user(callback: types.CallbackQuery):
    user_id = int(callback.data.split("_")[1])
    async with aiosqlite.connect('bot.db') as db:
        await db.execute("UPDATE users SET blocked = 1 WHERE user_id = ?", (user_id,))
        await db.commit()
    await callback.message.answer(f"Пользователь {user_id} заблокирован.")

@dp.callback_query(Text(startswith="clear_"))
async def clear_dialog(callback: types.CallbackQuery):
    user_id = int(callback.data.split("_")[1])
    async with aiosqlite.connect('bot.db') as db:
        await db.execute("DELETE FROM messages WHERE user_id = ?", (user_id,))
        await db.commit()
    await callback.message.answer(f"Диалог с пользователем {user_id} очищен.")

async def main():
    await init_db()
    await dp.start_polling(bot)

if __name__ == "__main__":
    asyncio.run(main())

В целом как основа я подошел. Композ и докерфайл были правильными. Докерфайл я попросил переписать для использования alpine.

На это у меня ушло 6 запросов. После чего я переписал творчество бота, добавил логгирование, argparse и тп. Я скинул боту код с исправлениями:

<код>

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

То что он родил меня опять не устроило:

Убери это. await bot.send_message(args.owner_id, forward_text). Айди отправившего сообщения в базе. Когда мы отвечаем на сообщение, то нужно смотреть в базе кто его отправитель. Те нужно создать еще одну таблицу.

Но бот меня не понял:

Эта таблица должна выглядеть так:

CREATE TABLE IF NOT EXISTS messages (
            message_id INTEGER PRIMARY KEY,
            sender_id INTEGER,
        )

Так же нужно добавить таблицу user_info где хранить записи типа user_id, fullname, username. Эти данные каждый раз обновляются когда пишет пользователь. Из этой же таблицы берутся данные, когда нажимаешь на кнопку Кто отправитель?

После еще пары перепиываний кода, я окончательно забил на интеллект этот и переписал уже все сам…

Из грубых ошибок в коде отмечу это:

def owner_keyboard(message_id: int) -> InlineKeyboardMarkup:
    """Создает клавиатуру с кнопками управления для владельца."""
    keyboard = InlineKeyboardMarkup()
    keyboard.add(
        InlineKeyboardButton(
            text="👁️ Whois",
            callback_data=f"view_user_{message_id}",
        ),
        InlineKeyboardButton(
            text="🚫 Ban", callback_data=f"block_{message_id}"
        ),
    )
    return keyboard

Это какой-то неправильный счинтаксис из-за которого бот, написанный ChatGPT падал. Я это фрагмент переписал так:

def owner_keyboard(user_id: int) -> InlineKeyboardMarkup:
    """Создает клавиатуру с кнопками управления для владельца."""
    return InlineKeyboardMarkup(
        inline_keyboard=[
            [
                InlineKeyboardButton(
                    text="👁️ Кто это?",
                    callback_data=f"whois_{user_id}",
                ),
                InlineKeyboardButton(
                    text="🚫 Бан",
                    callback_data=f"block_{user_id}",
                ),
            ],
        ]
    )

Так же мне пришлось добавить обработку ошибок:

# https://docs.aiogram.dev/en/latest/dispatcher/errors.html
@dp.error()
async def error_handler(event: ErrorEvent):
    logger.error("Error caused by %s", event.exception, exc_info=True)

Сделать закрытие курсоров после использования:

# Такое
    cursor = await db_connection.execute(
        "SELECT sender_id FROM messages ORDER BY ROWID DESC LIMIT 1"
    )
    result = await cursor.fetchone()
    return result[0] if result else None

# Заменять на это
    async with connection.execute(
        "SELECT sender_id FROM message_senders WHERE message_id = ?",
        (message_id,),
    ) as cursor:
        result = await cursor.fetchone()
        return result[0] if result else None

# Что аналогично
cursor = await execute()
result = await cursor.fetchone()

try:
    return result[0] if result else None
finally:
    await cursor.close()

Я переписал создание таблиц и часть запросов.

Меня порадовало то, что ChatGPT может генерировать довольно таки грамотные запросы:

    await connection.execute(
        """
        INSERT INTO user_info (user_id, full_name, username)
        VALUES (?, ?, ?)
        ON CONFLICT(user_id) DO UPDATE SET
            full_name=excluded.full_name,
            username=excluded.username,
            updated_at=CURRENT_TIMESTAMP
        """,
        (user_id, full_name, username),
    )

И вот что вышло:

https://github.com/s3rgeym/feedback-tgbot/tree/main

Протестировать можно тут:

https://t.me/feedback_s3rgeym_bot

 , ,

rtxtxtrx
()

Приложения и утилиты, которые стоит попробовать

Статьи — Администрирование
Приложения и утилиты, которые стоит попробовать

Многие пользователи Linux с большим стажем даже не подозревают о существовании этих замечательных инструментов, которые способны облегчить им жизнь…

( читать дальше... )

 , ,

rtxtxtrx
()