# Path: reviewer/models.py
# class ReviewGroup(models.Model):
#     """
#     many-to-many link of what groups can review for what organizations
#     (TODO) Eventually, we may want a workflow that allows someone
#     from one organization to vet events from another for the purposes
#     of copying them over.  In that case, the org would allow sharing (see event_exim app)
#     and wouldn't be added to the other org here, but a user might also be a member
#     of more than one org, and both orgs might be ok with 'sharing' the vetting
#     for the same event (assuming they have the same criteria).
#     """
#     organization = models.ForeignKey(Organization, db_index=True)
#     group = models.ForeignKey(Group, db_index=True)
#     visibility_level = models.IntegerField(
#         default=0,
#         help_text=("Think of it like an access hierarchy. "
#                    "0 is generally the lowest level. "
#                    "Anything higher is probably staff/etc. "
#                    "You can see Reviews/ReviewLogs with your own visibility and lower"))
# 
#     class Meta:
#         unique_together = ('organization', 'group')
# 
#     @classmethod
#     def org_groups(cls, organization_slug):
#         """
#         memo-ize orgs--it'll be a long time before we're too big for memory
#         """
#         if organization_slug not in _ORGANIZATIONS:
#             _ORGANIZATIONS[organization_slug] = list(
#                 ReviewGroup.objects.filter(
#                     organization__slug=organization_slug)
#                 .select_related('organization', 'group')
#                 # important for visibility options below
#                 .order_by('-visibility_level'))
#         return _ORGANIZATIONS.get(organization_slug)
# 
#     @classmethod
#     def user_allowed(cls, user, organization_slug):
#         allowed = ReviewGroup.org_groups(organization_slug)
#         allowed_groups = set([x.group_id for x in allowed])
#         group_ids = set(user.groups.values_list('id', flat=True))
#         return (group_ids.intersection(allowed_groups)
#                 or user.is_superuser)
# 
#     @classmethod
#     def user_visibility(cls, organization_slug, user):
#         org_groups = ReviewGroup.org_groups(organization_slug)
#         group_ids = set(user.groups.values_list('id', flat=True))
#         # ASSUMEs org_groups are ordered in descending value of visibility
#         # see org_groups()
#         for org_grp in org_groups:
#             if org_grp.group_id in group_ids:
#                 return org_grp.visibility_level
# 
#     @classmethod
#     def user_visibility_options(cls, organization_slug, user):
#         org_groups = ReviewGroup.org_groups(organization_slug)
#         group_ids = set(user.groups.values_list('id', flat=True))
# 
#         uservisibility = ReviewGroup.user_visibility(organization_slug, user)
#         options = {}
#         for org_grp in org_groups:
#             if org_grp.visibility_level <= uservisibility:
#                 if not options.get(org_grp.visibility_level) \
#                    or org_grp.group_id in group_ids:
#                     options[org_grp.visibility_level] = org_grp.group.name
#         return options
# 
#     @classmethod
#     def user_review_groups(cls, user):
#         return ReviewGroup.objects.filter(group__user=user)
# 
#     def __str__(self):
#         return '{} for {}'.format(self.group, self.organization)
# 
# class ReviewLog(models.Model):
#     content_type = models.ForeignKey(ContentType,
#                                      editable=False,
#                                      blank=True)
#     object_id = models.IntegerField()
#     content_object = GenericForeignKey('content_type', 'object_id')
# 
#     # subject is a secondary object reference,
#     # like the host id when the object is an event
#     subject = models.IntegerField(null=True, blank=True)
# 
#     organization = models.ForeignKey(Organization)
#     reviewer = models.ForeignKey(User)
#     created_at = models.DateTimeField(auto_now_add=True)
#     message = models.TextField()
#     log_type = models.CharField(max_length=8, default='note',
#                                 choices=(
#                                     ('note', 'Note'),
#                                     ('bulknote', 'Bulk Note'),
#                                     ('message', 'Message'),
#                                     ('bulkmsg', 'Bulk Message')
#                                 ))
#     visibility_level = models.IntegerField()
# 
#     class Meta:
#         permissions = (
#             ('message_sending', 'message sending'),
#             ('bulk_message_send', 'bulk message sending'),
#             ('bulk_note_add', 'bulk note adding'),
#             )


