From 6debad6eb97d54e97fe57df9c2fdb014c2f7c751 Mon Sep 17 00:00:00 2001 From: Simon Ding Date: Sun, 7 Jul 2024 15:02:40 +0800 Subject: [PATCH] search download --- pkg/utils/utils.go | 13 +++++++++++++ server/resources.go | 20 +++++++++++++++----- ui/lib/APIs.dart | 1 + ui/lib/main.dart | 17 +++++++++++++++-- ui/lib/tv_details.dart | 26 ++++++++++++++++++++++++-- ui/lib/utils.dart | 5 ++++- 6 files changed, 72 insertions(+), 10 deletions(-) create mode 100644 pkg/utils/utils.go diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go new file mode 100644 index 0000000..6cb1944 --- /dev/null +++ b/pkg/utils/utils.go @@ -0,0 +1,13 @@ +package utils + +import "unicode" + +func isASCII(s string) bool { + for _, c := range s { + if c > unicode.MaxASCII { + return false + } + } + return true +} + diff --git a/server/resources.go b/server/resources.go index 7dcb421..6916a29 100644 --- a/server/resources.go +++ b/server/resources.go @@ -49,9 +49,9 @@ func (s *Server) AddTorznabInfo(c *gin.Context) (interface{}, error) { } type searchAndDownloadIn struct { - Title string `json:"title"` - Season int `json:"season"` - Episode int `json:"episode"` + ID int `json:"id"` + Season int `json:"season"` + Episode int `json:"episode"` } func (s *Server) SearchAndDownload(c *gin.Context) (interface{}, error) { @@ -64,8 +64,16 @@ func (s *Server) SearchAndDownload(c *gin.Context) (interface{}, error) { if err != nil { return nil, errors.Wrap(err, "connect transmission") } + log.Infof("search episode resources link: %v", in) + series := s.db.GetSeriesDetails(in.ID) + if series == nil { + return nil, fmt.Errorf("no tv series of id %v", in.ID) + } - res := s.searchTvWithTorznab(in.Title, in.Season, in.Episode) + res := s.searchTvWithTorznab(series.OriginalName, in.Season, in.Episode) + if len(res) == 0 { + return "", fmt.Errorf("no resource found") + } r1 := res[0] log.Infof("found resource to download: %v", r1) torrent, err := trc.Download(r1.Magnet) @@ -78,7 +86,9 @@ func (s *Server) SearchAndDownload(c *gin.Context) (interface{}, error) { // return nil, errors.Wrap(err, "download torrent") // } log.Errorf("success add %s to download task", r1.Name) - return nil, nil + return gin.H{ + "name": r1.Name, + }, nil } type downloadClientIn struct { diff --git a/ui/lib/APIs.dart b/ui/lib/APIs.dart index d098430..998a4d4 100644 --- a/ui/lib/APIs.dart +++ b/ui/lib/APIs.dart @@ -6,6 +6,7 @@ class APIs { static final settingsUrl = "$_baseUrl/api/v1/setting/do"; static final watchlistUrl = "$_baseUrl/api/v1/tv/watchlist"; static final seriesDetailUrl = "$_baseUrl/api/v1/tv/series/"; + static final searchAndDownloadUrl = "$_baseUrl/api/v1/indexer/download"; static const tmdbImgBaseUrl = "https://image.tmdb.org/t/p/w500/"; diff --git a/ui/lib/main.dart b/ui/lib/main.dart index 5131678..581e073 100644 --- a/ui/lib/main.dart +++ b/ui/lib/main.dart @@ -55,7 +55,7 @@ class MyApp extends StatelessWidget { routes: [ GoRoute( path: WelcomePage.route, - builder: (context, state) => WelcomePage(), + builder: (context, state) => const WelcomePage(), ), GoRoute( path: SearchPage.route, @@ -63,7 +63,7 @@ class MyApp extends StatelessWidget { ), GoRoute( path: SystemSettingsPage.route, - builder: (context, state) => SystemSettingsPage(), + builder: (context, state) => const SystemSettingsPage(), ), GoRoute( path: TvDetailsPage.route, @@ -107,3 +107,16 @@ class MyApp extends StatelessWidget { ); } } + +CustomTransitionPage buildPageWithDefaultTransition({ + required BuildContext context, + required GoRouterState state, + required Widget child, +}) { + return CustomTransitionPage( + key: state.pageKey, + child: child, + transitionsBuilder: (context, animation, secondaryAnimation, child) => + FadeTransition(opacity: animation, child: child), + ); +} diff --git a/ui/lib/tv_details.dart b/ui/lib/tv_details.dart index b0facde..988d6d9 100644 --- a/ui/lib/tv_details.dart +++ b/ui/lib/tv_details.dart @@ -30,7 +30,6 @@ class _TvDetailsPageState extends State { @override void initState() { - super.initState(); _querySeriesDetails(); } @@ -62,7 +61,12 @@ class _TvDetailsPageState extends State { ), Text("${ep.title}", textAlign: TextAlign.left), const Expanded(child: Text("")), - IconButton(onPressed: () {}, icon: const Icon(Icons.search)) + IconButton( + onPressed: () { + _searchAndDownload( + context, seriesId, ep.seasonNumber!, ep.episodeNumber!); + }, + icon: const Icon(Icons.search)) ], ), ); @@ -148,6 +152,24 @@ class _TvDetailsPageState extends State { details = SeriesDetails.fromJson(rsp.data); }); } + + void _searchAndDownload(BuildContext context, String seriesId, int seasonNum, + int episodeNum) async { + var resp = await Dio().post(APIs.searchAndDownloadUrl, data: { + "id": int.parse(seriesId), + "season": seasonNum, + "episode": episodeNum, + }); + var sp = ServerResponse.fromJson(resp.data); + if (sp.code != 0 && context.mounted) { + Utils.showAlertDialog(context, sp.message); + return; + } + var name = (sp.data as Map)["name"]; + if (context.mounted) { + Utils.showSnakeBar(context, "$name 开始下载..."); + } + } } class SeriesDetails { diff --git a/ui/lib/utils.dart b/ui/lib/utils.dart index 41e8b75..b4c018d 100644 --- a/ui/lib/utils.dart +++ b/ui/lib/utils.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; class Utils { static Future showAlertDialog(BuildContext context, String msg) async { - return showDialog( context: context, barrierDismissible: true, // user must tap button! @@ -28,4 +27,8 @@ class Utils { }, ); } + + static showSnakeBar(BuildContext context, String msg) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(msg))); + } }