I noticed that these bots can’t seem to mention each other properly
I’m currently experimenting with a few AI bots on my board — like [mention]HelperBot[/mention], [mention]ForumGuide[/mention], and [mention]QuickFixer[/mention]. Everything works great, but I noticed that these bots can’t seem to mention each other properly. Even when using the [mention]Name[/mention] BBCode format in their replies, it doesn't trigger a proper mention or notification like it does for human users.
Is there any way to enable or support bot-to-bot mentions within the extension? Or perhaps a workaround you’d recommend?
Thanks again for all the work you’ve put into AILabs — it’s truly top-tier.
You're correct I was playing with a similar concept where one bot can communicate with another via @mention. Unfortunately this is not going to work and some code changes will be required. I did not look too far into that.
Thank you for your reply.
My goal was to create conversations between bots and have them respond randomly to forum posts.
Unfortunately, it seems this isn’t possible.
I spent an entire day experimenting with the event listener from the Simple Mentions extension, trying to find a workaround. I attempted to hook into the event like this:
'core.modify_text_for_storage_before' => 'convert_mentions',
Using the following code:
/**
-
Convert @bot-style mentions into BBCode mentions. */ public function convert_mentions($event) { if (isset($event['text'])) { $text = $event['text'];
$text = preg_replace('/@EVE\b/', '[mention]EVE[/mention]', $text); $text = preg_replace('/@Donna\b/', '[mention]Donna[/mention]', $text); $text = preg_replace('/@Theresa\b/', '[mention]Theresa[/mention]', $text); $event['text'] = $text;} }
However, even when AILab correctly inserts a [mention]...[/mention] tag, it never actually registers as a proper mention in phpBB.
I tried several approaches, but no matter what, phpBB always stores the output as plain text. So far, I haven’t found a way around this.
It's been a while since I looked at that code. If I recall correctly the problem was that the event has to be triggered by HTTP GET/POST. When you modify post and/or insert a mention/new post within the event handler it will not trigger the correct sequence of events to handle that action. There's probably a way to trigger event processing for inserted/updated posts but it was a bit too much for me at the time to process so I just gave up. Not sure if that will help you.
Actually yes — thank you, that really help,
So from what I understand, the issue is that when the code inserts posts directly, it bypasses phpBB’s normal submission flow. That means the mention system doesn’t get triggered at all, because it relies on a proper HTTP request to fire the full chain of events.
I’m now thinking about a few possible solutions. One idea is to try forcing a re-parse of the post after it’s been inserted — maybe by calling generate_text_for_storage() manually and enabling flags like allow_bbcode, allow_smilies, etc.
Another option I’m considering is switching to use phpBB’s native submit_post() function instead of inserting into the database directly. That should take care of everything — mentions, notifications, BBCode parsing, and cache updates — since it follows the full internal process.
If neither of those works cleanly, I might even try simulating a POST request internally using something like request->enable_super_globals() to see if that kicks the system into action.
Thanks again for pointing me in the right direction this gives me a clearer path to test next
This is how far i get unfortunately mention is still stored as a text and never get praised, I tried everything. First I just added [mention]Donna[/mention] — didn’t work. Then I switched to using submit_post() with all the right BBCode flags — still no praise. After digging into the mention extension, I realized it needs a real user session, so I injected the bot’s identity into $user->data. The posts got submitted properly, but mentions still weren’t praised.
Turns out the extension expects the mention to come from the JS dropdown — that’s how it links the username to a user ID. Without that, it won’t convert it. So I’m close, but the last missing step is manually converting [mention]Name[/mention] to [MENTION uid=X]Name[/MENTION]. That should finally make it work.
If you have any tip please share, thank you in advance.
<?php
/**
*
* AI Labs extension
*
* @copyright (c) 2023, privet.fun, https://privet.fun
* @license GNU General Public License, version 2 (GPL-2.0)
*
*/
namespace privet\ailabs\controller;
use privet\ailabs\includes\GenericCurl;
use Symfony\Component\HttpFoundation\JsonResponse;
use privet\ailabs\includes\AIController;
use privet\ailabs\includes\resultParse;
class chatgpt extends AIController
{
protected $max_tokens = 4096;
protected $settings_override;
protected function process()
{
global $phpbb_root_path, $phpEx, $user, $auth, $db, $config;
global $request, $phpbb_container;
$this->job['status'] = 'exec';
$this->job_update([
'status' => $this->job['status'],
'log' => json_encode($this->log)
]);
$this->post_update($this->job);
if (!empty($this->cfg->max_tokens)) {
$this->max_tokens = (int)$this->cfg->max_tokens;
}
$prefix_tokens = empty($this->cfg->prefix_tokens) ? 0 : $this->cfg->prefix_tokens;
$api_key = $this->cfg->api_key;
$this->cfg->api_key = null;
$api = new GenericCurl($api_key);
$api->debug = $this->debug;
$this->job['status'] = 'fail';
$response = $this->language->lang('AILABS_ERROR_CHECK_LOGS');
$api_response = null;
$info = null;
$content = [];
$post_first_taken = null;
$post_first_discarded = null;
$history = $this->retrieve_history($this->max_tokens);
$history_count = 0;
$history_tokens = 0;
$this->log['history'] = $history;
$this->log_flush();
if (!empty($history)) {
foreach ($history as $key => $value) {
if ($value['discard']) {
$post_first_discarded = $value['postid'];
break;
}
$history_count++;
$post_first_taken = $value['postid'];
$history_tokens += ($value['request_tokens'] + $value['response_tokens']);
array_unshift(
$content,
['role' => 'user', 'content' => $value['request']],
['role' => 'assistant', 'content' => $value['response']]
);
}
}
$request_text = trim($this->job['request']);
$configuration = ['temperature' => (float)$this->cfg->temperature];
if ($this->extract_numeric_settings($request_text, ['temperature' => 'temperature'], $configuration, $this->settings_override)) {
$this->log['settings_override'] = $this->settings_override;
}
$content[] = ['role' => 'user', 'content' => $request_text];
if (!empty($this->cfg->prefix)) {
array_unshift($content, ['role' => 'system', 'content' => $this->cfg->prefix]);
}
$request_json = [
'model' => $this->cfg->model,
'messages' => $content,
'temperature' => (float)$configuration["temperature"],
'frequency_penalty' => (float)$this->cfg->frequency_penalty,
'presence_penalty' => (float)$this->cfg->presence_penalty,
];
$this->log['request.json'] = $request_json;
$this->log_flush();
$request_tokens = 0;
$response_tokens = 0;
try {
$api_result = $api->sendRequest($this->cfg->url_chat, 'POST', $request_json);
$json = json_decode($api_result);
$this->log['response'] = $json;
$this->log['response.codes'] = $api->responseCodes;
$this->log_flush();
if (!empty($json->object) && !empty($json->choices) && strpos($json->object, 'chat.completion') !== false && in_array(200, $api->responseCodes)) {
$this->job['status'] = 'ok';
$api_response = $json->choices[0]->message->content;
$response = $api_response;
$request_tokens = $json->usage->prompt_tokens;
$response_tokens = $json->usage->completion_tokens;
if ($history_tokens > 0 || $prefix_tokens > 0) {
$this->log['request.tokens.raw'] = $request_tokens;
$request_tokens = $request_tokens - $history_tokens - $prefix_tokens;
$this->log['request.tokens.adjusted'] = $request_tokens;
}
}
} catch (\Exception $e) {
$this->log['exception'] = $e->getMessage();
$this->log_flush();
}
$this->log['finish'] = date('Y-m-d H:i:s');
if ($history_count > 0) {
$viewtopic = "{$this->root_path}viewtopic.{$this->php_ext}";
$discarded = '';
if ($post_first_discarded != null) {
$discarded = $this->language->lang('AILABS_POSTS_DISCARDED', $viewtopic, $post_first_discarded);
}
$total_posts_count = $history_count * 2 + 2;
$total_tokens_used_count = $history_tokens + $request_tokens + $response_tokens;
$info = $this->language->lang(
'AILABS_DISCARDED_INFO',
$viewtopic,
$post_first_taken,
$total_posts_count,
$discarded,
$total_tokens_used_count,
$this->max_tokens
);
}
$resultParse = new resultParse();
$resultParse->message = $response;
$resultParse->info = $info;
$resultParse->settings = empty($this->settings_override) ? $this->settings_override : $this->language->lang('AILABS_SETTINGS_OVERRIDE', $this->settings_override);
$final_response = $this->replace_vars($this->job, $resultParse);
// Submit post using phpBB's native submit_post() to trigger BBCode parsing + mentions
include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx);
$data = [
'forum_id' => (int)$this->job['forum_id'],
'topic_id' => (int)$this->job['topic_id'],
'poster_id' => (int)$this->job['poster_id'],
'icon_id' => false,
'enable_bbcode' => true,
'enable_smilies'=> true,
'enable_urls' => true,
'enable_sig' => true,
'message' => $final_response,
'message_md5' => md5($final_response),
'bbcode_bitfield' => '',
'bbcode_uid' => '',
'post_edit_locked' => 0,
'topic_title' => '',
'notify_set' => false,
'notify' => false,
'post_time' => time(),
'forum_name' => '',
'enable_indexing' => true,
];
$poll = $uid = $bitfield = $options = '';
generate_text_for_storage($data['message'], $uid, $bitfield, $options, true, true, true);
$data['bbcode_uid'] = $uid;
$data['bbcode_bitfield'] = $bitfield;
$post_id = submit_post('reply', $data['topic_title'], '', POST_NORMAL, $poll, $data);
$this->job['response_post_id'] = $post_id;
$this->job['response_time'] = time();
$this->job_update([
'status' => $this->job['status'],
'attempts' => $this->job['attempts'] + 1,
'response_time' => $this->job['response_time'],
'response' => utf8_encode_ucr($api_response),
'request_tokens' => $request_tokens,
'response_post_id' => $this->job['response_post_id'],
'response_tokens' => $response_tokens,
'log' => json_encode($this->log)
]);
$this->post_update($this->job);
return new JsonResponse($this->log);
}
}