This commit is contained in:
privet.fun 2023-06-04 14:05:48 -07:00
parent 076310e100
commit c675a9537c
21 changed files with 306 additions and 118 deletions

View file

@ -1,4 +1,4 @@
# AI Labs v 1.0.3 RC # AI Labs v 1.0.4 RC
##### [Changelog](#changelog_link) ##### [Changelog](#changelog_link)
Incorporate AI into your phpBB board and get ready for an exciting experience. Incorporate AI into your phpBB board and get ready for an exciting experience.
@ -41,7 +41,7 @@ Go to `ACP` > `Customise` > `Manage extensions` and enable the `AI Labs` extensi
Finally go to `ACP` > `Extensions` > `AI Labs` > `Settings` and add desired AI configurations: Finally go to `ACP` > `Extensions` > `AI Labs` > `Settings` and add desired AI configurations:
![Attachment settings](../privet/ailabs/docs/ailabs_settings.png) ![Attachment settings](../privet/ailabs/docs/ailabs_settings.png)
## ChatGPT basic setup ## ChatGPT setup
* You will need OpenAI account, sign up at https://platform.openai.com/. * You will need OpenAI account, sign up at https://platform.openai.com/.
To obtain API key go to https://platform.openai.com/account/api-keys, click on `Create new secret key`, copy and save in a safe place generated API key. To obtain API key go to https://platform.openai.com/account/api-keys, click on `Create new secret key`, copy and save in a safe place generated API key.
@ -105,12 +105,29 @@ Refer to https://platform.openai.com/docs/api-reference/images/create to learn m
* Refer to https://api.stability.ai/docs#tag/v1generation/operation/textToImage to learn more about configuration JSON parameters. * Refer to https://api.stability.ai/docs#tag/v1generation/operation/textToImage to learn more about configuration JSON parameters.
## Troubleshooting
AI Labs extension maintains internal logs, you should have admin or moderator rights to see log icon:
![Attachment settings](../privet/ailabs/docs/debugging_post_icon.png)
You can see entire AI communication history in the log:
![Attachment settings](../privet/ailabs/docs/debugging_log.png)
If Log entry is empty it ususally means that `/ailabs/*` routes blocked by one of phpBB extensions (eg <a href="https://www.phpbb.com/customise/db/extension/login_required">Login Required</a>) and you will need to add `/ailabs/*` to extension whitelist.
You can examine Log `response` (JSON) to see details for AI response.
Please feel free to post your quesions or concerns at https://github.com/privet-fun/phpbb_ailabs/issues.
## Support and suggestions ## Support and suggestions
This extension is currently being actively developed. For communication, please use https://github.com/privet-fun/phpbb_ailabs/issues. This extension is currently being actively developed. For communication, please use https://github.com/privet-fun/phpbb_ailabs/issues.
## <a name="changelog_link"></a>Changelog ## <a name="changelog_link"></a>Changelog
* 1.0.4 June 4, 2023
- Troubleshooting section added
- Added cofiguration for reply in topics
- Fixed links generation for cases where cookies disabled
- AI Labs internal controlles (`/ailabs/*`) will attempt to establish session to deal with phpBB extensions like <a href="https://www.phpbb.com/customise/db/extension/login_required">Login Required</a>
- Better descriptions added to help with setup
- Minor bugfixes
* 1.0.3 June 1, 2023 * 1.0.3 June 1, 2023
- bumped php requirements to >= 7.4 - bumped php requirements to >= 7.4
- Comma removed, reported by [Vlad__](https://www.phpbbguru.net/community/viewtopic.php?p=561224#p561224) - Comma removed, reported by [Vlad__](https://www.phpbbguru.net/community/viewtopic.php?p=561224#p561224)

View file

@ -6,15 +6,23 @@
<a id="maincontent"></a> <a id="maincontent"></a>
<h1>{{ lang('ACP_AILABS_TITLE') }}</h1> <div style="display: flex; align-items: baseline;">
<h1 style="white-space: nowrap;">{{ lang('ACP_AILABS_TITLE') }}</h1>
<div style="width: 100%;"></div><span style="white-space: nowrap;">v. {{ U_AILABS_VERSION }}</span>
</div>
<p> <p>
{{ lang('LBL_AILABS_SETTINGS_DESC') }} <span>{{ lang('LBL_AILABS_SETTINGS_DESC') }}</span>
{% if U_AILABS_VEIW %} {% if U_AILABS_VEIW %}
<a href="{{ U_ADD }}" class="button2" style="float: {{ S_CONTENT_FLOW_END }};">{{ lang('ACP_AILABS_ADD') }}</a> <a href="{{ U_ADD }}" class="button2" style="float: {{ S_CONTENT_FLOW_END }};">{{ lang('ACP_AILABS_ADD') }}</a>
<br> <br>
<br> <br>
{% if U_IP_CHECK %}
<span>{{ U_IP_CHECK }}</span>
{% endif %}
{% endif %} {% endif %}
{% if U_AILABS_ADD_EDIT %} {% if U_AILABS_ADD_EDIT %}
@ -120,6 +128,7 @@
function doReset() { function doReset() {
setTimeout(function () { setTimeout(function () {
resetValue('ailabs_forums_post', {{ ailabs_forums_post }}); resetValue('ailabs_forums_post', {{ ailabs_forums_post }});
resetValue('ailabs_forums_reply', {{ ailabs_forums_reply }});
resetValue('ailabs_forums_mention', {{ ailabs_forums_mention }}); resetValue('ailabs_forums_mention', {{ ailabs_forums_mention }});
}, 500); }, 500);
} }
@ -127,6 +136,7 @@
window.addEventListener("DOMContentLoaded", function () { window.addEventListener("DOMContentLoaded", function () {
$(".chosen-select").chosen(); $(".chosen-select").chosen();
setupSelect('ailabs_forums_post', {{ ailabs_forums_post }}); setupSelect('ailabs_forums_post', {{ ailabs_forums_post }});
setupSelect('ailabs_forums_reply', {{ ailabs_forums_reply }});
setupSelect('ailabs_forums_mention', {{ ailabs_forums_mention }}); setupSelect('ailabs_forums_mention', {{ ailabs_forums_mention }});
}); });
@ -151,7 +161,7 @@
</dd> </dd>
</dl> </dl>
<dl> <dl>
<dt><label for="ailabs_username">{L_ENTER_USERNAME}{L_COLON}</label></dt> <dt><label for="ailabs_username">{{ lang('LBL_AILABS_USERNAME') ~ lang('COLON') }}</label></dt>
<dd><input required class="text medium" type="text" id="ailabs_username" name="ailabs_username" <dd><input required class="text medium" type="text" id="ailabs_username" name="ailabs_username"
value="{{ ailabs_username }}" /></dd> value="{{ ailabs_username }}" /></dd>
<dd>[ <a href="{U_FIND_USERNAME}" onclick="find_username(this.href); return false;">{L_FIND_USERNAME}</a> ] <dd>[ <a href="{U_FIND_USERNAME}" onclick="find_username(this.href); return false;">{L_FIND_USERNAME}</a> ]
@ -195,10 +205,10 @@
</fieldset> </fieldset>
<fieldset> <fieldset>
<legend>{{ lang('LBL_AILABS_REPLY_POST_FORUMS') }}</legend> <legend>{{ lang('LBL_AILABS_POST_FORUMS') }}</legend>
<span>{{ lang('LBL_AILABS_REPLY_POST_FORUMS_EXPLAIN') }}</span> <span>{{ lang('LBL_AILABS_POST_FORUMS_EXPLAIN') }}</span>
<select id="ailabs_forums_post_select" class="chosen-select" multiple data-placeholder="{{ lang('LBL_AILABS_SELECT_FORUMS') }}" <select id="ailabs_forums_post_select" class="chosen-select" multiple
style="width: 100%;"> data-placeholder="{{ lang('LBL_AILABS_SELECT_FORUMS') }}" style="width: 100%;">
{% for key,value in AILABS_FORUMS_LIST %} {% for key,value in AILABS_FORUMS_LIST %}
<option value="{{ key }}">{{ value }}</option> <option value="{{ key }}">{{ value }}</option>
{% endfor %} {% endfor %}
@ -206,10 +216,21 @@
</fieldset> </fieldset>
<fieldset> <fieldset>
<legend>{{ lang('LBL_AILABS_REPLY_QUOTE_FORUMS') }}</legend> <legend>{{ lang('LBL_AILABS_REPLY_FORUMS') }}</legend>
<span>{{ lang('LBL_AILABS_REPLY_QUOTE_FORUMS_EXPLAIN') }}</span> <span>{{ lang('LBL_AILABS_REPLY_FORUMS_EXPLAIN') }}</span>
<select id="ailabs_forums_mention_select" class="chosen-select" multiple data-placeholder="{{ lang('LBL_AILABS_SELECT_FORUMS') }}" <select id="ailabs_forums_reply_select" class="chosen-select" multiple
style="width: 100%;"> data-placeholder="{{ lang('LBL_AILABS_SELECT_FORUMS') }}" style="width: 100%;">
{% for key,value in AILABS_FORUMS_LIST %}
<option value="{{ key }}">{{ value }}</option>
{% endfor %}
</select>
</fieldset>
<fieldset>
<legend>{{ lang('LBL_AILABS_QUOTE_FORUMS') }}</legend>
<span>{{ lang('LBL_AILABS_QUOTE_FORUMS_EXPLAIN') }}</span>
<select id="ailabs_forums_mention_select" class="chosen-select" multiple
data-placeholder="{{ lang('LBL_AILABS_SELECT_FORUMS') }}" style="width: 100%;">
{% for key,value in AILABS_FORUMS_LIST %} {% for key,value in AILABS_FORUMS_LIST %}
<option value="{{ key }}">{{ value }}</option> <option value="{{ key }}">{{ value }}</option>
{% endfor %} {% endfor %}
@ -220,6 +241,7 @@
<legend>{{ lang('ACP_SUBMIT_CHANGES') }}</legend> <legend>{{ lang('ACP_SUBMIT_CHANGES') }}</legend>
<p class="submit-buttons"> <p class="submit-buttons">
<input type="hidden" id="ailabs_forums_post" name="ailabs_forums_post"> <input type="hidden" id="ailabs_forums_post" name="ailabs_forums_post">
<input type="hidden" id="ailabs_forums_reply" name="ailabs_forums_reply">
<input type="hidden" id="ailabs_forums_mention" name="ailabs_forums_mention"> <input type="hidden" id="ailabs_forums_mention" name="ailabs_forums_mention">
<input type="reset" class="button2" value="{{ lang('RESET') }}" onclick="doReset()"> <input type="reset" class="button2" value="{{ lang('RESET') }}" onclick="doReset()">
@ -235,11 +257,17 @@
<table class="tableUsers zebra-table"> <table class="tableUsers zebra-table">
<thead> <thead>
<tr>
<th colspan="2" style="background: transparent; border: none;"></th>
<th colspan="3">{{ lang('LBL_AILABS_REPLY_TO') }}</th>
<th colspan="3" style="background: transparent; border: none;"></th>
</tr>
<tr> <tr>
<th>{{ lang('LBL_AILABS_USERNAME') }}</th> <th>{{ lang('LBL_AILABS_USERNAME') }}</th>
<th>{{ lang('LBL_AILABS_CONTROLLER') }}</th> <th>{{ lang('LBL_AILABS_CONTROLLER') }}</th>
<th>{{ lang('LBL_AILABS_REPLY_POST_FORUMS') }}</th> <th>{{ lang('LBL_AILABS_POST_FORUMS') }}</th>
<th>{{ lang('LBL_AILABS_REPLY_QUOTE_FORUMS') }}</th> <th>{{ lang('LBL_AILABS_REPLY_FORUMS') }}</th>
<th>{{ lang('LBL_AILABS_QUOTE_FORUMS') }}</th>
<th class="centered-text">{{ lang('LBL_AILABS_ENABLED') }}</th> <th class="centered-text">{{ lang('LBL_AILABS_ENABLED') }}</th>
<th></th> <th></th>
</tr> </tr>
@ -247,9 +275,10 @@
<tbody> <tbody>
{% for user in U_AILABS_USERS %} {% for user in U_AILABS_USERS %}
<tr> <tr>
<td><a href="/memberlist.php?mode=viewprofile&u={{ user.user_id }}">{{ user.username }}</a></td> <td><a href="{{ user.username_url }}">{{ user.username }}</a></td>
<td>{{ user.controller }}</td> <td>{{ user.controller }}</td>
<td>{{ user.forums_post_names }}</td> <td>{{ user.forums_post_names }}</td>
<td>{{ user.forums_reply_names }}</td>
<td>{{ user.forums_mention_names }}</td> <td>{{ user.forums_mention_names }}</td>
<td class="centered-text"><input type="checkbox" onclick="return false" {{ user.enabled ? 'checked' : '' }}> <td class="centered-text"><input type="checkbox" onclick="return false" {{ user.enabled ? 'checked' : '' }}>
</td> </td>

View file

@ -3,8 +3,8 @@
"type": "phpbb-extension", "type": "phpbb-extension",
"description": "AI Labs", "description": "AI Labs",
"homepage": "https://privet.fun", "homepage": "https://privet.fun",
"version": "1.0.3", "version": "1.0.4",
"time": "2023-06-01", "time": "2023-06-04",
"keywords": [ "keywords": [
"phpbb", "phpbb",
"extension", "extension",

View file

@ -15,6 +15,7 @@ services:
- '@template' - '@template'
- '@user' - '@user'
- '%core.root_path%' - '%core.root_path%'
- '%core.php_ext%'
- '%privet.ailabs.tables.users%' - '%privet.ailabs.tables.users%'
privet.ailabs.listener: privet.ailabs.listener:

View file

@ -23,6 +23,7 @@ class acp_controller //implements acp_interface
protected $template; protected $template;
protected $user; protected $user;
protected $root_path; protected $root_path;
protected $php_ext;
protected $ailabs_users_table; protected $ailabs_users_table;
protected $id; protected $id;
@ -51,6 +52,7 @@ class acp_controller //implements acp_interface
\phpbb\template\template $template, \phpbb\template\template $template,
\phpbb\user $user, \phpbb\user $user,
$root_path, $root_path,
$php_ext,
$ailabs_users_table $ailabs_users_table
) { ) {
$this->config = $config; $this->config = $config;
@ -63,6 +65,7 @@ class acp_controller //implements acp_interface
$this->template = $template; $this->template = $template;
$this->user = $user; $this->user = $user;
$this->root_path = $root_path; $this->root_path = $root_path;
$this->php_ext = $php_ext;
$this->ailabs_users_table = $ailabs_users_table; $this->ailabs_users_table = $ailabs_users_table;
} }
@ -93,6 +96,7 @@ class acp_controller //implements acp_interface
'config' => $this->request->variable('ailabs_config', '', true), 'config' => $this->request->variable('ailabs_config', '', true),
'template' => $this->request->variable('ailabs_template', '', true), 'template' => $this->request->variable('ailabs_template', '', true),
'forums_post' => $this->request->variable('ailabs_forums_post', ''), 'forums_post' => $this->request->variable('ailabs_forums_post', ''),
'forums_reply' => $this->request->variable('ailabs_forums_reply', ''),
'forums_mention' => $this->request->variable('ailabs_forums_mention', ''), 'forums_mention' => $this->request->variable('ailabs_forums_mention', ''),
'enabled' => $this->request->variable('ailabs_enabled', true), 'enabled' => $this->request->variable('ailabs_enabled', true),
]; ];
@ -111,8 +115,8 @@ class acp_controller //implements acp_interface
trigger_error($this->language->lang('AILABS_USER_ALREADY_CONFIGURED', $username) . adm_back_link($this->u_action), E_USER_WARNING); trigger_error($this->language->lang('AILABS_USER_ALREADY_CONFIGURED', $username) . adm_back_link($this->u_action), E_USER_WARNING);
} }
if (empty($data['forums_post']) && empty($data['forums_mention'])) { if (empty($data['forums_post']) && empty($data['forums_reply']) && empty($data['forums_mention'])) {
trigger_error($this->language->lang('AILABS_SPECIFY_POST_OR_MENTION') . adm_back_link($this->u_action), E_USER_WARNING); trigger_error($this->language->lang('AILABS_SPECIFY_FORUM') . adm_back_link($this->u_action), E_USER_WARNING);
} }
if (!isset($error)) { if (!isset($error)) {
@ -122,6 +126,7 @@ class acp_controller //implements acp_interface
'config' => (string) html_entity_decode($data['config']), 'config' => (string) html_entity_decode($data['config']),
'template' => (string) html_entity_decode($data['template']), 'template' => (string) html_entity_decode($data['template']),
'forums_post' => (string) html_entity_decode($data['forums_post']), 'forums_post' => (string) html_entity_decode($data['forums_post']),
'forums_reply' => (string) html_entity_decode($data['forums_reply']),
'forums_mention' => (string) html_entity_decode($data['forums_mention']), 'forums_mention' => (string) html_entity_decode($data['forums_mention']),
'enabled' => (bool) $data['enabled'] 'enabled' => (bool) $data['enabled']
]; ];
@ -159,6 +164,7 @@ class acp_controller //implements acp_interface
'ailabs_config' => (string) $row['config'], 'ailabs_config' => (string) $row['config'],
'ailabs_template' => (string) $row['template'], 'ailabs_template' => (string) $row['template'],
'ailabs_forums_post' => (string) $row['forums_post'], 'ailabs_forums_post' => (string) $row['forums_post'],
'ailabs_forums_reply' => (string) $row['forums_reply'],
'ailabs_forums_mention' => (string) $row['forums_mention'], 'ailabs_forums_mention' => (string) $row['forums_mention'],
'ailabs_enabled' => (bool) $row['enabled'] 'ailabs_enabled' => (bool) $row['enabled']
]; ];
@ -177,8 +183,6 @@ class acp_controller //implements acp_interface
]); ]);
} }
global $phpbb_root_path, $phpEx;
$this->template->assign_vars( $this->template->assign_vars(
array_merge( array_merge(
$edit, $edit,
@ -187,8 +191,9 @@ class acp_controller //implements acp_interface
'U_AILABS_ADD_EDIT' => true, 'U_AILABS_ADD_EDIT' => true,
'U_ACTION' => $this->action == 'add' ? $this->u_action . '&amp;action=add' : $this->u_action . '&amp;action=edit&amp;user_id=' . $this->user_id, 'U_ACTION' => $this->action == 'add' ? $this->u_action . '&amp;action=add' : $this->u_action . '&amp;action=edit&amp;user_id=' . $this->user_id,
'U_BACK' => $this->u_action, 'U_BACK' => $this->u_action,
'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&amp;form=ailabs_configuration&amp;field=ailabs_username&amp;select_single=true'), 'U_FIND_USERNAME' => generate_board_url() . '/' . append_sid("memberlist.$this->php_ext", 'mode=searchuser&amp;form=ailabs_configuration&amp;field=ailabs_username&amp;select_single=true', true, $this->user->session_id),
'AILABS_FORUMS_LIST' => $this->build_forums_list(), 'AILABS_FORUMS_LIST' => $this->build_forums_list(),
'U_AILABS_VERSION' => $this->config['privet_ailabs_version'],
] ]
) )
); );
@ -229,7 +234,9 @@ class acp_controller //implements acp_interface
$controller = explode("/", $row['controller']); $controller = explode("/", $row['controller']);
$row['controller'] = end($controller); $row['controller'] = end($controller);
$row['username_url'] = generate_board_url() . '/' . append_sid("memberlist.$this->php_ext", 'mode=viewprofile&amp;u=' . $row['user_id'], true, $this->user->session_id);
$row['forums_post_names'] = $this->get_forums_names($row['forums_post'], $forums); $row['forums_post_names'] = $this->get_forums_names($row['forums_post'], $forums);
$row['forums_reply_names'] = $this->get_forums_names($row['forums_reply'], $forums);
$row['forums_mention_names'] = $this->get_forums_names($row['forums_mention'], $forums); $row['forums_mention_names'] = $this->get_forums_names($row['forums_mention'], $forums);
$row['U_EDIT'] = $this->u_action . '&amp;action=edit&amp;user_id=' . $row['user_id'] . '&amp;hash=' . generate_link_hash('acp_ailabs'); $row['U_EDIT'] = $this->u_action . '&amp;action=edit&amp;user_id=' . $row['user_id'] . '&amp;hash=' . generate_link_hash('acp_ailabs');
$row['U_DELETE'] = $this->u_action . '&amp;action=delete&amp;user_id=' . $row['user_id'] . '&amp;username=' . $row['username'] . '&amp;hash=' . generate_link_hash('acp_ailabs'); $row['U_DELETE'] = $this->u_action . '&amp;action=delete&amp;user_id=' . $row['user_id'] . '&amp;username=' . $row['username'] . '&amp;hash=' . generate_link_hash('acp_ailabs');
@ -243,12 +250,23 @@ class acp_controller //implements acp_interface
'U_AILABS_USERS' => $ailabs_users, 'U_AILABS_USERS' => $ailabs_users,
'U_ADD' => $this->u_action . '&amp;action=add', 'U_ADD' => $this->u_action . '&amp;action=add',
'U_ACTION' => $this->u_action, 'U_ACTION' => $this->u_action,
'U_AILABS_VEIW' => true 'U_AILABS_VEIW' => true,
'U_AILABS_VERSION' => $this->config['privet_ailabs_version'],
'U_IP_CHECK' => $this->warn_ip_check()
]; ];
return $this->template->assign_vars($template_vars); return $this->template->assign_vars($template_vars);
} }
protected function warn_ip_check()
{
if ($this->config['ip_check'] != 0) {
$url = generate_board_url() . '/' . append_sid("adm/index.$this->php_ext", ['i' => 'acp_board', 'mode' => 'security'], true, $this->user->session_id);
return $this->language->lang('LBL_AILABS_IP_VALIDATION', $url);
}
return null;
}
protected function find_user_id($username) protected function find_user_id($username)
{ {
$user_id = null; $user_id = null;
@ -306,13 +324,13 @@ class acp_controller //implements acp_interface
return $return; return $return;
} }
protected function get_forums_names($str, $forums) { protected function get_forums_names($str, $forums)
{
$result = []; $result = [];
if (!empty($str)) { if (!empty($str)) {
$arr = json_decode($str); $arr = json_decode($str);
if (!empty($arr) && is_array($arr)) { if (!empty($arr) && is_array($arr)) {
foreach($arr as $id) foreach ($arr as $id) {
{
$name = empty($forums[$id]) ? $id : $forums[$id]; $name = empty($forums[$id]) ? $id : $forums[$id];
array_push($result, $name); array_push($result, $name);
} }
@ -320,5 +338,4 @@ class acp_controller //implements acp_interface
} }
return join(', ', $result); return join(', ', $result);
} }
} }

