Author SHA1 Message Date
klemek 0a8775dfc9 chore: 1.3.0
Python Lint CI / ty (push) Successful in 4m5s
Python Lint CI / ruff-format-check (push) Successful in 4m6s
Python Lint CI / ruff (push) Successful in 55s
2026-06-16 00:24:47 +02:00
klemek 015eebd6ed feat: blacklist 2026-06-16 00:24:40 +02:00
klemek 3df8cfffc7 chore: 1.2.0
Python Lint CI / ruff-format-check (push) Successful in 2m32s
Python Lint CI / ty (push) Successful in 3m7s
Python Lint CI / ruff (push) Successful in 1m5s
2026-06-15 15:09:33 +02:00
klemek 85a1c47c8c feat: custom word list 2026-06-15 15:09:27 +02:00
11 changed files with 1347 additions and 41 deletions
+1
View File
@@ -9,3 +9,4 @@ coverage.xml
build build
dist dist
.pytest_cache .pytest_cache
words.txt
+7 -4
View File
@@ -23,15 +23,18 @@ uvx --from git+https://git.klemek.fr/klemek/cool-domain cool-domain
## Usage ## Usage
```txt ```txt
usage: cool-domain [-h] [--count DOMAIN_COUNT] [--lang {english,french}] [--words WORD_COUNT] [--dig | --no-dig] [--debug | --no-debug] usage: cool-domain [-h] [--count DOMAIN_COUNT] [--words WORD_COUNT] [--lang {english,french,custom}] [--custom-words CUSTOM_WORDS]
[--quiet | --no-quiet] [--cache | --no-cache] [--cache-file CACHE_FILE] [--tld-list-uri TLD_LIST_URI] [--dig | --no-dig] [--debug | --no-debug] [--quiet | --no-quiet] [--cache | --no-cache] [--cache-file CACHE_FILE]
[--tld-list-uri TLD_LIST_URI]
options: options:
-h, --help show this help message and exit -h, --help show this help message and exit
--count DOMAIN_COUNT number of domains to generate (default: 1) --count DOMAIN_COUNT number of domains to generate (default: 1)
--lang {english,french}
word list lang (default: english)
--words WORD_COUNT number of words per domain (default: 1) --words WORD_COUNT number of words per domain (default: 1)
--lang {english,french,custom}
word list lang (default: english)
--custom-words CUSTOM_WORDS
custom word list location (default: words.txt)
--dig, --no-dig check availability with dig (default: true) --dig, --no-dig check availability with dig (default: true)
--debug, --no-debug --debug, --no-debug
--quiet, --no-quiet --quiet, --no-quiet
+15 -8
View File
@@ -1,23 +1,26 @@
import logging import logging
import sys import sys
from . import PKG_NAME, PKG_VERSION from cool_domain import PKG_NAME, PKG_VERSION
from .cache import Cache from cool_domain.cache import Cache
from .constants import LANGS from cool_domain.constants import LANGS
from .factory import Factory from cool_domain.factory import Factory
from .logs import setup_logs from cool_domain.logs import setup_logs
from .params import parse_parameters from cool_domain.params import parse_parameters
from .tld_list import TLDList from cool_domain.tld_list import TLDList
from cool_domain.word_list import WordList
def main() -> int: def main() -> int:
params = parse_parameters(sys.argv[1:]) params = parse_parameters(sys.argv[1:])
setup_logs(params) setup_logs(params)
logging.getLogger().info("%s %s", PKG_NAME, PKG_VERSION) logging.getLogger().info("%s %s", PKG_NAME, PKG_VERSION)
langs = LANGS
langs["custom"] = WordList("custom", params.custom_words)
with ( with (
Cache(filepath=params.cache_file, no_load=params.cache) as cache, Cache(filepath=params.cache_file, no_load=params.cache) as cache,
TLDList(cache=cache, remote_uri=params.tld_list_uri) as tld_list, TLDList(cache=cache, remote_uri=params.tld_list_uri) as tld_list,
LANGS[params.lang] as word_list, langs[params.lang] as word_list,
): ):
factory = Factory(tld_list=tld_list, word_list=word_list, words=params.words) factory = Factory(tld_list=tld_list, word_list=word_list, words=params.words)
logging.getLogger().info( logging.getLogger().info(
@@ -29,3 +32,7 @@ def main() -> int:
else: else:
logging.getLogger().info(factory.random_domain()) logging.getLogger().info(factory.random_domain())
return 0 return 0
if __name__ == "__main__":
main()
+1292 -3
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -4,8 +4,8 @@ import shutil
import subprocess import subprocess
import typing import typing
from .tld_list import TLDList from cool_domain.tld_list import TLDList
from .word_list import WordList from cool_domain.word_list import WordList
class FactoryError(Exception): class FactoryError(Exception):
+1 -1
View File
@@ -2,7 +2,7 @@ import enum
import logging import logging
import typing import typing
from .params import Parameters from cool_domain.params import Parameters
class TermColor(enum.StrEnum): class TermColor(enum.StrEnum):
+17 -9
View File
@@ -5,8 +5,8 @@ import pathlib
import tempfile import tempfile
import typing import typing
from . import PKG_NAME from cool_domain import PKG_NAME
from .constants import LANGS from cool_domain.constants import LANGS
@dataclasses.dataclass(frozen=True, slots=True) @dataclasses.dataclass(frozen=True, slots=True)
@@ -19,7 +19,8 @@ class Parameters:
dig: bool = True dig: bool = True
lang: str = "english" lang: str = "english"
cache_file: str = str(pathlib.Path(tempfile.gettempdir()) / ".cool-domain-cache") cache_file: str = str(pathlib.Path(tempfile.gettempdir()) / ".cool-domain-cache")
tld_list_uri: str = "https://publicsuffix.org/list/public_suffix_list.dat" tld_list_uri: str = "https://data.iana.org/TLD/tlds-alpha-by-domain.txt"
custom_words: str = "words.txt"
@classmethod @classmethod
def from_namespace(cls, args: argparse.Namespace) -> "Parameters": def from_namespace(cls, args: argparse.Namespace) -> "Parameters":
@@ -98,12 +99,6 @@ def parse_parameters(args: typing.Sequence[str]) -> Parameters:
default=default_values.count, default=default_values.count,
help_txt="number of domains to generate", help_txt="number of domains to generate",
) )
parser.add_argument(
"--lang",
default=default_values.lang,
help="word list lang (default: english)",
choices=LANGS.keys(),
)
__add_arg_int( __add_arg_int(
parser, parser,
"--words", "--words",
@@ -111,6 +106,19 @@ def parse_parameters(args: typing.Sequence[str]) -> Parameters:
default=default_values.words, default=default_values.words,
help_txt="number of words per domain", help_txt="number of words per domain",
) )
parser.add_argument(
"--lang",
default=default_values.lang,
help="word list lang (default: english)",
choices=[*list(LANGS.keys()), "custom"],
)
__add_arg_str(
parser,
"--custom-words",
env_var="CUSTOM_WORDS",
default=default_values.custom_words,
help_txt="custom word list location",
)
__add_arg_bool( __add_arg_bool(
parser, parser,
"--dig", "--dig",
+7 -9
View File
@@ -5,7 +5,8 @@ import typing
import requests import requests
import unidecode import unidecode
from .cache import Cache from cool_domain.cache import Cache
from cool_domain.constants import BLACKLIST
class TLDError(Exception): class TLDError(Exception):
@@ -29,20 +30,17 @@ class TLDList:
raw_lines = response.content.decode().split("\n") raw_lines = response.content.decode().split("\n")
out_lines = [] out_lines = []
for line in raw_lines: for line in raw_lines:
stripped_line = line.strip() stripped_line = line.strip().lower()
if ( if (
len(stripped_line) len(stripped_line)
and not stripped_line.startswith("//") and not stripped_line.startswith("//")
and not stripped_line.startswith("*") and not stripped_line.startswith("*")
and not stripped_line.startswith("#")
and not stripped_line.startswith("xn--")
and "." not in stripped_line
and unidecode.unidecode(stripped_line) == stripped_line and unidecode.unidecode(stripped_line) == stripped_line
and stripped_line not in BLACKLIST
): ):
if "." in stripped_line:
for other in out_lines:
if stripped_line.endswith(other):
break
else:
out_lines += [stripped_line]
else:
out_lines += [stripped_line] out_lines += [stripped_line]
return out_lines return out_lines
+2 -2
View File
@@ -8,10 +8,10 @@ import unidecode
class WordList: class WordList:
__slots__ = ["__filepath", "__name", "logger", "words"] __slots__ = ["__filepath", "__name", "logger", "words"]
def __init__(self, name: str, path: str, filename: str) -> None: def __init__(self, name: str, path: str) -> None:
self.logger: logging.Logger = logging.getLogger(self.__class__.__name__) self.logger: logging.Logger = logging.getLogger(self.__class__.__name__)
self.__name = name self.__name = name
self.__filepath = pathlib.Path(__file__).parent / ".." / path / filename self.__filepath = pathlib.Path(__file__).parent / ".." / path
self.words: list[str] = [] self.words: list[str] = []
def open(self) -> None: def open(self) -> None:
+1 -1
View File
@@ -1,6 +1,6 @@
[project] [project]
name = "cool-domain" name = "cool-domain"
version = "1.1.2" version = "1.3.0"
description = "Add your description here" description = "Add your description here"
readme = "README.md" readme = "README.md"
requires-python = ">=3.12" requires-python = ">=3.12"
Generated
+1 -1
View File
@@ -86,7 +86,7 @@ wheels = [
[[package]] [[package]]
name = "cool-domain" name = "cool-domain"
version = "1.1.2" version = "1.3.0"
source = { editable = "." } source = { editable = "." }
dependencies = [ dependencies = [
{ name = "requests" }, { name = "requests" },