Genn9508 commited on
Commit
e94991c
·
verified ·
1 Parent(s): d82cbb3

Delete Index_news.html

Browse files
Files changed (1) hide show
  1. Index_news.html +0 -533
Index_news.html DELETED
@@ -1,533 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="ru">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Новости Челябинской области с суммаризацией</title>
7
- <style>
8
- :root {
9
- --bg: #1e1e1e;
10
- --card-bg: #2d2d2d;
11
- --text: #e0e0e0;
12
- --input-bg: #3c3c3c;
13
- --input-border: #555;
14
- --btn-primary: #3498db;
15
- --btn-hover: #2980b9;
16
- --shadow: 0 4px 12px rgba(0,0,0,0.3);
17
- --radius: 12px;
18
- }
19
-
20
- .light-theme {
21
- --bg: #f5f7fa;
22
- --card-bg: white;
23
- --text: #333;
24
- --input-bg: #fff;
25
- --input-border: #ddd;
26
- --shadow: 0 4px 12px rgba(0,0,0,0.1);
27
- }
28
-
29
- body {
30
- font-family: 'Segoe UI', sans-serif;
31
- background: var(--bg);
32
- color: var(--text);
33
- margin: 0;
34
- padding: 20px;
35
- transition: background 0.3s, color 0.3s;
36
- }
37
-
38
- #background-wrapper {
39
- background-color: #ADD8E6;
40
- padding: 20px;
41
- box-sizing: border-box;
42
- }
43
-
44
- #container {
45
- display: grid;
46
- grid-template-columns: 30% 70%;
47
- gap: 20px;
48
- max-width: 1600px;
49
- margin: 0 auto;
50
- }
51
-
52
- #all-headlines-container {
53
- background-color: var(--card-bg);
54
- border: 1px solid var(--input-border);
55
- border-radius: var(--radius);
56
- padding: 20px;
57
- box-shadow: var(--shadow);
58
- }
59
-
60
- #all-headlines h3 {
61
- margin: 0 0 15px 0;
62
- font-size: 1.3em;
63
- color: var(--btn-primary);
64
- }
65
-
66
- .news-link {
67
- display: flex;
68
- margin-bottom: 10px;
69
- color: #3498db;
70
- text-decoration: none;
71
- font-size: 0.95em;
72
- transition: color 0.2s;
73
- }
74
-
75
- .news-link:hover {
76
- color: #2980b9;
77
- text-decoration: underline;
78
- }
79
-
80
- .news-link::before {
81
- content: "•";
82
- margin-right: 8px;
83
- color: #bbb;
84
- }
85
-
86
- #news-display {
87
- background-color: var(--card-bg);
88
- border: 1px solid var(--input-border);
89
- border-radius: var(--radius);
90
- padding: 25px 30px;
91
- box-shadow: var(--shadow);
92
- overflow: hidden;
93
- }
94
-
95
- #news-display h1 {
96
- font-size: 1.4em;
97
- font-weight: 700;
98
- margin: 0 0 10px 0;
99
- color: var(--text);
100
- }
101
-
102
- #news-display h2 {
103
- font-size: 1.1em;
104
- font-weight: 400;
105
- margin: 0 0 20px 0;
106
- color: #777;
107
- font-style: italic;
108
- }
109
-
110
- .news-title {
111
- font-size: 1.8em;
112
- font-weight: 700;
113
- margin: 0 0 16px 0;
114
- color: var(--text);
115
- line-height: 1.3;
116
- }
117
-
118
- .news-title a {
119
- text-decoration: none;
120
- color: #3498db;
121
- transition: color 0.3s;
122
- }
123
-
124
- .news-title a:hover {
125
- color: #2980b9;
126
- text-decoration: underline;
127
- }
128
-
129
- .pub-date {
130
- font-size: 0.9em;
131
- color: #bbb;
132
- margin: 0 0 10px 0;
133
- font-style: italic;
134
- }
135
-
136
- .description {
137
- font-size: 1.5em;
138
- line-height: 1.6;
139
- max-width: 800px;
140
- margin: 10px 0;
141
- padding: 10px;
142
- color: var(--text);
143
- text-align: left;
144
- background: rgba(52, 152, 219, 0.1);
145
- border-radius: 8px;
146
- }
147
-
148
- .full-text-container, .summary-container {
149
- margin-top: 25px;
150
- clear: both;
151
- }
152
-
153
- .news-image {
154
- float: left;
155
- max-width: 45%;
156
- height: auto;
157
- border-radius: 8px;
158
- box-shadow: 0 2px 8px rgba(0,0,0,0.2);
159
- margin-right: 20px;
160
- margin-bottom: 10px;
161
- }
162
-
163
- .full-text, .summary-text {
164
- font-size: 1.2em;
165
- line-height: 1.65;
166
- color: var(--text);
167
- }
168
-
169
- .summary-box {
170
- margin-top: 20px;
171
- padding: 16px;
172
- background: rgba(46, 204, 113, 0.15);
173
- border: 1px solid #2ecc7144;
174
- border-radius: 8px;
175
- font-size: 1.1em;
176
- line-height: 1.6;
177
- }
178
-
179
- .summary-label {
180
- font-weight: 700;
181
- color: #2ecc71;
182
- margin-bottom: 8px;
183
- display: block;
184
- }
185
-
186
- #progress {
187
- display: none;
188
- margin: 10px 0;
189
- padding: 10px;
190
- background: #e3f2fd;
191
- border: 1px solid #bbdefb;
192
- border-radius: 6px;
193
- font-size: 0.9em;
194
- color: #1976d2;
195
- text-align: center;
196
- font-style: italic;
197
- }
198
-
199
- .theme-toggle-btn {
200
- position: absolute;
201
- top: 20px;
202
- right: 20px;
203
- background: none;
204
- border: none;
205
- font-size: 20px;
206
- cursor: pointer;
207
- color: #3498db;
208
- }
209
-
210
- @media (max-width: 768px) {
211
- #container { grid-template-columns: 1fr; }
212
- .news-image { float: none; max-width: 100%; margin: 0 0 15px 0; }
213
- .full-text-container, .summary-container { display: block; }
214
- }
215
- </style>
216
- </head>
217
- <body class="dark-theme">
218
- <button class="theme-toggle-btn" onclick="toggleTheme()" title="Сменить тему">🌙</button>
219
-
220
- <div id="background-wrapper">
221
- <div id="container">
222
- <div id="all-headlines-container">
223
- <div id="all-headlines">
224
- <h3>Сегодня и вчера</h3>
225
- </div>
226
- </div>
227
-
228
- <div id="news-display">
229
- <h1>Новости Челябинской области</h1>
230
- <h2>Актуальные события региона</h2>
231
- Загрузка новостей...
232
- </div>
233
- </div>
234
-
235
- <div id="progress">Фильтруем новости за сегодня и вчера...</div>
236
- </div>
237
-
238
- <script>
239
- const PROXY_SERVER = 'http://localhost:3000';
240
- const RSS_FEED_URL = 'https://vecherka.su/rss/';
241
- const SUMMARIZE_API = 'https://Genn9508-IlyaGusev-rut5-base-sum-gazeta.hf.space/summarize';
242
-
243
- let newsItems = [];
244
- let currentIndex = 0;
245
- let isBusy = false; // Защита от повторного вызова
246
-
247
- // Переключение темы (один раз!)
248
- function toggleTheme() {
249
- const body = document.body;
250
- const btn = document.querySelector('.theme-toggle-btn');
251
- if (body.classList.contains('dark-theme')) {
252
- body.classList.remove('dark-theme');
253
- body.classList.add('light-theme');
254
- btn.textContent = '☀️';
255
- } else {
256
- body.classList.remove('light-theme');
257
- body.classList.add('dark-theme');
258
- btn.textContent = '🌙';
259
- }
260
- }
261
-
262
- function isTodayOrYesterday(pubDateStr) {
263
- const pubDate = new Date(pubDateStr);
264
- if (isNaN(pubDate.getTime())) return false;
265
- const now = new Date();
266
- const startOfToday = new Date(now.getFullYear(), now.getMonth(), now.getDate());
267
- const startOfYesterday = new Date(startOfToday);
268
- startOfYesterday.setDate(startOfToday.getDate() - 1);
269
- return (
270
- (pubDate >= startOfYesterday && pubDate < startOfToday) ||
271
- (pubDate >= startOfToday && pubDate < new Date(startOfToday.getTime() + 86400000))
272
- );
273
- }
274
-
275
- function containsReklama(text) {
276
- return /реклама/i.test(text || '');
277
- }
278
-
279
- async function fetchFullNews(link) {
280
- try {
281
- const site = link.includes('vecherka.su') ? 'vecherka.su' : 'default';
282
- const proxyUrl = `${PROXY_SERVER}/proxy-page?url=${encodeURIComponent(link)}&site=${site}`;
283
- const response = await fetch(proxyUrl);
284
- if (!response.ok) throw new Error(`HTTP ${response.status}`);
285
- return await response.json();
286
- } catch (error) {
287
- console.error('Ошибка загрузки полного текста:', error);
288
- return { html: '<p>Не удалось загрузить текст новости.</p>', title: 'Ошибка' };
289
- }
290
- }
291
-
292
- // Кэширование суммаризаций
293
- function getCachedSummary(urlKey) {
294
- const cache = localStorage.getItem('summaryCache');
295
- if (!cache) return null;
296
- const summaries = JSON.parse(cache);
297
- return summaries[urlKey] || null;
298
- }
299
-
300
- function setCachedSummary(urlKey, summary) {
301
- const cache = localStorage.getItem('summaryCache');
302
- const summaries = cache ? JSON.parse(cache) : {};
303
- summaries[urlKey] = summary;
304
- localStorage.setItem('summaryCache', JSON.stringify(summaries));
305
- }
306
-
307
- async function summarizeText(text, urlKey) {
308
- const cached = getCachedSummary(urlKey);
309
- if (cached) return cached;
310
-
311
- try {
312
- const response = await fetch(SUMMARIZE_API, {
313
- method: 'POST',
314
- headers: { 'Content-Type': 'application/json' },
315
- body: JSON.stringify({ text: text })
316
- });
317
-
318
- if (!response.ok) throw new Error('API error');
319
- const data = await response.json();
320
- const summary = data.summary || 'Не удалось сгенерировать краткое содержание.';
321
- setCachedSummary(urlKey, summary);
322
- return summary;
323
- } catch (error) {
324
- console.error('Ошибка суммаризации:', error);
325
- return 'Краткое содержание недоступно. Повторите позже.';
326
- }
327
- }
328
-
329
- async function parseRSS(str) {
330
- try {
331
- const parser = new DOMParser();
332
- const xmlDoc = parser.parseFromString(str, 'application/xml');
333
- const parserError = xmlDoc.querySelector('parsererror');
334
- if (parserError) throw new Error('XML error: ' + parserError.textContent);
335
-
336
- const items = xmlDoc.querySelectorAll('item');
337
- newsItems = [];
338
-
339
- for (const item of items) {
340
- const title = item.querySelector('title')?.textContent?.trim() || 'Нет заголовка';
341
- const link = item.querySelector('link')?.textContent?.trim() || '#';
342
- const pubDateStr = item.querySelector('pubDate')?.textContent?.trim() || '';
343
- const description = item.querySelector('description')?.textContent || '';
344
- const enclosure = item.querySelector('enclosure');
345
- const imageUrl = enclosure ? enclosure.getAttribute('url')?.trim() : '';
346
-
347
- if (!pubDateStr || !isTodayOrYesterday(pubDateStr)) continue;
348
- if (containsReklama(title) || containsReklama(description)) continue;
349
-
350
- newsItems.push({ title, link, pubDateStr, description, imageUrl });
351
- }
352
-
353
- updateHeadlinesList();
354
- document.getElementById('progress').textContent = `Загружено ${newsItems.length} новостей`;
355
- setTimeout(() => { document.getElementById('progress').style.display = 'none'; }, 2000);
356
-
357
- if (newsItems.length === 0) {
358
- document.getElementById('news-display').innerHTML = `
359
- <h1>Новости Челябинской области</h1>
360
- <h2>Актуальные события региона</h2>
361
- <p>Нет новостей за сегодня и вчера.</p>
362
- `;
363
- setTimeout(showNextNews, 15000);
364
- } else {
365
- showNextNews();
366
- }
367
- } catch (error) {
368
- console.error('Ошибка RSS:', error);
369
- document.getElementById('news-display').innerHTML = `<p style="color:red;">Ошибка: ${error.message}</p>`;
370
- document.getElementById('progress').style.display = 'none';
371
- }
372
- }
373
-
374
- function updateHeadlinesList() {
375
- const list = document.getElementById('all-headlines');
376
- list.innerHTML = '<h3>Сегодня и вчера</h3>';
377
- newsItems.forEach((item, i) => {
378
- const a = document.createElement('a');
379
- a.href = '#';
380
- a.className = 'news-link';
381
- a.textContent = item.title;
382
- a.onclick = (e) => {
383
- e.preventDefault();
384
- currentIndex = i;
385
- showNextNews();
386
- };
387
- list.appendChild(a);
388
- });
389
- }
390
-
391
- async function showNextNews() {
392
- if (isBusy) return; // Защита от повторного вызова
393
- isBusy = true;
394
-
395
- const container = document.getElementById('news-display');
396
- container.innerHTML = `
397
- <h1>Новости Челябинской области</h1>
398
- <h2>Актуальные события региона</h2>
399
- `;
400
-
401
- if (newsItems.length === 0) {
402
- container.innerHTML += '<p>Нет новостей за сегодня и вчера.</p>';
403
- setTimeout(() => {
404
- isBusy = false;
405
- showNextNews();
406
- }, 15000);
407
- return;
408
- }
409
-
410
- const item = newsItems[currentIndex];
411
- const fullData = await fetchFullNews(item.link);
412
-
413
- const newsDiv = document.createElement('div');
414
- newsDiv.className = 'news-item';
415
-
416
- const titleEl = document.createElement('div');
417
- titleEl.className = 'news-title';
418
- const linkEl = document.createElement('a');
419
- linkEl.href = item.link;
420
- linkEl.target = '_blank';
421
- linkEl.textContent = item.title;
422
- titleEl.appendChild(linkEl);
423
- newsDiv.appendChild(titleEl);
424
-
425
- const dateEl = document.createElement('div');
426
- dateEl.className = 'pub-date';
427
- dateEl.textContent = new Date(item.pubDateStr).toLocaleDateString('ru-RU', {
428
- day: 'numeric', month: 'long', year: 'numeric'
429
- });
430
- newsDiv.appendChild(dateEl);
431
-
432
- if (item.description) {
433
- const descEl = document.createElement('div');
434
- descEl.className = 'description';
435
- descEl.innerHTML = item.description;
436
- newsDiv.appendChild(descEl);
437
- }
438
-
439
- const fullTextWrapper = document.createElement('div');
440
- fullTextWrapper.className = 'full-text-container';
441
-
442
- if (item.imageUrl) {
443
- const img = document.createElement('img');
444
- img.src = item.imageUrl;
445
- img.alt = 'Изображение новости';
446
- img.className = 'news-image';
447
- fullTextWrapper.appendChild(img);
448
- }
449
-
450
- const fullText = document.createElement('div');
451
- fullText.className = 'full-text';
452
- fullText.innerHTML = fullData.html || '<p>Текст недоступен.</p>';
453
- fullTextWrapper.appendChild(fullText);
454
- newsDiv.appendChild(fullTextWrapper);
455
-
456
- // 🔥 Суммаризация
457
- const summaryBox = document.createElement('div');
458
- summaryBox.className = 'summary-container';
459
-
460
- const summaryLabel = document.createElement('div');
461
- summaryLabel.className = 'summary-label';
462
- summaryLabel.textContent = 'Кратко:';
463
- summaryBox.appendChild(summaryLabel);
464
-
465
- const summaryText = document.createElement('div');
466
- summaryText.className = 'summary-text';
467
- summaryText.innerHTML = '⏳ Обработка...';
468
- summaryBox.appendChild(summaryText);
469
-
470
- container.appendChild(newsDiv);
471
- container.appendChild(summaryBox);
472
-
473
- // Ключ кэша — на основе URL
474
- const urlKey = btoa(item.link);
475
- const textToSummarize = (item.description + ' ' + (fullData.html || '')).replace(/<[^>]+>/g, '').trim();
476
-
477
- // Таймаут на случай зависания API
478
- const timeout = new Promise((_, reject) => {
479
- setTimeout(() => reject(new Error('Таймаут суммаризации')), 10000);
480
- });
481
-
482
- try {
483
- const summary = await Promise.race([
484
- summarizeText(textToSummarize, urlKey),
485
- timeout
486
- ]);
487
- summaryText.innerHTML = summary;
488
- } catch (error) {
489
- summaryText.innerHTML = '⚠️ Суммаризация недоступна (таймаут или ошибка).';
490
- console.warn('Суммаризация прервана:', error.message);
491
- }
492
-
493
- // Всегда переходим к следующей новости через 15 сек
494
- currentIndex = (currentIndex + 1) % newsItems.length;
495
- setTimeout(() => {
496
- isBusy = false;
497
- showNextNews();
498
- }, 15000);
499
- }
500
-
501
- async function loadRSS() {
502
- try {
503
- const response = await fetch(`${PROXY_SERVER}/proxy-rss?url=${encodeURIComponent(RSS_FEED_URL)}`, {
504
- method: 'GET',
505
- headers: { 'Accept': 'application/xml, text/xml' },
506
- mode: 'cors',
507
- credentials: 'omit'
508
- });
509
-
510
- if (!response.ok) throw new Error(`HTTP ${response.status}`);
511
- const str = await response.text();
512
- parseRSS(str);
513
- } catch (error) {
514
- console.error('Ошибка загрузки RSS:', error);
515
- document.getElementById('news-display').innerHTML = `
516
- <p style="color:red;">
517
- Не удалось загрузить новости.<br>
518
- Проверь:<br>
519
- 1. Работает ли прокси на ${PROXY_SERVER}<br>
520
- 2. Доступен ли RSS: ${RSS_FEED_URL}
521
- </p>
522
- `;
523
- document.getElementById('progress').style.display = 'none';
524
- }
525
- }
526
-
527
- document.addEventListener('DOMContentLoaded', () => {
528
- loadRSS();
529
- });
530
- </script>
531
-
532
- </body>
533
- </html>