View file

@ -92,7 +92,6 @@ class chatgpt extends AIController
$post_first_discarded = null; $post_first_discarded = null;
$mode = $this->job['post_mode']; $mode = $this->job['post_mode'];
if ($mode == 'reply' || $mode == 'quote') {
$history = ['post_text' => $this->job['post_text']]; $history = ['post_text' => $this->job['post_text']];
$pattern = '/<QUOTE\sauthor="' . $this->job['ailabs_username'] . '"\spost_id="(.*)"\stime="(.*)"\suser_id="' . $this->job['ailabs_user_id'] . '">/'; $pattern = '/<QUOTE\sauthor="' . $this->job['ailabs_username'] . '"\spost_id="(.*)"\stime="(.*)"\suser_id="' . $this->job['ailabs_user_id'] . '">/';
@ -100,6 +99,7 @@ class chatgpt extends AIController
$this->log['history.pattern'] = $pattern; $this->log['history.pattern'] = $pattern;
$this->log_flush(); $this->log_flush();
// Attempt to unwind history using quoted posts
$history_tokens = 0; $history_tokens = 0;
$round = -1; $round = -1;
do { do {
@ -158,7 +158,6 @@ class chatgpt extends AIController
$this->log['history.posts'] = $posts; $this->log['history.posts'] = $posts;
$this->log_flush(); $this->log_flush();
} }
}
if (!empty($this->cfg->prefix)) { if (!empty($this->cfg->prefix)) {
array_unshift( array_unshift(
@ -237,14 +236,16 @@ class chatgpt extends AIController
$this->log['finish'] = date('Y-m-d H:i:s'); $this->log['finish'] = date('Y-m-d H:i:s');
if (!empty($posts)) { if (!empty($posts)) {
$viewtopic = "{$this->root_path}viewtopic.{$this->php_ext}";
$discarded = ''; $discarded = '';
if ($post_first_discarded != null) { if ($post_first_discarded != null) {
$discarded = $this->language->lang('AILABS_POSTS_DISCARDED', $post_first_discarded); $discarded = $this->language->lang('AILABS_POSTS_DISCARDED', $viewtopic, $post_first_discarded);
} }
$total_posts_count = count($posts) * 2 + 2; $total_posts_count = count($posts) * 2 + 2;
$total_tokens_used_count = $request_tokens + $response_tokens; $total_tokens_used_count = $request_tokens + $response_tokens;
$info = $this->language->lang( $info = $this->language->lang(
'AILABS_DISCARDED_INFO', 'AILABS_DISCARDED_INFO',
$viewtopic,
$post_first_taken, $post_first_taken,
$total_posts_count, $total_posts_count,
$discarded, $discarded,

View file

@ -33,10 +33,10 @@ class log extends AIController
if (!empty($data)) { if (!empty($data)) {
foreach ($data as &$row) { foreach ($data as &$row) {
$row['poster_user_url'] = generate_board_url() . '/' . append_sid("memberlist.$this->php_ext", 'mode=viewprofile&amp;u=' . $row['poster_id'], true, ''); $row['poster_user_url'] = generate_board_url() . '/' . append_sid("memberlist.$this->php_ext", 'mode=viewprofile&amp;u=' . $row['poster_id'], true, $this->user->session_id);
$row['ailabs_user_url'] = generate_board_url() . '/' . append_sid("memberlist.$this->php_ext", 'mode=viewprofile&amp;u=' . $row['ailabs_user_id'], true, ''); $row['ailabs_user_url'] = generate_board_url() . '/' . append_sid("memberlist.$this->php_ext", 'mode=viewprofile&amp;u=' . $row['ailabs_user_id'], true, $this->user->session_id);
if (!empty($row['response_post_id'])) { if (!empty($row['response_post_id'])) {
$row['response_url'] = generate_board_url() . '/' . append_sid('viewtopic.php?p=' . $row['response_post_id'] . '#p' . $row['response_post_id'], true, ''); $row['response_url'] = generate_board_url() . '/' . append_sid("viewtopic.$this->php_ext", 'p=' . $row['response_post_id'] . '#p' . $row['response_post_id'], true, $this->user->session_id);
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 65 KiB

View file

@ -114,11 +114,15 @@ class listener implements EventSubscriberInterface
foreach ($ailabs_users_forum as $user) { foreach ($ailabs_users_forum as $user) {
if ($mode == 'post' && $user['post'] == 1) { if ($mode == 'post' && $user['post'] == 1) {
array_push($ailabs_users, $user); array_push($ailabs_users, $user);
} else {
if ($mode == 'reply' && $user['reply'] == 1) {
array_push($ailabs_users, $user);
} else { } else {
if ($user['mention'] == 1 && in_array($user['user_id'], $ailabs_users_notified)) if ($user['mention'] == 1 && in_array($user['user_id'], $ailabs_users_notified))
array_push($ailabs_users, $user); array_push($ailabs_users, $user);
} }
} }
}
if (empty($ailabs_users)) { if (empty($ailabs_users)) {
return false; return false;
@ -154,6 +158,39 @@ class listener implements EventSubscriberInterface
$request = utf8_encode_ucr($request); $request = utf8_encode_ucr($request);
} }
global $config;
$cookie_name = $config['cookie_name'];
$headers = [];
$copy_headers = ['X-Forwarded-For', 'User-Agent'];
foreach ($copy_headers as $header_name) {
if (!empty($this->request->header($header_name))) {
array_push($headers, "$header_name: " . $this->request->header($header_name));
}
}
$cookies = [];
if ($this->request->is_set($cookie_name . '_sid', \phpbb\request\request_interface::COOKIE) || $this->request->is_set($cookie_name . '_u', \phpbb\request\request_interface::COOKIE)) {
array_push($cookies, $cookie_name . '_u=' . $this->request->variable($cookie_name . '_u', 0, false, \phpbb\request\request_interface::COOKIE));
array_push($cookies, $cookie_name . '_k=' . $this->request->variable($cookie_name . '_k', '', false, \phpbb\request\request_interface::COOKIE));
array_push($cookies, $cookie_name . '_sid=' . $this->request->variable($cookie_name . '_sid', '', false, \phpbb\request\request_interface::COOKIE));
array_push($headers, "Cookie: " . implode('; ', $cookies));
}
$context = null;
if (!empty($headers)) {
$context = stream_context_create(
array(
'http' => array(
'method' => "HEAD",
'header' => implode("\r\n", $headers)
)
)
);
}
// https://area51.phpbb.com/docs/dev/master/db/dbal.html // https://area51.phpbb.com/docs/dev/master/db/dbal.html
foreach ($ailabs_users as $user) { foreach ($ailabs_users as $user) {
$data = [ $data = [
@ -174,8 +211,11 @@ class listener implements EventSubscriberInterface
$this->update_post($data); $this->update_post($data);
$url = generate_board_url() . $user['controller'] . '?job_id=' . $data['job_id']; $url = append_sid(generate_board_url() . $user['controller'], ['job_id' => $data['job_id']], true, $this->user->session_id);
get_headers($url);
// Provide same cookies, session id and browser name so phpBB can authenticate user.
// Verify that Server Configuration > Security Settings > Session IP validation set to none
get_headers($url, false, $context);
unset($data); unset($data);
} }
} }
@ -211,6 +251,7 @@ class listener implements EventSubscriberInterface
$return = array(); $return = array();
$sql = 'SELECT c.user_id, ' . $sql = 'SELECT c.user_id, ' .
'c.forums_post LIKE \'%"' . $id . '"%\' as post, ' . 'c.forums_post LIKE \'%"' . $id . '"%\' as post, ' .
'c.forums_reply LIKE \'%"' . $id . '"%\' as reply, ' .
'c.forums_mention LIKE \'%"' . $id . '"%\' as mention, ' . 'c.forums_mention LIKE \'%"' . $id . '"%\' as mention, ' .
'c.controller, ' . 'c.controller, ' .
'u.username ' . 'u.username ' .
@ -223,6 +264,7 @@ class listener implements EventSubscriberInterface
'user_id' => $row['user_id'], 'user_id' => $row['user_id'],
'username' => $row['username'], 'username' => $row['username'],
'post' => $row['post'], 'post' => $row['post'],
'reply' => $row['reply'],
'mention' => $row['mention'], 'mention' => $row['mention'],
'controller' => $row['controller'] 'controller' => $row['controller']
)); ));
@ -312,9 +354,9 @@ class listener implements EventSubscriberInterface
$ailabs = array(); $ailabs = array();
foreach ($jobs as $key => $value) { foreach ($jobs as $key => $value) {
$value->user_url = generate_board_url() . '/' . append_sid("memberlist.$this->php_ext", 'mode=viewprofile&amp;u=' . $value->ailabs_user_id, true, ''); $value->user_url = generate_board_url() . '/' . append_sid("memberlist.$this->php_ext", 'mode=viewprofile&amp;u=' . $value->ailabs_user_id, true, $this->user->session_id);
if (!empty($value->response_post_id)) { if (!empty($value->response_post_id)) {
$value->response_url = generate_board_url() . '/' . append_sid('viewtopic.php?p=' . $value->response_post_id . '#p' . $value->response_post_id, true, ''); $value->response_url = generate_board_url() . '/' . append_sid("viewtopic.$this->php_ext", "p=$value->response_post_id#p$value->response_post_id", true, $this->user->session_id);
} }
$value->status = $this->get_status(empty($value->status) ? null : $value->status); $value->status = $this->get_status(empty($value->status) ? null : $value->status);
array_push($ailabs, $value); array_push($ailabs, $value);

View file

@ -240,8 +240,14 @@ class AIController
{ {
// Prep posting // Prep posting
$poll = $uid = $bitfield = $options = ''; $poll = $uid = $bitfield = $options = '';
$allow_bbcode = $allow_urls = $allow_smilies = true; generate_text_for_storage($response, $uid, $bitfield, $options, true, true, true);
generate_text_for_storage($response, $uid, $bitfield, $options, $allow_bbcode, $allow_urls, $allow_smilies);
// For some reason uid is not calculated by generate_text_for_storage
if (empty($uid)) {
$message_parser = new \parse_message($response);
$message_parser->parse(true, true, true);
$uid = $message_parser->bbcode_uid;
}
$data = array( $data = array(
'poster_id' => $job['ailabs_user_id'], 'poster_id' => $job['ailabs_user_id'],

View file

@ -19,8 +19,8 @@ if (empty($lang) || !is_array($lang)) {
$lang = array_merge($lang, [ $lang = array_merge($lang, [
'AILABS_ERROR_CHECK_LOGS' => '[color=#FF0000]Error. Pelase check logs.[/color]', 'AILABS_ERROR_CHECK_LOGS' => '[color=#FF0000]Error. Pelase check logs.[/color]',
'AILABS_POSTS_DISCARDED' => ', posts starting from [url=/viewtopic.php?p=%1$d#p%1$d]this post[/url] were discarded', 'AILABS_POSTS_DISCARDED' => ', posts starting from [url=%1$s?p=%2$d#p%2$d]this post[/url] were discarded',
'AILABS_DISCARDED_INFO' => '[size=75][url=/viewtopic.php?p=%1$d#p%1$d]Beginning[/url] of a conversation containing %2$d posts%3$s (%4$d tokens of %5$d were used)[/size]', 'AILABS_DISCARDED_INFO' => '[size=75][url=%1$s?p=%2$d#p%2$d]Beginning[/url] of a conversation containing %3$d posts%4$s (%5$d tokens of %6$d were used)[/size]',
'AILABS_THINKING' => 'thinking', 'AILABS_THINKING' => 'thinking',
'AILABS_REPLYING' => 'replying…', 'AILABS_REPLYING' => 'replying…',
'AILABS_REPLIED' => 'replied ↓', 'AILABS_REPLIED' => 'replied ↓',

View file

@ -29,7 +29,7 @@ $lang = array_merge($lang, [
'AILABS_USER_EMPTY' => 'Please select user', 'AILABS_USER_EMPTY' => 'Please select user',
'AILABS_USER_NOT_FOUND' => 'Unable to locate user %1$s', 'AILABS_USER_NOT_FOUND' => 'Unable to locate user %1$s',
'AILABS_USER_ALREADY_CONFIGURED' => 'User %1$s already configured, only one configuration per user supported', 'AILABS_USER_ALREADY_CONFIGURED' => 'User %1$s already configured, only one configuration per user supported',
'AILABS_SPECIFY_POST_OR_MENTION' => 'Both Reply on a post and Reply when quoted can\'t be empty, please specify at least one', 'AILABS_SPECIFY_FORUM' => 'Please select at least one forum',
'LOG_ACP_AILABS_ADDED' => 'AI Labs configuration added', 'LOG_ACP_AILABS_ADDED' => 'AI Labs configuration added',
'LOG_ACP_AILABS_EDITED' => 'AI Labs configuration updated', 'LOG_ACP_AILABS_EDITED' => 'AI Labs configuration updated',
@ -39,20 +39,31 @@ $lang = array_merge($lang, [
'ACP_AILABS_UPDATED' => 'Configuration successfully updated', 'ACP_AILABS_UPDATED' => 'Configuration successfully updated',
'ACP_AILABS_DELETED_CONFIRM' => 'Are you sure that you wish to delete the configuration associated with user %1$s?', 'ACP_AILABS_DELETED_CONFIRM' => 'Are you sure that you wish to delete the configuration associated with user %1$s?',
'LBL_AILABS_SETTINGS_DESC' => 'Please visit 👉 <a href="https://github.com/privet-fun/phpbb_ailabs">https://github.com/privet-fun/phpbb_ailabs</a> for detailed configuration instructions and examples', 'LBL_AILABS_SETTINGS_DESC' => 'Please visit 👉 <a href="https://github.com/privet-fun/phpbb_ailabs">https://github.com/privet-fun/phpbb_ailabs</a> for detailed configuration instructions, troubleshooting and examples.',
'LBL_AILABS_USERNAME' => 'User Name', 'LBL_AILABS_USERNAME' => 'AI bot',
'LBL_AILABS_CONTROLLER' => 'AI', 'LBL_AILABS_CONTROLLER' => 'AI',
'LBL_AILABS_CONFIG' => 'Configuration JSON', 'LBL_AILABS_CONFIG' => 'Configuration JSON',
'LBL_AILABS_TEMPLATE' => 'Template', 'LBL_AILABS_TEMPLATE' => 'Template',
'LBL_AILABS_REPLY_POST_FORUMS' => 'Reply on a post',
'LBL_AILABS_REPLY_QUOTE_FORUMS' => 'Reply when quoted', 'LBL_AILABS_REPLY_TO' => 'Forums where AI bot reply to',
'LBL_AILABS_POST_FORUMS' => 'New topic',
'LBL_AILABS_REPLY_FORUMS' => 'Reply in a topic',
'LBL_AILABS_QUOTE_FORUMS' => 'Quote or <a href="https://www.phpbb.com/customise/db/extension/simple_mentions/" rel="nofollow">mention</a>',
'LBL_AILABS_ENABLED' => 'Enabled', 'LBL_AILABS_ENABLED' => 'Enabled',
'LBL_AILABS_SELECT_FORUMS' => 'Select forums...', 'LBL_AILABS_SELECT_FORUMS' => 'Select forums...',
'LBL_AILABS_CONFIG_EXPLAIN' => 'Must be valid JSON, please refer to documnetation for details', 'LBL_AILABS_CONFIG_EXPLAIN' => 'Must be valid JSON, please refer to documnetation for details',
'LBL_AILABS_TEMPLATE_EXPLAIN' => 'Valid variables: {post_id}, {request}, {info}, {response}, {images}, {attachments}, {poster_id}, {poster_name}, {ailabs_username}', 'LBL_AILABS_TEMPLATE_EXPLAIN' => 'Valid variables: {post_id}, {request}, {info}, {response}, {images}, {attachments}, {poster_id}, {poster_name}, {ailabs_username}',
'LBL_AILABS_REPLY_POST_FORUMS_EXPLAIN' => 'Specify forums where AI will reply to new posts', 'LBL_AILABS_POST_FORUMS_EXPLAIN' => 'Specify forums where AI will reply to new topic',
'LBL_AILABS_REPLY_QUOTE_FORUMS_EXPLAIN' => 'Specify forums where AI will reply to quoted posts', 'LBL_AILABS_REPLY_FORUMS_EXPLAIN' => 'Specify forums where AI will reply to reply in the topic',
'LBL_AILABS_QUOTE_FORUMS_EXPLAIN' => 'Specify forums where AI will reply when quoted or <a href="https://www.phpbb.com/customise/db/extension/simple_mentions/" rel="nofollow">mentioned</a>',
'LBL_AILABS_IP_VALIDATION' => '⚠️ Warning: Your ACP > General > Server Configuration > Security Settings > ' .
'<a href="%1$s">Session IP validation setting NOT set to None</a>, ' .
'this may prevent AI Labs to reply if you are using phpBB extensions which force user to be logged in ' .
'(eg <a href="https://www.phpbb.com/customise/db/extension/login_required">Login Required</a>). ' .
'Set Session IP validation to None or add "/ailabs/*" to extension whitelist. ' .
'Please refer to <a href="https://github.com/privet-fun/phpbb_ailabs#troubleshooting">troubleshooting section</a> for more details.',
'LBL_AILABS_CONFIG_DEFAULT' => 'Load default configuration', 'LBL_AILABS_CONFIG_DEFAULT' => 'Load default configuration',
'LBL_AILABS_TEMPLATE_DEFAULT' => 'Load default template', 'LBL_AILABS_TEMPLATE_DEFAULT' => 'Load default template',
]); ]);

View file

@ -19,8 +19,8 @@ if (empty($lang) || !is_array($lang)) {
$lang = array_merge($lang, [ $lang = array_merge($lang, [
'AILABS_ERROR_CHECK_LOGS' => '[color=#FF0000]Ошибка. Лог содержит детальную информацию.[/color]', 'AILABS_ERROR_CHECK_LOGS' => '[color=#FF0000]Ошибка. Лог содержит детальную информацию.[/color]',
'AILABS_POSTS_DISCARDED' => ', сообщения начиная с [url=/viewtopic.php?p=%1$d#p%1$d]этого[/url] не включены', 'AILABS_POSTS_DISCARDED' => ', сообщения начиная с [url=%1$s?p=%2$d#p%2$d]этого[/url] не включены',
'AILABS_DISCARDED_INFO' => '[size=75][url=/viewtopic.php?p=%1$d#p%1$d]Начало[/url] беседы из %2$d сообщений%3$s (%4$d токенов из %5$d использовано)[/size]', 'AILABS_DISCARDED_INFO' => '[size=75][url=%1$s?p=%2$d#p%2$d]Начало[/url] беседы из %3$d сообщений%4$s (%5$d токенов из %6$d использовано)[/size]',
'AILABS_THINKING' => 'думает', 'AILABS_THINKING' => 'думает',
'AILABS_REPLYING' => 'отвечает…', 'AILABS_REPLYING' => 'отвечает…',
'AILABS_REPLIED' => 'ответил ↓', 'AILABS_REPLIED' => 'ответил ↓',

View file

@ -29,7 +29,7 @@ $lang = array_merge($lang, [
'AILABS_USER_EMPTY' => 'Пожалуйста, выберите пользователя', 'AILABS_USER_EMPTY' => 'Пожалуйста, выберите пользователя',
'AILABS_USER_NOT_FOUND' => 'Не удалось найти пользователя %1$s', 'AILABS_USER_NOT_FOUND' => 'Не удалось найти пользователя %1$s',
'AILABS_USER_ALREADY_CONFIGURED' => 'Пользователь %1$s уже настроен, поддерживается только одна конфигурация на пользователя', 'AILABS_USER_ALREADY_CONFIGURED' => 'Пользователь %1$s уже настроен, поддерживается только одна конфигурация на пользователя',
'AILABS_SPECIFY_POST_OR_MENTION' => 'Нельзя оставлять пустыми и "Ответ на сообщение" и "Ответ при цитировании", пожалуйста, укажите хотя бы одно значение', 'AILABS_SPECIFY_FORUM' => 'Укажите хотя бы один форум',
'LOG_ACP_AILABS_ADDED' => 'Конфигурация AI Labs добавлена', 'LOG_ACP_AILABS_ADDED' => 'Конфигурация AI Labs добавлена',
'LOG_ACP_AILABS_EDITED' => 'Конфигурация AI Labs изменена', 'LOG_ACP_AILABS_EDITED' => 'Конфигурация AI Labs изменена',
@ -39,20 +39,33 @@ $lang = array_merge($lang, [
'ACP_AILABS_UPDATED' => 'Конфигурация успешно обновлена', 'ACP_AILABS_UPDATED' => 'Конфигурация успешно обновлена',
'ACP_AILABS_DELETED_CONFIRM' => 'Вы уверены, что хотите удалить конфигурацию, связанную с пользователем %1$s?', 'ACP_AILABS_DELETED_CONFIRM' => 'Вы уверены, что хотите удалить конфигурацию, связанную с пользователем %1$s?',
'LBL_AILABS_SETTINGS_DESC' => 'Пожалуйста, посетите 👉 <a href="https://github.com/privet-fun/phpbb_ailabs">https://github.com/privet-fun/phpbb_ailabs</a> для получения подробных инструкций по настройке и примеров', 'LBL_AILABS_SETTINGS_DESC' => 'Пожалуйста, посетите 👉 <a href="https://github.com/privet-fun/phpbb_ailabs">https://github.com/privet-fun/phpbb_ailabs</a> для получения подробных инструкций по настройке и примеров.',
'LBL_AILABS_USERNAME' => 'Имя пользователя', 'LBL_AILABS_USERNAME' => 'AI бот',
'LBL_AILABS_CONTROLLER' => 'AI', 'LBL_AILABS_CONTROLLER' => 'AI',
'LBL_AILABS_CONFIG' => 'Конфигурация в формате JSON', 'LBL_AILABS_CONFIG' => 'Конфигурация в формате JSON',
'LBL_AILABS_TEMPLATE' => 'Шаблон', 'LBL_AILABS_TEMPLATE' => 'Шаблон',
'LBL_AILABS_REPLY_POST_FORUMS' => 'Ответ на сообщение',
'LBL_AILABS_REPLY_QUOTE_FORUMS' => 'Ответ при цитировании', 'LBL_AILABS_REPLY_TO' => 'Форумы где AI бот отвечает на',
'LBL_AILABS_POST_FORUMS' => 'Новую тему',
'LBL_AILABS_REPLY_FORUMS' => 'Ответ в теме',
'LBL_AILABS_QUOTE_FORUMS' => 'Цитирование или <a href="https://www.phpbb.com/customise/db/extension/simple_mentions/" rel="nofollow">упоминание</a>',
'LBL_AILABS_ENABLED' => 'Включено', 'LBL_AILABS_ENABLED' => 'Включено',
'LBL_AILABS_SELECT_FORUMS' => 'Выберите форумы...', 'LBL_AILABS_SELECT_FORUMS' => 'Выберите форумы...',
'LBL_AILABS_CONFIG_EXPLAIN' => 'Пожалуйста, обратитесь к документации для получения подробных инструкций по настройке и примеров', 'LBL_AILABS_CONFIG_EXPLAIN' => 'Пожалуйста, обратитесь к документации для получения подробных инструкций по настройке и примеров',
'LBL_AILABS_TEMPLATE_EXPLAIN' => 'Допустимые переменные: {post_id}, {request}, {info}, {response}, {images}, {attachments}, {poster_id}, {poster_name}, {ailabs_username}', 'LBL_AILABS_TEMPLATE_EXPLAIN' => 'Допустимые переменные: {post_id}, {request}, {info}, {response}, {images}, {attachments}, {poster_id}, {poster_name}, {ailabs_username}',
'LBL_AILABS_REPLY_POST_FORUMS_EXPLAIN' => 'Укажите форумы, на которых AI будет отвечать на новые сообщения', 'LBL_AILABS_POST_FORUMS_EXPLAIN' => 'Укажите форумы, на которых AI будет отвечать на новые темы',
'LBL_AILABS_REPLY_QUOTE_FORUMS_EXPLAIN' => 'Укажите форумы, на которых AI будет отвечать на цитируемые сообщения', 'LBL_AILABS_REPLY_FORUMS_EXPLAIN' => 'Укажите форумы, на которых AI будет отвечать на ответы',
'LBL_AILABS_QUOTE_FORUMS_EXPLAIN' => 'Укажите форумы, на которых AI будет отвечать на цитируемые сообщения или <a href="https://www.phpbb.com/customise/db/extension/simple_mentions/" rel="nofollow">упоминания</a>',
'LBL_AILABS_IP_VALIDATION' => '⚠️ Предупреждение: Администрировать > Общие > Конфигурация сервера > Безопасность > ' .
'<a href="%1$s">Проверка IP-адреса сессии НЕ установлена в значение «Нет»</a>. ' .
'Это может препятствовать работе AI Labs в случае если вы используете расширения phpBB, ' .
'требующие авторизацию пользователя ' .
'(например <a href="https://www.phpbb.com/customise/db/extension/login_required">Login Required</a>). ' .
'Установите проверку IP-адреса сессии в значение "Нет" или добавьте "/ailabs/*" в белый список расширений. ' .
'Пожалуйста, обратитесь к <a href="https://github.com/privet-fun/phpbb_ailabs#troubleshooting">разделу по ' .
'устранению неполадок</a> для получения дополнительной информации.',
'LBL_AILABS_CONFIG_DEFAULT' => 'Загрузить конфигурацию по умолчанию', 'LBL_AILABS_CONFIG_DEFAULT' => 'Загрузить конфигурацию по умолчанию',
'LBL_AILABS_TEMPLATE_DEFAULT' => 'Загрузить шаблон по умолчанию', 'LBL_AILABS_TEMPLATE_DEFAULT' => 'Загрузить шаблон по умолчанию',
]); ]);

View file

@ -0,0 +1,51 @@
<?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\migrations\v1x;
class release_1_0_4_schema extends \phpbb\db\migration\migration
{
static public function depends_on()
{
return array('\privet\ailabs\migrations\v1x\release_1_0_0_schema');
}
public function effectively_installed()
{
return isset($this->config['privet_ailabs_version']) && version_compare($this->config['privet_ailabs_version'], '1.0.4', '>=');
}
public function update_data()
{
return array(
array('config.add', array('privet_ailabs_version', '1.0.4')),
);
}
public function revert_data()
{
return array(
array('config.remove', array('privet_ailabs_version')),
);
}
public function update_schema()
{
return [
'add_columns' => [
$this->table_prefix . 'ailabs_users' => [
'forums_reply' => ['VCHAR', ''], // eg ["forum_id1","forum_id2"]
],
],
];
}
}