Beispiel #1
0
def ajax_checkout(request):
    project = get_obj_from_request(request.POST, 'project', Project)

    if project is None:
        return json_failure(design.bad_project_id)

    # make sure user can work on this band
    if not project.band.permission_to_work(request.user):
        return json_failure(
            design.you_dont_have_permission_to_work_on_this_band)

    if project.band.is_read_only():
        return json_failure(design.band_in_readonly_mode)

    # make sure project is available
    if project.checked_out_to is not None:
        return json_failure(design.this_project_already_checked_out)

    project.checked_out_to = request.user
    project.date_checked_out = datetime.now()
    project.save()

    # create log entry
    entry = LogEntry()
    entry.entry_type = LogEntry.SONG_CHECKED_OUT
    entry.band = project.band
    entry.project = project
    entry.catalyst = request.user
    entry.save()

    return json_success()
Beispiel #2
0
def ajax_checkout(request):
    project = get_obj_from_request(request.POST, 'project', Project)

    if project is None:
        return json_failure(design.bad_project_id)

    # make sure user can work on this band
    if not project.band.permission_to_work(request.user):
        return json_failure(design.you_dont_have_permission_to_work_on_this_band)

    if project.band.is_read_only():
        return json_failure(design.band_in_readonly_mode)

    # make sure project is available
    if project.checked_out_to is not None:
        return json_failure(design.this_project_already_checked_out)

    project.checked_out_to = request.user
    project.date_checked_out = datetime.now()
    project.save()

    # create log entry
    entry = LogEntry()
    entry.entry_type = LogEntry.SONG_CHECKED_OUT
    entry.band = project.band
    entry.project = project
    entry.catalyst = request.user
    entry.save()

    return json_success()
Beispiel #3
0
def ajax_project_list(request):
    # validate input
    page_number = get_val(request.GET, 'page', 1)

    filterName = request.GET.get('filter', 'all')
    if not FILTERS.has_key(filterName):
        filterName = DEFAULT_FILTER

    searchText = request.GET.get('search', '')

    band = get_obj_from_request(request.GET, 'band', Band)

    if band is None:
        return json_failure(design.bad_band_id)

    if not band.permission_to_critique(request.user):
        return json_failure(
            design.you_dont_have_permission_to_critique_this_band)

    # get a list of filtered projects
    projects = performFilter(filterName, Project.objects.filter(band=band),
                             request.user)

    # apply search text to query
    if searchText:
        # limit to 10 words
        words = searchText.split()[:10]
        for word in words:
            projects = projects.filter(title__icontains=word)

    paginator = Paginator(projects, settings.ITEMS_PER_PAGE)

    def project_to_dict(project):
        data = project.to_dict(access=SerializableModel.OWNER,
                               chains=['checked_out_to'])
        data['latest_version'] = version_to_dict(project.latest_version,
                                                 request.user)
        return data

    try:
        member_dict = BandMember.objects.get(band=band,
                                             user=request.user).to_dict()
    except BandMember.DoesNotExist:
        member_dict = None

    # build the json object
    data = {
        'projects':
        [project_to_dict(x) for x in paginator.page(page_number).object_list],
        'page_count':
        paginator.num_pages,
        'page_number':
        page_number,
        'band':
        band.to_dict(access=SerializableModel.OWNER),
        'band_member':
        member_dict,
    }

    return json_success(data)
Beispiel #4
0
def ajax_edit_comment(request):
    node = get_obj_from_request(request.POST, 'comment', SongCommentNode)

    if node is None:
        return json_failure(design.bad_song_comment_node_id)

    # can only edit own comments
    if node.owner != request.user:
        return json_failure(design.can_only_edit_your_own_comment)

    # can only delete within a certain amount of time
    now = datetime.now()
    if now > node.date_created + timedelta(
            hours=settings.COMMENT_EDIT_TIME_HOURS):
        return json_failure(design.too_late_to_edit_comment)

    content = request.POST.get('content', '')

    if len(content) == 0 or len(content) > 2000:
        return json_failure(design.content_wrong_length)

    node.content = content
    node.save()

    return json_success(node.to_dict())
Beispiel #5
0
def ajax_username_invite(request):
    invitee_username = get_val(request.POST, 'username', '')
    band = get_obj_from_request(request.POST, 'band', Band)

    try:
        invitee = User.objects.get(username=invitee_username)
    except User.DoesNotExist:
        return json_failure(design.that_user_does_not_exist)

    if band is None:
        return json_failure(design.bad_band_id)

    if not band.permission_to_invite(request.user):
        return json_failure(design.lack_permission_to_invite)

    # make sure the user isn't already in the band
    if BandMember.objects.filter(user=invitee, band=band).count() > 0:
        return json_failure(design.x_already_in_band.format(invitee.username))

    # make sure there isn't already an invitation for them
    if BandInvitation.objects.filter(invitee=invitee, band=band).count() > 0:
        return json_failure(design.already_invited_x_to_your_band.format(invitee.username))
    
    invite = BandInvitation()       
    invite.inviter = request.user
    invite.band = band
    invite.role = BandMember.BAND_MEMBER
    invite.invitee = invitee
    invite.save()

    # send a heads up email
    send_invitation_email(invite, request.get_host())
    return json_success()
Beispiel #6
0
def ajax_username_invite(request):
    invitee_username = get_val(request.POST, 'username', '')
    band = get_obj_from_request(request.POST, 'band', Band)

    try:
        invitee = User.objects.get(username=invitee_username)
    except User.DoesNotExist:
        return json_failure(design.that_user_does_not_exist)

    if band is None:
        return json_failure(design.bad_band_id)

    if not band.permission_to_invite(request.user):
        return json_failure(design.lack_permission_to_invite)

    # make sure the user isn't already in the band
    if BandMember.objects.filter(user=invitee, band=band).count() > 0:
        return json_failure(design.x_already_in_band.format(invitee.username))

    # make sure there isn't already an invitation for them
    if BandInvitation.objects.filter(invitee=invitee, band=band).count() > 0:
        return json_failure(
            design.already_invited_x_to_your_band.format(invitee.username))

    invite = BandInvitation()
    invite.inviter = request.user
    invite.band = band
    invite.role = BandMember.BAND_MEMBER
    invite.invitee = invitee
    invite.save()

    # send a heads up email
    send_invitation_email(invite, request.get_host())
    return json_success()
Beispiel #7
0
def handle_invite(request, accept):
    invite = get_obj_from_request(request.POST, 'invitation', BandInvitation)
    if invite is None:
        raise Http404

    # make sure the user has permission to reject this invitation
    if invite.invitee != request.user:
        return json_failure(design.invitation_not_sent_to_you)

    # make sure it's not expired
    if invite.expire_date is not None and datetime.now() > invite.expire_date:
        return json_failure(design.invitation_expired)

    if accept:
        # apply the invitation
        member = BandMember()
        member.user = request.user
        member.band = invite.band
        member.role = invite.role
        member.save()

        createNewBandMemberLogEntry(member)
        send_invitation_accepted_email(invite, request.get_host())

    invite.delete()
        
    return json_success()
Beispiel #8
0
def handle_invite(request, accept):
    invite = get_obj_from_request(request.POST, 'invitation', BandInvitation)
    if invite is None:
        raise Http404

    # make sure the user has permission to reject this invitation
    if invite.invitee != request.user:
        return json_failure(design.invitation_not_sent_to_you)

    # make sure it's not expired
    if invite.expire_date is not None and datetime.now() > invite.expire_date:
        return json_failure(design.invitation_expired)

    if accept:
        # apply the invitation
        member = BandMember()
        member.user = request.user
        member.band = invite.band
        member.role = invite.role
        member.save()

        createNewBandMemberLogEntry(member)
        send_invitation_accepted_email(invite, request.get_host())

    invite.delete()

    return json_success()
Beispiel #9
0
def ajax_create_band(request):
    form = NewBandForm(request.POST)

    if form.is_valid():
        profile = request.user.get_profile()
        if profile.bands_in_count() >= profile.band_count_limit:
            return json_failure(design.you_have_reached_your_band_count_limit)

        actually_create_band(request.user, form.cleaned_data.get('band_name'))
        return json_success()

    return json_failure(form_errors(form))
Beispiel #10
0
def ajax_create_band(request):
    form = NewBandForm(request.POST)

    if form.is_valid():
        profile = request.user.get_profile()
        if profile.bands_in_count() >= profile.band_count_limit:
            return json_failure(design.you_have_reached_your_band_count_limit)

        actually_create_band(request.user, form.cleaned_data.get('band_name'))
        return json_success()

    return json_failure(form_errors(form))
Beispiel #11
0
def ajax_upload_samples_as_version(request):
    """
    Upload some samples and then add each uploaded sample
    to a new project version.
    """
    project = get_obj_from_request(request.POST, 'project', Project)
    comments = request.POST.get('comments', '')

    if project is None:
        return json_failure(design.bad_project_id)

    band = project.band

    if not band.permission_to_work(request.user):
        return json_failure(
            design.you_dont_have_permission_to_work_on_this_band)

    if band.is_read_only():
        return json_failure(design.band_in_readonly_mode)

    node = SongCommentNode()
    node.owner = request.user
    node.content = comments
    node.save()

    version = ProjectVersion()
    version.project = project
    version.owner = request.user
    version.comment_node = node
    version.version = project.latest_version.version  # no +1, only adding samples.
    version.save()  # so we can add provided_samples

    node.version = version
    node.save()

    def add_sample_to_version(sample):
        version.provided_samples.add(sample)

    files = request.FILES.getlist('file')

    for item in files:
        handle_sample_upload(item,
                             request.user,
                             band,
                             callback=add_sample_to_version)

    band.save()
    version.save()
    version.makeLogEntry()

    return json_success()
Beispiel #12
0
def ajax_project_list(request):
    # validate input
    page_number = get_val(request.GET, 'page', 1)

    filterName = request.GET.get('filter', 'all')
    if not FILTERS.has_key(filterName):
        filterName = DEFAULT_FILTER

    searchText = request.GET.get('search', '')

    band = get_obj_from_request(request.GET, 'band', Band)

    if band is None:
        return json_failure(design.bad_band_id)

    if not band.permission_to_critique(request.user):
        return json_failure(design.you_dont_have_permission_to_critique_this_band)

    # get a list of filtered projects 
    projects = performFilter(filterName, Project.objects.filter(band=band), request.user)
    
    # apply search text to query
    if searchText:
        # limit to 10 words
        words = searchText.split()[:10]
        for word in words:
            projects = projects.filter(title__icontains=word)

    paginator = Paginator(projects, settings.ITEMS_PER_PAGE)

    def project_to_dict(project):
        data = project.to_dict(access=SerializableModel.OWNER, chains=['checked_out_to'])
        data['latest_version'] = version_to_dict(project.latest_version, request.user)
        return data

    try:
        member_dict = BandMember.objects.get(band=band, user=request.user).to_dict()
    except BandMember.DoesNotExist:
        member_dict = None

    # build the json object
    data = {
        'projects': [project_to_dict(x) for x in paginator.page(page_number).object_list],
        'page_count': paginator.num_pages,
        'page_number': page_number,
        'band': band.to_dict(access=SerializableModel.OWNER),
        'band_member': member_dict,
    }

    return json_success(data)
Beispiel #13
0
def ajax_dependency_ownership(request):
    profile = request.user.get_profile()

    dep_type_int = get_val(request.POST, 'dependency_type', -1)

    if dep_type_int == PluginDepenency.STUDIO:
        dep_type = Studio
        collection = profile.studios
    else:
        dep_type = PluginDepenency
        collection = profile.plugins

    dep = get_obj_from_request(request.POST, 'dependency_id', dep_type)

    if dep is None:
        return json_failure(design.bad_dependency_id)

    have = request.POST.get('have', 'false')
    if have == 'false':
        have = False
    else:
        have = True

    if have:
        collection.add(dep)
    else:
        collection.remove(dep)

    profile.save()

    return json_success()
Beispiel #14
0
def ajax_project_filters(request):
    band = get_obj_from_request(request.GET, 'band', Band)

    if band is None:
        return json_failure(design.bad_band_id)

    if not band.permission_to_work(request.user):
        return json_failure(design.you_dont_have_permission_to_work_on_this_band)

    projects = Project.objects.filter(band=band)

    results = dict(JFILTERS)
    for filterId, filterData in results.iteritems():
        filterData['count'] = performFilter(filterId, projects, request.user).count()

    return json_success(results)
Beispiel #15
0
def ajax_dependency_ownership(request):
    profile = request.user.get_profile()

    dep_type_int = get_val(request.POST, 'dependency_type', -1)

    if dep_type_int == PluginDepenency.STUDIO:
        dep_type = Studio
        collection = profile.studios
    else:
        dep_type = PluginDepenency
        collection = profile.plugins

    dep = get_obj_from_request(request.POST, 'dependency_id', dep_type)

    if dep is None:
        return json_failure(design.bad_dependency_id)

    have = request.POST.get('have', 'false')
    if have == 'false':
        have = False
    else:
        have = True

    if have:
        collection.add(dep)
    else:
        collection.remove(dep)

    profile.save()
    
    return json_success()
