Simple Machines Community Forum

Customizing SMF => Bridges and Integrations => Topic started by: IshanP on February 25, 2022, 12:45:04 AM

Title: Are there any plugins that change the personal messaging system?
Post by: IshanP on February 25, 2022, 12:45:04 AM
By making it more like other forum PMs systems like proboards's/XenForo's PM system?
Title: Re: Are there any plugins that change the personal messaging system?
Post by: Antechinus on February 25, 2022, 12:46:46 AM
It would make sense to describe how you want it to function. "Like something else" is not really a useful description. :)
Title: Re: Are there any plugins that change the personal messaging system?
Post by: Arantor on February 25, 2022, 03:08:23 AM
Not really, no, though I suspect if you found the configuration for conversation mode you might find it's at least part way there.

Getting towards something like XF's conversations (functionally: collections of messages with participants attached to the whole collection, rather than to each individual message) is quite the undertaking inside SMF.
Title: Re: Are there any plugins that change the personal messaging system?
Post by: Mike66 on February 25, 2022, 06:20:20 AM
SMF Packs does a conversations mod that works well in 2.0 but not 2.1.

I can't get it to work in 2.1
Title: Re: Are there any plugins that change the personal messaging system?
Post by: Mike66 on February 25, 2022, 01:25:07 PM
Quote from: Mike66 on February 25, 2022, 06:20:20 AMSMF Packs does a conversations mod that works well in 2.0 but not 2.1.

I can't get it to work in 2.1

Just to clarify this, I haven't managed to install the mod in 2.1, the SMF Packs Personal Conversations mod wants to install by emulating 2.0.

When I tried that I got Test Failed for Execute Modification in Sources/Subs-Post.php

Which says: (code) (find) (select):
// Send off a personal message.
function sendpm($recipients, $subject, $message, $store_outbox = false, $from = null, $pm_head = 0)

