Compare commits
2 Commits
v2.5.71
...
0e5eb84097
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0e5eb84097 | ||
|
|
6ef82a1d12 |
@@ -39,8 +39,9 @@ func (m *mockStore) ReadChapter(_ context.Context, _ string, _ int) (string, err
|
|||||||
func (m *mockStore) ListChapters(_ context.Context, _ string) ([]domain.ChapterInfo, error) {
|
func (m *mockStore) ListChapters(_ context.Context, _ string) ([]domain.ChapterInfo, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
func (m *mockStore) CountChapters(_ context.Context, _ string) int { return 0 }
|
func (m *mockStore) CountChapters(_ context.Context, _ string) int { return 0 }
|
||||||
func (m *mockStore) ReindexChapters(_ context.Context, _ string) (int, error) { return 0, nil }
|
func (m *mockStore) ReindexChapters(_ context.Context, _ string) (int, error) { return 0, nil }
|
||||||
|
func (m *mockStore) DeduplicateChapters(_ context.Context, _ string) (int, error) { return 0, nil }
|
||||||
|
|
||||||
// RankingStore
|
// RankingStore
|
||||||
func (m *mockStore) WriteRankingItem(_ context.Context, _ domain.RankingItem) error { return nil }
|
func (m *mockStore) WriteRankingItem(_ context.Context, _ domain.RankingItem) error { return nil }
|
||||||
@@ -52,10 +53,10 @@ func (m *mockStore) RankingFreshEnough(_ context.Context, _ time.Duration) (bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AudioStore
|
// AudioStore
|
||||||
func (m *mockStore) AudioObjectKey(_ string, _ int, _ string) string { return "" }
|
func (m *mockStore) AudioObjectKey(_ string, _ int, _ string) string { return "" }
|
||||||
func (m *mockStore) AudioObjectKeyExt(_ string, _ int, _, _ string) string { return "" }
|
func (m *mockStore) AudioObjectKeyExt(_ string, _ int, _, _ string) string { return "" }
|
||||||
func (m *mockStore) AudioExists(_ context.Context, _ string) bool { return false }
|
func (m *mockStore) AudioExists(_ context.Context, _ string) bool { return false }
|
||||||
func (m *mockStore) PutAudio(_ context.Context, _ string, _ []byte) error { return nil }
|
func (m *mockStore) PutAudio(_ context.Context, _ string, _ []byte) error { return nil }
|
||||||
func (m *mockStore) PutAudioStream(_ context.Context, _ string, _ io.Reader, _ int64, _ string) error {
|
func (m *mockStore) PutAudioStream(_ context.Context, _ string, _ io.Reader, _ int64, _ string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,6 +89,8 @@ func (s *stubStore) WriteChapterRefs(_ context.Context, _ string, _ []domain.Cha
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *stubStore) DeduplicateChapters(_ context.Context, _ string) (int, error) { return 0, nil }
|
||||||
|
|
||||||
func (s *stubStore) ChapterExists(_ context.Context, slug string, ref domain.ChapterRef) bool {
|
func (s *stubStore) ChapterExists(_ context.Context, slug string, ref domain.ChapterRef) bool {
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
defer s.mu.Unlock()
|
defer s.mu.Unlock()
|
||||||
|
|||||||
@@ -94,6 +94,10 @@ func (s *stubBookWriter) ChapterExists(_ context.Context, _ string, _ domain.Cha
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *stubBookWriter) DeduplicateChapters(_ context.Context, _ string) (int, error) {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
// stubBookReader satisfies bookstore.BookReader — returns a single chapter.
|
// stubBookReader satisfies bookstore.BookReader — returns a single chapter.
|
||||||
type stubBookReader struct {
|
type stubBookReader struct {
|
||||||
text string
|
text string
|
||||||
|
|||||||
33
ui/src/routes/api/admin/dedup-chapters/[slug]/+server.ts
Normal file
33
ui/src/routes/api/admin/dedup-chapters/[slug]/+server.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* POST /api/admin/dedup-chapters/[slug]
|
||||||
|
*
|
||||||
|
* Admin-only proxy to the Go backend's dedup endpoint.
|
||||||
|
* Removes duplicate chapters_idx records for a book, keeping the latest
|
||||||
|
* record per chapter number. Returns { slug, deleted }.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { json, error } from '@sveltejs/kit';
|
||||||
|
import type { RequestHandler } from './$types';
|
||||||
|
import { log } from '$lib/server/logger';
|
||||||
|
import { backendFetch } from '$lib/server/scraper';
|
||||||
|
|
||||||
|
export const POST: RequestHandler = async ({ params, locals }) => {
|
||||||
|
if (!locals.user || locals.user.role !== 'admin') {
|
||||||
|
throw error(403, 'Forbidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
const { slug } = params;
|
||||||
|
|
||||||
|
let res: Response;
|
||||||
|
try {
|
||||||
|
res = await backendFetch(`/api/admin/dedup-chapters/${encodeURIComponent(slug)}`, {
|
||||||
|
method: 'POST'
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
log.error('admin/dedup-chapters', 'backend proxy error', { slug, err: String(e) });
|
||||||
|
throw error(502, 'Could not reach backend');
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await res.json().catch(() => ({}));
|
||||||
|
return json(data, { status: res.status });
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user