Commit Graph

49 Commits

Author SHA1 Message Date
truewhile 496a897782 优化 2026-08-27 21:24:01 +08:00
truewhile b676733af7 优化strm同步
优化strm同步
2026-08-26 00:26:28 +08:00
truewhile 43fdfe8202 处理无法播放的问题
处理无法播放的问题
2026-08-24 21:06:44 +08:00
truewhile 44ca451cd4 优化
优化
2026-08-24 17:40:43 +08:00
truewhile c55d29ae84 添加strm生成
添加strm
2026-08-24 14:36:17 +08:00
truewhile 71bf60c69c 初始化
初始化项目
2026-08-23 22:12:32 +08:00
truewhile 65d1ad5ae5 优化番号处理逻辑,添加对MetaTube的支持
优化番号处理逻辑,添加对MetaTube的支持
2026-08-21 00:06:49 +08:00
ShukeBta 42ef19b7e5 fix(downloads): support Transmission and aria2 end to end
Fixes #65
2026-08-10 21:04:04 +08:00
ShukeBta c0d743d89d fix(subscriptions): reject concurrent duplicate rules
Fixes #66
2026-08-10 19:30:17 +08:00
ShukeBta 06b25564ea Add library covers and configurable footer visibility 2026-07-16 13:17:52 +08:00
ShukeBta b610dda098 fix: align scraped media naming and release sorting 2026-07-03 02:55:33 +08:00
ShukeBta 941bb273b9 fix media organize and subscription workflows 2026-06-30 20:18:02 +08:00
ShukeBta 47069fb751 split core model definitions 2026-06-27 08:21:46 +08:00
ShukeBta 5ef831f830 support multiple roots per library 2026-06-26 22:18:26 +08:00
ShukeBta bd35e5adf7 refactor emby api model types by topic 2026-06-26 20:13:59 +08:00
ShukeBta 192f35d9fa refactor: split modules and harden scraping workflows 2026-06-24 11:59:18 +08:00
ShukeBta 7b881d031c fix organizer diagnostics and site integrations 2026-06-21 09:44:29 +08:00
ShukeBta 6e61c8b545 feat(telegram): 订阅/下载补齐 year/rating/genres/原名/语言 富通知字段
- 模型: Subscription/DownloadTask 新增 OriginalName/OriginalLanguage/Year/
  Rating/Genres 列(GORM AutoMigrate 自动建列, 无需手写迁移)
- enrich 链路: displayMetadata 与 DownloadTaskMeta 携带新字段, 从
  SearchExternalMedia(TMDb/豆瓣/Bangumi)结果回填并持久化; 放宽提前返回
  门槛, 已有海报但缺新字段时仍补齐
- 通知: 订阅/下载完成事件 data 注入 year/rating/genres/original_title/
  original_language, 喂给作者富模板 formatTelegramMediaNotification
- 测试: 新增端到端断言, 验证补齐字段透传进 Telegram caption
2026-06-20 01:45:40 +08:00
ShukeBta 0a3748e564 Fix subscription restore and media library entry links 2026-06-18 10:54:10 +08:00
ShukeBta 850d3db811 Fix scraping workflows subscriptions bot and recycle bin 2026-06-17 19:48:17 +08:00
ShukeBta ab4637beed Update MediaStationGo branding and deployment docs 2026-06-17 16:01:16 +08:00
ShukeBta 3368ac2947 Fix bot binding and terminal device limits 2026-06-17 01:06:20 +08:00
ShukeBta a9b85c0f3f Allow virtual media reference ids 2026-06-16 02:20:27 +08:00
ShukeBta 61949c1e1c Fix SQLite to PostgreSQL media migration 2026-06-15 22:11:58 +08:00
ShukeBta fea1b1dda1 Fix PostgreSQL migration resume and home crash guard 2026-06-15 20:13:30 +08:00
ShukeBta 479a06f008 Unify organize ingest pipeline 2026-06-14 23:17:52 +08:00
ShukeBta a623702276 Deduplicate organize by multi-source metadata 2026-06-14 01:25:44 +08:00
ShukeBta 4e0929bbca fix organize path mapping and task flow 2026-06-13 16:32:38 +08:00
ShukeBta 0f82cb3084 feat: improve OpenList cloud storage support 2026-06-10 00:08:35 +08:00
ShukeBta d94330b30f fix(subscription): prevent duplicate qb downloads 2026-06-07 10:05:58 +08:00
shuk shuk 22b64d3d47 fix(organize): strip release tags/roman numerals/season markers; de-hardcode paths
feat(bot): button menu, capacity/open-reg quota, redemption codes, user mgmt,
account expiry + signin streak, device anti-sharing + inactivity cleanup,
one-click kick, self-service username/password

- Consolidate organize/rename defaults into Tools panel

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-06-07 09:54:14 +08:00
soldosluka857 b9b7b7052a feat(organize/scan): transfer modes, seeding-safe relocation, inode dedup, incremental scanning
- Organizer: add move/copy/hardlink/symlink transfer modes (default move),
  per-request target_path/transfer_mode overrides, and honor organize.target_dir
  / organize.transfer_mode settings.
- keep_seeding (default on): escalate move->hardlink (cross-device->copy) so the
  qBittorrent source stays in place and continues seeding after organize.
- qBittorrent SetLocation + POST /downloads/relocate to migrate whole torrents
  while keeping them seeding.
- Scanner: FileID (device:inode) hardlink dedup to avoid duplicate recognition
  and double-counted storage; extract single-file ingest.
- Watcher: recursive watch + incremental per-file ingest/remove instead of full
  re-scan; periodic full library scan now gated behind scan.periodic_enabled
  (default off) to reduce disk wear.
- Telegram bot: handle callback_query in polling, declare allowed_updates in
  webhook, answer callbacks.
- Frontend: settings for transfer mode / keep_seeding / periodic scan; organize
  panel target dir + transfer mode overrides.
- Tests for transfer modes, organizer resolution, SetLocation, inode dedup,
  incremental ingest/remove.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-30 12:01:46 +08:00
ShukeBta 99ecae0c44 fix: add global adult library visibility controls 2026-05-30 03:24:08 +08:00
ShukeBta b5e11b6938 fix: secure adult visibility and telegram bot access 2026-05-30 01:39:11 +08:00
ShukeBta 27df93fa3d feat: add licensing and access controls 2026-05-29 12:47:54 +08:00
ShukeBta c1b5dac784 feat: improve subscription and download cards 2026-05-28 23:27:34 +08:00
ShukeBta 05d49ca470 Add advanced discovery subscriptions 2026-05-28 22:21:48 +08:00
ShukeBta 32ccb33fed Fix local adult metadata and watch history removal 2026-05-28 14:52:20 +08:00
ShukeBta a98429c02a feat: 实现智能分类功能
- 配置模型扩展(OrganizerConfig:smart_classify + categories)
- 数据模型扩展(Media:languages/countries/genres 字段)
- TMDbProvider 增强(GetDetails 方法获取扩展元数据)
- Scraper 服务增强(保存 languages/countries/genres 到数据库)
- Organizer 智能分类逻辑(根据元数据自动分类到子目录)
- 前端 SettingsPage 添加智能分类开关
- 后端支持从数据库读取 organizer.smart_classify 设置

Task #90-94 完成,Task #95 部分完成
2026-05-18 02:49:28 +08:00
ShukeBta a8e825ec13 fix: 增强站点连接测试HTTP请求头,添加浏览器仿真与FlareSolverr支持
- 新增 internal/helper/http.go:带浏览器仿真请求头和Cloudflare/WAF绕过支持
- TestSiteConnectivity 支持 FlareSolverr 代理(需配置 flareSolverrUrl)
- 检测 Cloudflare challenge 页面并返回友好错误信息
- 重构 service/site.go TestConnection 使用新的 helper 方法
2026-05-18 01:41:00 +08:00
ShukeBta 9827b46c49 feat(site): 补全 Site 模型 11 个缺失字段并同步前端类型
- model/site.go: 新增 user_agent/rss_url/timeout/priority/use_proxy/rate_limit/
  browser_emulation/login_status/upload_bytes/download_bytes/downloader 11个字段
