From d2843d79a012bada886a37cdc8ceb9e06b191fa1 Mon Sep 17 00:00:00 2001 From: adonis Date: Tue, 7 Jul 2026 14:34:00 +0330 Subject: [PATCH] added some keys into setting --- .../Controllers/Admin/ProductController.php | 1 + app/Services/LivePriceTickService.php | 7 +- app/Services/PriceChannelBroadcastService.php | 323 ++++++++++++++++++ database/sql/deploy_settings_const.sql | 73 +++- database/sql/price_channel_settings.sql | 87 +++++ 5 files changed, 488 insertions(+), 3 deletions(-) create mode 100644 app/Services/PriceChannelBroadcastService.php create mode 100644 database/sql/price_channel_settings.sql diff --git a/app/Http/Controllers/Admin/ProductController.php b/app/Http/Controllers/Admin/ProductController.php index 2590bb1..eb49dd4 100644 --- a/app/Http/Controllers/Admin/ProductController.php +++ b/app/Http/Controllers/Admin/ProductController.php @@ -262,6 +262,7 @@ class ProductController extends SuperController dispatch(function () { app(PriceBroadcastService::class)->broadcastAfterPriceUpdate(); + app(\App\Services\PriceChannelBroadcastService::class)->broadcastIfEligible(); })->afterResponse(); return response()->json(true); diff --git a/app/Services/LivePriceTickService.php b/app/Services/LivePriceTickService.php index ce854eb..7f32d8a 100644 --- a/app/Services/LivePriceTickService.php +++ b/app/Services/LivePriceTickService.php @@ -86,7 +86,12 @@ class LivePriceTickService app(LivePriceCacheService::class)->markTick(); // last از put داخل lastPrice؛ list بعد از sync محصولات - app(PriceBroadcastService::class)->broadcastListIfChanged(); + $listChanged = app(PriceBroadcastService::class)->broadcastListIfChanged(); + + // بعد از هر تغییر قیمت، قیمت‌ها را به کانال‌های پیام‌رسان بفرست (با cooldown داخلی) + if ($listChanged) { + app(PriceChannelBroadcastService::class)->broadcastIfEligible(); + } } finally { $lock->release(); } diff --git a/app/Services/PriceChannelBroadcastService.php b/app/Services/PriceChannelBroadcastService.php new file mode 100644 index 0000000..ed43e42 --- /dev/null +++ b/app/Services/PriceChannelBroadcastService.php @@ -0,0 +1,323 @@ +config->getBool('price_channel_enabled', false)) { + return; + } + + $targets = $this->resolveActiveTargets(); + if ($targets === []) { + return; + } + + if (! $this->cooldownElapsed()) { + return; + } + + $message = $this->buildMessage(); + if ($message === '') { + return; + } + + foreach ($targets as $messenger => $target) { + $this->dispatchToMessenger($messenger, $target['token'], $target['chat_ids'], $message); + } + + $this->markSent(); + } catch (\Throwable $e) { + Log::warning('PriceChannelBroadcast failed', ['message' => $e->getMessage()]); + } + } + + /** + * پیام‌رسان‌های قابل ارسال: انتخاب‌شده + توکن معتبر + حداقل یک مقصد. + * + * @return array}> + */ + private function resolveActiveTargets(): array + { + $selected = $this->selectedMessengers(); + if ($selected === []) { + return []; + } + + $targets = []; + foreach ($selected as $messenger) { + $token = trim((string) $this->config->getString($this->tokenKey($messenger), '')); + $chatIds = $this->parseList($this->config->getString($this->chatIdsKey($messenger), '')); + + if ($token === '' || $chatIds === []) { + continue; + } + + $targets[$messenger] = ['token' => $token, 'chat_ids' => $chatIds]; + } + + return $targets; + } + + /** @return array */ + private function selectedMessengers(): array + { + $raw = $this->parseList($this->config->getString('price_channel_messengers', '')); + + return array_values(array_filter( + array_map(static fn ($m) => strtolower(trim($m)), $raw), + static fn ($m) => in_array($m, self::SUPPORTED_MESSENGERS, true) + )); + } + + private function tokenKey(string $messenger): string + { + return match ($messenger) { + 'bale' => 'bale_bot_token', + 'telegram' => 'telegram_bot_token', + 'rubika' => 'rubika_bot_token', + default => '', + }; + } + + private function chatIdsKey(string $messenger): string + { + return "price_channel_{$messenger}_to"; + } + + /** + * ساخت متن پیام قیمت — مرتب و بر اساس داده‌ی هر محصول. + */ + public function buildMessage(): string + { + $products = $this->eligibleProducts(); + if ($products === []) { + return ''; + } + + $channelDiff = (float) $this->config->getInt('price_channel_diff', 0); + $diffBuy = (float) $this->config->displayBuyPriceDiffRial(); + $diffSell = (float) $this->config->displaySellPriceDiffRial(); + $mesghal = $this->changeMesghal(); + + $lines = []; + $lines[] = $this->header(); + $lines[] = ''; + + foreach ($products as $product) { + $base = (float) ($product->price ?? 0); + + // 🔴 خرید (مشتری می‌فروشد، پایین‌تر) — 🟢 فروش (مشتری می‌خرد، بالاتر) + $low = $base - $diffSell - $channelDiff; + $high = $base + $diffBuy + $channelDiff; + + $lines[] = '🛒 ' . trim((string) $product->title); + $lines[] = '🔴 خرید ' . $this->formatPrice($low) . ' 🟢 فروش ' . $this->formatPrice($high); + + if ($this->isGramUnit($product) && $mesghal > 0) { + $lines[] = '💰 هر گرم: ' . $this->formatPrice($low / $mesghal) + . ' / ' . $this->formatPrice($high / $mesghal); + } + + $lines[] = ''; + } + + $footer = $this->footerLines(); + if ($footer !== []) { + $lines[] = '➖➖➖➖➖➖'; + foreach ($footer as $line) { + $lines[] = $line; + } + } + + return trim(implode("\n", $lines)); + } + + private function header(): string + { + $name = trim((string) $this->config->getString('name_fa', '')); + $time = now()->format('H:i'); + + $title = $name !== '' ? "📊 قیمت لحظه‌ای {$name}" : '📊 قیمت لحظه‌ای'; + + return $title . "\n🕐 ساعت " . $time; + } + + /** + * @return array + */ + private function eligibleProducts(): array + { + $products = Product::query() + ->where('active', 1) + ->orderBy('id') + ->get(); + + $eligible = []; + foreach ($products as $product) { + if ((int) ($product->price ?? 0) <= 0) { + continue; + } + if (! ($product->open_buy || $product->open_sell)) { + continue; + } + if (! $this->config->isProductWithinTradingHours($product)) { + continue; + } + + $eligible[] = $product; + } + + return $eligible; + } + + private function isGramUnit(Product $product): bool + { + return trim((string) ($product->unit ?? '')) === 'گرم'; + } + + /** قیمت را به واحد نمایش (تقسیم بر ۱۰٬۰۰۰) با جداکننده‌ی هزارگان می‌برد */ + private function formatPrice(float $value): string + { + return number_format(max(0, $value) / 10000, 0); + } + + private function changeMesghal(): float + { + $fromConfig = $this->config->get('change_mesghal'); + $value = (float) ($fromConfig ?: config('change_mesghal', self::DEFAULT_CHANGE_MESGHAL)); + + return $value > 0 ? $value : self::DEFAULT_CHANGE_MESGHAL; + } + + /** + * خطوط پایانی — فقط مقادیر پرشده نمایش داده می‌شوند (آیدی چنل، شماره، لینک). + * + * @return array + */ + private function footerLines(): array + { + $lines = []; + + foreach (['price_channel_footer_id', 'price_channel_footer_phone', 'price_channel_footer_link'] as $key) { + $value = trim((string) $this->config->getString($key, '')); + if ($value !== '') { + $lines[] = $value; + } + } + + return $lines; + } + + private function dispatchToMessenger(string $messenger, string $token, array $chatIds, string $message): void + { + foreach ($chatIds as $chatId) { + try { + match ($messenger) { + 'bale' => $this->sendBale($token, $chatId, $message), + 'telegram' => $this->sendTelegram($token, $chatId, $message), + 'rubika' => $this->sendRubika($token, $chatId, $message), + default => null, + }; + } catch (\Throwable $e) { + Log::warning("PriceChannel {$messenger} send failed", [ + 'chat_id' => $chatId, + 'message' => $e->getMessage(), + ]); + } + } + } + + private function sendBale(string $token, string $chatId, string $message): void + { + Http::withOptions(Controller::httpClientOptions()) + ->withoutVerifying() + ->timeout(6) + ->post("https://tapi.bale.ai/bot{$token}/sendMessage", [ + 'chat_id' => $chatId, + 'text' => $message, + ]); + } + + private function sendTelegram(string $token, string $chatId, string $message): void + { + Http::withOptions(Controller::httpClientOptions()) + ->timeout(6) + ->post("https://api.telegram.org/bot{$token}/sendMessage", [ + 'chat_id' => $chatId, + 'text' => $message, + ]); + } + + private function sendRubika(string $token, string $chatId, string $message): void + { + Http::withOptions(Controller::httpClientOptions()) + ->withoutVerifying() + ->timeout(6) + ->post("https://botapi.rubika.ir/v3/{$token}/sendMessage", [ + 'chat_id' => $chatId, + 'text' => $message, + ]); + } + + /** حداقل فاصله‌ی مجاز بین دو ارسال — جلوگیری از سیل پیام در هر تیک ۱۰ثانیه‌ای */ + private function cooldownElapsed(): bool + { + $minSeconds = max(0, $this->config->getInt('price_channel_min_seconds', 120)); + if ($minSeconds === 0) { + return true; + } + + $lastSent = Cache::get(self::COOLDOWN_CACHE_KEY); + if ($lastSent === null) { + return true; + } + + return now()->timestamp - (int) $lastSent >= $minSeconds; + } + + private function markSent(): void + { + Cache::put(self::COOLDOWN_CACHE_KEY, now()->timestamp, now()->addDay()); + } + + /** @return array */ + private function parseList(string $raw): array + { + $parts = preg_split('/[,\n]+/', trim($raw)) ?: []; + + return array_values(array_filter(array_map('trim', $parts), static fn ($p) => $p !== '')); + } +} diff --git a/database/sql/deploy_settings_const.sql b/database/sql/deploy_settings_const.sql index a5e334a..1929f44 100644 --- a/database/sql/deploy_settings_const.sql +++ b/database/sql/deploy_settings_const.sql @@ -343,6 +343,71 @@ INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `de SELECT 'bale_bot_token', '', 'توکن بات بله', 0, 1, NULL WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'bale_bot_token' LIMIT 1); +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'rubika_bot_token', '', 'توکن بات روبیکا', 0, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'rubika_bot_token' LIMIT 1); + +-- =========================================================================== +-- ارسال قیمت به کانال‌های پیام‌رسان (بله / تلگرام / روبیکا) +-- • محتوا (can_edit=1): روشن/خاموش، انتخاب پیام‌رسان، اختلاف، خطوط پایانی، فاصله +-- • سیستمی (can_edit=0): مقصد ارسال هر پیام‌رسان (آیدی چنل/گروه) +-- • توکن‌ها همان bale_bot_token / telegram_bot_token / rubika_bot_token (can_edit=0) +-- =========================================================================== +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'price_channel_enabled', 'false', 'ارسال قیمت به کانال', 1, 1, + 'روشن: بعد از هر تغییر قیمت، مظنه به کانال‌های پیام‌رسان انتخاب‌شده ارسال می‌شود.', 'switch' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_channel_enabled' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'price_channel_messengers', '', 'پیام‌رسان‌های ارسال قیمت', 1, 1, + 'کدام پیام‌رسان‌ها قیمت بگیرند؟ با ویرگول جدا کنید. گزینه‌ها: bale,telegram,rubika', 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_channel_messengers' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'price_channel_diff', '0', 'اختلاف قیمت کانال (ریال)', 1, 1, + 'مبلغی که به قیمت خرید کانال اضافه و از قیمت فروش کم می‌شود (اسپرد اضافه فقط برای کانال).', 'price' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_channel_diff' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'price_channel_min_seconds', '120', 'حداقل فاصله ارسال (ثانیه)', 1, 1, + 'حداقل فاصله بین دو ارسال به کانال؛ جلوی سیل پیام را می‌گیرد. صفر = هر تغییر قیمت.', 'number' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_channel_min_seconds' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'price_channel_footer_id', '', 'آیدی کانال در پیام', 1, 1, + 'اگر پر باشد در انتهای پیام نمایش داده می‌شود (مثلاً یوزرنیم کانال). خالی = نمایش داده نمی‌شود.', 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_channel_footer_id' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'price_channel_footer_phone', '', 'شماره تماس در پیام', 1, 1, + 'اگر پر باشد در انتهای پیام نمایش داده می‌شود. خالی = نمایش داده نمی‌شود.', 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_channel_footer_phone' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'price_channel_footer_link', '', 'لینک در پیام', 1, 1, + 'اگر پر باشد در انتهای پیام نمایش داده می‌شود. خالی = نمایش داده نمی‌شود.', 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_channel_footer_link' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'price_channel_bale_to', '', 'مقصد ارسال بله', 0, 1, + 'آیدی چنل/گروه بله برای ارسال قیمت (چند مقصد با ویرگول).', 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_channel_bale_to' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'price_channel_telegram_to', '', 'مقصد ارسال تلگرام', 0, 1, + 'آیدی چنل/گروه تلگرام برای ارسال قیمت (چند مقصد با ویرگول).', 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_channel_telegram_to' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'price_channel_rubika_to', '', 'مقصد ارسال روبیکا', 0, 1, + 'آیدی چنل/گروه روبیکا برای ارسال قیمت (چند مقصد با ویرگول).', 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_channel_rubika_to' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'change_mesghal', '4.3318', 'وزن مثقال (گرم)', 1, 1, + 'ضریب تبدیل قیمت مثقال به گرم برای نمایش خط «هر گرم» در پیام کانال.', 'number' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'change_mesghal' LIMIT 1); + INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) SELECT 'support_messenger_id', '', 'شناسه پشتیبانی پیام‌رسان', 1, 0, 'یوزرنیم یا شماره تماس بسته به پیام‌رسان انتخاب‌شده' WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'support_messenger_id' LIMIT 1); @@ -1191,7 +1256,8 @@ UPDATE `settings` SET `can_edit` = 0 WHERE `key` IN ( 'send_to_tahesab', 'service_charge_percentage', 'sse_path', 'tahesab_bank_account', 'tahesab_db', 'tahesab_host', 'tahesab_port', 'tahesab_token', - 'telegram_bot_token', + 'telegram_bot_token', 'rubika_bot_token', + 'price_channel_bale_to', 'price_channel_telegram_to', 'price_channel_rubika_to', 'unit', 'up_price', 'down_price', 'wss_enabled', @@ -1217,7 +1283,10 @@ UPDATE `settings` SET `can_edit` = 1 WHERE `key` IN ( 'register_jibit_verify', 'register_referral_bonus_message', 'register_referral_sms_to_referrer', 'sell_fee', 'show_last_price', 'startDay', 'support_messenger', 'support_messenger_id', 'support_messenger_text', - 'text_about', 'text_rule' + 'text_about', 'text_rule', + 'price_channel_enabled', 'price_channel_messengers', 'price_channel_diff', + 'price_channel_min_seconds', 'price_channel_footer_id', 'price_channel_footer_phone', + 'price_channel_footer_link', 'change_mesghal' ); -- تفکیک نهایی type (بعد از همه batchها — override روی دیتابیس موجود) diff --git a/database/sql/price_channel_settings.sql b/database/sql/price_channel_settings.sql new file mode 100644 index 0000000..01b32d9 --- /dev/null +++ b/database/sql/price_channel_settings.sql @@ -0,0 +1,87 @@ +-- ============================================================================= +-- price_channel_settings.sql — کلیدهای «ارسال قیمت به کانال» برای نصب‌های موجود +-- +-- این کلیدها در deploy_settings_const.sql هم هستند (روی هر deploy اجرا می‌شوند). +-- این فایل فقط برای افزودن سریع به یک DB موجود، بدون اجرای کل deploy، است. +-- +-- قبل از اجرا: USE `نام_دیتابیس`; + بکاپ +-- idempotent — چند بار قابل اجرا (value ردیف موجود دست نمی‌خورد). +-- ============================================================================= + +START TRANSACTION; +SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- توکن روبیکا (توکن بله/تلگرام از قبل موجودند) — سیستمی (can_edit=0) +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'rubika_bot_token', '', 'توکن بات روبیکا', 0, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'rubika_bot_token' LIMIT 1); + +-- محتوا — قابل ویرایش (can_edit=1) +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'price_channel_enabled', 'false', 'ارسال قیمت به کانال', 1, 1, + 'روشن: بعد از هر تغییر قیمت، مظنه به کانال‌های پیام‌رسان انتخاب‌شده ارسال می‌شود.', 'switch' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_channel_enabled' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'price_channel_messengers', '', 'پیام‌رسان‌های ارسال قیمت', 1, 1, + 'کدام پیام‌رسان‌ها قیمت بگیرند؟ با ویرگول جدا کنید. گزینه‌ها: bale,telegram,rubika', 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_channel_messengers' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'price_channel_diff', '0', 'اختلاف قیمت کانال (ریال)', 1, 1, + 'مبلغی که به قیمت خرید کانال اضافه و از قیمت فروش کم می‌شود (اسپرد اضافه فقط برای کانال).', 'price' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_channel_diff' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'price_channel_min_seconds', '120', 'حداقل فاصله ارسال (ثانیه)', 1, 1, + 'حداقل فاصله بین دو ارسال به کانال؛ جلوی سیل پیام را می‌گیرد. صفر = هر تغییر قیمت.', 'number' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_channel_min_seconds' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'price_channel_footer_id', '', 'آیدی کانال در پیام', 1, 1, + 'اگر پر باشد در انتهای پیام نمایش داده می‌شود (مثلاً یوزرنیم کانال). خالی = نمایش داده نمی‌شود.', 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_channel_footer_id' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'price_channel_footer_phone', '', 'شماره تماس در پیام', 1, 1, + 'اگر پر باشد در انتهای پیام نمایش داده می‌شود. خالی = نمایش داده نمی‌شود.', 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_channel_footer_phone' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'price_channel_footer_link', '', 'لینک در پیام', 1, 1, + 'اگر پر باشد در انتهای پیام نمایش داده می‌شود. خالی = نمایش داده نمی‌شود.', 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_channel_footer_link' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'change_mesghal', '4.3318', 'وزن مثقال (گرم)', 1, 1, + 'ضریب تبدیل قیمت مثقال به گرم برای نمایش خط «هر گرم» در پیام کانال.', 'number' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'change_mesghal' LIMIT 1); + +-- مقصد ارسال هر پیام‌رسان (آیدی چنل/گروه) — سیستمی (can_edit=0) +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'price_channel_bale_to', '', 'مقصد ارسال بله', 0, 1, + 'آیدی چنل/گروه بله برای ارسال قیمت (چند مقصد با ویرگول).', 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_channel_bale_to' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'price_channel_telegram_to', '', 'مقصد ارسال تلگرام', 0, 1, + 'آیدی چنل/گروه تلگرام برای ارسال قیمت (چند مقصد با ویرگول).', 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_channel_telegram_to' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'price_channel_rubika_to', '', 'مقصد ارسال روبیکا', 0, 1, + 'آیدی چنل/گروه روبیکا برای ارسال قیمت (چند مقصد با ویرگول).', 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_channel_rubika_to' LIMIT 1); + +-- استانداردسازی can_edit +UPDATE `settings` SET `can_edit` = 0 WHERE `key` IN ( + 'rubika_bot_token', + 'price_channel_bale_to', 'price_channel_telegram_to', 'price_channel_rubika_to' +); +UPDATE `settings` SET `can_edit` = 1 WHERE `key` IN ( + 'price_channel_enabled', 'price_channel_messengers', 'price_channel_diff', + 'price_channel_min_seconds', 'price_channel_footer_id', 'price_channel_footer_phone', + 'price_channel_footer_link', 'change_mesghal' +); + +COMMIT;