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

Send summary notifications instead of individual notifications for sound moderation to creators and moderators #1779

Open
qubodup opened this issue Jun 10, 2024 · 1 comment

Comments

@qubodup
Copy link

qubodup commented Jun 10, 2024

Users and moderators get one email per assigned/owned ticket change. This is stressful to navigate for busy users/moderators due to lots of padding between information in automatic email threads in GMail and probably in other clients as well. The mass of emails potentially wastes resources.

freesound _A_Freesound_moderator_handled_your_upl_24-06-08_22-12-25_1y3x
"[freesound] A Freesound moderator handled your upload" email group in my inbox earlier today (only a small part, zoomed out, stacked)

I worry that depending on the user's relationship to emailing this:

  1. makes users associate freesound with bad usability, a bad experience and ancient technology
  2. makes users ignore/miss requests for improvement due to natural conditioning to ignore spam-like emails or due to inability to process the overwhelming quantity amidst emails from social sites and online stores all grasping at the user's attention.

As a moderator I know that the current situation makes moderation an annoying experience when one creator updates many sounds, even though that usually is great news.

This ticket is targeted at the email experience only, ignoring on-site notification.

I imagine the current server notification workflow looks like this:

Freesound moderation notification email mindmap 2024old

I'm imagining it could work like this instead:

Freesound moderation notification email mindmap 2024suggested

Python-esque pseudocode of how I imagine it could work follows.

  • notifyable_ticket_changes is a simple table which would benefit from keeping the correct order.
  • Its entries are change_id, recipient_id, creator_id, sound_id, timeout, action, msg, ticket_id but maybe more needs to be stored for constructing the email at the end.
  • timeout is time when submitted + 5m. action is string Approve/Defer/Delete. msg is a bool (see msg = msg_form.cleaned_data.get("message", False) in l511 in freesound/tickets/views.py).
  • change_id is unique to ensure we only remove the changes we emailed about, as in theory new changes of already included tickets could be added while this is running.
  • More than 1000 entries should be a rarity unless the emailing part breaks down and the list keeps filling up.
# Run every 30s (note: suggested timeout is 5m though) after last call end to send as few emails in the same
# call as possible and thus spread load (might help false positive spam identification too?)

# track which recipients should be notified during this call
recipients_to_notify = []

now = time.now

# check every ticket change whether it's time to email the recipient yet
for change in notifyable_ticket_changes:

	# if it is time and not already in recipients_to_notify
	if change.timeout <= now and (not change.recipient_id in recipients_to_notify):
		# add to recipients_to_notify
		recipients_to_notify.append(change.recipient_id)
	
	# in case notifyable_ticket_changes is guaranteed sorted by timeout,
        # we could stop checking once we hit a change that is not due for notification yet
	### elif ticket.timeout > now : continue

# tree of ticket changes to notify about
notify_tree = {}

# keep track of successful notifications (only using change_id is easiest to read but might not be the most effective
notify_changes = []

# for every recipient
for change in notifyable_ticket_changes:

    # skip recipients' ticket changes that are not due for notification
    if not change.recipient in recipients_to_notify: continue

    # for each remaining recipient
    if not change.recipient_id in notfy_tree:
        notify_tree[change.recipient_id] = {}

    # for each creator (recipient = creator when creator is emailed), prepare a list of ticket change dicts
    if not change.creator_id in notify_tree[change.recipient_id]:
        notify_tree[change.recipient_id][change.creator_id] = []
	
    # I'm not sure what the right approach is. We need to conclude the current status,
    # so that if a moderator first approves/deletes and then ask a question on the ticket page,
    # the notification reflects both. I suppose this means we require the for loop to be chronological?
    if not change.sound_id in notify_tree[change.recipient_id][change.creator_id]:
        notify_tree[change.recipient_id][change.creator_id][ticket_sound_id] = {
            action = change.action,
            msg = change.msg,
            ticket_id = change.ticket_id
        }
    else:
        # we need to know whether any of the changes added a message
        if change.msg == True: notify_tree[change.recipient_id][change.creator_id][change.sound_id][msg] = True
        
        # once a sound is deleted, it can't change action
    	if notify_tree[change.recipient_id][change.creator_id][change.sound_id][action] != "Delete":
            # I guess once a sound is "Approve", only "Delete" may overwrite that action.
            # Not sure if just adding a comment triggers "Defer" action.
            if notify_tree[change.recipient_id][change.creator_id][change.sound_id][action] != "Approve" and change.action != "Defer":
                notify_tree[change.recipient_id][change.creator_id][change.sound_id][action] = change.action

    # add ticket id to delete later if email was success. Can't just use the recipient_id,
    # in case new entries are added in the meantime.
    if not change.change_id in notify_changes: notify_changes.append(change.change_id)
	
