Compare commits
5 Commits
main
...
feature/md
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae92b81dfe | ||
|
|
8765c1d74d | ||
|
|
7560b1702f | ||
|
|
b5813e3b53 | ||
|
|
13d85436a7 |
16
.github/workflows/deploy.yml
vendored
16
.github/workflows/deploy.yml
vendored
@ -37,7 +37,7 @@ jobs:
|
|||||||
cache_proxy:
|
cache_proxy:
|
||||||
- 'apps/cache-proxy/**'
|
- 'apps/cache-proxy/**'
|
||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
- name: Create .env file for build
|
- name: Create fake .env file for build
|
||||||
run: |
|
run: |
|
||||||
echo "BOT_TOKEN=fake" > .env
|
echo "BOT_TOKEN=fake" > .env
|
||||||
echo "LOGIN_GRAPHQL=fake" >> .env
|
echo "LOGIN_GRAPHQL=fake" >> .env
|
||||||
@ -48,10 +48,9 @@ jobs:
|
|||||||
echo "BOT_URL=http://localhost:3000" >> .env
|
echo "BOT_URL=http://localhost:3000" >> .env
|
||||||
echo "REDIS_PASSWORD=fake" >> .env
|
echo "REDIS_PASSWORD=fake" >> .env
|
||||||
echo "BOT_PROVIDER_TOKEN=fake" >> .env
|
echo "BOT_PROVIDER_TOKEN=fake" >> .env
|
||||||
echo "SUPPORT_TELEGRAM_URL=${{ secrets.SUPPORT_TELEGRAM_URL }}" >> .env
|
echo "OFFER_URL=http://localhost:3000/offer" >> .env
|
||||||
echo "URL_OFFER=${{ secrets.URL_OFFER }}" >> .env
|
echo "PRIVACY_URL=http://localhost:3000/privacy" >> .env
|
||||||
echo "URL_PRIVACY=${{ secrets.URL_PRIVACY }}" >> .env
|
echo "SUPPORT_TELEGRAM_URL=http://t.me/support" >> .env
|
||||||
echo "URL_FAQ=${{ secrets.URL_FAQ }}" >> .env
|
|
||||||
|
|
||||||
- name: Set image tags
|
- name: Set image tags
|
||||||
id: vars
|
id: vars
|
||||||
@ -116,7 +115,7 @@ jobs:
|
|||||||
ssh -i ~/.ssh/id_rsa -p ${{ secrets.VPS_PORT }} -o StrictHostKeyChecking=no ${{ secrets.VPS_USER }}@${{ secrets.VPS_HOST }} "mkdir -p /home/${{ secrets.VPS_USER }}/zapishis"
|
ssh -i ~/.ssh/id_rsa -p ${{ secrets.VPS_PORT }} -o StrictHostKeyChecking=no ${{ secrets.VPS_USER }}@${{ secrets.VPS_HOST }} "mkdir -p /home/${{ secrets.VPS_USER }}/zapishis"
|
||||||
|
|
||||||
# --- НОВОЕ: Шаг 2: Создание основного .env БЕЗ ТЕГОВ ---
|
# --- НОВОЕ: Шаг 2: Создание основного .env БЕЗ ТЕГОВ ---
|
||||||
- name: Create .env file for deploy
|
- name: Create real .env file (No Tags)
|
||||||
run: |
|
run: |
|
||||||
# Включаем все секреты, КРОМЕ тегов
|
# Включаем все секреты, КРОМЕ тегов
|
||||||
echo "BOT_TOKEN=${{ secrets.BOT_TOKEN }}" > .env
|
echo "BOT_TOKEN=${{ secrets.BOT_TOKEN }}" > .env
|
||||||
@ -130,9 +129,8 @@ jobs:
|
|||||||
echo "REDIS_PASSWORD=${{ secrets.REDIS_PASSWORD }}" >> .env
|
echo "REDIS_PASSWORD=${{ secrets.REDIS_PASSWORD }}" >> .env
|
||||||
echo "BOT_PROVIDER_TOKEN=${{ secrets.BOT_PROVIDER_TOKEN }}" >> .env
|
echo "BOT_PROVIDER_TOKEN=${{ secrets.BOT_PROVIDER_TOKEN }}" >> .env
|
||||||
echo "SUPPORT_TELEGRAM_URL=${{ secrets.SUPPORT_TELEGRAM_URL }}" >> .env
|
echo "SUPPORT_TELEGRAM_URL=${{ secrets.SUPPORT_TELEGRAM_URL }}" >> .env
|
||||||
echo "URL_OFFER=${{ secrets.URL_OFFER }}" >> .env
|
echo "OFFER_URL=${{ secrets.OFFER_URL }}" >> .env
|
||||||
echo "URL_PRIVACY=${{ secrets.URL_PRIVACY }}" >> .env
|
echo "PRIVACY_URL=${{ secrets.PRIVACY_URL }}" >> .env
|
||||||
echo "URL_FAQ=${{ secrets.URL_FAQ }}" >> .env
|
|
||||||
|
|
||||||
# --- НОВОЕ: Шаг 3: Создание файлов тегов (.project.env) ---
|
# --- НОВОЕ: Шаг 3: Создание файлов тегов (.project.env) ---
|
||||||
- name: Create Project Tag Env Files
|
- name: Create Project Tag Env Files
|
||||||
|
|||||||
@ -55,7 +55,6 @@ btn-pro = 👑 Pro доступ
|
|||||||
btn-subscribe = 👑 Приобрести Pro
|
btn-subscribe = 👑 Приобрести Pro
|
||||||
btn-pro-info = ℹ️ Мой Pro доступ
|
btn-pro-info = ℹ️ Мой Pro доступ
|
||||||
btn-open-app = 📱 Открыть приложение
|
btn-open-app = 📱 Открыть приложение
|
||||||
btn-faq = 📖 Инструкция
|
|
||||||
btn-documents = 📋 Документы
|
btn-documents = 📋 Документы
|
||||||
btn-back = ◀️ Назад
|
btn-back = ◀️ Назад
|
||||||
|
|
||||||
|
|||||||
@ -26,8 +26,8 @@ export async function addContact(conversation: Conversation<Context, Context>, c
|
|||||||
combine(
|
combine(
|
||||||
t('msg-need-phone'),
|
t('msg-need-phone'),
|
||||||
t('share-phone-agreement', {
|
t('share-phone-agreement', {
|
||||||
offerUrl: env.URL_OFFER,
|
offerUrl: env.OFFER_URL,
|
||||||
privacyUrl: env.URL_PRIVACY,
|
privacyUrl: env.PRIVACY_URL,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -42,8 +42,8 @@ export async function addContact(conversation: Conversation<Context, Context>, c
|
|||||||
t('msg-send-client-contact-or-phone'),
|
t('msg-send-client-contact-or-phone'),
|
||||||
t('msg-cancel-operation'),
|
t('msg-cancel-operation'),
|
||||||
t('share-contact-agreement', {
|
t('share-contact-agreement', {
|
||||||
offerUrl: env.URL_OFFER,
|
offerUrl: env.OFFER_URL,
|
||||||
privacyUrl: env.URL_PRIVACY,
|
privacyUrl: env.PRIVACY_URL,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -99,8 +99,8 @@ export async function subscription(conversation: Conversation<Context, Context>,
|
|||||||
|
|
||||||
const agreementText = await conversation.external(({ t }) => {
|
const agreementText = await conversation.external(({ t }) => {
|
||||||
return t('payment-agreement', {
|
return t('payment-agreement', {
|
||||||
offerUrl: env.URL_OFFER,
|
offerUrl: env.OFFER_URL,
|
||||||
privacyUrl: env.URL_PRIVACY,
|
privacyUrl: env.PRIVACY_URL,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -28,8 +28,8 @@ feature.command('start', logHandle('command-start'), async (ctx) => {
|
|||||||
combine(
|
combine(
|
||||||
ctx.t('msg-welcome'),
|
ctx.t('msg-welcome'),
|
||||||
ctx.t('share-phone-agreement', {
|
ctx.t('share-phone-agreement', {
|
||||||
offerUrl: env.URL_OFFER,
|
offerUrl: env.OFFER_URL,
|
||||||
privacyUrl: env.URL_PRIVACY,
|
privacyUrl: env.PRIVACY_URL,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
{
|
{
|
||||||
|
|||||||
@ -5,8 +5,8 @@ import { KEYBOARD_REMOVE } from '@/config/keyboards';
|
|||||||
async function handler(ctx: Context) {
|
async function handler(ctx: Context) {
|
||||||
await ctx.reply(
|
await ctx.reply(
|
||||||
ctx.t('agreement-links', {
|
ctx.t('agreement-links', {
|
||||||
offerUrl: env.URL_OFFER,
|
offerUrl: env.OFFER_URL,
|
||||||
privacyUrl: env.URL_PRIVACY,
|
privacyUrl: env.PRIVACY_URL,
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
...KEYBOARD_REMOVE,
|
...KEYBOARD_REMOVE,
|
||||||
|
|||||||
@ -4,6 +4,8 @@ export const envSchema = z.object({
|
|||||||
BOT_PROVIDER_TOKEN: z.string(),
|
BOT_PROVIDER_TOKEN: z.string(),
|
||||||
BOT_TOKEN: z.string(),
|
BOT_TOKEN: z.string(),
|
||||||
BOT_URL: z.string(),
|
BOT_URL: z.string(),
|
||||||
|
OFFER_URL: z.string(),
|
||||||
|
PRIVACY_URL: z.string(),
|
||||||
RATE_LIMIT: z
|
RATE_LIMIT: z
|
||||||
.string()
|
.string()
|
||||||
.transform((value) => Number.parseInt(value, 10))
|
.transform((value) => Number.parseInt(value, 10))
|
||||||
@ -18,9 +20,6 @@ export const envSchema = z.object({
|
|||||||
.string()
|
.string()
|
||||||
.transform((value) => Number.parseInt(value, 10))
|
.transform((value) => Number.parseInt(value, 10))
|
||||||
.default('6379'),
|
.default('6379'),
|
||||||
URL_FAQ: z.string(),
|
|
||||||
URL_OFFER: z.string(),
|
|
||||||
URL_PRIVACY: z.string(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const env = envSchema.parse(process.env);
|
export const env = envSchema.parse(process.env);
|
||||||
|
|||||||
@ -58,11 +58,6 @@ export const mainMenu = new Menu<Context>('main-menu', { autoAnswer: true })
|
|||||||
.row()
|
.row()
|
||||||
.text((ctx) => ctx.t('btn-documents'), handleDocuments)
|
.text((ctx) => ctx.t('btn-documents'), handleDocuments)
|
||||||
.row()
|
.row()
|
||||||
.url(
|
|
||||||
(ctx) => ctx.t('btn-faq'),
|
|
||||||
() => env.URL_FAQ,
|
|
||||||
)
|
|
||||||
.row()
|
|
||||||
.url(
|
.url(
|
||||||
(ctx) => ctx.t('btn-open-app'),
|
(ctx) => ctx.t('btn-open-app'),
|
||||||
() => {
|
() => {
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { OfferLink, SupportLink } from '@/components/documents/links';
|
||||||
import { env } from '@/config/env';
|
import { env } from '@/config/env';
|
||||||
|
|
||||||
export const metadata = {
|
export const metadata = {
|
||||||
@ -11,7 +12,7 @@ export const metadata = {
|
|||||||
|
|
||||||
#### 1. Термины и определения
|
#### 1. Термины и определения
|
||||||
|
|
||||||
1.1. Оферта — настоящий документ, постоянно размещенный в сети Интернет по адресу <a href={env.URL_OFFER}>{env.URL_OFFER}</a>.
|
1.1. Оферта — настоящий документ, постоянно размещенный в сети Интернет по адресу <OfferLink />.
|
||||||
|
|
||||||
1.2. Акцепт — полное и безоговорочное принятие условий Оферты Пользователем путем оплаты доступа через встроенный платежный бот ЮKassa в Telegram.
|
1.2. Акцепт — полное и безоговорочное принятие условий Оферты Пользователем путем оплаты доступа через встроенный платежный бот ЮKassa в Telegram.
|
||||||
|
|
||||||
@ -96,4 +97,6 @@ export const metadata = {
|
|||||||
|
|
||||||
#### 10. Контакты
|
#### 10. Контакты
|
||||||
|
|
||||||
Если у Вас есть вопросы по настоящему договору публичной оферты персональных данных, пожалуйста, свяжитесь с Разработчиком. Контакты указаны в описании бота.
|
Если у Вас есть вопросы по настоящему договору публичной оферты персональных данных, пожалуйста, свяжитесь с Разработчиком:
|
||||||
|
|
||||||
|
- **Telegram:** <SupportLink/>
|
||||||
|
|||||||
@ -1,3 +1,6 @@
|
|||||||
|
import { SupportLink } from '@/components/documents/links';
|
||||||
|
import { env } from '@/config/env';
|
||||||
|
|
||||||
export const metadata = {
|
export const metadata = {
|
||||||
title: 'Политика конфиденциальности',
|
title: 'Политика конфиденциальности',
|
||||||
description:
|
description:
|
||||||
@ -31,7 +34,8 @@ export const metadata = {
|
|||||||
|
|
||||||
3.2. Разработчик вправе изменять настоящую Политику — изменения вступают в силу с момента их публикации. Вы обязаны самостоятельно отслеживать обновления.
|
3.2. Разработчик вправе изменять настоящую Политику — изменения вступают в силу с момента их публикации. Вы обязаны самостоятельно отслеживать обновления.
|
||||||
|
|
||||||
3.3. Используя Сервис, Вы подтверждаете, что ознакомлены и согласны с условиями использования Telegram для ботов и мини-приложений: [https://telegram.org/tos/bots](https://telegram.org/tos/bots), [https://telegram.org/tos/mini-apps](https://telegram.org/tos/mini-apps).
|
3.3. Используя Сервис, Вы подтверждаете, что ознакомлены и согласны с условиями использования Telegram для ботов и мини-приложений:
|
||||||
|
[https://telegram.org/tos/bots](https://telegram.org/tos/bots), [https://telegram.org/tos/mini-apps](https://telegram.org/tos/mini-apps).
|
||||||
|
|
||||||
3.4. Вы гарантируете, что используете Сервис в соответствии с действующим законодательством и обладаете правом взаимодействовать с ним (например, достигли возраста, необходимого для использования услуг).
|
3.4. Вы гарантируете, что используете Сервис в соответствии с действующим законодательством и обладаете правом взаимодействовать с ним (например, достигли возраста, необходимого для использования услуг).
|
||||||
|
|
||||||
@ -128,4 +132,6 @@ export const metadata = {
|
|||||||
|
|
||||||
#### 11. Контакты
|
#### 11. Контакты
|
||||||
|
|
||||||
Если у Вас есть вопросы по Политике конфиденциальности или запросы в отношении персональных данных, пожалуйста, свяжитесь с Разработчиком. Контакты указаны в описании бота.
|
Если у Вас есть вопросы по Политике конфиденциальности или запросы в отношении персональных данных, пожалуйста, свяжитесь с Разработчиком:
|
||||||
|
|
||||||
|
- **Telegram:** <SupportLink/>
|
||||||
|
|||||||
@ -2,8 +2,8 @@ import { env } from '@/config/env';
|
|||||||
|
|
||||||
export function OfferLink() {
|
export function OfferLink() {
|
||||||
return (
|
return (
|
||||||
<a href={env.URL_OFFER} rel="noreferrer" target="_blank">
|
<a href={env.OFFER_URL} rel="noreferrer" target="_blank">
|
||||||
{env.URL_OFFER}
|
{env.OFFER_URL}
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,8 +4,8 @@ import { z } from 'zod';
|
|||||||
export const envSchema = z.object({
|
export const envSchema = z.object({
|
||||||
__DEV_TELEGRAM_ID: z.string().default(''),
|
__DEV_TELEGRAM_ID: z.string().default(''),
|
||||||
BOT_URL: z.string(),
|
BOT_URL: z.string(),
|
||||||
|
OFFER_URL: z.string(),
|
||||||
SUPPORT_TELEGRAM_URL: z.string(),
|
SUPPORT_TELEGRAM_URL: z.string(),
|
||||||
URL_OFFER: z.string(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const env = envSchema.parse(process.env);
|
export const env = envSchema.parse(process.env);
|
||||||
|
|||||||
@ -1,7 +1,39 @@
|
|||||||
import { type MDXComponents } from 'mdx/types';
|
import { type MDXComponents } from 'mdx/types';
|
||||||
|
import Link from 'next/link';
|
||||||
|
|
||||||
const components = {} satisfies MDXComponents;
|
/**
|
||||||
|
* Этот объект определяет, какие React-компоненты
|
||||||
|
* будут использоваться для рендеринга MDX-тегов (<a>, <h1>, <p> и т.д.)
|
||||||
|
* и какие кастомные компоненты будут доступны прямо в MDX.
|
||||||
|
*/
|
||||||
|
const components: MDXComponents = {
|
||||||
|
// 🔗 Заменяем стандартные <a> на <Link> Next.js
|
||||||
|
a: ({ children, href = '', ...props }) => {
|
||||||
|
// внутренние ссылки → через <Link>
|
||||||
|
if (href.startsWith('/')) {
|
||||||
|
return (
|
||||||
|
<Link href={href} {...props}>
|
||||||
|
{children}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function useMDXComponents(): MDXComponents {
|
// внешние ссылки → target="_blank"
|
||||||
return components;
|
return (
|
||||||
|
<a href={href} rel="noopener noreferrer" target="_blank" {...props}>
|
||||||
|
{children}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Эта функция вызывается автоматически при рендере MDX.
|
||||||
|
* Через неё Next.js App Router объединяет глобальные и локальные MDX-компоненты.
|
||||||
|
*/
|
||||||
|
export function useMDXComponents(componentsArgument: MDXComponents): MDXComponents {
|
||||||
|
return {
|
||||||
|
...components,
|
||||||
|
...componentsArgument, // позволяет переопределять внутри MDX
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,7 +36,7 @@
|
|||||||
"graphql": "catalog:",
|
"graphql": "catalog:",
|
||||||
"jsdom": "^25.0.1",
|
"jsdom": "^25.0.1",
|
||||||
"lucide-react": "catalog:",
|
"lucide-react": "catalog:",
|
||||||
"next": "^15.5.9",
|
"next": "^15.5.0",
|
||||||
"next-auth": "^4.24.11",
|
"next-auth": "^4.24.11",
|
||||||
"next-themes": "^0.4.4",
|
"next-themes": "^0.4.4",
|
||||||
"postcss": "catalog:",
|
"postcss": "catalog:",
|
||||||
|
|||||||
@ -341,8 +341,6 @@ export class SubscriptionsService extends BaseService {
|
|||||||
|
|
||||||
const now = dayjs();
|
const now = dayjs();
|
||||||
|
|
||||||
const { customer } = await this._getUser();
|
|
||||||
|
|
||||||
const { orders } = await ordersService.getOrders({
|
const { orders } = await ordersService.getOrders({
|
||||||
filters: {
|
filters: {
|
||||||
datetime_end: {
|
datetime_end: {
|
||||||
@ -351,13 +349,6 @@ export class SubscriptionsService extends BaseService {
|
|||||||
datetime_start: {
|
datetime_start: {
|
||||||
gte: now.startOf('month').toISOString(),
|
gte: now.startOf('month').toISOString(),
|
||||||
},
|
},
|
||||||
slot: {
|
|
||||||
master: {
|
|
||||||
documentId: {
|
|
||||||
eq: customer.documentId,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
state: {
|
state: {
|
||||||
eq: GQL.Enum_Order_State.Completed,
|
eq: GQL.Enum_Order_State.Completed,
|
||||||
|
|||||||
1016
pnpm-lock.yaml
generated
1016
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -4,8 +4,8 @@ packages:
|
|||||||
catalog:
|
catalog:
|
||||||
"@apollo/client": ^3.12.4
|
"@apollo/client": ^3.12.4
|
||||||
"@types/node": ^20
|
"@types/node": ^20
|
||||||
"@types/react": ^19.1.17
|
"@types/react": ^19.1.11
|
||||||
"@types/react-dom": ^19.1.17
|
"@types/react-dom": ^19.1.8
|
||||||
"@vchikalkin/eslint-config-awesome": ^2.2.2
|
"@vchikalkin/eslint-config-awesome": ^2.2.2
|
||||||
autoprefixer: ^10.4.20
|
autoprefixer: ^10.4.20
|
||||||
dayjs: ^1.11.3
|
dayjs: ^1.11.3
|
||||||
@ -19,8 +19,8 @@ catalog:
|
|||||||
postcss: ^8.4.49
|
postcss: ^8.4.49
|
||||||
postcss-load-config: ^6.0.1
|
postcss-load-config: ^6.0.1
|
||||||
prettier: ^3.2.5
|
prettier: ^3.2.5
|
||||||
react: ^19.1.4
|
react: ^19.1.1
|
||||||
react-dom: ^19.1.4
|
react-dom: ^19.1.1
|
||||||
radashi: ^12.5.1
|
radashi: ^12.5.1
|
||||||
rimraf: ^6.0.1
|
rimraf: ^6.0.1
|
||||||
tailwindcss: ^3.4.15
|
tailwindcss: ^3.4.15
|
||||||
|
|||||||
@ -18,9 +18,8 @@
|
|||||||
"REDIS_HOST",
|
"REDIS_HOST",
|
||||||
"REDIS_PORT",
|
"REDIS_PORT",
|
||||||
"REDIS_PASSWORD",
|
"REDIS_PASSWORD",
|
||||||
"URL_OFFER",
|
"OFFER_URL",
|
||||||
"URL_PRIVACY",
|
"PRIVACY_URL"
|
||||||
"URL_FAQ"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"lint": {
|
"lint": {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user