Beispiel #16
0
def ajax_upload_samples_as_version(request):
    """
    Upload some samples and then add each uploaded sample
    to a new project version.
    """
    project = get_obj_from_request(request.POST, 'project', Project)
    comments = request.POST.get('comments', '')

    if project is None:
        return json_failure(design.bad_project_id)

    band = project.band

    if not band.permission_to_work(request.user):
        return json_failure(design.you_dont_have_permission_to_work_on_this_band)

    if band.is_read_only():
        return json_failure(design.band_in_readonly_mode)

    node = SongCommentNode()
    node.owner = request.user
    node.content = comments
    node.save()

    version = ProjectVersion()
    version.project = project
    version.owner = request.user
    version.comment_node = node
    version.version = project.latest_version.version # no +1, only adding samples.
    version.save() # so we can add provided_samples

    node.version = version
    node.save()
    
    def add_sample_to_version(sample):
        version.provided_samples.add(sample)
        
    files = request.FILES.getlist('file')

    for item in files:
        handle_sample_upload(item, request.user, band, callback=add_sample_to_version)

    band.save()
    version.save()
    version.makeLogEntry()

    return json_success()
Beispiel #17
0
def ajax_delete_comment(request):
    node = get_obj_from_request(request.POST, 'comment', SongCommentNode)

    if node is None:
        return json_failure(design.bad_song_comment_node_id)

    # can only delete own comments
    if node.owner != request.user:
        return json_failure(design.can_only_delete_your_own_comment)

    # can only delete within a certain amount of time
    now = datetime.now()
    if now > node.date_created + timedelta(hours=settings.COMMENT_EDIT_TIME_HOURS):
        return json_failure(design.too_late_to_delete_comment)

    node.delete()
    return json_success()
Beispiel #18
0
def ajax_rename_project(request):
    """
    Make a new version that renames the project.
    """
    form = RenameProjectForm(request.POST)
    if form.is_valid():
        new_title = form.cleaned_data.get('title')
        comments = form.cleaned_data.get('comments', '')

        project_id = form.cleaned_data.get('project')
        try:
            project = Project.objects.get(pk=project_id)
        except Project.DoesNotExist:
            return json_failure(design.bad_project_id)

        if not project.band.permission_to_work(request.user):
            return json_failure(
                design.you_dont_have_permission_to_work_on_this_band)

        if project.band.is_read_only():
            return json_failure(design.band_in_readonly_mode)

        node = SongCommentNode()
        node.owner = request.user
        node.content = comments
        node.save()

        version = ProjectVersion()
        version.project = project
        version.owner = request.user
        version.comment_node = node
        version.version = project.latest_version.version  # no +1 because only renaming
        version.new_title = new_title
        version.old_title = project.title
        version.save()

        node.version = version
        node.save()

        project.title = new_title
        project.save()

        return json_success()

    return json_failure(form_errors(form))
Beispiel #19
0
def ajax_provide_project(request):
    version = get_obj_from_request(request.POST, 'version', ProjectVersion)

    if version is None:
        return json_failure(design.bad_version_id)

    band = version.project.band

    if not band.permission_to_work(request.user):
        return json_failure(design.you_dont_have_permission_to_work_on_this_band)

    if band.is_read_only():
        return json_failure(design.band_in_readonly_mode)

    project_handle = request.FILES.get('file')
    handle_project_upload(project_handle, request.user, version.song)

    return json_success()
Beispiel #20
0
def ajax_project_filters(request):
    band = get_obj_from_request(request.GET, 'band', Band)

    if band is None:
        return json_failure(design.bad_band_id)

    if not band.permission_to_work(request.user):
        return json_failure(
            design.you_dont_have_permission_to_work_on_this_band)

    projects = Project.objects.filter(band=band)

    results = dict(JFILTERS)
    for filterId, filterData in results.iteritems():
        filterData['count'] = performFilter(filterId, projects,
                                            request.user).count()

    return json_success(results)
Beispiel #21
0
def ajax_delete_comment(request):
    node = get_obj_from_request(request.POST, 'comment', SongCommentNode)

    if node is None:
        return json_failure(design.bad_song_comment_node_id)

    # can only delete own comments
    if node.owner != request.user:
        return json_failure(design.can_only_delete_your_own_comment)

    # can only delete within a certain amount of time
    now = datetime.now()
    if now > node.date_created + timedelta(
            hours=settings.COMMENT_EDIT_TIME_HOURS):
        return json_failure(design.too_late_to_delete_comment)

    node.delete()
    return json_success()
Beispiel #22
0
def ajax_rename_project(request):
    """
    Make a new version that renames the project.
    """
    form = RenameProjectForm(request.POST)
    if form.is_valid():
        new_title = form.cleaned_data.get('title')
        comments  = form.cleaned_data.get('comments', '')
    
        project_id = form.cleaned_data.get('project')
        try:
            project = Project.objects.get(pk=project_id)
        except Project.DoesNotExist:
            return json_failure(design.bad_project_id)

        if not project.band.permission_to_work(request.user):
            return json_failure(design.you_dont_have_permission_to_work_on_this_band)

        if project.band.is_read_only():
            return json_failure(design.band_in_readonly_mode)

        node = SongCommentNode()
        node.owner = request.user
        node.content = comments
        node.save()

        version = ProjectVersion()
        version.project = project
        version.owner = request.user
        version.comment_node = node
        version.version = project.latest_version.version # no +1 because only renaming
        version.new_title = new_title
        version.old_title = project.title
        version.save()

        node.version = version
        node.save()

        project.title = new_title
        project.save()

        return json_success()

    return json_failure(form_errors(form))
Beispiel #23
0
def ajax_provide_project(request):
    version = get_obj_from_request(request.POST, 'version', ProjectVersion)

    if version is None:
        return json_failure(design.bad_version_id)

    band = version.project.band

    if not band.permission_to_work(request.user):
        return json_failure(
            design.you_dont_have_permission_to_work_on_this_band)

    if band.is_read_only():
        return json_failure(design.band_in_readonly_mode)

    project_handle = request.FILES.get('file')
    handle_project_upload(project_handle, request.user, version.song)

    return json_success()
Beispiel #24
0
def ajax_upload_samples(request):
    band = get_obj_from_request(request.POST, 'band', Band)

    if band is None:
        return json_failure(design.bad_band_id)

    if not band.permission_to_work(request.user):
        return json_failure(design.you_dont_have_permission_to_work_on_this_band)

    if band.is_read_only():
        return json_failure(design.band_in_readonly_mode)

    files = request.FILES.getlist('file')

    for item in files:
        handle_sample_upload(item, request.user, band)
    band.save()
    
    return json_success()
Beispiel #25
0
def ajax_say(request):
    room = get_obj_from_request(request.POST, 'room', ChatRoom)
    if room is None:
        return json_failure(design.bad_room_id)

    data = {
        'user': {
            'is_authenticated': request.user.is_authenticated(),
            'permission_read': room.permission_to_hear(request.user),
            'permission_write': room.permission_to_chat(request.user),
        },
        'success': False,
    }

    if not room.is_active():
        return json_failure(design.room_is_not_active)

    message = request.POST.get('message', '')

    if message == "":
        return json_failure(design.cannot_say_blank_message)

    if len(message) > ChatMessage._meta.get_field('message').max_length: #@UndefinedVariable
        return json_failure(design.message_too_long)

    if not data['user']['permission_write']:
        return json_failure(design.you_lack_write_permission)

    msgType = get_val(request.POST, 'type', ChatMessage.MESSAGE)
    if msgType not in [ChatMessage.MESSAGE, ChatMessage.ACTION]:
        msgType = ChatMessage.MESSAGE

    # we're clear. add the message
    m = ChatMessage()
    m.room = room
    m.type = msgType
    m.author = request.user
    m.message = message
    m.save()

    data['success'] = True
    return json_response(data)
Beispiel #26
0
def ajax_create_invite(request):
    band = get_obj_from_request(request.POST, 'band', Band)
    invitee = get_obj_from_request(request.POST, 'invitee', User)

    if band is None:
        return json_failure(design.bad_band_id)

    if not band.openness == Band.FULL_OPEN:
        try:
            member = BandMember.objects.get(user=request.user, band=band)
        except BandMember.DoesNotExist:
            return json_failure(design.can_only_invite_to_your_own_band)

        if member.role != BandMember.MANAGER:
            return json_failure(design.only_managers_can_create_invitations)

    # make sure user isn't already in band
    if BandMember.objects.filter(band=band, user=invitee).count() > 0:
        return json_failure(design.x_already_in_band.format(invitee.username))

    invite = BandInvitation()
    invite.inviter = request.user
    invite.band = band
    invite.expire_date = datetime.now() + timedelta(days=30)

    if invitee == None:
        invite.code = create_hash(32)
        invite.save()
        data = {'url': invite.redeemHyperlink()}
        return json_success(data)
    else:
        # make sure invitation doesn't exist already
        if BandInvitation.objects.filter(band=band,
                                         invitee=invitee).count() > 0:
            return json_failure(
                design.already_invited_x_to_your_band.format(invitee.username))

        invite.invitee = invitee
        invite.save()
        send_invitation_email(invite, request.get_host())

        return json_success()
Beispiel #27
0
def ajax_onliners(request):
    room = get_obj_from_request(request.GET, 'room', ChatRoom)
    if room is None:
        return json_failure(design.bad_room_id)

    if not room.is_active():
        return json_success([])

    expire_date = datetime.now() - timedelta(seconds=settings.CHAT_TIMEOUT)
    data = [x.person.get_profile().to_dict() for x in Appearance.objects.filter(room=room, timestamp__gt=expire_date)]
    return json_success(data)
Beispiel #28
0
def ajax_upload_samples(request):
    band = get_obj_from_request(request.POST, 'band', Band)

    if band is None:
        return json_failure(design.bad_band_id)

    if not band.permission_to_work(request.user):
        return json_failure(
            design.you_dont_have_permission_to_work_on_this_band)

    if band.is_read_only():
        return json_failure(design.band_in_readonly_mode)

    files = request.FILES.getlist('file')

    for item in files:
        handle_sample_upload(item, request.user, band)
    band.save()

    return json_success()
Beispiel #29
0
def ajax_create_invite(request):
    band = get_obj_from_request(request.POST, 'band', Band)
    invitee = get_obj_from_request(request.POST, 'invitee', User)

    if band is None:
        return json_failure(design.bad_band_id)

    if not band.openness == Band.FULL_OPEN:
        try:
            member = BandMember.objects.get(user=request.user, band=band)
        except BandMember.DoesNotExist:
            return json_failure(design.can_only_invite_to_your_own_band)

        if member.role != BandMember.MANAGER:
            return json_failure(design.only_managers_can_create_invitations)

    # make sure user isn't already in band
    if BandMember.objects.filter(band=band, user=invitee).count() > 0:
        return json_failure(design.x_already_in_band.format(invitee.username))

    invite = BandInvitation()
    invite.inviter = request.user
    invite.band = band
    invite.expire_date = datetime.now() + timedelta(days=30)

    if invitee == None:
        invite.code = create_hash(32)
        invite.save()
        data = {'url': invite.redeemHyperlink()}
        return json_success(data)
    else:
        # make sure invitation doesn't exist already
        if BandInvitation.objects.filter(band=band, invitee=invitee).count() > 0:
            return json_failure(design.already_invited_x_to_your_band.format(invitee.username))

        invite.invitee = invitee
        invite.save()
        send_invitation_email(invite, request.get_host())

        return json_success()
Beispiel #30
0
def ajax_provide_mp3(request):
    version = get_obj_from_request(request.POST, 'version', ProjectVersion)

    if version is None:
        return json_failure(design.bad_version_id)

    band = version.project.band

    if not band.permission_to_work(request.user):
        return json_failure(design.you_dont_have_permission_to_work_on_this_band)

    if band.is_read_only():
        return json_failure(design.band_in_readonly_mode)

    mp3_handle = request.FILES.get('file')

    result = handle_mp3_upload(mp3_handle, version.song)
    if result['success']:
        version.song.save()
        return json_success()
    else:
        return json_failure(result['reason'])
Beispiel #31
0
def ajax_provide_mp3(request):
    version = get_obj_from_request(request.POST, 'version', ProjectVersion)

    if version is None:
        return json_failure(design.bad_version_id)

    band = version.project.band

    if not band.permission_to_work(request.user):
        return json_failure(
            design.you_dont_have_permission_to_work_on_this_band)

    if band.is_read_only():
        return json_failure(design.band_in_readonly_mode)

    mp3_handle = request.FILES.get('file')

    result = handle_mp3_upload(mp3_handle, version.song)
    if result['success']:
        version.song.save()
        return json_success()
    else:
        return json_failure(result['reason'])
Beispiel #32
0
def ajax_edit_comment(request):
    node = get_obj_from_request(request.POST, 'comment', SongCommentNode)

    if node is None:
        return json_failure(design.bad_song_comment_node_id)

    # can only edit own comments
    if node.owner != request.user:
        return json_failure(design.can_only_edit_your_own_comment)

    # can only delete within a certain amount of time
    now = datetime.now()
    if now > node.date_created + timedelta(hours=settings.COMMENT_EDIT_TIME_HOURS):
        return json_failure(design.too_late_to_edit_comment)

    content = request.POST.get('content', '')
    
    if len(content) == 0 or len(content) > 2000:
        return json_failure(design.content_wrong_length)

    node.content = content
    node.save()

    return json_success(node.to_dict())
Beispiel #33
0
def ajax_project(request):
    """
    return the project history. if a last_version is supplied, only
    return newer ones. Also return the current state - who has it
    checked out, etc.
    """
    last_version_id = get_val(request.GET, 'last_version', 0)
    project = get_obj_from_request(request.GET, 'project', Project)

    if project is None:
        return json_failure(design.bad_project_id)

    # make sure the user has permission
    data = {
        'user': {
            'is_authenticated': request.user.is_authenticated(),
            'has_permission':
            project.band.permission_to_critique(request.user),
        },
        'success': False,
    }

    if not data['user']['has_permission']:
        data['reason'] = design.you_dont_have_permission_to_critique_this_band
        return json_response(data)

    data['project'] = project.to_dict(SerializableModel.OWNER,
                                      chains=['checked_out_to'])
    data['project']['band'] = project.band.to_dict(SerializableModel.OWNER)

    if last_version_id == 0:
        # get entire version list
        data['versions'] = [
            version_to_dict(x, request.user)
            for x in ProjectVersion.objects.filter(project=project)
        ]
    else:
        data['versions'] = [
            version_to_dict(x, request.user)
            for x in ProjectVersion.objects.filter(project=project,
                                                   id__gt=last_version_id)
        ]

    data['user'].update(request.user.get_profile().to_dict())

    data['success'] = True
    return json_response(data)
Beispiel #34
0
def ajax_compo(request, compo_id):
    compo_id = int(compo_id)
    try:
        compo = get_object_or_404(Competition, pk=compo_id)
    except Competition.DoesNotExist:
        return json_failure(design.competition_not_found)

    data = {
        'user': {
            'is_authenticated': request.user.is_authenticated(),
        },
        'compo': compo_to_dict(compo, request.user),
        'party': {
            'buffer_time': settings.LISTENING_PARTY_BUFFER_TIME,
        }
    }

    if request.user.is_authenticated():
        max_votes = max_vote_count(compo.entry_set.count())
        used_votes = ThumbsUp.objects.filter(owner=request.user,
                                             entry__competition=compo)

        data['user'].update(request.user.get_profile().to_dict())
        data['votes'] = {
            'max': max_votes,
            'used': [x.to_dict() for x in used_votes],
            'left': max_votes - used_votes.count(),
        }
        user_entries = Entry.objects.filter(competition=compo,
                                            owner=request.user)
        data['submitted'] = (user_entries.count() > 0)

    def entry_to_dict(entry):
        data = entry.to_dict(chains=['owner.solo_band'])
        data['song'] = song_to_dict(entry.song, request.user)
        if request.user.is_authenticated() and entry.owner == request.user:
            version = ProjectVersion.objects.get(song=entry.song)
            data['project_id'] = version.project.pk
            data['version_number'] = version.version
        return data

    # entries. if competition is closed, sort by vote count.
    data['entries'] = [entry_to_dict(x) for x in compo.entry_set.all()]

    return json_response(data)
Beispiel #35
0
def ajax_compo(request, compo_id):
    compo_id = int(compo_id)
    try:
        compo = get_object_or_404(Competition, pk=compo_id)
    except Competition.DoesNotExist:
        return json_failure(design.competition_not_found)

    data = {
        'user': {
            'is_authenticated': request.user.is_authenticated(),
        },
        'compo': compo_to_dict(compo, request.user),
        'party': {
            'buffer_time': settings.LISTENING_PARTY_BUFFER_TIME,
        }
    }

    if request.user.is_authenticated():
        max_votes = max_vote_count(compo.entry_set.count())
        used_votes = ThumbsUp.objects.filter(owner=request.user, entry__competition=compo)

        data['user'].update(request.user.get_profile().to_dict());
        data['votes'] = {
            'max': max_votes,
            'used': [x.to_dict() for x in used_votes],
            'left': max_votes - used_votes.count(),
        }
        user_entries = Entry.objects.filter(competition=compo, owner=request.user)
        data['submitted'] = (user_entries.count() > 0)

    def entry_to_dict(entry):
        data = entry.to_dict(chains=['owner.solo_band'])
        data['song'] = song_to_dict(entry.song, request.user)
        if request.user.is_authenticated() and entry.owner == request.user:
            version = ProjectVersion.objects.get(song=entry.song)
            data['project_id'] = version.project.pk
            data['version_number'] = version.version
        return data

    # entries. if competition is closed, sort by vote count.
    data['entries'] = [entry_to_dict(x) for x in compo.entry_set.all()]

    return json_response(data)
Beispiel #36
0
def ajax_project(request):
    """
    return the project history. if a last_version is supplied, only
    return newer ones. Also return the current state - who has it
    checked out, etc.
    """
    last_version_id = get_val(request.GET, 'last_version', 0)
    project = get_obj_from_request(request.GET, 'project', Project)

    if project is None:
        return json_failure(design.bad_project_id)

    # make sure the user has permission
    data = {
        'user': {
            'is_authenticated': request.user.is_authenticated(),
            'has_permission': project.band.permission_to_critique(request.user),
        },
        'success': False,
    }

    if not data['user']['has_permission']:
        data['reason'] = design.you_dont_have_permission_to_critique_this_band
        return json_response(data)

    data['project'] = project.to_dict(SerializableModel.OWNER, chains=['checked_out_to'])
    data['project']['band'] = project.band.to_dict(SerializableModel.OWNER)

    if last_version_id == 0:
        # get entire version list
        data['versions'] = [version_to_dict(x, request.user) for x in ProjectVersion.objects.filter(project=project)]
    else:
        data['versions'] = [version_to_dict(x, request.user) for x in ProjectVersion.objects.filter(project=project, id__gt=last_version_id)]

    data['user'].update(request.user.get_profile().to_dict())

    data['success'] = True
    return json_response(data)
Beispiel #37
0
def ajax_comment(request):
    parent = get_obj_from_request(request.POST, 'parent', SongCommentNode)

    if parent is None:
        return json_failure(design.bad_song_comment_node_id)

    # make sure the user has permission to critique
    if parent.song is not None:
        if not parent.song.permission_to_critique(request.user):
            return json_failure(design.you_dont_have_permission_to_comment)
    else:
        if not parent.version.project.band.permission_to_critique(
                request.user):
            return json_failure(design.you_dont_have_permission_to_comment)

    # make sure the parent has enabled replies
    if parent.reply_disabled:
        return json_failure(design.comments_disabled_for_this_version)

    position = request.POST.get('position')
    if position is not None:
        try:
            position = float(position)
        except ValueError:
            position = None

        if position < 0 or position > parent.song.length:
            return json_failure(design.invalid_position)

    content = request.POST.get('content')

    if len(content) == 0 or len(content) > 2000:
        return json_failure(design.content_wrong_length)

    node = SongCommentNode()
    node.song = parent.song
    node.version = parent.version
    node.parent = parent
    node.owner = request.user
    node.content = content
    node.position = position
    node.reply_disabled = False
    node.save()

    return json_success(node.to_dict())
Beispiel #38
0
def ajax_comment(request):
    parent = get_obj_from_request(request.POST, 'parent', SongCommentNode)

    if parent is None:
        return json_failure(design.bad_song_comment_node_id)

    # make sure the user has permission to critique
    if parent.song is not None:
        if not parent.song.permission_to_critique(request.user):
            return json_failure(design.you_dont_have_permission_to_comment)
    else:
        if not parent.version.project.band.permission_to_critique(request.user):
            return json_failure(design.you_dont_have_permission_to_comment)

    # make sure the parent has enabled replies
    if parent.reply_disabled:
        return json_failure(design.comments_disabled_for_this_version)

    position = request.POST.get('position')
    if position is not None:
        try:
            position = float(position)
        except ValueError:
            position = None

        if position < 0 or position > parent.song.length:
            return json_failure(design.invalid_position)

    content = request.POST.get('content')

    if len(content) == 0 or len(content) > 2000:
        return json_failure(design.content_wrong_length)

    node = SongCommentNode()
    node.song = parent.song
    node.version = parent.version
    node.parent = parent
    node.owner = request.user
    node.content = content
    node.position = position
    node.reply_disabled = False
    node.save()

    return json_success(node.to_dict())
Beispiel #39
0
def ajax_email_invite(request):
    "send a band invitation by email."
    to_email = get_val(request.POST, 'email', '')
    band = get_obj_from_request(request.POST, 'band', Band)

    if band is None:
        return json_failure(design.bad_band_id)

    if not band.permission_to_invite(request.user):
        return json_failure(design.lack_permission_to_invite)

    if to_email == '':
        return json_failure(design.you_must_supply_an_email_address)

    if not is_valid_email(to_email):
        return json_failure(design.invalid_email_address)

    # if the email is a registered solid composer user, simply translate into direct invitation.
    try:
        local_user = User.objects.get(email=to_email)
    except User.DoesNotExist:
        local_user = None

    invite = BandInvitation()
    invite.inviter = request.user
    invite.band = band
    invite.role = BandMember.BAND_MEMBER

    subject = design.x_is_inviting_you_to_join_y.format(
        request.user.username, band.title)
    if local_user is not None:
        # make sure the user isn't already in the band
        if BandMember.objects.filter(user=local_user, band=band).count() > 0:
            return json_failure(
                design.x_already_in_band.format(local_user.username))

        # make sure there isn't already an invitation for them
        if BandInvitation.objects.filter(invitee=local_user,
                                         band=band).count() > 0:
            return json_failure(
                design.already_invited_x_to_your_band.format(
                    local_user.username))

        invite.invitee = local_user
        invite.save()

        # send a heads up email
        if local_user.get_profile().email_notifications:
            context = Context({
                'user': request.user,
                'band': band,
                'invite': invite,
                'host': request.get_host(),
            })
            message_txt = get_template(
                'workbench/email/invitation_direct.txt').render(context)
            message_html = get_template(
                'workbench/email/invitation_direct.html').render(context)
            send_html_mail(subject, message_txt, message_html, [to_email])

        return json_success()
    else:
        # create invitation link
        invite.expire_date = datetime.now() + timedelta(days=30)
        invite.code = create_hash(32)
        invite.save()

        # send the invitation email
        context = Context({
            'user': request.user,
            'band': band,
            'invite': invite,
            'host': request.get_host(),
        })
        message_txt = get_template(
            'workbench/email/invitation_link.txt').render(context)
        message_html = get_template(
            'workbench/email/invitation_link.html').render(context)
        send_html_mail(subject, message_txt, message_html, [to_email])

        return json_success()
Beispiel #40
0
def ajax_hear(request):
    """
    get new or all messages
    """
    last_message_str = request.GET.get('last_message', 'null')

    room = get_obj_from_request(request.GET, 'room', ChatRoom)
    if room is None:
        return json_failure(design.bad_room_id)

    # make sure user has permission to be in this room
    data = {
        'user': {
            'is_authenticated': request.user.is_authenticated(),
            'permission_read': room.permission_to_hear(request.user),
            'permission_write': room.permission_to_chat(request.user),
        },
        'room': room.to_dict(),
        'messages': [],
        'success': True
    }

    if request.user.is_authenticated():
        data['user'].update({
            'username': request.user.username,
        })

    if data['user']['permission_read']:
        def add_to_message(msg):
            return {
                'id': msg.id,
                'type': msg.type,
                'author': {
                    'username': msg.author.username,
                    'id': msg.author.id,
                },
                'message': msg.message,
                'timestamp': msg.timestamp,
            }

        if last_message_str == 'null':
            # get entire log for this chat.
            data['messages'] = [add_to_message(x) for x in ChatMessage.objects.filter(room=room)]
        else:
            try:
                last_message_id = int(last_message_str)
            except ValueError:
                last_message_id = 0

            data['messages'] = [add_to_message(x) for x in ChatMessage.objects.filter(room=room, id__gt=last_message_id)]

    if data['user']['permission_write']:
        # mark an appearance in the ChatRoom
        if request.user.is_authenticated() and room.is_active():
            appearances = Appearance.objects.filter(person=request.user, room=room)
            if appearances.count() > 0:
                appearances[0].save() # update the timestamp
            else:
                new_appearance = Appearance()
                new_appearance.room = room
                new_appearance.person = request.user
                new_appearance.save()

                # join message
                m = ChatMessage()
                m.room=room
                m.type=ChatMessage.JOIN
                m.author=request.user
                m.save()

    return json_response(data)
Beispiel #41
0
def ajax_checkin(request):
    project = get_obj_from_request(request.POST, 'project', Project)

    if project is None:
        return json_failure(design.bad_project_id)

    # make sure project is checked out to request user
    if project.checked_out_to is None or project.checked_out_to.id != request.user.id:
        return json_failure(design.not_checked_out_to_you)

    if project.band.is_read_only():
        return json_failure(design.band_in_readonly_mode)

    project_file = request.FILES.get('project_file')
    mp3_preview = request.FILES.get('mp3_preview')
    comments = request.POST.get('comments', '')

    if project_file is None and mp3_preview is None:
        # just check in
        project.checked_out_to = None
        project.save()

        # create log entry
        entry = LogEntry()
        entry.entry_type = LogEntry.SONG_JUST_CHECK_IN
        entry.band = project.band
        entry.catalyst = request.user
        entry.project = project
        entry.save()

        return json_success()

    # must supply a project file
    if project_file is None:
        return json_failure(design.must_submit_project_file)

    new_version_number = project.latest_version.version + 1
    filename_appendix = "_" + str(new_version_number)

    # upload the song and make a new project version
    result = upload_song(request.user,
                         file_mp3_handle=mp3_preview,
                         file_source_handle=project_file,
                         band=project.band,
                         song_title=project.title,
                         song_comments=comments,
                         filename_appendix=filename_appendix)

    if not result['success']:
        return json_failure(result['reason'])

    song = result['song']
    song.save()

    # make a new version
    version = ProjectVersion()
    version.project = project
    version.song = song
    version.version = new_version_number
    version.saveNewVersion()

    # update project info
    project.checked_out_to = None
    project.latest_version = version
    project.title = song.title
    project.save()

    return json_success()
Beispiel #42
0
def ajax_checkin(request):
    project = get_obj_from_request(request.POST, 'project', Project)
    
    if project is None:
        return json_failure(design.bad_project_id)

    # make sure project is checked out to request user
    if project.checked_out_to is None or project.checked_out_to.id != request.user.id:
        return json_failure(design.not_checked_out_to_you)

    if project.band.is_read_only():
        return json_failure(design.band_in_readonly_mode)

    project_file = request.FILES.get('project_file')
    mp3_preview = request.FILES.get('mp3_preview')
    comments = request.POST.get('comments', '')

    if project_file is None and mp3_preview is None:
        # just check in
        project.checked_out_to = None
        project.save()

        # create log entry
        entry = LogEntry()
        entry.entry_type = LogEntry.SONG_JUST_CHECK_IN
        entry.band = project.band
        entry.catalyst = request.user
        entry.project = project
        entry.save()

        return json_success()
    
    # must supply a project file
    if project_file is None:
        return json_failure(design.must_submit_project_file)

    new_version_number = project.latest_version.version + 1
    filename_appendix = "_" + str(new_version_number)

    # upload the song and make a new project version
    result = upload_song(request.user,
        file_mp3_handle=mp3_preview,
        file_source_handle=project_file,
        band=project.band,
        song_title=project.title,
        song_comments=comments,
        filename_appendix=filename_appendix)

    if not result['success']:
        return json_failure(result['reason'])

    song = result['song']
    song.save()

    # make a new version
    version = ProjectVersion()
    version.project = project
    version.song = song
    version.version = new_version_number
    version.saveNewVersion()

    # update project info
    project.checked_out_to = None
    project.latest_version = version
    project.title = song.title
    project.save()

    return json_success()
Beispiel #43
0
def ajax_submit_entry(request):
    compo = get_obj_from_request(request.POST, 'compo', Competition)
    if compo is None:
        return json_failure(design.competition_not_found)

    # make sure it's still submission time
    now = datetime.now()
    if now >= compo.submit_deadline:
        return json_failure(design.past_submission_deadline)

    if now <= compo.start_date:
        return json_failure(design.competition_not_started)

    title = request.POST.get('entry-title','')
    comments = request.POST.get('entry-comments', '')
    mp3_file = request.FILES.get('entry-file-mp3')
    source_file = request.FILES.get('entry-file-source')
    is_open_source = request.POST.get('entry-open-source', False)

    entries = Entry.objects.filter(owner=request.user, competition=compo)
    resubmitting = entries.count() > 0

    # make sure files are small enough
    if not resubmitting and mp3_file is None:
        return json_failure(design.mp3_required)

    if mp3_file is not None and mp3_file.size > settings.FILE_UPLOAD_SIZE_CAP:
        return json_failure(design.mp3_too_big)

    if source_file is not None:
        if source_file.size > settings.FILE_UPLOAD_SIZE_CAP:
            return json_failure(design.source_file_too_big)

    if title == '':
        return json_failure(design.entry_title_required)

    if mp3_file is not None:
        band = request.user.get_profile().solo_band

        if resubmitting:
            entry = entries[0]
            project = Project.objects.get(latest_version__song=entry.song)
            new_version_number = project.latest_version.version + 1
            filename_appendix = "_" + str(new_version_number)
        else:
            filename_appendix = ""

        result = upload_song(request.user,
            file_mp3_handle=mp3_file,
            file_source_handle=source_file, 
            max_song_len=settings.COMPO_ENTRY_MAX_LEN,
            band=band,
            song_title=title,
            song_album=compo.title,
            song_comments=comments,
            filename_appendix=filename_appendix)

        if not result['success']:
            return json_failure(result['reason'])

        song = result['song']
        song.is_open_source = is_open_source
        song.is_open_for_comments = True
        song.save()

        # make a new version and attach that to the entry
        if resubmitting:

            # create new version
            version = ProjectVersion()
            version.project = project
            version.song = song
            version.version = new_version_number
            version.saveNewVersion()

            old_length = entry.song.length
            buffer_time = 0
        else:
            # create the project
            project = Project()
            project.band = band
            project.save()

            # create the first version
            version = ProjectVersion()
            version.project = project
            version.song = song
            version.version = 1
            version.saveNewVersion()

            # subscribe the creator
            project.subscribers.add(request.user)
            project.save()

            # create new entry
            entry = Entry()
            entry.competition = compo
            entry.owner = request.user

            old_length = 0
            buffer_time = settings.LISTENING_PARTY_BUFFER_TIME

        entry.song = song
        entry.save()

        # update competition dates based on this newfound length 
        vote_period_delta = timedelta(seconds=compo.vote_period_length)
        if compo.have_listening_party:
            compo.listening_party_end_date += timedelta(seconds=(song.length-old_length+buffer_time))
            compo.vote_deadline = compo.listening_party_end_date + vote_period_delta
        else:
            compo.vote_deadline = compo.submit_deadline + vote_period_delta
        compo.save()

        chatroom = compo.chat_room
        chatroom.end_date = compo.listening_party_end_date + timedelta(hours=1)
        chatroom.save()
    else:
        # only providing source and possibly renaming.
        entry = entries[0]
        song = entry.song

        if source_file is not None:
            handle_project_upload(source_file, request.user, song)

        song.title = title
        song.is_open_source = is_open_source
        song.comments = comments
        song.save()

    return json_response({'success': True})
