mirror of
https://github.com/dgtlmoon/changedetection.io.git
synced 2025-12-02 14:22:34 +00:00
Some checks failed
Publish Python 🐍distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Has been cancelled
Publish Python 🐍distribution 📦 to PyPI and TestPyPI / Test the built 📦 package works basically. (push) Has been cancelled
Publish Python 🐍distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Has been cancelled
ChangeDetection.io App Test / lint-code (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-10 (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-11 (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-12 (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-13 (push) Has been cancelled
99 lines
3.5 KiB
Python
99 lines
3.5 KiB
Python
from typing import Dict, Any
|
|
from flask import request
|
|
|
|
|
|
class PreferenceManager:
|
|
"""
|
|
Manages user preferences with cookie persistence.
|
|
|
|
Handles reading from cookies, overriding with URL query parameters,
|
|
and setting cookies when preferences are updated.
|
|
"""
|
|
|
|
def __init__(self, preferences_config: Dict[str, Dict[str, Any]], cookie_scope: str = 'path'):
|
|
"""
|
|
Initialize the preference manager.
|
|
|
|
Args:
|
|
preferences_config: Dict defining preferences with their defaults and types
|
|
e.g., {'diff_type': {'default': 'diffLines', 'type': 'value'}}
|
|
cookie_scope: 'path' for current path only, 'global' for entire application
|
|
"""
|
|
self.config = preferences_config
|
|
self.cookie_scope = cookie_scope
|
|
self.preferences = {}
|
|
self.cookies_updated = False
|
|
|
|
def load_preferences(self) -> Dict[str, Any]:
|
|
"""
|
|
Load preferences from cookies and override with URL query parameters.
|
|
|
|
URL query parameters act as temporary overrides but don't update cookies.
|
|
|
|
Returns:
|
|
Dict containing current preference values
|
|
"""
|
|
for key, config in self.config.items():
|
|
# Read from cookie first (or use default)
|
|
if config['type'] == 'bool':
|
|
if key in request.cookies:
|
|
# Cookie exists, use its value
|
|
self.preferences[key] = request.cookies.get(key) == 'on'
|
|
else:
|
|
# No cookie, use configured default
|
|
self.preferences[key] = config['default']
|
|
else:
|
|
self.preferences[key] = request.cookies.get(key, config['default'])
|
|
|
|
# URL query parameters override (but don't update cookies)
|
|
if key in request.args:
|
|
if config['type'] == 'bool':
|
|
self.preferences[key] = request.args.get(key) == 'on'
|
|
else:
|
|
self.preferences[key] = request.args.get(key, config['default'])
|
|
|
|
return self.preferences
|
|
|
|
def load_from_form(self) -> Dict[str, Any]:
|
|
"""
|
|
Load preferences from POST form data and mark for cookie updates.
|
|
|
|
For checkboxes: absence in form.data means unchecked = False.
|
|
|
|
Returns:
|
|
Dict containing preference values from form
|
|
"""
|
|
self.cookies_updated = True
|
|
|
|
for key, config in self.config.items():
|
|
if config['type'] == 'bool':
|
|
# Checkbox: present = on, absent = off
|
|
self.preferences[key] = key in request.form and request.form.get(key) == 'on'
|
|
else:
|
|
# Value field: get from form or use default
|
|
self.preferences[key] = request.form.get(key, config['default'])
|
|
|
|
return self.preferences
|
|
|
|
def apply_cookies_to_response(self, response, max_age: int = 365 * 24 * 60 * 60):
|
|
"""
|
|
Apply cookies to the response if preferences were updated.
|
|
|
|
Args:
|
|
response: Flask response object
|
|
max_age: Cookie expiration time in seconds (default: 1 year)
|
|
|
|
Returns:
|
|
Modified response object
|
|
"""
|
|
if not self.cookies_updated:
|
|
return response
|
|
|
|
cookie_path = request.path if self.cookie_scope == 'path' else '/'
|
|
|
|
for key, value in self.preferences.items():
|
|
cookie_value = 'on' if value is True else ('off' if value is False else value)
|
|
response.set_cookie(key, cookie_value, max_age=max_age, path=cookie_path)
|
|
|
|
return response
|