import datetime
import json
import random
from django.core.mail import get_connection as get_mail_connection
from django.conf import settings
from django.conf.urls import url
from django.contrib import admin
from django.contrib.contenttypes.models import ContentType
from django.core.mail import send_mail, EmailMultiAlternatives
from django.http import HttpResponse
from django.template.loader import render_to_string
from django.template.response import TemplateResponse
from django.urls import reverse, NoReverseMatch
from django.utils.safestring import mark_safe
from reviewer.models import ReviewGroup, ReviewLog
            verb='Send a message')

    @staticmethod
    def bulk_content_action(modeladmin, request, queryset, log_type, action, verb):
        """
        Message sending action for a ModelAdmin that will send messages to everyone
        chosen in a queryset
        """
        title = "{} to many people".format(verb)
        objects_name = "tags"
        opts = modeladmin.model._meta
        action_checkbox_name="_selected_action"
        app_label = opts.app_label
        no_continue_message = ''
        perms_needed = not request.user.has_perm('reviewer.{}'.format(action))
        if perms_needed:
            no_continue_message = 'Contact a site administrator about getting permission to {}.'.format(action)
        count = queryset.count()
        max_apply = getattr(settings, "BULK_NOTEMESSAGE_MAX", 200)

        organization_slug = request.POST.get('organization')
        if not organization_slug:
            orgslugs = (ReviewGroup
                        .user_review_groups(request.user)
                        .values_list('organization__slug', flat=True)
                        .distinct())
            if len(orgslugs) == 1:
                organization_slug = orgslugs[0]

        if log_type in ('message', 'bulkmsg'):

