<?php
namespace App\Controller\User\VPN\Service;
use App\Entity\Generic\User;
use App\Entity\Telegram\AgentPublicBot\Bot;
use App\Entity\VPN\Service\Plan;
use App\Entity\VPN\Service\Service;
use App\Form\VPN\Service\Service\LimitedOcServType;
use App\Form\VPN\Service\Service\LimitedOpenType;
use App\Form\VPN\Service\Service\LimitedV2rayType;
use App\Form\VPN\Service\Service\LimitedVipType;
use App\Form\VPN\Service\Service\RollbackType;
use App\Form\VPN\Service\Service\UnlimitedOcServType;
use App\Form\VPN\Service\Service\UnlimitedOpenType;
use App\Form\VPN\Service\Service\UnlimitedV2rayType;
use App\Repository\VPN\V2ray\ServerRepository;
use App\Service\TransactionService;
use App\Service\Util\ByteConvert;
use App\Service\Util\DynamicPriceCalculation;
use App\Service\VPN\Service\ServiceService;
use App\ViewModel\VPN\Service\ServiceViewModel;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
#[Route('/panel/user/vpn/service')]
class ServiceController extends AbstractController
{
public ServiceService $service;
public ?Request $request;
public TransactionService $transaction;
public EntityManagerInterface $em;
public DynamicPriceCalculation $dynamicPriceCalculation;
public function __construct(ServiceService $service, RequestStack $requestStack, EntityManagerInterface $em, TransactionService $transaction, DynamicPriceCalculation $dynamicPriceCalculation)
{
$this->dynamicPriceCalculation = $dynamicPriceCalculation;
$this->em = $em;
$this->transaction = $transaction;
$this->service = $service;
$this->request = $requestStack->getCurrentRequest();
}
#[Route('/', name: 'app_panel_user_vpn_service_index', methods: ['GET'])]
public function index(Request $request): Response
{
/**
* @var User $user
*/
$user = $this->getUser();
if ($user->getConnectedTelegramUserId() === null || $user->getConnectedTelegramUserId() === []) {
$this->addFlash('error', 'لطفا ابتدا حساب خود را به تلگرام متصل فرمایید');
return $this->redirectToRoute('app_user_dashboard');
}
$info = new ServiceViewModel($request);
$data = $this->service->getListUser($info, $user);
return $this->render('panel/pages/user/vpn/service/list.html.twig', [
'paginator' => $data,
'currentPage' => 'app_panel_user_vpn_service_index',
'parameters' => $info,
'filters' => $this->getFilters(),
'lists' => $this->getLists(),
]);
}
public function getFilters(): array
{
$userBots = $this->getDoctrine()->getRepository(Bot::class)->findBy(['active' => 1, 'owner' => $this->getUser()]);
$botsList = [];
$botsList[] = ['name' => 'همه', 'value' => 'all'];
foreach ($userBots as $item) {
$botsList[] = ['name' => $item->getDescription(), 'value' => $item->getId()];
}
return [
[
'name' => 'clientId',
'type' => 'text',
'label' => 'شناسه سرویس',
'class' => '',
'value' => $this->request->get('clientId')
],
[
'name' => 'username',
'type' => 'text',
'label' => 'نام کاربری',
'class' => '',
'value' => $this->request->get('username')
],
[
'name' => 'botId',
'type' => 'radio',
'label' => 'ربات تلگرام',
'class' => '',
'radio' => $botsList,
'value' => $this->request->get('botId')
],
[
'name' => 'active',
'type' => 'radio',
'label' => 'وضعیت',
'class' => '',
'radio' => [
['name' => 'همه', 'value' => 'all'],
['name' => 'فعال', 'value' => 'true'],
['name' => 'غیرفعال', 'value' => 'false'],
],
'value' => $this->request->get('active')
],
[
'name' => 'serviceType',
'type' => 'radio',
'label' => 'نوع سرویس',
'class' => '',
'radio' => [
['name' => 'همه', 'value' => 'all'],
['name' => 'حجمی', 'value' => 'sized'],
['name' => 'نامحدود', 'value' => 'unlimited'],
],
'value' => $this->request->get('serviceType')
],
[
'name' => 'protocol',
'type' => 'radio',
'label' => 'نوع پروتکل',
'class' => '',
'radio' => [
['name' => 'همه', 'value' => 'all'],
['name' => 'V2ray', 'value' => 'v2ray'],
['name' => 'OpenVPN', 'value' => 'open'],
['name' => 'Cisco', 'value' => 'ocserv'],
['name' => 'VIP مولتی', 'value' => 'vip'],
],
'value' => $this->request->get('protocol')
],
];
}
public function getLists(): array
{
$array = [
[
'name' => 'v1ListService',
'label' => 'سرویس',
'class' => '',
'type' => 'serviceDetail',
'mobile' => true
],
[
'name' => 'v2InfoService',
'label' => 'اطلاعات دسترسی',
'class' => '',
'type' => 'serviceSubDetail',
'withoutPassword' => 'app_vpn_service_panel_no_password',
'withPassword' => 'app_vpn_service_panel_no_password',
'mobile' => true,
'charge' => 'app_panel_user_vpn_service_charge',
// 'rollback' => 'app_panel_user_vpn_service_rollback',
'status' => 'app_panel_user_vpn_service_status',
'disableHourly' => 'app_panel_user_vpn_service_index',
'enableHourly' => 'app_panel_user_vpn_service_index',
'username' => 'app_panel_user_vpn_service_edit'
],
];
return $array;
}
#[Route('/new', name: 'app_panel_user_vpn_service_new', methods: ['GET', 'POST'])]
public function new(Request $request, ByteConvert $byteConvert, ServerRepository $serverRepository, \App\Repository\VPN\OpenVPN\ServerRepository $openServerREpo, \App\Repository\VPN\OcServ\ServerRepository $ocServerRepository): Response
{
/**
* @var User $user
*/
$user = $this->getUser();
/**
* @var User $user
*/
$user = $this->getUser();
if ($user->getConnectedTelegramUserId() === null || $user->getConnectedTelegramUserId() === []) {
$this->addFlash('error', 'لطفا ابتدا حساب خود را به تلگرام متصل فرمایید');
return $this->redirectToRoute('app_user_dashboard');
}
$formTypes = [
'sizedVip' => LimitedVipType::class,
'sizedV2ray' => LimitedV2rayType::class,
'unlimitedV2ray' => UnlimitedV2rayType::class,
'sizedOcServ' => LimitedOcServType::class,
'unlimitedOcServ' => UnlimitedOcServType::class,
'sizedOpen' => LimitedOpenType::class,
'unlimitedOpen' => UnlimitedOpenType::class,
];
$forms = [];
foreach ($formTypes as $formName => $formClass) {
switch ($formName) {
case 'unlimitedV2ray':
$locations = [];
foreach ($serverRepository->findBy(['active' => 1]) as $server) {
$locations[$this->countryCodeToFlag($server->getCountry()->getCode()) . $server->getCountry()->getTitle()] = $server->getCountry()->getCode();
}
$form = $this->createForm($formClass, null, [
'clientId' => $this->service->getFreeClientId(),
'locations' => $locations
]);
break;
case 'unlimitedOcServ':
$locations = [];
foreach ($ocServerRepository->findBy(['active' => 1]) as $server) {
$locations[$this->countryCodeToFlag($server->getCountry()->getCode()) . $server->getCountry()->getTitle()] = $server->getCountry()->getCode();
}
$form = $this->createForm($formClass, null, [
'clientId' => $this->service->getFreeClientId(),
'locations' => $locations
]);
break;
case 'unlimitedOpen':
$locations = [];
foreach ($openServerREpo->findBy(['active' => 1]) as $server) {
$locations[$this->countryCodeToFlag($server->getCountry()->getCode()) . $server->getCountry()->getTitle()] = $server->getCountry()->getCode();
}
$form = $this->createForm($formClass, null, [
'clientId' => $this->service->getFreeClientId(),
'locations' => $locations
]);
break;
case 'sizedV2ray':
case 'sizedOpen':
case 'sizedOcServ':
case 'sizedVip':
$form = $this->createForm($formClass, null, [
'clientId' => $this->service->getFreeClientId()
]);
break;
}
$form->handleRequest($request);
switch ($formName) {
case 'sizedVip':
case 'sizedV2ray':
case 'unlimitedV2ray':
case 'sizedOcServ':
case 'unlimitedOcServ':
case 'sizedOpen':
case 'unlimitedOpen':
if ($form->isSubmitted() && $form->isValid()) {
$queryArray = $form->getData();
unset($queryArray['username']);
unset($queryArray['password']);
$queryArray['size'] = $byteConvert->toByte($queryArray['size'] . 'GB');
$queryArray['active'] = 1;
$targetPlan = $this->em->getRepository(Plan::class)->findOneBy($queryArray);
if (!$targetPlan) {
$this->addFlash('error', 'این بسته در حال حاضر ارائه نمیشود');
return $this->redirectToRoute('app_panel_user_vpn_service_new');
}
// var_dump($queryArray);die;
// TODO:Check User Interest Rate For Price
// $price = $targetPlan->getPrice();
$price = $this->dynamicPriceCalculation->calculatePrice($user, $targetPlan);
$allBalance = $user->getWallet() + $user->getGiftWallet();
if ($allBalance >= $price){
if ($user->getWallet() < $price) {
$neededPrice = $price - $user->getWallet();
$user->setGiftWallet($user->getGiftWallet() - $neededPrice);
$this->transaction->createTransaction($user, $neededPrice,
"دریافت مبلغ از کیف پول هدیه"
, 1, 0, null, 0, null, 'gift');
}
$serviceData = $form->getData();
$serviceData['clientId'] = $form->get('clientId')->getData();
if ($form->has('country')) {
// var_dump($form->get('country')->getData());die;
$country = $form->get('country')->getData() ?: null;
} else {
$country = 'all';
}
$service = $this->service->createService($targetPlan, $serviceData, $user, $country);
$this->transaction->createTransaction($user, $price,
"خرید سرویس جدید {$service->getClientId()}"
, 0, 0);
$this->addFlash('success', 'سرویس مد نظر با موفقیت ثبت شد');
return $this->redirectToRoute('app_panel_user_vpn_service_index');
}else {
$this->addFlash('error', 'موجودی کیف پول شما با جمع کیف پول هدیه کافی نمی باشد');
return $this->redirectToRoute('app_panel_user_vpn_service_new');
}
}
break;
default:
// Handle any default case if necessary
break;
}
$forms[$formName] = $form->createView();
}
return $this->render('panel/pages/user/vpn/service/enter.html.twig', [
'sizedVipForm' => $forms['sizedVip'] ?? '',
'sizedV2rayForm' => $forms['sizedV2ray'] ?? '',
'unlimitedV2rayForm' => $forms['unlimitedV2ray'] ?? '',
'sizedOcServForm' => $forms['sizedOcServ'] ?? '',
'unlimitedOcServForm' => $forms['unlimitedOcServ'] ?? '',
'sizedOpenForm' => $forms['sizedOpen'] ?? '',
'unlimitedOpenForm' => $forms['unlimitedOpen'] ?? '',
]);
}
#[Route('/charge/{id}', name: 'app_panel_user_vpn_service_charge', methods: ['GET', 'POST'])]
public function charge(Request $request, ByteConvert $byteConvert, ServerRepository $serverRepository, \App\Repository\VPN\OpenVPN\ServerRepository $openServerREpo, \App\Repository\VPN\OcServ\ServerRepository $ocServerRepository, Service $service)
{
/**
* @var User $user
*/
$user = $this->getUser();
// var_dump($user->getWallet());die;
$formTypes = [
'sizedVip' => LimitedVipType::class,
'sizedV2ray' => LimitedV2rayType::class,
'unlimitedV2ray' => UnlimitedV2rayType::class,
'sizedOcServ' => LimitedOcServType::class,
'unlimitedOcServ' => UnlimitedOcServType::class,
'sizedOpen' => LimitedOpenType::class,
'unlimitedOpen' => UnlimitedOpenType::class,
];
$forms = [];
foreach ($formTypes as $formName => $formClass) {
switch ($formName) {
case 'unlimitedV2ray':
$locations = [];
foreach ($serverRepository->findBy(['active' => 1]) as $server) {
$locations[$this->countryCodeToFlag($server->getCountry()->getCode()) . $server->getCountry()->getTitle()] = $server->getCountry()->getCode();
}
$form = $this->createForm($formClass, null, [
'clientId' => $service->getClientId(),
'locations' => $locations
]);
break;
case 'unlimitedOcServ':
$locations = [];
foreach ($ocServerRepository->findBy(['active' => 1]) as $server) {
$locations[$this->countryCodeToFlag($server->getCountry()->getCode()) . $server->getCountry()->getTitle()] = $server->getCountry()->getCode();
}
$form = $this->createForm($formClass, null, [
'clientId' => $service->getClientId(),
'locations' => $locations
]);
break;
case 'unlimitedOpen':
$locations = [];
foreach ($openServerREpo->findBy(['active' => 1]) as $server) {
$locations[$this->countryCodeToFlag($server->getCountry()->getCode()) . $server->getCountry()->getTitle()] = $server->getCountry()->getCode();
}
$form = $this->createForm($formClass, null, [
'clientId' => $service->getClientId(),
'locations' => $locations
]);
break;
case 'sizedV2ray':
case 'sizedOpen':
case 'sizedOcServ':
case 'sizedVip':
$form = $this->createForm($formClass, null, [
'clientId' => $service->getClientId(),
]);
break;
}
$form->remove('username');
$form->remove('password');
$form->remove('note');
$form->handleRequest($request);
switch ($formName) {
case 'sizedV2ray':
case 'sizedVip':
case 'unlimitedV2ray':
case 'sizedOcServ':
case 'unlimitedOcServ':
case 'sizedOpen':
case 'unlimitedOpen':
if ($form->isSubmitted() && $form->isValid()) {
$queryArray = $form->getData();
// unset($queryArray['username']);
// unset($queryArray['password']);
$queryArray['size'] = $byteConvert->toByte($queryArray['size'] . 'GB');
$queryArray['active'] = 1;
$targetPlan = $this->em->getRepository(Plan::class)->findOneBy($queryArray);
if (!$targetPlan) {
$this->addFlash('error', 'این بسته در حال حاضر ارائه نمیشود');
return $this->redirectToRoute('app_panel_user_vpn_service_charge', ['id' => $service->getId()]);
}
// TODO:Check User Interest Rate For Price
$buyPrice = $this->dynamicPriceCalculation->calculatePrice($user, $targetPlan);
if ($user->getWallet() >= $buyPrice) {
$serviceData = $form->getData();
$serviceData['clientId'] = $form->get('clientId')->getData();
$this->service->chargeService($service, $targetPlan, $serviceData, $user);
$this->transaction->createTransaction($user, $buyPrice, "تمدید سرویس {$service->getClientId()}",
0
);
$this->addFlash('success', 'سرویس مد نظر با موفقیت تمدید شد');
return $this->redirectToRoute('app_panel_user_vpn_service_index');
} else {
$this->addFlash('error', 'موجودی کیف پول شما کافی نمی باشد');
return $this->redirectToRoute('app_panel_user_vpn_service_charge', ['id' => $service->getId()]);
}
}
break;
default:
// Handle any default case if necessary
break;
}
$forms[$formName] = $form->createView();
}
return $this->render('panel/pages/user/vpn/service/enter.html.twig', [
'sizedVipForm' => $forms['sizedVip'] ?? '',
'sizedV2rayForm' => $forms['sizedV2ray'] ?? '',
'unlimitedV2rayForm' => $forms['unlimitedV2ray'] ?? '',
'sizedOcServForm' => $forms['sizedOcServ'] ?? '',
'unlimitedOcServForm' => $forms['unlimitedOcServ'] ?? '',
'sizedOpenForm' => $forms['sizedOpen'] ?? '',
'unlimitedOpenForm' => $forms['unlimitedOpen'] ?? '',
'charge' => 1
]);
}
#[Route('/edit/{id}', name: 'app_panel_user_vpn_service_edit', methods: ['GET', 'POST'])]
public function edit(Request $request, ByteConvert $byteConvert, ServerRepository $serverRepository, \App\Repository\VPN\OpenVPN\ServerRepository $openServerREpo, \App\Repository\VPN\OcServ\ServerRepository $ocServerRepository, Service $service)
{
/**
* @var User $user
*/
$user = $this->getUser();
$form = $this->createFormBuilder()
->add('username', TextType::class, [
'label' => 'نام کاربری',
'data' => $service->getUsername()
])->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$service->setUsername($form->get('username')->getData());
$this->em->flush();
$this->addFlash('success', 'بروز شد');
return $this->redirectToRoute('app_panel_user_vpn_service_index');
}
return $this->render('panel/pages/user/vpn/service/edit.html.twig', [
'form' => $form->createView()
]);
}
#[Route('/status/{id}', name: 'app_panel_user_vpn_service_status', methods: ['GET', 'POST'])]
public function changeStatus(Service $service)
{
if (!$service->isActive()) {
$this->addFlash('error', 'سرویس به پایان رسیده است نمیتواند وضعیتش تغییر پیدا کند');
return $this->redirectToRoute('app_panel_user_vpn_service_index');
}
$service->setIsEnabled(!$service->isEnabled());
$this->em->persist($service);
$this->em->flush();
return $this->redirectToRoute('app_panel_user_vpn_service_index');
}
#[Route('/rollback/{id}', name: 'app_panel_user_vpn_service_rollback', methods: ['GET', 'POST'])]
public function rollback(Service $service, Request $request)
{
$form = $this->createForm(RollbackType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$service->setActive(0);
$service->setRollbackNote($form->get('reason')->getData());
$this->transaction->createTransaction($service->getOwner(), $service->getTotalPrice(), 1, 'مرجوع سرویس با شناسه : ' . $service->getClientId(), $service, 'rollback', 0);
$this->addFlash('success', 'با موفقیت انجام شد');
return $this->redirectToRoute('app_panel_user_vpn_service_index');
}
return $this->render('panel/pages/user/vpn/service/rollback.html.twig', [
'form' => $form->createView(),
'rollback' => 1
]);
}
#[Route('/get-price-ajax', name: 'app_panel_user_vpn_service_get_price_ajax', methods: ['GET', 'POST'])]
public function getPriceAjax(ByteConvert $byteConvert, Request $request)
{
/**
* @var User $user
*/
$user = $this->getUser();
$queryArray = $request->request->all();
unset($queryArray['country']);
unset($queryArray['password']);
unset($queryArray['username']);
unset($queryArray['price']);
unset($queryArray['_token']);
$queryArray['size'] = $byteConvert->toByte($queryArray['size'] . 'GB');
$queryArray['active'] = 1;
$targetPlan = $this->em->getRepository(Plan::class)->findOneBy($queryArray);
// return $this->json(['res' => $queryArray]);
if (!$targetPlan) {
return $this->json(['message' => 'این بسته در حال حاضر ارائه نمیشود']);
} else {
if ($targetPlan->getServiceType() === 'unlimited') {
$price = $this->dynamicPriceCalculation->calculatePrice($user, $targetPlan);
return $this->json(['message' =>
'با احتساب نمایندگی سطح ' .
$this->dynamicPriceCalculation->getUserLevel($user, $targetPlan)
.
' شما قیمت : ' .
number_format($price) .
' تومان'
]);
} else {
$price = $this->dynamicPriceCalculation->calculatePrice($user, $targetPlan);
return $this->json(['message' =>
'با احتساب نمایندگی سطح ' .
$this->dynamicPriceCalculation->getUserLevel($user, $targetPlan)
.
' شما قیمت از ' .
number_format($targetPlan->getPrice()) . ' تومان' .
' به ' .
number_format($price) .
' تومان' .
' کاهش یافت'
]);
}
}
}
public function countryCodeToFlag($countryCode)
{
// Convert country code to uppercase
$countryCode = strtoupper($countryCode);
// Offset between uppercase ASCII and regional indicator symbols
$offset = 127397;
// Convert each character of the country code to its flag emoji equivalent
$flagEmoji = '';
for ($i = 0; $i < strlen($countryCode); $i++) {
$flagEmoji .= $this->emoji_convert_unicode(ord($countryCode[$i]) + $offset);
}
return $flagEmoji;
}
// Function to convert Unicode code point to emoji character
public function emoji_convert_unicode($unicode)
{
return mb_convert_encoding('&#' . intval($unicode) . ';', 'UTF-8', 'HTML-ENTITIES');
}
}