<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
		<title><![CDATA[MyBB Community Forums - Plugin Support]]></title>
		<link>https://community.mybb.com/</link>
		<description><![CDATA[MyBB Community Forums - https://community.mybb.com]]></description>
		<pubDate>Tue, 09 Jun 2026 06:40:11 +0000</pubDate>
		<generator>MyBB</generator>
		<item>
			<title><![CDATA[Help with downloads plugin]]></title>
			<link>https://community.mybb.com/thread-245407.html</link>
			<pubDate>Mon, 01 Jun 2026 02:24:44 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://community.mybb.com/member.php?action=profile&uid=161085">SamGreg2025</a>]]></dc:creator>
			<guid isPermaLink="false">https://community.mybb.com/thread-245407.html</guid>
			<description><![CDATA[Hello I installed the Mydownloads plugin but how ever can not seem to make it work correctly its activated but does not want me to upload files to the forums ? can anyone help me.<br /><!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://community.mybb.com/images/attachtypes/image.gif" title="JPEG Image" border="0" alt=".jpg" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=48881" target="_blank" title="">Pic 1.jpg</a> (Size: 250.1 KB / Downloads: 21)
<!-- end: postbit_attachments_attachment -->]]></description>
			<content:encoded><![CDATA[Hello I installed the Mydownloads plugin but how ever can not seem to make it work correctly its activated but does not want me to upload files to the forums ? can anyone help me.<br /><!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://community.mybb.com/images/attachtypes/image.gif" title="JPEG Image" border="0" alt=".jpg" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=48881" target="_blank" title="">Pic 1.jpg</a> (Size: 250.1 KB / Downloads: 21)
<!-- end: postbit_attachments_attachment -->]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Google SEO plugin: URL query param highlight conflict with pagination]]></title>
			<link>https://community.mybb.com/thread-245276.html</link>
			<pubDate>Thu, 07 May 2026 08:14:27 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://community.mybb.com/member.php?action=profile&uid=59317">Goose</a>]]></dc:creator>
			<guid isPermaLink="false">https://community.mybb.com/thread-245276.html</guid>
			<description><![CDATA[Hello,<br />
<br />
I run mybb v1.8.39 with plugin "Google SEO (Updated for PHP 8) (1.8.6)".<br />
<br />
A user have reported an issue. After a search, with the "highlight" param in the query, the pagination links are not OK: there are two '?' in the URL.<br />
<br />
Obtained link:<br />
<pre class="block-code line-numbers language-none"><code class="language-none">https://WEBSITE/SEO-URL-OF-SUBJECT?page=3?highlight=SEARCHED_KEYWORD</code></pre><br />
<br />
Should be:<br />
<pre class="block-code line-numbers language-none"><code class="language-none">https://WEBSITE/SEO-URL-OF-SUBJECT?page=3&amp;highlight=SEARCHED_KEYWORD</code></pre> <br />
<br />
<br />
Real example: <a href="https://www.japancar.fr/forum/Sujet-ACTU-HONDA?highlight=honda" target="_blank" rel="noopener" class="mycode_url">https://www.japancar.fr/forum/Sujet-ACTU...ight=honda</a> (then, see the pagination links on the page)<br />
<br />
<br />
Do you know where should I look?]]></description>
			<content:encoded><![CDATA[Hello,<br />
<br />
I run mybb v1.8.39 with plugin "Google SEO (Updated for PHP 8) (1.8.6)".<br />
<br />
A user have reported an issue. After a search, with the "highlight" param in the query, the pagination links are not OK: there are two '?' in the URL.<br />
<br />
Obtained link:<br />
<pre class="block-code line-numbers language-none"><code class="language-none">https://WEBSITE/SEO-URL-OF-SUBJECT?page=3?highlight=SEARCHED_KEYWORD</code></pre><br />
<br />
Should be:<br />
<pre class="block-code line-numbers language-none"><code class="language-none">https://WEBSITE/SEO-URL-OF-SUBJECT?page=3&amp;highlight=SEARCHED_KEYWORD</code></pre> <br />
<br />
<br />
Real example: <a href="https://www.japancar.fr/forum/Sujet-ACTU-HONDA?highlight=honda" target="_blank" rel="noopener" class="mycode_url">https://www.japancar.fr/forum/Sujet-ACTU...ight=honda</a> (then, see the pagination links on the page)<br />
<br />
<br />
Do you know where should I look?]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Required Approvals 1.1]]></title>
			<link>https://community.mybb.com/thread-245271.html</link>
			<pubDate>Wed, 06 May 2026 10:37:40 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://community.mybb.com/member.php?action=profile&uid=73777">Xenodream</a>]]></dc:creator>
			<guid isPermaLink="false">https://community.mybb.com/thread-245271.html</guid>
			<description><![CDATA[I was using this plugin in 1.833 and php7.4 without any problems, but it is not compatible with 1.839 and php8.2+ (activating it causes 500 server internal error), and it seems to have been abandoned.<br />
<br />
But I can't find any alternative for moderating new user's first posts, which I want in order to purge spammers without their spam first being visible to others (I'd rather not moderate all user posts). Security questions and periodic purging of dodgy accounts only goes so far.<br />
Is there some other way to achieve this?<br />
<br />
Or, as it's quite a simple plugin, how hard would it be for someone to make that or some similar plugin compatible with php8?]]></description>
			<content:encoded><![CDATA[I was using this plugin in 1.833 and php7.4 without any problems, but it is not compatible with 1.839 and php8.2+ (activating it causes 500 server internal error), and it seems to have been abandoned.<br />
<br />
But I can't find any alternative for moderating new user's first posts, which I want in order to purge spammers without their spam first being visible to others (I'd rather not moderate all user posts). Security questions and periodic purging of dodgy accounts only goes so far.<br />
Is there some other way to achieve this?<br />
<br />
Or, as it's quite a simple plugin, how hard would it be for someone to make that or some similar plugin compatible with php8?]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Plugin install broke everything.]]></title>
			<link>https://community.mybb.com/thread-245249.html</link>
			<pubDate>Thu, 30 Apr 2026 14:24:09 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://community.mybb.com/member.php?action=profile&uid=161197">talland</a>]]></dc:creator>
			<guid isPermaLink="false">https://community.mybb.com/thread-245249.html</guid>
			<description><![CDATA[Installing a Plugin is really complicated, is there another way than trying to move each plugin-folder / -file to the correct folder?]]></description>
			<content:encoded><![CDATA[Installing a Plugin is really complicated, is there another way than trying to move each plugin-folder / -file to the correct folder?]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[PHP 8.3 version Upgrade.  Script in ACP is not compatible]]></title>
			<link>https://community.mybb.com/thread-245152.html</link>
			<pubDate>Sun, 12 Apr 2026 14:43:54 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://community.mybb.com/member.php?action=profile&uid=148916">Billy_Bob</a>]]></dc:creator>
			<guid isPermaLink="false">https://community.mybb.com/thread-245152.html</guid>
			<description><![CDATA[Anyone have a compatible script for the plugin control panel?<br />
<br />
This is the error message when I open the plugin control page.<br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://community.mybb.com/images/attachtypes/image.gif" title="JPEG Image" border="0" alt=".jpg" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=48775" target="_blank" title="">plugin failure to load control screen.jpg</a> (Size: 79.77 KB / Downloads: 60)
<!-- end: postbit_attachments_attachment --><br />
<br />
This is the affected Script:<br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://community.mybb.com/images/attachtypes/image.gif" title="JPEG Image" border="0" alt=".jpg" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=48777" target="_blank" title="">failed script.jpg</a> (Size: 207.53 KB / Downloads: 45)
<!-- end: postbit_attachments_attachment --><br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://community.mybb.com/images/attachtypes/image.gif" title="JPEG Image" border="0" alt=".jpg" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=48776" target="_blank" title="">Filed script 2.jpg</a> (Size: 126.81 KB / Downloads: 44)
<!-- end: postbit_attachments_attachment --><br />
<hr class="mycode_hr" />
Am I reading this failure right or is it another PHP document?]]></description>
			<content:encoded><![CDATA[Anyone have a compatible script for the plugin control panel?<br />
<br />
This is the error message when I open the plugin control page.<br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://community.mybb.com/images/attachtypes/image.gif" title="JPEG Image" border="0" alt=".jpg" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=48775" target="_blank" title="">plugin failure to load control screen.jpg</a> (Size: 79.77 KB / Downloads: 60)
<!-- end: postbit_attachments_attachment --><br />
<br />
This is the affected Script:<br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://community.mybb.com/images/attachtypes/image.gif" title="JPEG Image" border="0" alt=".jpg" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=48777" target="_blank" title="">failed script.jpg</a> (Size: 207.53 KB / Downloads: 45)
<!-- end: postbit_attachments_attachment --><br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://community.mybb.com/images/attachtypes/image.gif" title="JPEG Image" border="0" alt=".jpg" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=48776" target="_blank" title="">Filed script 2.jpg</a> (Size: 126.81 KB / Downloads: 44)
<!-- end: postbit_attachments_attachment --><br />
<hr class="mycode_hr" />
Am I reading this failure right or is it another PHP document?]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Uninstalling Tapatalk plugin generate Error Logs]]></title>
			<link>https://community.mybb.com/thread-245136.html</link>
			<pubDate>Wed, 08 Apr 2026 19:56:18 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://community.mybb.com/member.php?action=profile&uid=59317">Goose</a>]]></dc:creator>
			<guid isPermaLink="false">https://community.mybb.com/thread-245136.html</guid>
			<description><![CDATA[Dear all,<br />
<br />
I am struggling with a problem I was not able to understand after 3 hours of testing...<br />
<br />
I run a myBB v1.8.39 with few plugins installed. One of them is Tapatalk, and I want to remove it.<br />
<br />
I can click on "Uninstall" for this plugin, and it seems OK. But immediately, the Error Log (managed within MyBB) is filled with Megabytes of lines.<br />
<br />
If I reinstall Tapatalk plugin, the error logging stop, everything is back to normal.<br />
<br />
<br />
<br />
What is strange is that the myBB forum seems to be functional after tapatalk plugin removal: I can navigate, etc...<br />
I have tried rebuilding cache after uninstalling the tapatalk plugin, but doesn't solve the issue.<br />
<br />
I have checked the install and uninstall functions of tapatalk plugin but I was not able to find any root cause for the moment.<br />
<br />
<br />
Any idea what to look for ?<br />
<br />
<br />
<br />
Here is a sample of the errors I have in the Error Log:<br />
<br />
<pre data-deferred="true" class="block-code line-numbers language-none"><code class="language-none">&lt;error&gt;
	&lt;dateline&gt;1775677572&lt;/dateline&gt;
	&lt;script&gt;inc/plugins/google_seo/url.php&lt;/script&gt;
	&lt;line&gt;1622&lt;/line&gt;
	&lt;type&gt;2&lt;/type&gt;
	&lt;friendly_type&gt;Warning&lt;/friendly_type&gt;
	&lt;message&gt;Undefined variable $newurl&lt;/message&gt;
	&lt;back_trace&gt;#0  errorHandler-&gt;error() called at [/inc/class_error.php:157]
#1  errorHandler-&gt;error_callback() called at [/inc/plugins/google_seo/url.php:1622]
#2  google_seo_url_multipage() called at [/inc/functions.php:1148]
#3  multipage() called at [/inc/functions.php:4819]
#4  build_breadcrumb() called at [/inc/functions.php:298]
#5  parse_page() called at [/inc/functions.php:22]
#6  output_page() called at [/showthread.php:1652]
&lt;/back_trace&gt;
&lt;/error&gt;

&lt;error&gt;
	&lt;dateline&gt;1775677573&lt;/dateline&gt;
	&lt;script&gt;inc/plugins/inferno/class_core.php&lt;/script&gt;
	&lt;line&gt;93&lt;/line&gt;
	&lt;type&gt;2&lt;/type&gt;
	&lt;friendly_type&gt;Warning&lt;/friendly_type&gt;
	&lt;message&gt;Trying to access array offset on false&lt;/message&gt;
	&lt;back_trace&gt;#0  errorHandler-&gt;error() called at [/inc/class_error.php:157]
#1  errorHandler-&gt;error_callback() called at [/inc/plugins/inferno/class_core.php:93]
#2  inferno_shoutbox-&gt;is_banned() called at [/inc/plugins/inferno/class_core.php:60]
#3  inferno_shoutbox-&gt;__construct() called at [/inc/plugins/inferno/class_core.php:76]
#4  inferno_shoutbox::get_instance() called at [/inc/plugins/inferno.php:40]
#5  inferno_init() called at [/inc/plugins/inferno.php:82]
#6  inferno_global() called at [/inc/class_plugins.php:142]
#7  pluginSystem-&gt;run_hooks() called at [/global.php:498]
#8  require_once() called at [/showthread.php:28]
&lt;/back_trace&gt;
&lt;/error&gt;

&lt;error&gt;
	&lt;dateline&gt;1775677573&lt;/dateline&gt;
	&lt;script&gt;inc/plugins/google_seo/url.php&lt;/script&gt;
	&lt;line&gt;846&lt;/line&gt;
	&lt;type&gt;2&lt;/type&gt;
	&lt;friendly_type&gt;Warning&lt;/friendly_type&gt;
	&lt;message&gt;Undefined array key 3128&lt;/message&gt;
	&lt;back_trace&gt;#0  errorHandler-&gt;error() called at [/inc/class_error.php:157]
#1  errorHandler-&gt;error_callback() called at [/inc/plugins/google_seo/url.php:846]
#2  google_seo_url_cache() called at [/inc/plugins/google_seo/url.php:1360]
#3  google_seo_url_profile() called at [/inc/functions.php:6444]
#4  get_profile_link() called at [/inc/functions_post.php:280]
#5  build_postbit() called at [/showthread.php:1122]
&lt;/back_trace&gt;
&lt;/error&gt;

&lt;error&gt;
	&lt;dateline&gt;1775677573&lt;/dateline&gt;
	&lt;script&gt;inc/plugins/google_seo.php&lt;/script&gt;
	&lt;line&gt;198&lt;/line&gt;
	&lt;type&gt;2&lt;/type&gt;
	&lt;friendly_type&gt;Warning&lt;/friendly_type&gt;
	&lt;message&gt;Trying to access array offset on null&lt;/message&gt;
	&lt;back_trace&gt;#0  errorHandler-&gt;error() called at [/inc/class_error.php:157]
#1  errorHandler-&gt;error_callback() called at [/inc/plugins/google_seo.php:198]
#2  google_seo_tid() called at [/inc/plugins/google_seo/url.php:1465]
#3  google_seo_url_post() called at [/inc/functions.php:6608]
#4  get_post_link() called at [/inc/functions_post.php:722]
#5  build_postbit() called at [/showthread.php:1122]
&lt;/back_trace&gt;
&lt;/error&gt;</code></pre>]]></description>
			<content:encoded><![CDATA[Dear all,<br />
<br />
I am struggling with a problem I was not able to understand after 3 hours of testing...<br />
<br />
I run a myBB v1.8.39 with few plugins installed. One of them is Tapatalk, and I want to remove it.<br />
<br />
I can click on "Uninstall" for this plugin, and it seems OK. But immediately, the Error Log (managed within MyBB) is filled with Megabytes of lines.<br />
<br />
If I reinstall Tapatalk plugin, the error logging stop, everything is back to normal.<br />
<br />
<br />
<br />
What is strange is that the myBB forum seems to be functional after tapatalk plugin removal: I can navigate, etc...<br />
I have tried rebuilding cache after uninstalling the tapatalk plugin, but doesn't solve the issue.<br />
<br />
I have checked the install and uninstall functions of tapatalk plugin but I was not able to find any root cause for the moment.<br />
<br />
<br />
Any idea what to look for ?<br />
<br />
<br />
<br />
Here is a sample of the errors I have in the Error Log:<br />
<br />
<pre data-deferred="true" class="block-code line-numbers language-none"><code class="language-none">&lt;error&gt;
	&lt;dateline&gt;1775677572&lt;/dateline&gt;
	&lt;script&gt;inc/plugins/google_seo/url.php&lt;/script&gt;
	&lt;line&gt;1622&lt;/line&gt;
	&lt;type&gt;2&lt;/type&gt;
	&lt;friendly_type&gt;Warning&lt;/friendly_type&gt;
	&lt;message&gt;Undefined variable $newurl&lt;/message&gt;
	&lt;back_trace&gt;#0  errorHandler-&gt;error() called at [/inc/class_error.php:157]
#1  errorHandler-&gt;error_callback() called at [/inc/plugins/google_seo/url.php:1622]
#2  google_seo_url_multipage() called at [/inc/functions.php:1148]
#3  multipage() called at [/inc/functions.php:4819]
#4  build_breadcrumb() called at [/inc/functions.php:298]
#5  parse_page() called at [/inc/functions.php:22]
#6  output_page() called at [/showthread.php:1652]
&lt;/back_trace&gt;
&lt;/error&gt;

&lt;error&gt;
	&lt;dateline&gt;1775677573&lt;/dateline&gt;
	&lt;script&gt;inc/plugins/inferno/class_core.php&lt;/script&gt;
	&lt;line&gt;93&lt;/line&gt;
	&lt;type&gt;2&lt;/type&gt;
	&lt;friendly_type&gt;Warning&lt;/friendly_type&gt;
	&lt;message&gt;Trying to access array offset on false&lt;/message&gt;
	&lt;back_trace&gt;#0  errorHandler-&gt;error() called at [/inc/class_error.php:157]
#1  errorHandler-&gt;error_callback() called at [/inc/plugins/inferno/class_core.php:93]
#2  inferno_shoutbox-&gt;is_banned() called at [/inc/plugins/inferno/class_core.php:60]
#3  inferno_shoutbox-&gt;__construct() called at [/inc/plugins/inferno/class_core.php:76]
#4  inferno_shoutbox::get_instance() called at [/inc/plugins/inferno.php:40]
#5  inferno_init() called at [/inc/plugins/inferno.php:82]
#6  inferno_global() called at [/inc/class_plugins.php:142]
#7  pluginSystem-&gt;run_hooks() called at [/global.php:498]
#8  require_once() called at [/showthread.php:28]
&lt;/back_trace&gt;
&lt;/error&gt;

&lt;error&gt;
	&lt;dateline&gt;1775677573&lt;/dateline&gt;
	&lt;script&gt;inc/plugins/google_seo/url.php&lt;/script&gt;
	&lt;line&gt;846&lt;/line&gt;
	&lt;type&gt;2&lt;/type&gt;
	&lt;friendly_type&gt;Warning&lt;/friendly_type&gt;
	&lt;message&gt;Undefined array key 3128&lt;/message&gt;
	&lt;back_trace&gt;#0  errorHandler-&gt;error() called at [/inc/class_error.php:157]
#1  errorHandler-&gt;error_callback() called at [/inc/plugins/google_seo/url.php:846]
#2  google_seo_url_cache() called at [/inc/plugins/google_seo/url.php:1360]
#3  google_seo_url_profile() called at [/inc/functions.php:6444]
#4  get_profile_link() called at [/inc/functions_post.php:280]
#5  build_postbit() called at [/showthread.php:1122]
&lt;/back_trace&gt;
&lt;/error&gt;

&lt;error&gt;
	&lt;dateline&gt;1775677573&lt;/dateline&gt;
	&lt;script&gt;inc/plugins/google_seo.php&lt;/script&gt;
	&lt;line&gt;198&lt;/line&gt;
	&lt;type&gt;2&lt;/type&gt;
	&lt;friendly_type&gt;Warning&lt;/friendly_type&gt;
	&lt;message&gt;Trying to access array offset on null&lt;/message&gt;
	&lt;back_trace&gt;#0  errorHandler-&gt;error() called at [/inc/class_error.php:157]
#1  errorHandler-&gt;error_callback() called at [/inc/plugins/google_seo.php:198]
#2  google_seo_tid() called at [/inc/plugins/google_seo/url.php:1465]
#3  google_seo_url_post() called at [/inc/functions.php:6608]
#4  get_post_link() called at [/inc/functions_post.php:722]
#5  build_postbit() called at [/showthread.php:1122]
&lt;/back_trace&gt;
&lt;/error&gt;</code></pre>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Selfmade Plugin - need some advice]]></title>
			<link>https://community.mybb.com/thread-245079.html</link>
			<pubDate>Wed, 25 Mar 2026 16:11:37 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://community.mybb.com/member.php?action=profile&uid=160634">Allvater</a>]]></dc:creator>
			<guid isPermaLink="false">https://community.mybb.com/thread-245079.html</guid>
			<description><![CDATA[hey guys!<br />
<br />
i made my own plugin for my rpg board<br />
<br />
it can count words and adds xp<br />
<br />
can someone, that is deeper than me into mybb and coding tell me if there are any issues with that code?<br />
<br />
atm it works very fine<br />
<br />
<br />
<pre data-deferred="true" class="block-code line-numbers language-none"><code class="language-php">&lt;?php
/**
 * xp plugin for MyBB 1.8.x.
 */

if (!defined('IN_MYBB')) {
    die('Direct initialization of this file is not allowed.');
}

if (!defined('AURUN_XP_MIN_GLORY_DISPLAY')) {
    define('AURUN_XP_MIN_GLORY_DISPLAY', 0.01);
}

$plugins-&gt;add_hook('admin_config_settings_change', 'aurun_xp_settings_changed');
$plugins-&gt;add_hook('global_start', 'aurun_xp_global_start');
$plugins-&gt;add_hook('index_start', 'aurun_xp_index_start');
$plugins-&gt;add_hook('stats_start', 'aurun_xp_stats_start');
$plugins-&gt;add_hook('member_profile_end', 'aurun_xp_member_profile_end');
$plugins-&gt;add_hook('memberlist_user', 'aurun_xp_memberlist_user');
$plugins-&gt;add_hook('postbit', 'aurun_xp_postbit');
$plugins-&gt;add_hook('postbit_prev', 'aurun_xp_postbit');
$plugins-&gt;add_hook('postbit_pm', 'aurun_xp_postbit');
$plugins-&gt;add_hook('postbit_announcement', 'aurun_xp_postbit');

$plugins-&gt;add_hook('datahandler_post_insert_post_end', 'aurun_xp_handle_insert_post');
$plugins-&gt;add_hook('datahandler_post_insert_thread_end', 'aurun_xp_handle_insert_thread');
$plugins-&gt;add_hook('datahandler_post_update_end', 'aurun_xp_handle_update_post');
$plugins-&gt;add_hook('xmlhttp_update_post', 'aurun_xp_handle_inline_edit');
$plugins-&gt;add_hook('editpost_do_editpost_end', 'aurun_xp_handle_editpost_end');
$plugins-&gt;add_hook('editpost_deletepost', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('editpost_restorepost', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('editpost_start', 'aurun_xp_handle_author_change_request');

$plugins-&gt;add_hook('class_moderation_delete_post_start', 'aurun_xp_capture_post_delete_start');
$plugins-&gt;add_hook('class_moderation_delete_thread_start', 'aurun_xp_capture_thread_delete_start');
$plugins-&gt;add_hook('class_moderation_delete_post', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_delete_thread', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_soft_delete_posts', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_restore_posts', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_soft_delete_threads', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_restore_threads', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_move_thread_redirect', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_move_simple', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_copy_thread', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_move_threads', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_merge_posts', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_merge_threads', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_split_posts', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_approve_posts', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_unapprove_posts', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_approve_threads', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_unapprove_threads', 'aurun_xp_mark_dirty_event');

function aurun_xp_info()
{
    return [
        'name' =&gt; 'Aurun XP / Ruhm',
        'description' =&gt; 'counting words and adding xp.',
        'website' =&gt; '',
        'author' =&gt; 'Allvater',
        'authorsite' =&gt; '',
        'version' =&gt; '1.1.0',
        'compatibility' =&gt; '18*',
    ];
}

function aurun_xp_is_installed()
{
    global $db;

    return $db-&gt;field_exists('xp_words', 'posts') &amp;&amp; $db-&gt;field_exists('xp_glory_total', 'users');
}

function aurun_xp_install()
{
    aurun_xp_ensure_schema();
    aurun_xp_create_settings();
    aurun_xp_mark_dirty(true, 'install');
    aurun_xp_rebuild_all();
}

function aurun_xp_uninstall()
{
    global $db;

    aurun_xp_remove_settings();
    aurun_xp_drop_column_if_exists('posts', 'xp_words');
    aurun_xp_drop_column_if_exists('posts', 'xp_glory');
    aurun_xp_drop_column_if_exists('users', 'xp_glory_total');
    $db-&gt;delete_query('datacache', &quot;title IN ('aurun_xp_stats', 'aurun_xp_dirty', 'aurun_xp_delete_snapshot')&quot;);
}

function aurun_xp_activate()
{
    aurun_xp_ensure_schema();
}

function aurun_xp_deactivate()
{
    // Keine Template-Edits oder Template-Insertions.
}

function aurun_xp_ensure_schema()
{
    global $db;

    if (!$db-&gt;field_exists('xp_words', 'posts')) {
        $db-&gt;add_column('posts', 'xp_words', 'INT UNSIGNED NOT NULL DEFAULT 0');
    }

    if (!$db-&gt;field_exists('xp_glory', 'posts')) {
        $db-&gt;add_column('posts', 'xp_glory', 'DECIMAL(12,2) NOT NULL DEFAULT 0.00');
    }

    if (!$db-&gt;field_exists('xp_glory_total', 'users')) {
        $db-&gt;add_column('users', 'xp_glory_total', 'DECIMAL(14,2) NOT NULL DEFAULT 0.00');
    }
}

function aurun_xp_drop_column_if_exists($table, $column)
{
    global $db;

    if ($db-&gt;field_exists($column, $table)) {
        $db-&gt;drop_column($table, $column);
    }
}

function aurun_xp_create_settings()
{
    global $db;

    $gid = (int) $db-&gt;fetch_field($db-&gt;simple_select('settinggroups', 'gid', &quot;name='aurun_xp'&quot;), 'gid');

    if (!$gid) {
        $gid = (int) $db-&gt;insert_query('settinggroups', [
            'name' =&gt; 'aurun_xp',
            'title' =&gt; 'Aurun XP / Ruhm',
            'description' =&gt; 'Einstellungen für Wortzählung, Ruhm und Anzeigevariablen.',
            'disporder' =&gt; 90,
            'isdefault' =&gt; 0,
        ]);
    }

    $settings = [
        'aurun_xp_scored_forums' =&gt; [
            'title' =&gt; 'Gewertete Foren',
            'description' =&gt; 'Kommaseparierte Foren-IDs. Nur diese Foren zählen für User-Ruhm, Gesamtruhm, RPG-Beiträge, RPG-Themen und längsten RPG-Beitrag.',
            'optionscode' =&gt; 'text',
            'value' =&gt; '',
            'disporder' =&gt; 1,
        ],
        'aurun_xp_scored_groups' =&gt; [
            'title' =&gt; 'Gewertete Gruppen',
            'description' =&gt; 'Kommaseparierte Gruppen-IDs. Es wird nur die primäre Gruppe eines Users geprüft.',
            'optionscode' =&gt; 'text',
            'value' =&gt; '',
            'disporder' =&gt; 2,
        ],
        'aurun_xp_inactive_groups' =&gt; [
            'title' =&gt; 'Inaktive Gruppen',
            'description' =&gt; 'Kommaseparierte Gruppen-IDs. Diese User behalten ihren Ruhm, zählen weiter zum Gesamtruhm, werden aber in Listen, Top-Spieler und Krone ausgeblendet.',
            'optionscode' =&gt; 'text',
            'value' =&gt; '',
            'disporder' =&gt; 3,
        ],
        'aurun_xp_glory_per_word' =&gt; [
            'title' =&gt; 'Ruhm pro Wort',
            'description' =&gt; 'Numerischer Wert, z. B. 0.01. Gilt nur für Beiträge in gewerteten Foren von Usern in gewerteten Gruppen.',
            'optionscode' =&gt; 'numeric',
            'value' =&gt; '0.01',
            'disporder' =&gt; 4,
        ],
    ];

    foreach ($settings as $name =&gt; $setting) {
        $where = &quot;name='&quot; . $db-&gt;escape_string($name) . &quot;'&quot;;
        $existing = (int) $db-&gt;fetch_field($db-&gt;simple_select('settings', 'sid', $where), 'sid');

        $payload = [
            'name' =&gt; $name,
            'title' =&gt; $setting['title'],
            'description' =&gt; $setting['description'],
            'optionscode' =&gt; $setting['optionscode'],
            'value' =&gt; $setting['value'],
            'disporder' =&gt; $setting['disporder'],
            'gid' =&gt; $gid,
            'isdefault' =&gt; 0,
        ];

        if ($existing) {
            $db-&gt;update_query('settings', $payload, $where);
        } else {
            $db-&gt;insert_query('settings', $payload);
        }
    }

    rebuild_settings();
}

function aurun_xp_remove_settings()
{
    global $db;

    $db-&gt;delete_query('settings', &quot;name IN ('aurun_xp_scored_forums','aurun_xp_scored_groups','aurun_xp_inactive_groups','aurun_xp_glory_per_word')&quot;);
    $db-&gt;delete_query('settinggroups', &quot;name='aurun_xp'&quot;);
    rebuild_settings();
}

function aurun_xp_settings_changed()
{
    aurun_xp_reset_config_cache();
    aurun_xp_mark_dirty(true, 'settings_changed');
}

function aurun_xp_reset_config_cache()
{
    $GLOBALS['aurun_xp_config_cache'] = null;
}

function aurun_xp_mark_dirty($dirty = true, $reason = '')
{
    global $cache;

    $current = $cache-&gt;read('aurun_xp_dirty');
    if (!is_array($current)) {
        $current = [];
    }

    $payload = [
        'dirty' =&gt; (int) $dirty,
        'updated_at' =&gt; TIME_NOW,
        'reason' =&gt; (string) $reason,
        'rebuilding' =&gt; 0,
    ];

    if (!$dirty &amp;&amp; !empty($current['rebuilding'])) {
        $payload['rebuilding'] = 0;
    }

    $cache-&gt;update('aurun_xp_dirty', $payload);
}

function aurun_xp_set_rebuilding_flag($rebuilding)
{
    global $cache;

    $state = $cache-&gt;read('aurun_xp_dirty');
    if (!is_array($state)) {
        $state = [];
    }

    $state['dirty'] = (int) ($state['dirty'] ?? 0);
    $state['updated_at'] = TIME_NOW;
    $state['reason'] = (string) ($state['reason'] ?? '');
    $state['rebuilding'] = (int) $rebuilding;
    $cache-&gt;update('aurun_xp_dirty', $state);
}

function aurun_xp_parse_id_list($raw)
{
    $raw = trim((string) $raw);
    if ($raw === '') {
        return [];
    }

    $ids = [];
    foreach (preg_split('/\s*,\s*/', $raw, -1, PREG_SPLIT_NO_EMPTY) as $part) {
        $value = (int) $part;
        if ($value &gt; 0) {
            $ids[$value] = $value;
        }
    }

    return array_values($ids);
}

function aurun_xp_get_config()
{
    global $mybb;

    if (isset($GLOBALS['aurun_xp_config_cache']) &amp;&amp; is_array($GLOBALS['aurun_xp_config_cache'])) {
        return $GLOBALS['aurun_xp_config_cache'];
    }

    $GLOBALS['aurun_xp_config_cache'] = [
        'scored_forums' =&gt; aurun_xp_parse_id_list($mybb-&gt;settings['aurun_xp_scored_forums'] ?? ''),
        'scored_groups' =&gt; aurun_xp_parse_id_list($mybb-&gt;settings['aurun_xp_scored_groups'] ?? ''),
        'inactive_groups' =&gt; aurun_xp_parse_id_list($mybb-&gt;settings['aurun_xp_inactive_groups'] ?? ''),
        'glory_per_word' =&gt; round((float) ($mybb-&gt;settings['aurun_xp_glory_per_word'] ?? 0), 2),
    ];

    return $GLOBALS['aurun_xp_config_cache'];
}

function aurun_xp_is_scored_forum($fid)
{
    return in_array((int) $fid, aurun_xp_get_config()['scored_forums'], true);
}

function aurun_xp_is_scored_group($groupId)
{
    return in_array((int) $groupId, aurun_xp_get_config()['scored_groups'], true);
}

function aurun_xp_is_inactive_group($groupId)
{
    return in_array((int) $groupId, aurun_xp_get_config()['inactive_groups'], true);
}

function aurun_xp_is_active_user(array $user)
{
    $uid = (int) ($user['uid'] ?? 0);
    $groupId = (int) ($user['usergroup'] ?? 0);

    return $uid &gt; 0 &amp;&amp; $uid !== 3 &amp;&amp; !aurun_xp_is_inactive_group($groupId);
}

function aurun_xp_format_glory($value)
{
    return number_format((float) $value, 2, ',', '');
}

function aurun_xp_count_words($message)
{
    $message = (string) $message;
    if ($message === '') {
        return 0;
    }

    $message = preg_replace('#https?://\S+#iu', ' ', $message);
    $message = preg_replace('#www\.\S+#iu', ' ', $message);
    $message = preg_replace('#\[(?:/?)(?:[^\]\s=]+)(?:=[^\]]+)?\]#u', ' ', $message);
    $message = html_entity_decode(strip_tags($message), ENT_QUOTES, 'UTF-8');

    preg_match_all('/\p{L}{2,}(?:-\p{L}{2,})*/u', $message, $matches);

    return count($matches[0]);
}

function aurun_xp_calculate_glory($fid, $usergroup, $wordCount)
{
    $config = aurun_xp_get_config();

    if ($wordCount &lt;= 0 || !aurun_xp_is_scored_forum($fid) || !aurun_xp_is_scored_group($usergroup)) {
        return 0.00;
    }

    return round($wordCount * (float) $config['glory_per_word'], 2);
}

function aurun_xp_get_post_snapshot($pid)
{
    global $db;

    $query = $db-&gt;query(
        &quot;SELECT p.pid, p.tid, p.uid, p.fid, p.message, p.subject, p.visible, p.dateline, p.xp_words, p.xp_glory,
                t.visible AS threadvisible
         FROM &quot; . TABLE_PREFIX . &quot;posts p
         LEFT JOIN &quot; . TABLE_PREFIX . &quot;threads t ON (t.tid = p.tid)
         WHERE p.pid='&quot; . (int) $pid . &quot;'
         LIMIT 1&quot;
    );

    return $db-&gt;fetch_array($query);
}

function aurun_xp_get_user_snapshot($uid)
{
    global $db;

    $uid = (int) $uid;
    if ($uid &lt;= 0) {
        return null;
    }

    if (!isset($GLOBALS['aurun_xp_user_snapshot_cache'])) {
        $GLOBALS['aurun_xp_user_snapshot_cache'] = [];
    }

    if (array_key_exists($uid, $GLOBALS['aurun_xp_user_snapshot_cache'])) {
        return $GLOBALS['aurun_xp_user_snapshot_cache'][$uid];
    }

    $GLOBALS['aurun_xp_user_snapshot_cache'][$uid] = $db-&gt;fetch_array($db-&gt;simple_select('users', 'uid,username,usergroup,displaygroup,xp_glory_total', 'uid=' . $uid));

    return $GLOBALS['aurun_xp_user_snapshot_cache'][$uid];
}

function aurun_xp_extract_pid_from_datahandler($dataHandler)
{
    if (is_object($dataHandler)) {
        foreach (['pid', 'post_insert_data'] as $property) {
            if ($property === 'pid' &amp;&amp; !empty($dataHandler-&gt;pid)) {
                return (int) $dataHandler-&gt;pid;
            }
            if ($property === 'post_insert_data' &amp;&amp; !empty($dataHandler-&gt;post_insert_data['pid'])) {
                return (int) $dataHandler-&gt;post_insert_data['pid'];
            }
        }
        if (!empty($dataHandler-&gt;data['pid'])) {
            return (int) $dataHandler-&gt;data['pid'];
        }
        if (!empty($dataHandler-&gt;return_values['pid'])) {
            return (int) $dataHandler-&gt;return_values['pid'];
        }
    }

    global $pid, $mybb;
    if (!empty($pid)) {
        return (int) $pid;
    }
    if (isset($mybb)) {
        return (int) $mybb-&gt;get_input('pid', MyBB::INPUT_INT);
    }

    return 0;
}

function aurun_xp_guard_once($pid, $context)
{
    $pid = (int) $pid;
    if ($pid &lt;= 0) {
        return false;
    }

    if (!isset($GLOBALS['aurun_xp_once_guard'])) {
        $GLOBALS['aurun_xp_once_guard'] = [];
    }

    $key = (string) $pid;
    if (isset($GLOBALS['aurun_xp_once_guard'][$key])) {
        return false;
    }

    $GLOBALS['aurun_xp_once_guard'][$key] = true;

    return true;
}

function aurun_xp_handle_insert_post($dataHandler = null)
{
    $pid = aurun_xp_extract_pid_from_datahandler($dataHandler);
    if ($pid &gt; 0) {
        aurun_xp_apply_post_change($pid, 'insert_post');
    }
}

function aurun_xp_handle_insert_thread($dataHandler = null)
{
    $pid = aurun_xp_extract_pid_from_datahandler($dataHandler);
    if ($pid &gt; 0) {
        aurun_xp_apply_post_change($pid, 'insert_thread');
    }
}

function aurun_xp_handle_update_post($dataHandler = null)
{
    $pid = aurun_xp_extract_pid_from_datahandler($dataHandler);
    if ($pid &gt; 0 &amp;&amp; aurun_xp_guard_once($pid, 'update_post')) {
        aurun_xp_apply_post_change($pid, 'update_post');
    }
}

function aurun_xp_handle_inline_edit()
{
    global $mybb, $pid;

    $inlinePid = (int) $mybb-&gt;get_input('pid', MyBB::INPUT_INT);
    if ($inlinePid &lt;= 0 &amp;&amp; !empty($pid)) {
        $inlinePid = (int) $pid;
    }

    if ($inlinePid &gt; 0 &amp;&amp; aurun_xp_guard_once($inlinePid, 'inline_edit')) {
        aurun_xp_apply_post_change($inlinePid, 'inline_edit');
    }
}

function aurun_xp_handle_editpost_end()
{
    global $pid;

    if ((int) $pid &gt; 0 &amp;&amp; aurun_xp_guard_once((int) $pid, 'editpost')) {
        aurun_xp_apply_post_change((int) $pid, 'editpost');
    }
}

function aurun_xp_handle_author_change_request()
{
    global $mybb;

    if (
        $mybb-&gt;request_method === 'post'
        &amp;&amp; $mybb-&gt;get_input('action') === 'do_author'
        &amp;&amp; ($mybb-&gt;settings['aj_changeauthor'] == 1 || $mybb-&gt;settings['aj_admin_changeauthor'] == 1)
    ) {
        $pid = (int) $mybb-&gt;get_input('pid', MyBB::INPUT_INT);
        if ($pid &gt; 0) {
            register_shutdown_function('aurun_xp_refresh_post_metrics_after_shutdown', $pid, 'author_change');
        }
    }
}

function aurun_xp_refresh_post_metrics_after_shutdown($pid, $reason = '')
{
    $pid = (int) $pid;
    if ($pid &lt;= 0) {
        return;
    }

    if (aurun_xp_guard_once($pid, 'shutdown_update')) {
        aurun_xp_apply_post_change($pid, 'shutdown_update');
    }
}

function aurun_xp_get_stats_cache_for_update()
{
    global $cache;

    $stats = $cache-&gt;read('aurun_xp_stats');
    if (!is_array($stats)) {
        aurun_xp_rebuild_all();
        $stats = $cache-&gt;read('aurun_xp_stats');
    }

    return is_array($stats) ? $stats : [];
}

function aurun_xp_write_stats_cache(array $stats)
{
    global $cache;

    $cache-&gt;update('aurun_xp_stats', $stats);
}

function aurun_xp_refresh_top_player_cache(array &amp;$stats = null)
{
    if ($stats === null) {
        $stats = aurun_xp_get_stats_cache_for_update();
    }

    $topPlayer = aurun_xp_fetch_top_player();
    $stats['xp_top_glory_uid'] = (int) ($topPlayer['uid'] ?? 0);
    $stats['xp_top_glory_value'] = number_format((float) ($topPlayer['xp_glory_total'] ?? 0), 2, '.', '');

    return $stats;
}

function aurun_xp_recount_longest_post()
{
    global $db;

    $longestPost = [
        'pid' =&gt; 0,
        'tid' =&gt; 0,
        'uid' =&gt; 0,
        'subject' =&gt; '',
        'dateline' =&gt; 0,
        'words' =&gt; 0,
    ];

    $query = $db-&gt;query(
        &quot;SELECT p.pid, p.tid, p.uid, p.subject, p.dateline, p.xp_words
         FROM &quot; . TABLE_PREFIX . &quot;posts p
         LEFT JOIN &quot; . TABLE_PREFIX . &quot;threads t ON (t.tid = p.tid)
         WHERE p.visible = 1
           AND t.visible = 1
           AND p.fid IN (&quot; . aurun_xp_sql_id_list(aurun_xp_get_config()['scored_forums']) . &quot;)
         ORDER BY p.xp_words DESC, p.pid ASC
         LIMIT 1&quot;
    );

    if ($query) {
        $row = $db-&gt;fetch_array($query);
        if ($row) {
            $longestPost = [
                'pid' =&gt; (int) $row['pid'],
                'tid' =&gt; (int) $row['tid'],
                'uid' =&gt; (int) $row['uid'],
                'subject' =&gt; (string) $row['subject'],
                'dateline' =&gt; (int) $row['dateline'],
                'words' =&gt; (int) $row['xp_words'],
            ];
        }
    }

    return $longestPost;
}

function aurun_xp_refresh_longest_post_cache(array &amp;$stats, $pid, $wordCount, $isCandidate)
{
    $currentPid = (int) ($stats['xp_longest_post_pid'] ?? 0);
    $currentWords = (int) ($stats['xp_longest_post_words'] ?? 0);

    if ($isCandidate &amp;&amp; (int) $wordCount &gt; $currentWords) {
        $post = aurun_xp_get_post_snapshot($pid);
        $stats['xp_longest_post_pid'] = (int) $pid;
        $stats['xp_longest_post_words'] = (int) $wordCount;
        $stats['xp_longest_post_tid'] = (int) ($post['tid'] ?? 0);
        $stats['xp_longest_post_uid'] = (int) ($post['uid'] ?? 0);
        $stats['xp_longest_post_subject'] = (string) ($post['subject'] ?? '');
        $stats['xp_longest_post_dateline'] = (int) ($post['dateline'] ?? 0);

        return $stats;
    }

    if ($currentPid === (int) $pid &amp;&amp; (!$isCandidate || (int) $wordCount &lt; $currentWords)) {
        $longestPost = aurun_xp_recount_longest_post();
        $stats['xp_longest_post_pid'] = $longestPost['pid'];
        $stats['xp_longest_post_words'] = $longestPost['words'];
        $stats['xp_longest_post_tid'] = $longestPost['tid'];
        $stats['xp_longest_post_uid'] = $longestPost['uid'];
        $stats['xp_longest_post_subject'] = $longestPost['subject'];
        $stats['xp_longest_post_dateline'] = $longestPost['dateline'];
    }

    return $stats;
}

function aurun_xp_adjust_user_glory_total($uid, $delta)
{
    global $db;

    $uid = (int) $uid;
    $delta = round((float) $delta, 2);

    if ($uid &lt;= 0 || abs($delta) &lt; 0.01) {
        return false;
    }

    $user = aurun_xp_get_user_snapshot($uid);
    if (!$user) {
        return false;
    }

    $newTotal = round(max(0, (float) $user['xp_glory_total'] + $delta), 2);

    $db-&gt;update_query('users', [
        'xp_glory_total' =&gt; number_format($newTotal, 2, '.', ''),
    ], 'uid=' . $uid);

    if (!isset($GLOBALS['aurun_xp_user_snapshot_cache'])) {
        $GLOBALS['aurun_xp_user_snapshot_cache'] = [];
    }
    if ($user) {
        $user['xp_glory_total'] = number_format($newTotal, 2, '.', '');
        $GLOBALS['aurun_xp_user_snapshot_cache'][$uid] = $user;
    }

    return true;
}

function aurun_xp_accountswitcher_author_changed($pid, $oldUid, $newUid)
{
    $pid = (int) $pid;
    $oldUid = (int) $oldUid;
    $newUid = (int) $newUid;

    if ($pid &lt;= 0 || $oldUid &lt;= 0 || $newUid &lt;= 0 || $oldUid === $newUid) {
        return false;
    }

    $post = aurun_xp_get_post_snapshot($pid);
    if (!$post) {
        return false;
    }

    $isVisible = ((int) $post['visible'] === 1 &amp;&amp; (int) ($post['threadvisible'] ?? 1) === 1);
    $glory = round((float) ($post['xp_glory'] ?? 0), 2);

    if (!$isVisible || $glory &lt;= 0) {
        return true;
    }

    aurun_xp_adjust_user_glory_total($oldUid, -$glory);
    aurun_xp_adjust_user_glory_total($newUid, $glory);

    $stats = aurun_xp_get_stats_cache_for_update();
    aurun_xp_refresh_top_player_cache($stats);
    aurun_xp_write_stats_cache($stats);

    return true;
}

function aurun_xp_refresh_post_metrics($pid)
{
    global $db;

    $post = aurun_xp_get_post_snapshot($pid);
    if (!$post) {
        return;
    }

    $user = aurun_xp_get_user_snapshot((int) $post['uid']);
    $wordCount = aurun_xp_count_words($post['message']);
    $glory = aurun_xp_calculate_glory((int) $post['fid'], (int) ($user['usergroup'] ?? 0), $wordCount);

    $db-&gt;update_query('posts', [
        'xp_words' =&gt; $wordCount,
        'xp_glory' =&gt; number_format($glory, 2, '.', ''),
    ], 'pid=' . (int) $pid);
}

function aurun_xp_apply_post_change($pid, $context = 'update_post', array $options = [])
{
    global $db;

    $pid = (int) $pid;
    if ($pid &lt;= 0) {
        return false;
    }

    $post = aurun_xp_get_post_snapshot($pid);
    if (!$post) {
        return false;
    }

    $isInsert = in_array($context, ['insert_post', 'insert_thread'], true);
    $oldWords = (int) ($options['old_words'] ?? ($isInsert ? 0 : ($post['xp_words'] ?? 0)));
    $oldGlory = round((float) ($options['old_glory'] ?? ($isInsert ? 0 : ($post['xp_glory'] ?? 0))), 2);
    $oldVisible = (int) ($options['old_visible'] ?? ($isInsert ? 0 : ($post['visible'] ?? 0)));
    $oldThreadVisible = (int) ($options['old_threadvisible'] ?? ($isInsert ? 0 : ($post['threadvisible'] ?? 0)));
    $oldUid = (int) ($options['old_uid'] ?? ($post['uid'] ?? 0));

    $user = aurun_xp_get_user_snapshot((int) $post['uid']);
    $newWords = aurun_xp_count_words($post['message']);
    $newGlory = aurun_xp_calculate_glory((int) $post['fid'], (int) ($user['usergroup'] ?? 0), $newWords);

    $db-&gt;update_query('posts', [
        'xp_words' =&gt; $newWords,
        'xp_glory' =&gt; number_format($newGlory, 2, '.', ''),
    ], 'pid=' . $pid);

    $newVisible = ((int) $post['visible'] === 1 &amp;&amp; (int) ($post['threadvisible'] ?? 1) === 1);
    $oldVisibleCounted = ($oldVisible === 1 &amp;&amp; $oldThreadVisible === 1);
    $oldContribution = $oldVisibleCounted ? $oldGlory : 0.00;
    $newContribution = $newVisible ? $newGlory : 0.00;

    if ($oldUid === (int) $post['uid']) {
        $delta = round($newContribution - $oldContribution, 2);
        if (abs($delta) &gt;= 0.01) {
            aurun_xp_adjust_user_glory_total((int) $post['uid'], $delta);
        }
    } else {
        if ($oldContribution &gt; 0) {
            aurun_xp_adjust_user_glory_total($oldUid, -$oldContribution);
        }
        if ($newContribution &gt; 0) {
            aurun_xp_adjust_user_glory_total((int) $post['uid'], $newContribution);
        }
    }

    $stats = aurun_xp_get_stats_cache_for_update();
    $stats['xp_total_glory'] = number_format(round((float) ($stats['xp_total_glory'] ?? 0) + ($newContribution - $oldContribution), 2), 2, '.', '');

    if ($context === 'insert_post' &amp;&amp; $newVisible &amp;&amp; aurun_xp_is_scored_forum((int) $post['fid'])) {
        $stats['xp_rpg_posts_total'] = (int) ($stats['xp_rpg_posts_total'] ?? 0) + 1;
    } elseif ($context === 'insert_thread' &amp;&amp; $newVisible &amp;&amp; aurun_xp_is_scored_forum((int) $post['fid'])) {
        $stats['xp_rpg_posts_total'] = (int) ($stats['xp_rpg_posts_total'] ?? 0) + 1;
        $stats['xp_rpg_threads_total'] = (int) ($stats['xp_rpg_threads_total'] ?? 0) + 1;
    }

    $isLongestCandidate = $newVisible &amp;&amp; aurun_xp_is_scored_forum((int) $post['fid']);
    aurun_xp_refresh_longest_post_cache($stats, $pid, $newWords, $isLongestCandidate);
    aurun_xp_refresh_top_player_cache($stats);
    $stats['rebuilt_at'] = TIME_NOW;
    aurun_xp_write_stats_cache($stats);

    return true;
}

function aurun_xp_capture_post_delete_start($pid)
{
    global $cache;

    $cache-&gt;update('aurun_xp_delete_snapshot', [
        'type' =&gt; 'post',
        'pid' =&gt; (int) $pid,
        'updated_at' =&gt; TIME_NOW,
    ]);

    return $pid;
}

function aurun_xp_capture_thread_delete_start($tid)
{
    global $cache;

    $cache-&gt;update('aurun_xp_delete_snapshot', [
        'type' =&gt; 'thread',
        'tid' =&gt; (int) $tid,
        'updated_at' =&gt; TIME_NOW,
    ]);

    return $tid;
}

function aurun_xp_mark_dirty_event($payload = null)
{
    aurun_xp_mark_dirty(true, 'moderation');

    return $payload;
}

function aurun_xp_maybe_run_dirty_rebuild()
{
    global $cache;
    static $running = false;

    if ($running) {
        return;
    }

    $state = $cache-&gt;read('aurun_xp_dirty');
    if (!is_array($state) || empty($state['dirty'])) {
        return;
    }

    if (!empty($state['rebuilding'])) {
        return;
    }

    $running = true;
    aurun_xp_set_rebuilding_flag(true);
    aurun_xp_rebuild_all();
    $running = false;
}

function aurun_xp_rebuild_all()
{
    global $db, $cache;

    aurun_xp_ensure_schema();

    $db-&gt;write_query('UPDATE ' . TABLE_PREFIX . &quot;users SET xp_glory_total='0.00'&quot;);

    $userGroups = [];
    $query = $db-&gt;simple_select('users', 'uid,usergroup');
    while ($user = $db-&gt;fetch_array($query)) {
        $userGroups[(int) $user['uid']] = (int) $user['usergroup'];
    }

    $activeGloryByUser = [];
    $totalGlory = 0.00;
    $rpgPostsTotal = 0;
    $longestPost = [
        'pid' =&gt; 0,
        'tid' =&gt; 0,
        'uid' =&gt; 0,
        'subject' =&gt; '',
        'dateline' =&gt; 0,
        'words' =&gt; 0,
    ];

    $postsQuery = $db-&gt;query(
        &quot;SELECT p.pid, p.tid, p.uid, p.fid, p.message, p.subject, p.visible, p.dateline,
                t.visible AS threadvisible
         FROM &quot; . TABLE_PREFIX . &quot;posts p
         LEFT JOIN &quot; . TABLE_PREFIX . &quot;threads t ON (t.tid = p.tid)
         ORDER BY p.pid ASC&quot;
    );

    while ($post = $db-&gt;fetch_array($postsQuery)) {
        $uid = (int) $post['uid'];
        $wordCount = aurun_xp_count_words($post['message']);
        $glory = aurun_xp_calculate_glory((int) $post['fid'], (int) ($userGroups[$uid] ?? 0), $wordCount);

        $db-&gt;update_query('posts', [
            'xp_words' =&gt; $wordCount,
            'xp_glory' =&gt; number_format($glory, 2, '.', ''),
        ], 'pid=' . (int) $post['pid']);

        $isVisible = ((int) $post['visible'] === 1 &amp;&amp; (int) $post['threadvisible'] === 1);
        if (!$isVisible) {
            continue;
        }

        if (aurun_xp_is_scored_forum((int) $post['fid'])) {
            ++$rpgPostsTotal;

            if ($wordCount &gt; $longestPost['words']) {
                $longestPost = [
                    'pid' =&gt; (int) $post['pid'],
                    'tid' =&gt; (int) $post['tid'],
                    'uid' =&gt; $uid,
                    'subject' =&gt; (string) $post['subject'],
                    'dateline' =&gt; (int) $post['dateline'],
                    'words' =&gt; $wordCount,
                ];
            }
        }

        if ($glory &gt; 0) {
            $activeGloryByUser[$uid] = round(($activeGloryByUser[$uid] ?? 0) + $glory, 2);
            $totalGlory = round($totalGlory + $glory, 2);
        }
    }

    foreach ($activeGloryByUser as $uid =&gt; $gloryTotal) {
        $db-&gt;update_query('users', [
            'xp_glory_total' =&gt; number_format($gloryTotal, 2, '.', ''),
        ], 'uid=' . (int) $uid);
    }

    $rpgThreadsTotal = 0;
    $threadQuery = $db-&gt;query(
        &quot;SELECT COUNT(*) AS total
         FROM &quot; . TABLE_PREFIX . &quot;threads
         WHERE fid IN (&quot; . aurun_xp_sql_id_list(aurun_xp_get_config()['scored_forums']) . &quot;)
           AND visible = 1
           AND closed NOT LIKE 'moved|%'&quot;
    );
    if ($threadQuery) {
        $rpgThreadsTotal = (int) $db-&gt;fetch_field($threadQuery, 'total');
    }

    $topPlayer = aurun_xp_fetch_top_player();

    $cache-&gt;update('aurun_xp_stats', [
        'xp_total_glory' =&gt; number_format($totalGlory, 2, '.', ''),
        'xp_rpg_posts_total' =&gt; $rpgPostsTotal,
        'xp_rpg_threads_total' =&gt; $rpgThreadsTotal,
        'xp_longest_post_pid' =&gt; $longestPost['pid'],
        'xp_longest_post_words' =&gt; $longestPost['words'],
        'xp_longest_post_tid' =&gt; $longestPost['tid'],
        'xp_longest_post_uid' =&gt; $longestPost['uid'],
        'xp_longest_post_subject' =&gt; $longestPost['subject'],
        'xp_longest_post_dateline' =&gt; $longestPost['dateline'],
        'xp_top_glory_uid' =&gt; (int) ($topPlayer['uid'] ?? 0),
        'xp_top_glory_value' =&gt; number_format((float) ($topPlayer['xp_glory_total'] ?? 0), 2, '.', ''),
        'rebuilt_at' =&gt; TIME_NOW,
    ]);

    aurun_xp_set_rebuilding_flag(false);
    aurun_xp_mark_dirty(false, 'rebuilt');
}

function aurun_xp_sql_id_list(array $ids)
{
    $ids = array_map('intval', $ids);
    $ids = array_filter($ids, static function ($id) {
        return $id &gt; 0;
    });

    if (empty($ids)) {
        return '0';
    }

    return implode(',', $ids);
}

function aurun_xp_fetch_top_player($limit = 1)
{
    global $db;

    $limit = (int) max(1, $limit);
    $config = aurun_xp_get_config();
    $inactiveGroups = aurun_xp_sql_id_list($config['inactive_groups']);
    $inactiveClause = $inactiveGroups !== '0' ? &quot; AND usergroup NOT IN (&quot; . $inactiveGroups . &quot;)&quot; : '';

    $query = $db-&gt;query(
        &quot;SELECT uid, username, usergroup, displaygroup, xp_glory_total
         FROM &quot; . TABLE_PREFIX . &quot;users
         WHERE uid &lt;&gt; 3
           AND xp_glory_total &gt;= '0.01'&quot; . $inactiveClause . &quot;
         ORDER BY xp_glory_total DESC, username ASC
         LIMIT &quot; . $limit
    );

    if ($limit === 1) {
        $user = $db-&gt;fetch_array($query);

        return $user ?: null;
    }

    $users = [];
    while ($user = $db-&gt;fetch_array($query)) {
        $users[] = $user;
    }

    return $users;
}

function aurun_xp_get_ranked_users($limit = 0)
{
    global $db;

    $config = aurun_xp_get_config();
    $inactiveGroups = aurun_xp_sql_id_list($config['inactive_groups']);
    $inactiveClause = $inactiveGroups !== '0' ? &quot; AND usergroup NOT IN (&quot; . $inactiveGroups . &quot;)&quot; : '';
    $sqlLimit = $limit &gt; 0 ? ' LIMIT ' . (int) $limit : '';
    $query = $db-&gt;query(
        &quot;SELECT uid, username, usergroup, displaygroup, xp_glory_total
         FROM &quot; . TABLE_PREFIX . &quot;users
         WHERE xp_glory_total &gt;= '0.01'
           AND uid &lt;&gt; 3&quot; . $inactiveClause . &quot;
         ORDER BY xp_glory_total DESC, username ASC&quot; . $sqlLimit
    );

    $users = [];
    while ($user = $db-&gt;fetch_array($query)) {
        $users[] = $user;
    }

    return $users;
}

function aurun_xp_get_cached_stats()
{
    global $cache;

    aurun_xp_maybe_run_dirty_rebuild();

    $stats = $cache-&gt;read('aurun_xp_stats');

    return is_array($stats) ? $stats : [];
}

function aurun_xp_crown_html($uid)
{
    $stats = aurun_xp_get_cached_stats();

    if ((int) $uid &gt; 0 &amp;&amp; (int) ($stats['xp_top_glory_uid'] ?? 0) === (int) $uid) {
        return '&lt;span class=&quot;aurunxp-crown&quot; title=&quot;Ruhmreichster Charakter&quot;&gt;👑&lt;/span&gt;';
    }

    return '';
}

function aurun_xp_global_start()
{
    global $mybb;

    aurun_xp_maybe_run_dirty_rebuild();

    if ((int) ($mybb-&gt;user['uid'] ?? 0) &lt;= 0) {
        return;
    }

    $mybb-&gt;user['aurunxp_glory'] = aurun_xp_format_glory((float) ($mybb-&gt;user['xp_glory_total'] ?? 0));
    $mybb-&gt;user['aurunxp_crown'] = aurun_xp_crown_html((int) $mybb-&gt;user['uid']);
}

function aurun_xp_index_start()
{
    global $aurunxp_total_glory, $aurunxp_rpg_posts_total, $aurunxp_rpg_threads_total, $aurunxp_top_list, $aurunxp_longest_post;

    $stats = aurun_xp_get_cached_stats();
    $aurunxp_total_glory = aurun_xp_format_glory((float) ($stats['xp_total_glory'] ?? 0));
    $aurunxp_rpg_posts_total = my_number_format((int) ($stats['xp_rpg_posts_total'] ?? 0));
    $aurunxp_rpg_threads_total = my_number_format((int) ($stats['xp_rpg_threads_total'] ?? 0));

    $topList = [];
    foreach (aurun_xp_fetch_top_player(10) as $user) {
        $topList[] = build_profile_link(
            format_name(htmlspecialchars_uni($user['username']), (int) $user['usergroup'], (int) $user['displaygroup']),
            (int) $user['uid']
        ) . ' (' . aurun_xp_format_glory((float) $user['xp_glory_total']) . ')';
    }
    $aurunxp_top_list = implode(', ', $topList);

    $aurunxp_longest_post = '';
    if (!empty($stats['xp_longest_post_pid'])) {
        $author = aurun_xp_get_user_snapshot((int) $stats['xp_longest_post_uid']);
        $authorLink = $author ? build_profile_link(htmlspecialchars_uni($author['username']), (int) $author['uid']) : 'Unbekannt';
        $title = htmlspecialchars_uni($stats['xp_longest_post_subject'] ?: ('Beitrag #' . (int) $stats['xp_longest_post_pid']));
        $aurunxp_longest_post = '&lt;a href=&quot;' . get_post_link((int) $stats['xp_longest_post_pid']) . '&quot;&gt;' . $title . '&lt;/a&gt; | ' .
            $authorLink . ' | ' .
            my_number_format((int) $stats['xp_longest_post_words']) . ' Wörter | ' .
            my_date('relative', (int) $stats['xp_longest_post_dateline']);
    }
}

function aurun_xp_stats_start()
{
    global $aurunxp_stats_rpg_posts_total, $aurunxp_stats_rpg_threads_total, $aurunxp_stats_longest_post, $aurunxp_stats_top_user, $aurunxp_stats_top_ten;

    $stats = aurun_xp_get_cached_stats();
    $aurunxp_stats_rpg_posts_total = my_number_format((int) ($stats['xp_rpg_posts_total'] ?? 0));
    $aurunxp_stats_rpg_threads_total = my_number_format((int) ($stats['xp_rpg_threads_total'] ?? 0));
    $aurunxp_stats_longest_post = my_number_format((int) ($stats['xp_longest_post_words'] ?? 0));

    $topUser = aurun_xp_fetch_top_player();
    $aurunxp_stats_top_user = '';
    if ($topUser) {
        $aurunxp_stats_top_user = build_profile_link(htmlspecialchars_uni($topUser['username']), (int) $topUser['uid']) .
            ' (' . aurun_xp_format_glory((float) $topUser['xp_glory_total']) . ')';
        if (aurun_xp_crown_html((int) $topUser['uid']) !== '') {
            $aurunxp_stats_top_user .= ' ' . aurun_xp_crown_html((int) $topUser['uid']);
        }
    }

    $topTen = [];
    foreach (aurun_xp_fetch_top_player(10) as $user) {
        $entry = build_profile_link(htmlspecialchars_uni($user['username']), (int) $user['uid']) .
            ' (' . aurun_xp_format_glory((float) $user['xp_glory_total']) . ')';
        $topTen[] = $entry;
    }
    $aurunxp_stats_top_ten = implode(', ', $topTen);
}

function aurun_xp_member_profile_end()
{
    global $memprofile;

    $memprofile['aurunxp_glory'] = aurun_xp_format_glory((float) ($memprofile['xp_glory_total'] ?? 0));
    $memprofile['aurunxp_crown'] = aurun_xp_crown_html((int) ($memprofile['uid'] ?? 0));
}

function aurun_xp_memberlist_user(&amp;$user)
{
    $user['aurunxp_glory'] = aurun_xp_format_glory((float) ($user['xp_glory_total'] ?? 0));
    $user['aurunxp_crown'] = aurun_xp_crown_html((int) ($user['uid'] ?? 0));
}

function aurun_xp_postbit(&amp;$post)
{
    $post['aurunxp_words'] = my_number_format((int) ($post['xp_words'] ?? 0));
    $post['aurunxp_glory'] = aurun_xp_format_glory((float) ($post['xp_glory'] ?? 0));

    if (isset($post['xp_glory_total'])) {
        $post['aurunxp_user_glory'] = aurun_xp_format_glory((float) $post['xp_glory_total']);
    } else {
        $author = aurun_xp_get_user_snapshot((int) ($post['uid'] ?? 0));
        $post['aurunxp_user_glory'] = aurun_xp_format_glory((float) ($author['xp_glory_total'] ?? 0));
    }

    $post['aurunxp_crown'] = aurun_xp_crown_html((int) ($post['uid'] ?? 0));
}</code></pre>]]></description>
			<content:encoded><![CDATA[hey guys!<br />
<br />
i made my own plugin for my rpg board<br />
<br />
it can count words and adds xp<br />
<br />
can someone, that is deeper than me into mybb and coding tell me if there are any issues with that code?<br />
<br />
atm it works very fine<br />
<br />
<br />
<pre data-deferred="true" class="block-code line-numbers language-none"><code class="language-php">&lt;?php
/**
 * xp plugin for MyBB 1.8.x.
 */

if (!defined('IN_MYBB')) {
    die('Direct initialization of this file is not allowed.');
}

if (!defined('AURUN_XP_MIN_GLORY_DISPLAY')) {
    define('AURUN_XP_MIN_GLORY_DISPLAY', 0.01);
}

$plugins-&gt;add_hook('admin_config_settings_change', 'aurun_xp_settings_changed');
$plugins-&gt;add_hook('global_start', 'aurun_xp_global_start');
$plugins-&gt;add_hook('index_start', 'aurun_xp_index_start');
$plugins-&gt;add_hook('stats_start', 'aurun_xp_stats_start');
$plugins-&gt;add_hook('member_profile_end', 'aurun_xp_member_profile_end');
$plugins-&gt;add_hook('memberlist_user', 'aurun_xp_memberlist_user');
$plugins-&gt;add_hook('postbit', 'aurun_xp_postbit');
$plugins-&gt;add_hook('postbit_prev', 'aurun_xp_postbit');
$plugins-&gt;add_hook('postbit_pm', 'aurun_xp_postbit');
$plugins-&gt;add_hook('postbit_announcement', 'aurun_xp_postbit');

$plugins-&gt;add_hook('datahandler_post_insert_post_end', 'aurun_xp_handle_insert_post');
$plugins-&gt;add_hook('datahandler_post_insert_thread_end', 'aurun_xp_handle_insert_thread');
$plugins-&gt;add_hook('datahandler_post_update_end', 'aurun_xp_handle_update_post');
$plugins-&gt;add_hook('xmlhttp_update_post', 'aurun_xp_handle_inline_edit');
$plugins-&gt;add_hook('editpost_do_editpost_end', 'aurun_xp_handle_editpost_end');
$plugins-&gt;add_hook('editpost_deletepost', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('editpost_restorepost', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('editpost_start', 'aurun_xp_handle_author_change_request');

$plugins-&gt;add_hook('class_moderation_delete_post_start', 'aurun_xp_capture_post_delete_start');
$plugins-&gt;add_hook('class_moderation_delete_thread_start', 'aurun_xp_capture_thread_delete_start');
$plugins-&gt;add_hook('class_moderation_delete_post', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_delete_thread', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_soft_delete_posts', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_restore_posts', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_soft_delete_threads', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_restore_threads', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_move_thread_redirect', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_move_simple', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_copy_thread', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_move_threads', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_merge_posts', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_merge_threads', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_split_posts', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_approve_posts', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_unapprove_posts', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_approve_threads', 'aurun_xp_mark_dirty_event');
$plugins-&gt;add_hook('class_moderation_unapprove_threads', 'aurun_xp_mark_dirty_event');

function aurun_xp_info()
{
    return [
        'name' =&gt; 'Aurun XP / Ruhm',
        'description' =&gt; 'counting words and adding xp.',
        'website' =&gt; '',
        'author' =&gt; 'Allvater',
        'authorsite' =&gt; '',
        'version' =&gt; '1.1.0',
        'compatibility' =&gt; '18*',
    ];
}

function aurun_xp_is_installed()
{
    global $db;

    return $db-&gt;field_exists('xp_words', 'posts') &amp;&amp; $db-&gt;field_exists('xp_glory_total', 'users');
}

function aurun_xp_install()
{
    aurun_xp_ensure_schema();
    aurun_xp_create_settings();
    aurun_xp_mark_dirty(true, 'install');
    aurun_xp_rebuild_all();
}

function aurun_xp_uninstall()
{
    global $db;

    aurun_xp_remove_settings();
    aurun_xp_drop_column_if_exists('posts', 'xp_words');
    aurun_xp_drop_column_if_exists('posts', 'xp_glory');
    aurun_xp_drop_column_if_exists('users', 'xp_glory_total');
    $db-&gt;delete_query('datacache', &quot;title IN ('aurun_xp_stats', 'aurun_xp_dirty', 'aurun_xp_delete_snapshot')&quot;);
}

function aurun_xp_activate()
{
    aurun_xp_ensure_schema();
}

function aurun_xp_deactivate()
{
    // Keine Template-Edits oder Template-Insertions.
}

function aurun_xp_ensure_schema()
{
    global $db;

    if (!$db-&gt;field_exists('xp_words', 'posts')) {
        $db-&gt;add_column('posts', 'xp_words', 'INT UNSIGNED NOT NULL DEFAULT 0');
    }

    if (!$db-&gt;field_exists('xp_glory', 'posts')) {
        $db-&gt;add_column('posts', 'xp_glory', 'DECIMAL(12,2) NOT NULL DEFAULT 0.00');
    }

    if (!$db-&gt;field_exists('xp_glory_total', 'users')) {
        $db-&gt;add_column('users', 'xp_glory_total', 'DECIMAL(14,2) NOT NULL DEFAULT 0.00');
    }
}

function aurun_xp_drop_column_if_exists($table, $column)
{
    global $db;

    if ($db-&gt;field_exists($column, $table)) {
        $db-&gt;drop_column($table, $column);
    }
}

function aurun_xp_create_settings()
{
    global $db;

    $gid = (int) $db-&gt;fetch_field($db-&gt;simple_select('settinggroups', 'gid', &quot;name='aurun_xp'&quot;), 'gid');

    if (!$gid) {
        $gid = (int) $db-&gt;insert_query('settinggroups', [
            'name' =&gt; 'aurun_xp',
            'title' =&gt; 'Aurun XP / Ruhm',
            'description' =&gt; 'Einstellungen für Wortzählung, Ruhm und Anzeigevariablen.',
            'disporder' =&gt; 90,
            'isdefault' =&gt; 0,
        ]);
    }

    $settings = [
        'aurun_xp_scored_forums' =&gt; [
            'title' =&gt; 'Gewertete Foren',
            'description' =&gt; 'Kommaseparierte Foren-IDs. Nur diese Foren zählen für User-Ruhm, Gesamtruhm, RPG-Beiträge, RPG-Themen und längsten RPG-Beitrag.',
            'optionscode' =&gt; 'text',
            'value' =&gt; '',
            'disporder' =&gt; 1,
        ],
        'aurun_xp_scored_groups' =&gt; [
            'title' =&gt; 'Gewertete Gruppen',
            'description' =&gt; 'Kommaseparierte Gruppen-IDs. Es wird nur die primäre Gruppe eines Users geprüft.',
            'optionscode' =&gt; 'text',
            'value' =&gt; '',
            'disporder' =&gt; 2,
        ],
        'aurun_xp_inactive_groups' =&gt; [
            'title' =&gt; 'Inaktive Gruppen',
            'description' =&gt; 'Kommaseparierte Gruppen-IDs. Diese User behalten ihren Ruhm, zählen weiter zum Gesamtruhm, werden aber in Listen, Top-Spieler und Krone ausgeblendet.',
            'optionscode' =&gt; 'text',
            'value' =&gt; '',
            'disporder' =&gt; 3,
        ],
        'aurun_xp_glory_per_word' =&gt; [
            'title' =&gt; 'Ruhm pro Wort',
            'description' =&gt; 'Numerischer Wert, z. B. 0.01. Gilt nur für Beiträge in gewerteten Foren von Usern in gewerteten Gruppen.',
            'optionscode' =&gt; 'numeric',
            'value' =&gt; '0.01',
            'disporder' =&gt; 4,
        ],
    ];

    foreach ($settings as $name =&gt; $setting) {
        $where = &quot;name='&quot; . $db-&gt;escape_string($name) . &quot;'&quot;;
        $existing = (int) $db-&gt;fetch_field($db-&gt;simple_select('settings', 'sid', $where), 'sid');

        $payload = [
            'name' =&gt; $name,
            'title' =&gt; $setting['title'],
            'description' =&gt; $setting['description'],
            'optionscode' =&gt; $setting['optionscode'],
            'value' =&gt; $setting['value'],
            'disporder' =&gt; $setting['disporder'],
            'gid' =&gt; $gid,
            'isdefault' =&gt; 0,
        ];

        if ($existing) {
            $db-&gt;update_query('settings', $payload, $where);
        } else {
            $db-&gt;insert_query('settings', $payload);
        }
    }

    rebuild_settings();
}

function aurun_xp_remove_settings()
{
    global $db;

    $db-&gt;delete_query('settings', &quot;name IN ('aurun_xp_scored_forums','aurun_xp_scored_groups','aurun_xp_inactive_groups','aurun_xp_glory_per_word')&quot;);
    $db-&gt;delete_query('settinggroups', &quot;name='aurun_xp'&quot;);
    rebuild_settings();
}

function aurun_xp_settings_changed()
{
    aurun_xp_reset_config_cache();
    aurun_xp_mark_dirty(true, 'settings_changed');
}

function aurun_xp_reset_config_cache()
{
    $GLOBALS['aurun_xp_config_cache'] = null;
}

function aurun_xp_mark_dirty($dirty = true, $reason = '')
{
    global $cache;

    $current = $cache-&gt;read('aurun_xp_dirty');
    if (!is_array($current)) {
        $current = [];
    }

    $payload = [
        'dirty' =&gt; (int) $dirty,
        'updated_at' =&gt; TIME_NOW,
        'reason' =&gt; (string) $reason,
        'rebuilding' =&gt; 0,
    ];

    if (!$dirty &amp;&amp; !empty($current['rebuilding'])) {
        $payload['rebuilding'] = 0;
    }

    $cache-&gt;update('aurun_xp_dirty', $payload);
}

function aurun_xp_set_rebuilding_flag($rebuilding)
{
    global $cache;

    $state = $cache-&gt;read('aurun_xp_dirty');
    if (!is_array($state)) {
        $state = [];
    }

    $state['dirty'] = (int) ($state['dirty'] ?? 0);
    $state['updated_at'] = TIME_NOW;
    $state['reason'] = (string) ($state['reason'] ?? '');
    $state['rebuilding'] = (int) $rebuilding;
    $cache-&gt;update('aurun_xp_dirty', $state);
}

function aurun_xp_parse_id_list($raw)
{
    $raw = trim((string) $raw);
    if ($raw === '') {
        return [];
    }

    $ids = [];
    foreach (preg_split('/\s*,\s*/', $raw, -1, PREG_SPLIT_NO_EMPTY) as $part) {
        $value = (int) $part;
        if ($value &gt; 0) {
            $ids[$value] = $value;
        }
    }

    return array_values($ids);
}

function aurun_xp_get_config()
{
    global $mybb;

    if (isset($GLOBALS['aurun_xp_config_cache']) &amp;&amp; is_array($GLOBALS['aurun_xp_config_cache'])) {
        return $GLOBALS['aurun_xp_config_cache'];
    }

    $GLOBALS['aurun_xp_config_cache'] = [
        'scored_forums' =&gt; aurun_xp_parse_id_list($mybb-&gt;settings['aurun_xp_scored_forums'] ?? ''),
        'scored_groups' =&gt; aurun_xp_parse_id_list($mybb-&gt;settings['aurun_xp_scored_groups'] ?? ''),
        'inactive_groups' =&gt; aurun_xp_parse_id_list($mybb-&gt;settings['aurun_xp_inactive_groups'] ?? ''),
        'glory_per_word' =&gt; round((float) ($mybb-&gt;settings['aurun_xp_glory_per_word'] ?? 0), 2),
    ];

    return $GLOBALS['aurun_xp_config_cache'];
}

function aurun_xp_is_scored_forum($fid)
{
    return in_array((int) $fid, aurun_xp_get_config()['scored_forums'], true);
}

function aurun_xp_is_scored_group($groupId)
{
    return in_array((int) $groupId, aurun_xp_get_config()['scored_groups'], true);
}

function aurun_xp_is_inactive_group($groupId)
{
    return in_array((int) $groupId, aurun_xp_get_config()['inactive_groups'], true);
}

function aurun_xp_is_active_user(array $user)
{
    $uid = (int) ($user['uid'] ?? 0);
    $groupId = (int) ($user['usergroup'] ?? 0);

    return $uid &gt; 0 &amp;&amp; $uid !== 3 &amp;&amp; !aurun_xp_is_inactive_group($groupId);
}

function aurun_xp_format_glory($value)
{
    return number_format((float) $value, 2, ',', '');
}

function aurun_xp_count_words($message)
{
    $message = (string) $message;
    if ($message === '') {
        return 0;
    }

    $message = preg_replace('#https?://\S+#iu', ' ', $message);
    $message = preg_replace('#www\.\S+#iu', ' ', $message);
    $message = preg_replace('#\[(?:/?)(?:[^\]\s=]+)(?:=[^\]]+)?\]#u', ' ', $message);
    $message = html_entity_decode(strip_tags($message), ENT_QUOTES, 'UTF-8');

    preg_match_all('/\p{L}{2,}(?:-\p{L}{2,})*/u', $message, $matches);

    return count($matches[0]);
}

function aurun_xp_calculate_glory($fid, $usergroup, $wordCount)
{
    $config = aurun_xp_get_config();

    if ($wordCount &lt;= 0 || !aurun_xp_is_scored_forum($fid) || !aurun_xp_is_scored_group($usergroup)) {
        return 0.00;
    }

    return round($wordCount * (float) $config['glory_per_word'], 2);
}

function aurun_xp_get_post_snapshot($pid)
{
    global $db;

    $query = $db-&gt;query(
        &quot;SELECT p.pid, p.tid, p.uid, p.fid, p.message, p.subject, p.visible, p.dateline, p.xp_words, p.xp_glory,
                t.visible AS threadvisible
         FROM &quot; . TABLE_PREFIX . &quot;posts p
         LEFT JOIN &quot; . TABLE_PREFIX . &quot;threads t ON (t.tid = p.tid)
         WHERE p.pid='&quot; . (int) $pid . &quot;'
         LIMIT 1&quot;
    );

    return $db-&gt;fetch_array($query);
}

function aurun_xp_get_user_snapshot($uid)
{
    global $db;

    $uid = (int) $uid;
    if ($uid &lt;= 0) {
        return null;
    }

    if (!isset($GLOBALS['aurun_xp_user_snapshot_cache'])) {
        $GLOBALS['aurun_xp_user_snapshot_cache'] = [];
    }

    if (array_key_exists($uid, $GLOBALS['aurun_xp_user_snapshot_cache'])) {
        return $GLOBALS['aurun_xp_user_snapshot_cache'][$uid];
    }

    $GLOBALS['aurun_xp_user_snapshot_cache'][$uid] = $db-&gt;fetch_array($db-&gt;simple_select('users', 'uid,username,usergroup,displaygroup,xp_glory_total', 'uid=' . $uid));

    return $GLOBALS['aurun_xp_user_snapshot_cache'][$uid];
}

function aurun_xp_extract_pid_from_datahandler($dataHandler)
{
    if (is_object($dataHandler)) {
        foreach (['pid', 'post_insert_data'] as $property) {
            if ($property === 'pid' &amp;&amp; !empty($dataHandler-&gt;pid)) {
                return (int) $dataHandler-&gt;pid;
            }
            if ($property === 'post_insert_data' &amp;&amp; !empty($dataHandler-&gt;post_insert_data['pid'])) {
                return (int) $dataHandler-&gt;post_insert_data['pid'];
            }
        }
        if (!empty($dataHandler-&gt;data['pid'])) {
            return (int) $dataHandler-&gt;data['pid'];
        }
        if (!empty($dataHandler-&gt;return_values['pid'])) {
            return (int) $dataHandler-&gt;return_values['pid'];
        }
    }

    global $pid, $mybb;
    if (!empty($pid)) {
        return (int) $pid;
    }
    if (isset($mybb)) {
        return (int) $mybb-&gt;get_input('pid', MyBB::INPUT_INT);
    }

    return 0;
}

function aurun_xp_guard_once($pid, $context)
{
    $pid = (int) $pid;
    if ($pid &lt;= 0) {
        return false;
    }

    if (!isset($GLOBALS['aurun_xp_once_guard'])) {
        $GLOBALS['aurun_xp_once_guard'] = [];
    }

    $key = (string) $pid;
    if (isset($GLOBALS['aurun_xp_once_guard'][$key])) {
        return false;
    }

    $GLOBALS['aurun_xp_once_guard'][$key] = true;

    return true;
}

function aurun_xp_handle_insert_post($dataHandler = null)
{
    $pid = aurun_xp_extract_pid_from_datahandler($dataHandler);
    if ($pid &gt; 0) {
        aurun_xp_apply_post_change($pid, 'insert_post');
    }
}

function aurun_xp_handle_insert_thread($dataHandler = null)
{
    $pid = aurun_xp_extract_pid_from_datahandler($dataHandler);
    if ($pid &gt; 0) {
        aurun_xp_apply_post_change($pid, 'insert_thread');
    }
}

function aurun_xp_handle_update_post($dataHandler = null)
{
    $pid = aurun_xp_extract_pid_from_datahandler($dataHandler);
    if ($pid &gt; 0 &amp;&amp; aurun_xp_guard_once($pid, 'update_post')) {
        aurun_xp_apply_post_change($pid, 'update_post');
    }
}

function aurun_xp_handle_inline_edit()
{
    global $mybb, $pid;

    $inlinePid = (int) $mybb-&gt;get_input('pid', MyBB::INPUT_INT);
    if ($inlinePid &lt;= 0 &amp;&amp; !empty($pid)) {
        $inlinePid = (int) $pid;
    }

    if ($inlinePid &gt; 0 &amp;&amp; aurun_xp_guard_once($inlinePid, 'inline_edit')) {
        aurun_xp_apply_post_change($inlinePid, 'inline_edit');
    }
}

function aurun_xp_handle_editpost_end()
{
    global $pid;

    if ((int) $pid &gt; 0 &amp;&amp; aurun_xp_guard_once((int) $pid, 'editpost')) {
        aurun_xp_apply_post_change((int) $pid, 'editpost');
    }
}

function aurun_xp_handle_author_change_request()
{
    global $mybb;

    if (
        $mybb-&gt;request_method === 'post'
        &amp;&amp; $mybb-&gt;get_input('action') === 'do_author'
        &amp;&amp; ($mybb-&gt;settings['aj_changeauthor'] == 1 || $mybb-&gt;settings['aj_admin_changeauthor'] == 1)
    ) {
        $pid = (int) $mybb-&gt;get_input('pid', MyBB::INPUT_INT);
        if ($pid &gt; 0) {
            register_shutdown_function('aurun_xp_refresh_post_metrics_after_shutdown', $pid, 'author_change');
        }
    }
}

function aurun_xp_refresh_post_metrics_after_shutdown($pid, $reason = '')
{
    $pid = (int) $pid;
    if ($pid &lt;= 0) {
        return;
    }

    if (aurun_xp_guard_once($pid, 'shutdown_update')) {
        aurun_xp_apply_post_change($pid, 'shutdown_update');
    }
}

function aurun_xp_get_stats_cache_for_update()
{
    global $cache;

    $stats = $cache-&gt;read('aurun_xp_stats');
    if (!is_array($stats)) {
        aurun_xp_rebuild_all();
        $stats = $cache-&gt;read('aurun_xp_stats');
    }

    return is_array($stats) ? $stats : [];
}

function aurun_xp_write_stats_cache(array $stats)
{
    global $cache;

    $cache-&gt;update('aurun_xp_stats', $stats);
}

function aurun_xp_refresh_top_player_cache(array &amp;$stats = null)
{
    if ($stats === null) {
        $stats = aurun_xp_get_stats_cache_for_update();
    }

    $topPlayer = aurun_xp_fetch_top_player();
    $stats['xp_top_glory_uid'] = (int) ($topPlayer['uid'] ?? 0);
    $stats['xp_top_glory_value'] = number_format((float) ($topPlayer['xp_glory_total'] ?? 0), 2, '.', '');

    return $stats;
}

function aurun_xp_recount_longest_post()
{
    global $db;

    $longestPost = [
        'pid' =&gt; 0,
        'tid' =&gt; 0,
        'uid' =&gt; 0,
        'subject' =&gt; '',
        'dateline' =&gt; 0,
        'words' =&gt; 0,
    ];

    $query = $db-&gt;query(
        &quot;SELECT p.pid, p.tid, p.uid, p.subject, p.dateline, p.xp_words
         FROM &quot; . TABLE_PREFIX . &quot;posts p
         LEFT JOIN &quot; . TABLE_PREFIX . &quot;threads t ON (t.tid = p.tid)
         WHERE p.visible = 1
           AND t.visible = 1
           AND p.fid IN (&quot; . aurun_xp_sql_id_list(aurun_xp_get_config()['scored_forums']) . &quot;)
         ORDER BY p.xp_words DESC, p.pid ASC
         LIMIT 1&quot;
    );

    if ($query) {
        $row = $db-&gt;fetch_array($query);
        if ($row) {
            $longestPost = [
                'pid' =&gt; (int) $row['pid'],
                'tid' =&gt; (int) $row['tid'],
                'uid' =&gt; (int) $row['uid'],
                'subject' =&gt; (string) $row['subject'],
                'dateline' =&gt; (int) $row['dateline'],
                'words' =&gt; (int) $row['xp_words'],
            ];
        }
    }

    return $longestPost;
}

function aurun_xp_refresh_longest_post_cache(array &amp;$stats, $pid, $wordCount, $isCandidate)
{
    $currentPid = (int) ($stats['xp_longest_post_pid'] ?? 0);
    $currentWords = (int) ($stats['xp_longest_post_words'] ?? 0);

    if ($isCandidate &amp;&amp; (int) $wordCount &gt; $currentWords) {
        $post = aurun_xp_get_post_snapshot($pid);
        $stats['xp_longest_post_pid'] = (int) $pid;
        $stats['xp_longest_post_words'] = (int) $wordCount;
        $stats['xp_longest_post_tid'] = (int) ($post['tid'] ?? 0);
        $stats['xp_longest_post_uid'] = (int) ($post['uid'] ?? 0);
        $stats['xp_longest_post_subject'] = (string) ($post['subject'] ?? '');
        $stats['xp_longest_post_dateline'] = (int) ($post['dateline'] ?? 0);

        return $stats;
    }

    if ($currentPid === (int) $pid &amp;&amp; (!$isCandidate || (int) $wordCount &lt; $currentWords)) {
        $longestPost = aurun_xp_recount_longest_post();
        $stats['xp_longest_post_pid'] = $longestPost['pid'];
        $stats['xp_longest_post_words'] = $longestPost['words'];
        $stats['xp_longest_post_tid'] = $longestPost['tid'];
        $stats['xp_longest_post_uid'] = $longestPost['uid'];
        $stats['xp_longest_post_subject'] = $longestPost['subject'];
        $stats['xp_longest_post_dateline'] = $longestPost['dateline'];
    }

    return $stats;
}

function aurun_xp_adjust_user_glory_total($uid, $delta)
{
    global $db;

    $uid = (int) $uid;
    $delta = round((float) $delta, 2);

    if ($uid &lt;= 0 || abs($delta) &lt; 0.01) {
        return false;
    }

    $user = aurun_xp_get_user_snapshot($uid);
    if (!$user) {
        return false;
    }

    $newTotal = round(max(0, (float) $user['xp_glory_total'] + $delta), 2);

    $db-&gt;update_query('users', [
        'xp_glory_total' =&gt; number_format($newTotal, 2, '.', ''),
    ], 'uid=' . $uid);

    if (!isset($GLOBALS['aurun_xp_user_snapshot_cache'])) {
        $GLOBALS['aurun_xp_user_snapshot_cache'] = [];
    }
    if ($user) {
        $user['xp_glory_total'] = number_format($newTotal, 2, '.', '');
        $GLOBALS['aurun_xp_user_snapshot_cache'][$uid] = $user;
    }

    return true;
}

function aurun_xp_accountswitcher_author_changed($pid, $oldUid, $newUid)
{
    $pid = (int) $pid;
    $oldUid = (int) $oldUid;
    $newUid = (int) $newUid;

    if ($pid &lt;= 0 || $oldUid &lt;= 0 || $newUid &lt;= 0 || $oldUid === $newUid) {
        return false;
    }

    $post = aurun_xp_get_post_snapshot($pid);
    if (!$post) {
        return false;
    }

    $isVisible = ((int) $post['visible'] === 1 &amp;&amp; (int) ($post['threadvisible'] ?? 1) === 1);
    $glory = round((float) ($post['xp_glory'] ?? 0), 2);

    if (!$isVisible || $glory &lt;= 0) {
        return true;
    }

    aurun_xp_adjust_user_glory_total($oldUid, -$glory);
    aurun_xp_adjust_user_glory_total($newUid, $glory);

    $stats = aurun_xp_get_stats_cache_for_update();
    aurun_xp_refresh_top_player_cache($stats);
    aurun_xp_write_stats_cache($stats);

    return true;
}

function aurun_xp_refresh_post_metrics($pid)
{
    global $db;

    $post = aurun_xp_get_post_snapshot($pid);
    if (!$post) {
        return;
    }

    $user = aurun_xp_get_user_snapshot((int) $post['uid']);
    $wordCount = aurun_xp_count_words($post['message']);
    $glory = aurun_xp_calculate_glory((int) $post['fid'], (int) ($user['usergroup'] ?? 0), $wordCount);

    $db-&gt;update_query('posts', [
        'xp_words' =&gt; $wordCount,
        'xp_glory' =&gt; number_format($glory, 2, '.', ''),
    ], 'pid=' . (int) $pid);
}

function aurun_xp_apply_post_change($pid, $context = 'update_post', array $options = [])
{
    global $db;

    $pid = (int) $pid;
    if ($pid &lt;= 0) {
        return false;
    }

    $post = aurun_xp_get_post_snapshot($pid);
    if (!$post) {
        return false;
    }

    $isInsert = in_array($context, ['insert_post', 'insert_thread'], true);
    $oldWords = (int) ($options['old_words'] ?? ($isInsert ? 0 : ($post['xp_words'] ?? 0)));
    $oldGlory = round((float) ($options['old_glory'] ?? ($isInsert ? 0 : ($post['xp_glory'] ?? 0))), 2);
    $oldVisible = (int) ($options['old_visible'] ?? ($isInsert ? 0 : ($post['visible'] ?? 0)));
    $oldThreadVisible = (int) ($options['old_threadvisible'] ?? ($isInsert ? 0 : ($post['threadvisible'] ?? 0)));
    $oldUid = (int) ($options['old_uid'] ?? ($post['uid'] ?? 0));

    $user = aurun_xp_get_user_snapshot((int) $post['uid']);
    $newWords = aurun_xp_count_words($post['message']);
    $newGlory = aurun_xp_calculate_glory((int) $post['fid'], (int) ($user['usergroup'] ?? 0), $newWords);

    $db-&gt;update_query('posts', [
        'xp_words' =&gt; $newWords,
        'xp_glory' =&gt; number_format($newGlory, 2, '.', ''),
    ], 'pid=' . $pid);

    $newVisible = ((int) $post['visible'] === 1 &amp;&amp; (int) ($post['threadvisible'] ?? 1) === 1);
    $oldVisibleCounted = ($oldVisible === 1 &amp;&amp; $oldThreadVisible === 1);
    $oldContribution = $oldVisibleCounted ? $oldGlory : 0.00;
    $newContribution = $newVisible ? $newGlory : 0.00;

    if ($oldUid === (int) $post['uid']) {
        $delta = round($newContribution - $oldContribution, 2);
        if (abs($delta) &gt;= 0.01) {
            aurun_xp_adjust_user_glory_total((int) $post['uid'], $delta);
        }
    } else {
        if ($oldContribution &gt; 0) {
            aurun_xp_adjust_user_glory_total($oldUid, -$oldContribution);
        }
        if ($newContribution &gt; 0) {
            aurun_xp_adjust_user_glory_total((int) $post['uid'], $newContribution);
        }
    }

    $stats = aurun_xp_get_stats_cache_for_update();
    $stats['xp_total_glory'] = number_format(round((float) ($stats['xp_total_glory'] ?? 0) + ($newContribution - $oldContribution), 2), 2, '.', '');

    if ($context === 'insert_post' &amp;&amp; $newVisible &amp;&amp; aurun_xp_is_scored_forum((int) $post['fid'])) {
        $stats['xp_rpg_posts_total'] = (int) ($stats['xp_rpg_posts_total'] ?? 0) + 1;
    } elseif ($context === 'insert_thread' &amp;&amp; $newVisible &amp;&amp; aurun_xp_is_scored_forum((int) $post['fid'])) {
        $stats['xp_rpg_posts_total'] = (int) ($stats['xp_rpg_posts_total'] ?? 0) + 1;
        $stats['xp_rpg_threads_total'] = (int) ($stats['xp_rpg_threads_total'] ?? 0) + 1;
    }

    $isLongestCandidate = $newVisible &amp;&amp; aurun_xp_is_scored_forum((int) $post['fid']);
    aurun_xp_refresh_longest_post_cache($stats, $pid, $newWords, $isLongestCandidate);
    aurun_xp_refresh_top_player_cache($stats);
    $stats['rebuilt_at'] = TIME_NOW;
    aurun_xp_write_stats_cache($stats);

    return true;
}

function aurun_xp_capture_post_delete_start($pid)
{
    global $cache;

    $cache-&gt;update('aurun_xp_delete_snapshot', [
        'type' =&gt; 'post',
        'pid' =&gt; (int) $pid,
        'updated_at' =&gt; TIME_NOW,
    ]);

    return $pid;
}

function aurun_xp_capture_thread_delete_start($tid)
{
    global $cache;

    $cache-&gt;update('aurun_xp_delete_snapshot', [
        'type' =&gt; 'thread',
        'tid' =&gt; (int) $tid,
        'updated_at' =&gt; TIME_NOW,
    ]);

    return $tid;
}

function aurun_xp_mark_dirty_event($payload = null)
{
    aurun_xp_mark_dirty(true, 'moderation');

    return $payload;
}

function aurun_xp_maybe_run_dirty_rebuild()
{
    global $cache;
    static $running = false;

    if ($running) {
        return;
    }

    $state = $cache-&gt;read('aurun_xp_dirty');
    if (!is_array($state) || empty($state['dirty'])) {
        return;
    }

    if (!empty($state['rebuilding'])) {
        return;
    }

    $running = true;
    aurun_xp_set_rebuilding_flag(true);
    aurun_xp_rebuild_all();
    $running = false;
}

function aurun_xp_rebuild_all()
{
    global $db, $cache;

    aurun_xp_ensure_schema();

    $db-&gt;write_query('UPDATE ' . TABLE_PREFIX . &quot;users SET xp_glory_total='0.00'&quot;);

    $userGroups = [];
    $query = $db-&gt;simple_select('users', 'uid,usergroup');
    while ($user = $db-&gt;fetch_array($query)) {
        $userGroups[(int) $user['uid']] = (int) $user['usergroup'];
    }

    $activeGloryByUser = [];
    $totalGlory = 0.00;
    $rpgPostsTotal = 0;
    $longestPost = [
        'pid' =&gt; 0,
        'tid' =&gt; 0,
        'uid' =&gt; 0,
        'subject' =&gt; '',
        'dateline' =&gt; 0,
        'words' =&gt; 0,
    ];

    $postsQuery = $db-&gt;query(
        &quot;SELECT p.pid, p.tid, p.uid, p.fid, p.message, p.subject, p.visible, p.dateline,
                t.visible AS threadvisible
         FROM &quot; . TABLE_PREFIX . &quot;posts p
         LEFT JOIN &quot; . TABLE_PREFIX . &quot;threads t ON (t.tid = p.tid)
         ORDER BY p.pid ASC&quot;
    );

    while ($post = $db-&gt;fetch_array($postsQuery)) {
        $uid = (int) $post['uid'];
        $wordCount = aurun_xp_count_words($post['message']);
        $glory = aurun_xp_calculate_glory((int) $post['fid'], (int) ($userGroups[$uid] ?? 0), $wordCount);

        $db-&gt;update_query('posts', [
            'xp_words' =&gt; $wordCount,
            'xp_glory' =&gt; number_format($glory, 2, '.', ''),
        ], 'pid=' . (int) $post['pid']);

        $isVisible = ((int) $post['visible'] === 1 &amp;&amp; (int) $post['threadvisible'] === 1);
        if (!$isVisible) {
            continue;
        }

        if (aurun_xp_is_scored_forum((int) $post['fid'])) {
            ++$rpgPostsTotal;

            if ($wordCount &gt; $longestPost['words']) {
                $longestPost = [
                    'pid' =&gt; (int) $post['pid'],
                    'tid' =&gt; (int) $post['tid'],
                    'uid' =&gt; $uid,
                    'subject' =&gt; (string) $post['subject'],
                    'dateline' =&gt; (int) $post['dateline'],
                    'words' =&gt; $wordCount,
                ];
            }
        }

        if ($glory &gt; 0) {
            $activeGloryByUser[$uid] = round(($activeGloryByUser[$uid] ?? 0) + $glory, 2);
            $totalGlory = round($totalGlory + $glory, 2);
        }
    }

    foreach ($activeGloryByUser as $uid =&gt; $gloryTotal) {
        $db-&gt;update_query('users', [
            'xp_glory_total' =&gt; number_format($gloryTotal, 2, '.', ''),
        ], 'uid=' . (int) $uid);
    }

    $rpgThreadsTotal = 0;
    $threadQuery = $db-&gt;query(
        &quot;SELECT COUNT(*) AS total
         FROM &quot; . TABLE_PREFIX . &quot;threads
         WHERE fid IN (&quot; . aurun_xp_sql_id_list(aurun_xp_get_config()['scored_forums']) . &quot;)
           AND visible = 1
           AND closed NOT LIKE 'moved|%'&quot;
    );
    if ($threadQuery) {
        $rpgThreadsTotal = (int) $db-&gt;fetch_field($threadQuery, 'total');
    }

    $topPlayer = aurun_xp_fetch_top_player();

    $cache-&gt;update('aurun_xp_stats', [
        'xp_total_glory' =&gt; number_format($totalGlory, 2, '.', ''),
        'xp_rpg_posts_total' =&gt; $rpgPostsTotal,
        'xp_rpg_threads_total' =&gt; $rpgThreadsTotal,
        'xp_longest_post_pid' =&gt; $longestPost['pid'],
        'xp_longest_post_words' =&gt; $longestPost['words'],
        'xp_longest_post_tid' =&gt; $longestPost['tid'],
        'xp_longest_post_uid' =&gt; $longestPost['uid'],
        'xp_longest_post_subject' =&gt; $longestPost['subject'],
        'xp_longest_post_dateline' =&gt; $longestPost['dateline'],
        'xp_top_glory_uid' =&gt; (int) ($topPlayer['uid'] ?? 0),
        'xp_top_glory_value' =&gt; number_format((float) ($topPlayer['xp_glory_total'] ?? 0), 2, '.', ''),
        'rebuilt_at' =&gt; TIME_NOW,
    ]);

    aurun_xp_set_rebuilding_flag(false);
    aurun_xp_mark_dirty(false, 'rebuilt');
}

function aurun_xp_sql_id_list(array $ids)
{
    $ids = array_map('intval', $ids);
    $ids = array_filter($ids, static function ($id) {
        return $id &gt; 0;
    });

    if (empty($ids)) {
        return '0';
    }

    return implode(',', $ids);
}

function aurun_xp_fetch_top_player($limit = 1)
{
    global $db;

    $limit = (int) max(1, $limit);
    $config = aurun_xp_get_config();
    $inactiveGroups = aurun_xp_sql_id_list($config['inactive_groups']);
    $inactiveClause = $inactiveGroups !== '0' ? &quot; AND usergroup NOT IN (&quot; . $inactiveGroups . &quot;)&quot; : '';

    $query = $db-&gt;query(
        &quot;SELECT uid, username, usergroup, displaygroup, xp_glory_total
         FROM &quot; . TABLE_PREFIX . &quot;users
         WHERE uid &lt;&gt; 3
           AND xp_glory_total &gt;= '0.01'&quot; . $inactiveClause . &quot;
         ORDER BY xp_glory_total DESC, username ASC
         LIMIT &quot; . $limit
    );

    if ($limit === 1) {
        $user = $db-&gt;fetch_array($query);

        return $user ?: null;
    }

    $users = [];
    while ($user = $db-&gt;fetch_array($query)) {
        $users[] = $user;
    }

    return $users;
}

function aurun_xp_get_ranked_users($limit = 0)
{
    global $db;

    $config = aurun_xp_get_config();
    $inactiveGroups = aurun_xp_sql_id_list($config['inactive_groups']);
    $inactiveClause = $inactiveGroups !== '0' ? &quot; AND usergroup NOT IN (&quot; . $inactiveGroups . &quot;)&quot; : '';
    $sqlLimit = $limit &gt; 0 ? ' LIMIT ' . (int) $limit : '';
    $query = $db-&gt;query(
        &quot;SELECT uid, username, usergroup, displaygroup, xp_glory_total
         FROM &quot; . TABLE_PREFIX . &quot;users
         WHERE xp_glory_total &gt;= '0.01'
           AND uid &lt;&gt; 3&quot; . $inactiveClause . &quot;
         ORDER BY xp_glory_total DESC, username ASC&quot; . $sqlLimit
    );

    $users = [];
    while ($user = $db-&gt;fetch_array($query)) {
        $users[] = $user;
    }

    return $users;
}

function aurun_xp_get_cached_stats()
{
    global $cache;

    aurun_xp_maybe_run_dirty_rebuild();

    $stats = $cache-&gt;read('aurun_xp_stats');

    return is_array($stats) ? $stats : [];
}

function aurun_xp_crown_html($uid)
{
    $stats = aurun_xp_get_cached_stats();

    if ((int) $uid &gt; 0 &amp;&amp; (int) ($stats['xp_top_glory_uid'] ?? 0) === (int) $uid) {
        return '&lt;span class=&quot;aurunxp-crown&quot; title=&quot;Ruhmreichster Charakter&quot;&gt;👑&lt;/span&gt;';
    }

    return '';
}

function aurun_xp_global_start()
{
    global $mybb;

    aurun_xp_maybe_run_dirty_rebuild();

    if ((int) ($mybb-&gt;user['uid'] ?? 0) &lt;= 0) {
        return;
    }

    $mybb-&gt;user['aurunxp_glory'] = aurun_xp_format_glory((float) ($mybb-&gt;user['xp_glory_total'] ?? 0));
    $mybb-&gt;user['aurunxp_crown'] = aurun_xp_crown_html((int) $mybb-&gt;user['uid']);
}

function aurun_xp_index_start()
{
    global $aurunxp_total_glory, $aurunxp_rpg_posts_total, $aurunxp_rpg_threads_total, $aurunxp_top_list, $aurunxp_longest_post;

    $stats = aurun_xp_get_cached_stats();
    $aurunxp_total_glory = aurun_xp_format_glory((float) ($stats['xp_total_glory'] ?? 0));
    $aurunxp_rpg_posts_total = my_number_format((int) ($stats['xp_rpg_posts_total'] ?? 0));
    $aurunxp_rpg_threads_total = my_number_format((int) ($stats['xp_rpg_threads_total'] ?? 0));

    $topList = [];
    foreach (aurun_xp_fetch_top_player(10) as $user) {
        $topList[] = build_profile_link(
            format_name(htmlspecialchars_uni($user['username']), (int) $user['usergroup'], (int) $user['displaygroup']),
            (int) $user['uid']
        ) . ' (' . aurun_xp_format_glory((float) $user['xp_glory_total']) . ')';
    }
    $aurunxp_top_list = implode(', ', $topList);

    $aurunxp_longest_post = '';
    if (!empty($stats['xp_longest_post_pid'])) {
        $author = aurun_xp_get_user_snapshot((int) $stats['xp_longest_post_uid']);
        $authorLink = $author ? build_profile_link(htmlspecialchars_uni($author['username']), (int) $author['uid']) : 'Unbekannt';
        $title = htmlspecialchars_uni($stats['xp_longest_post_subject'] ?: ('Beitrag #' . (int) $stats['xp_longest_post_pid']));
        $aurunxp_longest_post = '&lt;a href=&quot;' . get_post_link((int) $stats['xp_longest_post_pid']) . '&quot;&gt;' . $title . '&lt;/a&gt; | ' .
            $authorLink . ' | ' .
            my_number_format((int) $stats['xp_longest_post_words']) . ' Wörter | ' .
            my_date('relative', (int) $stats['xp_longest_post_dateline']);
    }
}

function aurun_xp_stats_start()
{
    global $aurunxp_stats_rpg_posts_total, $aurunxp_stats_rpg_threads_total, $aurunxp_stats_longest_post, $aurunxp_stats_top_user, $aurunxp_stats_top_ten;

    $stats = aurun_xp_get_cached_stats();
    $aurunxp_stats_rpg_posts_total = my_number_format((int) ($stats['xp_rpg_posts_total'] ?? 0));
    $aurunxp_stats_rpg_threads_total = my_number_format((int) ($stats['xp_rpg_threads_total'] ?? 0));
    $aurunxp_stats_longest_post = my_number_format((int) ($stats['xp_longest_post_words'] ?? 0));

    $topUser = aurun_xp_fetch_top_player();
    $aurunxp_stats_top_user = '';
    if ($topUser) {
        $aurunxp_stats_top_user = build_profile_link(htmlspecialchars_uni($topUser['username']), (int) $topUser['uid']) .
            ' (' . aurun_xp_format_glory((float) $topUser['xp_glory_total']) . ')';
        if (aurun_xp_crown_html((int) $topUser['uid']) !== '') {
            $aurunxp_stats_top_user .= ' ' . aurun_xp_crown_html((int) $topUser['uid']);
        }
    }

    $topTen = [];
    foreach (aurun_xp_fetch_top_player(10) as $user) {
        $entry = build_profile_link(htmlspecialchars_uni($user['username']), (int) $user['uid']) .
            ' (' . aurun_xp_format_glory((float) $user['xp_glory_total']) . ')';
        $topTen[] = $entry;
    }
    $aurunxp_stats_top_ten = implode(', ', $topTen);
}

function aurun_xp_member_profile_end()
{
    global $memprofile;

    $memprofile['aurunxp_glory'] = aurun_xp_format_glory((float) ($memprofile['xp_glory_total'] ?? 0));
    $memprofile['aurunxp_crown'] = aurun_xp_crown_html((int) ($memprofile['uid'] ?? 0));
}

function aurun_xp_memberlist_user(&amp;$user)
{
    $user['aurunxp_glory'] = aurun_xp_format_glory((float) ($user['xp_glory_total'] ?? 0));
    $user['aurunxp_crown'] = aurun_xp_crown_html((int) ($user['uid'] ?? 0));
}

function aurun_xp_postbit(&amp;$post)
{
    $post['aurunxp_words'] = my_number_format((int) ($post['xp_words'] ?? 0));
    $post['aurunxp_glory'] = aurun_xp_format_glory((float) ($post['xp_glory'] ?? 0));

    if (isset($post['xp_glory_total'])) {
        $post['aurunxp_user_glory'] = aurun_xp_format_glory((float) $post['xp_glory_total']);
    } else {
        $author = aurun_xp_get_user_snapshot((int) ($post['uid'] ?? 0));
        $post['aurunxp_user_glory'] = aurun_xp_format_glory((float) ($author['xp_glory_total'] ?? 0));
    }

    $post['aurunxp_crown'] = aurun_xp_crown_html((int) ($post['uid'] ?? 0));
}</code></pre>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[plugin mybb a clear news not rolling to left]]></title>
			<link>https://community.mybb.com/thread-245058.html</link>
			<pubDate>Sat, 21 Mar 2026 19:14:50 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://community.mybb.com/member.php?action=profile&uid=126708">Josemichele</a>]]></dc:creator>
			<guid isPermaLink="false">https://community.mybb.com/thread-245058.html</guid>
			<description><![CDATA[Hi<br />
my plugin mybb a clear news not rolling to left<br />
<br />
please anybody help me<br />
<br />
thank you !]]></description>
			<content:encoded><![CDATA[Hi<br />
my plugin mybb a clear news not rolling to left<br />
<br />
please anybody help me<br />
<br />
thank you !]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Enhanced Account Switcher (by doylecc)]]></title>
			<link>https://community.mybb.com/thread-245049.html</link>
			<pubDate>Fri, 20 Mar 2026 15:29:58 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://community.mybb.com/member.php?action=profile&uid=160634">Allvater</a>]]></dc:creator>
			<guid isPermaLink="false">https://community.mybb.com/thread-245049.html</guid>
			<description><![CDATA[Is here anyone that is using that plugin? (or maybe doylecc himself)<br />
<br />
<br />
i have a little issue<br />
<br />
the list (link/switch) that is shown in postbit is NOT showing in announcements! <br />
<br />
anywhere else its working<br />
<br />
the total amount of posts of all attached accounts IS showing up in announcements...but the list itself not<br />
<br />
<br />
is this a main issue of the plugin, or do i have made some edits or other plugins, that cause this issue?<br />
<br />
<br />
thanks a lot for any suggestion, how to fix that...]]></description>
			<content:encoded><![CDATA[Is here anyone that is using that plugin? (or maybe doylecc himself)<br />
<br />
<br />
i have a little issue<br />
<br />
the list (link/switch) that is shown in postbit is NOT showing in announcements! <br />
<br />
anywhere else its working<br />
<br />
the total amount of posts of all attached accounts IS showing up in announcements...but the list itself not<br />
<br />
<br />
is this a main issue of the plugin, or do i have made some edits or other plugins, that cause this issue?<br />
<br />
<br />
thanks a lot for any suggestion, how to fix that...]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[it is not working properly , Like Reactions System]]></title>
			<link>https://community.mybb.com/thread-245017.html</link>
			<pubDate>Sun, 15 Mar 2026 10:32:18 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://community.mybb.com/member.php?action=profile&uid=159863">Pavaroty</a>]]></dc:creator>
			<guid isPermaLink="false">https://community.mybb.com/thread-245017.html</guid>
			<description><![CDATA[<a href="https://community.mybb.com/mods.php?action=view&amp;pid=1684" target="_blank" rel="noopener" class="mycode_url">https://community.mybb.com/mods.php?acti...w&amp;pid=1684</a><br />
<br />
I download the plugin but it doesn't work properly, when I want to see who gave a Like, I get this error<br />
<br />
<br />
<a href="https://postimg.cc/hzv2qPqM" target="_blank" rel="noopener" class="mycode_url">https://postimg.cc/hzv2qPqM</a><br />
<br />
<br />
I am using MyBB 1.8.5 and PHP version 7.1 and I have the Libray , 13 plugin installed.<br />
<br />
please help me<br />
<br />
thank you very much]]></description>
			<content:encoded><![CDATA[<a href="https://community.mybb.com/mods.php?action=view&amp;pid=1684" target="_blank" rel="noopener" class="mycode_url">https://community.mybb.com/mods.php?acti...w&amp;pid=1684</a><br />
<br />
I download the plugin but it doesn't work properly, when I want to see who gave a Like, I get this error<br />
<br />
<br />
<a href="https://postimg.cc/hzv2qPqM" target="_blank" rel="noopener" class="mycode_url">https://postimg.cc/hzv2qPqM</a><br />
<br />
<br />
I am using MyBB 1.8.5 and PHP version 7.1 and I have the Libray , 13 plugin installed.<br />
<br />
please help me<br />
<br />
thank you very much]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Blank Plugins Page]]></title>
			<link>https://community.mybb.com/thread-244974.html</link>
			<pubDate>Wed, 04 Mar 2026 02:32:23 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://community.mybb.com/member.php?action=profile&uid=126154">stack</a>]]></dc:creator>
			<guid isPermaLink="false">https://community.mybb.com/thread-244974.html</guid>
			<description><![CDATA[Hello there! I have found a plethora of german plugins that are amazing and I am working on translating them. Most of them have gone great, so I'm inclined to say this isn't a translation error and is something in the inc/plugin.php file. When I install the plugin to my FTP, my admin &gt; plugins page turns to this.<br />
<br />
When I remove that specific file from the inc/plugins, the ACP works again.<br />
There is an _info, _install, _uninstall, and _deactivate option in the plugin, which I know caused issues in the past with other plugins. I'm not totally sure what my issue is. <br />
<br />
I attached the inc/plugins file for y'all to look at. Thank you!<br /><!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://community.mybb.com/images/attachtypes/image.gif" title="PNG Image" border="0" alt=".png" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=48713" target="_blank" title="">sgdsgsgs.png</a> (Size: 44.55 KB / Downloads: 42)
<!-- end: postbit_attachments_attachment --><br /><!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://community.mybb.com/images/attachtypes/php.gif" title="PHP File" border="0" alt=".php" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=48714" target="_blank" title="">questsystem.php.php</a> (Size: 130.89 KB / Downloads: 17)
<!-- end: postbit_attachments_attachment -->]]></description>
			<content:encoded><![CDATA[Hello there! I have found a plethora of german plugins that are amazing and I am working on translating them. Most of them have gone great, so I'm inclined to say this isn't a translation error and is something in the inc/plugin.php file. When I install the plugin to my FTP, my admin &gt; plugins page turns to this.<br />
<br />
When I remove that specific file from the inc/plugins, the ACP works again.<br />
There is an _info, _install, _uninstall, and _deactivate option in the plugin, which I know caused issues in the past with other plugins. I'm not totally sure what my issue is. <br />
<br />
I attached the inc/plugins file for y'all to look at. Thank you!<br /><!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://community.mybb.com/images/attachtypes/image.gif" title="PNG Image" border="0" alt=".png" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=48713" target="_blank" title="">sgdsgsgs.png</a> (Size: 44.55 KB / Downloads: 42)
<!-- end: postbit_attachments_attachment --><br /><!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://community.mybb.com/images/attachtypes/php.gif" title="PHP File" border="0" alt=".php" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=48714" target="_blank" title="">questsystem.php.php</a> (Size: 130.89 KB / Downloads: 17)
<!-- end: postbit_attachments_attachment -->]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Plugin isn't showing up within Configuration tab under Plugins]]></title>
			<link>https://community.mybb.com/thread-244957.html</link>
			<pubDate>Sun, 01 Mar 2026 04:44:54 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://community.mybb.com/member.php?action=profile&uid=160767">godsavethequeen</a>]]></dc:creator>
			<guid isPermaLink="false">https://community.mybb.com/thread-244957.html</guid>
			<description><![CDATA[So I added the Enhanced Account Switcher to my root file and it looks like everything processed through with no issues. <br />
I even double checked the plugin folder and it showed up there with no issues.<br />
So when I go into my admin account and look under Configuration, I don't see the Enhanced Account Switcher show up. I only see 'Hello World' under Inactive Plugins. I've double checked my files in both FileZilla and CoreFTP. I've also re-read the steps for the installation. <br />
<br />
I'm not sure what else I'm possibly missing now.  <img src="https://community.mybb.com/images/smilies/undecided.gif" alt="Undecided" title="Undecided" class="smilie smilie_28" />]]></description>
			<content:encoded><![CDATA[So I added the Enhanced Account Switcher to my root file and it looks like everything processed through with no issues. <br />
I even double checked the plugin folder and it showed up there with no issues.<br />
So when I go into my admin account and look under Configuration, I don't see the Enhanced Account Switcher show up. I only see 'Hello World' under Inactive Plugins. I've double checked my files in both FileZilla and CoreFTP. I've also re-read the steps for the installation. <br />
<br />
I'm not sure what else I'm possibly missing now.  <img src="https://community.mybb.com/images/smilies/undecided.gif" alt="Undecided" title="Undecided" class="smilie smilie_28" />]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[DVZ Shoutbox Not working]]></title>
			<link>https://community.mybb.com/thread-244920.html</link>
			<pubDate>Fri, 20 Feb 2026 22:59:31 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://community.mybb.com/member.php?action=profile&uid=160697">crazytuna</a>]]></dc:creator>
			<guid isPermaLink="false">https://community.mybb.com/thread-244920.html</guid>
			<description><![CDATA[I installed DVZ shoutbox, edited my index page and when you enter a message it does not show up in shoutbox.]]></description>
			<content:encoded><![CDATA[I installed DVZ shoutbox, edited my index page and when you enter a message it does not show up in shoutbox.]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Edit signature unusable with Darkmode Switch on myBB 1.8]]></title>
			<link>https://community.mybb.com/thread-244908.html</link>
			<pubDate>Wed, 18 Feb 2026 08:01:29 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://community.mybb.com/member.php?action=profile&uid=160677">porcelaine</a>]]></dc:creator>
			<guid isPermaLink="false">https://community.mybb.com/thread-244908.html</guid>
			<description><![CDATA[Hello everyone<br />
<br />
I've encountered an issue with the darkmode switch when trying to edit signatures on the standard theme. It seems to make the feature unusable because the icons for the text editor are missing? Does anyone know a solution for this? I doublechecked that I've installed the plugin correctly and I tried to look into the css file but I'm kind of at a loss. Thank you very much for your time.<br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://community.mybb.com/images/attachtypes/image.gif" title="PNG Image" border="0" alt=".png" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=48652" target="_blank" title="">attach.png</a> (Size: 21.99 KB / Downloads: 46)
<!-- end: postbit_attachments_attachment -->]]></description>
			<content:encoded><![CDATA[Hello everyone<br />
<br />
I've encountered an issue with the darkmode switch when trying to edit signatures on the standard theme. It seems to make the feature unusable because the icons for the text editor are missing? Does anyone know a solution for this? I doublechecked that I've installed the plugin correctly and I tried to look into the css file but I'm kind of at a loss. Thank you very much for your time.<br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://community.mybb.com/images/attachtypes/image.gif" title="PNG Image" border="0" alt=".png" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=48652" target="_blank" title="">attach.png</a> (Size: 21.99 KB / Downloads: 46)
<!-- end: postbit_attachments_attachment -->]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Enhanced Account Switcher - Accounts without permission]]></title>
			<link>https://community.mybb.com/thread-244907.html</link>
			<pubDate>Tue, 17 Feb 2026 21:29:25 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://community.mybb.com/member.php?action=profile&uid=160672">mikaelvos</a>]]></dc:creator>
			<guid isPermaLink="false">https://community.mybb.com/thread-244907.html</guid>
			<description><![CDATA[I just installed the advanced account switcher with no real issues (latest version as per <a href="https://doylecc.altervista.org/bb/downloads.php?dlid=26&amp;cat=2" target="_blank" rel="noopener" class="mycode_url">the dev's latest release</a>) but am for some reason repeatedly receiving the error accounts are lacking permission. Both freshly-made accounts as well as preexisting accounts. Where can I update this? I've been digging around but can't figure it out.<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://community.mybb.com/images/attachtypes/image.gif" title="PNG Image" border="0" alt=".png" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=48650" target="_blank" title="">Screenshot 2026-02-17 221811.png</a> (Size: 32.59 KB / Downloads: 54)
<!-- end: postbit_attachments_attachment --><br />
<hr class="mycode_hr" />
Nevermind, rejoyce as I solve my own issue. <br />
The answer is found in <br />
users&amp;groups &gt; edit group &gt; miscellaneous &gt; enhanced account switcher (&gt; can use)]]></description>
			<content:encoded><![CDATA[I just installed the advanced account switcher with no real issues (latest version as per <a href="https://doylecc.altervista.org/bb/downloads.php?dlid=26&amp;cat=2" target="_blank" rel="noopener" class="mycode_url">the dev's latest release</a>) but am for some reason repeatedly receiving the error accounts are lacking permission. Both freshly-made accounts as well as preexisting accounts. Where can I update this? I've been digging around but can't figure it out.<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://community.mybb.com/images/attachtypes/image.gif" title="PNG Image" border="0" alt=".png" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=48650" target="_blank" title="">Screenshot 2026-02-17 221811.png</a> (Size: 32.59 KB / Downloads: 54)
<!-- end: postbit_attachments_attachment --><br />
<hr class="mycode_hr" />
Nevermind, rejoyce as I solve my own issue. <br />
The answer is found in <br />
users&amp;groups &gt; edit group &gt; miscellaneous &gt; enhanced account switcher (&gt; can use)]]></content:encoded>
		</item>
	</channel>
</rss>