udyndns 0.0.1__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.
- udyndns-0.0.1/LICENSE +13 -0
- udyndns-0.0.1/PKG-INFO +17 -0
- udyndns-0.0.1/README.md +0 -0
- udyndns-0.0.1/setup.cfg +4 -0
- udyndns-0.0.1/setup.py +28 -0
- udyndns-0.0.1/udyndns/__init__.py +110 -0
- udyndns-0.0.1/udyndns/__main__.py +35 -0
- udyndns-0.0.1/udyndns/version.py +1 -0
- udyndns-0.0.1/udyndns.egg-info/PKG-INFO +17 -0
- udyndns-0.0.1/udyndns.egg-info/SOURCES.txt +11 -0
- udyndns-0.0.1/udyndns.egg-info/dependency_links.txt +1 -0
- udyndns-0.0.1/udyndns.egg-info/requires.txt +2 -0
- udyndns-0.0.1/udyndns.egg-info/top_level.txt +1 -0
udyndns-0.0.1/LICENSE
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
|
2
|
+
Version 2, December 2004
|
|
3
|
+
|
|
4
|
+
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
|
5
|
+
|
|
6
|
+
Everyone is permitted to copy and distribute verbatim or modified
|
|
7
|
+
copies of this license document, and changing it is allowed as long
|
|
8
|
+
as the name is changed.
|
|
9
|
+
|
|
10
|
+
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
|
11
|
+
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
12
|
+
|
|
13
|
+
0. You just DO WHAT THE FUCK YOU WANT TO.
|
udyndns-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: udyndns
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: A very simple OVH dyndns client to workaround difficulties with Ubiquity unadyn...
|
|
5
|
+
Home-page: https://github.com/KurisuD/udyndns
|
|
6
|
+
Author: KurisuD
|
|
7
|
+
Author-email: KurisuD@pypi.darnand.net
|
|
8
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
10
|
+
Classifier: License :: Public Domain
|
|
11
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
12
|
+
Classifier: Topic :: Home Automation
|
|
13
|
+
Classifier: Topic :: Internet :: Name Service (DNS)
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
Requires-Dist: aiounifi
|
|
17
|
+
Requires-Dist: pap_logger
|
udyndns-0.0.1/README.md
ADDED
|
File without changes
|
udyndns-0.0.1/setup.cfg
ADDED
udyndns-0.0.1/setup.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# coding=utf-8
|
|
2
|
+
import setuptools
|
|
3
|
+
|
|
4
|
+
from udyndns.version import __version__
|
|
5
|
+
|
|
6
|
+
with open("README.md") as fh:
|
|
7
|
+
long_description = fh.read()
|
|
8
|
+
|
|
9
|
+
setuptools.setup(
|
|
10
|
+
name="udyndns",
|
|
11
|
+
version=__version__,
|
|
12
|
+
author="KurisuD",
|
|
13
|
+
author_email="KurisuD@pypi.darnand.net",
|
|
14
|
+
description="A very simple OVH dyndns client to workaround difficulties with Ubiquity unadyn...",
|
|
15
|
+
long_description=long_description,
|
|
16
|
+
long_description_content_type="text/markdown",
|
|
17
|
+
url="https://github.com/KurisuD/udyndns",
|
|
18
|
+
packages=setuptools.find_packages(),
|
|
19
|
+
install_requires=['aiounifi', 'pap_logger'],
|
|
20
|
+
classifiers=[
|
|
21
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
22
|
+
"Programming Language :: Python :: 3.10",
|
|
23
|
+
"License :: Public Domain",
|
|
24
|
+
"Operating System :: POSIX :: Linux",
|
|
25
|
+
"Topic :: Home Automation",
|
|
26
|
+
"Topic :: Internet :: Name Service (DNS)"
|
|
27
|
+
],
|
|
28
|
+
)
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import logging
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
import aiounifi
|
|
6
|
+
import requests
|
|
7
|
+
from aiohttp import ClientSession
|
|
8
|
+
from aiounifi.controller import Controller
|
|
9
|
+
from aiounifi.models.configuration import Configuration
|
|
10
|
+
from requests.auth import HTTPBasicAuth
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
async def get_wan_ip(host: str, port: int, username: str, password: str, timeout: int = 10) -> [Optional[str]]:
|
|
14
|
+
"""
|
|
15
|
+
obtains the WAN IP address of the unifi gateway
|
|
16
|
+
|
|
17
|
+
:param host: hostname or ip address of your unifi gateway / dream machine / ...
|
|
18
|
+
:param port: port to your unifi gateway / dream machine / ...
|
|
19
|
+
:param username: username to authenticate on your unifi device.
|
|
20
|
+
:param password: password to authenticate on your unifi device.
|
|
21
|
+
:param timeout: number of seconds to wait for your unifi device to respond.
|
|
22
|
+
:return: the WAN IP address of the unifi gateway / dream machine / ...
|
|
23
|
+
:type host: str
|
|
24
|
+
:type port: int
|
|
25
|
+
:type username: str
|
|
26
|
+
:type password: str
|
|
27
|
+
:type timeout: int
|
|
28
|
+
:rtype: str | None
|
|
29
|
+
|
|
30
|
+
"""
|
|
31
|
+
async with ClientSession() as _session:
|
|
32
|
+
_config = Configuration(session=_session, host=host, username=username, port=port, password=password)
|
|
33
|
+
api = Controller(config=_config)
|
|
34
|
+
try:
|
|
35
|
+
async with asyncio.timeout(10):
|
|
36
|
+
await api.login()
|
|
37
|
+
except aiounifi.Unauthorized as err:
|
|
38
|
+
logging.warning(f"Connected to {host}:{port} but user {username} is not registered: {err}")
|
|
39
|
+
|
|
40
|
+
except (
|
|
41
|
+
TimeoutError,
|
|
42
|
+
aiounifi.BadGateway,
|
|
43
|
+
aiounifi.Forbidden,
|
|
44
|
+
aiounifi.ServiceUnavailable,
|
|
45
|
+
aiounifi.RequestError,
|
|
46
|
+
aiounifi.ResponseError,
|
|
47
|
+
) as err:
|
|
48
|
+
logging.error(f"Error connecting to the UniFi Network at {host}:{port}: {err}")
|
|
49
|
+
return None
|
|
50
|
+
_proxy_network_str = "/proxy/network" if api.connectivity.is_unifi_os else ""
|
|
51
|
+
health_data = await _session.get(
|
|
52
|
+
f"https://{host}:{port}{_proxy_network_str}/api/s/default/stat/health",
|
|
53
|
+
headers={"Accept": "application/json",
|
|
54
|
+
"Content-Type": "application/json"},
|
|
55
|
+
timeout=timeout,
|
|
56
|
+
ssl=_config.ssl_context
|
|
57
|
+
)
|
|
58
|
+
health = await health_data.json()
|
|
59
|
+
wan_ip = [subsystem for subsystem in health['data'] if subsystem["subsystem"] == "wan"][0]["wan_ip"]
|
|
60
|
+
logging.info(f"WAN IP for {host}:{port}: {wan_ip}")
|
|
61
|
+
return wan_ip
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def update_ovh_dyn_dns(fqdn: str, ip: str, username: str, password: str) -> bool:
|
|
65
|
+
"""
|
|
66
|
+
Updates the OVH Dyndns's registered wan ip address for your domain, if necessary.
|
|
67
|
+
:param fqdn: The fully qualified domain name to be updated.
|
|
68
|
+
:param ip: the wan ip address to be used for the update.
|
|
69
|
+
:param username: your ovh dyndns username for updating this fqdn.
|
|
70
|
+
:param password: your ovh dyndns password for updating this fqdn.
|
|
71
|
+
:return: True on success, False otherwise.
|
|
72
|
+
:type fqdn: str
|
|
73
|
+
:type ip: str
|
|
74
|
+
:type username: str
|
|
75
|
+
:type password: str
|
|
76
|
+
:rtype: bool
|
|
77
|
+
"""
|
|
78
|
+
logging.info(f"Checking dynamic DNS for {fqdn}")
|
|
79
|
+
session = requests.Session()
|
|
80
|
+
session.auth = HTTPBasicAuth(username=username, password=password)
|
|
81
|
+
current_ip_url = f"https://www.ovh.com/nic/update?system=dyndns&hostname={fqdn}"
|
|
82
|
+
current_ip_resp = session.get(current_ip_url)
|
|
83
|
+
if current_ip_resp.ok:
|
|
84
|
+
logging.info(current_ip_resp.status_code)
|
|
85
|
+
logging.info(current_ip_resp.text)
|
|
86
|
+
current = current_ip_resp.text.split(" ")[1].strip()
|
|
87
|
+
if current != ip:
|
|
88
|
+
logging.info(f"Need to update IP from '{current}' to '{ip}'")
|
|
89
|
+
new_ip_url = f"{current_ip_url}&myip={ip}"
|
|
90
|
+
logging.info(new_ip_url)
|
|
91
|
+
new_ip_resp = session.get(new_ip_url)
|
|
92
|
+
if new_ip_resp.ok:
|
|
93
|
+
logging.info(f"New IP results: {new_ip_resp.text}")
|
|
94
|
+
return True
|
|
95
|
+
else:
|
|
96
|
+
logging.warning(new_ip_resp.status_code)
|
|
97
|
+
logging.warning(new_ip_resp.reason)
|
|
98
|
+
return False
|
|
99
|
+
else:
|
|
100
|
+
logging.info(f"Our unifi API retrieved IP {ip} is the same as our current IP: {current}")
|
|
101
|
+
return True
|
|
102
|
+
else:
|
|
103
|
+
logging.error(f"Unable to authenticate to the {current_ip_url}")
|
|
104
|
+
logging.error(current_ip_resp.status_code)
|
|
105
|
+
logging.error(current_ip_resp.reason)
|
|
106
|
+
logging.error(current_ip_resp.text)
|
|
107
|
+
return False
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
__all__ = ["get_wan_ip", "update_ovh_dyn_dns"]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import json
|
|
3
|
+
import logging
|
|
4
|
+
import sys
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from __init__ import get_wan_ip, update_ovh_dyn_dns
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def main():
|
|
11
|
+
"""
|
|
12
|
+
Updates OVH dyndns based on the WAN IP retrieved from the unifi API since unadyn is so stubbornly unable to do so.
|
|
13
|
+
"""
|
|
14
|
+
udyndns_config_file = Path("~").expanduser() / ".udyndns.json"
|
|
15
|
+
if not udyndns_config_file.exists():
|
|
16
|
+
raise FileNotFoundError(f"{udyndns_config_file} not found")
|
|
17
|
+
for fqdn, config in json.loads(udyndns_config_file.read_text()).items():
|
|
18
|
+
unifi_config = config["unifi"]
|
|
19
|
+
wan_ip = asyncio.run(get_wan_ip(**unifi_config))
|
|
20
|
+
if wan_ip:
|
|
21
|
+
ovh_config = config["ovh"]
|
|
22
|
+
ovh_config.update({"fqdn": fqdn, "ip": wan_ip})
|
|
23
|
+
logging.info(f"Will check and update {fqdn} with {wan_ip} if necessary")
|
|
24
|
+
update_ovh_dyn_dns(**ovh_config)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
if __name__ == '__main__':
|
|
28
|
+
from pap_logger import PaPLogger
|
|
29
|
+
|
|
30
|
+
p = PaPLogger(level=logging.INFO)
|
|
31
|
+
try:
|
|
32
|
+
main()
|
|
33
|
+
except Exception as e:
|
|
34
|
+
logging.error(f"Sorry, we could not proceed: {e}")
|
|
35
|
+
sys.exit(1)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '0.0.1'
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: udyndns
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: A very simple OVH dyndns client to workaround difficulties with Ubiquity unadyn...
|
|
5
|
+
Home-page: https://github.com/KurisuD/udyndns
|
|
6
|
+
Author: KurisuD
|
|
7
|
+
Author-email: KurisuD@pypi.darnand.net
|
|
8
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
10
|
+
Classifier: License :: Public Domain
|
|
11
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
12
|
+
Classifier: Topic :: Home Automation
|
|
13
|
+
Classifier: Topic :: Internet :: Name Service (DNS)
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
Requires-Dist: aiounifi
|
|
17
|
+
Requires-Dist: pap_logger
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
setup.py
|
|
4
|
+
udyndns/__init__.py
|
|
5
|
+
udyndns/__main__.py
|
|
6
|
+
udyndns/version.py
|
|
7
|
+
udyndns.egg-info/PKG-INFO
|
|
8
|
+
udyndns.egg-info/SOURCES.txt
|
|
9
|
+
udyndns.egg-info/dependency_links.txt
|
|
10
|
+
udyndns.egg-info/requires.txt
|
|
11
|
+
udyndns.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
udyndns
|