diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
new file mode 100644
index 0000000..9d76b83
--- /dev/null
+++ b/.github/workflows/main.yml
@@ -0,0 +1,38 @@
+name: main
+
+on:
+ push:
+ branches: [main]
+ pull_request:
+
+jobs:
+ main:
+ env:
+ POETRY_VIRTUALENVS_IN_PROJECT: true
+ runs-on: ubuntu-20.04
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-python@v2
+ with:
+ python-version: 3.8
+ - run: pip install poetry==1.1.7
+ - name: cache venv
+ uses: actions/cache@v2
+ with:
+ path: .venv
+ key: venv-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }}
+ - run: poetry install
+ - name: static code analysis
+ run: |
+ poetry run black --check
+ - run: poetry run pytest
+ - name: build package
+ run: |
+ make clean
+ make package
+ - uses: actions/upload-artifact@v2
+ with:
+ name: package
+ path: build/plugin_video_ipfs.zip
+ retention-days: 3
+ if-no-files-found: error
diff --git a/.gitignore b/.gitignore
index 3c6c035..1261a23 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,7 @@
/*.egg-info
/.pytest_cache
__pycache__
-/venv
+/.venv
+/dist
+/upload_build.sh
+/.vscode
\ No newline at end of file
diff --git a/Makefile b/Makefile
index 6067b43..9dd64b9 100644
--- a/Makefile
+++ b/Makefile
@@ -2,19 +2,6 @@
SOURCES=$(shell find . -name '*.py')
OUTPUT_PATH=build/plugin.video.ipfs
-venv:
- ( \
- virtualenv --python=python3.7 venv
- source venv/bin/activate; \
- pip install -r requirements.txt; \
- )
-
-test: install venv $(SOURCES)
- venv/bin/py.test
-
-install:
- venv/bin/python setup.py develop
-
clean:
rm -rf build
@@ -23,9 +10,10 @@ 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
+ poetry build
mkdir -p $(OUTPUT_PATH)/ipfs
- cp -r src/*.py $(OUTPUT_PATH)
- cp -r src/ipfs/*.py $(OUTPUT_PATH)/ipfs
+ tar -xzf dist/ipfs-video-kodi-*.tar.gz -C dist --wildcards '*/ipfs_video_kodi'
+ cp -r dist/*/ipfs_video_kodi/* $(OUTPUT_PATH)
cp -r resources $(OUTPUT_PATH)
cp icon.png $(OUTPUT_PATH)
cp addon.xml $(OUTPUT_PATH)
diff --git a/addon.xml b/addon.xml
index b7e1290..90779e9 100644
--- a/addon.xml
+++ b/addon.xml
@@ -1,23 +1,20 @@
-
-
-
-
-
-
- video
-
-
- IPFS video viewing plugin
- A plugin allowing access to IPFS video media.
- https://ipfs.video/
-
- icon.png
- fanart.jpg
- resources/screenshot-01.jpg
-
-
-
+
+
+
+
+
+
+ video
+
+
+ IPFS video viewing plugin
+ A plugin allowing access to IPFS video media.
+ https://ipfs.video/
+
+ icon.png
+ fanart.jpg
+ resources/screenshot-01.jpg
+
+
+
\ No newline at end of file
diff --git a/src/ipfs/__init__.py b/ipfs_video_kodi/ipfs/__init__.py
similarity index 60%
rename from src/ipfs/__init__.py
rename to ipfs_video_kodi/ipfs/__init__.py
index 2570e03..0ba6257 100644
--- a/src/ipfs/__init__.py
+++ b/ipfs_video_kodi/ipfs/__init__.py
@@ -1,36 +1,43 @@
+import random
import requests
-import random
+
def via(gateway):
return IPFS(gateway)
+def lower_keys(dictList):
+ return [{k.lower(): v for k, v in entry.items()} for entry in dictList]
+
class IPFS:
def __init__(self, gateway):
assert len(gateway) > 0
self._gateway = gateway
self._cache = {}
- def get(self, path, params):
- url = self._gateway + '/api/v0/dag/get'
+ def get_links(self, path, params):
+ url = self._gateway + "/api/v0/dag/get"
r = requests.get(url, params=params, timeout=20)
r.raise_for_status()
- return r
+ rjson = r.json()
+ return lower_keys(
+ filter(
+ lambda link: len(link["Name"]) > 0 and "/" in link["Hash"],
+ rjson["Links"],
+ )
+ )
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:
- #Drop 10 keys
+ # Drop 10 keys
for k in random.sample(self._cache.keys(), 10):
del self._cache[k]
return self._cache[hash]
- r = self.get('/api/v0/dag/get', params={"arg": hash})
- r.raise_for_status()
-
- entries = list(filter(lambda link: len(link['Name']) > 0 and '/' in link['Cid'], r.json()["links"]))
+ entries = self.get_links("/api/v0/dag/get", params={"arg": hash})
self._cache[hash] = entries
return entries
diff --git a/src/main.py b/ipfs_video_kodi/main.py
similarity index 70%
rename from src/main.py
rename to ipfs_video_kodi/main.py
index 3f58dbc..87ae7c0 100644
--- a/src/main.py
+++ b/ipfs_video_kodi/main.py
@@ -1,11 +1,12 @@
# -*- coding: utf-8 -*-
import sys
+
import xbmcgui
import xbmcplugin
try:
- #Python 3
- from urllib.parse import urlencode, parse_qsl
+ # Python 3
+ from urllib.parse import parse_qsl, urlencode
except ImportError:
from urllib import urlencode
from urlparse import parse_qsl
@@ -16,8 +17,9 @@
_url = sys.argv[0]
# Get the plugin handle as an integer number.
_handle = int(sys.argv[1])
-_rootCid = xbmcplugin.getSetting(_handle, 'rootCid')
-_ipfs = ipfs.via(xbmcplugin.getSetting(_handle, 'ipfsGateway'))
+_rootCid = xbmcplugin.getSetting(_handle, "rootCid")
+_ipfs = ipfs.via(xbmcplugin.getSetting(_handle, "ipfsGateway"))
+
def self_url(**kwargs):
"""
@@ -28,7 +30,8 @@ def self_url(**kwargs):
:return: plugin call URL
:rtype: str
"""
- return '{0}?{1}'.format(_url, urlencode(kwargs))
+ return "{0}?{1}".format(_url, urlencode(kwargs))
+
def list_node(cid):
"""
@@ -42,24 +45,23 @@ def list_node(cid):
xbmcplugin.setPluginCategory(_handle, cid)
# Set plugin content. It allows Kodi to select appropriate views
# for this type of content.
- xbmcplugin.setContent(_handle, 'videos')
+ xbmcplugin.setContent(_handle, "videos")
# Get the list of videos in the category.
links = _ipfs.list(cid)
for link in links:
- is_folder = len(_ipfs.list(link['Cid']['/'])) > 0
+ is_folder = len(_ipfs.list(link["hash"]["/"])) > 0
- list_item = xbmcgui.ListItem(label=link['Name'])
+ list_item = xbmcgui.ListItem(label=link["name"])
# Set additional info for the list item.
# 'mediatype' is needed for skin to display info for this ListItem correctly.
- list_item.setInfo('video', {'title': link['Name'],
- 'mediatype': 'video'})
+ list_item.setInfo("video", {"title": link["name"], "mediatype": "video"})
# TODO set thumbnails
# list_item.setArt({'thumb': video['thumb'], 'icon': video['thumb'], 'fanart': video['thumb']})
- list_item.setProperty('IsPlayable', ('false' if is_folder else 'true'))
+ list_item.setProperty("IsPlayable", ("false" if is_folder else "true"))
- url = self_url(action=('list' if is_folder else 'play'), cid=link['Cid']['/'])
+ url = self_url(action=("list" if is_folder else "play"), cid=link["hash"]["/"])
# Add our item to the Kodi virtual folder listing.
xbmcplugin.addDirectoryItem(_handle, url, list_item, is_folder)
# Add a sort method for the virtual folder items (alphabetically, ignore articles)
@@ -88,21 +90,21 @@ def router(paramstring):
"""
params = dict(parse_qsl(paramstring))
- #Default action
+ # Default action
if not params:
- params['action'] = 'list'
- params['cid'] = _rootCid
+ params["action"] = "list"
+ params["cid"] = _rootCid
# Check the parameters passed to the plugin
- if params['action'] == 'list':
- list_node(params['cid'])
- elif params['action'] == 'play':
- play_node(params['cid'])
+ if params["action"] == "list":
+ list_node(params["cid"])
+ elif params["action"] == "play":
+ play_node(params["cid"])
else:
- raise ValueError('Invalid paramstring: {0}!'.format(paramstring))
+ raise ValueError("Invalid paramstring: {0}!".format(paramstring))
-if __name__ == '__main__':
+if __name__ == "__main__":
# Call the router function and pass the plugin call parameters to it.
# We use string slicing to trim the leading '?' from the plugin call paramstring
router(sys.argv[2][1:])
diff --git a/poetry.lock b/poetry.lock
new file mode 100644
index 0000000..1c8d876
--- /dev/null
+++ b/poetry.lock
@@ -0,0 +1,339 @@
+[[package]]
+name = "atomicwrites"
+version = "1.4.0"
+description = "Atomic file writes."
+category = "dev"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+
+[[package]]
+name = "attrs"
+version = "21.4.0"
+description = "Classes Without Boilerplate"
+category = "dev"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+
+[package.extras]
+dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"]
+docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"]
+tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"]
+tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"]
+
+[[package]]
+name = "black"
+version = "21.12b0"
+description = "The uncompromising code formatter."
+category = "dev"
+optional = false
+python-versions = ">=3.6.2"
+
+[package.dependencies]
+click = ">=7.1.2"
+mypy-extensions = ">=0.4.3"
+pathspec = ">=0.9.0,<1"
+platformdirs = ">=2"
+tomli = ">=0.2.6,<2.0.0"
+typing-extensions = ">=3.10.0.0"
+
+[package.extras]
+colorama = ["colorama (>=0.4.3)"]
+d = ["aiohttp (>=3.7.4)"]
+jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
+python2 = ["typed-ast (>=1.4.3)"]
+uvloop = ["uvloop (>=0.15.2)"]
+
+[[package]]
+name = "certifi"
+version = "2021.10.8"
+description = "Python package for providing Mozilla's CA Bundle."
+category = "main"
+optional = false
+python-versions = "*"
+
+[[package]]
+name = "charset-normalizer"
+version = "2.0.9"
+description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
+category = "main"
+optional = false
+python-versions = ">=3.5.0"
+
+[package.extras]
+unicode_backport = ["unicodedata2"]
+
+[[package]]
+name = "click"
+version = "8.0.3"
+description = "Composable command line interface toolkit"
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+colorama = {version = "*", markers = "platform_system == \"Windows\""}
+
+[[package]]
+name = "colorama"
+version = "0.4.4"
+description = "Cross-platform colored terminal text."
+category = "dev"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+
+[[package]]
+name = "idna"
+version = "3.3"
+description = "Internationalized Domain Names in Applications (IDNA)"
+category = "main"
+optional = false
+python-versions = ">=3.5"
+
+[[package]]
+name = "iniconfig"
+version = "1.1.1"
+description = "iniconfig: brain-dead simple config-ini parsing"
+category = "dev"
+optional = false
+python-versions = "*"
+
+[[package]]
+name = "mypy-extensions"
+version = "0.4.3"
+description = "Experimental type system extensions for programs checked with the mypy typechecker."
+category = "dev"
+optional = false
+python-versions = "*"
+
+[[package]]
+name = "packaging"
+version = "21.3"
+description = "Core utilities for Python packages"
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
+
+[[package]]
+name = "pathspec"
+version = "0.9.0"
+description = "Utility library for gitignore style pattern matching of file paths."
+category = "dev"
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
+
+[[package]]
+name = "platformdirs"
+version = "2.4.1"
+description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+
+[package.extras]
+docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"]
+test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"]
+
+[[package]]
+name = "pluggy"
+version = "1.0.0"
+description = "plugin and hook calling mechanisms for python"
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+
+[package.extras]
+dev = ["pre-commit", "tox"]
+testing = ["pytest", "pytest-benchmark"]
+
+[[package]]
+name = "py"
+version = "1.11.0"
+description = "library with cross-python path, ini-parsing, io, code, log facilities"
+category = "dev"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+
+[[package]]
+name = "pyparsing"
+version = "3.0.6"
+description = "Python parsing module"
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+
+[package.extras]
+diagrams = ["jinja2", "railroad-diagrams"]
+
+[[package]]
+name = "pytest"
+version = "6.2.5"
+description = "pytest: simple powerful testing with Python"
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
+attrs = ">=19.2.0"
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+iniconfig = "*"
+packaging = "*"
+pluggy = ">=0.12,<2.0"
+py = ">=1.8.2"
+toml = "*"
+
+[package.extras]
+testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"]
+
+[[package]]
+name = "requests"
+version = "2.26.0"
+description = "Python HTTP for Humans."
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
+
+[package.dependencies]
+certifi = ">=2017.4.17"
+charset-normalizer = {version = ">=2.0.0,<2.1.0", markers = "python_version >= \"3\""}
+idna = {version = ">=2.5,<4", markers = "python_version >= \"3\""}
+urllib3 = ">=1.21.1,<1.27"
+
+[package.extras]
+socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"]
+use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"]
+
+[[package]]
+name = "toml"
+version = "0.10.2"
+description = "Python Library for Tom's Obvious, Minimal Language"
+category = "dev"
+optional = false
+python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
+
+[[package]]
+name = "tomli"
+version = "1.2.3"
+description = "A lil' TOML parser"
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+
+[[package]]
+name = "typing-extensions"
+version = "4.0.1"
+description = "Backported and Experimental Type Hints for Python 3.6+"
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+
+[[package]]
+name = "urllib3"
+version = "1.26.7"
+description = "HTTP library with thread-safe connection pooling, file post, and more."
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4"
+
+[package.extras]
+brotli = ["brotlipy (>=0.6.0)"]
+secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"]
+socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
+
+[metadata]
+lock-version = "1.1"
+python-versions = "~3.8"
+content-hash = "5efc61e5e11dbf61fcf9c5621f676c29778d9251713d95a85c05ade4f852e261"
+
+[metadata.files]
+atomicwrites = [
+ {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"},
+ {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"},
+]
+attrs = [
+ {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"},
+ {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"},
+]
+black = [
+ {file = "black-21.12b0-py3-none-any.whl", hash = "sha256:a615e69ae185e08fdd73e4715e260e2479c861b5740057fde6e8b4e3b7dd589f"},
+ {file = "black-21.12b0.tar.gz", hash = "sha256:77b80f693a569e2e527958459634f18df9b0ba2625ba4e0c2d5da5be42e6f2b3"},
+]
+certifi = [
+ {file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"},
+ {file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"},
+]
+charset-normalizer = [
+ {file = "charset-normalizer-2.0.9.tar.gz", hash = "sha256:b0b883e8e874edfdece9c28f314e3dd5badf067342e42fb162203335ae61aa2c"},
+ {file = "charset_normalizer-2.0.9-py3-none-any.whl", hash = "sha256:1eecaa09422db5be9e29d7fc65664e6c33bd06f9ced7838578ba40d58bdf3721"},
+]
+click = [
+ {file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"},
+ {file = "click-8.0.3.tar.gz", hash = "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"},
+]
+colorama = [
+ {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
+ {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
+]
+idna = [
+ {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"},
+ {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"},
+]
+iniconfig = [
+ {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
+ {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
+]
+mypy-extensions = [
+ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
+ {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
+]
+packaging = [
+ {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
+ {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
+]
+pathspec = [
+ {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"},
+ {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"},
+]
+platformdirs = [
+ {file = "platformdirs-2.4.1-py3-none-any.whl", hash = "sha256:1d7385c7db91728b83efd0ca99a5afb296cab9d0ed8313a45ed8ba17967ecfca"},
+ {file = "platformdirs-2.4.1.tar.gz", hash = "sha256:440633ddfebcc36264232365d7840a970e75e1018d15b4327d11f91909045fda"},
+]
+pluggy = [
+ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
+ {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
+]
+py = [
+ {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
+ {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
+]
+pyparsing = [
+ {file = "pyparsing-3.0.6-py3-none-any.whl", hash = "sha256:04ff808a5b90911829c55c4e26f75fa5ca8a2f5f36aa3a51f68e27033341d3e4"},
+ {file = "pyparsing-3.0.6.tar.gz", hash = "sha256:d9bdec0013ef1eb5a84ab39a3b3868911598afa494f5faa038647101504e2b81"},
+]
+pytest = [
+ {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"},
+ {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"},
+]
+requests = [
+ {file = "requests-2.26.0-py2.py3-none-any.whl", hash = "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24"},
+ {file = "requests-2.26.0.tar.gz", hash = "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"},
+]
+toml = [
+ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
+ {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
+]
+tomli = [
+ {file = "tomli-1.2.3-py3-none-any.whl", hash = "sha256:e3069e4be3ead9668e21cb9b074cd948f7b3113fd9c8bba083f48247aab8b11c"},
+ {file = "tomli-1.2.3.tar.gz", hash = "sha256:05b6166bff487dc068d322585c7ea4ef78deed501cc124060e0f238e89a9231f"},
+]
+typing-extensions = [
+ {file = "typing_extensions-4.0.1-py3-none-any.whl", hash = "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"},
+ {file = "typing_extensions-4.0.1.tar.gz", hash = "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e"},
+]
+urllib3 = [
+ {file = "urllib3-1.26.7-py2.py3-none-any.whl", hash = "sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844"},
+ {file = "urllib3-1.26.7.tar.gz", hash = "sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece"},
+]
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..1262938
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,18 @@
+[tool.poetry]
+name = "ipfs-video-kodi"
+version = "0.0.6"
+description = "Kodi plugin to view IPFS video files"
+authors = ["Bram Neijt "]
+license = "GPLv3"
+
+[tool.poetry.dependencies]
+python = "~3.8"
+requests = "^2.26.0"
+
+[tool.poetry.dev-dependencies]
+pytest = "^6.2.5"
+black = {version = "^21.12b0", allow-prereleases = true}
+
+[build-system]
+requires = ["poetry-core>=1.0.0"]
+build-backend = "poetry.core.masonry.api"
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index 9a55a62..0000000
--- a/requirements.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-
-requests
-
-pytest
diff --git a/resources/settings.xml b/resources/settings.xml
index ea805d4..9565bec 100644
--- a/resources/settings.xml
+++ b/resources/settings.xml
@@ -1,7 +1,7 @@
-
+
diff --git a/setup.py b/setup.py
deleted file mode 100644
index 5818e32..0000000
--- a/setup.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from setuptools import setup
-
-setup(name='ipfs-video-kodi',
- version='0.1',
- description='The funniest joke in the world',
- url='',
- author='Flying Circus',
- author_email='flyingcircus@example.com',
- license='MIT',
- packages=["src"],
- zip_safe=False)
diff --git a/test/test_ipfs.py b/test/test_ipfs.py
index b8ac98d..49797c7 100644
--- a/test/test_ipfs.py
+++ b/test/test_ipfs.py
@@ -1,22 +1,16 @@
# -*- coding: utf-8 -*-
import unittest
-import src.ipfs as ipfs
+import ipfs_video_kodi.ipfs as ipfs
-test_gateway = ipfs.via("http://51.15.122.1")
+test_gateway = ipfs.via("https://ipfs.io")
-class TestIpfsMethods(unittest.TestCase):
-
- def test_list_file_should_be_empty(self):
- a = test_gateway.list("QmTNdv6MBhCjcGY5tpabi7aCeLZL65tmDzW37J9ZrFbZfL")
- self.assertEqual(a, [])
-
- def test_list_directory_should_work(self):
- a = test_gateway.list("QmVZV84e6nSwfA8LppiS4KXKiAhpbqqGYzofHtecQjd9js")
- self.assertEqual(len(a), 1)
- self.assertEqual(a[0]['Name'], "pexel")
-
-
-
-if __name__ == '__main__':
- unittest.main()
+def test_list_directory_should_work():
+ a = test_gateway.list("Qme4QjkyZQuFtN2SDhELfXVshMyAEec53jaFQ8kR4maLeV")
+ assert len(a) == 1
+ assert (
+ a[0]["name"]
+ == "Alan Kay at OOPSLA 1997 - The computer revolution hasnt happened yet.webm"
+ )
+ b = test_gateway.list("QmYHDhsgUgdKSAimguGC92MzQ8VNFHZw3yp6kAHwiXCFLm")
+ assert len(b) == 3