1from enum import Enum
2
3from pydantic import ConfigDict, BaseModel, Field, field_validator
4
5from app.models.node import Node
6
7
8class ProxyTypes(str, Enum):
9 # proxy_type = protocol
10 VMess = "vmess"
11 VLESS = "vless"
12 Trojan = "trojan"
13 Shadowsocks = "shadowsocks"
14
15
16class InboundHostSecurity(str, Enum):
17 inbound_default = "inbound_default"
18 none = "none"
19 tls = "tls"
20
21
22InboundHostALPN = Enum(
23 "ProxyHostALPN",
24 {
25 "none": "",
26 "h2": "h2",
27 "http/1.1": "http/1.1",
28 "h2,http/1.1": "h2,http/1.1",
29 "h3": "h3",
30 "h3,h2": "h3,h2",
31 "h3,h2,http/1.1": "h3,h2,http/1.1",
32 },
33)
34
35
36InboundHostFingerprint = Enum(
37 "ProxyHostFingerprint",
38 {
39 "none": "",
40 "chrome": "chrome",
41 "firefox": "firefox",
42 "safari": "safari",
43 "ios": "ios",
44 "android": "android",
45 "edge": "edge",
46 "360": "360",
47 "qq": "qq",
48 "random": "random",
49 "randomized": "randomized",
50 },
51)
52
53
54class FormatVariables(dict):
55 def __missing__(self, key):
56 return key.join("{}")
57
58
59class FragmentSettings(BaseModel):
60 packets: str = Field(pattern=r"^(:?tlshello|[\d-]{1,32})$")
61 length: str = Field(pattern=r"^[\d-]{1,32}$")
62 interval: str = Field(pattern=r"^[\d-]{1,32}$")
63
64
65class InboundHost(BaseModel):
66 remark: str
67 address: str
68 port: int | None = Field(None)
69 sni: str | None = Field(None)
70 host: str | None = Field(None)
71 path: str | None = Field(None)
72 security: InboundHostSecurity = InboundHostSecurity.inbound_default
73 alpn: InboundHostALPN = InboundHostALPN.none
74 fingerprint: InboundHostFingerprint = InboundHostFingerprint.none
75 allowinsecure: bool | None = None
76 is_disabled: bool | None = None
77 mux: bool = Field(False)
78 fragment: FragmentSettings | None = Field(None)
79 model_config = ConfigDict(from_attributes=True)
80
81 @field_validator("remark", "address", "path")
82 @classmethod
83 def validate_fmt_variables(cls, v: str) -> str:
84 if not v:
85 return v
86
87 v.format_map(FormatVariables())
88
89 return v
90
91
92class InboundHostResponse(InboundHost):
93 id: int
94
95
96class Inbound(BaseModel):
97 id: int
98 tag: str
99 protocol: ProxyTypes
100 config: str
101 node: Node
102 service_ids: list[int]
103 model_config = ConfigDict(from_attributes=True)