def login(username, password): # check if the username is valid orig_user = session.query(Client).filter_by(username=username).one_or_none() if orig_user is None: return False last_blocked = orig_user.last_blocked if last_blocked and (datetime.now() - dateparser.parse(last_blocked)).seconds < 300: # user is blocked for 5 minutes return False # hash the password user_salt = orig_user.salt hashed_password = bcrypt.hashpw(password.encode(), user_salt) user = session.query(Client).filter_by(username=username, password=hashed_password).one_or_none() if user: # successful login, reset the invalid_logins table user.invalid_logins.login_count = 0 return user else: if orig_user is not None: # invalid login, must increment in the DB table invalid_login_count = orig_user.invalid_logins.login_count + 1 if invalid_login_count == INVALID_LOGIN_BRUTEFORCE_PROTECTION_COUNT: # block user block_user(orig_user) else: orig_user.invalid_logins.login_count = invalid_login_count return False
def delete_rows_from_table(table_name: str, char_id: int): """ This function will delete every row in TABLE_NAME with a saved_character_id of char_id :param table_name: a string -> "saved_character_loaded_scripts" for example which is in ALLOWED_TABLES_TO_DELETE_FROM Every table in that variable has a saved_character_id column :param char_id: the id of the rows we want to delete -> 1 The function is used whenever we want to save new information. To save the new updated information, we have to delete the old one first. """ if table_name in ALLOWED_TABLES_TO_DELETE_FROM: session.query(ALLOWED_TABLES_TO_DELETE_FROM[table_name]).filter_by(saved_character_id=char_id).delete() else: raise Exception(f'You do not have permission to delete from the {table_name} table!')
def load_character_level_stats() -> dict: """ Return a dictionary holding information about the amount of stats that a character should get according to the level he has just attained """ # Define these here as well. We can't import from constants because constants imports from here KEY_LEVELUP_STATS_HEALTH = 'health' KEY_LEVELUP_STATS_MANA = 'mana' KEY_LEVELUP_STATS_STRENGTH = 'strength' KEY_LEVELUP_STATS_ARMOR = 'armor' KEY_LEVELUP_STATS_AGILITY = 'agility' level_stats = {} loaded_stats = session.query(LevelUpStatsSchema).all() for stat in loaded_stats: level = stat.level health = parse_int(stat.health) mana = parse_int(stat.mana) strength = parse_int(stat.strength) agility = parse_int(stat.agility) armor = parse_int(stat.armor) level_stats[level] = { KEY_LEVELUP_STATS_HEALTH: health, KEY_LEVELUP_STATS_MANA: mana, KEY_LEVELUP_STATS_AGILITY: agility, KEY_LEVELUP_STATS_STRENGTH: strength, KEY_LEVELUP_STATS_ARMOR: armor } return level_stats
def load_character_xp_requirements() -> {int: int}: """ Load the information about the necessary XP needed to reach a certain level. """ loaded_xp_reqs = session.query(LevelXpRequirementSchema).all() return {xp_req.level: xp_req.xp_required for xp_req in loaded_xp_reqs}
def load_monsters(zone: str, subzone: str, character) -> tuple: """ Loads all the creatures in the given zone :return: A Dictionary: Key: guid, Value: Object of class entities.py/Monster, A Set of Tuples ((Monster GUID, Monster Name)) """ monsters_dict: {int: Monster} = {} guid_name_set: {(int, str)} = set() print("Loading Monsters...") creatures = session.query(CreaturesSchema).filter_by(type='monster', zone=zone, sub_zone=subzone).all() for creature in creatures: if character.has_killed_monster(creature.guid): # if the character has killed this monster before and has it saved, we don't want to load it continue monster = creature.convert_to_living_thing_object() guid_name_set.add((creature.guid, monster.name)) monsters_dict[creature.guid] = monster print("Monsters loaded!") return monsters_dict, guid_name_set
def load_monsters(zone: str, subzone: str, character) -> tuple: """ Loads all the creatures in the given zone :return: A Dictionary: Key: guid, Value: Object of class entities.py/Monster, A Set of Tuples ((Monster GUID, Monster Name)) """ monsters_dict: {int: Monster} = {} guid_name_set: {(int, str)} = set() print("Loading Monsters...") creatures = session.query(CreaturesSchema).filter_by( type='monster', zone=zone, sub_zone=subzone).all() for creature in creatures: if character.has_killed_monster(creature.guid): # if the character has killed this monster before and has it saved, we don't want to load it continue monster = creature.convert_to_living_thing_object() guid_name_set.add((creature.guid, monster.name)) monsters_dict[creature.guid] = monster print("Monsters loaded!") return monsters_dict, guid_name_set
def load_npcs(zone: str, subzone: str) -> tuple: """ Load all the friendly NPCs in the given zone/subzone :return: A Dictionary: Key: guid, Value: Object of class entities.py/FriendlyNPC, A Set of Tuples ((npc GUID, npc Name)) """ npcs_dict: {str: 'FriendlyNPC' or 'VendorNPC'} = {} guid_name_set: {(int, str)} = set() print("Loading Friendly NPCs...") loaded_npcs = session.query(CreaturesSchema).filter( (((CreaturesSchema.type == 'fnpc') | (CreaturesSchema.type == 'vendor')) & (CreaturesSchema.zone == zone) & (CreaturesSchema.sub_zone == subzone))) for npc_info in loaded_npcs: guid: int = npc_info.guid loaded_npc = npc_info.convert_to_living_thing_object() guid_name_set.add((guid, loaded_npc.name)) npcs_dict[guid] = loaded_npc print("Friendly NPCs loaded!") return npcs_dict, guid_name_set
def load_all_saved_characters_general_info() -> [dict()]: """ This function loads general information about the saved characters in the DB and returns it as a list of dictionaries to be easily printable. """ loaded_characters: [SavedCharacterSchema] = session.query(SavedCharacterSchema).options(load_only("name", "character_class", "level")).all() return [{'name': ch.name, 'class': ch.character_class, 'level': ch.level} for ch in loaded_characters]
def movie_choice_prompt(): """ Shows the movies to the user and prompts him for a choice using the movie's id """ to_give_up = False show_movies() movie_id = input(">Choose a movie: ") movie = session.query(MovieSchema).get(movie_id) while not movie: print("Invalid movie id!") movie_id = input(">Choose a movie: ") if movie_id == "give up": to_give_up = True break movie = session.query(MovieSchema).get(movie_id) return movie, to_give_up
def delete_rows_from_table(table_name: str, char_id: int): """ This function will delete every row in TABLE_NAME with a saved_character_id of char_id :param table_name: a string -> "saved_character_loaded_scripts" for example which is in ALLOWED_TABLES_TO_DELETE_FROM Every table in that variable has a saved_character_id column :param char_id: the id of the rows we want to delete -> 1 The function is used whenever we want to save new information. To save the new updated information, we have to delete the old one first. """ if table_name in ALLOWED_TABLES_TO_DELETE_FROM: session.query(ALLOWED_TABLES_TO_DELETE_FROM[table_name]).filter_by( saved_character_id=char_id).delete() else: raise Exception( f'You do not have permission to delete from the {table_name} table!' )
def load_paladin_spells_for_level(level: int) -> ['PaladinSpell']: """ Load all the paladin spells that are available for the SPECIFIC level. Get all the PaladinSpells schema objects and convert them to PaladinSpell objects. Return said objects in a list """ loaded_spells: [PaladinSpellsSchema] = session.query(PaladinSpellsSchema).filter_by(level_required=level).all() return [spell.convert_to_paladin_spell_object() for spell in loaded_spells]
def save_character(character: Character): """ Save the character into the database """ character_info: SavedCharacterSchema = session.query(SavedCharacterSchema).filter_by(name=character.name).one_or_none() character_level: int = character.level # type: int character_class: str = character.get_class() # type: str character_gold: int = character.inventory['gold'] # type: int equipment: {str: int} = character.equipment headpiece_id: int = get_item_id_or_none(equipment[CHARACTER_EQUIPMENT_HEADPIECE_KEY]) shoulderpad_id: int = get_item_id_or_none(equipment[CHARACTER_EQUIPMENT_SHOULDERPAD_KEY]) necklace_id: int = get_item_id_or_none(equipment[CHARACTER_EQUIPMENT_NECKLACE_KEY]) chestguard_id: int = get_item_id_or_none(equipment[CHARACTER_EQUIPMENT_CHESTGUARD_KEY]) bracer_id: int = get_item_id_or_none(equipment[CHARACTER_EQUIPMENT_BRACER_KEY]) gloves_id: int = get_item_id_or_none(equipment[CHARACTER_EQUIPMENT_GLOVES_KEY]) belt_id: int = get_item_id_or_none(equipment[CHARACTER_EQUIPMENT_BELT_KEY]) leggings_id: int = get_item_id_or_none(equipment[CHARACTER_EQUIPMENT_LEGGINGS_KEY]) boots_id: int = get_item_id_or_none(equipment[CHARACTER_EQUIPMENT_BOOTS_KEY]) character_values: {str: int or str} = { 'name': character.name, 'character_class': character_class, 'level': character_level, 'gold': character_gold, 'headpiece_id': headpiece_id, 'shoulderpad_id': shoulderpad_id, 'necklace_id': necklace_id, 'chestguard_id': chestguard_id, 'belt_id': belt_id, 'bracer_id': bracer_id, 'gloves_id': gloves_id, 'leggings_id': leggings_id, 'boots_id': boots_id} # if the character exists, update the row, otherwise create a new one if character_info: session.query(SavedCharacterSchema).filter_by(name=character.name).update(character_values) else: session.add(SavedCharacterSchema(**character_values)) session.commit() # save the sub-tables char_entry = session.query(SavedCharacterSchema).filter_by(name=character.name).first().entry save_loaded_scripts(char_entry, character.loaded_scripts) save_killed_monsters(char_entry, character.killed_monsters) save_completed_quests(char_entry, character.completed_quests) save_inventory(char_entry, character.inventory) session.commit() print("-" * 40) print(f'Character {character.name} was saved successfully!') print("-" * 40)
def get_movie_projections(movie_id, date=None) -> tuple: """ Given a movie_id and an optional date, return the appropriate movie projections """ movie = session.query(MovieSchema).get(movie_id) if not movie: print("Invalid movie id!") return None, None elif date and not is_valid_date(date): print('Invalid date! Date should be in the format of YYYY-MM-DD!') return None, None return movie, movie.projections
def load_dot(dot_id: int, caster_level: int) -> 'DoT': """ Loads a DoT from the spell_dots table, whose contents are the following: Load the information about the DoT, convert it to an instance of class DoT and return it. :param dot_id: the entry of the DoT in the spell_dots table :param level: the level of the caster """ dot_info: DotSchema = session.query(DotSchema).get(dot_id) return dot_info.convert_to_dot_object(caster_level)
def log_user(): """ Log in a user to the system""" print('Please log in:') username = input('>Username ') password = input('>Password ') # fetch from the DB user = session.query(UserSchema).filter_by(username=username, password=password).one_or_none() while user is None: print("Invalid username/password! Would you like to log in again?(y/n)") choice = input() if choice not in ['y', 'yes', 'Y', 'Yes']: return None # user has given up on logging in username = input('>Username ') password = input('>Password ') user = session.query(UserSchema).filter_by(username=username, password=password).one_or_none() return user
def load_item(item_id: int): """ Load an item from item_template, convert it to a object of Class Item and return it """ if item_id <= 0 or not isinstance(item_id, int): raise Exception("There is no such item with an ID that's 0 or negative!") item_template_info: ItemTemplateSchema = session.query(ItemTemplateSchema).get(item_id) if item_template_info is None: raise Exception(f'There is no such item with an ID {item_id}!') return item_template_info.convert_to_item_object()
def load_all_saved_characters_general_info() -> [dict()]: """ This function loads general information about the saved characters in the DB and returns it as a list of dictionaries to be easily printable. """ loaded_characters: [SavedCharacterSchema ] = session.query(SavedCharacterSchema).options( load_only("name", "character_class", "level")).all() return [{ 'name': ch.name, 'class': ch.character_class, 'level': ch.level } for ch in loaded_characters]
def load_item(item_id: int): """ Load an item from item_template, convert it to a object of Class Item and return it """ if item_id <= 0 or not isinstance(item_id, int): raise Exception( "There is no such item with an ID that's 0 or negative!") item_template_info: ItemTemplateSchema = session.query( ItemTemplateSchema).get(item_id) if item_template_info is None: raise Exception(f'There is no such item with an ID {item_id}!') return item_template_info.convert_to_item_object()
def load_buff(buff_id: int) -> 'BeneficialBuff': """ Loads a buff from the DB table spells_buffs, whose contents are the following: entry, name, duration, stat, amount, stat2, amount2,stat3, amount3, comment 1, Heart of a Lion, 5,strength, 10, Increases strength by 10 for 5 turns stat - the stat this buff increases amount - the amount it increases the stat by duration - the amount of turns this buff lasts for This buff increases your strength by 10 for 5 turns. Load the information about the buff, convert it to an class Buff object and return it :param buff_id: the buff entry in spells_buffs :return: A instance of class Buff """ buff: BuffSchema = session.query(BuffSchema).get(buff_id) return buff.convert_to_beneficial_buff_object()
def load_creature_defaults() -> {int: {str: int}}: """ Load the default values that a creature should have/give at a certain level. :return: A dictionary as follows: Key: Level(ex: 1), Value: Dictionary{'armor': 50, 'min_gold_reward': 2, 'max_gold_reward': 5, 'xp_reward': 50} """ creature_defaults = {} loaded_creature_defaults: [CreatureDefaultsSchema] = session.query(CreatureDefaultsSchema).all() for creature_default in loaded_creature_defaults: creature_defaults[creature_default.creature_level] = {'armor': creature_default.armor, 'min_gold_reward': creature_default.min_gold_reward, 'max_gold_reward': creature_default.max_gold_reward, 'xp_reward': creature_default.xp_reward} return creature_defaults
def load_saved_character(name: str): """ This function loads the information about a saved chacacter in the saved_character DB table. name, class, level, loaded_scripts_ID, killed_monsters_ID, completed_quests_ID, inventory_ID, gold Netherblood, Paladin, 10, 1, 1, 1, 1, 23 The attributes that end in ID like loaded_scripts_ID are references to other tables. For more information: https://github.com/Enether/python_wow/wiki/How-saving-a-Character-works-and-information-about-the-saved_character-database-table. """ from classes import Paladin loaded_character: SavedCharacterSchema = session.query(SavedCharacterSchema).filter_by(name=name).one_or_none() if loaded_character is None: raise NoSuchCharacterError(f'There is no saved character by the name of {name}!') return loaded_character.convert_to_character_object()
def load_saved_character(name: str): """ This function loads the information about a saved chacacter in the saved_character DB table. name, class, level, loaded_scripts_ID, killed_monsters_ID, completed_quests_ID, inventory_ID, gold Netherblood, Paladin, 10, 1, 1, 1, 1, 23 The attributes that end in ID like loaded_scripts_ID are references to other tables. For more information: https://github.com/Enether/python_wow/wiki/How-saving-a-Character-works-and-information-about-the-saved_character-database-table. """ from classes import Paladin loaded_character: SavedCharacterSchema = session.query( SavedCharacterSchema).filter_by(name=name).one_or_none() if loaded_character is None: raise NoSuchCharacterError( f'There is no saved character by the name of {name}!') return loaded_character.convert_to_character_object()
def load_quests(zone: str, subzone: str, character) -> {str: Quest}: """ Load all the quests in the zone/subzone that are available for the given character. :param zone: The zone that the query will use :param subzone: The subzone that the query will use :param character: The Character object we're loading the quests for. :return: A Dctionary Key: Quest Name Value: Quest Object """ loaded_quests: {str: Quest} = {} quests = session.query(QuestSchema).filter_by(zone=zone, sub_zone=subzone).all() print("Loading Quests...") for quest in quests: if character.has_completed_quest(quest.entry): continue # do not load the quest into the game if the character has completed it loaded_quests[quest.name] = quest.convert_to_quest_object() return loaded_quests
def load_creature_defaults() -> {int: {str: int}}: """ Load the default values that a creature should have/give at a certain level. :return: A dictionary as follows: Key: Level(ex: 1), Value: Dictionary{'armor': 50, 'min_gold_reward': 2, 'max_gold_reward': 5, 'xp_reward': 50} """ creature_defaults = {} loaded_creature_defaults: [CreatureDefaultsSchema ] = session.query(CreatureDefaultsSchema).all() for creature_default in loaded_creature_defaults: creature_defaults[creature_default.creature_level] = { 'armor': creature_default.armor, 'min_gold_reward': creature_default.min_gold_reward, 'max_gold_reward': creature_default.max_gold_reward, 'xp_reward': creature_default.xp_reward } return creature_defaults
def load_npcs(zone: str, subzone: str) -> tuple: """ Load all the friendly NPCs in the given zone/subzone :return: A Dictionary: Key: guid, Value: Object of class entities.py/FriendlyNPC, A Set of Tuples ((npc GUID, npc Name)) """ npcs_dict: {str: 'FriendlyNPC' or 'VendorNPC'} = {} guid_name_set: {(int, str)} = set() print("Loading Friendly NPCs...") loaded_npcs = session.query(CreaturesSchema).filter((((CreaturesSchema.type == 'fnpc') | (CreaturesSchema.type == 'vendor')) & (CreaturesSchema.zone == zone) & (CreaturesSchema.sub_zone == subzone))) for npc_info in loaded_npcs: guid: int = npc_info.guid loaded_npc = npc_info.convert_to_living_thing_object() guid_name_set.add((guid, loaded_npc.name)) npcs_dict[guid] = loaded_npc print("Friendly NPCs loaded!") return npcs_dict, guid_name_set
def consume_tan_code(tan_code): t_code = session.query(TanCode).filter_by(tan_code=tan_code) t_code.delete(synchronize_session='fetch') session.flush() session.commit()
def save_character(character: Character): """ Save the character into the database """ character_info: SavedCharacterSchema = session.query( SavedCharacterSchema).filter_by(name=character.name).one_or_none() character_level: int = character.level # type: int character_class: str = character.get_class() # type: str character_gold: int = character.inventory['gold'] # type: int equipment: {str: int} = character.equipment headpiece_id: int = get_item_id_or_none( equipment[CHARACTER_EQUIPMENT_HEADPIECE_KEY]) shoulderpad_id: int = get_item_id_or_none( equipment[CHARACTER_EQUIPMENT_SHOULDERPAD_KEY]) necklace_id: int = get_item_id_or_none( equipment[CHARACTER_EQUIPMENT_NECKLACE_KEY]) chestguard_id: int = get_item_id_or_none( equipment[CHARACTER_EQUIPMENT_CHESTGUARD_KEY]) bracer_id: int = get_item_id_or_none( equipment[CHARACTER_EQUIPMENT_BRACER_KEY]) gloves_id: int = get_item_id_or_none( equipment[CHARACTER_EQUIPMENT_GLOVES_KEY]) belt_id: int = get_item_id_or_none(equipment[CHARACTER_EQUIPMENT_BELT_KEY]) leggings_id: int = get_item_id_or_none( equipment[CHARACTER_EQUIPMENT_LEGGINGS_KEY]) boots_id: int = get_item_id_or_none( equipment[CHARACTER_EQUIPMENT_BOOTS_KEY]) character_values: { str: int or str } = { 'name': character.name, 'character_class': character_class, 'level': character_level, 'gold': character_gold, 'headpiece_id': headpiece_id, 'shoulderpad_id': shoulderpad_id, 'necklace_id': necklace_id, 'chestguard_id': chestguard_id, 'belt_id': belt_id, 'bracer_id': bracer_id, 'gloves_id': gloves_id, 'leggings_id': leggings_id, 'boots_id': boots_id } # if the character exists, update the row, otherwise create a new one if character_info: session.query(SavedCharacterSchema).filter_by( name=character.name).update(character_values) else: session.add(SavedCharacterSchema(**character_values)) session.commit() # save the sub-tables char_entry = session.query(SavedCharacterSchema).filter_by( name=character.name).first().entry save_loaded_scripts(char_entry, character.loaded_scripts) save_killed_monsters(char_entry, character.killed_monsters) save_completed_quests(char_entry, character.completed_quests) save_inventory(char_entry, character.inventory) session.commit() print("-" * 40) print(f'Character {character.name} was saved successfully!') print("-" * 40)
def get_all_movies_ordered_by_date(): movies = session.query(MovieSchema).order_by(MovieSchema.rating.desc()).all() return movies
(self.item5, self.item5_chance), (self.item6, self.item6_chance), (self.item7, self.item7_chance), (self.item8, self.item8_chance), (self.item9, self.item9_chance), (self.item10, self.item10_chance), (self.item11, self.item11_chance), (self.item12, self.item12_chance), (self.item13, self.item13_chance), (self.item14, self.item14_chance), (self.item15, self.item15_chance), (self.item16, self.item16_chance), (self.item17, self.item17_chance), (self.item18, self.item18_chance), (self.item19, self.item19_chance), (self.item20, self.item20_chance)] valid_item_pairs = [(item, chance) for item, chance in item_pairs if item is not None and chance != 0] dropped_items = [] for item, drop_chance in valid_item_pairs: ''' Generate a random float from 0.0 to ~0.9999 with random.random(), then multiply it by 100 and compare it to the drop_chance. If the drop_chance is bigger, the item has dropped. Example: drop chance is 30% and we roll a random float. There's a 70% chance to get a float that's bigger than 0.3 and a 30% chance to get a float that's smaller. Therefore if we get 0.3 and below, the 30% chance has been satisfied. We roll 0.25, multiply it by 100 = 25 and see that the drop chance is bigger, therefore the item should drop. ''' random_roll: float = random.random() if drop_chance >= (random_roll * 100): dropped_items.append(item.convert_to_item_object()) return dropped_items # load all the loot tables in memory so that future SQLAlchemy queries do not access the DB # NOTE: Do not do this if the loot tables become more than 500 ! loot_tables = session.query(LootTableSchema).all()
def cancel_reservation(cinema: Cinema, username: str): user = cinema.user _ = session.query(ReservationSchema).filter_by(user_id=user.id_).delete() session.flush() session.commit() print('You have successfully cancelled all your reservations!')