diff --git a/app/db/crud.py b/app/db/crud.py
@@ -33,8 +33,8 @@ def add_default_hosts(db: Session, inbounds: List[Inbound]):
def assure_node_inbounds(db: Session, inbounds: List[Inbound], node_id: int):
- existing_inbounds = set((i.protocol, i.tag) for i in db.query(Inbound).filter(Inbound.node_id == node_id).all())
- inbounds_set = set((json.loads(i.config)["protocol"], i.tag) for i in list(inbounds))
+ existing_inbounds = set((i.protocol, i.tag, i.config) for i in db.query(Inbound).filter(Inbound.node_id == node_id).all())
+ inbounds_set = set((json.loads(i.config)["protocol"], i.tag, i.config) for i in list(inbounds))
new_inbounds = inbounds_set - existing_inbounds
deleted_inbounds = existing_inbounds - inbounds_set
# difference = [ i for i in existing_inbounds if (i.protocol, i.tag) not in existing_inbounds ]
@@ -46,7 +46,7 @@ def assure_node_inbounds(db: Session, inbounds: List[Inbound], node_id: int):
.execution_options(synchronize_session="fetch")
)
db.execute(stmt)"""
- new_inbounds = [Inbound(tag=i[1], protocol=i[0], node_id=node_id) for i in new_inbounds]
+ new_inbounds = [Inbound(tag=i[1], protocol=i[0], config=i[2], node_id=node_id) for i in new_inbounds]
db.add_all(new_inbounds)
db.flush()
for i in new_inbounds:
diff --git a/app/db/migrations/versions/20faa9f18c0a_init.py b/app/db/migrations/versions/20faa9f18c0a_init.py
@@ -41,10 +41,10 @@ def upgrade() -> None:
op.create_table('nodes',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=256, collation='NOCASE'), nullable=True),
- sa.Column('address', sa.String(length=256), nullable=False),
- sa.Column('port', sa.Integer(), nullable=False),
+ sa.Column('address', sa.String(length=256), nullable=True),
+ sa.Column('port', sa.Integer(), nullable=True),
sa.Column('xray_version', sa.String(length=32), nullable=True),
- sa.Column('status', sa.Enum('connected', 'connecting', 'error', 'disabled', name='nodestatus'), nullable=False),
+ sa.Column('status', sa.Enum('healthy', 'unhealthy', 'disabled', name='nodestatus'), nullable=False),
sa.Column('last_status_change', sa.DateTime(), nullable=True),
sa.Column('message', sa.String(length=1024), nullable=True),
sa.Column('created_at', sa.DateTime(), nullable=True),
@@ -85,6 +85,7 @@ def upgrade() -> None:
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('protocol', sa.String(), nullable=True),
sa.Column('tag', sa.String(length=256), nullable=False),
+ sa.Column('config', sa.String(), nullable=False),
sa.Column('node_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['node_id'], ['nodes.id'], ),
sa.PrimaryKeyConstraint('id')
diff --git a/app/db/models.py b/app/db/models.py
@@ -121,6 +121,7 @@ class Inbound(Base):
id = Column(Integer, primary_key=True)
protocol = Column(Enum(ProxyTypes))
tag = Column(String(256), nullable=False, index=True)
+ config = Column(String(), nullable=False)
node_id = Column(Integer, ForeignKey("nodes.id"), index=True)
node = relationship("Node", back_populates="inbounds")
services = relationship("Service", secondary=inbounds_services, back_populates="inbounds")
diff --git a/app/marznode/grpc.py b/app/marznode/grpc.py
@@ -4,6 +4,7 @@ import tempfile
from grpclib import GRPCError
from grpclib.client import Channel
+from grpclib.exceptions import StreamTerminatedError
from grpclib.health.v1.health_grpc import HealthStub
from grpclib.health.v1.health_pb2 import HealthCheckResponse, HealthCheckRequest
@@ -99,7 +100,7 @@ class MarzNodeGRPC(MarzNodeBase):
async def is_alive(self) -> bool:
try:
response = await self._health.Check(HealthCheckRequest())
- except (OSError, ConnectionError, GRPCError):
+ except (OSError, ConnectionError, GRPCError, StreamTerminatedError):
pass
else:
if response.status is HealthCheckResponse.SERVING:
diff --git a/app/models/proxy.py b/app/models/proxy.py
@@ -160,6 +160,7 @@ class InboundBase(BaseModel):
id: Optional[int] = Field(None)
tag: str = Field()
protocol: ProxyTypes = Field()
+ config: str
node_id: Optional[int] = Field(None)
model_config = ConfigDict(from_attributes=True)
diff --git a/app/models/user.py b/app/models/user.py
@@ -94,8 +94,10 @@ class UserBase(BaseModel):
return v
model_config = ConfigDict(from_attributes=True)
+
from app.models.service import ServiceBase
+
class User(UserBase):
pass
@@ -131,7 +133,7 @@ class UserCreate(User):
on_hold_expire = info.data.get("on_hold_expire_duration")
expire = info.data.get("expire")
if status == UserStatusCreate.on_hold:
- if (on_hold_expire == 0 or on_hold_expire is None):
+ if on_hold_expire == 0 or on_hold_expire is None:
raise ValueError("User cannot be on hold without a valid on_hold_expire_duration.")
if expire:
raise ValueError("User cannot be on hold with specified expire.")
@@ -192,9 +194,9 @@ class UserResponse(User):
@computed_field
@property
def links(self) -> List[str]:
- return [""]# generate_v2ray_links(
- # inbounds=self.inbounds, key=self.key, extra_data=self.dict(exclude={'subscription_url', 'links'})
- # )
+ return generate_v2ray_links(
+ inbounds=self.inbounds, key=self.key, extra_data=self.dict(exclude={'subscription_url', 'links'})
+ )
@computed_field
@property
diff --git a/app/utils/share.py b/app/utils/share.py
@@ -922,11 +922,10 @@ def process_inbounds_and_tags(
results = []
for inb in inbounds:
- inb_id, protocol, tag = inb.id, inb.protocol, inb.tag
+ inb_id, inbound, protocol, tag = inb.id, json.loads(inb.config), inb.protocol, inb.tag
settings = generate_settings(ukey, protocol)
format_variables.update({"PROTOCOL": protocol.name})
- inbound = xray.configs[inb.node_id].inbounds_by_tag.get(tag)
if not inbound:
continue