-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathconfig.py
More file actions
232 lines (199 loc) · 10.8 KB
/
config.py
File metadata and controls
232 lines (199 loc) · 10.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
import os
import json
from pathlib import Path
from flask import request, render_template, make_response, flash, redirect, url_for
from flask_login import current_user
from shared import (
limiter, dynamic_rate_limit, PATH, ABOVE_HTML_FILE,
EXTRA_HEADLINES_HTML_ABOVE_FILE, EXTRA_HEADLINES_HTML_BELOW_FILE,
ENABLE_URL_CUSTOMIZATION, SITE_URLS, ALL_URLS, FAVICON,
EXPIRE_YEARS, URLS_COOKIE_VERSION, clear_page_caches, g_c, history, g_logger, MODE
)
from forms import ConfigForm, UrlForm, CustomRSSForm
from caching import _file_cache
from LLMModelManager import LLMModelManager
model_manager = LLMModelManager()
def init_config_routes(app):
@app.route('/config', methods=['GET', 'POST'], strict_slashes=False)
@limiter.limit(dynamic_rate_limit)
def config():
# Use Flask-Login for admin authentication
is_admin = current_user.is_authenticated
if request.method == 'POST' and is_admin:
# Handle LLM model management actions
action = request.form.get('llm_action')
if action:
if action == 'reset_all':
model_manager.clear_failed_models()
flash('All failed models have been reset.', 'success')
elif action == 'unmark_failed':
model = request.form.get('model_name')
if model:
model_manager.unmark_failed(model)
flash(f'Model {model} has been unmarked as failed.', 'success')
elif action == 'mark_failed':
model = request.form.get('model_name')
if model:
model_manager.mark_failed(model, 'Manually marked as failed by admin', '')
flash(f'Model {model} has been marked as failed.', 'success')
return redirect(url_for('config'))
if request.method == 'GET':
form = ConfigForm()
no_underlines_cookie = request.cookies.get('NoUnderlines', "1")
form.no_underlines.data = no_underlines_cookie == "1"
# Load headlines HTML if in admin mode
if is_admin:
try:
above_html_path = Path(PATH) / ABOVE_HTML_FILE
with open(above_html_path, 'r', encoding='utf-8') as f:
form.headlines.data = f.read()
except (FileNotFoundError, IOError) as e:
g_logger.warning(f"Error reading headlines file: {e}")
form.headlines.data = ""
# Load persistent admin extras (not wiped by LLM runs)
try:
extra_above_path = Path(PATH) / EXTRA_HEADLINES_HTML_ABOVE_FILE
with open(extra_above_path, 'r', encoding='utf-8') as f:
form.extra_headlines_html_above.data = f.read()
except (FileNotFoundError, IOError) as e:
g_logger.warning(f"Error reading extra headlines above file: {e}")
form.extra_headlines_html_above.data = ""
try:
extra_below_path = Path(PATH) / EXTRA_HEADLINES_HTML_BELOW_FILE
with open(extra_below_path, 'r', encoding='utf-8') as f:
form.extra_headlines_html_below.data = f.read()
except (FileNotFoundError, IOError) as e:
g_logger.warning(f"Error reading extra headlines below file: {e}")
form.extra_headlines_html_below.data = ""
# Only add URL customization options if enabled
if ENABLE_URL_CUSTOMIZATION:
page_order = request.cookies.get('RssUrls')
if page_order is not None:
page_order = json.loads(page_order)
else:
page_order = SITE_URLS
custom_count = 0
for i, p_url in enumerate(page_order):
rss_info = ALL_URLS.get(p_url, None)
if rss_info is not None and rss_info.logo_url != "Custom.png":
urlf = UrlForm()
urlf.pri = (i + 1) * 10
urlf.url = p_url
urlf.reset = False # Explicitly set reset to False
form.urls.append_entry(urlf)
else:
custom_count += 1
rssf = CustomRSSForm()
rssf.url = p_url
rssf.pri = (i + 1) * 10
form.url_custom.append_entry(rssf)
# Only add empty custom URL entries if customization is enabled
for i in range(custom_count, 5):
rssf = CustomRSSForm()
rssf.url = "http://"
rssf.pri = (i + 30) * 10
form.url_custom.append_entry(rssf)
llm_models = model_manager.get_all_models_status() if is_admin else []
page = render_template('config.html', form=form, is_admin=is_admin,
favicon=FAVICON, enable_url_customization=ENABLE_URL_CUSTOMIZATION,
llm_models=llm_models)
return page
else:
form = ConfigForm()
# Validate form with CSRF protection
if not form.validate():
# Form validation failed, re-render with errors
flash('Please correct the errors below.', 'error')
page = render_template('config.html', form=form, is_admin=is_admin,
favicon=FAVICON, enable_url_customization=ENABLE_URL_CUSTOMIZATION)
return page
if form.delete_cookie.data:
template = render_template('configdone.html', message="Deleted cookies.")
resp = make_response(template)
resp.delete_cookie('RssUrls')
resp.delete_cookie('Theme')
resp.delete_cookie('NoUnderlines')
return resp
# Use Flask-Login authentication - no need for manual password checking
is_admin = current_user.is_authenticated
# Save headlines if in admin mode and headlines were provided
if is_admin and form.headlines.data:
try:
above_html_path = Path(PATH) / ABOVE_HTML_FILE
with open(above_html_path, 'w', encoding='utf-8') as f:
f.write(form.headlines.data)
g_logger.info(f"Saved headlines to {above_html_path}.")
flash('Headlines saved successfully.', 'success')
except (FileNotFoundError, IOError) as e:
g_logger.error(f"Error saving headlines file: {e}")
flash('Error saving headlines. Please try again.', 'error')
# Clear the cache for the above HTML file (in-memory and diskcache)
above_html_full_path = Path(PATH) / ABOVE_HTML_FILE
if above_html_full_path in _file_cache:
del _file_cache[above_html_full_path]
# Clear all page caches since headlines have changed
clear_page_caches()
# Save persistent extras for admin mode
if is_admin:
extras_saved = False
try:
extra_above_path = Path(PATH) / EXTRA_HEADLINES_HTML_ABOVE_FILE
with open(extra_above_path, 'w', encoding='utf-8') as f:
f.write(form.extra_headlines_html_above.data or "")
extras_saved = True
except (FileNotFoundError, IOError) as e:
g_logger.error(f"Error saving extra headlines above file: {e}")
flash('Error saving extra headlines (above). Please try again.', 'error')
try:
extra_below_path = Path(PATH) / EXTRA_HEADLINES_HTML_BELOW_FILE
with open(extra_below_path, 'w', encoding='utf-8') as f:
f.write(form.extra_headlines_html_below.data or "")
extras_saved = True
except (FileNotFoundError, IOError) as e:
g_logger.error(f"Error saving extra headlines below file: {e}")
flash('Error saving extra headlines (below). Please try again.', 'error')
if extras_saved:
# Clear the file-cache entries so the next request renders fresh extras
extra_above_full_path = Path(PATH) / EXTRA_HEADLINES_HTML_ABOVE_FILE
if extra_above_full_path in _file_cache:
del _file_cache[extra_above_full_path]
extra_below_full_path = Path(PATH) / EXTRA_HEADLINES_HTML_BELOW_FILE
if extra_below_full_path in _file_cache:
del _file_cache[extra_below_full_path]
clear_page_caches()
page_order = []
# Only process URL customization if enabled
if ENABLE_URL_CUSTOMIZATION:
urls = list(form.urls)
url_custom = list(form.url_custom)
# Handle feed resets
if is_admin:
for url_form in urls:
if url_form.reset.data:
url_to_reset = url_form.url.data
g_c.clear_last_fetch(url_to_reset)
history.reset_history(url_to_reset)
flash(f"'{url_to_reset}' has been reset and will be refreshed soon.", "success")
for site in url_custom:
if len(site.url.data) > 10 and len(site.url.data) < 120:
urls.append(site)
urls.sort(key=lambda x: x.pri.data)
for urlf in urls:
if isinstance(urlf.form, UrlForm):
page_order.append(urlf.url.data)
elif isinstance(urlf.form, CustomRSSForm):
page_order.append(urlf.url.data)
else:
# Use default site URLs if customization is disabled
page_order = SITE_URLS
template = render_template('configdone.html', message="Cookies saved for later.")
resp = make_response(template)
if page_order != SITE_URLS:
cookie_str = json.dumps(page_order)
resp.set_cookie('RssUrls', cookie_str, max_age=EXPIRE_YEARS)
resp.set_cookie('UrlsVer', URLS_COOKIE_VERSION, max_age=EXPIRE_YEARS)
else:
resp.delete_cookie('RssUrls')
resp.delete_cookie('UrlsVer')
resp.set_cookie("NoUnderlines", "1" if form.no_underlines.data else "0", max_age=EXPIRE_YEARS)
return resp