diff --git a/Makefile b/Makefile index a8f4617..748ccdb 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,8 @@ SOURCES=$(shell find . -name '*.py') OUTPUT_PATH=build/plugin.video.ipfs +MY_VAR := $(shell echo whatever) + clean: rm -rf build rm -rf dist @@ -11,8 +13,7 @@ build/plugin_video_ipfs.zip: build cd build && zip -r plugin_video_ipfs.zip plugin.video.ipfs build: $(SOURCES) fanart.jpg icon.png addon.xml resources/settings.xml - VERSION=$(poetry version --short) - sed -i 's/id="plugin.video.ipfs" version="[^"]*"/id="plugin.video.ipfs" version="'${VERSION}'"/' addon.xml + sed -i 's/id="plugin.video.ipfs" version="[^"]*"/id="plugin.video.ipfs" version="'$(shell poetry version --short)'"/' addon.xml poetry build mkdir -p $(OUTPUT_PATH)/ipfs tar -xzf dist/ipfs-video-kodi-*.tar.gz -C dist --wildcards '*/ipfs_video_kodi' diff --git a/README.md b/README.md index 0ed6a3a..f3fe5c1 100644 --- a/README.md +++ b/README.md @@ -14,15 +14,18 @@ The main branch in github is _not_ installable as a kodi package, please use the # Viewing your own content - Install IPFS on your media player -- Use `ipfs add -r -w yourdirectory` to insert your directory +- Use `ipfs add -r -w yourdirectory` to insert your directory, remember the resulting CID - Configure plugin to have gateway point to `http://localhost:8080` -- Use the hash of the directory as the root CID in the plugin configuration +- Enter the CID of the directory as the root CID in the plugin configuration +- Optionally: + - Use `ipfs name publish ` to create an [IPNS](https://docs.ipfs.io/concepts/ipns/#example-ipns-setup-with-cli) record + - Enter `ipfs/` as the root CID in the plugin configuration # Develop -- `make venv` -- `make test` -- `make build` +- Create venv for development: `poetry install` +- Run the tests: `poetry run pytest` +- Build a release package: `make build` # License information diff --git a/addon.xml b/addon.xml index d00e8ee..c59b709 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + diff --git a/ipfs_video_kodi/ipfs/__init__.py b/ipfs_video_kodi/ipfs/__init__.py index 17e7976..fd9f6dc 100644 --- a/ipfs_video_kodi/ipfs/__init__.py +++ b/ipfs_video_kodi/ipfs/__init__.py @@ -1,7 +1,8 @@ import random - import requests +MAX_CACHE_SIZE = 100 + def via(gateway): return IPFS(gateway) @@ -17,7 +18,8 @@ def __init__(self, gateway): self._gateway = gateway self._cache = {} - def get_links(self, path, params): + def get_links(self, cid): + params = {"arg": cid} url = self._gateway + "/api/v0/dag/get" r = requests.get(url, params=params, timeout=20) r.raise_for_status() @@ -36,18 +38,35 @@ def get_links(self, path, params): i["hash"] = i["cid"] return link_list - def list(self, hash): - """Get the directory content of the given hash""" - assert type(hash) == str - if hash in self._cache: - if len(self._cache) > 50: + def resolve_ipns(self, cid): + params = {"arg": cid} + url = self._gateway + "/api/v0/name/resolve" + print(params) + r = requests.get(url, params=params, timeout=20) + r.raise_for_status() + rjson = r.json() + path = rjson.get("Path") or rjson.get("path") + assert path.startswith("/ipfs/"), "Should resolve to ipfs path" + return path[len("/ipfs/") :] + + def list(self, path): + """Get the directory content of the given path (ipns/hash or plain cid)""" + assert type(path) == str, "Argument path must be a string" + cid = ( + self.resolve_ipns(path[len("/ipns/") :]) + if path.startswith("/ipns/") + else path + ) + + if cid in self._cache: + if len(self._cache) > MAX_CACHE_SIZE: # Drop 10 keys for k in random.sample(self._cache.keys(), 10): del self._cache[k] - return self._cache[hash] + return self._cache[cid] - entries = self.get_links("/api/v0/dag/get", params={"arg": hash}) - self._cache[hash] = entries + entries = self.get_links(cid) + self._cache[cid] = entries return entries def link(self, hash): diff --git a/tests/test_ipfs.py b/tests/test_ipfs.py index 4454773..768884e 100644 --- a/tests/test_ipfs.py +++ b/tests/test_ipfs.py @@ -1,11 +1,18 @@ # -*- coding: utf-8 -*- import pytest - import ipfs_video_kodi.ipfs as ipfs test_gateway = ipfs.via("https://ipfs.io") +@pytest.mark.skip(reason="ipns link is not maintained") +def test_list_ipns_should_work(): + a = test_gateway.list( + "/ipns/k51qzi5uqu5dhlmx2xfqsn7f94tq2gp1inr9yu7cm8dsmycdwk2xp6aykqzf5i" + ) + assert len(a) == 3 + + def test_list_directory_should_work(): a = test_gateway.list("Qme4QjkyZQuFtN2SDhELfXVshMyAEec53jaFQ8kR4maLeV") assert len(a) == 1