'%allowed_language%'], defaults: ['_locale'=>'en'] )] public function index(Request $request, AuthorizationCheckerInterface $authorizationChecker, ConnectMastodonAccountFlow $flow, Mastodon_api $mastodon_api, TranslatorInterface $translator, EventDispatcherInterface $eventDispatcher): RedirectResponse|Response { if ($authorizationChecker->isGranted('IS_AUTHENTICATED_FULLY')) { $local = $request->getSession()->get('_locale'); return $this->redirect($this->generateUrl('schedule', ['_locale' => $local])); } $client = new Client(); $flow->bind($client); $form = $flow->createForm(); $urlToMastodon = null; $client_id = null; $client_secret = null; if ($flow->isValid($form)) { if ($flow->getCurrentStep() == 1) { $host = $client->getHost(); $result = $mastodon_api->getInstanceNodeInfo($host); //We currently only support Mastodon accounts if ($result != "MASTODON" && $result != "PLEROMA") { $form->get('host')->addError(new FormError($translator->trans('error.instance.mastodon_only', [], 'fediplan', 'en'))); } else { $mastodon_api->set_url("https://" . $host); $mastodon_api->set_scopes([]); $createApp = $mastodon_api->create_app("FediPlan", [], '', "https://plan.fedilab.app"); if (isset($createApp['error'])) { $form->get('host')->addError(new FormError($translator->trans('error.instance.mastodon_client_id', [], 'fediplan', 'en'))); } else { // form for the next step $mastodon_api->set_client($createApp['response']['client_id'], $createApp['response']['client_secret']); $urlToMastodon = $mastodon_api->getAuthorizationUrl(); $flow->saveCurrentStepData($form); $client_id = $createApp['response']['client_id']; $client_secret = $createApp['response']['client_secret']; $flow->nextStep(); $form = $flow->createForm(); } } } else if ($flow->getCurrentStep() == 2) { $host = $client->getHost(); $code = $client->getCode(); $mastodon_api->set_url("https://" . $client->getHost()); $mastodon_api->set_scopes([]); $mastodon_api->set_client($client->getClientId(), $client->getClientSecret()); $reply = $mastodon_api->loginAuthorization($code); if (isset($reply['error'])) { $form->get('code')->addError(new FormError($translator->trans('error.instance.mastodon_token', [], 'fediplan', 'en'))); } else { $access_token = $reply['response']['access_token']; $token_type = $reply['response']['token_type']; $mastodon_api->set_url("https://" . $client->getHost()); $mastodon_api->set_token($access_token, $token_type); $accountReply = $mastodon_api->accounts_verify_credentials(); if (isset($accountReply['error'])) { $form->get('code')->addError(new FormError($translator->trans('error.instance.mastodon_account', [], 'fediplan', 'en'))); } else { $account = $mastodon_api->getSingleAccount($accountReply['response']); $instanceReply = $mastodon_api->get_instance(); $instance = $mastodon_api->getInstanceConfiguration($instanceReply['response']); $session = $request->getSession(); $session->set("instance",$instance); $account->setInstance($host); $account->setToken($token_type . " " . $access_token); $token = new UsernamePasswordToken($account, 'main', array('ROLE_USER')); try { $this->container->get('security.token_storage')->setToken($token); $event = new InteractiveLoginEvent($request, $token); $eventDispatcher->dispatch($event, "security.interactive_login"); return $this->redirectToRoute('schedule'); } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { $form->get('code')->addError(new FormError($translator->trans('error.instance.mastodon_account', [], 'fediplan', 'en'))); } } } } } return $this->render('fediplan/index.html.twig', [ 'form' => $form->createView(), 'flow' => $flow, 'urlToMastodon' => $urlToMastodon, 'client_id' => $client_id, 'client_secret' => $client_secret, ]); } #[Route( '/{_locale}/schedule', name: 'schedule', requirements: ['_locale' => '%allowed_language%'], defaults: ['_locale'=>'en'] )] public function schedule(Request $request, Mastodon_api $mastodon_api, TranslatorInterface $translator): Response { $compose = new Compose(); $pollOption1 = new PollOption(); $pollOption1->setTitle(""); $options = $compose->getPollOptions(); $options[] = $pollOption1; $pollOption2 = new PollOption(); $pollOption2->setTitle(""); $options[] = $pollOption2; $compose->setPollOptions($options); $user = $this->getUser(); $form = $this->createForm(ComposeType::class, $compose, ['user' => $user]); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { /** @var $data Compose */ $data = $form->getData(); $mastodon_api->set_url("https://" . $user->getInstance()); $token = explode(" ", $user->getToken())[1]; $type = explode(" ", $user->getToken())[0]; $mastodon_api->set_token($token, $type); $params = []; //Update media description and store their id foreach ($_POST as $key => $value) { if ($key != "compose") { if (str_contains($key, 'media_id_')) { $mediaId = $value; $description = $_POST['media_description_' . $mediaId]; //update description if needed if ($description != null && trim($description) != "") { $mastodon_api->update_media($mediaId, ['description' => $description]); } $params['media_ids'][] = $mediaId; } } } //Schedule status if ($data->getContentWarning()) { $params['spoiler_text'] = $data->getContentWarning(); } if ($data->getContent()) { $params['status'] = $data->getContent(); } if ($data->getVisibility()) { $params['visibility'] = $data->getVisibility(); } $params['sensitive'] = ($data->getSensitive() == null || !$data->getSensitive()) ? false : true; if($data->getAttachPoll() > 0) { $pollOptions = $data->getPollOptions(); } else{ $pollOptions = array(); } $pollExpiresAt = $data->getPollExpiresAt(); $isPollMultiple = $data->isPollMultiple(); if (count($pollOptions) > 0) { $count_correct_values = 0; foreach ($pollOptions as $po) { /** @var $po PollOption */ if ($po->getTitle() != null && strlen(trim($po->getTitle())) > 0) { $count_correct_values++; } } if ($count_correct_values > 1) { $params['poll']['options'] = []; foreach ($pollOptions as $po) { /** @var $po PollOption */ if ($po->getTitle() != null && strlen(trim($po->getTitle())) > 0) { $params['poll']['options'][] = trim($po->getTitle()); } } $params['poll']['expires_in'] = $pollExpiresAt; $params['poll']['multiple'] = $isPollMultiple; } } try { $date = new DateTime($data->getScheduledAt()->format("Y-m-d H:i"), new DateTimeZone($data->getTimeZone())); $date->setTimezone(new DateTimeZone("UTC")); $params['scheduled_at'] = $date->format(DateTime::ISO8601); } catch (Exception $e) { } $response = $mastodon_api->post_statuses($params); $session = $request->getSession(); if (isset($response['error'])) { $session->getFlashBag()->add( 'Error', $response['error_message'] ); } else { unset($compose); unset($form); $compose = new Compose(); $pollOption1 = new PollOption(); $pollOption1->setTitle(""); $options = $compose->getPollOptions(); $options[] = $pollOption1; $pollOption2 = new PollOption(); $pollOption2->setTitle(""); $options[] = $pollOption2; $compose->setPollOptions($options); $session->getFlashBag()->add( 'Success', $translator->trans('common.schedule_success', [], 'fediplan', 'en') ); $form = $this->createForm(ComposeType::class, $compose, ['user' => $this->getUser()]); } } /** @var $user MastodonAccount */ $user = $this->getUser(); return $this->render("fediplan/schedule.html.twig", [ 'form' => $form->createView(), 'instance' => $user->getInstance(), 'token' => $user->getToken(), ]); } #[Route( '/{_locale}/scheduled', name: 'scheduled', requirements: ['_locale' => '%allowed_language%'], defaults: ['_locale'=>'en'] )] public function scheduled(): Response { return $this->render("fediplan/scheduled.html.twig"); } #[Route( '/{_locale}/scheduled/messages/{max_id}', name: 'load_more', options: ['expose' => true] )] public function loadMoreAction(Mastodon_api $mastodon_api, string $max_id = null): JsonResponse { /** @var $user MastodonAccount */ $user = $this->getUser(); $mastodon_api->set_url("https://" . $user->getInstance()); $token = explode(" ", $user->getToken())[1]; $type = explode(" ", $user->getToken())[0]; $mastodon_api->set_token($token, $type); $params = []; if ($max_id != null) { $params['max_id'] = $max_id; } $scheduled_reply = $mastodon_api->get_scheduled($params); $statuses = $mastodon_api->getScheduledStatuses($scheduled_reply['response'], $user); $data['max_id'] = $scheduled_reply['max_id']; $data['html'] = $this->renderView('fediplan/Ajax/layout.html.twig', ['statuses' => $statuses]); return new JsonResponse($data); } #[Route( '/{_locale}/scheduled/delete/messages/{id}', name: 'delete_message', requirements: ['_locale' => '%allowed_language%'], options: ['expose' => true], defaults: ['_locale'=>'en'], methods: ['POST'] )] public function deleteMessage(Mastodon_api $mastodon_api, string $id = null): JsonResponse { $user = $this->getUser(); $mastodon_api->set_url("https://" . $user->getInstance()); $token = explode(" ", $user->getToken())[1]; $type = explode(" ", $user->getToken())[0]; $mastodon_api->set_token($token, $type); $response = $mastodon_api->delete_scheduled($id); return new JsonResponse($response); } #[Route( '/{_locale}/about', name: 'about', requirements: ['_locale' => '%allowed_language%'], defaults: ['_locale'=>'en'] )] public function about(): Response { return $this->render("fediplan/about.html.twig"); } #[Route( '/logout', name: 'logout' )] public function logout(): Response { return $this->render("fediplan/index.html.twig"); } }