Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions task_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ def apiv2_get_user_profile(user: UserDatabaseObject):
'username': user.username,
'is_official': user.is_official,
'is_lms_enabled': user.lms_enabled,
'hide_below': user.effective_hide_below,
'has_migrated': user.has_migrated,
'active_task_id': user.current_task_id(),
'completed_tasks': [
Expand Down
22 changes: 22 additions & 0 deletions task_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ def add_task_account(username, is_official, lms_enabled):
"username": str(username),
"isOfficial": bool(is_official),
"lmsEnabled": bool(lms_enabled),
"hideBelow": 'easy',
"discordLinked": False,
"discordNameSyncEnabled": False,
"completedTasks": [],
Expand Down Expand Up @@ -494,6 +495,27 @@ def get_first_task_instance(generated_task: TaskData, incomplete_tasks: list[Tas
__set_current_task(username, f'{tier}Tasks', first_task_instance.id, True)
return first_task_instance


def set_hide_below(username: str, hide_below: str) -> None:
if hide_below not in user_dao.ROLLABLE_TIERS:
raise ValueError(f"Invalid minimum rollable tier: {hide_below}")

result = mydb['taskLists'].update_one(
{'username': username, 'isOfficial': False},
{'$set': {'hideBelow': hide_below}}
)
if result.matched_count == 0:
user = mydb['taskLists'].find_one(
{'username': username},
{'_id': 0, 'isOfficial': 1}
)
if user is None:
raise LookupError(f"No task account found for username {username}")
if user.get('isOfficial', False):
raise PermissionError("Hide Tasks Below is only available for unofficial accounts.")
raise LookupError(f"Could not update task account for username {username}")


# If user has just completed a task of the given tier and the progress is 100, then they've just completed the last task
def __get_firework_variables(username, tier):
user = get_user(username)
Expand Down
26 changes: 25 additions & 1 deletion taskapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
get_lms_status, lms_status_change, update_imported_tasks,
official_status_change, username_change, get_taskCurrent_tier, generate_task_for_tier,
complete_task_unofficial_tier, get_user, get_leaderboard,
get_roll_candidates_for_tier, get_discord_name_sync_enabled, clear_leaderboard_cache)
get_roll_candidates_for_tier, get_discord_name_sync_enabled, clear_leaderboard_cache,
set_hide_below)
import send_grid_email
from templesync import check_logs, temple_player_data, import_logs
from task_types import CollectionLogVerificationData
Expand All @@ -22,6 +23,7 @@
import task_api
import discord_api
import command_api
from user_dao import ROLLABLE_TIERS


'''
Expand Down Expand Up @@ -1083,6 +1085,8 @@ def profile():
email_val=user_info.email_val,
official=user_info.official,
lms_status=user_info.user.lms_enabled,
hide_below=user_info.user.hide_below,
rollable_tiers=ROLLABLE_TIERS,
discord_status=user_info.user.discord_linked,
discord_default_username=discord_default_username,
discord_name_sync_enabled=user_info.user.discord_name_sync_enabled,
Expand Down Expand Up @@ -1142,6 +1146,26 @@ def change_lms_status():
lms_status_change(username, data)
return {'success' : True}


@app.route("/profile/change-hide-below/", methods=['POST'])
@login_required
def change_hide_below():
user = get_user(session['username'])
if user.is_official:
return {'success': False, 'error': 'Hide Tasks Below is only available for unofficial accounts.'}, 403

hide_below = request.form.get('hide_below')
if hide_below not in ROLLABLE_TIERS:
return {'success': False, 'error': 'Invalid minimum task tier.'}, 400

try:
set_hide_below(session['username'], hide_below)
except PermissionError as error:
return {'success': False, 'error': str(error)}, 403

return {'success': True}


# AJAX route to change offical status
@app.route("/profile/change-official/", methods=['POST'])
@login_required
Expand Down
26 changes: 23 additions & 3 deletions templates/profile.html
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,14 @@ <h3>{{username}} Profile</h3>
<input type="checkbox" id="skip_roll_animation">
<span class="slider round"></span>
</label>
{% if not official %}
<p>Hide Tasks Below</p>
<select id="hide_below" aria-label="Hide tasks below">
{% for tier in rollable_tiers %}
<option value="{{ tier }}" {% if hide_below == tier %}selected{% endif %}>{{ tier|capitalize }}</option>
{% endfor %}
</select>
{% endif %}
</div>
<div class="warning-section">
<p id="warning"style="display: none;" class="incomplete">!!!YOU CANNOT RE-ENABLE OFFICIAL STATUS!!!</p>
Expand Down Expand Up @@ -366,7 +374,21 @@ <h3>Discord Settings</h3>
});
}


$('#hide_below').on('change', function() {
const hideBelow = $(this).val();
$.ajax({
url: '/profile/change-hide-below/',
type: 'POST',
data: {hide_below: hideBelow}
}).done(function(data) {
if (!data.success) {
alert(data.error || 'Could not update the minimum task tier.');
}
}).fail(function() {
alert('Could not update the minimum task tier.');
});
});

$('#discord_name_sync_enabled').on('change', function(e) {
var discord_name_sync_enabled = e.target.checked;
req = $.ajax({
Expand Down Expand Up @@ -418,5 +440,3 @@ <h3>Discord Settings</h3>
});
</script>
{% endblock%}


19 changes: 17 additions & 2 deletions user_dao.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,15 @@
"5cbcc790-10d1-4c17-8b39-cad7b48dadf8",
"4a387bb0-dfc3-4374-aa35-9bacfc2fc92d",
}
ROLLABLE_TIERS = ('easy', 'medium', 'hard', 'elite', 'master')

@dataclass
class UserDatabaseObject:
id: ObjectId
username: str
is_official: bool
lms_enabled: bool
hide_below: str
discord_linked: bool
discord_name_sync_enabled: bool
has_migrated: bool
Expand Down Expand Up @@ -99,14 +101,23 @@ def current_tier(self) -> str:
else:
return None

def current_rollable_tier(self) -> str | None:
for tier in ['easy', 'medium', 'hard', 'elite', 'master']:
def current_rollable_tier(self) -> str | None:
hide_below = self.effective_hide_below
if hide_below not in ROLLABLE_TIERS:
raise ValueError(f"Invalid minimum rollable tier: {hide_below}")

first_tier_index = ROLLABLE_TIERS.index(hide_below)
for tier in ROLLABLE_TIERS[first_tier_index:]:
tasks = self.get_incomplete_tasks(tier)
if len(tasks) != 0:
return tier

return None

@property
def effective_hide_below(self) -> str:
return self.hide_below if not self.is_official else ROLLABLE_TIERS[0]

def get_incomplete_tasks(self, tier: str) -> list[TaskData]:
all_tasks = tasklists.list_for_tier(tier, self.lms_enabled)
completed_task_ids = list(map(lambda x: x.id, self.get_task_list(tier).completed_tasks))
Expand Down Expand Up @@ -252,6 +263,9 @@ def task_info_for_id(task_list: list[TaskData], task_id: str) -> tasklists.TaskD
def convert_database_user(user_data: dict) -> UserDatabaseObject:
tiers = user_data['tiers']
lms_enabled = user_data.get('lmsEnabled', False)
hide_below = user_data.get('hideBelow', 'easy')
if hide_below not in ROLLABLE_TIERS:
raise ValueError(f"Invalid stored minimum rollable tier: {hide_below}")

def to_item_ids(value) -> list[int]:
if not isinstance(value, list):
Expand Down Expand Up @@ -343,6 +357,7 @@ def convert_database_tier(tier: str) -> UserTaskList:
username=user_data['username'],
is_official=user_data['isOfficial'],
lms_enabled=user_data['lmsEnabled'],
hide_below=hide_below,
has_migrated=user_data.get('hasMigrated', False),
discord_linked=user_data.get('discordLinked', False),
discord_name_sync_enabled=user_data.get('discordNameSyncEnabled', False),
Expand Down
Loading