def generate_unique_codename(config): """Generate random codenames until we get an unused one""" while True: codename = current_app.crypto_util.genrandomid( Source.NUM_WORDS, i18n.get_language(config)) # The maximum length of a word in the wordlist is 9 letters and the # codename length is 7 words, so it is currently impossible to # generate a codename that is longer than the maximum codename length # (currently 128 characters). This code is meant to be defense in depth # to guard against potential future changes, such as modifications to # the word list or the maximum codename length. if len(codename) > Source.MAX_CODENAME_LEN: current_app.logger.warning( "Generated a source codename that was too long, " "skipping it. This should not happen. " "(Codename='{}')".format(codename)) continue # scrypt (slow) filesystem_id = current_app.crypto_util.hash_codename(codename) matching_sources = Source.query.filter( Source.filesystem_id == filesystem_id).all() if len(matching_sources) == 0: return codename
def make_password(config): while True: password = crypto_util.genrandomid(7, i18n.get_language(config)) try: Journalist.check_password_acceptable(password) return password except PasswordError: continue
def format_percent(english: str) -> str: """Formats a percentage, taking locale into account.""" parsed = float(english) formatted = '{0:.2f}%'.format(parsed) decimal_points = { "hu": ",", } decimal_point = decimal_points.get(i18n.get_language(), ".") return formatted.replace(".", str(decimal_point))
def language_advert(): lang=get_language() f=os.path.join(get_flag_file_path(),lang+".png") if os.path.isfile(f)==True: b=bibtex() loaded=b.load(os.path.join(get_full_desired_lang_path(),"ref.bib")) if loaded==False or r.author=="": my_help_class.help_append([f,"<big><b>"+_("gpvdm in your language!")+"</b></big><br>"+"Would you like gpvdm to be translated into your native language? If so please help with the gpvdm <a href=\"https://gpvdm.com/translation.html\">translation project.</a>"]) else: my_help_class.help_append([f,"<big><b>"+_("gpvdm translated by:")+"</b></big><br>"+r.author])
def update_missing_housenumbers(relations: areas.Relations, update: bool) -> None: """Update the relation's house number coverage stats.""" info("update_missing_housenumbers: start") for relation_name in relations.get_active_names(): relation = relations.get_relation(relation_name) if not update and os.path.exists( relation.get_files().get_housenumbers_percent_path()): continue streets = relation.get_config().should_check_missing_streets() if streets == "only": continue orig_language = i18n.get_language() relation.write_missing_housenumbers() for language in ["en", "hu"]: i18n.set_language(language) cache.get_missing_housenumbers_html(relation) i18n.set_language(orig_language) info("update_missing_housenumbers: end")
def get_additional_housenumbers_htmlcache_path(self) -> str: """Builds the file name of the additional house number HTML cache file of a relation.""" return os.path.join(self.__workdir, "%s.additional-htmlcache.%s" % (self.__name, i18n.get_language()))
def handle(self, msg): # if this caller doesn't have a "question" attribute, # they're not currently answering a question tree, so # just search for triggers and return sessions = Session.objects.all().filter(state__isnull=False).filter(connection=msg.persistant_connection) if not sessions: try: tree = Tree.objects.get(trigger=msg.text) # start a new session for this person and save it session = Session(connection=msg.persistant_connection, tree=tree, state=tree.root_state) session.save() self.debug("session %s saved" % session) #self.connections[msg.connection.identity] = tree.root_state # no trigger found? no big deal. the # message is probably for another app except Tree.DoesNotExist: return False # the caller is part-way though a question # tree, so check their answer and respond else: session = sessions[0] state = session.state self.debug(state) # this becomes a bit more complicated now. loop through all transitions # starting with this state and try each one depending on the type # this will be a greedy algorithm and NOT safe if multiple transitions # can match the same answer transitions = Transition.objects.filter(current_state=state) found_transition = None for transition in transitions: if self.matches(transition.answer, msg.text): found_transition = transition break # not a valid answer, so remind # the user of the valid options. if not found_transition: transitions = Transition.objects.filter(current_state=state) # there are no defined answers. therefore there are no more questions to ask if len(transitions) == 0: msg.respond("You are done with this survey. Thanks for participating!") # remove the connection so the caller can start a new session session.state = None session.save() # self.connections.pop(msg.connection.identity) return else: flat_answers = " or ".join([trans.answer.helper_text() for trans in transitions]) msg.respond('"%s" is not a valid answer. You must enter %s' % (msg.text, flat_answers)) return True # if this answer has a response, send it back to the user # before doing anything else. this means that they might # receive two messages (this, and the next question), but # avoids having to concatenate them. # czue - removing this functionality #if answer.response: # msg.respond(answer.response) # no matter what we want to create an entry for this response # have to know what sequence number to insert ids = Entry.objects.all().filter(session=session).order_by('sequence_id').values_list('sequence_id', flat=True) if ids: # not sure why pop() isn't allowed... sequence = ids[len(ids) -1] + 1 else: sequence = 1 entry = Entry(session=session,sequence_id=sequence,transition=found_transition,text=msg.text) entry.save() self.debug("entry %s saved" % entry) # advance to the next question, or remove # this caller's state if there are no more # this might be "None" but that's ok, it will be the equivalent of ending the session session.state = found_transition.next_state session.save() self.debug("session %s saved" % session) #self.connections[msg.connection.identity] =\ # transition.next_state # sent the LAST_MESSAGE to end the conversation, # unless the last question triggered a response #if not answer.response: # msg.respond(self.last_message) # if there is a next question ready to ask # (and this includes THE FIRST), send it along sessions = Session.objects.all().filter(state__isnull=False).filter(connection=msg.persistant_connection) if sessions: state = sessions[0].state if state.question: msg.respond(_(state.question.text, get_language(sessions[0].connection))) self.info(_(state.question.text, get_language(sessions[0].connection))) # if we haven't returned long before now, we're # long committed to dealing with this message return True