News:

Want to get involved in developing SMF, then why not lend a hand on our github!

Main Menu

Are there any plugins that change the personal messaging system?

Started by IshanP, February 25, 2022, 12:45:04 AM

Previous topic - Next topic

IshanP

By making it more like other forum PMs systems like proboards's/XenForo's PM system?

Antechinus

It would make sense to describe how you want it to function. "Like something else" is not really a useful description. :)

Arantor

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.

Mike66

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

Mike66

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.

Kindred

Please discuss mod specific issues in rhe thread dedicated to supporting that mod
Слaва
Украинi

Please do not PM, IM or Email me with support questions.  You will get better and faster responses in the support boards.  Thank you.

"Loki is not evil, although he is certainly not a force for good. Loki is... complicated."

Mike66

Valid point - sorry Kindred.

Feel free to move or delete my post.

Advertisement: