From 53c4c54606bfb0e737d765fa06d435a32bf5359a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Elio=20Petten=C3=B2?= Date: Wed, 27 Dec 2023 23:35:37 +0000 Subject: [PATCH] Change the JSON result format to include a timestamp. --- ipv6_in_real_life/data_structures.py | 41 +-------------------- ipv6_in_real_life/json.py | 55 ++++++++++++++++++++++++++++ manual_generate.py | 6 ++- 3 files changed, 60 insertions(+), 42 deletions(-) create mode 100644 ipv6_in_real_life/json.py diff --git a/ipv6_in_real_life/data_structures.py b/ipv6_in_real_life/data_structures.py index 137994c..99aa36f 100644 --- a/ipv6_in_real_life/data_structures.py +++ b/ipv6_in_real_life/data_structures.py @@ -5,9 +5,8 @@ import asyncio import dataclasses import datetime -import json import logging -from typing import Any, Dict, Iterable, List, Optional, Sequence, Union +from typing import Any, Dict, Iterable, List, Optional, Sequence import aiodns import pycountry @@ -16,8 +15,6 @@ _LOGGER = logging.getLogger(__name__) -HostJson = Dict[str, Union[bool, str, None]] - @dataclasses.dataclass class Host: @@ -51,16 +48,6 @@ async def resolve(self, resolver: aiodns.DNSResolver) -> None: ] self.has_ipv6_address = bool(valid_ipv6) - def as_json(self) -> HostJson: - return { - "name": self.name, - "has_ipv4_address": self.has_ipv4_address, - "has_ipv6_address": self.has_ipv6_address, - } - - -EntityJson = Dict[str, Union[str, List[HostJson], HostJson]] - @dataclasses.dataclass class Entity: @@ -93,18 +80,6 @@ async def resolve(self, resolver: aiodns.DNSResolver) -> None: host.has_ipv6_address for host in self.additional_hosts ) - def as_dict( - self, - ) -> EntityJson: - return { - "name": self.name, - "main_host": self.main_host.as_json(), - "additional_hosts": [host.as_json() for host in self.additional_hosts], - } - - -CategoryJson = List[EntityJson] - @dataclasses.dataclass class Category: @@ -127,12 +102,6 @@ def ready_percentage(self) -> str: ready_ratio = self.ready_count / self.total_count return f"{ready_ratio:.0%}" - def as_json(self) -> CategoryJson: - return [entity.as_dict() for entity in self.entities] - - -CountryDataJson = Dict[str, CategoryJson] - @dataclasses.dataclass class CountryData: @@ -151,9 +120,6 @@ def register(self, entity: Entity) -> None: self.categories[entity.category] = Category(entity.category) self.categories[entity.category].register(entity) - def as_json(self) -> CountryDataJson: - return {key: category.as_json() for key, category in self.categories.items()} - @dataclasses.dataclass class Source: @@ -181,8 +147,3 @@ async def resolve_all(self) -> None: ) self.last_resolved = datetime.datetime.now() - - def as_json(self) -> str: - return json.dumps( - {code: country.as_json() for code, country in self.countries_data.items()} - ) diff --git a/ipv6_in_real_life/json.py b/ipv6_in_real_life/json.py new file mode 100644 index 0000000..cfe11ce --- /dev/null +++ b/ipv6_in_real_life/json.py @@ -0,0 +1,55 @@ +# SPDX-FileCopyrightText: 2021 Diego Elio Pettenò +# +# SPDX-License-Identifier: 0BSD + +import json +import time +from typing import Dict, List, Union + +from . import data_structures + +HostJson = Dict[str, Union[bool, str, None]] +EntityJson = Dict[str, Union[str, List[HostJson], HostJson]] +CategoryJson = List[EntityJson] +CountryDataJson = Dict[str, CategoryJson] +SourceJson = Dict[str, CountryDataJson] + + +def host_to_json(host: data_structures.Host) -> HostJson: + return { + "name": host.name, + "has_ipv4_address": host.has_ipv4_address, + "has_ipv6_address": host.has_ipv6_address, + } + + +def entity_to_json(entity: data_structures.Entity) -> EntityJson: + return { + "name": entity.name, + "main_host": host_to_json(entity.main_host), + "additional_hosts": [host_to_json(host) for host in entity.additional_hosts], + } + + +def category_to_json(category: data_structures.Category) -> CategoryJson: + return [entity_to_json(entity) for entity in category.entities] + + +def country_data_to_json(country_data: data_structures.CountryData) -> CountryDataJson: + return { + key: category_to_json(category) + for key, category in country_data.categories.items() + } + + +def source_to_json(source: data_structures.Source) -> SourceJson: + return { + code: country_data_to_json(country) + for code, country in source.countries_data.items() + } + + +def generate_json(source: data_structures.Source) -> str: + return json.dumps( + {"results": source_to_json(source), "timestamp": int(time.time())} + ) diff --git a/manual_generate.py b/manual_generate.py index b8060e9..48655b4 100644 --- a/manual_generate.py +++ b/manual_generate.py @@ -9,7 +9,7 @@ import click import click_log -from ipv6_in_real_life import data_input, observability, render +from ipv6_in_real_life import data_input, json, observability, render click_log.basic_config() @@ -28,7 +28,9 @@ async def amain( await source.resolve_all() try: - (output_directory / "ipv6-in-real-life.json").write_text(source.as_json()) + (output_directory / "ipv6-in-real-life.json").write_text( + json.generate_json(source) + ) if not json_only: (output_directory / "index.html").write_text(render.index(source)) (output_directory / "details.html").write_text(render.details(source))