Beispiel #44
0
def ajax_submit_entry(request):
    compo = get_obj_from_request(request.POST, 'compo', Competition)
    if compo is None:
        return json_failure(design.competition_not_found)

    # make sure it's still submission time
    now = datetime.now()
    if now >= compo.submit_deadline:
        return json_failure(design.past_submission_deadline)

    if now <= compo.start_date:
        return json_failure(design.competition_not_started)

    title = request.POST.get('entry-title', '')
    comments = request.POST.get('entry-comments', '')
    mp3_file = request.FILES.get('entry-file-mp3')
    source_file = request.FILES.get('entry-file-source')
    is_open_source = request.POST.get('entry-open-source', False)

    entries = Entry.objects.filter(owner=request.user, competition=compo)
    resubmitting = entries.count() > 0

    # make sure files are small enough
    if not resubmitting and mp3_file is None:
        return json_failure(design.mp3_required)

    if mp3_file is not None and mp3_file.size > settings.FILE_UPLOAD_SIZE_CAP:
        return json_failure(design.mp3_too_big)

    if source_file is not None:
        if source_file.size > settings.FILE_UPLOAD_SIZE_CAP:
            return json_failure(design.source_file_too_big)

    if title == '':
        return json_failure(design.entry_title_required)

    if mp3_file is not None:
        band = request.user.get_profile().solo_band

        if resubmitting:
            entry = entries[0]
            project = Project.objects.get(latest_version__song=entry.song)
            new_version_number = project.latest_version.version + 1
            filename_appendix = "_" + str(new_version_number)
        else:
            filename_appendix = ""

        result = upload_song(request.user,
                             file_mp3_handle=mp3_file,
                             file_source_handle=source_file,
                             max_song_len=settings.COMPO_ENTRY_MAX_LEN,
                             band=band,
                             song_title=title,
                             song_album=compo.title,
                             song_comments=comments,
                             filename_appendix=filename_appendix)

        if not result['success']:
            return json_failure(result['reason'])

        song = result['song']
        song.is_open_source = is_open_source
        song.is_open_for_comments = True
        song.save()

        # make a new version and attach that to the entry
        if resubmitting:

            # create new version
            version = ProjectVersion()
            version.project = project
            version.song = song
            version.version = new_version_number
            version.saveNewVersion()

            old_length = entry.song.length
            buffer_time = 0
        else:
            # create the project
            project = Project()
            project.band = band
            project.save()

            # create the first version
            version = ProjectVersion()
            version.project = project
            version.song = song
            version.version = 1
            version.saveNewVersion()

            # subscribe the creator
            project.subscribers.add(request.user)
            project.save()

            # create new entry
            entry = Entry()
            entry.competition = compo
            entry.owner = request.user

            old_length = 0
            buffer_time = settings.LISTENING_PARTY_BUFFER_TIME

        entry.song = song
        entry.save()

        # update competition dates based on this newfound length
        vote_period_delta = timedelta(seconds=compo.vote_period_length)
        if compo.have_listening_party:
            compo.listening_party_end_date += timedelta(
                seconds=(song.length - old_length + buffer_time))
            compo.vote_deadline = compo.listening_party_end_date + vote_period_delta
        else:
            compo.vote_deadline = compo.submit_deadline + vote_period_delta
        compo.save()

        chatroom = compo.chat_room
        chatroom.end_date = compo.listening_party_end_date + timedelta(hours=1)
        chatroom.save()
    else:
        # only providing source and possibly renaming.
        entry = entries[0]
        song = entry.song

        if source_file is not None:
            handle_project_upload(source_file, request.user, song)

        song.title = title
        song.is_open_source = is_open_source
        song.comments = comments
        song.save()

    return json_response({'success': True})
Beispiel #45
0
def ajax_email_invite(request):
    "send a band invitation by email."
    to_email = get_val(request.POST, 'email', '')
    band = get_obj_from_request(request.POST, 'band', Band)
    
    if band is None:
        return json_failure(design.bad_band_id)

    if not band.permission_to_invite(request.user):
        return json_failure(design.lack_permission_to_invite)

    if to_email == '':
        return json_failure(design.you_must_supply_an_email_address)

    if not is_valid_email(to_email):
        return json_failure(design.invalid_email_address)

    # if the email is a registered solid composer user, simply translate into direct invitation.
    try:
        local_user = User.objects.get(email=to_email)
    except User.DoesNotExist:
        local_user = None

    invite = BandInvitation()       
    invite.inviter = request.user
    invite.band = band
    invite.role = BandMember.BAND_MEMBER

    subject = design.x_is_inviting_you_to_join_y.format(request.user.username, band.title)
    if local_user is not None:
        # make sure the user isn't already in the band
        if BandMember.objects.filter(user=local_user, band=band).count() > 0:
            return json_failure(design.x_already_in_band.format(local_user.username))

        # make sure there isn't already an invitation for them
        if BandInvitation.objects.filter(invitee=local_user, band=band).count() > 0:
            return json_failure(design.already_invited_x_to_your_band.format(local_user.username))

        invite.invitee = local_user
        invite.save()
        
        # send a heads up email
        if local_user.get_profile().email_notifications:
            context = Context({
                'user': request.user,
                'band': band,
                'invite': invite,
                'host': request.get_host(),
            })
            message_txt = get_template('workbench/email/invitation_direct.txt').render(context)
            message_html = get_template('workbench/email/invitation_direct.html').render(context)
            send_html_mail(subject, message_txt, message_html, [to_email])

        return json_success()
    else:
        # create invitation link
        invite.expire_date = datetime.now() + timedelta(days=30)
        invite.code = create_hash(32)
        invite.save()

        # send the invitation email
        context = Context({
            'user': request.user,
            'band': band,
            'invite': invite,
            'host': request.get_host(),
        })
        message_txt = get_template('workbench/email/invitation_link.txt').render(context)
        message_html = get_template('workbench/email/invitation_link.html').render(context)
        send_html_mail(subject, message_txt, message_html, [to_email])

        return json_success()