Compare commits

...

4 Commits

Author SHA1 Message Date
Alexander Popov 802715acb2
update title 2023-06-25 21:13:48 +03:00
Alexander Popov dda2cd1009
add pages 2023-06-25 21:13:11 +03:00
Alexander Popov 694a426dc6
update tables & some fix 2023-06-25 21:11:33 +03:00
Alexander Popov 82469bbf98
update index page 2023-06-25 20:24:13 +03:00
19 changed files with 964 additions and 322 deletions

View File

@ -8,7 +8,7 @@ tags: [crystal, tutorial, development]
## О статье
Это мой вольный перевод оригинальной
[статьи](https://crystal-lang.org/reference/1.6/syntax_and_semantics/documenting_code.html)
[статьи](https://crystal-lang.org/reference/1.8/syntax_and_semantics/documenting_code.html)
из документации по **Crystal**.
> Если есть желание внести правки, пожалуйста пишите.

View File

@ -42,7 +42,7 @@ Windows Defender - спасибо, что ты есть!
### imgur, imageshack, freepic
Перекрасили логотипы, вставили флаги, etc.
Те ещё помойки. Что-бы посмотреть изображение, нужно скачать тонны JS.
В общём ещё один повод. Спасибо за сорудничество!
В общем ещё один повод. Спасибо за сорудничество!
### Vim
Перекрасил логотип
@ -50,7 +50,7 @@ Windows Defender - спасибо, что ты есть!
### Pastebin.com
Перекрасили логотип
### Downlod Master
### Download Master
При заходе с Российского IP HTTP 403
### Bash.org.ru / Bash.im
@ -63,9 +63,6 @@ Windows Defender - спасибо, что ты есть!
### Rust
И так не использовал, но на всякий случай, чтобы не [забыть](https://blog.rust-lang.org/2022/02/24/Rust-1.59.0.html).
### Qt
Закрыли всё
### Grammarly
> Grammarly stands with our friends, colleagues, and family in Ukraine, and with all people of Ukraine.

View File

@ -181,5 +181,5 @@ setTimeout(() => location.replace(location.protocol + "//" + location.host + "/p
## Мой инстанс
Мой pasty доступен по адресу
Мой pasty доступен по адресу `TODO: add links`

View File

@ -24,7 +24,7 @@ Webинтерфейс для управления WireGuard сервером.
```json
{
"username": "admin",
"password": "admin"
"username": "admin",
"password": "admin"
}
```

View File

@ -0,0 +1,516 @@
---
title: "↔️ Программирование сокетов в Linux"
date: 2023-06-18T17:52:44+03:00
draft: true
tags: [c, development, linux]
---
> Автор: Александр Шаргин
> Опубликовано: 16.05.2001
> Исправлено: 04.02.2006
> Версия текста: 1.1
> Оригинальная страница: https://rsdn.org/article/unix/sockets.xml
## Введение
**Socket API** был впервые реализован в операционной системе Berkley UNIX.
Сейчас этот программный интерфейс доступен практически в любой модификации Unix,
в том числе в Linux. Хотя все реализации чем-то отличаются друг от друга,
основной набор функций в них совпадает.
Изначально сокеты использовались в программах на C/C++,
но в настоящее время средства для работы с ними предоставляют многие языки (Perl, Java и др.).
Сокеты предоставляют весьма мощный и гибкий механизм межпроцессного взаимодействия (IPC).
Они могут использоваться для организации взаимодействия программ на одном компьютере,
по локальной сети или через Internet, что позволяет вам создавать распределённые приложения
различной сложности. Кроме того, с их помощью можно организовать взаимодействие с программами,
работающими под управлением других операционных систем.
Например, под Windows существует интерфейс Window Sockets,
спроектированный на основе socket API. Ниже мы увидим, насколько легко можно
адаптировать существующую Unix-программу для работы под Windows.
Сокеты поддерживают многие стандартные сетевые протоколы
(конкретный их список зависит от реализации)
и предоставляют унифицированный интерфейс для работы с ними.
Наиболее часто сокеты используются для работы в IP-сетях.
В этом случае их можно использовать для взаимодействия приложений
не только по специально разработанным, но и по стандартным протоколам -
HTTP, FTP, Telnet и т. д. Например, вы можете написать собственный Web-браузер или Web-сервер,
способный обслуживать одновременно множество клиентов.
Как видим, сокеты - весьма мощное и удобное средство для сетевого программирования.
В этой статье я покажу, как ими пользоваться. Начав с понятия сокета
и самых основных функций для работы с ним, мы постепенно перейдём
к обсуждению более сложных тем. В частности, мы рассмотрим использование низкоуровневых сокетов,
различные способы организации параллельного обслуживания клиентов,
использование стандартных протоколов Internet и взаимодействие с программами,
работающими под управлением операционной системы Microsoft Windows.
**ПРИМЕЧАНИЕ**
Большая часть материала, изложенного в статье, применимо ко всему семейству ОС Unix.
Тем не менее, все приводимые далее факты и демонстрационные программы проверялись
только под Linux, поэтому название этой ОС и вынесено в заголовок статьи.
## Основы socket API
### Понятие сокета
Сокет (socket) - это конечная точка сетевых коммуникаций.
Он является чем-то вроде "портала", через которое можно отправлять байты во внешний мир.
Приложение просто пишет данные в сокет; их дальнейшая буферизация,
отправка и транспортировка осуществляется используемым стеком протоколов и сетевой аппаратурой.
Чтение данных из сокета происходит аналогичным образом.
В программе сокет идентифицируется дескриптором - это просто переменная типа `int`.
Программа получает дескриптор от операционной системы при создании сокета,
а затем передаёт его сервисам socket API для указания сокета,
над которым необходимо выполнить то или иное действие.
### Атрибуты сокета
С каждым сокет связываются три атрибута: `домен`, `тип` и `протокол`.
Эти атрибуты задаются при создании сокета и остаются неизменными
на протяжении всего времени его существования.
Для создания сокета используется функция `socket`, имеющая следующий прототип.
```c
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
```
Домен определяет пространство адресов, в котором располагается сокет,
и множество протоколов, которые используются для передачи данных.
Чаще других используются домены Unix и Internet, задаваемые константами
`AF_UNIX` и `AF_INET` соответственно
(префикс AF означает "address family" - "семейство адресов").
При задании `AF_UNIX` для передачи данных используется файловая система ввода/вывода Unix.
В этом случае сокеты используются для межпроцессного взаимодействия
на одном компьютере и не годятся для работы по сети.
Константа `AF_INET` соответствует Internet-домену.
Сокеты, размещённые в этом домене, могут использоваться для работы в любой IP-сети.
Существуют и другие домены (`AF_IPX` для протоколов Novell,
`AF_INET6` для новой модификации протокола IP - IPv6 и т. д.),
но в этой статье мы не будем их рассматривать.
Тип сокета определяет способ передачи данных по сети. Чаще других применяются:
- `SOCK_STREAM`. Передача потока данных с предварительной установкой соединения.
Обеспечивается надёжный канал передачи данных, при котором фрагменты отправленного блока
не теряются, не переупорядочиваются и не дублируются.
Поскольку этот тип сокетов является самым распространённым,
до конца раздела мы будем говорить только о нём.
Остальным типам будут посвящены отдельные разделы.
- `SOCK_DGRAM`. Передача данных в виде отдельных сообщений (датаграмм).
Предварительная установка соединения не требуется. Обмен данными происходит быстрее,
но является ненадёжным: сообщения могут теряться в пути, дублироваться и переупорядочиваться.
Допускается передача сообщения нескольким получателям (multicasting)
и широковещательная передача (broadcasting).
- `SOCK_RAW`. Этот тип присваивается низкоуровневым (т. н. "сырым") сокетам.
Их отличие от обычных сокетов состоит в том, что с их помощью программа может
взять на себя формирование некоторых заголовков, добавляемых к сообщению.
Обратите внимание, что не все домены допускают задание произвольного типа сокета.
Например, совместно с доменом Unix используется только тип `SOCK_STREAM`.
С другой стороны, для Internet-домена можно задавать любой из перечисленных типов.
В этом случае для реализации `SOCK_STREAM` используется протокол TCP,
для реализации `SOCK_DGRAM` - протокол UDP,
а тип `SOCK_RAW` используется для низкоуровневой работы с протоколами IP, ICMP и т. д.
Наконец, последний атрибут определяет протокол, используемый для передачи данных.
Как мы только что видели, часто протокол однозначно определяется по домену и типу сокета.
В этом случае в качестве третьего параметра функции `socket` можно передать 0,
что соответствует протоколу по умолчанию. Тем не менее, иногда
(например, при работе с низкоуровневыми сокетами) требуется задать протокол явно.
Числовые идентификаторы протоколов зависят от выбранного домена;
их можно найти в документации.
### Адреса
Прежде чем передавать данные через сокет, его необходимо связать с адресом в выбранном домене
(эту процедуру называют именованием сокета). Иногда связывание осуществляется неявно
(внутри функций `connect` и `accept`), но выполнять его необходимо во всех случаях.
Вид адреса зависит от выбранного вами домена.
В Unix-домене это текстовая строка - имя файла, через который происходит обмен данными.
В Internet-домене адрес задаётся комбинацией IP-адреса и 16-битного номера порта.
IP-адрес определяет хост в сети, а порт - конкретный сокет на этом хосте.
Протоколы TCP и UDP используют различные пространства портов.
Для явного связывания сокета с некоторым адресом используется функция `bind`.
Её прототип имеет вид:
```c
#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, struct sockaddr *addr, int addrlen);
```
В качестве первого параметра передаётся дескриптор сокета,
который мы хотим привязать к заданному адресу.
Второй параметр, `addr`, содержит указатель на структуру с адресом,
а третий - длину этой структуры. Посмотрим, что она собой представляет.
```c
struct sockaddr {
unsigned short sa_family; // Семейство адресов, AF_xxx
char sa_data[14]; // 14 байтов для хранения адреса
};
```
Поле `sa_family` содержит идентификатор домена, тот же, что и первый параметр функции `socket`.
В зависимости от значения этого поля по-разному интерпретируется содержимое массива `sa_data`.
Разумеется, работать с этим массивом напрямую не очень удобно,
поэтому вы можете использовать вместо `sockaddr` одну из альтернативных структур вида
`sockaddr_XX` (`XX` - суффикс, обозначающий домен: `un` - Unix, `in` - Internet и т. д.).
При передаче в функцию `bind` указатель на эту структуру приводится к указателю на `sockaddr`.
Рассмотрим для примера структуру `sockaddr_in`.
```c
struct sockaddr_in {
short int sin_family; // Семейство адресов
unsigned short int sin_port; // Номер порта
struct in_addr sin_addr; // IP-адрес
unsigned char sin_zero[8]; // "Дополнение" до размера структуры sockaddr
};
```
Здесь поле `sin_family` соответствует полю `sa_family` в `sockaddr`,
в `sin_port` записывается номер порта, а в `sin_addr` - IP-адрес хоста.
Поле `sin_addr` само является структурой, которая имеет вид:
```c
struct in_addr {
unsigned long s_addr;
};
```
Зачем понадобилось заключать всего одно поле в структуру?
Дело в том, что раньше `in_addr` представляла собой объединение (union),
содержащее гораздо большее число полей. Сейчас, когда в ней осталось всего одно поле,
она продолжает использоваться для обратной совместимости.
И ещё одно важное замечание. Существует два порядка хранения байтов в слове и двойном слове.
Один из них называется порядком хоста (host byte order),
другой - сетевым порядком (network byte order) хранения байтов.
При указании IP-адреса и номера порта необходимо преобразовать число
из порядка хоста в сетевой. Для этого используются функции
`htons` (Host TO Network Short) и `htonl` (Host TO Network Long).
Обратное преобразование выполняют функции `ntohs` и `ntohl`.
**ПРИМЕЧАНИЕ**
На некоторых машинах (к PC это не относится) порядок хоста и сетевой порядок хранения байтов
совпадают. Тем не менее, функции преобразования лучше применять и там,
поскольку это улучшит переносимость программы.
Это никак не скажется на производительности, так как препроцессор сам уберёт
все "лишние" вызовы этих функций, оставив их только там,
где преобразование действительно необходимо.
### Установка соединения (сервер)
Установка соединения на стороне сервера состоит из четырёх этапов,
ни один из которых не может быть опущен. Сначала сокет создаётся и привязывается
к локальному адресу. Если компьютер имеет несколько сетевых интерфейсов
с различными IP-адресами, вы можете принимать соединения только с одного из них,
передав его адрес функции `bind`. Если же вы готовы соединяться с клиентами
через любой интерфейс, задайте в качестве адреса константу `INADDR_ANY`.
Что касается номера порта, вы можете задать конкретный номер
или 0 (в этом случае система сама выберет произвольный неиспользуемый
в данный момент номер порта).
На следующем шаге создаётся очередь запросов на соединение.
При этом сокет переводится в режим ожидания запросов со стороны клиентов.
Всё это выполняет функция `listen`.
```c
int listen(int sockfd, int backlog);
```
Первый параметр - дескриптор сокета, а второй задаёт размер очереди запросов.
Каждый раз, когда очередной клиент пытается соединиться с сервером,
его запрос ставится в очередь, так как сервер может быть занят обработкой других запросов.
Если очередь заполнена, все последующие запросы будут игнорироваться.
Когда сервер готов обслужить очередной запрос, он использует функцию `accept`.
```c
#include <sys/socket.h>
int accept(int sockfd, void *addr, int *addrlen);
```
Функция `accept` создаёт для общения с клиентом новый сокет и возвращает его дескриптор.
Параметр `sockfd` задаёт слушающий сокет. После вызова он остаётся
в слушающем состоянии и может принимать другие соединения.
В структуру, на которую ссылается `addr`, записывается адрес сокета клиента,
который установил соединение с сервером. В переменную, адресуемую указателем `addrlen`,
изначально записывается размер структуры;
функция `accept` записывает туда длину, которая реально была использована.
Если вас не интересует адрес клиента, вы можете просто передать `NULL`
в качестве второго и третьего параметров.
Обратите внимание, что полученный от `accept` новый сокет связан с тем же самым адресом,
что и слушающий сокет. Сначала это может показаться странным.
Но дело в том, что адрес TCP-сокета не обязан быть уникальным в Internet-домене.
Уникальными должны быть только соединения, для идентификации которых используются
два адреса сокетов, между которыми происходит обмен данными.
### Установка соединения (клиент)
На стороне клиента для установления соединения используется функция `connect`,
которая имеет следующий прототип.
```c
#include <sys/types.h>
#include <sys/socket.h>
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
```
Здесь `sockfd` - сокет, который будет использоваться для обмена данными с сервером,
`serv_addr` содержит указатель на структуру с адресом сервера,
а `addrlen` - длину этой структуры. Обычно сокет не требуется предварительно привязывать
к локальному адресу, так как функция `connect` сделает это за вас,
подобрав подходящий свободный порт. Вы можете принудительно назначить
клиентскому сокету некоторый номер порта, используя `bind` перед вызовом `connect`.
Делать это следует в случае, когда сервер соединяется с только с клиентами,
использующими определённый порт (примерами таких серверов являются `rlogind` и `rshd`).
В остальных случаях проще и надёжнее предоставить системе выбрать порт за вас.
### Обмен данными
После того как соединение установлено, можно начинать обмен данными.
Для этого используются функции `send` и `recv`.
В Unix для работы с сокетами можно использовать также файловые функции `read` и `write`,
но они обладают меньшими возможностями, а кроме того не будут работать на других платформах
(например, под Windows), поэтому я не рекомендую ими пользоваться.
Функция `send` используется для отправки данных и имеет следующий прототип.
```c
int send(int sockfd, const void *msg, int len, int flags);
```
Здесь `sockfd` - это, как всегда, дескриптор сокета, через который мы отправляем данные,
`msg` - указатель на буфер с данными,
`len` - длина буфера в байтах,
а `flags` - набор битовых флагов, управляющих работой функции
(если флаги не используются, передайте функции 0).
Вот некоторые из них (полный список можно найти в документации):
- `MSG_OOB`. Предписывает отправить данные как срочные (out of band data, OOB).
Концепция срочных данных позволяет иметь два параллельных канала данных в одном соединении.
Иногда это бывает удобно. Например, Telnet использует срочные данные для передачи команд типа
Ctrl+C. В настоящее время использовать их не рекомендуется из-за проблем с совместимостью
(существует два разных стандарта их использования, описанные в RFC793 и RFC1122).
Безопаснее просто создать для срочных данных отдельное соединение.
- `MSG_DONTROUTE`. Запрещает маршрутизацию пакетов.
Нижележащие транспортные слои могут проигнорировать этот флаг.
Функция `send` возвращает число байтов, которое на самом деле было отправлено
(или -1 в случае ошибки). Это число может быть меньше указанного размера буфера.
Если вы хотите отправить весь буфер целиком,
вам придётся написать свою функцию и вызывать в ней `send`,
пока все данные не будут отправлены. Она может выглядеть примерно так.
```c
int sendall(int s, char *buf, int len, int flags)
{
int total = 0;
int n;
while(total < len)
{
n = send(s, buf+total, len-total, flags);
if(n == -1) { break; }
total += n;
}
return (n==-1 ? -1 : total);
}
```
Использование `sendall` ничем не отличается от использования `send`,
но она отправляет весь буфер с данными целиком.
Для чтения данных из сокета используется функция `recv`.
```c
int recv(int sockfd, void *buf, int len, int flags);
```
В целом её использование аналогично `send`.
Она точно так же принимает дескриптор сокета, указатель на буфер и набор флагов.
Флаг `MSG_OOB` используется для приёма срочных данных,
а `MSG_PEEK` позволяет "подсмотреть" данные, полученные от удалённого хоста,
не удаляя их из системного буфера
(это означает, что при следующем обращении к `recv` вы получите те же самые данные).
Полный список флагов можно найти в документации.
По аналогии с `send` функция `recv` возвращает количество прочитанных байтов,
которое может быть меньше размера буфера.
Вы без труда сможете написать собственную функцию `recvall`, заполняющую буфер целиком.
Существует ещё один особый случай, при котором `recv` возвращает 0.
Это означает, что соединение было разорвано.
### Закрытие сокета
Закончив обмен данными, закройте сокет с помощью функции `close`.
Это приведёт к разрыву соединения.
```c
#include <unistd.h>
int close(int fd);
```
Вы также можете запретить передачу данных в каком-то одном направлении, используя `shutdown`.
```c
int shutdown(int sockfd, int how);
```
Параметр `how` может принимать одно из следующих значений:
- 0 - запретить чтение из сокета.
- 1 - запретить запись в сокет.
- 2 - запретить и то и другое.
Хотя после вызова `shutdown` с параметром `how`, равным 2,
вы больше не сможете использовать сокет для обмена данными,
вам всё равно потребуется вызвать `close`,
чтобы освободить связанные с ним системные ресурсы.
### Обработка ошибок
До сих пор я ни слова не сказал об ошибках,
которые могут происходить (и часто происходят) в процессе работы с сокетами.
Так вот: если что-то пошло не так, все рассмотренные нами функции возвращают -1,
записывая в глобальную переменную `errno` код ошибки.
Соответственно, вы можете проанализировать значение этой переменной
и предпринять действия по восстановлению нормальной работы программы,
не прерывая её выполнения. А можете просто выдать диагностическое сообщение
(для этого удобно использовать функцию `perror`),
а затем завершить программу с помощью `exit`.
Именно так я буду поступать в демонстрационных примерах.
### Отладка программ
Начинающие программисты часто спрашивают, как можно отлаживать сетевую программу,
если под рукой нет сети. Оказывается, можно обойтись и без неё.
Достаточно запустить клиента и сервера на одной машине,
а затем использовать для соединения адрес интерфейса внутренней петли (loopback interface).
В программе ему соответствует константа `INADDR_LOOPBACK`
(не забудьте применять к ней функцию `htonl!`).
Пакеты, направляемые по этому адресу, в сеть не попадают.
Вместо этого они передаются стеку протоколов TCP/IP как только что принятые.
Таким образом моделируется наличие виртуальной сети,
в которой вы можете отлаживать ваши сетевые приложения.
Для простоты я буду использовать в демонстрационных примерах интерфейс внутренней петли.
### Эхо-клиент и эхо-сервер
Теперь, когда мы изучили основные функции для работы с сокетами,
самое время посмотреть, как они используются на практике.
Для этого я написал две небольшие демонстрационные программы.
Эхо-клиент посылает сообщение **«Hello there!»** и выводит на экран ответ сервера.
Его код приведён в **листинге 1**.
Эхо-сервер читает всё, что передаёт ему клиент,
а затем просто отправляет полученные данные обратно.
Его код содержится в **листинге 2**.
**Листинг 1. Эхо-клиент.**
```c
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
char message[] = "Hello there!\n";
char buf[sizeof(message)];
int main()
{
int sock;
struct sockaddr_in addr;
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock < 0)
{
perror("socket");
exit(1);
}
addr.sin_family = AF_INET;
addr.sin_port = htons(3425); // или любой другой порт...
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
perror("connect");
exit(2);
}
send(sock, message, sizeof(message), 0);
recv(sock, buf, sizeof(message), 0);
printf(buf);
close(sock);
return 0;
}
```
**Листинг 2. Эхо-сервер.**
```c
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main()
{
int sock, listener;
struct sockaddr_in addr;
char buf[1024];
int bytes_read;
listener = socket(AF_INET, SOCK_STREAM, 0);
if(listener < 0)
{
perror("socket");
exit(1);
}
addr.sin_family = AF_INET;
addr.sin_port = htons(3425);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(listener, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
perror("bind");
exit(2);
}
listen(listener, 1);
while(1)
{
sock = accept(listener, NULL, NULL);
if(sock < 0)
{
perror("accept");
exit(3);
}
while(1)
{
bytes_read = recv(sock, buf, 1024, 0);
if(bytes_read <= 0) break;
send(sock, buf, bytes_read, 0);
}
close(sock);
}
return 0;
}
```

View File

@ -1,5 +1,5 @@
---
title: "🎒 Увеличиваю переносимый вес в S.T.A.L.K.E.R."
title: "🎒 Увеличиваем переносимый вес в S.T.A.L.K.E.R."
date: 2023-01-09T01:43:01+03:00
draft: false
tags: [games, tips]

View File

@ -17,13 +17,15 @@ tags: [http, tips]
Методы HTTP спроектированы для воздействия на ресурс стандартным способом:
{{< table "table table-sm table-striped table-hover" >}}
| Метод HTTP | Действие | Пример |
|------------|----------|--------|
| GET | Получить информацию о ресурсе | example.com/api/orders (получить список заказов) |
| GET | Получить информацию о ресурсе | example.com/api/orders/123 (получить заказ #123) |
| POST | Создать новый ресурс | example.com/api/orders (создать новый заказ из данных переданных с запросом) |
| PUT | Обновить ресурс | example.com/api/orders/123 (обновить заказ #123 данными переданными с запросом) |
| DELETE| Удалить ресурс |example.com/api/orders/123 (удалить заказ #123) |
|:----------:|:---------|:-------|
| GET | Получить информацию о ресурсе | `example.com/api/orders` (получить список заказов) |
| GET | Получить информацию о ресурсе | `example.com/api/orders/123` (получить заказ #123) |
| POST | Создать новый ресурс | `example.com/api/orders` (создать новый заказ из данных переданных с запросом) |
| PUT | Обновить ресурс | `example.com/api/orders/123` (обновить заказ #123 данными переданными с запросом) |
| DELETE | Удалить ресурс | `example.com/api/orders/123` (удалить заказ #123) |
{{</ table >}}
Дизайн REST не дает рекомендаций каким конкретно должен быть
формат данных передаваемых с запросами.
@ -60,13 +62,15 @@ http://[hostname]/todo/api/v1.0/
Для доступа к ресурсам будем использовать следующие методы HTTP:
{{< table "table table-sm table-striped table-hover" >}}
| Метод HTTP | URI | Действие |
|------------|-----|----------|
| GET | http://[hostname]/todo/api/v1.0/tasks | Получить список задач |
| GET | http://[hostname]/todo/api/v1.0/tasks/[task_id] | Получить задачу |
| POST | http://[hostname]/todo/api/v1.0/tasks | Создать новую задачу |
| PUT | http://[hostname]/todo/api/v1.0/tasks/[task_id] | Обновить существующую задачу |
| DELETE | http://[hostname]/todo/api/v1.0/tasks/[task_id] | Удалить задачу |
|:----------:|-----|----------|
| GET | `http://[hostname]/todo/api/v1.0/tasks` | Получить список задач |
| GET | `http://[hostname]/todo/api/v1.0/tasks/[task_id]` | Получить задачу |
| POST | `http://[hostname]/todo/api/v1.0/tasks` | Создать новую задачу |
| PUT | `http://[hostname]/todo/api/v1.0/tasks/[task_id]` | Обновить существующую задачу |
| DELETE | `http://[hostname]/todo/api/v1.0/tasks/[task_id]` | Удалить задачу |
{{</ table >}}
## Используемые ресурсы

View File

@ -0,0 +1,134 @@
---
title: "🔐 GnuPG"
date: 2023-04-05T12:05:35+03:00
draft: false
tags: [gpg, privacy, tips]
---
## GnuPG
GnuPG — полная и свободная реализация [OpenPGP](https://openpgp.org/about/) стандарта,
определенного в [RFC4880](https://tools.ietf.org/html/rfc4880) (также известного, как PGP).
GnuPG позволяет вам шифровать и подписывать данные и сообщения.
Он оснащен универсальной системой управления ключами,
а также модулями доступа для всех типов открытых ключей.
GnuPG, также известный как GPG,
это инструмент командной строки с возможностью легкой интеграции с другими приложениями.
Доступен богатый выбор пользовательских приложений и библиотек.
Также 2 версия GnuPG поддерживает S/MIME и Secure Shell (ssh).
## Расположение каталогов
`$GNUPGHOME` используется GnuPG для определения каталога,
в котором хранятся конфигурационные файлы.
По умолчанию `$GNUPGHOME` не назначена и вместо этого используется `$HOME`;
таким образом, вы найдете каталог `~/.gnupg` сразу после установки.
Чтобы изменить стандартное расположение, выполните `gpg --homedir путь/к/файлу`
или установите переменную окружения `GNUPGHOME`.
## Файлы конфигурации
Файлы конфигурации по умолчанию `~/.gnupg/gpg.conf`.
По умолчанию разрешения доступа каталога gnupg установлены в `700`,
а файлов, которые он содержит - `600`.
Только владелец каталога имеет разрешение на просмотр содержимого,
радактирование и доступ к файлам. В целях безопасности,
эти разрешения не должны быть изменены.
В случае, если этот каталог или любые файлы внутри не следуют данной мере безопасности,
вы получите предупреждение о наличии небезопасных файлов и разрешений домашнего каталога.
## Создание пары ключей
Чтобы создать пару ключей, необходимо ввести команду:
```sh
gpg --full-gen-key
```
Используйте опцию `--expert`, чтобы выбрать другие шифры,
такие как [ECC](https://en.wikipedia.org/wiki/Elliptic_curve_cryptography).
Более простая опция `--gen-key` использует параметры по умолчанию для шифра,
размера и срока действия ключа и запрашивает только имя и адрес электронной почты.
## Экспорт открытого ключа
Основное назначение GnuPG — обеспечение конфиденциальности обмена сообщениями
с помощью криптографии с открытым ключом.
С его помощью каждый пользователь распространяет открытый ключ своей связки ключей,
который может быть использован другими пользователями для шифрования сообщений пользователю.
Закрытый ключ всегда должен оставаться в тайне, иначе конфиденциальность будет нарушена.
Таким образом, чтобы другие могли отправлять вам зашифрованные сообщения,
им нужен ваш открытый ключ.
Чтобы сгенерировать ASCII-версию открытого ключа пользователя в файл `public.key`
(например, для отправки по электронной почте):
```sh
gpg --export --armor --output public.key user-id
```
### Импорт открытого ключа
Чтобы зашифровать сообщения другим людям, а также проверить их подписи,
вам нужен их открытый ключ. Чтобы импортировать открытый ключ из файла public.key в свой список открытых ключей, выполните команду:
```sh
gpg --import public.key
```
## Резервное копирование закрытого ключа
Чтобы создать резервную копию вашего закрытого ключа, выполните:
```sh
gpg --export-secret-keys --armor --output privkey.asc user-id
```
Обратите внимание, что вышеуказанная команда требует ввода пароля от ключа.
В противном случае любой, кто получит доступ к экспортированному файлу,
сможет шифровать и подписывать документы, как если бы он был вами,
без необходимости знать пароль.
⚠️ **Важно:**
Пароль — обычно самое слабое звено в защите закрытого ключа.
Поместите закрытый ключ в безопасное место на другой системе или на другом устройстве,
например, в заблокированный контейнер или на зашифрованный диск.
Это единственное средство защиты, которое поможет
вам восстановить контроль над списком ваших ключей в случае,
например, поломки диска, кражи или ещё чего-нибудь похуже.
Этот способ резервного копирования ключей имеет некоторые ограничения по безопасности.
Более безопасный способ резервного копирования и импорта ключей с помощью gpg описан
[здесь](https://web.archive.org/web/20210803213236/https://habd.as/post/moving-gpg-keys-privately/).
## Импорт закрытого ключа из резервной копии:
```sh
gpg --import privkey.asc
```
Совет: [Paperkey](https://www.jabberwocky.com/software/paperkey/) позволяет экспортировать ключ в виде простого текста
или машиночитаемого штрих-кода, которые можно отпечатать на бумаге.
## Резервное копирование сертификата отзыва
Сертификаты отзыва автоматически генерируются для вновь создаваемых ключей.
По умолчанию они находятся в `~/.gnupg/openpgp-revocs.d/`.
Имя файла сертификата — это отпечаток ключа, который он отзывает.
Сертификаты отзыва также можно сгенерированы вручную с помощью следующей команды:
```sh
gpg --gen-revoke --armor --output revcert.asc user-id
```
Этот сертификат используется, чтобы выполнить отзыв ключа в случае,
если он оказался потерян или скомпрометирован.
Резервная копия будет полезна, если у вас больше нет доступа к закрытому ключу,
из-за чего вы не можете сгенерировать
новый сертификат отзыва с помощью приведённой выше команды.
Он достаточно короткий, чтобы его можно было распечатать и набрать от руки при необходимости.
⚠️ **Важно:** Любой человек, имеющий доступ к сертификату отзыва,
может публично отозвать ключ, и это действие нельзя отменить.
Защищайте свой сертификат отзыва так же, как вы защищаете свой закрытый ключ.

View File

@ -48,3 +48,5 @@ Ctrl + b $
```text
Ctrl + b d
```
`TODO: сделать из этого таблицу`

View File

@ -1,7 +1,7 @@
---
title: "Диаграмма выводов Ardunino Nano"
date: 2023-06-19T22:05:27+03:00
draft: true
title: "🔌 Диаграмма выводов Ardunino Nano"
date: 2023-06-25T20:53:27+03:00
draft: false
tags: [arduino, tips, hardware]
---
@ -20,7 +20,8 @@ tags: [arduino, tips, hardware]
## Цифровые пины
| Pin Name | Description | Secondary Function | Description |
{{< table "table table-sm table-striped table-hover" >}}
| Имя ПИНА | Описание | Вторичная функция | Описание |
|----------|----------------|--------------------|------------------------------|
| D0 | Digital Pin 0 | RX | Receive pin for Serial UART |
| D1 | Digital Pin 1 | TX | Transmit pin for Serial UART |
@ -36,10 +37,12 @@ tags: [arduino, tips, hardware]
| D11 | Digital Pin 11 | MOSI | SPI Master Out-Slave In |
| D12 | Digital Pin 12 | MISO | SPI Master In-Slave Out |
| D13 | Digital Pin 13 | SCK | SPI Clock |
{{</ table >}}
## Аналоговые пины
| Pin Name | Description | Secondary Function | Description |
{{< table "table table-sm table-striped table-hover" >}}
| Имя ПИНА | Описание | Вторичная функция | Описание |
|----------|--------------|--------------------|-------------|
| A0 | Analog Pin 0 | | |
| A1 | Analog Pin 1 | | |
@ -49,10 +52,12 @@ tags: [arduino, tips, hardware]
| A5 | Analog Pin 5 | SCLI2C | Clock |
| A6 | Analog Pin 6 | SCL | |
| A7 | Analog Pin 7 | SCL | |
{{</ table >}}
## Пины питания
| Pin Name | Description |
{{< table "table table-sm table-striped table-hover" >}}
| Имя пина | Описание |
|----------|----------------------------------------------------------------------------------------------------|
| 5V | 5V (Regulated) Source |
| 3.3V | 3.3V Source |
@ -61,3 +66,4 @@ tags: [arduino, tips, hardware]
| Vin | DC Jack Input Voltage |
| IOREF | I/O Reference Voltage. This pin is connected to 5V for the UNO |
| AREF | ADC Reference Voltage. Insert other voltage (0-5V only) to use as reference for analog conversions |
{{</ table >}}

View File

@ -5,7 +5,7 @@ draft: true
tags: [music]
---
Моё сердечко пренадлежит:
Моё сердечко пренадлежит:
Adept
Metallica
Ill Nino

View File

@ -51,6 +51,7 @@ DFPlayer Mini — это миниатюрный MP3 проигрыватель
![](/content/images/smd/dfplayer_mini_pinout_back-scaled.jpg)
{{< table "table table-sm table-striped table-hover" >}}
| Пин | Описание | Примечание |
|--------|--------------------|---------------------------------------------------------------------------------------|
| VCC | Входное напряжение | DC3.2~5.0В; DC4.2В |
@ -69,6 +70,7 @@ DFPlayer Mini — это миниатюрный MP3 проигрыватель
| USB+ | USB+ DP | Порт USB |
| USB- | USB- DM | Порт USB |
| BUSY | Статус | Low — включено, High — выключено |
{{</ table >}}
## Рабочие режимы

View File

@ -0,0 +1 @@
Drop `bootstrap.min.css` from Bootstrap **5.3.0** in `static/css` folder.

View File

@ -0,0 +1,83 @@
<section class="bg-white border rounded shadow-sm p-3 mb-3">
<h2 class="text-center mb-3">🗂️ Project list</h2>
<div class="row row-cols-1 row-cols-md-2 g-3">
<!-- minecraft launcher -->
<div class="col">
<div class="bg-body-tertiary border rounded p-3">
<p class="fw-bold mb-2">⛏️
<a class="border-bottom border-primary text-decoration-none py-1"
href="https://me.a2s.su/minecraft-launcher/" target="_blank">
Minecraft JE Batch Launcher</a>
</p>
<p class="mb-0">Simple script for launch Minecraft without official launcher. Any OS</p>
</div>
</div>
<!-- ё с точками -->
<div class="col">
<div class="bg-body-tertiary border rounded p-3">
<p class="fw-bold mb-2">🔡
<a class="border-bottom border-primary text-decoration-none py-1"
href="https://xn--61a.a2s.su" target="_blank">
е с точками</a>
</p>
<p class="mb-0">Сайт для тех, что ценит русский язык и красивое написание текста</p>
</div>
</div>
<!-- ytcg -->
<div class="col">
<div class="bg-body-tertiary border rounded p-3">
<p class="fw-bold mb-2">🎞️
<a class="border-bottom border-primary text-decoration-none py-1"
href="https://me.a2s.su/ytcg/" target="_blank">
Get YouTube video cover</a>
</p>
<p class="mb-0">Service for download video cover from YouTube</p>
</div>
</div>
<div class="col">
<!-- chola -->
<div class="bg-body-tertiary border rounded p-3">
<p class="fw-bold mb-2">⌨️
<a class="border-bottom border-primary text-decoration-none py-1"
href="https://me.a2s.su/chola/" target="_blank">
CHange Of LAyout</a>
</p>
<p class="mb-0">Меняем написанный текст буржуйской раскладки на нашинскую</p>
</div>
</div>
<!-- pmng -->
<div class="col">
<div class="bg-body-tertiary border rounded p-3">
<p class="fw-bold mb-2">🔑
<a class="border-bottom border-primary text-decoration-none py-1"
href="https://git.a2s.su/iiiypuk/pmng" target="_blank">
pmng</a>
</p>
<p class="mb-0">The very simple password manager for humans</p>
</div>
</div>
<!-- assm -->
<div class="col">
<div class="bg-body-tertiary border rounded p-3">
<p class="fw-bold mb-2">🍎
<a class="border-bottom border-primary text-decoration-none py-1"
href="https://git.a2s.su/emilecok/assm" target="_blank">
assm</a>
</p>
<p class="mb-0">iOS splash screen generator</p>
</div>
</div>
<!-- vk0nline -->
<div class="col">
<div class="bg-body-tertiary border rounded p-3">
<p class="fw-bold mb-2">🟢
<a class="border-bottom border-primary text-decoration-none py-1"
href="https://git.a2s.su/iiiypuk/vk0nline" target="_blank">
vk0nline</a>
</p>
<p class="mb-0">systemd service and utility for set online status on vk.com</p>
</div>
</div>
</div>
</section>

View File

@ -0,0 +1,126 @@
<section class="bg-white border rounded shadow-sm p-2 mb-3">
<h2 class="text-center mt-2 mb-3">💼 Other projects</h2>
<div class="list-group">
<div class="list-group-item list-group-item-action border-0 rounded-0 my-1">
<p class="mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/mirror"
target="_blank">git.a2s.su</a>
Git mirrors of some repos
</p>
</div>
<div class="list-group-item list-group-item-action border-0 my-1">
<p class="mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/iiiypuk/battlepillars-bot"
target="_blank">battlepillars-bot</a>
Farming apples bot for
<a class="border-bottom border-primary text-decoration-none py-1" href="https://store.steampowered.com/app/280930/Battlepillars_Gold_Edition/">Battlepillars</a>
</p>
</div>
<div class="list-group-item list-group-item-action border-0 my-1">
<p class="mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/iiiypuk/delver"
target="_blank">delver-pack-ru-ru</a>
Репозиторий перевода Delver
</p>
</div>
<div class="list-group-item list-group-item-action border-0 my-1">
<p class="mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/iiiypuk/git-ahead-check"
target="_blank">git-ahead-check</a>
A tool for checking changes that have not been sent in Git repos
</p>
</div>
<div class="list-group-item list-group-item-action border-0 my-1">
<p class="mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/iiiypuk/eir"
target="_blank">eir</a>
Easy Internet Radio (Visual Basic 6)
</p>
</div>
<div class="list-group-item list-group-item-action border-0 my-1">
<p class="mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/iiiypuk/aimp-theme-pscc"
target="_blank">aimp-theme-pscc</a>
Photoshop CC 2014 Visual Style for AIMP 4
</p>
</div>
<div class="list-group-item list-group-item-action border-0 my-1">
<p class="mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/iiiypuk/proot-alpine"
target="_blank">proot-alpine</a>
Script for run Alpine Linux from user directory
</p>
</div>
<div class="list-group-item list-group-item-action border-0 my-1">
<p class="mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/iiiypuk/stanis-tits-scrap"
target="_blank">stanis-tits-scrap</a>
Скрипт для скачивания голых и не только девушек с блога
<a class="border-bottom border-primary text-decoration-none py-1"
href="http://blog.stanis.ru/" target="_blank">stanis.ru</a>
</p>
</div>
<div class="list-group-item list-group-item-action border-0 my-1">
<p class="mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/iiiypuk/lpp-linux-builder"
target="_blank">lpp-linux-builder</a>
Script for build
<a class="border-bottom border-primary text-decoration-none py-1" href="http://rinnegatamante.github.io/lpp-vita/" target="_blank">Lua Player Plus</a>
apps for PSVITA (PSP2)
</p>
</div>
<div class="list-group-item list-group-item-action border-0 my-1">
<p class="mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/iiiypuk/lastfm-backup"
target="_blank">lastfm-backup</a>
Script for download music scrobbles from Last.fm
</p>
</div>
<div class="list-group-item list-group-item-action border-0 my-1">
<p class="mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/iiiypuk/olr_steam"
target="_blank">olr_steam</a>
Скрипт для запуска Oblivion Lost Remake в Steam
</p>
</div>
<div class="list-group-item list-group-item-action border-0 my-1">
<p class="mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/iiiypuk/ogsr_steam"
target="_blank">ogsr_steam</a>
Скрипт для запуска OGSR Mod в Steam
</p>
</div>
<div class="list-group-item list-group-item-action border-0 my-1">
<p class="mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/iiiypuk/minecraft-launcher-libs"
target="_blank">minecraft-launcher-libs</a>
Library parser from
<code class="font-monospace rounded p-1 bg-dark text-white">version.json</code>
on Minecraft JE
</p>
</div>
<div class="list-group-item list-group-item-action border-0 rounded-0 my-1">
<p class="mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/iiiypuk/cuboid"
target="_blank">cuboid</a>
Stuff JoyeTech Cuboid TC 150W
</p>
</div>
</div>
</section>

View File

@ -0,0 +1,9 @@
<section class="bg-white border rounded shadow-sm p-3 mb-3">
<h2 class="text-center mb-3">📫 How to reach me</h2>
<div class="lh-lg text-center">
<a class="border-bottom border-primary text-decoration-none py-1 mx-1" target="_blank" href="mailto:iiiypuk@fastmail.fm">Mail</a>
<a class="border-bottom border-primary text-decoration-none py-1 mx-1" target="_blank" href="http://a2s.su:8000/">Micro blog</a>
<a class="border-bottom border-primary text-decoration-none py-1 mx-1" target="_blank" href="irc://iiiypuk.me:6667/admin">IRC</a>
<a class="border-bottom border-primary text-decoration-none py-1 mx-1" target="_blank" href="gemini://a2s.su">Gemini</a>
</div>
</section>

View File

@ -0,0 +1,42 @@
<section class="bg-white border rounded shadow-sm p-3 mb-3">
<h2 class="text-center">🔌 What I use</h2>
<p class="text-center lh-lg">
<span class="fw-bold">📕 Languages & frameworks:</span>
<span class="border-bottom p-1">Pure C</span>,
<span class="border-bottom p-1">Crystal</span>,
<span class="border-bottom p-1">JavaScript</span>,
<span class="border-bottom p-1">Python</span>,
<span class="border-bottom p-1">PHP</span>,
<span class="border-bottom p-1 text-nowrap">Bootstrap 5</span>
</p>
<p class="text-center lh-lg">
<span class="fw-bold">🧰 Tools:</span>
<span class="border-bottom p-1">Porteus</span>,
<span class="border-bottom p-1 text-nowrap">Alpine Linux</span>,
<span class="border-bottom p-1">OpenBSD</span>,
<span class="border-bottom p-1 text-nowrap">Arch Linux</span>,
<span class="border-bottom p-1 text-nowrap">Windows 11</span>,
<span class="border-bottom p-1 text-nowrap">Sublime Text 4</span>,
<span class="border-bottom p-1 text-nowrap">Windows Terminal</span>,
<span class="border-bottom p-1">CorelDRAW</span>,
<span class="border-bottom p-1">GameMaker</span>,
<span class="border-bottom p-1">EditorConfig</span>,
<span class="border-bottom p-1">Gitea</span>,
<span class="border-bottom p-1">Git</span>,
<span class="border-bottom p-1">Tmux</span>
</p>
<p class="text-center lh-lg">
<span class="fw-bold">📢 Services:</span>
<span class="border-bottom p-1">FastMail</span>,
<span class="border-bottom p-1">Last.fm</span>,
<span class="border-bottom p-1">MyAnimeList</span>,
<span class="border-bottom p-1">Postcrossing</span>,
<span class="border-bottom p-1">Pinterest</span>
</p>
</section>

View File

@ -3,303 +3,17 @@
<main>
<section>
<p class="bg-white border rounded shadow-sm p-3 text-center">
Hey, my name is Alexander Popov.<br>
I am a chef of anything IT :)
🙃<br>
Hey, my name is Alexander Popov.
I am a chef of anything IT.
</p>
</section>
<section class="bg-white border rounded shadow-sm p-3 mb-3">
<h2 class="text-center">🔌 What I use</h2>
{{ template "_index/projects.html" . }}
{{ template "_index/projects2.html" . }}
{{ template "_index/what_i_use.html" . }}
{{ template "_index/reach_me.html" . }}
<p class="text-center lh-lg">
<span class="fw-bold">📕 Languages & frameworks:</span>
<span class="border-bottom p-1">Pure C</span>,
<span class="border-bottom p-1">Crystal</span>,
<span class="border-bottom p-1">JavaScript</span>,
<span class="border-bottom p-1">Python</span>,
<span class="border-bottom p-1">PHP</span>,
<span class="border-bottom p-1 text-nowrap">Bootstrap 5</span>
</p>
<p class="text-center lh-lg">
<span class="fw-bold">🧰 Tools:</span>
<span class="border-bottom p-1">Porteus</span>,
<span class="border-bottom p-1 text-nowrap">Alpine Linux</span>,
<span class="border-bottom p-1">OpenBSD</span>,
<span class="border-bottom p-1 text-nowrap">Arch Linux</span>,
<span class="border-bottom p-1 text-nowrap">Windows 11</span>,
<span class="border-bottom p-1 text-nowrap">Sublime Text 4</span>,
<span class="border-bottom p-1 text-nowrap">Windows Terminal</span>,
<span class="border-bottom p-1">CorelDRAW</span>,
<span class="border-bottom p-1">GameMaker</span>,
<span class="border-bottom p-1">EditorConfig</span>,
<span class="border-bottom p-1">Gitea</span>,
<span class="border-bottom p-1">Git</span>,
<span class="border-bottom p-1">Tmux</span>
</p>
<p class="text-center lh-lg">
<span class="fw-bold">📢 Services:</span>
<span class="border-bottom p-1">FastMail</span>,
<span class="border-bottom p-1">Last.fm</span>,
<span class="border-bottom p-1">Pinterest</span>
</p>
</section>
<section class="bg-white border rounded shadow-sm p-3 mb-3">
<h2 class="text-center mb-3">🗂️ Project list</h2>
<div class="row row-cols-1 row-cols-md-2 g-3">
<!-- minecraft launcher -->
<div class="col">
<div class="border rounded p-3">
<p class="fw-bold mb-2">⛏️
<a class="border-bottom border-primary text-decoration-none py-1"
href="https://me.a2s.su/minecraft-launcher/" target="_blank">
Minecraft JE Batch Launcher</a>
</p>
<p class="mb-0">Simple script for launch Minecraft without official launcher. Any OS</p>
<p class="mb-0">
<span class="badge bg-secondary text-nowrap fw-normal">Game</span>
<span class="badge bg-secondary text-nowrap fw-normal">Shell</span>
</p>
</div>
</div>
<!-- ё с точками -->
<div class="col">
<div class="border rounded p-3">
<p class="fw-bold mb-2">🔡
<a class="border-bottom border-primary text-decoration-none py-1"
href="https://xn--61a.a2s.su" target="_blank">
е с точками</a>
</p>
<p class="mb-0">Сайт для тех, что ценит русский язык и красивое написание текста</p>
<p class="mb-0">
<span class="badge bg-secondary text-nowrap fw-normal">Grammar</span>
<span class="badge bg-secondary text-nowrap fw-normal">JavaScript</span>
</p>
</div>
</div>
<!-- ytcg -->
<div class="col">
<div class="border rounded p-3">
<p class="fw-bold mb-2">🎞️
<a class="border-bottom border-primary text-decoration-none py-1"
href="https://me.a2s.su/ytcg/" target="_blank">
Get YouTube video cover</a>
</p>
<p class="mb-0">Service for download video cover from YouTube</p>
<p class="mb-0">
<span class="badge bg-secondary text-nowrap fw-normal">YouTube</span>
<span class="badge bg-secondary text-nowrap fw-normal">JavaScript</span>
</p>
</div>
</div>
<div class="col">
<!-- chola -->
<div class="border rounded p-3">
<p class="fw-bold mb-2">⌨️
<a class="border-bottom border-primary text-decoration-none py-1"
href="https://me.a2s.su/chola/" target="_blank">
CHange Of LAyout</a>
</p>
<p class="mb-0">Меняем написанный текст буржуйской раскладки на нашинскую</p>
<p class="mb-0">
<span class="badge bg-secondary text-nowrap fw-normal">Grammar</span>
<span class="badge bg-secondary text-nowrap fw-normal">JavaScript</span>
</p>
</div>
</div>
<!-- pmng -->
<div class="col">
<div class="border rounded p-3">
<p class="fw-bold mb-2">🔑
<a class="border-bottom border-primary text-decoration-none py-1"
href="https://git.a2s.su/iiiypuk/pmng" target="_blank">
pmng</a>
</p>
<p class="mb-0">The very simple password manager for humans</p>
<p class="mb-0">
<span class="badge bg-secondary text-nowrap fw-normal">CLI</span>
<span class="badge bg-secondary text-nowrap fw-normal">Tool</span>
<span class="badge bg-secondary text-nowrap fw-normal">Crystal</span>
</p>
</div>
</div>
<!-- assm -->
<div class="col">
<div class="border rounded p-3">
<p class="fw-bold mb-2">🍎
<a class="border-bottom border-primary text-decoration-none py-1"
href="https://git.a2s.su/emilecok/assm" target="_blank">
assm</a>
</p>
<p class="mb-0">iOS splash screen generator</p>
<p class="mb-0">
<span class="badge bg-secondary text-nowrap fw-normal">CLI</span>
<span class="badge bg-secondary text-nowrap fw-normal">Tool</span>
<span class="badge bg-secondary text-nowrap fw-normal">Python</span>
</p>
</div>
</div>
<!-- vk0nline -->
<div class="col">
<div class="border rounded p-3">
<p class="fw-bold mb-2">🟢
<a class="border-bottom border-primary text-decoration-none py-1"
href="https://git.a2s.su/iiiypuk/vk0nline" target="_blank">
vk0nline</a>
</p>
<p class="mb-0">systemd service and utility for set online status on vk.com</p>
<p class="mb-0">
<span class="badge bg-secondary text-nowrap fw-normal">Social</span>
<span class="badge bg-secondary text-nowrap fw-normal">Crystal</span>
<span class="badge bg-secondary text-nowrap fw-normal">systemd</span>
</p>
</div>
</div>
</div>
</section>
<section class="bg-white border rounded shadow-sm p-3 mb-3">
<h2 class="text-center mb-3">💼 Other projects</h2>
<div class="row row-cols-1 g-3">
<div class="col">
<p class="border rounded p-2 mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/mirror"
target="_blank">git.a2s.su</a>
Git mirrors of some repos
</p>
</div>
<div class="col">
<p class="border rounded p-2 mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/iiiypuk/battlepillars-bot"
target="_blank">battlepillars-bot</a>
Farming apples bot for
<a class="border-bottom border-primary text-decoration-none py-1" href="https://store.steampowered.com/app/280930/Battlepillars_Gold_Edition/">Battlepillars</a>
</p>
</div>
<div class="col">
<p class="border rounded p-2 mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/iiiypuk/delver"
target="_blank">delver-pack-ru-ru</a>
Репозиторий перевода Delver
</p>
</div>
<div class="col">
<p class="border rounded p-2 mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/iiiypuk/git-ahead-check"
target="_blank">git-ahead-check</a>
A tool for checking changes that have not been sent in Git repos
</p>
</div>
<div class="col">
<p class="border rounded p-2 mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/iiiypuk/eir"
target="_blank">eir</a>
Easy Internet Radio (Visual Basic 6)
</p>
</div>
<div class="col">
<p class="border rounded p-2 mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/iiiypuk/aimp-theme-pscc"
target="_blank">aimp-theme-pscc</a>
Photoshop CC 2014 Visual Style for AIMP 4
</p>
</div>
<div class="col">
<p class="border rounded p-2 mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/iiiypuk/proot-alpine"
target="_blank">proot-alpine</a>
Script for run Alpine Linux from user directory
</p>
</div>
<div class="col">
<p class="border rounded p-2 mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/iiiypuk/stanis-tits-scrap"
target="_blank">stanis-tits-scrap</a>
Скрипт для скачивания голых и не только девушек с блога
<a class="border-bottom border-primary text-decoration-none py-1"
href="http://blog.stanis.ru/" target="_blank">stanis.ru</a>
</p>
</div>
<div class="col">
<p class="border rounded p-2 mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/iiiypuk/lpp-linux-builder"
target="_blank">lpp-linux-builder</a>
Script for build
<a class="border-bottom border-primary text-decoration-none py-1" href="http://rinnegatamante.github.io/lpp-vita/" target="_blank">Lua Player Plus</a>
apps for PSVITA (PSP2)
</p>
</div>
<div class="col">
<p class="border rounded p-2 mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/iiiypuk/lastfm-backup"
target="_blank">lastfm-backup</a>
Script for download music scrobbles from Last.fm
</p>
</div>
<div class="col">
<p class="border rounded p-2 mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/iiiypuk/olr_steam"
target="_blank">olr_steam</a>
Скрипт для запуска Oblivion Lost Remake в Steam
</p>
</div>
<div class="col">
<p class="border rounded p-2 mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/iiiypuk/ogsr_steam"
target="_blank">ogsr_steam</a>
Скрипт для запуска OGSR Mod в Steam
</p>
</div>
<div class="col">
<p class="border rounded p-2 mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/iiiypuk/minecraft-launcher-libs"
target="_blank">minecraft-launcher-libs</a>
Library parser from
<code class="font-monospace rounded p-1 bg-dark text-white">version.json</code>
on Minecraft JE
</p>
</div>
<div class="col">
<p class="border rounded p-2 mb-0">
<a class="border-bottom border-primary text-decoration-none py-1 fw-bold"
href="https://git.a2s.su/iiiypuk/cuboid"
target="_blank">cuboid</a>
Stuff JoyeTech Cuboid TC 150W
</p>
</div>
</div>
</section>
<section class="bg-white border rounded shadow-sm p-3 mb-3">
<h2 class="text-center mb-3">📫 How to reach me</h2>
<div class="lh-lg text-center">
<a class="border-bottom border-primary text-decoration-none p-1" target="_blank" href="mailto:iiiypuk@fastmail.fm">EMail</a>
<a class="border-bottom border-primary text-decoration-none p-1" target="_blank" href="http://a2s.su:8000/">Micro blog</a>
<a class="border-bottom border-primary text-decoration-none p-1" target="_blank" href="irc://iiiypuk.me:6667/admin">IRC</a>
<a class="border-bottom border-primary text-decoration-none p-1" target="_blank" href="gemini://a2s.su">Gemini</a>
</div>
</section>
</main>
</div>
{{ end }}

View File

@ -0,0 +1,6 @@
{{ $htmlTable := .Inner | markdownify }}
{{ $class := .Get 0 }}
{{ $old := "<table>" }}
{{ $new := printf "<table class=\"%s\">" $class }}
{{ $htmlTable := replace $htmlTable $old $new }}
{{ $htmlTable | safeHTML }}