diff --git a/lnbits/core/services/lightning_address.py b/lnbits/core/services/lightning_address.py index 2c2f9faf0..51df5bea3 100644 --- a/lnbits/core/services/lightning_address.py +++ b/lnbits/core/services/lightning_address.py @@ -28,6 +28,8 @@ from lnbits.settings import settings MAX_SENDABLE_MSAT = 2_100_000_000_000_000_000 COMMENT_ALLOWED = 799 LIGHTNING_ADDRESS_REGEX = re.compile(r"^[a-z0-9_.-]{1,210}$") + + def normalize_lightning_address_local_part(local_part: str) -> str: return local_part.strip().lower() diff --git a/lnbits/helpers.py b/lnbits/helpers.py index 971e75de3..6abdbf543 100644 --- a/lnbits/helpers.py +++ b/lnbits/helpers.py @@ -3,7 +3,6 @@ import json import re from datetime import datetime, timedelta, timezone from pathlib import Path -from random import SystemRandom from typing import Any from urllib import request from urllib.parse import urlparse @@ -14,6 +13,7 @@ from fastapi.routing import APIRoute from loguru import logger from packaging import version from pydantic.schema import field_schema +from random_username.generate import generate_username # type: ignore[import-untyped] from starlette.templating import Jinja2Templates from lnbits.settings import settings @@ -22,69 +22,9 @@ from lnbits.utils.exchange_rates import currencies from .db import FilterModel -_RANDOM = SystemRandom() - -_PARTICIPLES = [ - "asking", - "blazing", - "bouncing", - "charging", - "climbing", - "dancing", - "drifting", - "flying", - "glowing", - "hopping", - "jumping", - "laughing", - "leaping", - "racing", - "rising", - "running", - "shining", - "singing", - "skipping", - "sparking", - "spinning", - "sprinting", - "twirling", - "wandering", - "zipping", -] - -_NOUNS = [ - "anchor", - "beacon", - "bolt", - "comet", - "ember", - "falcon", - "flash", - "garden", - "harbor", - "lantern", - "market", - "meadow", - "meteor", - "orbit", - "phoenix", - "rabbit", - "rocket", - "signal", - "spark", - "summit", - "thunder", - "wallet", - "wave", - "zephyr", -] - def _generate_local_part() -> str: - participle = _RANDOM.choice(_PARTICIPLES) - noun = _RANDOM.choice(_NOUNS) - suffix = _RANDOM.randint(0, 999) - return f"{participle}.{noun}.{suffix:03d}" + return generate_username(1)[0].lower() def get_db_vendor_name(): diff --git a/poetry.lock b/poetry.lock index 9decab91d..2a9a66ebb 100644 --- a/poetry.lock +++ b/poetry.lock @@ -3954,6 +3954,18 @@ files = [ {file = "pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f"}, ] +[[package]] +name = "random-username" +version = "1.0.2" +description = "Randomly generate compelling usernames." +optional = false +python-versions = "*" +groups = ["main"] +files = [ + {file = "random-username-1.0.2.tar.gz", hash = "sha256:5fdc0604b5d1bdfe4acf4cd7491a9de1caf41bbdd890f646b434e09ae2a1b7ce"}, + {file = "random_username-1.0.2-py3-none-any.whl", hash = "sha256:2536feb63fecde7e01ede4a541aadb6f0b58794a7ab327ca5369d2a4b7664c06"}, +] + [[package]] name = "referencing" version = "0.36.2" @@ -5184,4 +5196,4 @@ migration = ["psycopg2-binary"] [metadata] lock-version = "2.1" python-versions = ">=3.10,<3.13" -content-hash = "b167368cde275d9b12ea2c352a9ca2558da1aa9476ada0795cfd4f45d2ca72bc" +content-hash = "e41fd327115a1614f2e7b5dae7d7077e30f1cb723e1880a88132ec38df2b4b1a" diff --git a/pyproject.toml b/pyproject.toml index 023ae2dd5..d392f44a5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,6 +54,7 @@ dependencies = [ "urllib3>=2.7.0", "pyinstrument>=5.1.2", "wasmtime>=45.0.0", + "random-username~=1.0.2", ] [project.scripts] diff --git a/uv.lock b/uv.lock index bb02e17ff..24058c661 100644 --- a/uv.lock +++ b/uv.lock @@ -1324,6 +1324,7 @@ dependencies = [ { name = "python-dotenv" }, { name = "python-multipart" }, { name = "pywebpush" }, + { name = "random-username" }, { name = "shortuuid" }, { name = "slowapi" }, { name = "sqlalchemy" }, @@ -1414,6 +1415,7 @@ requires-dist = [ { name = "python-dotenv", specifier = "~=1.2.1" }, { name = "python-multipart", specifier = "~=0.0.22" }, { name = "pywebpush", specifier = "~=2.2.0" }, + { name = "random-username", specifier = "~=1.0.2" }, { name = "shortuuid", specifier = "~=1.0.13" }, { name = "slowapi", specifier = "~=0.1.9" }, { name = "sqlalchemy", specifier = "~=1.4.54" }, @@ -2392,6 +2394,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" }, ] +[[package]] +name = "random-username" +version = "1.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/be/84/7004e0038707827e7ebe91a09e0f46483e36134de3b20bc0d5cf864a4caa/random-username-1.0.2.tar.gz", hash = "sha256:5fdc0604b5d1bdfe4acf4cd7491a9de1caf41bbdd890f646b434e09ae2a1b7ce", size = 3805, upload-time = "2019-01-11T22:57:45.038Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/92/d8/0f96b9bdea0683884b0ff2d8663b2580e2bad4418848540d1a12e1fd1d7b/random_username-1.0.2-py3-none-any.whl", hash = "sha256:2536feb63fecde7e01ede4a541aadb6f0b58794a7ab327ca5369d2a4b7664c06", size = 6673, upload-time = "2019-01-11T22:57:43.656Z" }, +] + [[package]] name = "referencing" version = "0.36.2"