- 字段对齐 Python 原版 MediaStation Site 模型(28字段 → 23字段)
- GORM AutoMigrate 自动补列,旧数据填充默认值(timeout=15, priority=50)
- types/index.ts: Site 接口同步所有新字段(带注释)
- 后端编译 ✅  前端构建 ✅  API 验证 ✅
2026-05-18 00:52:11 +08:00
ShukeBta 8e06b7e149 chore: remove license code, fix compilation, update README bilingual
- Remove all license-related code (handler/service/repository/model)
  License authorization is managed by separate server:
  https://github.com/ShukeBta/MediaStationLicenseServer
- Fix compilation errors: model field alignment, method name fixes,
  route conflicts, struct literal corrections (7 files)
- Add Chinese README.md as primary, English README_EN.md
- Update .gitignore: exclude .workbuddy/, editor backups
- Add new repository files: assistant, play_profile, storage_config
2026-05-17 00:02:41 +08:00
ShukeBta 37dd83c56d Resolve merge conflicts: merge all Go backend and React frontend changes 2026-05-16 22:48:30 +08:00
ShukeBta cbb4b806be feat: merge conflict resolution, site management, UI fixes 2026-05-16 17:57:34 +08:00
Kiro Agent 1dbd73b30b feat: complete Vue UI parity (full backend + frontend)
== New domain models (7) ==
- UserPermission: per-user feature toggles (13 booleans)
- StorageConfig: encrypted Alist/S3/WebDAV adapters
- LicenseKey + LicenseActivation: offline license issuance
- DownloadClient: multi-client downloader configs
- AssistantSession + AssistantMessage: multi-turn AI chat persistence

== New services (5) ==
- PermissionService: admin grants always-true; user defaults seeded
- StorageConfigService: AES-GCM encryption + per-type connection probe
- LicenseService: 24-char hyphenated key generation, activation/heartbeat
- DownloadClientService: qB/Aria2/Transmission CRUD + WebUI test
- AssistantService: chat history + execute/undo stubs (op_id tracking)

== Extended AIService.Chat ==
- Multi-turn LLM call with chat history; offline fallback reply

== New endpoints (60+) ==
Auth:
  POST /auth/refresh, /auth/logout, /auth/change-password
  PATCH /auth/profile
  GET /auth/permissions, /auth/me

Permissions admin:
  GET/PUT /admin/users/:id/permissions
  POST /admin/users/:id/permissions/reset

Search:
  GET /search, /search/advanced, /search/tmdb, /search/sites

System:
  GET /system/config, /settings/schema, /system/events/ticket
  POST /admin/system/scheduler/:name/trigger

Stats:
  GET /stats/user/:id, /stats/top-users
  POST /stats/play

Sites:
  GET /sites/:id/resource, /sites/:id/userdata

Subscriptions:
  PUT /subscriptions/:id, POST /subscriptions/:id/search

Playlists:
  POST /playlists/:id/reorder
  DELETE /playlists/:id/items/by-id/:item_id

DLNA per-renderer:
  POST /dlna/:uuid/{play,pause,stop}, GET /dlna/:uuid/status

Media:
  POST/DELETE /media/:id/favorite, GET /media/:id/favorite/status
  POST /media/:id/ai-scrape, /media/scrape/test, /media/organize
  GET /favorites (alias)

Playback:
  GET /playback/:id/info, /playback/:id/external-players, /playback/:id/external-url
  POST /playback/:id/progress
  GET /playback/transcode/:job_id/status