# Path: reviewer/models.py
# class ReviewGroup(models.Model):
#     """
#     many-to-many link of what groups can review for what organizations
#     (TODO) Eventually, we may want a workflow that allows someone
#     from one organization to vet events from another for the purposes
#     of copying them over.  In that case, the org would allow sharing (see event_exim app)
#     and wouldn't be added to the other org here, but a user might also be a member
#     of more than one org, and both orgs might be ok with 'sharing' the vetting
#     for the same event (assuming they have the same criteria).
#     """
#     organization = models.ForeignKey(Organization, db_index=True)
#     group = models.ForeignKey(Group, db_index=True)
#     visibility_level = models.IntegerField(
#         default=0,
#         help_text=("Think of it like an access hierarchy. "
#                    "0 is generally the lowest level. "
#                    "Anything higher is probably staff/etc. "
#                    "You can see Reviews/ReviewLogs with your own visibility and lower"))
# 
#     class Meta:
#         unique_together = ('organization', 'group')
# 
#     @classmethod
#     def org_groups(cls, organization_slug):
#         """
#         memo-ize orgs--it'll be a long time before we're too big for memory
#         """
#         if organization_slug not in _ORGANIZATIONS:
#             _ORGANIZATIONS[organization_slug] = list(
#                 ReviewGroup.objects.filter(
#                     organization__slug=organization_slug)
#                 .select_related('organization', 'group')
#                 # important for visibility options below
#                 .order_by('-visibility_level'))
#         return _ORGANIZATIONS.get(organization_slug)
# 
#     @classmethod
#     def user_allowed(cls, user, organization_slug):
#         allowed = ReviewGroup.org_groups(organization_slug)
#         allowed_groups = set([x.group_id for x in allowed])
#         group_ids = set(user.groups.values_list('id', flat=True))
#         return (group_ids.intersection(allowed_groups)
#                 or user.is_superuser)
# 
#     @classmethod
#     def user_visibility(cls, organization_slug, user):
#         org_groups = ReviewGroup.org_groups(organization_slug)
#         group_ids = set(user.groups.values_list('id', flat=True))
#         # ASSUMEs org_groups are ordered in descending value of visibility
#         # see org_groups()
#         for org_grp in org_groups:
#             if org_grp.group_id in group_ids:
#                 return org_grp.visibility_level
# 
#     @classmethod
#     def user_visibility_options(cls, organization_slug, user):
#         org_groups = ReviewGroup.org_groups(organization_slug)
#         group_ids = set(user.groups.values_list('id', flat=True))
# 
#         uservisibility = ReviewGroup.user_visibility(organization_slug, user)
#         options = {}
#         for org_grp in org_groups:
#             if org_grp.visibility_level <= uservisibility:
#                 if not options.get(org_grp.visibility_level) \
#                    or org_grp.group_id in group_ids:
#                     options[org_grp.visibility_level] = org_grp.group.name
#         return options
# 
#     @classmethod
#     def user_review_groups(cls, user):
#         return ReviewGroup.objects.filter(group__user=user)
# 
#     def __str__(self):
#         return '{} for {}'.format(self.group, self.organization)
# 
# class ReviewLog(models.Model):
#     content_type = models.ForeignKey(ContentType,
#                                      editable=False,
#                                      blank=True)
#     object_id = models.IntegerField()
#     content_object = GenericForeignKey('content_type', 'object_id')
# 
#     # subject is a secondary object reference,
#     # like the host id when the object is an event
#     subject = models.IntegerField(null=True, blank=True)
# 
#     organization = models.ForeignKey(Organization)
#     reviewer = models.ForeignKey(User)
#     created_at = models.DateTimeField(auto_now_add=True)
#     message = models.TextField()
#     log_type = models.CharField(max_length=8, default='note',
#                                 choices=(
#                                     ('note', 'Note'),
#                                     ('bulknote', 'Bulk Note'),
#                                     ('message', 'Message'),
#                                     ('bulkmsg', 'Bulk Message')
#                                 ))
#     visibility_level = models.IntegerField()
# 
#     class Meta:
#         permissions = (
#             ('message_sending', 'message sending'),
#             ('bulk_message_send', 'bulk message sending'),
#             ('bulk_note_add', 'bulk note adding'),
#             )


# Path: reviewer/message_sending.py
import datetime
import json
import random
from django.core.mail import get_connection as get_mail_connection
from django.conf import settings
from django.conf.urls import url
from django.contrib import admin
from django.contrib.contenttypes.models import ContentType
from django.core.mail import send_mail, EmailMultiAlternatives
from django.http import HttpResponse
from django.template.loader import render_to_string
from django.template.response import TemplateResponse
from django.urls import reverse, NoReverseMatch
from django.utils.safestring import mark_safe
from reviewer.models import ReviewGroup, ReviewLog

            verb='Send a message')

    @staticmethod
    def bulk_content_action(modeladmin, request, queryset, log_type, action, verb):
        """
        Message sending action for a ModelAdmin that will send messages to everyone
        chosen in a queryset
        """
        title = "{} to many people".format(verb)
        objects_name = "tags"
        opts = modeladmin.model._meta
        action_checkbox_name="_selected_action"
        app_label = opts.app_label
        no_continue_message = ''
        perms_needed = not request.user.has_perm('reviewer.{}'.format(action))
        if perms_needed:
            no_continue_message = 'Contact a site administrator about getting permission to {}.'.format(action)
        count = queryset.count()
        max_apply = getattr(settings, "BULK_NOTEMESSAGE_MAX", 200)

        organization_slug = request.POST.get('organization')
        if not organization_slug:
            orgslugs = (ReviewGroup
                        .user_review_groups(request.user)
                        .values_list('organization__slug', flat=True)
                        .distinct())
            if len(orgslugs) == 1:
                organization_slug = orgslugs[0]

        if log_type in ('message', 'bulkmsg'):

            howmany = ReviewLog.objects.filter(reviewer=request.user,