def pwchange(request): LOGGER.debug( 'Password change page accessed using method {}'.format(request.method), request, request.POST) var = {'page_title': 'Změna hesla'} user = request.user uid = user.id username = request.user.username if request.method == 'POST': if request.POST.get('back'): return redirect('home') fields = ('oldpassword', 'newpassword1', 'newpassword2') for fld in fields: var[fld] = request.POST.get(fld, '') if not user.check_password(var['oldpassword']): var['error_message'] = 'Nesprávné heslo' var['oldpassword'] = '' elif var['newpassword1'] != var['newpassword2']: var['error_message'] = 'Zadaná hesla se neshodují' var['newpassword1'] = var['newpassword2'] = '' elif len(var['newpassword1']) < MIN_PWLEN: var['error_message'] = 'Nové heslo je příliš krátké' var['newpassword1'] = var['newpassword2'] = '' else: user.set_password(var['newpassword1']) user.save() LOGGER.info( 'User "{}" ({:d}) changed password'.format(username, uid), request) return redirect('/accounts/pwchanged/') return render(request, 'pwchange.xhtml', var)
def cron_courts(): try: res = get(ROOT_URL + LIST_COURTS) soup = BeautifulSoup(res.text, 'html.parser') Court.objects.get_or_create(id=SUPREME_COURT, name='Nejvyšší soud') Court.objects.get_or_create(id=SUPREME_ADMINISTRATIVE_COURT, name='Nejvyšší správní soud') upper = soup.find(id='kraj').find_all('option')[1:] lower = soup.find(id='soudy').find_all('option')[1:] for court in upper + lower: Court.objects.get_or_create(id=court['value'], name=court.string.encode('utf-8')) except: # pragma: no cover LOGGER.warning('Error importing courts') Court.objects.all().update(reports=None) for court in Court.objects.all(): if isreg(court): try: sleep(1) res = get(ROOT_URL + LIST_REPORTS.format(court.pk)) soup = BeautifulSoup(res.text, 'xml') for item in soup.find_all('okresniSoud'): Court.objects.filter(pk=item.id.string).update(reports=court) except: # pragma: no cover LOGGER.warning('Error setting hierarchy for {}'.format(court.id)) LOGGER.info('Courts imported')
def dir_check(osoba, vec): for debtor in Debtor.objects.all(): date_birth = osoba.datumNarozeni if date_birth: date_birth = date_birth.date() if ((not debtor.court or debtor.court == osoba.idOsobyPuvodce) and text_opt(debtor.name, osoba.nazevOsoby, debtor.name_opt) and text_opt(debtor.first_name, osoba.jmeno, debtor.first_name_opt) and (not debtor.genid or debtor.genid == osoba.ic) and (not debtor.taxid or icmp(debtor.taxid, osoba.dic)) and (not debtor.birthid or debtor.birthid == osoba.rc) and (not debtor.date_birth or debtor.date_birth == date_birth) and (not debtor.year_birth_from or debtor.year_birth_from <= date_birth.year) and (not debtor.year_birth_to or debtor.year_birth_to >= date_birth.year)): if Discovered.objects.update_or_create( uid_id=debtor.uid_id, desc=debtor.desc, vec=vec)[1]: if debtor.uid.email: Debtor.objects.filter(id=debtor.id).update(notify=True) LOGGER.info( 'New debtor "{}" detected for user "{}" ({:d})'.format( debtor.desc, User.objects.get(pk=debtor.uid_id).username, debtor.uid_id))
def szr_notice(uid): text = '' res = Proceedings.objects.filter(uid=uid, notify=True).order_by('desc', 'id') if res: text = 'V těchto soudních řízeních, která sledujete, došlo ke změně:\n\n' for proc in res: desc = ' ({})'.format(proc.desc) if proc.desc else '' text += ' - {}, sp. zn. {}{}\n'.format( proc.court, composeref(proc.senate, proc.register, proc.number, proc.year), desc) if proc.court_id != SUPREME_ADMINISTRATIVE_COURT: court_type = 'ns' if proc.court_id == SUPREME_COURT else 'os' text += ' {}\n\n'.format(ROOT_URL + GET_PROC.format( proc.court.id, proc.court.reports.id if proc.court.reports else proc.court.id, proc.senate, quote(proc.register.upper()), proc.number, proc.year, court_type)) elif proc.auxid: text += ' {}\n\n'.format(NSS_GET_PROC.format(proc.auxid)) proc.notify = False proc.save() LOGGER.info('Non-empty notice prepared for user "{}" ({:d})'.format(User.objects.get(pk=uid).username, uid)) return text
def cron_update(): cron_getws2() cron_gettr() cron_proctr() cron_deltr() cron_delerr() LOGGER.info('Batch processed')
def procform(request, idx=0): LOGGER.debug( 'Proceedings form accessed using method {}, id={}'.format( request.method, idx), request, request.POST) err_message = '' uid = request.user.id uname = request.user.username page_title = 'Úprava řízení' if idx else 'Nové řízení' button = getbutton(request) if request.method == 'GET': form = ProcForm(initial=model_to_dict( get_object_or_404(Proceedings, pk=idx, uid=uid))) if idx else ProcForm() elif button == 'back': return redirect('szr:mainpage') else: form = ProcForm(request.POST) if form.is_valid(): cld = form.cleaned_data if not cld['senate']: cld['senate'] = 0 if idx: proc = get_object_or_404(Proceedings, pk=idx, uid=uid) cld['pk'] = idx cld['timestamp_add'] = proc.timestamp_add cld['court_id'] = cld['court'] del cld['court'] onlydesc = (idx and proc.court.id == cld['court_id'] and proc.senate == cld['senate'] and proc.register == cld['register'] and proc.number == cld['number'] and proc.year == cld['year']) if onlydesc: cld['changed'] = proc.changed cld['updated'] = proc.updated cld['hash'] = proc.hash cld['auxid'] = proc.auxid cld['notify'] = proc.notify proc = Proceedings(uid_id=uid, **cld) if not onlydesc: updateproc(proc) proc.save() LOGGER.info( 'User "{}" ({:d}) {} proceedings "{}" ({})'.format( uname, uid, 'updated' if idx else 'added', proc.desc, p2s(proc)), request) return redirect('szr:mainpage') else: # pragma: no cover LOGGER.debug('Invalid form', request) err_message = INERR return render( request, 'szr_procform.xhtml', { 'app': APP, 'form': form, 'page_title': page_title, 'err_message': err_message })
def cron_publishers(): def proc_publisher(tag, typ, high=False, subsidiary_region=False, subsidiary_county=False, reports=None): pubid = int(tag['href'].rpartition('=')[2]) name = ( tag.text.replace(' ', ' ') .replace('KS ', 'Krajský soud ') .replace('MS ', 'Městský soud ') .replace('OS Praha ', 'Obvodní soud Praha ') .replace('OS ', 'Okresní soud ') .replace('KSZ ', 'Krajské státní zastupitelství ') .replace('MSZ ', 'Městské státní zastupitelství ') .replace('OSZ Praha ', 'Obvodní státní zastupitelství Praha ') .replace('OSZ ', 'Okresní státní zastupitelství ') ) return Publisher.objects.update_or_create( name=name, defaults={ 'type': typ, 'pubid': pubid, 'high': high, 'subsidiary_region': subsidiary_region, 'subsidiary_county': subsidiary_county, 'reports': reports, 'updated': datetime.now() - UPDATE_INTERVAL})[0] def proc_publishers(soup, typ, high=False): if high: for tag in soup.find_all('a'): proc_publisher(tag, typ, high=True) else: rep = proc_publisher(soup.select('dt a')[0], typ) for tag in soup.find_all('dd'): cls = tag.get('class', []) subsidiary_region = 'pobockakraj' in cls subsidiary_county = 'pobockaokres' in cls proc_publisher( tag.find('a'), typ, subsidiary_region=subsidiary_region, subsidiary_county=subsidiary_county, reports=rep) for typ in TYPES: try: res = get(PUBLISHERS_URL.format(typ)) soup = BeautifulSoup(res.text, 'html.parser') high = soup.find('div', 'bezlokality') lower = soup.find('div', 'slokalitou') proc_publishers(high, typ, high=True) for reg in lower.find_all('dl'): proc_publishers(reg, typ, high=False) except: pass LOGGER.info('Publishers imported')
def debtorform(request, idx=0): LOGGER.debug( 'Debtor form accessed using method {}, id={}'.format(request.method, idx), request, request.POST) err_message = '' uid = request.user.id uname = request.user.username page_title = 'Úprava dlužníka' if idx else 'Nový dlužník' button = getbutton(request) if request.method == 'GET': if idx: debtor = model_to_dict(get_object_or_404(Debtor, pk=idx, uid=uid)) for opt in OPTS: debtor[opt] = TEXT_OPTS_KEYS[debtor[opt]] if debtor['birthid']: debtor['birthid'] = '{}/{}'.format(debtor['birthid'][:6], debtor['birthid'][6:]) form = DebtorForm(initial=debtor) else: form = DebtorForm() elif button == 'back': return redirect('dir:mainpage') else: form = DebtorForm(request.POST) if form.is_valid(): cld = form.cleaned_data if idx: debtor = get_object_or_404(Debtor, pk=idx, uid=uid) cld['pk'] = idx cld['notify'] = debtor.notify cld['timestamp_add'] = debtor.timestamp_add cld['birthid'] = cld['birthid'].replace('/', '') for key in cld: if cld[key] == '': cld[key] = None debtor = Debtor(uid_id=uid, **cld) for opt in OPTS: debtor.__setattr__(opt, TEXT_OPTS_KEYS.index(cld[opt])) debtor.save() LOGGER.info( 'User "{}" ({:d}) {} debtor {}'.format(uname, uid, 'updated' if idx else 'added', debtor.desc), request) return redirect('dir:mainpage') else: LOGGER.debug('Invalid form', request) err_message = INERR return render( request, 'dir_debtorform.xhtml', {'app': APP, 'form': form, 'page_title': page_title, 'err_message': err_message})
def cron_fixindex(): num = 0 for doc in Document.objects.all(): if not DocumentIndex.objects.using('sphinx').filter(id=doc.id).exists(): num += 1 update_index(doc) if num: LOGGER.info('Index fixed, {:d} record(s) added'.format(num)) else: LOGGER.debug('Index fixed, no records added')
def logout(request): LOGGER.debug('Logout page accessed using method {}'.format(request.method), request) uid = request.user.id username = request.user.username auth.logout(request) if username: LOGGER.info('User "{}" ({:d}) logged out'.format(username, uid), request) return redirect('home')
def cron_remove_orphans(): num = 0 for doc in Document.objects.all(): if not File.objects.filter(document=doc).exists(): num += 1 DocumentIndex.objects.using('sphinx').filter(id=doc.id).delete() doc.delete() if num: LOGGER.info('Removed {:d} orphan(s)'.format(num)) else: LOGGER.debug('No orphans removed')
def cron_fixindex(): num = 0 for doc in Document.objects.all(): if not DocumentIndex.objects.using('sphinx').filter( id=doc.id).exists(): num += 1 update_index(doc) if num: LOGGER.info('Index fixed, {:d} record(s) added'.format(num)) else: LOGGER.debug('Index fixed, no records added')
def procform(request, idx=0): LOGGER.debug('Proceedings form accessed using method {}, id={}'.format(request.method, idx), request, request.POST) err_message = '' uid = request.user.id uname = request.user.username page_title = 'Úprava řízení' if idx else 'Nové řízení' button = getbutton(request) if request.method == 'GET': form = ProcForm(initial=model_to_dict(get_object_or_404(Proceedings, pk=idx, uid=uid))) if idx else ProcForm() elif button == 'back': return redirect('szr:mainpage') else: form = ProcForm(request.POST) if form.is_valid(): cld = form.cleaned_data if not cld['senate']: cld['senate'] = 0 if idx: proc = get_object_or_404(Proceedings, pk=idx, uid=uid) cld['pk'] = idx cld['timestamp_add'] = proc.timestamp_add cld['court_id'] = cld['court'] del cld['court'] onlydesc = ( idx and proc.court.id == cld['court_id'] and proc.senate == cld['senate'] and proc.register == cld['register'] and proc.number == cld['number'] and proc.year == cld['year']) if onlydesc: cld['changed'] = proc.changed cld['updated'] = proc.updated cld['hash'] = proc.hash cld['auxid'] = proc.auxid cld['notify'] = proc.notify proc = Proceedings(uid_id=uid, **cld) if not onlydesc: updateproc(proc) proc.save() LOGGER.info( 'User "{}" ({:d}) {} proceedings "{}" ({})' .format(uname, uid, 'updated' if idx else 'added', proc.desc, p2s(proc)), request) return redirect('szr:mainpage') else: # pragma: no cover LOGGER.debug('Invalid form', request) err_message = INERR return render( request, 'szr_procform.xhtml', {'app': APP, 'form': form, 'page_title': page_title, 'err_message': err_message})
def cron_notify(): for user in User.objects.all(): uid = user.id text = szr_notice(uid) + sur_notice(uid) + sir_notice( uid) + dir_notice(uid) + uds_notice(uid) if text and user.email: text += 'Server {} ({})\n'.format(LOCAL_SUBDOMAIN, LOCAL_URL) send_mail('Zprava ze serveru {}'.format(LOCAL_SUBDOMAIN), text, [user.email]) LOGGER.debug('Email sent to user "{}" ({:d})'.format( User.objects.get(pk=uid).username, uid)) LOGGER.info('Emails sent')
def partyexport(request): LOGGER.debug('Party export page accessed', request) uid = request.user.id uname = request.user.username res = Party.objects.filter(uid=uid).order_by('party', 'party_opt', 'id').distinct() response = HttpResponse(content_type='text/csv; charset=utf-8') response['Content-Disposition'] = 'attachment; filename=sur.csv' writer = csvwriter(response) for item in res: dat = (item.party + TEXT_OPTS_CA[item.party_opt],) writer.writerow(dat) LOGGER.info('User "{}" ({:d}) exported parties'.format(uname, uid), request) return response
def sur_notice(uid): text = '' res = Found.objects.filter(uid=uid).order_by('name', 'id').distinct() if res: text = 'Byli nově zaznamenáni tito účastníci řízení, které sledujete:\n\n' for item in res: text += ' - {0.name}, {0.court}, sp. zn. {1}\n'.format( item, composeref(item.senate, item.register, item.number, item.year)) text += ' {}\n\n'.format(item.url) Found.objects.filter(uid=uid).delete() LOGGER.info('Non-empty notice prepared for user "{}" ({:d})'.format(User.objects.get(pk=uid).username, uid)) Party.objects.filter(uid=uid).update(notify=False) return text
def partyform(request, idx=0): LOGGER.debug( 'Party form accessed using method {}, id={}'.format( request.method, idx), request, request.POST) err_message = '' uid = request.user.id uname = request.user.username page_title = 'Úprava účastníka' if idx else 'Nový účastník' button = getbutton(request) if request.method == 'GET': if idx: dct = model_to_dict(get_object_or_404(Party, pk=idx, uid=uid)) dct['party_opt'] = TEXT_OPTS_KEYS[dct['party_opt']] form = PartyForm(initial=dct) else: form = PartyForm() elif button == 'back': return redirect('sur:mainpage') else: form = PartyForm(request.POST) if form.is_valid(): cld = form.cleaned_data if idx: res = get_object_or_404(Party, pk=idx, uid=uid) cld['pk'] = idx cld['notify'] = res.notify cld['timestamp_add'] = res.timestamp_add res = Party(uid_id=uid, **cld) res.party_opt = TEXT_OPTS_KEYS.index(cld['party_opt']) res.save() LOGGER.info( 'User "{}" ({:d}) {} party {}'.format( uname, uid, 'updated' if idx else 'added', res.party), request) return redirect('sur:mainpage') else: LOGGER.debug('Invalid form', request) err_message = INERR return render( request, 'sur_partyform.xhtml', { 'app': APP, 'form': form, 'min_chars': grammar(MIN_LENGTH, GR_CHAR), 'page_title': page_title, 'err_message': err_message })
def cron_notify(): for user in User.objects.all(): uid = user.id text = szr_notice(uid) + sur_notice(uid) + sir_notice(uid) + dir_notice(uid) + uds_notice(uid) if text and user.email: text += 'Server {} ({})\n'.format(LOCAL_SUBDOMAIN, LOCAL_URL) send_mail( 'Zprava ze serveru {}'.format(LOCAL_SUBDOMAIN), text, [user.email]) LOGGER.debug( 'Email sent to user "{}" ({:d})' .format(User.objects.get(pk=uid).username, uid)) LOGGER.info('Emails sent')
def cron_schedule(*args): dates = [] for arg in args: if len(arg) > 2: string = arg.split('.') dates.append(date(*map(int, string[2::-1]))) else: dates.append(date.today() + timedelta(int(arg))) for court in Court.objects.all(): if court.id in {SUPREME_COURT, SUPREME_ADMINISTRATIVE_COURT}: continue for dat in dates: Task.objects.get_or_create(court=court, date=dat) LOGGER.info('Tasks scheduled')
def cron_courtrooms(): for court in Court.objects.exclude(id=SUPREME_ADMINISTRATIVE_COURT): try: sleep(1) res = get(LIST_COURTROOMS.format(court.pk)) soup = BeautifulSoup(res.text, 'xml') for room in soup.find_all('jednaciSin'): croom, croomc = Courtroom.objects.get_or_create( court=court, desc=room.nazev.string) if not croomc: croom.save() except: # pragma: no cover LOGGER.warning('Error downloading courtrooms') LOGGER.info('Courtrooms downloaded')
def lostpw(request): LOGGER.debug( 'Lost password page accessed using method {}'.format(request.method), request, request.POST) err_message = None page_title = 'Ztracené heslo' if request.method == 'GET': form = LostPwForm() elif request.POST.get('back'): return redirect('login') else: form = LostPwForm(request.POST) if form.is_valid(): cld = form.cleaned_data users = User.objects.filter(username=cld['username']) if users.exists() and users[0].email: user = users[0] link = '{:032x}'.format(getrandbits(16 * 8)) PwResetLink(user_id=user.id, link=link).save() text = '''Vážený uživateli, někdo požádal o obnovení hesla pro Váš účet "{0}" na serveru {1} ({2}). Pokud skutečně chcete své heslo obnovit, použijte, prosím, následující jednorázový odkaz: {2}{3} V případě, že jste o obnovení hesla nežádali, můžete tuto zprávu ignorovat. Server {1} ({2}) '''.format(user.username, LOCAL_SUBDOMAIN, LOCAL_URL, reverse('resetpw', args=(link, ))) send_mail('Link pro obnoveni hesla', text, (user.email, )) LOGGER.info( 'Password recovery link for user "{0.username}" ({0.id:d}) sent' .format(user), request) return redirect('/accounts/pwlinksent/') else: LOGGER.debug('Invalid form', request) err_message = 'Prosím, opravte označená pole ve formuláři' return render(request, 'lostpw.xhtml', { 'form': form, 'page_title': page_title, 'err_message': err_message, })
def partyexport(request): LOGGER.debug('Party export page accessed', request) uid = request.user.id uname = request.user.username res = Party.objects.filter(uid=uid).order_by('party', 'party_opt', 'id').distinct() response = HttpResponse(content_type='text/csv; charset=utf-8') response['Content-Disposition'] = 'attachment; filename=sur.csv' writer = csvwriter(response) for item in res: dat = (item.party + TEXT_OPTS_CA[item.party_opt], ) writer.writerow(dat) LOGGER.info('User "{}" ({:d}) exported parties'.format(uname, uid), request) return response
def sir_notice(uid): text = '' res = Tracked.objects.filter(uid=uid, vec__link__isnull=False).order_by('desc', 'id').distinct() if res: text = 'Došlo ke změně v těchto insolvenčních řízeních, která sledujete:\n\n' for ins in res: refresh_link(ins.vec) text += ( ' - {0}sp. zn. {1} {2.senat:d} INS {2.bc:d}/{2.rocnik:d}\n' .format('{}, '.format(ins.desc) if ins.desc else '', L2S[ins.vec.idOsobyPuvodce], ins.vec)) text += ' {}\n\n'.format(ins.vec.link) Tracked.objects.filter(uid=uid, vec__link__isnull=False).delete() LOGGER.info('Non-empty notice prepared for user "{}" ({:d})'.format(User.objects.get(pk=uid).username, uid)) Insolvency.objects.filter(uid=uid).update(notify=False) return text
def procexport(request): LOGGER.debug('Proceedings export page accessed', request) uid = request.user.id uname = request.user.username res = Proceedings.objects.filter(uid=uid).order_by('desc', 'pk').distinct() response = HttpResponse(content_type='text/csv; charset=utf-8') response['Content-Disposition'] = 'attachment; filename=szr.csv' writer = csvwriter(response) for proc in res: dat = (proc.desc, proc.court.id, composeref(proc.senate, proc.register, proc.number, proc.year)) writer.writerow(dat) LOGGER.info('User "{}" ({:d}) exported proceedings'.format(uname, uid), request) return response
def partydelall(request): LOGGER.debug('Delete all parties page accessed using method {}'.format(request.method), request) uid = request.user.id uname = request.user.username if request.method == 'GET': return render( request, 'sur_partydelall.xhtml', {'app': APP, 'page_title': 'Smazání všech účastníků'}) else: if getbutton(request) == 'yes' and 'conf' in request.POST and request.POST['conf'] == 'Ano': Party.objects.filter(uid=uid).delete() LOGGER.info('User "{}" ({:d}) deleted all parties'.format(uname, uid), request) return redirect('sur:mainpage')
def sur_notice(uid): text = '' res = Found.objects.filter(uid=uid).order_by('name', 'id').distinct() if res: text = 'Byli nově zaznamenáni tito účastníci řízení, které sledujete:\n\n' for item in res: text += ' - {0.name}, {0.court}, sp. zn. {1}\n'.format( item, composeref(item.senate, item.register, item.number, item.year)) text += ' {}\n\n'.format(item.url) Found.objects.filter(uid=uid).delete() LOGGER.info('Non-empty notice prepared for user "{}" ({:d})'.format( User.objects.get(pk=uid).username, uid)) Party.objects.filter(uid=uid).update(notify=False) return text
def debtordelall(request): LOGGER.debug('Delete all debtors page accessed using method {}'.format(request.method), request) uid = request.user.id uname = request.user.username if request.method == 'GET': return render( request, 'dir_debtordelall.xhtml', {'app': APP, 'page_title': 'Smazání všech dlužníků'}) else: if getbutton(request) == 'yes' and 'conf' in request.POST and request.POST['conf'] == 'Ano': Debtor.objects.filter(uid=uid).delete() LOGGER.info('User "{}" ({:d}) deleted all debtors'.format(uname, uid), request) return redirect('dir:mainpage')
def useradd(request): LOGGER.debug( 'User add page accessed using method {}'.format(request.method), request, request.POST) err_message = None if request.method == 'GET': form = UserAddForm() else: form = UserAddForm(request.POST) if form.is_valid(): cld = form.cleaned_data user = User.objects.create_user(cld['username'], cld['email'], cld['password1']) if user: user.first_name = cld['first_name'] user.last_name = cld['last_name'] user.save() logout(request) LOGGER.info( 'New user "{0.username}" ({0.id:d}) created'.format(user), request) return redirect('useradded') LOGGER.error('Failed to create user', request) return error(request) # pragma: no cover else: LOGGER.debug('Invalid form', request) err_message = INERR if 'Duplicate username' in form['username'].errors.as_text(): err_message = 'Toto uživatelské jméno se již používá' LOGGER.debug('Duplicate user name', request) elif 'Wrong answer' in form['captcha'].errors.as_text(): err_message = 'Chybná odpověď na kontrolní otázku' LOGGER.debug('Wrong answer', request) elif 'Different passwords' in form['password2'].errors.as_text(): err_message = 'Rozdílná hesla' LOGGER.debug('Different passwords', request) else: err_message = 'Slabé heslo' LOGGER.debug('Weak password', request) return render( request, 'useradd.xhtml', { 'form': form, 'page_title': 'Registrace nového uživatele', 'err_message': err_message, })
def dir_notice(uid): text = '' debtors = Discovered.objects.filter(uid=uid, vec__link__isnull=False).order_by('desc', 'id').distinct() if debtors: text = 'Byli nově zaznamenáni tito dlužníci, které sledujete:\n\n' for debtor in debtors: text += ' - {0}, sp. zn. {1} {2.senat:d} INS {2.bc:d}/{2.rocnik:d}\n'.format( debtor.desc, L2S[debtor.vec.idOsobyPuvodce], debtor.vec) text += ' {}\n\n'.format(debtor.vec.link) Discovered.objects.filter(uid=uid, vec__link__isnull=False).delete() LOGGER.info( 'Non-empty notice prepared for user "{}" ({:d})'.format(User.objects.get(pk=uid).username, uid)) Debtor.objects.filter(uid=uid).update(notify=False) return text
def partyform(request, idx=0): LOGGER.debug('Party form accessed using method {}, id={}'.format(request.method, idx), request, request.POST) err_message = '' uid = request.user.id uname = request.user.username page_title = 'Úprava účastníka' if idx else 'Nový účastník' button = getbutton(request) if request.method == 'GET': if idx: dct = model_to_dict(get_object_or_404(Party, pk=idx, uid=uid)) dct['party_opt'] = TEXT_OPTS_KEYS[dct['party_opt']] form = PartyForm(initial=dct) else: form = PartyForm() elif button == 'back': return redirect('sur:mainpage') else: form = PartyForm(request.POST) if form.is_valid(): cld = form.cleaned_data if idx: res = get_object_or_404(Party, pk=idx, uid=uid) cld['pk'] = idx cld['notify'] = res.notify cld['timestamp_add'] = res.timestamp_add res = Party(uid_id=uid, **cld) res.party_opt = TEXT_OPTS_KEYS.index(cld['party_opt']) res.save() LOGGER.info( 'User "{}" ({:d}) {} party {}'.format(uname, uid, 'updated' if idx else 'added', res.party), request) return redirect('sur:mainpage') else: LOGGER.debug('Invalid form', request) err_message = INERR return render( request, 'sur_partyform.xhtml', {'app': APP, 'form': form, 'min_chars': grammar(MIN_LENGTH, GR_CHAR), 'page_title': page_title, 'err_message': err_message})
def uds_notice(uid): text = '' docs = Retrieved.objects.filter(uid=uid).order_by('id').distinct() if docs: text = 'Na úředních deskách byly nově zaznamenány tyto osoby, které sledujete:\n\n' for doc in docs: lst = [doc.party.party, doc.document.publisher.name, doc.document.desc] if doc.document.ref: lst.append('sp. zn. {}'.format(doc.document.ref)) text += ' - {}\n'.format(', '.join(filter(bool, lst))) text += ' {}\n\n'.format(DOCUMENT_URL.format(doc.document.id)) Retrieved.objects.filter(uid=uid).delete() LOGGER.info( 'Non-empty notice prepared for user "{}" ({:d})'.format(User.objects.get(pk=uid).username, uid)) Party.objects.filter(uid=uid).update(notify=False) return text
def sur_check(par, name, court, senate, register, number, year, url): for party in Party.objects.filter(**par): if text_opt(party.party, name, party.party_opt): if Found.objects.update_or_create( uid_id=party.uid_id, name=name, court=court, senate=senate, register=register, number=number, year=year, url=url)[1]: if party.uid.email: Party.objects.filter(id=party.id).update(notify=True) LOGGER.info( 'New party "{}" detected for user "{}" ({:d})' .format(name, User.objects.get(pk=party.uid_id).username, party.uid_id))
def uds_notice(uid): text = '' docs = Retrieved.objects.filter(uid=uid).order_by('id').distinct() if docs: text = 'Na úředních deskách byly nově zaznamenány tyto osoby, které sledujete:\n\n' for doc in docs: lst = [ doc.party.party, doc.document.publisher.name, doc.document.desc ] if doc.document.ref: lst.append('sp. zn. {}'.format(doc.document.ref)) text += ' - {}\n'.format(', '.join(filter(bool, lst))) text += ' {}\n\n'.format(DOCUMENT_URL.format(doc.document.id)) Retrieved.objects.filter(uid=uid).delete() LOGGER.info('Non-empty notice prepared for user "{}" ({:d})'.format( User.objects.get(pk=uid).username, uid)) Party.objects.filter(uid=uid).update(notify=False) return text
def sur_check(par, name, court, senate, register, number, year, url): for party in Party.objects.filter(**par): if text_opt(party.party, name, party.party_opt): if Found.objects.update_or_create(uid_id=party.uid_id, name=name, court=court, senate=senate, register=register, number=number, year=year, url=url)[1]: if party.uid.email: Party.objects.filter(id=party.id).update(notify=True) LOGGER.info( 'New party "{}" detected for user "{}" ({:d})'.format( name, User.objects.get(pk=party.uid_id).username, party.uid_id))
def sir_notice(uid): text = '' res = Tracked.objects.filter(uid=uid, vec__link__isnull=False).order_by( 'desc', 'id').distinct() if res: text = 'Došlo ke změně v těchto insolvenčních řízeních, která sledujete:\n\n' for ins in res: refresh_link(ins.vec) text += ( ' - {0}sp. zn. {1} {2.senat:d} INS {2.bc:d}/{2.rocnik:d}\n'. format('{}, '.format(ins.desc) if ins.desc else '', L2S[ins.vec.idOsobyPuvodce], ins.vec)) text += ' {}\n\n'.format(ins.vec.link) Tracked.objects.filter(uid=uid, vec__link__isnull=False).delete() LOGGER.info('Non-empty notice prepared for user "{}" ({:d})'.format( User.objects.get(pk=uid).username, uid)) Insolvency.objects.filter(uid=uid).update(notify=False) return text
def insexport(request): LOGGER.debug('Proceedings export page accessed', request) uid = request.user.id uname = request.user.username res = Insolvency.objects.filter(uid=uid).order_by('desc', 'pk').distinct() response = HttpResponse(content_type='text/csv; charset=utf-8') response['Content-Disposition'] = 'attachment; filename=sir.csv' writer = csvwriter(response) for idx in res: dat = ( idx.desc, str(idx.number), str(idx.year), 'ano' if idx.detailed else 'ne', ) writer.writerow(dat) LOGGER.info('User "{}" ({:d}) exported proceedings'.format(uname, uid), request) return response
def cron_find(): now = datetime.now() try: dec = Decision.objects.filter(anonfilename='', date__gte=(now - OBS)).earliest('updated') dec.updated = now dec.save() res = get(FIND_URL) soup = BeautifulSoup(res.text, 'html.parser') form = soup.find('form') dct = {i['name']: i['value'] for i in form.find_all('input') if i['type'] == 'hidden' and i.has_attr('value')} ref = ('{} '.format(dec.senate) if dec.senate else '') ref += '{0.register} {0.number:d}/{0.year:d}'.format(dec) dct['_ctl0:ContentPlaceMasterPage:_ctl0:txtDatumOd'] = dct['_ctl0:ContentPlaceMasterPage:_ctl0:txtDatumDo'] = \ '{0.day:02d}.{0.month:02d}.{0.year:d}'.format(dec.date) dct['_ctl0:ContentPlaceMasterPage:_ctl0:txtSpisovaZnackaFull'] = ref dct['_ctl0_ContentPlaceMasterPage__ctl0_rbTypDatum_0'] = 'on' res = post(FIND_URL, dct) soup = BeautifulSoup(res.text, 'html.parser') for anchor in soup.select('table#_ctl0_ContentPlaceMasterPage__ctl0_grwA')[0].select('a[title^=Anonymizovan]'): fileurl = anchor['href'] filename = fileurl.split('/')[-1] if not FRE.match(filename): continue res = get(ROOT_URL + fileurl) if not res.ok: continue LOGGER.info( 'Writing anonymized decision "{}"' .format(composeref(dec.senate, dec.register, dec.number, dec.year))) with open(join(REPO_PREF, filename), 'wb') as outfile: if not outfile.write(res.content): # pragma: no cover LOGGER.error( 'Failed to write anonymized decision "{}"' .format(composeref(dec.senate, dec.register, dec.number, dec.year))) return adddoc(APP, filename, ROOT_URL + fileurl) dec.anonfilename = filename dec.save() return except: # pragma: no cover LOGGER.warning('Find failed')
def insform(request, idx=0): LOGGER.debug( 'Proceedings form accessed using method {}, id={}'.format( request.method, idx), request, request.POST) err_message = '' uid = request.user.id uname = request.user.username page_title = 'Úprava řízení' if idx else 'Nové řízení' button = getbutton(request) if request.method == 'GET': form = InsForm(initial=model_to_dict( get_object_or_404(Insolvency, pk=idx, uid=uid))) if idx else InsForm() elif button == 'back': return redirect('sir:mainpage') else: form = InsForm(request.POST) if form.is_valid(): cld = form.cleaned_data if idx: res = get_object_or_404(Insolvency, pk=idx, uid=uid) cld['pk'] = idx cld['notify'] = res.notify cld['timestamp_add'] = res.timestamp_add res = Insolvency(uid_id=uid, **cld) res.save() LOGGER.info( 'User "{}" ({:d}) {} proceedings "{}" ({})'.format( uname, uid, 'updated' if idx else 'added', res.desc, p2s(res)), request) return redirect('sir:mainpage') else: LOGGER.debug('Invalid form', request) err_message = INERR return render( request, 'sir_insform.xhtml', { 'app': APP, 'form': form, 'page_title': page_title, 'err_message': err_message })
def resetpw(request, link): LOGGER.debug('Password reset page accessed', request) PwResetLink.objects.filter(timestamp_add__lt=(datetime.now() - LINKLIFE)).delete() link = get_object_or_404(PwResetLink, link=link) user = link.user newpassword = '' for _ in range(PWLEN): newpassword += choice(PWCHARS) user.set_password(newpassword) user.save() link.delete() LOGGER.info( 'Password for user "{}" ({:d}) reset'.format(user.username, user.id), request) return render(request, 'pwreset.xhtml', { 'page_title': 'Heslo bylo obnoveno', 'newpassword': newpassword, })
def insform(request, idx=0): LOGGER.debug( 'Proceedings form accessed using method {}, id={}'.format(request.method, idx), request, request.POST) err_message = '' uid = request.user.id uname = request.user.username page_title = 'Úprava řízení' if idx else 'Nové řízení' button = getbutton(request) if request.method == 'GET': form = InsForm(initial=model_to_dict(get_object_or_404(Insolvency, pk=idx, uid=uid))) if idx else InsForm() elif button == 'back': return redirect('sir:mainpage') else: form = InsForm(request.POST) if form.is_valid(): cld = form.cleaned_data if idx: res = get_object_or_404(Insolvency, pk=idx, uid=uid) cld['pk'] = idx cld['notify'] = res.notify cld['timestamp_add'] = res.timestamp_add res = Insolvency(uid_id=uid, **cld) res.save() LOGGER.info( 'User "{}" ({:d}) {} proceedings "{}" ({})' .format(uname, uid, 'updated' if idx else 'added', res.desc, p2s(res)), request) return redirect('sir:mainpage') else: LOGGER.debug('Invalid form', request) err_message = INERR return render( request, 'sir_insform.xhtml', {'app': APP, 'form': form, 'page_title': page_title, 'err_message': err_message})
def partydel(request, idx=0): LOGGER.debug( 'Party delete page accessed using method {}, id={}'.format( request.method, idx), request, request.POST) uid = request.user.id uname = request.user.username party = get_object_or_404(Party, pk=idx, uid=uid) if request.method == 'GET': return render(request, 'sur_partydel.xhtml', { 'app': APP, 'page_title': 'Smazání účastníka', 'desc': party.party }) else: if getbutton(request) == 'yes': LOGGER.info( 'User "{}" ({:d}) deleted party "{}"'.format( uname, uid, party.party), request) party.delete() return redirect('sur:partydeleted') return redirect('sur:mainpage')
def procexport(request): LOGGER.debug('Proceedings export page accessed', request) uid = request.user.id uname = request.user.username res = Proceedings.objects.filter(uid=uid).order_by('desc', 'pk').distinct() response = HttpResponse(content_type='text/csv; charset=utf-8') response['Content-Disposition'] = 'attachment; filename=szr.csv' writer = csvwriter(response) for proc in res: dat = ( proc.desc, proc.court.id, composeref( proc.senate, proc.register, proc.number, proc.year) ) writer.writerow(dat) LOGGER.info('User "{}" ({:d}) exported proceedings'.format(uname, uid), request) return response
def partydel(request, idx=0): LOGGER.debug( 'Party delete page accessed using method {}, id={}'.format(request.method, idx), request, request.POST) uid = request.user.id uname = request.user.username party = get_object_or_404(Party, pk=idx, uid=uid) if request.method == 'GET': return render( request, 'sur_partydel.xhtml', {'app': APP, 'page_title': 'Smazání účastníka', 'desc': party.party}) else: if getbutton(request) == 'yes': LOGGER.info('User "{}" ({:d}) deleted party "{}"'.format(uname, uid, party.party), request) party.delete() return redirect('sur:partydeleted') return redirect('sur:mainpage')
def procdel(request, idx=0): LOGGER.debug( 'Proceedings delete page accessed using method {}, id={}'.format( request.method, idx), request, request.POST) uid = request.user.id uname = request.user.username proc = get_object_or_404(Proceedings, pk=idx, uid=uid) if request.method == 'GET': return render(request, 'szr_procdel.xhtml', { 'app': APP, 'page_title': 'Smazání řízení', 'desc': proc.desc }) else: if getbutton(request) == 'yes': LOGGER.info( 'User "{}" ({:d}) deleted proceedings "{}" ({})'.format( uname, uid, proc.desc, p2s(proc)), request) proc.delete() return redirect('szr:procdeleted') return redirect('szr:mainpage')
def debtordel(request, idx=0): LOGGER.debug( 'Debtor delete page accessed using method {}, id={}'.format(request.method, idx), request, request.POST) uid = request.user.id uname = request.user.username debtor = get_object_or_404(Debtor, pk=idx, uid=uid) if request.method == 'GET': return render( request, 'dir_debtordel.xhtml', {'app': APP, 'page_title': 'Smazání dlužníka', 'desc': debtor.desc}) else: if getbutton(request) == 'yes': LOGGER.info('User "{}" ({:d}) deleted debtor "{}"'.format(uname, uid, debtor.desc), request) debtor.delete() return redirect('dir:debtordeleted') return redirect('dir:mainpage')
def insdel(request, idx=0): LOGGER.debug( 'Proceedings delete page accessed using method {}, id={}'.format(request.method, idx), request, request.POST) uid = request.user.id uname = request.user.username ins = get_object_or_404(Insolvency, pk=idx, uid=uid) if request.method == 'GET': return render( request, 'sir_insdel.xhtml', {'app': APP, 'page_title': 'Smazání řízení', 'desc': ins.desc}) else: if getbutton(request) == 'yes': LOGGER.info( 'User "{}" ({:d}) deleted proceedings "{}" ({})'.format(uname, uid, ins.desc, p2s(ins)), request) ins.delete() return redirect('sir:insdeleted') return redirect('sir:mainpage')
def partybatchform(request): LOGGER.debug('Party import page accessed using method {}'.format(request.method), request) err_message = '' uid = request.user.id uname = request.user.username if request.method == 'POST': button = getbutton(request) if button == 'load': infile = request.FILES.get('load') if not infile: err_message = 'Nejprve zvolte soubor k načtení' else: errors = [] try: count = 0 with infile: idx = 0 for line in csvreader(StringIO(infile.read().decode())): idx += 1 errlen = len(errors) if not line: continue line = line[0].strip() if ':' in line: line, party_opt = line.split(':', 1) else: party_opt = '*' if not between(MIN_LENGTH, len(line), MAX_LENGTH): errors.append((idx, 'Chybná délka řetězce')) continue if party_opt not in TEXT_OPTS_ABBR: errors.append((idx, 'Chybná zkratka pro posici')) continue if len(errors) == errlen: try: Party.objects.update_or_create( uid_id=uid, party=line, defaults={'party_opt': TEXT_OPTS_AI[party_opt]} ) except: errors.append((idx, 'Řetězci "{}" odpovídá více než jeden účastník'.format(line))) continue count += 1 LOGGER.info('User "{}" ({:d}) imported {} party/ies'.format(uname, uid, count), request) return render( request, 'sur_partybatchresult.xhtml', {'app': APP, 'page_title': 'Import účastníků řízení ze souboru', 'count': count, 'errors': errors}) except: # pragma: no cover LOGGER.error('Error reading file', request) err_message = 'Chyba při načtení souboru' else: LOGGER.debug('Invalid form', request) err_message = INERR return render( request, 'sur_partybatchform.xhtml', {'app': APP, 'page_title': 'Import účastníků řízení ze souboru', 'err_message': err_message, 'min_length': MIN_LENGTH, 'max_length': MAX_LENGTH})
def cron_update(): nss = Court.objects.get(pk=SUPREME_ADMINISTRATIVE_COURT) try: res = get(FORM_URL) soup = BeautifulSoup(res.text, 'html.parser') form = soup.find('form') dct = {i['name']: i['value'] for i in form.find_all('input') if i['type'] == 'hidden' and i.has_attr('value')} while True: dct['_ctl0:ContentPlaceMasterPage:_ctl0:ddlSortName'] = '5' dct['_ctl0:ContentPlaceMasterPage:_ctl0:ddlSortDirection'] = '1' res = post(FORM_URL, dct) soup = BeautifulSoup(res.text, 'html.parser') for item in soup.select('table.item'): try: ttr = item.select('tr') senate, register, number, year, page = decomposeref(ttr[0].td.text.strip()) if Decision.objects.filter( senate=senate, register=register, number=number, year=year, page=page).exists(): continue fileurl = ttr[4].a['href'] filename = fileurl.split('/')[-1] if not FRE.match(filename): continue res = get(ROOT_URL + fileurl) if not res.ok: continue LOGGER.info('Writing abridged decision "{}"'.format(composeref(senate, register, number, year))) with open(join(REPO_PREF, filename), 'wb') as outfile: if not outfile.write(res.content): # pragma: no cover LOGGER.error( 'Failed to write abridged decision "{}"' .format(composeref(senate, register, number, year))) continue adddoc(APP, filename, ROOT_URL + fileurl) agenda = Agenda.objects.get_or_create(desc=ttr[2].td.text.strip())[0] dat = date(*map(int, list(reversed(ttr[3].td.text.split('.'))))) dec = Decision( senate=senate, register=register, number=number, year=year, page=page, agenda=agenda, date=dat, filename=filename) dec.save() for query in ttr[1].td: if 'strip' in dir(query): qstrip = query.strip() party = Party.objects.get_or_create(name=qstrip)[0] dec.parties.add(party) sur_check( {'check_udn': True}, qstrip, nss, senate, register, number, year, DEC_URL.format(senate, quote(register), number, year, page)) except: # pragma: no cover pass pagers = soup.select('div#PagingBox2')[0] cpag = int(pagers.b.text[1:-1]) pager = pagers.select('a') if cpag > len(pager): break form = soup.find('form') dct = {i['name']: i['value'] for i in form.find_all('input') if i['type'] == 'hidden' and i.has_attr('value')} dct['__EVENTTARGET'] = pager[cpag - 1]['href'][70:-34] dct['__EVENTARGUMENT'] = '' except: # pragma: no cover LOGGER.warning('Update failed')
def insbatchform(request): LOGGER.debug('Proceedings import page accessed using method {}'.format(request.method), request) err_message = '' uid = request.user.id uname = request.user.username if request.method == 'POST': button = getbutton(request) if button == 'load': infile = request.FILES.get('load') if not infile: err_message = 'Nejprve zvolte soubor k načtení' else: errors = [] try: count = 0 with infile: idx = 0 for line in csvreader(StringIO(infile.read().decode())): idx += 1 errlen = len(errors) if not line: continue desc = line[0].strip() if not desc: errors.append((idx, 'Prázdný popis')) continue if len(desc) > 255: errors.append((idx, 'Příliš dlouhý popis')) continue try: number = int(line[1]) assert number > 0 except: errors.append((idx, 'Chybné běžné číslo')) continue try: year = int(line[2]) assert year >= 2008 except: errors.append((idx, 'Chybný ročník')) continue detailed = line[3].strip() if detailed == 'ano': detailed = True elif detailed == 'ne': detailed = False else: errors.append((idx, 'Chybný údaj pro pole Vše')) continue if len(errors) == errlen: try: Insolvency.objects.update_or_create( uid_id=uid, desc=desc, defaults={ 'number': number, 'year': year, 'detailed': detailed} ) except: errors.append((idx, 'Popisu "{}" odpovídá více než jedno řízení'.format(desc))) continue count += 1 LOGGER.info('User "{}" ({:d}) imported {:d} proceedings'.format(uname, uid, count), request) return render( request, 'sir_insbatchresult.xhtml', {'app': APP, 'page_title': 'Import řízení ze souboru', 'count': count, 'errors': errors}) except: # pragma: no cover LOGGER.error('Error reading file', request) err_message = 'Chyba při načtení souboru' return render( request, 'sir_insbatchform.xhtml', {'app': APP, 'page_title': 'Import řízení ze souboru', 'err_message': err_message})
def cron_update(*args): today = date.today() if args: dates = [] for arg in args: string = arg.split('.') dates.append(datetime(*map(int, string[2::-1]))) else: dates = [today + ODP] for dat in dates: flt = {'subsidiary_region': False, 'subsidiary_county': False} if not args: flt['updated__lt'] = datetime.now() - UPDATE_INTERVAL for publisher in Publisher.objects.filter(**flt).order_by('id'): try: sleep(1) res = get(LIST_URL.format(publisher.pubid)) assert res.ok soup = BeautifulSoup(res.text, 'html.parser') rows = soup.find_all('tr') if not rows: continue for row in rows: cells = row.find_all('td') if len(cells) < 5: continue links = cells[0].select('a[href]') if not links: continue desc = ref = senate = register = number = year = page = agenda = posted = None files = [] href = links[0].get('href') if href and href.startswith('vyveseni.aspx?vyveseniid='): try: docid = int(href.partition('=')[2]) except ValueError: continue try: posted = date(*map(int, cells[0].text.strip().split('.')[2::-1])) except: continue else: continue if Document.objects.filter(publisher=publisher, posted=posted, docid=docid).exists(): continue try: desc = cells[1].text.strip() ref = cells[2].text.strip() senate, register, number, year, page = parse_ref(ref) agenda = Agenda.objects.get_or_create(desc=cells[3].text.strip())[0] anchors = cells[4].find_all('a') if not anchors: continue for anchor in anchors: if not(anchor and anchor.has_attr('href') and anchor['href'].startswith('soubor.aspx?souborid=')): continue fileid = int(anchor['href'].partition('=')[2]) span = anchor.find('span', 'zkraceno') filename = span['title'].strip() if span else anchor.text.strip() if not filename: continue if filename.endswith(')'): filename = filename.rpartition(' (')[0] filename = filename.replace(' ', '_') if fileid not in [x[0] for x in files]: files.append((fileid, filename)) doc = Document.objects.get_or_create( docid=docid, publisher=publisher, desc=desc, ref=ref, senate=senate, register=register, number=number, year=year, page=page, agenda=agenda, posted=posted, )[0] for fileid, filename in files: if File.objects.filter(fileid=fileid).exists(): File.objects.filter(fileid=fileid).update(document=doc) continue infile = get(FILE_URL.format(fileid)) assert infile.ok content = infile.content dirname = join(REPO_PREF, str(fileid)) makedirs(dirname, exist_ok=True) pathname = join(dirname, filename) with open(pathname, 'wb') as outfile: outfile.write(content) adddoc(APP, join(str(fileid), filename), FILE_URL.format(fileid)) try: text = process(pathname).decode() ocr = len(text) < 5 if ocr: text = process(pathname, method='tesseract', language='ces').decode() except: text = '' ocr = False File.objects.update_or_create( fileid=fileid, defaults={ 'document': doc, 'name': filename, 'text': text, 'ocr': ocr, } ) update_index(doc) if not args or TEST: sleep(.2) for party in Party.objects.filter(check_uds=True): if DocumentIndex.objects.filter(id=doc.id, text__search='"{}"'.format(party.party)): Retrieved.objects.update_or_create( uid_id=party.uid_id, party=party, document=doc) if party.uid.email: Party.objects.filter(id=party.id).update(notify=True) LOGGER.info( 'New party "{}" detected for user "{}" ({:d})' .format( party.party, User.objects.get(pk=party.uid_id).username, party.uid_id)) except: continue LOGGER.debug('Updated "{}", {:%Y-%m-%d}'.format(publisher.name, dat)) if not args: Publisher.objects.filter(id=publisher.id).update(updated=datetime.now()) except: LOGGER.info('Failed to update "{}", {:%Y-%m-%d}'.format(publisher.name, dat)) LOGGER.debug('Updated all publishers, {:%Y-%m-%d}'.format(dat))
def updateproc(proc): notnew = bool(proc.updated) proc.updated = datetime.now() proc.save() court = proc.court_id try: if court == SUPREME_ADMINISTRATIVE_COURT: addauxid(proc) if not proc.auxid: return url = NSS_GET_PROC.format(proc.auxid) res = get(url) soup = BeautifulSoup(res.text, 'html.parser') table = soup.find('table', 'frm') else: court_type = 'ns' if court == SUPREME_COURT else 'os' url = ROOT_URL + GET_PROC.format( court, proc.court.reports.id if proc.court.reports else proc.court.id, proc.senate, quote(proc.register.upper()), proc.number, proc.year, court_type) res = get(url) soup = BeautifulSoup(res.text, 'html.parser') table = soup.find('tr', 'AAAA') assert table except: # pragma: no cover LOGGER.warning( 'Failed to check proceedings "{0.desc}" ({1}) for user "{2}" ({0.uid_id:d})' .format(proc, p2s(proc), User.objects.get(pk=proc.uid_id).username)) return False hsh = md5(str(table).encode()).hexdigest() if court != SUPREME_ADMINISTRATIVE_COURT: changed = None try: tbl = table.find_next_sibling().find_next_sibling().table.tr.td.find_next_sibling().text.split() if len(tbl) == 4: changed = datetime(*map(int, list(reversed(tbl[0].split('.'))) + tbl[1].split(':'))) except: # pragma: no cover LOGGER.warning( 'Failed to check proceedings "{0.desc}" ({1}) for user "{2}" ({0.uid_id:d})' .format(proc, p2s(proc), User.objects.get(pk=proc.uid_id).username)) if changed != proc.changed or hsh != proc.hash: proc.notify |= notnew if changed: proc.changed = changed LOGGER.info( 'Change detected in proceedings "{0.desc}" ({1}) for user "{2}" ({0.uid_id:d})' .format(proc, p2s(proc), User.objects.get(pk=proc.uid_id).username)) elif hsh != proc.hash: proc.notify |= notnew if notnew: proc.changed = proc.updated if proc.changed: LOGGER.info( 'Change detected in proceedings "{0.desc}" ({1}) for user "{2}" ({0.uid_id:d})' .format(proc, p2s(proc), User.objects.get(pk=proc.uid_id).username)) proc.hash = hsh LOGGER.debug( 'Proceedings "{0.desc}" ({1}) updated for user "{2}" ({0.uid_id:d})' .format(proc, p2s(proc), User.objects.get(pk=proc.uid_id).username)) return True