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
« 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."""
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
16class SettingsSeedboxForm(FlaskForm): # type: ignore[misc]
17 """
18 Form for configuring remote Seedbox connection and synchronization parameters.
20 Manages host authentication, protocol parameters, path definitions, and
21 file filtration rules for the seedbox integration.
22 """
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})?$"
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 )