def hash_over(hostname, over):
    try:
        str = hostname + over['subject'] + over['xref'] + over['message-id']
    except Exception as err:
        print('Error occured during getting keys of over dictionary.')
        print('Error: {}'.format(err))
        return None

    str = get_encoded(str)
    if str is None:
        return None

    return hashlib.sha1(str).hexdigest() def parse_nntp_date(str):
    # Parse the date of a post

    # First try all registered possible formats
    possible_formats = [
        '%a, %d %b %Y %H:%M:%S',
        '%a, %d %b %Y %H:%M:%S %z (%Z)',
        '%a, %d %b %Y %H:%M:%S %Z',
        '%a, %d %b %Y %H:%M:%S %z',
        '%d %b %Y %H:%M:%S %z',
        '%a, %d %b %Y %H:%M %z',
        '%a, %d %b %y %H:%M:%S %Z',
        '%d %b %Y %H:%M:%S %Z'
    ]
    for f in possible_formats:
        try:
            return dt.datetime.strptime(str, f)
        except:
            pass

    # If it failed, try another one by deleting incorrect TZ time
    try:
        str_tmp = re.sub('(\+[0-2][0-9]:[0-5][0-9])', '', str)
        return dt.datetime.strptime(str_tmp, '%a, %d %b %Y %H:%M:%S %z (%Z)')
    except:
        # If it didn't worked either, just return current date!
        print_fail(None, 'Failed parsing date! (' + str + ')')
        return dt.datetime.now() def get_decoded(str):
    try:
        str = str.decode('utf-8')
    except:
        try:
            str = str.decode('iso-8859-15', 'surrogateescape')
        except:
            try:
                str = str.decode("windows-1252")
            except Exception as err:
                # print('Error occured during decoding process.')
                # print('Error: {}'.format(err))
                return str
    return str def print_done():
    print(
        bcolors.OKGREEN, 'Added!', bcolors.ENDC
    ) def print_exists():
    print(
        bcolors.OKGREEN, 'Already exists!', bcolors.ENDC
    ) def print_fail(e, msg=None):
    print(
        bcolors.FAIL, 'Failed! ',
        ((('(' + str(e) + ')') if e else '') if not msg else msg),
        bcolors.ENDC
    )
    import traceback
    traceback.print_stack() def print_msg(type, msg, end=''):
    if type == 'host':
        print(bcolors.HEADER, 'Host: ', bcolors.ENDC, end=end, flush=False)
    elif type == 'group':
        print(bcolors.HEADER, '  Group: ', bcolors.ENDC, end=end, flush=False)
    elif type == 'news':
        print(bcolors.HEADER, '    News: ', bcolors.ENDC, end=end, flush=False)
    print(msg, '... ', end=end, flush=False) def get_father(references):
    try:
        return get_list_from_references(references)[-1]
    except Exception:
        return '' def properly_decode_header(subject):
    subject = get_encoded(subject).decode("utf8", "replace")
    contents = make_header(decode_header(subject))
    return str(contents) def get_co(host, port, ssl, user, password, timeout):
    try:
        if ssl:
            co = nntplib.NNTP_SSL(host, port, user, password, timeout=timeout)
        else:
            co = nntplib.NNTP(host, port, user, password, timeout=timeout)
    except Exception as err:
        raise ConnectionError('Could not connect to the server, please, check '
                         'your connection ({}).'.format(err))
    return co
from datetime import datetime
from itertools import chain
from _sha256 import sha224
from uuid import uuid4
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.core.exceptions import ObjectDoesNotExist
from django.db import models, transaction
from ngnotifier.utils import hash_over, parse_nntp_date, get_decoded,\
    print_done, print_exists, print_fail, print_msg, get_father,\
    properly_decode_header, get_co
from push_notifications.models import APNSDevice, GCMDevice
                if verbose:
                    print_msg('news', properly_decode_header(over['subject']))
                try:
                    n = NGNews.objects.get(groups__in=[self], message_id=over['message-id'])
                    if verbose:
                        print_exists()
                    if n.hash != hash:
                        n.delete()
                        raise ObjectDoesNotExist()
                    # Check if the already existing news is in self group
                    if self not in n.groups.all():
                        already_existing_news.append(n)
                except ObjectDoesNotExist:
                    date = parse_nntp_date(over['date'])
                    _, info = tmp_co.body(over['message-id'])
                    contents = ''
                    for line in info[2]:
                        contents += get_decoded(line) + '\n'
                    try:
                        nn = NGNews()
                        nn.hash = hash
                        nn.subject = properly_decode_header(over['subject'])
                        nn.contents = contents
                        nn.email_from = properly_decode_header(over['from'])
                        nn.message_id = over['message-id']
                        nn.date = date
                        nn.lines = over[':lines']
                        nn.xref = over['xref']
                        nn.references = over['references']
                        nn.father = get_father(over['references'])
                        nn.bytes = over[':bytes']
                        new_news_list.append(nn)
                        if verbose:
                            print_done()
                    except Exception as e:
                        print_fail(e)
            except Exception as e:
                print_fail(e)
        for n in already_existing_news:
            n.add_group(self)
        for n in new_news_list:
            n.save()
            n.groups.add(self)
            n.save()
        self.nb_news += len(already_existing_news) + len(new_news_list)
        self.nb_topics = NGNews.objects.filter(groups__id=self.id, father='').count()
        self.save()
        return new_news_list

    def get_news(self):
        return NGNews.objects.filter(
            groups=self
        )

    def has_followers(self):
        return self.followers.all()

    def get_followers(self):
        return self.has_followers()

    def get_nb_topics(self):
        return NGNews.objects.filter(groups__in=[self], father='').count()


class NGHost(models.Model):
    host = models.TextField(unique=True)
    port = models.IntegerField(default=119)
    ssl = models.BooleanField(default=False)
    user = models.CharField(max_length=200, null=True)
    password = models.CharField(max_length=200, null=True)
    timeout = models.IntegerField(default=30)
    nb_notifs_sent = models.IntegerField(default=0)
    nb_groups = models.IntegerField(default=0)

    def save(self, *args, **kwargs):
        if not self.pk:
            super().save(*args, **kwargs)
        else:
            super().save(*args, **kwargs)

    def get_co(self):
        try:
            return get_co(self.host, self.port, self.ssl,
                          self.user, self.password, self.timeout)
        except Exception as err:
            raise ConnectionError('Could not connect to the server, please '
                                  'check your connection ({}).'.format(err))

    # Get groups that are still available on the server
    def get_available_groups(self, groups=None, verbose=False):

        if groups is None or len(groups) == 0:
            _, grp_list = self.get_co().list()
            grp_list = [x.group for x in grp_list]
        else:
            grp_list = groups


        NGGroups = []

        for group_name in grp_list:
            if verbose:
                print_msg('group', group_name)
            try:
                ng_group = NGGroup.objects.get(host=self, name=group_name)
                NGGroups.append(ng_group)
                if verbose:
                    print_exists()
            except ObjectDoesNotExist:
                try:
                    ng_group = NGGroup()
                    ng_group.host = self
                    ng_group.name = group_name
                    ng_group.save()
                    NGGroups.append(ng_group)
                    self.nb_groups += 1
                    self.save()
                    if verbose:
                        print_done()
                except Exception as e:

                    print_fail(e)