mirror of
https://github.com/GopeedLab/gopeed.git
synced 2026-11-09 01:50:30 +00:00
feat(protocol): add FTP, FTPS and FTPES downloads (#1569)
This commit is contained in:
1 parent
e0951de270
commit
c0b70d319d
54 files changed
+3850
-38
No files matched your search
@@ -64,6 +64,10 @@ class ProtocolConfig {
|
||||
Ed2kConfig ed2k = Ed2kConfig();
|
||||
HlsConfig hls = HlsConfig();
|
||||
|
||||
/// A server without FTP support sends no `ftp` key; the defaults keep the rest of the config readable.
|
||||
@JsonKey(fromJson: _ftpConfigFromJson)
|
||||
FtpConfig ftp = FtpConfig();
|
||||
|
||||
ProtocolConfig();
|
||||
|
||||
factory ProtocolConfig.fromJson(Map<String, dynamic>? json) =>
|
||||
@@ -91,6 +95,20 @@ class HlsConfig {
|
||||
Map<String, dynamic> toJson() => _$HlsConfigToJson(this);
|
||||
}
|
||||
|
||||
FtpConfig _ftpConfigFromJson(Map<String, dynamic>? json) => json == null ? FtpConfig() : FtpConfig.fromJson(json);
|
||||
|
||||
/// Global FTP defaults. It mirrors the `ftp` protocol config of the server.
|
||||
@JsonSerializable()
|
||||
class FtpConfig {
|
||||
int connections;
|
||||
|
||||
FtpConfig({this.connections = 0});
|
||||
|
||||
factory FtpConfig.fromJson(Map<String, dynamic> json) => _$FtpConfigFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$FtpConfigToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class HttpConfig {
|
||||
String userAgent;
|
||||
|
||||
@@ -67,13 +67,15 @@ ProtocolConfig _$ProtocolConfigFromJson(Map<String, dynamic> json) => ProtocolCo
|
||||
..http = HttpConfig.fromJson(json['http'] as Map<String, dynamic>)
|
||||
..bt = BtConfig.fromJson(json['bt'] as Map<String, dynamic>)
|
||||
..ed2k = Ed2kConfig.fromJson(json['ed2k'] as Map<String, dynamic>)
|
||||
..hls = HlsConfig.fromJson(json['hls'] as Map<String, dynamic>);
|
||||
..hls = HlsConfig.fromJson(json['hls'] as Map<String, dynamic>)
|
||||
..ftp = _ftpConfigFromJson(json['ftp'] as Map<String, dynamic>?);
|
||||
|
||||
Map<String, dynamic> _$ProtocolConfigToJson(ProtocolConfig instance) => <String, dynamic>{
|
||||
'http': instance.http.toJson(),
|
||||
'bt': instance.bt.toJson(),
|
||||
'ed2k': instance.ed2k.toJson(),
|
||||
'hls': instance.hls.toJson(),
|
||||
'ftp': instance.ftp.toJson(),
|
||||
};
|
||||
|
||||
HlsConfig _$HlsConfigFromJson(Map<String, dynamic> json) => HlsConfig(
|
||||
@@ -90,6 +92,11 @@ Map<String, dynamic> _$HlsConfigToJson(HlsConfig instance) => <String, dynamic>{
|
||||
'prefetchContentLength': instance.prefetchContentLength,
|
||||
};
|
||||
|
||||
FtpConfig _$FtpConfigFromJson(Map<String, dynamic> json) =>
|
||||
FtpConfig(connections: (json['connections'] as num?)?.toInt() ?? 0);
|
||||
|
||||
Map<String, dynamic> _$FtpConfigToJson(FtpConfig instance) => <String, dynamic>{'connections': instance.connections};
|
||||
|
||||
HttpConfig _$HttpConfigFromJson(Map<String, dynamic> json) => HttpConfig(
|
||||
userAgent: json['userAgent'] as String? ?? '',
|
||||
connections: (json['connections'] as num?)?.toInt() ?? 0,
|
||||
|
||||
@@ -67,3 +67,28 @@ class OptsExtraHttp {
|
||||
|
||||
Map<String, dynamic> toJson() => _$OptsExtraHttpToJson(this);
|
||||
}
|
||||
|
||||
/// Options for an FTP task. It mirrors `pkg/protocol/ftp.OptsExtra`. The TLS
|
||||
/// mode of an `ftp://` link is on the request, see `ReqExtraFtp`.
|
||||
@JsonSerializable()
|
||||
class OptsExtraFtp {
|
||||
int connections;
|
||||
bool? autoTorrent;
|
||||
bool? deleteTorrentAfterDownload;
|
||||
bool? autoExtract;
|
||||
String archivePassword;
|
||||
bool deleteAfterExtract;
|
||||
|
||||
OptsExtraFtp({
|
||||
this.connections = 0,
|
||||
this.autoTorrent,
|
||||
this.deleteTorrentAfterDownload,
|
||||
this.autoExtract,
|
||||
this.archivePassword = '',
|
||||
this.deleteAfterExtract = false,
|
||||
});
|
||||
|
||||
factory OptsExtraFtp.fromJson(Map<String, dynamic> json) => _$OptsExtraFtpFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$OptsExtraFtpToJson(this);
|
||||
}
|
||||
@@ -65,3 +65,21 @@ Map<String, dynamic> _$OptsExtraHttpToJson(OptsExtraHttp instance) =>
|
||||
'deleteAfterExtract': instance.deleteAfterExtract,
|
||||
'checksum': ?instance.checksum?.toJson(),
|
||||
};
|
||||
|
||||
OptsExtraFtp _$OptsExtraFtpFromJson(Map<String, dynamic> json) => OptsExtraFtp(
|
||||
connections: (json['connections'] as num?)?.toInt() ?? 0,
|
||||
autoTorrent: json['autoTorrent'] as bool?,
|
||||
deleteTorrentAfterDownload: json['deleteTorrentAfterDownload'] as bool?,
|
||||
autoExtract: json['autoExtract'] as bool?,
|
||||
archivePassword: json['archivePassword'] as String? ?? '',
|
||||
deleteAfterExtract: json['deleteAfterExtract'] as bool? ?? false,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$OptsExtraFtpToJson(OptsExtraFtp instance) => <String, dynamic>{
|
||||
'connections': instance.connections,
|
||||
'autoTorrent': ?instance.autoTorrent,
|
||||
'deleteTorrentAfterDownload': ?instance.deleteTorrentAfterDownload,
|
||||
'autoExtract': ?instance.autoExtract,
|
||||
'archivePassword': instance.archivePassword,
|
||||
'deleteAfterExtract': instance.deleteAfterExtract,
|
||||
};
|
||||
@@ -42,6 +42,20 @@ class ReqExtraBt {
|
||||
Map<String, dynamic> toJson() => _$ReqExtraBtToJson(this);
|
||||
}
|
||||
|
||||
/// The request extra of an FTP task. It mirrors `pkg/protocol/ftp.ReqExtra`;
|
||||
/// [tls] only applies to `ftp://` URLs, because `ftps://` always uses
|
||||
/// implicit TLS and `ftpes://` always uses explicit TLS.
|
||||
@JsonSerializable()
|
||||
class ReqExtraFtp {
|
||||
String tls;
|
||||
|
||||
ReqExtraFtp({this.tls = 'none'});
|
||||
|
||||
factory ReqExtraFtp.fromJson(Map<String, dynamic> json) => _$ReqExtraFtpFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$ReqExtraFtpToJson(this);
|
||||
}
|
||||
|
||||
enum RequestProxyMode { follow, none, custom }
|
||||
|
||||
@JsonSerializable()
|
||||
|
||||
@@ -41,6 +41,10 @@ ReqExtraBt _$ReqExtraBtFromJson(Map<String, dynamic> json) =>
|
||||
|
||||
Map<String, dynamic> _$ReqExtraBtToJson(ReqExtraBt instance) => <String, dynamic>{'trackers': instance.trackers};
|
||||
|
||||
ReqExtraFtp _$ReqExtraFtpFromJson(Map<String, dynamic> json) => ReqExtraFtp(tls: json['tls'] as String? ?? 'none');
|
||||
|
||||
Map<String, dynamic> _$ReqExtraFtpToJson(ReqExtraFtp instance) => <String, dynamic>{'tls': instance.tls};
|
||||
|
||||
RequestProxy _$RequestProxyFromJson(Map<String, dynamic> json) => RequestProxy(
|
||||
mode: $enumDecodeNullable(_$RequestProxyModeEnumMap, json['mode']) ?? RequestProxyMode.follow,
|
||||
scheme: json['scheme'] as String? ?? 'http',
|
||||
|
||||
@@ -6,7 +6,7 @@ part 'task.g.dart';
|
||||
|
||||
enum Status { ready, running, pause, wait, error, done }
|
||||
|
||||
enum Protocol { http, bt, ed2k, hls }
|
||||
enum Protocol { http, bt, ed2k, hls, ftp }
|
||||
|
||||
// ExtractStatus enum matching Go backend
|
||||
enum ExtractStatus {
|
||||
|
||||
@@ -40,7 +40,13 @@ const _$StatusEnumMap = {
|
||||
Status.done: 'done',
|
||||
};
|
||||
|
||||
const _$ProtocolEnumMap = {Protocol.http: 'http', Protocol.bt: 'bt', Protocol.ed2k: 'ed2k', Protocol.hls: 'hls'};
|
||||
const _$ProtocolEnumMap = {
|
||||
Protocol.http: 'http',
|
||||
Protocol.bt: 'bt',
|
||||
Protocol.ed2k: 'ed2k',
|
||||
Protocol.hls: 'hls',
|
||||
Protocol.ftp: 'ftp',
|
||||
};
|
||||
|
||||
Progress _$ProgressFromJson(Map<String, dynamic> json) => Progress(
|
||||
used: (json['used'] as num).toInt(),
|
||||
|
||||
@@ -52,7 +52,8 @@ sealed class TaskStats {
|
||||
final runtime = _map(json['runtime']);
|
||||
if (snapshot.isEmpty && runtime.isEmpty) return null;
|
||||
return switch (protocol) {
|
||||
Protocol.http => HttpTaskStats.fromJson(snapshot),
|
||||
// FTP stats have the same shape as HTTP stats: one entry per connection.
|
||||
Protocol.http || Protocol.ftp => HttpTaskStats.fromJson(snapshot),
|
||||
Protocol.bt => BtTaskStats.fromJson(snapshot: snapshot, runtime: runtime),
|
||||
Protocol.ed2k => Ed2kTaskStats.fromJson(snapshot: snapshot, runtime: runtime),
|
||||
Protocol.hls || null => null,
|
||||
|
||||
Reference in new issue
Block a user