Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spam folder for messages #59

Open
6 of 7 tasks
lonewolf1321 opened this issue Jan 28, 2024 · 22 comments
Open
6 of 7 tasks

Spam folder for messages #59

lonewolf1321 opened this issue Jan 28, 2024 · 22 comments
Labels
feature request Issue is about a new feature in the app needs triage Issue is not yet ready for PR authors to take up

Comments

@lonewolf1321
Copy link

lonewolf1321 commented Jan 28, 2024

Checklist

  • I made sure that there are no existing issues - open or closed - to which I could contribute my information.
  • I made sure that there are no existing discussions - open or closed - to which I could contribute my information.
  • I have read the FAQs inside the app (Menu -> About -> FAQs) and my problem isn't listed.
  • I have taken the time to fill in all the required details. I understand that the bug report will be dismissed otherwise.
  • This issue contains only one feature request.
  • I have read and understood the contribution guidelines.
  • I optionally donated to support the Fossify mission.

Feature description

I know its an initial release and i am sorry to requesting a feature too early, Only issue with the fossify sms is there isn't a spam folder or a way to retrieve accidentally blocked sms

Why do you want this feature?

I accidentally blocked an sms , i couldn't find an spam folder or anything like that, as a temporary solution i installed another sms app and retrieve that blocked message from there

Additional information

Even there won't be a spam folder ,please add any way to retrieve blocked messages

@lonewolf1321 lonewolf1321 added feature request Issue is about a new feature in the app needs triage Issue is not yet ready for PR authors to take up labels Jan 28, 2024
@Aga-C Aga-C removed the needs triage Issue is not yet ready for PR authors to take up label Jan 28, 2024
@mksafavi
Copy link

I was looking for this as well. Having a way to see blocked messages is necessary especially for unintended keyword blocks.
Also, google messages has a notification feature for blocked messages. When it blocks a message it sends a notification without showing the message body by saying new spam or blocked message. having that as an option would be nice too.

@inson1
Copy link

inson1 commented Feb 21, 2024

Idk I think having notification about that would be against its purpose imo (but maybe opt in option wouldnt hurt)

@mksafavi
Copy link

mksafavi commented Feb 21, 2024 via email

@inson1
Copy link

inson1 commented Feb 21, 2024

@mksafavi well anyway Spam folder would be better, right?

@lonewolf1321
Copy link
Author

Just like an email service there will be messages falsely detected for spam and we always check spam folder next if we didn't received the message, so an spam folder can be considered as basic feature for any messaging app, hope we get that in future

@naveensingh
Copy link
Member

I wanted this too :)

IIRC MMS isn't even saved if the sender is blocked.

@slhale
Copy link

slhale commented May 7, 2024

I also want this! I am paranoid that I might have accidentally blocked a message unintentionally. I really just want the keyword blocking to avoid spamming of notifications, not to never have access to the message.

A Spam folder seems similar to the Archive and Recycle folders that already exist, so it doesn't seem like a huge ask to me.

@gregzme17
Copy link

any news on this? Google messages has two functions, mark messages as Spam and Block numbers.

@Aga-C Aga-C added the needs triage Issue is not yet ready for PR authors to take up label Nov 22, 2024
@Aga-C
Copy link
Member

Aga-C commented Nov 22, 2024

I reverted needs triage because after investigation we've found out, that SMS from a blocked number doesn't get through to the app, so even if we create a spam folder it doesn't show anything. We need to check it further, how to bypass it, and then we can think of creating a spam folder.

It most likely also affects this issue: #237.

@mahdiar
Copy link

mahdiar commented Dec 13, 2024

qksms has its own blocking manager and user can achieve blocked sms inside the app.

@cyberblackhole
Copy link

Please implement this. i believe this is much needed to view blocked sms's. I just moved from QKSMS, though many features are missing here. I request this one to be completed.

@naveensingh
Copy link
Member

I'm thinking about using an internal blocking list in both Phone and Messages but it's not exactly a 'simple to explain' solution.

@naveensingh
Copy link
Member

Perhaps this can be done in two parts with #271 being the first one (including pattern blocking).

That way, we'll have the UI/UX clarified before we attempt to use an internal list.

@MGidnian
Copy link

MGidnian commented Jan 11, 2025

Hello everyone,

I have begun developing a new feature/fix and am currently stuck. I would greatly appreciate your technical comments and guidance on how to proceed. Below is a detailed explanation of the feature, its motivation, the high-level plan, what is working so far, and the issues encountered.


Feature Description

  • User Story:
    As a user, I want messages containing blocked keywords or numbers to be sent to the recycle bin instead of being permanently dropped, so I can review them later if necessary.

  • Current State:
    If a message contains a blocked keyword or number, it isn’t saved on the device at all, and no notification is received.

  • Expected Behavior:
    If a message matches a blocked keyword/number, it should be saved as usual but then moved directly to the recycle bin without notifying the user.


Motivation

  • User Control:
    Simply dropping messages isn’t ideal because the user loses control over what was filtered out. Saving them in the recycle bin allows the user to review and decide on further action.

  • Optimized Filtering:
    Without visibility into blocked messages, users can’t refine their blocklist effectively. Saving these messages provides insight into what’s being blocked, enabling better filter optimization.

Why Not a Dedicated Spam Folder?
A dedicated spam folder would be the best solution (I think), but implementing it involves complex changes (database schema modifications, UI work, and other under-the-hood adjustments) that are beyond my current expertise. Using the recycle bin as an interim solution still offers value to the user by allowing access to blocked messages without cluttering the main view.


High-Level Plan

  1. Ensure Recycle Bin Feature is Enabled
    Verify that the recycle bin functionality is active before processing messages.

  2. On Receiving a Message (SMS/MMS)

    • Check if the message matches any keywords or numbers in the blocklist.
  3. If No Match

    • Process the message normally as it is today.
  4. If There Is a Match

    1. Save the message to the database and add it to the app.
    2. Do not send a notification or increase the unread messages count.
    3. Move the saved message to the recycle bin.

Focus on SMS Flow

I’m starting with the SMS flow. See updates to SmsReceiver.kt here:

package org.fossify.messages.receivers

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Handler
import android.os.Looper
import android.provider.Telephony
import org.fossify.commons.extensions.baseConfig
import org.fossify.commons.extensions.getMyContactsCursor
import org.fossify.commons.extensions.isNumberBlocked
import org.fossify.commons.helpers.SimpleContactsHelper
import org.fossify.commons.helpers.ensureBackgroundThread
import org.fossify.commons.models.PhoneNumber
import org.fossify.commons.models.SimpleContact
import org.fossify.messages.extensions.*
import org.fossify.messages.helpers.ReceiverUtils.isMessageFilteredOut
import org.fossify.messages.helpers.refreshMessages
import org.fossify.messages.models.Message

class SmsReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        val messages = Telephony.Sms.Intents.getMessagesFromIntent(intent)
        var address = ""
        var body = ""
        var subject = ""
        var date = 0L
        var threadId = 0L
        var status = Telephony.Sms.STATUS_NONE
        val type = Telephony.Sms.MESSAGE_TYPE_INBOX
        val read = 0
        val subscriptionId = intent.getIntExtra("subscription", -1)

        val privateCursor = context.getMyContactsCursor(false, true)
        ensureBackgroundThread {
            messages.forEach {
                address = it.originatingAddress ?: ""
                subject = it.pseudoSubject
                status = it.status
                body += it.messageBody
                date = System.currentTimeMillis()
                threadId = context.getThreadId(address)
            }
            if (context.baseConfig.blockUnknownNumbers) {
                val simpleContactsHelper = SimpleContactsHelper(context)
                simpleContactsHelper.exists(address, privateCursor) { exists ->
                    if (exists) {
                        handleMessage(context, address, subject, body, date, read, threadId, type, subscriptionId, status)
                    }
                }
            } else {
                handleMessage(context, address, subject, body, date, read, threadId, type, subscriptionId, status)
            }
        }
    }

    private fun handleMessage(
        context: Context,
        address: String,
        subject: String,
        body: String,
        date: Long,
        read: Int,
        threadId: Long,
        type: Int,
        subscriptionId: Int,
        status: Int
    ) {
        // Step 1: Perform Keyword Check
        val messageShouldBeBlocked: Boolean = (isMessageFilteredOut(context, body) || context.isNumberBlocked(address))
        
        // Set read to 0 if the message should be blocked
        val effectiveReadStatus = if (messageShouldBeBlocked) 1 else read

        val photoUri = SimpleContactsHelper(context).getPhotoUriFromPhoneNumber(address)
        val bitmap = context.getNotificationBitmap(photoUri)
        Handler(Looper.getMainLooper()).post {
            val privateCursor = context.getMyContactsCursor(favoritesOnly = false, withPhoneNumbersOnly = true)
            ensureBackgroundThread {
                val newMessageId = context.insertNewSMS(address, subject, body, date, effectiveReadStatus, threadId, type, subscriptionId)
                val conversation = context.getConversations(threadId).firstOrNull() ?: return@ensureBackgroundThread
                
                try {
                    context.insertOrUpdateConversation(conversation)
                } catch (ignored: Exception) {}
                
                if (!messageShouldBeBlocked) {
                    try {
                        context.updateUnreadCountBadge(context.conversationsDB.getUnreadConversations())
                    } catch (ignored: Exception) {}
                }

                val senderName = context.getNameFromAddress(address, privateCursor)
                val phoneNumber = PhoneNumber(address, 0, "", address)
                val participant = SimpleContact(0, 0, senderName, photoUri, arrayListOf(phoneNumber), ArrayList(), ArrayList())
                val participants = arrayListOf(participant)
                val messageDate = (date / 1000).toInt()

                val message =
                    Message(
                        newMessageId,
                        body,
                        type,
                        status,
                        participants,
                        messageDate,
                        messageShouldBeBlocked,
                        threadId,
                        false,
                        null,
                        address,
                        senderName,
                        photoUri,
                        subscriptionId
                    )
                context.messagesDB.insertOrUpdate(message)
                if (context.config.isArchiveAvailable) {
                    context.updateConversationArchivedStatus(threadId, false)
                }

                // Step 3: Send to recycle bin if blocked
                if (messageShouldBeBlocked) {
                    context.moveMessageToRecycleBin(newMessageId)
                    refreshMessages()
                } else {
                    refreshMessages()
                    context.showReceivedMessageNotification(newMessageId, address, body, threadId, bitmap)
                }
            }
        }
    }
}

