dynamicdns 0.1.0rc0__tar.gz → 0.1.0rc3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ {
2
+ "editor.defaultFormatter": "charliermarsh.ruff",
3
+ "editor.rulers": [
4
+ 100
5
+ ],
6
+ "editor.formatOnSave": true,
7
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dynamicdns
3
- Version: 0.1.0rc0
3
+ Version: 0.1.0rc3
4
4
  Summary: Collection of Dynamic DNS providers
5
5
  Project-URL: Documentation, https://github.com/tr4nt0r/dynamicdns#readme
6
6
  Project-URL: Issues, https://github.com/tr4nt0r/dynamicdns/issues
@@ -33,7 +33,6 @@ Source = "https://github.com/tr4nt0r/dynamicdns"
33
33
 
34
34
  [tool.hatch.version]
35
35
  source = "regex_commit"
36
- commit_extra_args = ["-e"]
37
36
  path = "src/dynamicdns/__init__.py"
38
37
 
39
38
  [tool.hatch.envs.default]
@@ -44,12 +43,6 @@ dependencies = [
44
43
  "voluptuous==0.15.2"
45
44
  ]
46
45
 
47
- [tool.hatch.envs.hatch-static-analysis]
48
- config-path = "none"
49
- dependencies = [
50
- "ruff==0.13.2"
51
- ]
52
-
53
46
  [tool.hatch.envs.hatch-test]
54
47
  parallel = true
55
48
  extra-dependencies = [
@@ -93,3 +86,7 @@ convention = "numpy"
93
86
  [tool.ruff.format]
94
87
  quote-style = "double"
95
88
  indent-style = "space"
89
+
90
+ [tool.hatch.envs.hatch-static-analysis]
91
+ config-path = "none"
92
+ dependencies = ["ruff==0.13.2"]
@@ -2,12 +2,12 @@
2
2
  #
3
3
  # SPDX-License-Identifier: MIT
4
4
 
5
- from .providers import Provider, ProviderConf, providers
5
+ from .providers import Provider, ProviderConf, PROVIDERS
6
6
  from .updater import Updater
7
7
 
8
- __version__ = "0.1.0rc0"
8
+ __version__ = "0.1.0rc3"
9
9
  __all__ = [
10
- "providers",
10
+ "PROVIDERS",
11
11
  "Provider",
12
12
  "ProviderConf",
13
13
  "Updater",
@@ -2,7 +2,6 @@
2
2
 
3
3
  from typing import Final
4
4
 
5
- CONF_HOSTS: Final = "hosts"
6
5
  CONF_HOST: Final = "host"
7
6
  CONF_TOKEN: Final = "token"
8
7
  CONF_USERNAME: Final = "username"
@@ -13,3 +12,4 @@ CONF_VERBOSE: Final = "verbose"
13
12
  CONF_TXT: Final = "txt"
14
13
  CONF_CLEAR: Final = "clear"
15
14
  CONF_DOMAIN: Final = "domain"
15
+ CONF_URL: Final = "url"
@@ -16,6 +16,7 @@ from .const import (
16
16
  CONF_IPV6_ADDRESS,
17
17
  CONF_PASSWORD,
18
18
  CONF_TOKEN,
19
+ CONF_URL,
19
20
  CONF_USERNAME,
20
21
  )
21
22
 
@@ -23,11 +24,14 @@ from .const import (
23
24
  class Provider(StrEnum):
24
25
  """Dynamic DNS providers."""
25
26
 
26
- DUCKDNS = "duckdns"
27
- MYTHICBEASTS_IPV4 = "mythicbeasts_ipv4"
28
27
  ANYDNS = "anydns"
28
+ DUCKDNS = "duckdns"
29
29
  FREEDNS = "freedns"
30
30
  FREEDNS_IPV6 = "freedns_ipv6"
31
+ MYTHICBEASTS = "mythicbeasts"
32
+ NAMECHEAP = "namecheap"
33
+ NO_IP = "no_ip"
34
+ CUSTOM = "custom"
31
35
 
32
36
 
33
37
  @dataclass(frozen=True, kw_only=True)
@@ -43,13 +47,16 @@ class ProviderConf:
43
47
 
44
48
  def render_url(self, data: dict[str, str]) -> URL:
45
49
  """Render the provider URL with given data and remove unused query parameters."""
46
-
47
- url = URL(self.base_url)
50
+ url = URL(data.get(CONF_URL) or self.base_url)
48
51
  url = url.with_path(url.path.format(**data))
52
+ if url.user:
53
+ url = url.with_user(url.user.format(**data))
54
+ if url.password:
55
+ url = url.with_password(url.password.format(**data))
49
56
  return url % {k: data[v] for k, v in self.params.items() if v in data}
50
57
 
51
58
 
52
- providers: dict[Provider, ProviderConf] = {
59
+ PROVIDERS: dict[Provider, ProviderConf] = {
53
60
  Provider.DUCKDNS: ProviderConf(
54
61
  name="Duck DNS",
55
62
  base_url="https://www.duckdns.org/update?verbose=true",
@@ -67,8 +74,8 @@ providers: dict[Provider, ProviderConf] = {
67
74
  ),
68
75
  success_fn=lambda x: x.startswith("OK"),
69
76
  ),
70
- Provider.MYTHICBEASTS_IPV4: ProviderConf(
71
- name="Mythic Beasts IPv4",
77
+ Provider.MYTHICBEASTS: ProviderConf(
78
+ name="Mythic Beasts",
72
79
  base_url="https://ipv4.api.mythic-beasts.com/dns/v2/dynamic/{domain}",
73
80
  method="POST",
74
81
  params={"username": CONF_USERNAME, "password": CONF_PASSWORD},
@@ -77,31 +84,85 @@ providers: dict[Provider, ProviderConf] = {
77
84
  vol.Required(CONF_DOMAIN): str,
78
85
  vol.Required(CONF_USERNAME): str,
79
86
  vol.Required(CONF_PASSWORD): str,
80
- },
87
+ }
81
88
  ),
82
89
  ),
83
90
  Provider.ANYDNS: ProviderConf(
84
91
  name="AnyDNS.info",
85
92
  base_url="https://anydns.info/update.php",
86
- params={"host": CONF_HOST, "user": CONF_USERNAME, "password": CONF_PASSWORD},
93
+ params={
94
+ "host": CONF_DOMAIN,
95
+ "user": CONF_USERNAME,
96
+ "password": CONF_PASSWORD,
97
+ "ip": CONF_IP_ADDRESS,
98
+ "ip6": CONF_IPV6_ADDRESS,
99
+ },
87
100
  schema=vol.Schema(
88
101
  {
89
- vol.Required(CONF_HOST): str,
102
+ vol.Required(CONF_DOMAIN): str,
90
103
  vol.Required(CONF_USERNAME): str,
91
104
  vol.Required(CONF_PASSWORD): str,
92
105
  },
93
106
  ),
94
107
  ),
95
108
  Provider.FREEDNS: ProviderConf(
96
- name="FreeDNS IPv4",
109
+ name="FreeDNS",
97
110
  base_url="https://sync.afraid.org/u/{token}/",
111
+ params={"address": CONF_IP_ADDRESS},
98
112
  schema=vol.Schema({vol.Required(CONF_TOKEN): str}),
99
113
  success_fn=lambda x: x.startswith(("Updated", "No IP change")),
100
114
  ),
101
115
  Provider.FREEDNS_IPV6: ProviderConf(
102
116
  name="FreeDNS IPv6",
103
117
  base_url="https://v6.sync.afraid.org/u/{token}",
118
+ params={"address": CONF_IPV6_ADDRESS},
104
119
  schema=vol.Schema({vol.Required(CONF_TOKEN): str}),
105
120
  success_fn=lambda x: x.startswith(("Updated", "No IP change")),
106
121
  ),
122
+ Provider.NAMECHEAP: ProviderConf(
123
+ name="Namecheap",
124
+ base_url=(
125
+ "https://dynamicdns.park-your-domain.com/update?host={host}&domain={domain}"
126
+ "&password={password}&ip={ip_address}"
127
+ ),
128
+ params={
129
+ "host": CONF_HOST,
130
+ "domain": CONF_DOMAIN,
131
+ "password": CONF_PASSWORD,
132
+ "ip": CONF_IP_ADDRESS,
133
+ },
134
+ schema=vol.Schema(
135
+ {
136
+ vol.Required(CONF_HOST, default="@"): str,
137
+ vol.Required(CONF_DOMAIN): str,
138
+ vol.Required(CONF_PASSWORD): str,
139
+ }
140
+ ),
141
+ success_fn=lambda x: "<ErrCount>0</ErrCount>" in x,
142
+ ),
143
+ Provider.NO_IP: ProviderConf(
144
+ name="NO-IP.com",
145
+ base_url="https://{username}:{password}@dynupdate.no-ip.com/nic/update",
146
+ params={
147
+ "hostname": CONF_DOMAIN,
148
+ "myip": CONF_IP_ADDRESS,
149
+ },
150
+ schema=vol.Schema(
151
+ {
152
+ vol.Required(CONF_DOMAIN, default="all.ddnskey.com"): str,
153
+ vol.Required(CONF_USERNAME): str,
154
+ vol.Required(CONF_PASSWORD): str,
155
+ }
156
+ ),
157
+ success_fn=lambda x: x.startswith(("good", "nochg")),
158
+ ),
159
+ Provider.CUSTOM: ProviderConf(
160
+ name="Custom dynamic DNS provider",
161
+ base_url="{url}",
162
+ params={
163
+ "ip": CONF_IP_ADDRESS,
164
+ "ipv6": CONF_IPV6_ADDRESS,
165
+ },
166
+ schema=vol.Schema({vol.Required(CONF_URL): str}),
167
+ ),
107
168
  }
File without changes
@@ -6,7 +6,7 @@ import logging
6
6
 
7
7
  from aiohttp import ClientSession
8
8
 
9
- from .providers import Provider, providers
9
+ from .providers import Provider, PROVIDERS
10
10
 
11
11
  _LOGGER = logging.getLogger(__package__)
12
12
 
@@ -23,15 +23,16 @@ class Updater:
23
23
  """Initialize."""
24
24
 
25
25
  self.session = session
26
- self.method = providers[provider].method
27
- self.url = providers[provider].render_url(data)
28
- self.success = providers[provider].success_fn
26
+ self.provider = provider
27
+ self.method = PROVIDERS[provider].method
28
+ self.url = PROVIDERS[provider].render_url(data)
29
+ self.success = PROVIDERS[provider].success_fn
29
30
 
30
31
  async def update(self) -> bool:
31
32
  """Update the dynamic DNS record."""
32
33
 
33
34
  async with self.session.request(self.method, self.url) as res:
34
- _LOGGER.debug(await res.text())
35
+ _LOGGER.debug("[%s]: %s", self.provider.name, await res.text())
35
36
  return (
36
37
  self.success(await res.text()) if self.success is not None else res.ok
37
38
  )
@@ -1,4 +0,0 @@
1
- {
2
- "editor.defaultFormatter": "charliermarsh.ruff",
3
- "editor.rulers": [100],
4
- }
File without changes
File without changes
File without changes