Downloads:
  POST /download/:id/{pause,resume,organize}
  POST /download/{organize,sync,start-auto-sync}
  GET /download/tasks
  Admin: full CRUD on /admin/download/clients + /admin/download/aria2/stats

License:
  POST /license/{activate,heartbeat}
  GET /license/{status,heartbeat-status}
  Admin: /admin/license/{generate,list,:id/activations,:id/revoke,activation/:id/unbind}

Storage:
  GET /admin/storage/{status,:type}
  PUT /admin/storage/:type, POST /admin/storage/:type/test

Assistant (multi-turn AI):
  GET/POST /admin/assistant/sessions
  GET/DELETE /admin/assistant/session/:id
  POST /admin/assistant/{chat,execute}
  POST /admin/assistant/undo/:op_id
  GET /admin/assistant/history

== New React pages (4) ==
- AssistantChatPage (/assistant): full multi-turn chat UI with sessions
  sidebar, optimistic user-turn append, live AI response.
- DownloadClientsPage (/download-clients): typed CRUD form for
  qBittorrent / Aria2 / Transmission + per-row Test action.
- LicensePage (/license): generate keys, list activations, revoke,
  unbind individual devices.
- StorageConfigPage (/storage-config): tabbed Alist/WebDAV/S3 form
  with secret-aware redaction + connection probe.

== New API helpers (5) ==
- assistant, download_clients, license, permissions, storage_config

== Layout ==
- Sidebar gains 4 new admin links (AI 对话, 下载器, 外部存储, 许可证).
2026-05-16 09:49:35 +00:00
Kiro Agent 7095d9ebec feat: port remaining Vue UI surfaces with full backend support
Backend additions:
- New GORM models: NotifyChannel, PlayProfile (with PIN hashing).
- NotifyChannelService: multi-channel CRUD + unified dispatcher
  supporting Telegram / Bark / WeChat / Webhook with optional
  per-channel event filtering.
- PlayProfileService: per-user 'viewing personas' with
  content-rating gates, library scoping, PIN protection, and
  player defaults (autoplay, skip-intro, audio/subtitle prefs).
- New endpoints:
    GET    /admin/notify/channels           list
    POST   /admin/notify/channels           create
    PUT    /admin/notify/channels/:id       update
    DELETE /admin/notify/channels/:id       delete
    POST   /admin/notify/channels/:id/test  send test
    GET    /play-profiles                   list (admin: ?all=true)
    POST   /play-profiles                   create
    PUT    /play-profiles/:id               update
    DELETE /play-profiles/:id               delete
    GET    /media/recent                    home page rail
    GET    /media/stats                     library composition
    GET    /watch-history                   list
    GET    /watch-history/stats             aggregate
    GET    /watch-history/continue          continue-watching rail
    DELETE /watch-history[?media_id=]       clear
    DELETE /watch-history/:id               remove one
    GET    /discover/sections               available rails
    GET    /discover/feed?sections=a,b      multi-section TMDb fetch
    GET    /system/info                     name/version/runtime
    GET    /system/status                   uptime/cpu/mem/disk
    GET    /system/scheduler                read-only scheduler view
    GET    /stats/overview                  counts only
    GET    /stats/trend                     daily plays
    GET    /stats/top-content               most played
    GET    /stats/libraries                 per-library size
    GET    /stats/monitor                   live hardware

Frontend additions:
- New API helpers: notify_channels, play_profiles, history,
  stats_extra, media_extra, discover_extra, system.
- ProfileManagementPage (/play-profiles): full CRUD form with
  PIN management, library scoping, language preferences.
- NotifyChannelsPage (/notify-channels, admin): typed config
  forms per channel type + per-channel test action.
- SettingsPage (/settings, admin): grouped key/value editor
  covering General, Organize/Scrape, Adult, qBittorrent.
- Layout sidebar links and App.tsx routes wired for all three.
2026-05-16 09:01:09 +00:00
Kiro 7a18eb670a feat: site management + cross-site torrent search
Port the complete site management system from the original MediaStation:

Model:
  - model/model.go: Added Site table with fields for name, base_url,
    site_type (nexusphp/gazelle/unit3d/mteam/custom_rss), auth_type
    (cookie/api_key/authorization), cookie, api_key, auth_header,
    user_agent, rss_url, timeout, priority, use_proxy, enabled,
    login_status, downloader. Registered in AllModels().

Backend services:
  - service/site.go: SiteService with CRUD (Create/List/FindByID/Update/
    Delete), TestConnection (validates credentials via HTTP, updates
    login_status in DB), and Search (cross-site fan-out that queries
    every enabled site adapter and returns merged results sorted by
    seeders descending).
  - service/site_adapter.go: SiteAdapter interface + NewSiteAdapter
    factory + 5 implementations:
    * nexusPhpAdapter — regex HTML scraping of torrents.php
    * gazelleAdapter — JSON API /ajax.php?action=browse
    * unit3dAdapter — REST API /api/torrents/filter
    * mteamAdapter — M-Team v3 POST /api/torrent/search with x-api-key
    * rssAdapter — XML RSS/Atom feed parsing with keyword filter

Handler + routes:
  - handler/sites.go: listSites, getSite, createSite, updateSite,
    deleteSite, testSite, siteSearch handlers.
  - handler/handler.go: 7 new routes under authed group:
    GET/POST /sites, GET/PUT/DELETE /sites/:id,
    POST /sites/:id/test, GET /sites/search.

Frontend:
  - api/sites.ts: typed interfaces (Site, SiteSearchResult,
    CreateSiteInput) and sitesAPI helper.
  - pages/SitesPage.tsx: full CRUD UI with add-site form (site_type +
    auth_type selectors, cookie/api_key/rss inputs), connection test
    button with live status indicator, delete action.
  - pages/SiteSearchPage.tsx: cross-site search with keyword input,
    merged result table (site/title/size/seeders/leechers/free),
    one-click download-to-qBittorrent button.
  - App.tsx: lazy-loaded routes /sites and /site-search.
  - Layout.tsx: sidebar links 站点管理 + 站点搜索 under 自动化 group.

Verified: go build + go vet + go test pass; tsc -b + vite build passes
(32 lazy chunks, main bundle 255 KB / 85 KB gzipped).
2026-05-16 08:29:00 +00:00
Kiro 4b747c74ca feat: port missing MediaStation features (DLNA, STRM, files, dup, sched, api-configs, emby, storage)
Audit-driven port from the original Python MediaStation. Eight major
subsystems that were absent from the Go rewrite are now in place,
each with its own service, handler, frontend page and smoke-test
assertions.

Backend services
  - service/crypto.go: AES-256-GCM encrypt/decrypt for at-rest secrets
    keyed off the JWT secret. Legacy plaintext rows pass through
    unchanged for smooth upgrades. Unit-tested.
  - service/api_config.go: third-party provider config (TMDb, Bangumi,
    TheTVDB, Fanart, Douban, OpenAI). Seeds defaults on first run.
    Encrypts api_key on write, returns masked 'abc1****wxyz' projection.
  - service/duplicate.go: sparse-sample MD5 (head + middle + tail, 1MiB
    each, plus file-size suffix) duplicate finder. Picks 'best' primary
    (matched > size > id) and marks others is_duplicate=true.
  - service/filemanager.go: server-side allow-listed file browser used
    by the library-path picker. Strict path-traversal protection.
  - service/dlna.go: real SSDP M-SEARCH discovery + AVTransport
    SetAVTransportURI/Play SOAP cast. 30 s discovery cache.
  - service/scheduler.go: 3 recurring background jobs (library_scan
    60min, transcode_cleanup 24h, recycle_purge 24h with 30-day
    cutoff). Status + run-now endpoints.
  - service/cache_cleanup.go: walkAndPrune helper used by scheduler.
  - service/storage.go: DB-only disk-usage breakdown by library and by
    container format.
  - service/emby_compat.go: read-only Emby/Jellyfin shim
    (System/Info, Users, Users/x/Views, Items, PlaybackInfo) so Infuse
    / VidHub / Kodi can browse MediaStationGo libraries.

