Compare commits
13 Commits
feature/md
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ecf72656b | ||
|
|
241effd3b8 | ||
|
|
64c9134cc2 | ||
|
|
19b53db5f3 | ||
|
|
a26c0eab8a | ||
|
|
3ac86cfeb0 | ||
|
|
d895433a65 | ||
|
|
3064887ecf | ||
|
|
02e9d5c529 | ||
|
|
f45140ef04 | ||
|
|
bdcd11d97e | ||
|
|
6a0d34d37b | ||
|
|
2df80c90f6 |
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 fake .env file for build
|
- name: Create .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,9 +48,10 @@ 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 "OFFER_URL=http://localhost:3000/offer" >> .env
|
echo "SUPPORT_TELEGRAM_URL=${{ secrets.SUPPORT_TELEGRAM_URL }}" >> .env
|
||||||
echo "PRIVACY_URL=http://localhost:3000/privacy" >> .env
|
echo "URL_OFFER=${{ secrets.URL_OFFER }}" >> .env
|
||||||
echo "SUPPORT_TELEGRAM_URL=http://t.me/support" >> .env
|
echo "URL_PRIVACY=${{ secrets.URL_PRIVACY }}" >> .env
|
||||||
|
echo "URL_FAQ=${{ secrets.URL_FAQ }}" >> .env
|
||||||
|
|
||||||
- name: Set image tags
|
- name: Set image tags
|
||||||
id: vars
|
id: vars
|
||||||
@ -115,7 +116,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 real .env file (No Tags)
|
- name: Create .env file for deploy
|
||||||
run: |
|
run: |
|
||||||
# Включаем все секреты, КРОМЕ тегов
|
# Включаем все секреты, КРОМЕ тегов
|
||||||
echo "BOT_TOKEN=${{ secrets.BOT_TOKEN }}" > .env
|
echo "BOT_TOKEN=${{ secrets.BOT_TOKEN }}" > .env
|
||||||
@ -129,8 +130,9 @@ 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 "OFFER_URL=${{ secrets.OFFER_URL }}" >> .env
|
echo "URL_OFFER=${{ secrets.URL_OFFER }}" >> .env
|
||||||
echo "PRIVACY_URL=${{ secrets.PRIVACY_URL }}" >> .env
|
echo "URL_PRIVACY=${{ secrets.URL_PRIVACY }}" >> .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,6 +55,7 @@ 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.OFFER_URL,
|
offerUrl: env.URL_OFFER,
|
||||||
privacyUrl: env.PRIVACY_URL,
|
privacyUrl: env.URL_PRIVACY,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -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.OFFER_URL,
|
offerUrl: env.URL_OFFER,
|
||||||
privacyUrl: env.PRIVACY_URL,
|
privacyUrl: env.URL_PRIVACY,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -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.OFFER_URL,
|
offerUrl: env.URL_OFFER,
|
||||||
privacyUrl: env.PRIVACY_URL,
|
privacyUrl: env.URL_PRIVACY,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -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.OFFER_URL,
|
offerUrl: env.URL_OFFER,
|
||||||
privacyUrl: env.PRIVACY_URL,
|
privacyUrl: env.URL_PRIVACY,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
{
|
{
|
||||||
|
|||||||
@ -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.OFFER_URL,
|
offerUrl: env.URL_OFFER,
|
||||||
privacyUrl: env.PRIVACY_URL,
|
privacyUrl: env.URL_PRIVACY,
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
...KEYBOARD_REMOVE,
|
...KEYBOARD_REMOVE,
|
||||||
|
|||||||
@ -4,8 +4,6 @@ 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))
|
||||||
@ -20,6 +18,9 @@ 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,6 +58,11 @@ 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,4 +1,3 @@
|
|||||||
import { OfferLink, SupportLink } from '@/components/documents/links';
|
|
||||||
import { env } from '@/config/env';
|
import { env } from '@/config/env';
|
||||||
|
|
||||||
export const metadata = {
|
export const metadata = {
|
||||||
@ -12,7 +11,7 @@ export const metadata = {
|
|||||||
|
|
||||||
#### 1. Термины и определения
|
#### 1. Термины и определения
|
||||||
|
|
||||||
1.1. Оферта — настоящий документ, постоянно размещенный в сети Интернет по адресу <OfferLink />.
|
1.1. Оферта — настоящий документ, постоянно размещенный в сети Интернет по адресу <a href={env.URL_OFFER}>{env.URL_OFFER}</a>.
|
||||||
|
|
||||||
1.2. Акцепт — полное и безоговорочное принятие условий Оферты Пользователем путем оплаты доступа через встроенный платежный бот ЮKassa в Telegram.
|
1.2. Акцепт — полное и безоговорочное принятие условий Оферты Пользователем путем оплаты доступа через встроенный платежный бот ЮKassa в Telegram.
|
||||||
|
|
||||||
@ -97,6 +96,4 @@ export const metadata = {
|
|||||||
|
|
||||||
#### 10. Контакты
|
#### 10. Контакты
|
||||||
|
|
||||||
Если у Вас есть вопросы по настоящему договору публичной оферты персональных данных, пожалуйста, свяжитесь с Разработчиком:
|
Если у Вас есть вопросы по настоящему договору публичной оферты персональных данных, пожалуйста, свяжитесь с Разработчиком. Контакты указаны в описании бота.
|
||||||
|
|
||||||
- **Telegram:** <SupportLink/>
|
|
||||||
@ -1,6 +1,3 @@
|
|||||||
import { SupportLink } from '@/components/documents/links';
|
|
||||||
import { env } from '@/config/env';
|
|
||||||
|
|
||||||
export const metadata = {
|
export const metadata = {
|
||||||
title: 'Политика конфиденциальности',
|
title: 'Политика конфиденциальности',
|
||||||
description:
|
description:
|
||||||
@ -34,8 +31,7 @@ export const metadata = {
|
|||||||
|
|
||||||
3.2. Разработчик вправе изменять настоящую Политику — изменения вступают в силу с момента их публикации. Вы обязаны самостоятельно отслеживать обновления.
|
3.2. Разработчик вправе изменять настоящую Политику — изменения вступают в силу с момента их публикации. Вы обязаны самостоятельно отслеживать обновления.
|
||||||
|
|
||||||
3.3. Используя Сервис, Вы подтверждаете, что ознакомлены и согласны с условиями использования Telegram для ботов и мини-приложений:
|
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).
|
||||||
[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. Вы гарантируете, что используете Сервис в соответствии с действующим законодательством и обладаете правом взаимодействовать с ним (например, достигли возраста, необходимого для использования услуг).
|
||||||
|
|
||||||
@ -132,6 +128,4 @@ 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.OFFER_URL} rel="noreferrer" target="_blank">
|
<a href={env.URL_OFFER} rel="noreferrer" target="_blank">
|
||||||
{env.OFFER_URL}
|
{env.URL_OFFER}
|
||||||
</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,39 +1,7 @@
|
|||||||
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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// внешние ссылки → target="_blank"
|
export function useMDXComponents(): MDXComponents {
|
||||||
return (
|
return components;
|
||||||
<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.0",
|
"next": "^15.5.9",
|
||||||
"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,6 +341,8 @@ 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: {
|
||||||
@ -349,6 +351,13 @@ 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.11
|
"@types/react": ^19.1.17
|
||||||
"@types/react-dom": ^19.1.8
|
"@types/react-dom": ^19.1.17
|
||||||
"@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.1
|
react: ^19.1.4
|
||||||
react-dom: ^19.1.1
|
react-dom: ^19.1.4
|
||||||
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,8 +18,9 @@
|
|||||||
"REDIS_HOST",
|
"REDIS_HOST",
|
||||||
"REDIS_PORT",
|
"REDIS_PORT",
|
||||||
"REDIS_PASSWORD",
|
"REDIS_PASSWORD",
|
||||||
"OFFER_URL",
|
"URL_OFFER",
|
||||||
"PRIVACY_URL"
|
"URL_PRIVACY",
|
||||||
|
"URL_FAQ"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"lint": {
|
"lint": {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user