email = construct_email(notify_tree)
		
try:
    send_email(email)
fail:
    # not sure but the "good" thing is this should be repeated in the next call.
    # If we have to anticipate issues, perhaps some thing(s) should be limited,
    # like max 1000 changed_ticket per call or max 200 tickets per email or recipients?
success:
    # how to ensure this doesn't fail? Else might end up with same notification email every call...
    remove_from_notifyable_ticket_changes(notify_changes)

I did not write up how construct_email() would work yet but can definitely do that if I get confirmation that it would be useful.

Here is a summary of how the emails should work depending on whether moderator or creator is emailed and which categories (approve/defer/delete each with or without msg) are included and how many tickets/sounds per category are affected:

# to creator

Dear [creator x],

## action needed

[if unpublished and note, 1]
Your response might be needed on this sound:
"Laughter 2" http://ticket
[elif unpublished and note, >1]
Your response might be needed on these sounds:
"Laughter 2" http://ticket
"Laughter 2" http://ticket

## good news, comments prioritized

[if published and note, 1]
The moderation team approved this sound and left a note for you:
"Laughter 2" http://ticket
[elif published and note, >1]
The moderation team approved these sounds and left notes for you:
"Laughter 2" http://ticket
"Laughter 2" http://ticket

[if published no note, 1]
[The moderation team/They also] approved this sound:
"Laughter 2" http://ticket
[elif published no note, >1]
[The moderation team/They also] approved these sounds:
"Laughter 2" http://ticket
"Laughter 2" http://ticket

## bad news

[if deleted and note, 1]
This sound was removed and a note was left:
"Laughter 2" http://ticket
[elif deleted and note, >1]
These sounds were removed and notes were left:
"Laughter 2" http://ticket
"Laughter 2" http://ticket

[if deleted no note, 1]
The following sound was removed:
"Laughter 2" http://ticket
[elif deleted no note, >1]
The following sounds were removed:
"Laughter 2" http://ticket
"Laughter 2" http://ticket

Emails for mods are sorted by creators, as moderating in batches per user is usually a smoother process

# to moderator

Dear [moderator x],

The following tickets assigned to you were upadted:
FunUploader edited and left a note for "Laughter 2" http://ticket
FunUploader left a note for "Laughter 2" http://ticket
FunUploader left a note for "Laughter 2" http://ticket
FunUploader "Laughter 2" http://ticket
Sonic Buddy edited and left a note "Laughter 2" http://ticket
Sonic Buddy edited "Laughter 2" http://ticket
Sonic Buddy deleted "Laughter 2" http://ticket
French Dispatcher 420 left a note for "Laughter 2" http://ticket

The email subject lines could be improved and depend on # of affected sounds/tickets:

old for creators and mods:
[freesound] A Freesound moderator handled your upload

new for creators if [freesound] required:
[freesound] Upload moderation update
[freesound] Upload moderation updates (#)

new for creators if [freesound] can be omitted:
Freesound upload moderation update
Freesound upload moderation updates (#)

new for mods:
[freesound] Moderation ticket update
[freesound] Moderation tickets updates (#) 

The ticket links are unpleasantly long. For that I would be happy to additionally write (pseudo)code to generate HTML emails if I get confirmation that freesound will be able to utilize them.

@ffont
Copy link
Member

ffont commented Nov 8, 2024

Thanks a lot for the detailed ticket @qubodup!
We're very very limited in development time right now and there are a couple of other "big" things that we should work on, but if/when we are ready to work on some other things, this could be a good idea.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants