# Path: narwhal/core/profile/models.py
# class Profile(Model):
#     user = AutoOneToOneField(User, related_name='profile')
#     key = CharField(max_length=32, default=lambda: md5(os.urandom(40)).hexdigest())
#     
#     avatar = ImageField(upload_to='profiles/avatar/', blank=True, null=True)
#     uploaded = BigIntegerField(default=0)
#     downloaded = BigIntegerField(default=0)
#     
#     # extra_data should only be used for data that should not be 
#     # searched upon, such as chat protocol addresses
#     data = JSONField(default=lambda: {})
#     
#     #def __getattr__(self, name):
#     #    try: return self.extra_data[name]
#     #    except KeyError, e: raise AttributeError, e
#     #def __setattr__(self, name, value):
#     #    self.extra_data[name] = value
#     
#     def __unicode__(self):
#         return self.user.username
#     
#     @permalink
#     def get_absolute_url(self):
#         return ('profile:profile', (), {'username': self.user.username} )
#     
#     def gravatar(self):
#         if self.user.email:
#             return "http://www.gravatar.com/avatar/%s.png?d=%s" % (
#                 md5(self.user.email.lower().strip()).hexdigest(),
#                 settings.PROFILE_GRAVATAR_STANDIN )
#         
#     def ratio(self):
#         return "%.2f"% (self.total_uploaded / float(self.total_downloaded))
# 
# Path: narwhal/core/torrent/models.py
# class Torrent(Model):
#     class Meta:
#         ordering = ('-added',)
#         app_label = 'torrent'
#         verbose_name =_('torrent')
#         verbose_name_plural =_('torrents')
# 
#     category = ForeignKey(Category, related_name='torrents')
#     title = CharField(_('Title'), max_length=80)
#     slug = SlugField(_('Slug'))
#     user = ForeignKey('auth.User', blank=True, null=True, verbose_name=_('Author'))
#     image = ImageField(_('Image'), upload_to='img/torrents', blank=True, null=True)
#     description = TextField(_('Description'))
#     added = DateTimeField(_('Added'), auto_now_add=True, editable=False)
#     
#     torrent = FileField(upload_to='torrent/')
#     data = JSONField(editable=False, default=lambda: {})
#     info_hash = CharField(_('Info hash'), unique=True, max_length=40, db_index=True, editable=False)
#     seeders = PositiveIntegerField(editable=False, default=0)
#     leechers = PositiveIntegerField(editable=False, default=0)
#     downloaded = PositiveIntegerField(editable=False, default=0)
#     comments_enabled = BooleanField(_('comments enabled'), default=True)
#     
#     tags = TaggableManager()
#     
#     def single_file(self):
#         print self.data
#         return 'length' in self.data['info'].keys()
#     single_file.boolean = True
# 
#     def files(self):
#         if self.single_file():
#             return [ self.data['info']['name'] ]
#         else:
#             return [ ( "/".join(f['path']), f['length']) for f in self.data['info']['files'] ]
# 
#     def num_files(self):
#         if self.single_file():
#             return 1
#         else:
#             return len(self.data['info']['files'])
# 
#     def size(self):
#         if 'length' in self.data['info'].keys():
#             return self.data['info']['length']
#         elif 'files' in self.data['info'].keys():
#             return reduce(lambda a,b:a+b, (length for file, length in self.data['info']['files'].items()) )
# 
#     def __unicode__(self):
#         return smart_unicode(self.title)
# 
#     def validate(self):
#         fkeys = self.data['info'].keys()
#         if not 'length' in fkeys and  not 'files' in fkeys:
#             raise ValidationError(_('Torrent File is not valid: does not contain any files.'))
#         #extra validation performed by subclasses
# 
#     def save(self, **kwargs):
#         #from markdown import Markdown
#         #md = Markdown(extensions=['footnotes'], safe_mode=True)
#         #self.html = md.convert(self.text)
#         if not self.slug:
#             self.slug = slugify(self.title)[:self._meta.get_field_by_name('slug')[0].max_length]
#         super(Torrent, self).save(**kwargs)
# 
# Path: narwhal/core/tracker/models.py



from urlparse import parse_qsl
from django.conf import settings
from django.http import HttpResponse, Http404
from django.utils.datastructures import MultiValueDictKeyError
from django.core.cache import cache
from django.contrib.auth.models import User
from annoying.decorators import render_to
from bencode import bencode, bdecode
from narwhal.core.profile.models import Profile
from narwhal.core.torrent.models import Torrent
from narwhal.core.tracker.models import Peer
    
    response = {'interval': settings.TRACKER_ANNOUNCE_INTERVAL}
    
    try:
        torrent = Torrent.objects.get(info_hash=info_hash)
        
        # required fields
        ip = request.META['REMOTE_ADDR']
        port = request.GET['port']
        peer_id = request.GET['peer_id']
        event = request.GET.get('event')
        numwant = request.GET.get('numwant',50)
        
        # tracking fields
        if settings.TRACKER_ANNOUNCE_STATS:
            uploaded = request.GET['uploaded']
            downloaded = request.GET['downloaded']
            left = request.GET['left']
            compact = request.GET.get('compact', 0)
        
        # keying for keeping the trash out. DIE UNWASHED MASSES, DIE.
        key = request.GET.get('key')
        if key and (settings.TRACKER_USER_STATS or \
                (settings.TRACKER_PRIVATE and not cache.get("tracker-key-ok-"+key)) ):
            try:
                profile = Profile.objects.get(key = key)
                if settings.TRACKER_USER_STATS:
                    pass # TODO: Add stats code here
                if settings.TRACKER_PRIVATE:
                    cache.set("tracker-key-ok-"+key, True, settings.TRACKER_ANNOUNCE_INTERVAL*5)

# Path: narwhal/core/profile/models.py
# class Profile(Model):
#     user = AutoOneToOneField(User, related_name='profile')
#     key = CharField(max_length=32, default=lambda: md5(os.urandom(40)).hexdigest())
#     
#     avatar = ImageField(upload_to='profiles/avatar/', blank=True, null=True)
#     uploaded = BigIntegerField(default=0)
#     downloaded = BigIntegerField(default=0)
#     
#     # extra_data should only be used for data that should not be 
#     # searched upon, such as chat protocol addresses
#     data = JSONField(default=lambda: {})
#     
#     #def __getattr__(self, name):
#     #    try: return self.extra_data[name]
#     #    except KeyError, e: raise AttributeError, e
#     #def __setattr__(self, name, value):
#     #    self.extra_data[name] = value
#     
#     def __unicode__(self):
#         return self.user.username
#     
#     @permalink
#     def get_absolute_url(self):
#         return ('profile:profile', (), {'username': self.user.username} )
#     
#     def gravatar(self):
#         if self.user.email:
#             return "http://www.gravatar.com/avatar/%s.png?d=%s" % (
#                 md5(self.user.email.lower().strip()).hexdigest(),
#                 settings.PROFILE_GRAVATAR_STANDIN )
#         
#     def ratio(self):
#         return "%.2f"% (self.total_uploaded / float(self.total_downloaded))
# 
# Path: narwhal/core/torrent/models.py
# class Torrent(Model):
#     class Meta:
#         ordering = ('-added',)
#         app_label = 'torrent'
#         verbose_name =_('torrent')
#         verbose_name_plural =_('torrents')
# 
#     category = ForeignKey(Category, related_name='torrents')
#     title = CharField(_('Title'), max_length=80)
#     slug = SlugField(_('Slug'))
#     user = ForeignKey('auth.User', blank=True, null=True, verbose_name=_('Author'))
#     image = ImageField(_('Image'), upload_to='img/torrents', blank=True, null=True)
#     description = TextField(_('Description'))
#     added = DateTimeField(_('Added'), auto_now_add=True, editable=False)
#     
#     torrent = FileField(upload_to='torrent/')
#     data = JSONField(editable=False, default=lambda: {})
#     info_hash = CharField(_('Info hash'), unique=True, max_length=40, db_index=True, editable=False)
#     seeders = PositiveIntegerField(editable=False, default=0)
#     leechers = PositiveIntegerField(editable=False, default=0)
#     downloaded = PositiveIntegerField(editable=False, default=0)
#     comments_enabled = BooleanField(_('comments enabled'), default=True)
#     
#     tags = TaggableManager()
#     
#     def single_file(self):
#         print self.data
#         return 'length' in self.data['info'].keys()
#     single_file.boolean = True
# 
#     def files(self):
#         if self.single_file():
#             return [ self.data['info']['name'] ]
#         else:
#             return [ ( "/".join(f['path']), f['length']) for f in self.data['info']['files'] ]
# 
#     def num_files(self):
#         if self.single_file():
#             return 1
#         else:
#             return len(self.data['info']['files'])
# 
#     def size(self):
#         if 'length' in self.data['info'].keys():
#             return self.data['info']['length']
#         elif 'files' in self.data['info'].keys():
#             return reduce(lambda a,b:a+b, (length for file, length in self.data['info']['files'].items()) )
# 
#     def __unicode__(self):
#         return smart_unicode(self.title)
# 
#     def validate(self):
#         fkeys = self.data['info'].keys()
#         if not 'length' in fkeys and  not 'files' in fkeys:
#             raise ValidationError(_('Torrent File is not valid: does not contain any files.'))
#         #extra validation performed by subclasses
# 
#     def save(self, **kwargs):
#         #from markdown import Markdown
#         #md = Markdown(extensions=['footnotes'], safe_mode=True)
#         #self.html = md.convert(self.text)
#         if not self.slug:
#             self.slug = slugify(self.title)[:self._meta.get_field_by_name('slug')[0].max_length]
#         super(Torrent, self).save(**kwargs)
# 
# Path: narwhal/core/tracker/models.py



# Path: narwhal/core/tracker/views.py
from urlparse import parse_qsl
from django.conf import settings
from django.http import HttpResponse, Http404
from django.utils.datastructures import MultiValueDictKeyError
from django.core.cache import cache
from django.contrib.auth.models import User
from annoying.decorators import render_to
from bencode import bencode, bdecode
from narwhal.core.profile.models import Profile
from narwhal.core.torrent.models import Torrent
from narwhal.core.tracker.models import Peer

    
    response = {'interval': settings.TRACKER_ANNOUNCE_INTERVAL}
    
    try:
        torrent = Torrent.objects.get(info_hash=info_hash)
        
        # required fields
        ip = request.META['REMOTE_ADDR']
        port = request.GET['port']
        peer_id = request.GET['peer_id']
        event = request.GET.get('event')
        numwant = request.GET.get('numwant',50)
        
        # tracking fields
        if settings.TRACKER_ANNOUNCE_STATS:
            uploaded = request.GET['uploaded']
            downloaded = request.GET['downloaded']
            left = request.GET['left']
            compact = request.GET.get('compact', 0)
        
        # keying for keeping the trash out. DIE UNWASHED MASSES, DIE.
        key = request.GET.get('key')
        if key and (settings.TRACKER_USER_STATS or \
                (settings.TRACKER_PRIVATE and not cache.get("tracker-key-ok-"+key)) ):
            try:
                profile = Profile.objects.get(key = key)
                if settings.TRACKER_USER_STATS:
                    pass # TODO: Add stats code here
                if settings.TRACKER_PRIVATE:
                    cache.set("tracker-key-ok-"+key, True, settings.TRACKER_ANNOUNCE_INTERVAL*5)

            except Profile.DoesNotExist: