class IssueCreateForm(forms.ModelForm):
    issueUrl = forms.CharField(label="issueUrl")
    class Meta:
        model = Issue
        fields = ('title','language','content') class BountyCreateForm(forms.ModelForm):

    class Meta:
        model = Bounty
        fields = ('price',) class UserProfileForm(forms.ModelForm):
    user = forms.IntegerField(label="", widget=forms.HiddenInput(), required=False)
    first_name = forms.CharField(label="First Name")
    last_name = forms.CharField(required=False, label="Last Name")
    email = forms.EmailField(label="Email", max_length=255)
    
    class Meta:
        model = UserProfile
        exclude = ('balance',)

    def __init__(self, *args, **kwargs):
      super(UserProfileForm, self).__init__(*args, **kwargs)
      user = kwargs['instance'].user
        
      if user.pk:
          self.fields['first_name'].initial = user.first_name
          self.fields['last_name'].initial = user.last_name
          self.fields['email'].initial = user.email

    def clean_email(self):
      email = self.cleaned_data.get("email")

      if self.instance.user.email != email:
        try:
            User.objects.get(email = email)
            raise forms.ValidationError("Email taken.")
        except User.DoesNotExist:
              pass
      return email class Issue(models.Model):
    """
    An issue from a web service entered into Coder Bounty
    """

    OPEN_STATUS = "open"
    IN_REVIEW_STATUS = "in review"
    PAID_STATUS = "paid"
    CLOSED_STATUS = "closed"
    TAKEN_STATUS = "taken"
    STATUS_CHOICES = (
        (OPEN_STATUS, "open"),
        (IN_REVIEW_STATUS, "in review"),
        (TAKEN_STATUS, "taken"),
        (PAID_STATUS, "paid"),
        (CLOSED_STATUS, "closed"),
    )
    LANGUAGES = (
        ("C#", "C#"),
        ("C", "C"),
        ("C++", "C++"),
        ("CSS", "CSS"),
        ("Erlang", "Erlang"),
        ("Go", "Go"),
        ("Haskell", "Haskell"),
        ("HTML", "HTML"),
        ("Java", "Java"),
        ("JavaScript", "JavaScript"),
        ("NodeJS", "NodeJS"),
        ("Perl", "Perl"),
        ("PHP", "PHP"),
        ("Python", "Python"),
        ("Ruby", "Ruby"),
        ("Scala", "Scala"),
        ("Shell", "Shell"),
        ("VB", "VB"),
    )

    # creator = models.ForeignKey(User, related_name="+", null=True, blank=True)
    service = models.ForeignKey(Service, related_name="+", on_delete=models.CASCADE)
    number = models.IntegerField()
    project = models.CharField(max_length=255)
    user = models.CharField(max_length=255, null=True, blank=True)
    image = models.ImageField(upload_to="images/projects", blank=True)
    title = models.CharField(max_length=255)
    content = models.TextField(max_length=400)
    language = models.CharField(max_length=255, choices=LANGUAGES, blank=True)
    status = models.CharField(
        max_length=255, choices=STATUS_CHOICES, default=OPEN_STATUS
    )
    winner = models.ForeignKey(
        User, related_name="+", null=True, blank=True, on_delete=models.CASCADE
    )
    paid = models.DecimalField(max_digits=10, decimal_places=0, null=True, blank=True)
    closed_by = models.CharField(max_length=255, null=True, blank=True)
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)
    notified_user = models.BooleanField(default=False)
    views = models.IntegerField(default=1)

    def bounties(self):
        return Bounty.objects.filter(issue=self).order_by("-ends")

    def all_bounties(self):
        return Bounty.objects.filter(issue=self).order_by("-ends")

    def bounty(self):
        return int(self.bounties().aggregate(Sum("price"))["price__sum"] or 0)

    def html_url(self):
        service = self.service
        template = Template(service.link_template)
        return (
            "http://"
            + service.domain
            + template.substitute(
                {"user": self.user, "project": self.project, "number": self.number}
            )
        )

    def api_url(self):
        service = self.service
        template = Template(service.template)
        return service.api_url + template.substitute(
            {"user": self.user, "project": self.project, "number": self.number}
        )

    def get_api_data(self, url=None):
        if self.service.name == "Github":
            if not url:
                url = self.api_url()
            return json.load(urllib.request.urlopen(url))

    def __unicode__(self):
        return "%s issue #%s" % (self.project, self.number)

    def get_absolute_url(self):
        return "/issue/%s" % self.id

    def get_taker(self):
        date_from = datetime.datetime.now() - datetime.timedelta(days=1)
        try:
            return Taker.objects.filter(issue=self, created__gte=date_from).order_by(
                "-created"
            )[0]
        except:
            return False

    class Meta:
        ordering = ["-created"]
        unique_together = ("service", "number", "project")

    # there was an issue when saving from admin
    # def save(self, *args, **kwargs):
    #     #add issue status to activity feed
    #     super(Issue, self).save(*args, **kwargs)
    #     if self.status == Issue.IN_REVIEW_STATUS:
    #         action.send(self.user, verb="is in review now",  target=self.number)
    #     elif self.status == Issue.OPEN_STATUS:
    #         action.send(self.user, verb="opened issue", target=self)
    #     elif self.status == Issue.PAID_STATUS:
    #         action.send(self.user, verb="was paid", target=self.number) class UserProfile(models.Model):
    CHOICE_PAYMANT_SERVICE = (("paypal", "Paypal"),)

    user = models.OneToOneField(
        User, related_name="userprofile", on_delete=models.CASCADE
    )
    balance = models.DecimalField(
        max_digits=10, decimal_places=2, null=True, blank=True
    )
    payment_service = models.CharField(
        max_length=255, null=True, blank=True, choices=CHOICE_PAYMANT_SERVICE
    )
    payment_service_email = models.EmailField(
        max_length=255, null=True, blank=True, default=""
    )

    def avatar(self, size=36):
        for account in self.user.socialaccount_set.all():
            if "avatar_url" in account.extra_data:
                return account.extra_data["avatar_url"]
            elif "picture" in account.extra_data:
                return account.extra_data["picture"]

        gravatar_url = "http://www.gravatar.com/avatar.php?"
        gravatar_url += urllib.parse.urlencode(
            {
                "gravatar_id": hashlib.md5(
                    self.user.email.lower().encode("utf-8")
                ).hexdigest(),
                "default": "retro",
                "size": str(size),
            }
        )
        return gravatar_url

    def avatar_large(self, size=200):
        return self.avatar(size=200)

    def bounties_won(self, size=200):
        return (
            Payment.objects.filter(user=self.user).aggregate(Sum("amount"))[
                "amount__sum"
            ]
            or 0
        )

    def save(self, *args, **kwargs):
        if self.pk is None:
            action.send(self.user, verb="signed up")
            cache.clear()
        super(UserProfile, self).save(*args, **kwargs)

    def bounties_placed(self):
        return (
            Bounty.objects.filter(user=self.user).aggregate(Sum("price"))["price__sum"]
            or 0
        )

    def __unicode__(self):
        return self.user.email class Bounty(models.Model):
    """
    A bounty made on an issue
    """

    user = models.ForeignKey(User, on_delete=models.CASCADE)
    issue = models.ForeignKey(Issue, on_delete=models.CASCADE)
    price = models.DecimalField(max_digits=10, decimal_places=0)
    ends = models.DateTimeField(null=True, blank=True)
    created = models.DateTimeField(auto_now_add=True)
    checkout_id = models.IntegerField(null=True)

    def time_remaining(self):
        if self.issue.status == Issue.OPEN_STATUS:
            return timeuntil(self.ends, datetime.datetime.now()).split(",")[0]
        return timeuntil(self.ends, self.created).split(",")[0]

    def get_twitter_message(self):
        msg = "Added $%s bounty for %s issue %s. http://coderbounty.com/issue/%s" % (
            self.price,
            self.issue.project,
            self.issue.number,
            self.issue.id,
        )
        return msg

    def save(self, *args, **kwargs):
        if self.pk is None:
            action.send(
                self.user,
                verb="placed a $" + str(self.price) + " bounty on ",
                target=self.issue,
            )
            cache.clear()

        super(Bounty, self).save(*args, **kwargs) class Service(models.Model):
    """
    A web service that allows users to enter issues on projects
    """

    name = models.CharField(max_length=255)
    domain = models.CharField(max_length=255)
    template = models.CharField(max_length=255)
    regex = models.CharField(max_length=255)
    type = models.CharField(
        max_length=255, choices=(("json", "json"), ("xml", "xml"), ("http", "http"))
    )
    api_url = models.CharField(max_length=255, blank=True)
    link_template = models.CharField(max_length=255, blank=True)

    def __unicode__(self):
        return self.name class Taker(models.Model):
    issue = models.ForeignKey(Issue, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    created = models.DateTimeField(auto_now_add=True)

    def time_remaining(self):
        date_from = self.created + datetime.timedelta(hours=6)
        end_time = date_from - datetime.datetime.utcnow().replace(tzinfo=utc)
        return str(end_time).split(".")[0]

    def time_remaining_seconds(self):
        date_from = self.created + datetime.timedelta(hours=6)
        return (date_from - datetime.datetime.utcnow().replace(tzinfo=utc)).seconds

    def expired(self):
        return (datetime.datetime.utcnow().replace(tzinfo=utc) - self.created).days >= 3 class Solution(models.Model):

    OPEN = "open"
    MERGED = "merged"
    PAID = "paid"
    STATUS_CHOICES = (
        (OPEN, "open"),
        (MERGED, "merged"),
        (PAID, "paid"),
    )

    issue = models.ForeignKey(Issue, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)
    url = models.URLField(help_text="Pull Request URL")
    status = models.CharField(max_length=250, choices=STATUS_CHOICES, default=OPEN)

    def get_absolute_url(self):
        return "/solution/%s" % self.id

    def __unicode__(self):
        return "solution #%s" % self.id

    def notify_owner(self):
        """Email Bounty Owner"""
        pass

    def notify_coder(self, status):
        "notify coder about solution status"
        pass

    def notify_coderbounty(self):
        "notify coderbounty to realse funds"
        pass

    def save(self, *args, **kwargs):
        if self.pk is None:
            # notify owner if there's a new solution
            # a solution for project issue #34 has been submitted by username!  Please take a look at it here0link
            # and either approve or reject it.
            self.notify_owner()

        if self.status == Solution.PAID:
            # notify coder to revision the solution
            # your solution was not approved, please revise it and submit another solution.

            self.notify_coder(status=self.status)

        if self.status == Solution.MERGED:
            # ask cb to realease bounty
            # notify coder that PR has been accepted
            # your solution has been approved, the payment is on it's way!
            self.notify_coderbounty()
            self.notify_coder(status=self.status)

        super(Solution, self).save(*args, **kwargs) class Payment(models.Model):
    issue = models.ForeignKey(Issue, on_delete=models.CASCADE)
    solution = models.ForeignKey(Solution, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    amount = models.DecimalField(max_digits=10, decimal_places=0)
    txn_id = models.CharField(max_length=255, blank=True, null=True)
    created = models.DateTimeField()
    updated = models.DateTimeField() def get_issue_helper(request, url):
    parsed_url = urlparse(url)

    try:
        service = Service.objects.get(domain=parsed_url.netloc)
    except Service.DoesNotExist:
        messages.error(request, "Not specified service")
        return False

    helper = get_helper_instance(service, "IssueHelper")

    return helper def leaderboard():
    return (
        User.objects.filter(payment__amount__gt=0)
        .annotate(total=Sum("payment__amount"))
        .order_by("-total")[:10]
    ) def post_to_slack(bounty):
    if not settings.DEBUG:

        payload = {
            "text": str(bounty.user)
            + " placed a Bounty of $"
            + str(bounty.price)
            + " More details at http://coderbounty.com"
            + str(bounty.issue.get_absolute_url())
        }

        url = "https://hooks.slack.com/services/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"
        r = requests.post(url, data=json.dumps(payload)) def submit_issue_taker(data):
    issueID = data["issue"]
    user = data["user"]
    issuetakenTime = data["issueStartTime"]
    issueTaker = data["user"]
    issueEndtime = issuetakenTime + datetime.timedelta(hours=24)
    issue = Issue.objects.get(pk=issueID)
    issue.status = "taken"
    issue.save()
    taker = Taker(
        is_taken=True,
        issu_id=issueID,
        issue=issue,
        user=user,
        status="taken",
        issueTaken=issuetakenTime,
        issueEnd=issueEndtime,
    )
    taker.save()
    return data def get_comment_helper(service):
    helper = get_helper_instance(service, "CommentHelper")
    return helper def create_comment(issue=None, comment=None):
    if not comment:
        comment = (
            "![Coderbounty](http://www.coderbounty.com/get_bounty_image/"
            + str(issue.id)
            + "/) http://coderbounty.com/issue/"
            + str(issue.id)
        )
    # see if we've commented already and just update
    # try to have one comment that we update
    return globals()[
        "post_" + issue.service.name.replace(" ", "_").lower() + "_comment"
    ](issue, comment)
from .forms import IssueCreateForm, BountyCreateForm, UserProfileForm
from actstream import action
from actstream.models import Action, user_stream
from django.conf import settings
from django.contrib import messages
from django.contrib.auth import get_user_model
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.contrib.auth.models import User
from django.contrib.messages.views import SuccessMessageMixin
from django.core import serializers
from django.urls import reverse
from django.core.mail import send_mail
from django.db.models import Count
from django.http import HttpResponse
from django.shortcuts import redirect, render
from django.views.generic import ListView, DetailView, FormView, TemplateView, View
from django.views.generic.edit import UpdateView
from django.views.generic.detail import SingleObjectMixin
from .models import Issue, UserProfile, Bounty, Service, Taker, Solution, Payment
from .utils import (
    get_issue_helper,
    leaderboard,
    post_to_slack,
    submit_issue_taker,
    get_comment_helper,
    create_comment,
)
from wepay import WePay
from time import strftime
from allauth.socialaccount.models import (
    SocialToken,
    SocialApp,
    SocialAccount,
    SocialLogin,
)
from django.http import Http404
from django.views.decorators.cache import cache_page
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.template.loader import render_to_string
from django.db.models import Sum
    from PIL import Image
    from PIL import ImageFont
    from PIL import ImageDraw
import datetime
import json
import requests
                import paypalrestsdk
            import paypalrestsdk
            import random
            import string
            import paypalrestsdk
                    + " paymentID"
                    + self.request.GET.get("paymentId"),
                    "payment error",
                    "support@coderbounty.com",
                    ["support@coderbounty.com"],
                    html_message="payment error",
                )

        return super(IssueDetailView, self).get(request, *args, **kwargs)

    @method_decorator(login_required)
    def post(self, request, *args, **kwargs):
        comment_service_helper = get_comment_helper(self.get_object().service)

        comment_service_helper.load_comments(self.get_object())
        if self.get_object().status in ("open", "in review"):
            if self.get_object().get_api_data()["state"] == "closed":
                issue = self.get_object()
                if Solution.objects.filter(issue=issue):
                    # process the payment here and mark it as paid if the solution was accepted
                    issue.status = "in review"
                else:
                    issue.status = "closed"
                issue.save()
        if self.request.POST.get("take"):
            if self.request.user.is_authenticated:
                taker = Taker(issue=self.get_object(), user=self.request.user)
                taker.save()
                issue = self.get_object()
                issue.status = "taken"
                issue.save()
                action.send(
                    self.request.user, verb="has taken ", target=self.get_object()
                )
                msg_plain = render_to_string(
                    "email/issue_taken.txt",
                    {
                        "user": self.request.user,
                        "issue": self.get_object(),
                        "time_remaining": taker.time_remaining,
                    },
                )
                msg_html = render_to_string(
                    "email/issue_taken.txt",
                    {
                        "user": self.request.user,
                        "issue": self.get_object(),
                        "time_remaining": taker.time_remaining,
                    },
                )

                send_mail(
                    "You have taken issue: "
                    + self.get_object().project
                    + " issue #"
                    + str(self.get_object().number),
                    msg_plain,
                    "support@coderbounty.com",
                    [self.request.user.email],
                    html_message=msg_html,
                )
            else:
                return redirect(
                    "/accounts/login/?next=/issue/" + str(self.get_object().id)
                )
        if self.request.POST.get("solution"):
            if self.get_object().status not in ("closed", "in review"):

                if self.request.user.is_authenticated:
                    solution = Solution(
                        issue=self.get_object(),
                        user=self.request.user,
                        url=request.POST.get("solution"),
                    )
                    solution.save()
                    issue = self.get_object()
                    issue.status = "in review"
                    issue.save()
                    action.send(
                        self.request.user,
                        verb="posted ",
                        action_object=solution,
                        target=self.get_object(),
                    )

                    bounty_poster = Bounty.objects.filter(issue=self.get_object())[
                        :1
                    ].get()

                    msg_plain = render_to_string(
                        "email/solution_posted.txt",
                        {"user": bounty_poster.user, "issue": self.get_object()},
                    )
                    msg_html = render_to_string(
                        "email/solution_posted.txt",
                        {"user": bounty_poster.user, "issue": self.get_object()},
                    )

                    send_mail(
                        "Coderbounty solution posted on "
                        + self.get_object().project
                        + " issue #"
                        + str(self.get_object().number),
                        msg_plain,
                        "support@coderbounty.com",
                        [bounty_poster.user.email],
                        html_message=msg_html,
                    )

                else:
                    return redirect(
                        "/accounts/login/?next=/issue/" + str(self.get_object().id)
                    )

        return super(IssueDetailView, self).get(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super(IssueDetailView, self).get_context_data(**kwargs)
        context["leaderboard"] = leaderboard()
        context["taker"] = self.get_object().get_taker()

        context["takers"] = Taker.objects.filter(issue=self.get_object()).order_by(