Coverage for seedboxsync/front/forms/settings/seedbox.py: 100%

22 statements  

« prev     ^ index     » next       coverage.py v7.16.1, created at 2026-09-26 17:14 +0000

1# 

2# Copyright (C) 2015-2026 Guillaume Kulakowski <guillaume@kulakowski.fr> 

3# 

4# For the full copyright and license information, please view the LICENSE 

5# file that was distributed with this source code. 

6# 

7"""SeedboxSync WTForms form for settings Seedbox.""" 

8 

9from flask_wtf import FlaskForm 

10from wtforms import IntegerField, PasswordField, SelectField, StringField 

11from wtforms.validators import DataRequired, NumberRange, Regexp 

12from seedboxsync.front.babel import gettext as _ 

13from seedboxsync.front.forms.validators import DomainOrIP 

14 

15 

16class SettingsSeedboxForm(FlaskForm): # type: ignore[misc] 

17 """ 

18 Form for configuring remote Seedbox connection and synchronization parameters. 

19 

20 Manages host authentication, protocol parameters, path definitions, and 

21 file filtration rules for the seedbox integration. 

22 """ 

23 

24 DOMAIN_REGEX = r"^(?:(?!-)[A-Za-z0-9-]{0,61}[A-Za-z0-9]\.)+[A-Za-z]{2,}$" 

25 OCTAL_REGEX = r"^(?:0|0o[0-7]{3,4})?$" 

26 

27 seedbox_host = StringField(_("Hostname"), validators=[DataRequired(), DomainOrIP()], render_kw={"placeholder": "my-seedbox.ltd", "icon": "fa-server"}) 

28 seedbox_port = IntegerField(_("Port"), validators=[DataRequired(), NumberRange(min=1, max=65535)], render_kw={"placeholder": "22", "icon": "fa-plug"}) 

29 seedbox_login = StringField(_("Login"), validators=[DataRequired()], render_kw={"placeholder": "me", "icon": "fa-user"}) 

30 seedbox_password = PasswordField(_("Password"), validators=[DataRequired()], render_kw={"placeholder": "********", "icon": "fa-key"}) 

31 seedbox_timeout = IntegerField(_("Timeout (in seconds)"), validators=[NumberRange(min=0, max=100000)], render_kw={"placeholder": "30", "icon": "fa-clock"}) 

32 seedbox_protocol = SelectField( 

33 _("Protocol"), 

34 choices=[ 

35 ("sftp", _("sFTP")), 

36 ("ftp", _("FTP")), 

37 ], 

38 default="sftp", 

39 render_kw={"icon": "fa-network-wired"}, 

40 ) 

41 seedbox_chmod = StringField( 

42 _("chmod (in octal notation)"), 

43 validators=[Regexp(OCTAL_REGEX)], 

44 render_kw={"placeholder": "0o644", "icon": "fa-lock", "help": _("Chmod torrent after upload. Use octal notation, e.g. 0o644.")}, 

45 ) 

46 seedbox_max_concurrent_prefetch_requests = IntegerField( 

47 _("Max concurrent prefetch requests"), 

48 validators=[DataRequired(), NumberRange(min=1, max=1024)], 

49 render_kw={ 

50 "placeholder": "128", 

51 "icon": "fa-check", 

52 "help": ( 

53 _( 

54 "Only for SFTP (Paramiko). The maximum number of concurrent read requests to prefetch. When this is None (the default), do not limit " 

55 "the number of concurrent prefetch requests." 

56 "Note: OpenSSH's sftp internally imposes a limit of 64 concurrent requests, while Paramiko imposes no limit by default; consider setting " 

57 "a limit if a file can be successfully received with sftp but hangs with Paramiko." 

58 ) 

59 ), 

60 }, 

61 ) 

62 seedbox_tmp_path = StringField( 

63 _("Temporary path"), 

64 validators=[DataRequired()], 

65 render_kw={"placeholder": "./tmp", "icon": "fa-folder", "help": _("Use a temporary directory for incomplete transfers (must be created manually).")}, 

66 ) 

67 seedbox_watch_path = StringField( 

68 _("Watch path"), 

69 validators=[DataRequired()], 

70 render_kw={"placeholder": "./watch", "icon": "fa-folder", "help": _("Your BitTorrent client's watch folder (must be created manually).")}, 

71 ) 

72 seedbox_finished_path = StringField( 

73 _("Finished path"), 

74 validators=[DataRequired()], 

75 render_kw={"placeholder": "./downdloads", "icon": "fa-folder", "help": _("The folder where your BitTorrent client puts finished files.")}, 

76 ) 

77 seedbox_prefixed_path = StringField( 

78 _("Prefixed path"), 

79 render_kw={"placeholder": "dowloaded", "icon": "fa-broom", "help": _("Remove a prefix from the synced path (usually the same as finished_path).")}, 

80 ) 

81 seedbox_part_suffix = StringField( 

82 _("Suffix used for .part"), 

83 render_kw={"placeholder": ".part", "icon": "fa-caret-left", "help": _("Exclude files with this suffix (e.g. incomplete downloads).")}, 

84 ) 

85 seedbox_exclude_syncing = StringField( 

86 _("Files to exclude from synching"), 

87 render_kw={ 

88 "placeholder": "^.*missing$", 

89 "icon": "fa-ban", 

90 "help": _("Exclude files from sync using a regular expression (Python re syntax). Example: .*missing$"), 

91 }, 

92 )