Model updates
  - Media: new strm_url (302 redirect target), file_hash, is_duplicate,
    duplicate_of fields.
  - APIConfig: new table for encrypted provider secrets.
  - AutoMigrate registers APIConfig.

Stream layer
  - StreamService.ServeFile now redirects 302 to strm_url when set so
    WebDAV / Alist / S3 / HTTP direct links work transparently.

Handlers + routes
  - Authed: GET /files, GET /storage, GET /dlna/devices, POST /dlna/cast,
    PUT/DELETE /media/:id/strm, POST /strm/import,
    POST /duplicates/{scan,unmark}.
  - Admin: GET/PUT/DELETE /admin/api-configs/:provider,
    GET /admin/scheduler, POST /admin/scheduler/:name/run.
  - New /emby/* group: System/Info, Users, Users/:userId/Views,
    Users/:userId/Items, Items/:id/PlaybackInfo (auth-required).

Frontend pages (lazy-loaded, 7 new chunks)
  - DlnaPage: device list + media picker + cast button.
  - FileManagerPage: root selector + breadcrumb + sortable listing.
  - APIConfigsPage: per-provider card with masked-key editor.
  - StoragePage: usage tiles + per-library bars + per-container grid.
  - DuplicatesPage: scan form + grouped report with primary highlight.
  - SchedulerPage: live job table with run-now button (5s refresh).
  - Sidebar reorganised: 自动化 group adds DLNA, 管理 group adds
    存储 / 文件浏览 / 重复文件 / 定时任务 / API 配置.

Smoke test additions (all admin-only)
  - api-configs seeded with 6 providers
  - api-config encrypted in db (sqlite3 enc:v1: prefix check)
  - storage breakdown
  - file browser lists library root + rejects /etc (path traversal)
  - dlna devices endpoint
  - scheduler exposes 3 jobs + run library_scan
  - emby /System/Info + /Users/{x}/Views
  - strm set + stream 302 + strm clear
  - duplicate scan

Verified: go build, go vet, go test (incl. new TestCrypto* suite + the
existing TestParseEpisode/TestCleanQuery/TestSrtToVTT/TestStripASSTags/
TestBuildFFmpegArgs); tsc -b && vite build emits 28 route chunks plus
the deferred hls chunk; main bundle 253 KB / 85 KB gzipped; smoke test
PASS=42 / FAIL=0.
2026-05-15 10:58:32 +00:00
Kiro d5cf5fb4b2 feat: bootstrap MediaStationGo (Go + React rewrite of MediaStation)
Adopt the cropflre/nowen-video tech stack and rebuild the project from
scratch:

  - Backend: Go 1.25 + Gin + GORM + SQLite (WAL) + JWT + WebSocket hub.
    Layered packages config / database / model / repository / service /
    middleware / handler. Default admin (admin/admin123) seeded on first
    run; /api routes for auth, libraries, media, stream and admin
    panels. WebSocket scan-progress events at /api/ws.
  - Frontend: React 18 + Vite 5 + Tailwind 3.4 + Zustand + axios +
    react-router 6 + lucide-react + framer-motion + hls.js. Pages for
    Login / Home / Library / Search / MediaDetail / Player / Admin
    (Library, Users, Settings tabs).
  - Distribution: multi-arch Dockerfile (frontend -> backend -> Alpine
    runtime), docker-compose.yml, GitHub Actions for CI and GHCR
    publish, Makefile, env-prefixed config (MEDIASTATION_*).
  - Docs: README, CONTRIBUTING, .env.example, config.example.yaml.

Backend builds, vets and tests pass. Frontend builds via tsc -b && vite
build (250 kB JS / 16 kB CSS, gzipped 84 / 4 kB).
2026-05-14 15:26:29 +00:00