What Is Working

  • The SMS is received and saved properly.
  • Blocked messages appear in the recycle bin and are not visible in the main inbox.
  • Users are not notified about blocked messages:
    • No notifications are sent.
    • Unread message badges are not increased.
    • Conversations do not appear bolded.

Known Issue

  • Scrolling Issue in Recycle Bin showing legitimate messages as well:
    When viewing a conversation in the recycle bin that contains blocked messages, scrolling a bit causes the conversation to load all messages, including legitimate ones. This behavior needs to be addressed.

Next Steps

  1. Resolve the scrolling/loading issue where legitimate messages appear unexpectedly in the recycle bin.
  2. In the future, enable the recycle bin by default when blocked keywords are added to the blocklist.

Thank you for taking the time to review this (and maintaining the app in general @naveensingh @Aga-C ). Any insights, feedback, or suggestions on how to address the current issue and proceed further would be greatly appreciated!
I will submit a PR once this works and tested.

@naveensingh
Copy link
Member

naveensingh commented Jan 11, 2025

@MGidnian

Please do not work on issues with needs triage label and please be concise with your messages. Consider reading the contribution guidelines.

Also, that whole code block isn't wasn't formatted properly, it seems like you used some LLM (AI studio?) to format it and it messed it up. AI is good but it's not THAT good.

Using the recycle bin as an interim solution still offers value to the user by allowing access to blocked messages without cluttering the main view.

This is not the way.

@MGidnian
Copy link

MGidnian commented Jan 11, 2025

@naveensingh ,
I reviewed the guidelines once more, thanks! I know I'm new but trying to be helpful so sorry for any mistakes.
Althoguh it has needs triage label, I saw this is old and it didn't seem to be in work. As I have a personal need for this, I went ahead and suggested to work on this.

  1. Why it's not the way? I would be glad to work the details to get this going. The reason I put such an elaborate message was to clarify why I think it's good to start with a solution and how would I go about implementing it.
  2. Can you explain what needs triage and where can I help? (if at all)

I agree, AI is not THAT great - but I actually wrote everything myself! I just used GPT to make it markdown compliant. The issue wasn't with GPT, I used a single line code formatting instead of multiline by mistake :P

@Aga-C
Copy link
Member

Aga-C commented Jan 11, 2025

I saw this is old and it didn't seem to be in work.

Maybe it wasn't as much visible, but there was some work. We did the first prototype for internal investigation a few months ago, which resulted in my comment from November, that there are problems with utilizing the current global block list. And the latest idea how to bypass the limitations is just from a week ago.

@naveensingh
Copy link
Member

Why it's not the way?

Putting blocked messages inside a recycle bin doesn't make sense. Whenever this is implemented, it will be its own option like 'Blocked messages'.

Can you explain what needs triage and where can I help?

The needs triage label is removed once all the if/when/what/how questions regarding an issue are cleared.

Thanks for the effort!

@MGidnian
Copy link

MGidnian commented Jan 11, 2025

Maybe it wasn't as much visible, but there was some work.

Thanks, yes I saw the conversation up as well @naveensingh suggested recycle bin (or as I understand now a "spam bin") can be the first phase, with no many details following. That's why I picked it up and suggested my code.

Putting blocked messages inside a recycle bin doesn't make sense

Several users mentioned here/reddit it would be a fine solution, me including. IMHO it's better than just dropping messages today which is not straightforward UX.

Maybe it's too complex to explain(?), but if not - can you please share a little bit so I can work on it?
If not and you are kind enough - can you explain or set me on the right direction to why legitimate messages will appear in the recycle bin for my code?
so at least I or others can create some local build until you/we get this feature right 🙏

@naveensingh
Copy link
Member

why legitimate messages will appear in the recycle bin for my code

I don't see anything wrong with the code. It's probably something subtle or it maybe something you changed in the recycle bin activity or related code.

@MGidnian
Copy link

Thanks 🙏
I have performed multiple tests with: Master, clean v1.1.3 and with my own code. They all reproduce. this is a bug 🤷
I'll open a ticket about it later

@naveensingh
Copy link
Member

I'll open a ticket about 🪲 later

Don't bother, the recycle bin will probably be removed in favor of the archive feature.

@Aga-C Aga-C marked this as a duplicate of #283 Jan 16, 2025
@naveensingh naveensingh pinned this issue Jan 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request Issue is about a new feature in the app needs triage Issue is not yet ready for PR authors to take up
Projects
None yet
Development

No branches or pull requests

11 participants