And: (code) (replace) (select) (expand):
// Send off a personal conversation.
function sendpm($recipients, $subject, $message, $options = false, $from = null, $pm_head = 0)
{
    global $scripturl, $txt, $user_info, $language;
    global $modSettings, $smcFunc, $context;
   
    // Check this one!
    if (!is_array($options))
        $options = array(
            'is_starred' => 0
        );

    // Make sure the PM language file is loaded, we might need something out of it.
    loadLanguage('PersonalMessage');

    $onBehalf = $from !== null;

    // Initialize log array.
    $log = array(
        'failed' => array(),
        'sent' => array()
    );

    if ($from === null)
        $from = array(
            'id' => $user_info['id'],
            'name' => $user_info['name'],
            'username' => $user_info['username']
        );
    // Probably not needed.  /me something should be of the typer.
    else
        $user_info['name'] = $from['name'];

    // This is the one that will go in their inbox.
    $htmlmessage = $smcFunc['htmlspecialchars']($message, ENT_QUOTES);
    $htmlsubject = $smcFunc['htmlspecialchars']($subject);
    preparsecode($htmlmessage);

    // Integrated PMs
    call_integration_hook('integrate_personal_message', array($recipients, $from['username'], $subject, $message));
   
    // Get a list of usernames and convert them to IDs.
    $usernames = array();
    foreach ($recipients as $rec_type => $rec)
    {
        foreach ($rec as $id => $member)
        {
            if (!is_numeric($recipients[$rec_type][$id]) && ($from['id'] != $user_info['id'] || $id != $user_info['id']))
            {
                $recipients[$rec_type][$id] = $smcFunc['strtolower'](trim(preg_replace('/[<>&"\'=\\\]/', '', $recipients[$rec_type][$id])));
                $usernames[$recipients[$rec_type][$id]] = 0;
            }
        }
    }
   
    if (!empty($usernames))
    {
        $request = $smcFunc['db_query']('pm_find_username', '
            SELECT id_member, member_name
            FROM {db_prefix}members
            WHERE ' . ($smcFunc['db_case_sensitive'] ? 'LOWER(member_name)' : 'member_name') . ' IN ({array_string:usernames})',
            array(
                'usernames' => array_keys($usernames),
            )
        );
        while ($row = $smcFunc['db_fetch_assoc']($request))
            if (isset($usernames[$smcFunc['strtolower']($row['member_name'])]))
                $usernames[$smcFunc['strtolower']($row['member_name'])] = $row['id_member'];
        $smcFunc['db_free_result']($request);

        // Replace the usernames with IDs. Drop usernames that couldn't be found.
        foreach ($recipients as $rec_type => $rec)
            foreach ($rec as $id => $member)
            {
                if (is_numeric($recipients[$rec_type][$id]))
                    continue;

                if (!empty($usernames[$member]))
                    $recipients[$rec_type][$id] = $usernames[$member];
                else
                {
                    $log['failed'][$id] = sprintf($txt['pm_error_user_not_found'], $recipients[$rec_type][$id]);
                    unset($recipients[$rec_type][$id]);
                }
            }
    }

    // Make sure there are no duplicate 'to' members.
    $recipients['bcc'] = !empty($recipients['bcc']) ? $recipients['bcc'] : array();
    $recipients['to'] = array_merge($recipients['to'], $recipients['bcc']);

    // Combine 'to' and 'bcc' recipients.
    $all_to = array_unique($recipients['to']);

    // Load the membergrounp message limits.
    //!!! Consider caching this?
    static $message_limit_cache = array();
    if (!allowedTo('moderate_forum') && empty($message_limit_cache))
    {
        $request = $smcFunc['db_query']('', '
            SELECT id_group, max_messages
            FROM {db_prefix}membergroups',
            array(
            )
        );
        while ($row = $smcFunc['db_fetch_assoc']($request))
            $message_limit_cache[$row['id_group']] = $row['max_messages'];
        $smcFunc['db_free_result']($request);
    }

    // Load the groups that are allowed to read PMs.
    $allowed_groups = array();
    $disallowed_groups = array();
    $request = $smcFunc['db_query']('', '
        SELECT id_group, add_deny
        FROM {db_prefix}permissions
        WHERE permission = {string:read_permission}',
        array(
            'read_permission' => 'pm_read',
        )
    );

    while ($row = $smcFunc['db_fetch_assoc']($request))
    {
        if (empty($row['add_deny']))
            $disallowed_groups[] = $row['id_group'];
        else
            $allowed_groups[] = $row['id_group'];
    }

    $smcFunc['db_free_result']($request);

    if (empty($modSettings['permission_enable_deny']))
        $disallowed_groups = array();

    $request = $smcFunc['db_query']('', '
        SELECT
            member_name, real_name, id_member, email_address, lngfile,
            pm_email_notify, instant_messages,' . (allowedTo('moderate_forum') ? ' 0' : '
            (pm_receive_from = {int:admins_only}' . (empty($modSettings['enable_buddylist']) ? '' : ' OR
            (pm_receive_from = {int:buddies_only} AND FIND_IN_SET({string:from_id}, buddy_list) = 0) OR
            (pm_receive_from = {int:not_on_ignore_list} AND FIND_IN_SET({string:from_id}, pm_ignore_list) != 0)') . ')') . ' AS ignored,
            FIND_IN_SET({string:from_id}, buddy_list) != 0 AS is_buddy, is_activated,
            additional_groups, id_group, id_post_group
        FROM {db_prefix}members
        WHERE id_member IN ({array_int:recipients})
        ORDER BY lngfile
        LIMIT {int:count_recipients}',
        array(
            'not_on_ignore_list' => 1,
            'buddies_only' => 2,
            'admins_only' => 3,
            'recipients' => $all_to,
            'count_recipients' => count($all_to),
            'from_id' => $from['id'],
        )
    );
    $notifications = array();
    while ($row = $smcFunc['db_fetch_assoc']($request))
    {
        // We need to know this members groups.
        $groups = explode(',', $row['additional_groups']);
        $groups[] = $row['id_group'];
        $groups[] = $row['id_post_group'];

        $message_limit = -1;
        // For each group see whether they've gone over their limit - assuming they're not an admin.
        if (!in_array(1, $groups))
        {
            foreach ($groups as $id)
            {
                if (isset($message_limit_cache[$id]) && $message_limit != 0 && $message_limit < $message_limit_cache[$id])
                    $message_limit = $message_limit_cache[$id];
            }

            // !!! This is currently removed, maybe we can limit the number of conversations?
            /*if ($message_limit > 0 && $message_limit <= $row['instant_messages'])
            {
                $log['failed'][$row['id_member']] = sprintf($txt['pm_error_data_limit_reached'], $row['real_name']);
                unset($all_to[array_search($row['id_member'], $all_to)]);
                continue;
            }*/

            // Do they have any of the allowed groups?
            if (count(array_intersect($allowed_groups, $groups)) == 0 || count(array_intersect($disallowed_groups, $groups)) != 0)
            {
                $log['failed'][$row['id_member']] = sprintf($txt['pm_error_user_cannot_read'], $row['real_name']);
                unset($all_to[array_search($row['id_member'], $all_to)]);
                continue;
            }
        }

        // Note that PostgreSQL can return a lowercase t/f for FIND_IN_SET
        if (!empty($row['ignored']) && $row['ignored'] != 'f' && $row['id_member'] != $from['id'])
        {
            $log['failed'][$row['id_member']] = sprintf($txt['pm_error_ignored_by_user'], $row['real_name']);
            unset($all_to[array_search($row['id_member'], $all_to)]);
            continue;
        }

        // If the receiving account is banned (>=10) or pending deletion (4), refuse to send the PM.
        if ($row['is_activated'] >= 10 || ($row['is_activated'] == 4 && !$user_info['is_admin']))
        {
            $log['failed'][$row['id_member']] = sprintf($txt['pm_error_user_cannot_read'], $row['real_name']);
            unset($all_to[array_search($row['id_member'], $all_to)]);
            continue;
        }

        // Send a notification, if enabled - taking the buddy list into account.
        if (!empty($row['email_address']) && ($row['pm_email_notify'] == 1 || ($row['pm_email_notify'] > 1 && (!empty($modSettings['enable_buddylist']) && $row['is_buddy']))) && $row['is_activated'] == 1 && $from['id'] != $row['id_member'])
            $notifications[empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile']][] = $row['email_address'];

        if ($from['id'] == $user_info['id'])
            $log['sent'][$row['id_member']] = sprintf(isset($txt['pm_successfully_sent']) ? $txt['pm_successfully_sent'] : '', $row['real_name']);
    }
    $smcFunc['db_free_result']($request);
   
    // Save this moment!
    $this_moment = time();

    // Insert the message itself and then grab the last insert id.
    if (empty($pm_head))
    {
        $smcFunc['db_insert']('',
            '{db_prefix}conversations',
            array(
                'title' => 'string-255', 'is_locked' => 'int', 'starter_name' => 'string-64',
                'start_date' => 'int', 'last_post' => 'int', 'starter' => 'int', 'allow_others' => 'int',
                'last_post_by' => 'int', 'last_post_name' => 'string-64', 'last_post_date' => 'int',
                'messages' => 'int', 'participants' => 'int'
            ),
            array(
                $htmlsubject, !empty($options['is_locked']) ? 1 : 0, $from['username'],
                $this_moment, 0, $from['id'], !empty($options['allow_others']) ? 1 : 0,
                $from['id'], $from['username'], $this_moment,
                1, (count($all_to) + 1)
            ),
            array('id_conversation')
        );
       
        $id_pm = $smcFunc['db_insert_id']('{db_prefix}conversations', 'id_conversation');
        $new_conversation = true;
    }
    else
    {
        $id_pm = $pm_head;
        $new_conversation = false;
       
        // Update it
        $smcFunc['db_query']('', '
        UPDATE {db_prefix}conversations
        SET messages = messages + 1
        WHERE id_conversation = {int:conversation}
        LIMIT 1',
            array(
                'conversation'    => $id_pm,
            )
        );
    }
   
    // Store it
    $context['id_conversation'] = $id_pm;
   
    // Now add the message!
    $smcFunc['db_insert']('',
        '{db_prefix}conversations_messages',
        array(
            'id_conversation' => 'int', 'id_member' => 'int', 'date' => 'int',
            'content' => 'string', 'real_name' => 'string-64'
        ),
        array(
            $id_pm, $from['id'], $this_moment,
            $message, $from['username']
        ),
        array('id_message')
    );
   
    $context['new_conversations_msg'] = $smcFunc['db_insert_id']('{db_prefix}conversations_messages', 'id_message');

    // Add the recipients.
    if ($new_conversation)
    {
        $insertRows = array(
            array($from['id'], $this_moment, !empty($options['is_starred']) ? 1 : 0, $id_pm, 0, 1, time())
        );
        foreach ($all_to as $to)
        {
            // Skip ourselves!
            if ($to != $from['id'])
                $insertRows[] = array($to, $this_moment, 0, $id_pm, 1, 1, 0);
        }

        $smcFunc['db_insert']('insert',
            '{db_prefix}conversations_participants',
            array(
                'id_member' => 'int', 'join_date' => 'int', 'starred' => 'int', 'id_conversation' => 'int',
                'is_unread' => 'int', 'is_participant' => 'int', 'last_view' => 'int',
            ),
            $insertRows,
            array('id_pm', 'id_member')
        );
    }
    // Should we do something?
    else
    {
        // Starred?
        if (isset($options['is_starred']))
        {
            $smcFunc['db_query']('', '
            UPDATE {db_prefix}conversations_participants
            SET starred = {int:starred}
            WHERE id_conversation = {int:conversation}
                AND id_member = {int:member}
            LIMIT 1',
                array(
                    'conversation'    => $id_pm,
                    'member'        => $from['id'],
                    'starred'        => !empty($options['is_starred']) ? 1 : 0,
                )
            );
        }
       
        // Update it!
        $smcFunc['db_query']('', '
        UPDATE {db_prefix}conversations
        SET last_post_by = {int:member}, last_post_date = {int:date}, last_post_name = {string:name}' . (isset($options['is_locked']) ? ', is_locked = {int:is_locked}' : '') . (isset($options['allow_others']) ? ', allow_others = {int:allow_others}' : '') . '
        WHERE id_conversation = {int:conversation}
        LIMIT 1',
            array(
                'name'            => $from['username'],
                'conversation'    => $id_pm,
                'date'            => $this_moment,
                'member'        => $from['id'],
                'is_locked'        => !empty($options['is_locked']) ? 1 : 0,
                'allow_others'    => !empty($options['allow_others']) ? 1 : 0,
            )
        );
    }

    // Notify using the alerts system
    if (function_exists('not_log_pm'))
        not_log_pm(array_keys($log['sent']), $from['name'], $subject, $message, $id_pm);

    censorText($message);
    censorText($subject);
    $message = trim(un_htmlspecialchars(strip_tags(strtr(parse_bbc(htmlspecialchars($message), false), array('<br />' => "\n", '</div>' => "\n", '</li>' => "\n", '[' => '[', '&#93;' => ']')))));

    foreach ($notifications as $lang => $notification_list)
    {
        // Make sure to use the right language.
        loadLanguage('index+PersonalMessage', $lang, false);
        loadLanguage('Conversations', $lang, false);

        // Replace the right things in the message strings.
        $mailsubject = str_replace(array('SUBJECT', 'SENDER'), array($subject, un_htmlspecialchars($from['name'])), $new_conversation ?  $txt['new_pm_subject'] : $txt['new_reply_pm_subject']);
        $mailmessage = str_replace(array('SUBJECT', 'MESSAGE', 'SENDER'), array($subject, $message, un_htmlspecialchars($from['name'])), $txt['pm_email']);
       
        // Unlocked?
        if (empty($options['is_locked']))
            $mailmessage .= "\n\n" . $txt['instant_reply'] . ' ' . $scripturl . '?action=pm;sa=send;c=' . $id_pm;

        // Off the notification email goes!
        sendmail($notification_list, $mailsubject, $mailmessage, null, 'p' . $id_pm, false, 2, null, true);
    }

    // Load default languages
    loadLanguage('index+PersonalMessage');

    // Add one to their unread and read message counts.
    foreach ($all_to as $k => $id)
        if ($id == $from['id'] && $from['id'] == $user_info['id'])
            unset($all_to[$k]);
           
    // If it's new then mark it as unread
    if ($new_conversation && !empty($all_to))
        updateMemberData($all_to, array('instant_messages' => '+', 'unread_messages' => '+', 'new_pm' => 1));
    // If it's not just mark it as unread for those who already saw everything else!
    else if (!empty($all_to))
    {
        // Time to check if this is actually new
        $dbquery = $smcFunc['db_query']('', '
        SELECT is_unread, id_member
        FROM {db_prefix}conversations_participants
        WHERE id_conversation = {int:conversation}
            AND id_member IN ({array_int:members})',
            array(
                'members'        => $all_to,
                'conversation'    => $id_pm
            )
        );
       
        $notify = array();
        while ($row = $smcFunc['db_fetch_assoc']($dbquery))
        {
            if (empty($row['is_unread']))
                $notify[] = $row['id_member'];   
        }
        $smcFunc['db_free_result']($dbquery);
       
        // Notify them!
        if (!empty($notify))
            updateMemberData($notify, array('instant_messages' => '+', 'unread_messages' => '+', 'new_pm' => 1));
    }
   
    // Last but not least! Mark this as unread for every participant!
    if (!$new_conversation)
    {
        $smcFunc['db_query']('', '
        UPDATE {db_prefix}conversations_participants
        SET is_unread = 1
        WHERE id_conversation = {int:conversation}
            AND id_member != {int:member}',
            array(
                'member'        => $user_info['id'],
                'conversation'    => $id_pm
            )
        );
    }

    return $log;
}

// Send off a personal message.
function sendpmlegacy($recipients, $subject, $message, $store_outbox = false, $from = null, $pm_head = 0)

But when I open Sources/Subs-Post.php I can't find that code to replace it.
Title: Re: Are there any plugins that change the personal messaging system?
Post by: Kindred on February 25, 2022, 01:32:44 PM
Please discuss mod specific issues in rhe thread dedicated to supporting that mod
Title: Re: Are there any plugins that change the personal messaging system?
Post by: Mike66 on February 25, 2022, 02:34:36 PM
Valid point - sorry Kindred.

Feel free to move or delete my post.