Google Chat App with a Cloud Run Function – RenderActions and cardsV2 error

I am trying to build a Google Chat App that calls a Cloud Run function as the logic. I am assuming the GCP interfaces must have recently changed/updated because a lot of the guides and troubleshooting do not match the UI elements I am seeing in GCP.

I am getting the below two errors in my Log Explorer when I try to send a simple message to the Chat Bot.

Failed to parse JSON as RenderActions, DataActions or Card.
Failed to parse JSON as RenderActions. Failed with error: Cannot find field: cardsV2 in message google.apps.card.v1.RenderActions
Failed to parse JSON as DataActions. Failed with error: Cannot find field: cardsV2 in message google.apps.card.v1.DataActions
Failed to parse JSON as Card. Failed with error: Cannot find field: cardsV2 in message google.apps.card.v1.Card

and

Can't post a reply. The Chat app didn't respond or its response was invalid. If your Chat app is configured as an add-on, see "Build Google Chat interfaces" (https://developers.google.com/workspace/add-ons/chat/build) in the Google Workspace add-ons documentation. Otherwise, see "Receive and respond to Google Chat events" (https://developers.google.com/chat/api/guides/message-formats) in the Chat API documentation.

Below is my Cloud Function (Node.js).

/**
 * Google Chat Bot Echo function.
 *
 * This function is triggered by an HTTP request from Google Chat.
 * It processes the event payload and responds with a structured card message.
 *
 * @param {object} req The HTTP request object.
 * @param {object} res The HTTP response object.
 */
exports.chatBot = (req, res) => {
  // Check if the request method is POST. Google Chat sends POST requests.
  if (req.method !== 'POST') {
    return res.status(403).send('Forbidden');
  }

  const event = req.body;
  console.log('Received event:', JSON.stringify(event, null, 2));

  let responseMessage;

  // Handle different event types from Google Chat.
  switch (event.type) {
    case 'ADDED_TO_SPACE':
      // This event is triggered when the bot is added to a space or a DM.
      const spaceType = event.space.type;
      if (spaceType === 'DM') {
        responseMessage = `Hi ${event.user.displayName}! Thanks for starting a chat. I'll echo back anything you say.`;
      } else {
        responseMessage = `Thanks for adding me to ${event.space.displayName}! I'm ready to echo messages.`;
      }
      break;
    case 'MESSAGE':
      // This event is triggered when a user sends a message to the bot.
      // event.message.argumentText contains the text sent after the bot's @-mention.
      const userMessage = (event.message.argumentText || '').trim();
      if (userMessage) {
        responseMessage = `You said: "${userMessage}"`;
      } else {
        responseMessage = 'Hello! Please mention me and type a message.';
      }
      break;
    case 'REMOVED_FROM_SPACE':
      // This event is triggered when the bot is removed. No response is needed.
      console.log(`Bot removed from ${event.space.displayName}.`);
      return res.status(200).send();
    default:
      // For any other event type, send a default response.
      responseMessage = 'I received an event I don't know how to handle.';
      break;
  }
  
  // For a Google Workspace Add-on responding to a MESSAGE event,
  // the response must be a `renderActions` object.
  const reply = {
    "renderActions": {
      "action": {
        "navigations": [
          {
            "pushCard": {
              "header": {
                "title": "Echo Bot"
              },
              "sections": [
                {
                  "widgets": [
                    {
                      "textParagraph": {
                        "text": responseMessage
                      }
                    }
                  ]
                }
              ]
            }
          }
        ]
      }
    }
  };

  // Send the JSON response back to Google Chat.
  res.status(200).json(reply);
};

I am fairly new to GCP Google Chat API and Cloud Run Functions, so my apologies if this question seems a bit obvious. But I have been stuck for a while and cannot find a resolution anywhere. Any help would be much appreciate!

Alternative to getSVGForLocalExport in Highcharts 12.4.0?

In the past, we used getSVGForLocalExport() to retrieve svg for multiple charts so we could combine them into one output image (portion of code shown below). It appears getSVGForLocalExport() no longer exists in offline-exporting.js as of 12.3.0. Is there an alternative function that can be used for similar functionality? Thank you.

charts[i].getSVGForLocalExport(options, {}, function() {
        console.log('Failed to get SVG');
     }, function(svg) {
        addSVG(svg);
        // Export next only when this SVG is received
        return exportChart(i + 1);
     });

Three.js – DOF not working with point clouds (THREE.Points)

I’m trying to implement a Depth of Field (DOF) effect in a Three.js scene that includes a point cloud rendered using THREE.Points. I’ve based my implementation on these official examples:

These examples work well for standard 3D meshes like spheres or cubes. However, when I apply the DOF effect to a point cloud, the points remain uniformly blurry, regardless of their depth.

I’ve tried tweaking the focus, aperture, and maxblur values, but they don’t seem to have any visible effect on the point cloud.

const bokehPass = new BokehPass(
  scene,
  camera,
  {
    focus: 1.0,
    aperture: 0.025,
    maxblur: 0.01,
  }
);

I also tested the setup by adding a regular 3D sphere at the same position as the point cloud. The DOF effect works correctly on the sphere, but the point cloud remains unaffected.

How can I get DOF to work correctly?

Add an image to canvas in Javascript? [duplicate]

So I want to do a very simple thing, I think. I want to add a image to a 2d platform game I am making. The image itself is the level and after it is added I planned on adding invisble platforms on top of it to make the game playable. But how do you add the image in the first place?

Image: 8000 x 512 px Languages: Javascript, HTML, CSS

Tried EVERYTHING. I expect at least one method to work

Why I cannot send body with a fetch request when mode is no-cors?

Trying to make a cross-origing fetch request with the no-cors mode I found out it is not possible in this case to send any data to the server as a body:

const url = 'http://cross-origin-example.com/post';
const request = new Request(url, {
  method: 'POST',
  mode: 'no-cors',
  headers: {
    'Content-Type': 'text/plain',
  },
  body: 'boo',
});
fetch(url, request).then((response) => console.log(response));

In Chrome, such a request will not be sent at all throwing the following error:

Uncaught (in promise) TypeError: Failed to execute ‘fetch’ on
‘Window’: If request is made from ReadableStream, mode should
be”same-origin” or “cors”

Firefox make the request reach the server but with the body missing.

I know when using the no-cors mode the JS code gets an opaque response, which effectively conceals the result of fetching. However, on what basis the browsers do not allow attach body in this case? Is it standardized behavior (in fact, I failed to find such a restriction somewhere in the fetch spec) or just a browser extra limitation?

how to have a tick mark on a d3 x-axis for every year rather than every other

I want to have the x-axis show one tick per year, but I’m having trouble. I’m using the code provided on the d3 website. Can anyone advise?

<div id="container"></div>
<script type="module">

// Declare the chart dimensions and margins.
const width = 1140;
const height = 400;
const marginTop = 20;
const marginRight = 20;
const marginBottom = 30;
const marginLeft = 40;

// Declare the x (horizontal position) scale.
const x = d3.scaleUtc()
    .domain([new Date("2007-01-01"), new Date("2023-01-01")])
    .range([marginLeft, width - marginRight]); //shows one tick every other year
x.ticks(d3.utcYear.every(1)); //my code, but it doesn't work. x-axis still shows one tick every other year

// Declare the y (vertical position) scale.
const y = d3.scaleLinear()
    .domain([0, 100])
    .range([height - marginBottom, marginTop]);

// Create the SVG container.
const svg = d3.create("svg")
    .attr("width", width)
    .attr("height", height);

// Add the x-axis.
svg.append("g")
    .attr("transform", `translate(0,${height - marginBottom})`)
    .call(d3.axisBottom(x));


// Add the y-axis.
svg.append("g")
    .attr("transform", `translate(${marginLeft},0)`)
    .call(d3.axisLeft(y));

// Append the SVG element.
container.append(svg.node());

</script>

How to avoid label collision open layers?

I’m using OpenLayers in a vessel tracking map, and I have a custom label layer that renders vessel names.

The problem:
Even with declutter: true, many of the vessel labels overlap, and some disappear because they collide with others. This makes it hard to read vessel names when several vessels are close to each other.

What I’d like:
A “smarter” way of placing labels — e.g., automatically shifting a label to the NE, NW, SE, or SW of the vessel if it collides with another label, so that more of them remain visible. Ideally I want to try a few candidate positions per feature and pick one that doesn’t collide.

Below is a simplified version of my label-layer. I’m providing a few alternative styles but it’s not enough as when zoomed out alot of the labels disappear. Seems like all of the alternative styles need to be overlapping else the same label will appear multiple times.


  private createLabelLayer() {
    const layer = new VectorLayer({
      source: new VectorSource({
        overlaps: true,
      }),
      style: (feature) => {
        const vessel = this.vesselList.get(feature.get('vesselId'))

        const labelText = feature.get('text')
        style.getText()?.setText(labelText)

        const { dimensions } = vessel || {}
        let offY = 0
        let offX = 0
        if (dimensions) {
          style.getText()?.setOffsetY(offY)
          style.getText()?.setOffsetX(offX)
        }

        const styles = getLabelStyles(style, zIndex)

        return styles
      },
      declutter: true,
      zIndex: this.zIndexes.labels,
      maxResolution: this.thresholds.webglPoints,
    })
    layer.set('type', 'labelLayer')
    return layer
  }

const baselines: CanvasTextBaseline[] = ['middle', 'top', 'bottom']
const aligns: CanvasTextAlign[] = ['center', 'left', 'right']

const getLabelStyles = (baseStyle: Style, zIndex: number) => {
  const out: Style[] = [baseStyle]

  for (const bl of baselines) {
    for (const al of aligns) {
      const style = baseStyle.clone()

      const text = style.getText()

      text?.setTextBaseline(bl)
      text?.setTextAlign(al)
      text?.setOverflow(true)
      style.setZIndex(zIndex)

      out.push(style)
    }
  }
  return out
}

Is there a built-in way in OpenLayers to try alternative label positions, or is declutter: true the only out-of-the-box option?

Forge Viewer offline in Vue/Vite (iOS WebView) – call function across files without import/window/globalThis

We are building an offline Forge Viewer project using Vue + Vite, which will later be wrapped in an iOS app (Capacitor).

In offline mode, we need to serve model files and translations from a local cache. Normally, we’d use Cache Storage API and Service Worker, but those don’t work properly inside the iOS WebView environment.

So instead, we implemented a custom CacheService that can return cached model files (JSON, SVF, resources). Example:

// CacheService.js
class CacheService {
  async getModelFile(url) {
    // returns cached file content
  }
}

const cacheService = new CacheService();
export default cacheService;

In online mode, Forge Viewer fetches its resources normally.
In offline mode, we want to intercept Forge Viewer’s internal _rawGet calls and redirect them to cacheService.getModelFile(url) if available.

The problem:

  • Forge Viewer scripts are minified modules and run in a worker-like environment.

  • We cannot use:

    • import or importScripts (because it breaks inside Forge viewer worker logic)
    • window.cacheService (not defined in iOS WebView worker context)
    • globalThis.cacheService (also not reliable in this case)
    • Any global variable injection

So the question is:

How can we expose a function from one file and call it in another, in this environment, without relying on import, importScripts, window, or globalThis?

We basically need a way for Forge Viewer’s offline request code to call back into our own cacheService.getModelFile() implementation when a network request fails.

Any ideas on how to structure this or inject such a function in a Vite + Vue + Forge Viewer offline setup?

A way to expose a function (singleton) globally so that Forge Viewer’s internal request code can call it, without using import, window, globalThis, or service workers.

How to avoid duplicating unchanged endpoints when versioning a REST API? [closed]

I need to introduce a breaking change to one endpoint in a REST API. The backend currently versions by duplicating the entire app per version. Example layout:

/rest
    /v1
        /controllers
        /models
    /v2
        /controllers
        /models
    /v3
        /controllers
        /models

Not all endpoints change with each version. When a bug is fixed in v2, the same fix must be applied manually in v3. This duplication is error-prone.

What project structure or pattern allows:

  1. Shared implementation for unchanged endpoints across versions.

  2. Isolation for versioned endpoints when breaking changes are required.

Constraints:

  • Language/framework agnostic.

  • Folder layout or structural examples are acceptable.

  • I want to know how to implement this technically, not whether one approach is “better.”

WordPress Unsafe SQL calls

I create one custom plugin and submit for review to wordpress.org. But the give me test log they says Unsafe SQL calls

`includes/databases/class-stepup-user-crud.php:313 $sql_orders = $wpdb->prepare(
"
SELECT p.*
FROM {$db->tb_posts} p
INNER JOIN {$db->tb_postmeta} pm ON p.ID = pm.post_id AND meta_key = %s AND (meta_value = %d OR meta_value like '%s')
",
'_user_id',
$user_id,
$user_id_str
);
includes/databases/class-stepup-user-crud.php:338 $sql = $sql_orders /* . ' UNION ' . $sql_guest_orders */ . $sql_rest;
includes/databases/class-stepup-user-crud.php:341 $order_posts = $db->wpdb->get_results($sql);
# There is a call to a wpdb::prepare() function, that's correct.
# You cannot add variables like "$db->tb_posts" directly to the SQL query.
# Using wpdb::prepare($query, $args) you will need to include placeholders for each variable within the query and include the variables in the second parameter.
# The SQL query needs to be included in a wpdb::prepare($query, $args) function.`

I added $db->tb_posts in global class.

they says do not use variable like these

You cannot add variables like "$db->tb_posts" directly to the SQL query

Please help me.

I read these content
https://www.wordfence.com/blog/2025/08/how-to-find-sql-injection-vulnerabilities-in-wordpress-plugins-and-themes/

some document says use $wpdb::prapare() and I already used it but not found correct solution.

These is my query

    $sql_orders = $wpdb->prepare( "SELECT p.* FROM {$db->tb_posts} p INNER JOIN {$db->tb_postmeta} pm ON p.ID = pm.post_id AND meta_key = %s AND (meta_value = %d OR meta_value like '%s')", '_user_id',$user_id,$user_id_str); 
$sql = $sql_orders . $sql_rest; 
$order_posts = $db->wpdb->get_results($sql); 

Custom WordPress login modal with AJAX – logging in works but then any attempt to access /wp-admin causes a redirect to ‘SITE_URL/home’

I have created a custom login modal for my wordpress site. In seems to be working on the surface, as in it logs in correctly, the admin bar appears at the top on page refresh and I’m able to access front-end content that is only available to admin accounts when I log in as an admin.

However, when I try to access any page in the dashboard (/wp-admin), the page hangs for a
while and then redirects me to the homepage with ‘/home’ added to the URL.

I built the functions.php action that receives the login data from the front-end and calls wp_signon() as I saw in the documentation. So I’m a bit confused why it is behaving as it is. Am I missing something from the login process?

Here is the action:

function ajax_custom_login() {
    $remember = isset($_POST['remember']) && $_POST['remember'] === 'on';

    $info = array();
    $info['user_login']    = sanitize_text_field($_POST['username']);
    $info['user_password'] = sanitize_text_field($_POST['password']);
    $info['remember']      = $remember;

    $user = wp_signon($info, false);

    if (is_wp_error($user)) {
        wp_send_json_error(array('message' => $user->get_error_message()));
    } else {
        wp_send_json_success(array('message' => 'Login successful, redirecting...'));
    }
}

I am using Wordfence and require administrators to use 2FA (not normal users) so I’m assuming this might be part of the problem. However, I’ve tried logging into the administrator account using the /wp-login.php page and told WordFence to “Remember for 30 days”.

Edit: Potentially ignore the Wordfence part below this – I have just tried the login process with my custom login form, after deactivating Wordfence, and the redirect is still happening. So it doesn’t seem like that is the problem.

If I do this, then log out and then log in with the custom login form, I thought it would let me log in because Wordfence is remembering the login for 30 days. It seems like it might be partially doing this because I’m able to get a success response back from wp_signon() and the admin bar appears on refresh, but I’m wondering if Wordfence is causing the ‘SITE_URL/home’ redirect? Is this a known problem? Am I missing something else in the login process?

Any advice would be greatly appreciated.

Is there a way to make my tabs appear 4 in a row for large screens, 3 in a row for medium screens, and stack atop each other for small screens?

I am using Tailwind CSS in my PHP/HTML project, so the only solution I’m looking for is tailwind. I got the tabs to sit side by side, but unfortunately, when I test on small screens, they still sit side by side, and appear horribly squished and out of screen. Which is why I want them to be stacked atop each other on small screens. Also, I haven’t been able to get the tabs to display in rows of 4s for large screens but rows of 3s for medium screens. my code:

<div class="flex flex-wrap justify-center gap-4 mt-8 px-4">
    <?php
    if (isLoggedIn()) {
        $links = [
            ['name' => 'Home', 'href' => '/', 'icon' => 'home'],
            ['name' => 'Inspections', 'href' => '/inspections', 'icon' => 'clipboard'],
            ['name' => 'Questions', 'href' => '/questions', 'icon' => 'question-mark'],
            ['name' => 'Inspectors', 'href' => '/inspectors', 'icon' => 'user-plus'],
            ['name' => 'Cover Pages', 'href' => '/covers', 'icon' => 'document-text'],
            ['name' => 'Profile', 'href' => '/profile', 'icon' => 'user'],
            ['name' => 'Contact', 'href' => '/contact', 'icon' => 'users'],
        ];
    }

    foreach ($links as $link): ?>
        <a href="<?= BASE_PATH . $link['href'] ?>" class="flex flex-col items-center justify-center bg-gray-100 dark:bg-gray-800 rounded-lg shadow hover:bg-gray-200 dark:hover:bg-gray-700 transition cursor-pointer" style="width:140px; height:140px;">
            <?php switch ($link['icon']) {
                case 'home':
                    echo '<svg xmlns="http://www.w3.org/2000/svg" class="w-7 h-7 text-blue-600 dark:text-white mb-2" fill="currentColor" viewBox="0 0 24 24">
                        <path d="M3 9.75L12 3l9 6.75V21a.75.75 0 01-.75.75H3.75A.75.75 0 013 21V9.75z" />
                    </svg>';
                    break;
                case 'clipboard':
                    echo '<svg xmlns="http://www.w3.org/2000/svg" class="w-7 h-7 text-blue-600 dark:text-white mb-2" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
                        <path stroke-linecap="round" stroke-linejoin="round" d="M15.666 3.888A2.25 2.25 0 0 0 13.5 2.25h-3c-1.03 0-1.9.693-2.166 1.638m7.332 0c.055.194.084.4.084.612v0a.75.75 0 0 1-.75.75H9a.75.75 0 0 1-.75-.75v0c0-.212.03-.418.084-.612m7.332 0c.646.049 1.288.11 1.927.184 1.1.128 1.907 1.077 1.907 2.185V19.5a2.25 2.25 0 0 1-2.25 2.25H6.75A2.25 2.25 0 0 1 4.5 19.5V6.257c0-1.108.806-2.057 1.907-2.185a48.208 48.208 0 0 1 1.927-.184" />
                    </svg>';
                    break;
                case 'question-mark':
                    echo '<svg xmlns="http://www.w3.org/2000/svg" class="w-7 h-7 text-blue-600 dark:text-white mb-2" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
                        <path stroke-linecap="round" stroke-linejoin="round" d="M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 5.25h.008v.008H12v-.008Z" />
                    </svg>';
                    break;
                case 'user-plus':
                    echo '<svg xmlns="http://www.w3.org/2000/svg" class="w-7 h-7 text-blue-600 dark:text-white mb-2" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
                        <path stroke-linecap="round" stroke-linejoin="round" d="M18 7.5v3m0 0v3m0-3h3m-3 0h-3m-2.25-4.125a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0ZM3 19.235v-.11a6.375 6.375 0 0 1 12.75 0v.109A12.318 12.318 0 0 1 9.374 21c-2.331 0-4.512-.645-6.374-1.766Z" />
                    </svg>';
                    break;
                case 'document-text':
                    echo '<svg xmlns="http://www.w3.org/2000/svg" class="w-7 h-7 text-blue-600 dark:text-white mb-2" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
                        <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z" />
                    </svg>';
                    break;
                case 'user':
                    echo '<svg xmlns="http://www.w3.org/2000/svg" class="w-7 h-7 text-blue-600 dark:text-white mb-2" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
                        <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" />
                    </svg>';
                    break;
                case 'users':
                    echo '<svg xmlns="http://www.w3.org/2000/svg" class="w-7 h-7 text-blue-600 dark:text-white mb-2" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
                        <path stroke-linecap="round" stroke-linejoin="round" d="M17.25 6.75a3 3 0 11-6 0 3 3 0 016 0zM6.75 6.75a3 3 0 116 0 3 3 0 01-6 0zM3 21a6 6 0 0112 0M9 21a6 6 0 0112 0" />
                    </svg>';
                    break;
            } ?>
            <span class="text-sm font-medium text-gray-700 dark:text-gray-200 mb-2"><?= $link['name'] ?></span>
        </a>
    <?php endforeach; ?>
</div>

I tried updating the grid container to this:

<div class="grid gap-4 mt-8 px-4 max-w-screen-lg mx-auto grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 auto-cols-max justify-items-center">

and the tab anchors to this:

<a href="<?= BASE_PATH . $link['href'] ?>" class="h-[140px] flex flex-col items-center justify-center bg-gray-100 dark:bg-gray-800 rounded-lg shadow hover:bg-gray-200 dark:hover:bg-gray-700 transition cursor-pointer">

which made the tabs stack on small screens exactly as I wanted; however, the same also is happening on large screens and medium screens, which is not the effect I intended.

In PHP, should a child class redeclare constructor dependencies if the parent constructor already defines them, or can it omit them entirely?

So I’m kinda stuck wrapping my head around this whole parent-child dependency thing. My assumption was, once you declare all the dependencies in the parent (BaseController), the child (like IndexController) wouldn’t need to declare them again in its own constructor; it could just rely on parent::__construct(). Tried removing the four dependencies from IndexController, but got hit with an error. Basically, you still gotta re-declare those four deps in the child’s constructor so they can be passed up to parent::__construct(). At least that’s what the AI told me. Lastly, are those use statements really necessary to be in every file?

BaseController.php

   <?php

use AppModelsSiteSettings;
use AppServices{
    AuthService,
    LoggerService,
    MessageService
};

class BaseController
{
    public function __construct(
        protected SiteSettings $siteSettings,
        protected AuthService $authService,
        protected LoggerService $loggerService,
        protected MessageService $messageService
    ) {}
} 

IndexController.php

<?php

use AppModelsSiteSettings;
use AppServices{
    AuthService,
    LoggerService,
    MessageService
};

class IndexController extends BaseController
{
    public function __construct(
        SiteSettings $site_settings,
        AuthService $auth_service,
        LoggerService $logger_service,
        MessageService $message_service,
        private ServersRepository $serversRepository,
        private ServerFilter $serverFilter,
        private CategoriesRepository $categoriesRepository,
        private LanguagesRepository $languagesRepository
    ) {
        parent::__construct(
            $site_settings,
            $auth_service,
            $logger_service,
            $message_service
        );
    }
$this->messageService->get('MSG_LOGIN_SUCCESS');
} 

Container.php

<?php

use AppModelsSiteSettings;
use AppServices{
AuthService,
LoggerService,
MessageService
};

class Container
{
public function __construct()
{

        $this->factories[IndexController::class] = function (Container $c) {
            return new IndexController(
                $c->get(SiteSettings::class),
                $c->get(AuthService::class),
                $c->get(LoggerService::class),
                $c->get(MessageService::class),
                $c->get(ServersRepository::class),
                $c->get(ServerFilter::class),
                $c->get(CategoriesRepository::class),
                $c->get(LanguagesRepository::class)
            );
        };
}