From db1e1cabf67a14cd39f7c80b42941d8ca8dcdc1b Mon Sep 17 00:00:00 2001
From: Adar Nimrod <nimrod@shore.co.il>
Date: Wed, 1 May 2019 16:48:09 +0300
Subject: [PATCH] Complete refactor and reworked usage.

The usage is completely replaced. Now locally I run inside a pipenv and
remotely using Docker.

- Use Supersonic as the Cron daemon.
- Run locally using pipenv.
- Run remotely using Docker (and docker-compose).
- Automate tasks using pipenv custom script shortcuts.
- Updated pre-commit hooks, added yamllint hook.
- Added license.
- Updated README.
---
 .dockerignore           |   4 +
 .envrc                  |   2 +
 .pre-commit-config.yaml |  30 ++-
 Dockerfile              |  17 ++
 LICENSE.txt             |  21 ++
 Pipfile                 |  19 ++
 Pipfile.lock            | 426 ++++++++++++++++++++++++++++++++++++++++
 README.md               |  41 ++--
 ansible.cfg             |  18 --
 crontab                 |   1 +
 db/.gitkeep             |   0
 docker-compose.yml      |  14 ++
 playbook.yml            |  43 ----
 poca.xml                |   4 +-
 receiver                |   5 -
 requirements.yml        |   3 -
 roles/.gitkeep          |   0
 tox.ini                 |  40 ----
 18 files changed, 542 insertions(+), 146 deletions(-)
 create mode 100644 .dockerignore
 create mode 100644 .envrc
 create mode 100644 Dockerfile
 create mode 100644 LICENSE.txt
 create mode 100644 Pipfile
 create mode 100644 Pipfile.lock
 delete mode 100644 ansible.cfg
 create mode 100644 crontab
 delete mode 100644 db/.gitkeep
 create mode 100644 docker-compose.yml
 delete mode 100644 playbook.yml
 delete mode 100755 receiver
 delete mode 100644 requirements.yml
 delete mode 100644 roles/.gitkeep
 delete mode 100644 tox.ini

diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..f507923
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,4 @@
+*
+!Pipfile*
+!poca.xml
+!crontab
diff --git a/.envrc b/.envrc
new file mode 100644
index 0000000..f270360
--- /dev/null
+++ b/.envrc
@@ -0,0 +1,2 @@
+source_up
+layout pipenv
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 58d620d..8c234b0 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,19 +1,15 @@
--   repo: https://github.com/pre-commit/pre-commit-hooks
-    sha: v0.7.1
+---
+repos:
+  - repo: https://github.com/pre-commit/pre-commit-hooks
+    rev: v2.2.1
     hooks:
-    -   id: check-added-large-files
-    -   id: check-yaml
-    -   id: check-merge-conflict
--   repo: https://github.com/willthames/ansible-lint
-    sha: v3.4.13
+      - id: check-yaml
+      - id: check-xml
+      - id: check-added-large-files
+      - id: check-merge-conflict
+      - id: check-symlinks
+      - id: trailing-whitespace
+  - repo: https://github.com/adrienverge/yamllint
+    rev: v1.15.0
     hooks:
-    -   id: ansible-lint
-        files: playbook\.yml
-        args: ['--exclude=roles']
--   repo: https://github.com/adarnimrod/shell-pre-commit
-    sha: v0.5.4
-    hooks:
-    -   id: shell-lint
-        files: receiver
-    -   id: shellcheck
-        files: receiver
+      - id: yamllint
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..6e28155
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,17 @@
+FROM adarnimrod/cron as supersonic
+
+FROM python:3.7-alpine
+COPY --from=supersonic /usr/local/bin/supersonic /usr/local/bin/
+RUN pip install --no-cache-dir pipenv
+COPY Pipfile* /poquita/
+WORKDIR /poquita
+RUN apk add --update --no-cache --virtual .lxml-build build-base libxslt-dev && \
+    pipenv install --deploy --system && \
+    apk del .lxml-build && \
+    apk add --update --no-cache --virtual .lxml-runtime libxml2 libxslt
+COPY --chown=root:root crontab /poquita/
+COPY --chown=root:root poca.xml /poquita/
+VOLUME /poquita/db/ /poquita/Podcasts/
+CMD [ "supersonic", "crontab" ]
+USER nobody
+HEALTHCHECK CMD pgrep supersonic
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..17196c5
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019 Adar Nimrod
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/Pipfile b/Pipfile
new file mode 100644
index 0000000..7c8d7b6
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,19 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[dev-packages]
+pre-commit = "*"
+docker-compose = "*"
+
+[packages]
+poca = "*"
+
+[requires]
+python_version = "3.7"
+
+[scripts]
+deploy = "docker-compose up --detach --build --remove-orphans"
+subscribe = "poca-subscribe -c ."
+lint = "pre-commit"
diff --git a/Pipfile.lock b/Pipfile.lock
new file mode 100644
index 0000000..0cb4883
--- /dev/null
+++ b/Pipfile.lock
@@ -0,0 +1,426 @@
+{
+    "_meta": {
+        "hash": {
+            "sha256": "467c199d378be775568e3fa1965a6f404e3c8a4bf03c1bfdc25fe8c0e01f4194"
+        },
+        "pipfile-spec": 6,
+        "requires": {
+            "python_version": "3.7"
+        },
+        "sources": [
+            {
+                "name": "pypi",
+                "url": "https://pypi.org/simple",
+                "verify_ssl": true
+            }
+        ]
+    },
+    "default": {
+        "certifi": {
+            "hashes": [
+                "sha256:59b7658e26ca9c7339e00f8f4636cdfe59d34fa37b9b04f6f9e9926b3cece1a5",
+                "sha256:b26104d6835d1f5e49452a26eb2ff87fe7090b89dfcaee5ea2212697e1e1d7ae"
+            ],
+            "version": "==2019.3.9"
+        },
+        "chardet": {
+            "hashes": [
+                "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
+                "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
+            ],
+            "version": "==3.0.4"
+        },
+        "feedparser": {
+            "hashes": [
+                "sha256:bd030652c2d08532c034c27fcd7c85868e7fa3cb2b17f230a44a6bbc92519bf9",
+                "sha256:cd2485472e41471632ed3029d44033ee420ad0b57111db95c240c9160a85831c",
+                "sha256:ce875495c90ebd74b179855449040003a1beb40cd13d5f037a0654251e260b02"
+            ],
+            "version": "==5.2.1"
+        },
+        "idna": {
+            "hashes": [
+                "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407",
+                "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"
+            ],
+            "version": "==2.8"
+        },
+        "lxml": {
+            "hashes": [
+                "sha256:03984196d00670b2ab14ae0ea83d5cc0cfa4f5a42558afa9ab5fa745995328f5",
+                "sha256:0815b0c9f897468de6a386dc15917a0becf48cc92425613aa8bbfc7f0f82951f",
+                "sha256:175f3825f075cf02d15099eb52658457cf0ff103dcf11512b5d2583e1d40f58b",
+                "sha256:30e14c62d88d1e01a26936ecd1c6e784d4afc9aa002bba4321c5897937112616",
+                "sha256:3210da6f36cf4b835ff1be853962b22cc354d506f493b67a4303c88bbb40d57b",
+                "sha256:40f60819fbd5bad6e191ba1329bfafa09ab7f3f174b3d034d413ef5266963294",
+                "sha256:43b26a865a61549919f8a42e094dfdb62847113cf776d84bd6b60e4e3fc20ea3",
+                "sha256:4a03dd682f8e35a10234904e0b9508d705ff98cf962c5851ed052e9340df3d90",
+                "sha256:62f382cddf3d2e52cf266e161aa522d54fd624b8cc567bc18f573d9d50d40e8e",
+                "sha256:7b98f0325be8450da70aa4a796c4f06852949fe031878b4aa1d6c417a412f314",
+                "sha256:846a0739e595871041385d86d12af4b6999f921359b38affb99cdd6b54219a8f",
+                "sha256:a3080470559938a09a5d0ec558c005282e99ac77bf8211fb7b9a5c66390acd8d",
+                "sha256:ad841b78a476623955da270ab8d207c3c694aa5eba71f4792f65926dc46c6ee8",
+                "sha256:afdd75d9735e44c639ffd6258ce04a2de3b208f148072c02478162d0944d9da3",
+                "sha256:b4fbf9b552faff54742bcd0791ab1da5863363fb19047e68f6592be1ac2dab33",
+                "sha256:b90c4e32d6ec089d3fa3518436bdf5ce4d902a0787dbd9bb09f37afe8b994317",
+                "sha256:b91cfe4438c741aeff662d413fd2808ac901cc6229c838236840d11de4586d63",
+                "sha256:bdb0593a42070b0a5f138b79b872289ee73c8e25b3f0bea6564e795b55b6bcdd",
+                "sha256:c4e4bca2bb68ce22320297dfa1a7bf070a5b20bcbaec4ee023f83d2f6e76496f",
+                "sha256:cec4ab14af9eae8501be3266ff50c3c2aecc017ba1e86c160209bb4f0423df6a",
+                "sha256:e83b4b2bf029f5104bc1227dbb7bf5ace6fd8fabaebffcd4f8106fafc69fc45f",
+                "sha256:e995b3734a46d41ae60b6097f7c51ba9958648c6d1e0935b7e0ee446ee4abe22",
+                "sha256:f679d93dec7f7210575c85379a31322df4c46496f184ef650d3aba1484b38a2d",
+                "sha256:fd213bb5166e46974f113c8228daaef1732abc47cb561ce9c4c8eaed4bd3b09b",
+                "sha256:fdcb57b906dbc1f80666e6290e794ab8fb959a2e17aa5aee1758a85d1da4533f",
+                "sha256:ff424b01d090ffe1947ec7432b07f536912e0300458f9a7f48ea217dd8362b86"
+            ],
+            "version": "==4.3.3"
+        },
+        "mutagen": {
+            "hashes": [
+                "sha256:bb61e2456f59a9a4a259fbc08def6d01ba45a42da8eeaa97d00633b0ec5de71c"
+            ],
+            "version": "==1.42.0"
+        },
+        "poca": {
+            "hashes": [
+                "sha256:31f69c19870b712995cfc1e0788ba2b1c8fe649832d851fc78e0369abfb1f692"
+            ],
+            "index": "pypi",
+            "version": "==1.0"
+        },
+        "requests": {
+            "hashes": [
+                "sha256:502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e",
+                "sha256:7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b"
+            ],
+            "version": "==2.21.0"
+        },
+        "urllib3": {
+            "hashes": [
+                "sha256:4c291ca23bbb55c76518905869ef34bdd5f0e46af7afe6861e8375643ffee1a0",
+                "sha256:9a247273df709c4fedb38c711e44292304f73f39ab01beda9f6b9fc375669ac3"
+            ],
+            "version": "==1.24.2"
+        }
+    },
+    "develop": {
+        "asn1crypto": {
+            "hashes": [
+                "sha256:2f1adbb7546ed199e3c90ef23ec95c5cf3585bac7d11fb7eb562a3fe89c64e87",
+                "sha256:9d5c20441baf0cb60a4ac34cc447c6c189024b6b4c6cd7877034f4965c464e49"
+            ],
+            "version": "==0.24.0"
+        },
+        "aspy.yaml": {
+            "hashes": [
+                "sha256:ae249074803e8b957c83fdd82a99160d0d6d26dff9ba81ba608b42eebd7d8cd3",
+                "sha256:c7390d79f58eb9157406966201abf26da0d56c07e0ff0deadc39c8f4dbc13482"
+            ],
+            "version": "==1.2.0"
+        },
+        "bcrypt": {
+            "hashes": [
+                "sha256:0ba875eb67b011add6d8c5b76afbd92166e98b1f1efab9433d5dc0fafc76e203",
+                "sha256:21ed446054c93e209434148ef0b362432bb82bbdaf7beef70a32c221f3e33d1c",
+                "sha256:28a0459381a8021f57230954b9e9a65bb5e3d569d2c253c5cac6cb181d71cf23",
+                "sha256:2aed3091eb6f51c26b7c2fad08d6620d1c35839e7a362f706015b41bd991125e",
+                "sha256:2fa5d1e438958ea90eaedbf8082c2ceb1a684b4f6c75a3800c6ec1e18ebef96f",
+                "sha256:3a73f45484e9874252002793518da060fb11eaa76c30713faa12115db17d1430",
+                "sha256:3e489787638a36bb466cd66780e15715494b6d6905ffdbaede94440d6d8e7dba",
+                "sha256:44636759d222baa62806bbceb20e96f75a015a6381690d1bc2eda91c01ec02ea",
+                "sha256:678c21b2fecaa72a1eded0cf12351b153615520637efcadc09ecf81b871f1596",
+                "sha256:75460c2c3786977ea9768d6c9d8957ba31b5fbeb0aae67a5c0e96aab4155f18c",
+                "sha256:8ac06fb3e6aacb0a95b56eba735c0b64df49651c6ceb1ad1cf01ba75070d567f",
+                "sha256:8fdced50a8b646fff8fa0e4b1c5fd940ecc844b43d1da5a980cb07f2d1b1132f",
+                "sha256:9b2c5b640a2da533b0ab5f148d87fb9989bf9bcb2e61eea6a729102a6d36aef9",
+                "sha256:a9083e7fa9adb1a4de5ac15f9097eb15b04e2c8f97618f1b881af40abce382e1",
+                "sha256:b7e3948b8b1a81c5a99d41da5fb2dc03ddb93b5f96fcd3fd27e643f91efa33e1",
+                "sha256:b998b8ca979d906085f6a5d84f7b5459e5e94a13fc27c28a3514437013b6c2f6",
+                "sha256:dd08c50bc6f7be69cd7ba0769acca28c846ec46b7a8ddc2acf4b9ac6f8a7457e",
+                "sha256:de5badee458544ab8125e63e39afeedfcf3aef6a6e2282ac159c95ae7472d773",
+                "sha256:ede2a87333d24f55a4a7338a6ccdccf3eaa9bed081d1737e0db4dbd1a4f7e6b6"
+            ],
+            "version": "==3.1.6"
+        },
+        "cached-property": {
+            "hashes": [
+                "sha256:3a026f1a54135677e7da5ce819b0c690f156f37976f3e30c5430740725203d7f",
+                "sha256:9217a59f14a5682da7c4b8829deadbfc194ac22e9908ccf7c8820234e80a1504"
+            ],
+            "version": "==1.5.1"
+        },
+        "certifi": {
+            "hashes": [
+                "sha256:59b7658e26ca9c7339e00f8f4636cdfe59d34fa37b9b04f6f9e9926b3cece1a5",
+                "sha256:b26104d6835d1f5e49452a26eb2ff87fe7090b89dfcaee5ea2212697e1e1d7ae"
+            ],
+            "version": "==2019.3.9"
+        },
+        "cffi": {
+            "hashes": [
+                "sha256:041c81822e9f84b1d9c401182e174996f0bae9991f33725d059b771744290774",
+                "sha256:046ef9a22f5d3eed06334d01b1e836977eeef500d9b78e9ef693f9380ad0b83d",
+                "sha256:066bc4c7895c91812eff46f4b1c285220947d4aa46fa0a2651ff85f2afae9c90",
+                "sha256:066c7ff148ae33040c01058662d6752fd73fbc8e64787229ea8498c7d7f4041b",
+                "sha256:2444d0c61f03dcd26dbf7600cf64354376ee579acad77aef459e34efcb438c63",
+                "sha256:300832850b8f7967e278870c5d51e3819b9aad8f0a2c8dbe39ab11f119237f45",
+                "sha256:34c77afe85b6b9e967bd8154e3855e847b70ca42043db6ad17f26899a3df1b25",
+                "sha256:46de5fa00f7ac09f020729148ff632819649b3e05a007d286242c4882f7b1dc3",
+                "sha256:4aa8ee7ba27c472d429b980c51e714a24f47ca296d53f4d7868075b175866f4b",
+                "sha256:4d0004eb4351e35ed950c14c11e734182591465a33e960a4ab5e8d4f04d72647",
+                "sha256:4e3d3f31a1e202b0f5a35ba3bc4eb41e2fc2b11c1eff38b362de710bcffb5016",
+                "sha256:50bec6d35e6b1aaeb17f7c4e2b9374ebf95a8975d57863546fa83e8d31bdb8c4",
+                "sha256:55cad9a6df1e2a1d62063f79d0881a414a906a6962bc160ac968cc03ed3efcfb",
+                "sha256:5662ad4e4e84f1eaa8efce5da695c5d2e229c563f9d5ce5b0113f71321bcf753",
+                "sha256:59b4dc008f98fc6ee2bb4fd7fc786a8d70000d058c2bbe2698275bc53a8d3fa7",
+                "sha256:73e1ffefe05e4ccd7bcea61af76f36077b914f92b76f95ccf00b0c1b9186f3f9",
+                "sha256:a1f0fd46eba2d71ce1589f7e50a9e2ffaeb739fb2c11e8192aa2b45d5f6cc41f",
+                "sha256:a2e85dc204556657661051ff4bab75a84e968669765c8a2cd425918699c3d0e8",
+                "sha256:a5457d47dfff24882a21492e5815f891c0ca35fefae8aa742c6c263dac16ef1f",
+                "sha256:a8dccd61d52a8dae4a825cdbb7735da530179fea472903eb871a5513b5abbfdc",
+                "sha256:ae61af521ed676cf16ae94f30fe202781a38d7178b6b4ab622e4eec8cefaff42",
+                "sha256:b012a5edb48288f77a63dba0840c92d0504aa215612da4541b7b42d849bc83a3",
+                "sha256:d2c5cfa536227f57f97c92ac30c8109688ace8fa4ac086d19d0af47d134e2909",
+                "sha256:d42b5796e20aacc9d15e66befb7a345454eef794fdb0737d1af593447c6c8f45",
+                "sha256:dee54f5d30d775f525894d67b1495625dd9322945e7fee00731952e0368ff42d",
+                "sha256:e070535507bd6aa07124258171be2ee8dfc19119c28ca94c9dfb7efd23564512",
+                "sha256:e1ff2748c84d97b065cc95429814cdba39bcbd77c9c85c89344b317dc0d9cbff",
+                "sha256:ed851c75d1e0e043cbf5ca9a8e1b13c4c90f3fbd863dacb01c0808e2b5204201"
+            ],
+            "version": "==1.12.3"
+        },
+        "cfgv": {
+            "hashes": [
+                "sha256:6e9f2feea5e84bc71e56abd703140d7a2c250fc5ba38b8702fd6a68ed4e3b2ef",
+                "sha256:e7f186d4a36c099a9e20b04ac3108bd8bb9b9257e692ce18c8c3764d5cb12172"
+            ],
+            "version": "==1.6.0"
+        },
+        "chardet": {
+            "hashes": [
+                "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
+                "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
+            ],
+            "version": "==3.0.4"
+        },
+        "cryptography": {
+            "hashes": [
+                "sha256:066f815f1fe46020877c5983a7e747ae140f517f1b09030ec098503575265ce1",
+                "sha256:210210d9df0afba9e000636e97810117dc55b7157c903a55716bb73e3ae07705",
+                "sha256:26c821cbeb683facb966045e2064303029d572a87ee69ca5a1bf54bf55f93ca6",
+                "sha256:2afb83308dc5c5255149ff7d3fb9964f7c9ee3d59b603ec18ccf5b0a8852e2b1",
+                "sha256:2db34e5c45988f36f7a08a7ab2b69638994a8923853dec2d4af121f689c66dc8",
+                "sha256:409c4653e0f719fa78febcb71ac417076ae5e20160aec7270c91d009837b9151",
+                "sha256:45a4f4cf4f4e6a55c8128f8b76b4c057027b27d4c67e3fe157fa02f27e37830d",
+                "sha256:48eab46ef38faf1031e58dfcc9c3e71756a1108f4c9c966150b605d4a1a7f659",
+                "sha256:6b9e0ae298ab20d371fc26e2129fd683cfc0cfde4d157c6341722de645146537",
+                "sha256:6c4778afe50f413707f604828c1ad1ff81fadf6c110cb669579dea7e2e98a75e",
+                "sha256:8c33fb99025d353c9520141f8bc989c2134a1f76bac6369cea060812f5b5c2bb",
+                "sha256:9873a1760a274b620a135054b756f9f218fa61ca030e42df31b409f0fb738b6c",
+                "sha256:9b069768c627f3f5623b1cbd3248c5e7e92aec62f4c98827059eed7053138cc9",
+                "sha256:9e4ce27a507e4886efbd3c32d120db5089b906979a4debf1d5939ec01b9dd6c5",
+                "sha256:acb424eaca214cb08735f1a744eceb97d014de6530c1ea23beb86d9c6f13c2ad",
+                "sha256:c8181c7d77388fe26ab8418bb088b1a1ef5fde058c6926790c8a0a3d94075a4a",
+                "sha256:d4afbb0840f489b60f5a580a41a1b9c3622e08ecb5eec8614d4fb4cd914c4460",
+                "sha256:d9ed28030797c00f4bc43c86bf819266c76a5ea61d006cd4078a93ebf7da6bfd",
+                "sha256:e603aa7bb52e4e8ed4119a58a03b60323918467ef209e6ff9db3ac382e5cf2c6"
+            ],
+            "version": "==2.6.1"
+        },
+        "docker": {
+            "extras": [
+                "ssh"
+            ],
+            "hashes": [
+                "sha256:2b1f48041cfdcc9f6b5da0e04e0e326ded225e736762ade2060000e708f4c9b7",
+                "sha256:c456ded5420af5860441219ff8e51cdec531d65f4a9e948ccd4133e063b72f50"
+            ],
+            "version": "==3.7.2"
+        },
+        "docker-compose": {
+            "hashes": [
+                "sha256:5582a51827676f5243473310e911503e1016bbdf3be1b89dcb4201f42b5fa369",
+                "sha256:7c630f8cfdcea45fd44f7c2f3971afb99b11b5e1df214b5ed270086aab82fc80"
+            ],
+            "index": "pypi",
+            "version": "==1.24.0"
+        },
+        "docker-pycreds": {
+            "hashes": [
+                "sha256:6ce3270bcaf404cc4c3e27e4b6c70d3521deae82fb508767870fdbf772d584d4",
+                "sha256:7266112468627868005106ec19cd0d722702d2b7d5912a28e19b826c3d37af49"
+            ],
+            "version": "==0.4.0"
+        },
+        "dockerpty": {
+            "hashes": [
+                "sha256:69a9d69d573a0daa31bcd1c0774eeed5c15c295fe719c61aca550ed1393156ce"
+            ],
+            "version": "==0.4.1"
+        },
+        "docopt": {
+            "hashes": [
+                "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"
+            ],
+            "version": "==0.6.2"
+        },
+        "identify": {
+            "hashes": [
+                "sha256:443f419ca6160773cbaf22dbb302b1e436a386f23129dbb5482b68a147c2eca9",
+                "sha256:bd7f15fe07112b713fb68fbdde3a34dd774d9062128f2c398104889f783f989d"
+            ],
+            "version": "==1.4.2"
+        },
+        "idna": {
+            "hashes": [
+                "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407",
+                "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"
+            ],
+            "version": "==2.8"
+        },
+        "importlib-metadata": {
+            "hashes": [
+                "sha256:46fc60c34b6ed7547e2a723fc8de6dc2e3a1173f8423246b3ce497f064e9c3de",
+                "sha256:bc136180e961875af88b1ab85b4009f4f1278f8396a60526c0009f503a1a96ca"
+            ],
+            "version": "==0.9"
+        },
+        "jsonschema": {
+            "hashes": [
+                "sha256:000e68abd33c972a5248544925a0cae7d1125f9bf6c58280d37546b946769a08",
+                "sha256:6ff5f3180870836cae40f06fa10419f557208175f13ad7bc26caa77beb1f6e02"
+            ],
+            "version": "==2.6.0"
+        },
+        "nodeenv": {
+            "hashes": [
+                "sha256:ad8259494cf1c9034539f6cced78a1da4840a4b157e23640bc4a0c0546b0cb7a"
+            ],
+            "version": "==1.3.3"
+        },
+        "paramiko": {
+            "hashes": [
+                "sha256:3c16b2bfb4c0d810b24c40155dbfd113c0521e7e6ee593d704e84b4c658a1f3b",
+                "sha256:a8975a7df3560c9f1e2b43dc54ebd40fd00a7017392ca5445ce7df409f900fcb"
+            ],
+            "version": "==2.4.2"
+        },
+        "pre-commit": {
+            "hashes": [
+                "sha256:2576a2776098f3902ef9540a84696e8e06bf18a337ce43a6a889e7fa5d26c4c5",
+                "sha256:82f2f2d657d7f9280de9f927ae56886d60b9ef7f3714eae92d12713cd9cb9e11"
+            ],
+            "index": "pypi",
+            "version": "==1.15.2"
+        },
+        "pyasn1": {
+            "hashes": [
+                "sha256:da2420fe13a9452d8ae97a0e478adde1dee153b11ba832a95b223a2ba01c10f7",
+                "sha256:da6b43a8c9ae93bc80e2739efb38cc776ba74a886e3e9318d65fe81a8b8a2c6e"
+            ],
+            "version": "==0.4.5"
+        },
+        "pycparser": {
+            "hashes": [
+                "sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3"
+            ],
+            "version": "==2.19"
+        },
+        "pynacl": {
+            "hashes": [
+                "sha256:05c26f93964373fc0abe332676cb6735f0ecad27711035b9472751faa8521255",
+                "sha256:0c6100edd16fefd1557da078c7a31e7b7d7a52ce39fdca2bec29d4f7b6e7600c",
+                "sha256:0d0a8171a68edf51add1e73d2159c4bc19fc0718e79dec51166e940856c2f28e",
+                "sha256:1c780712b206317a746ace34c209b8c29dbfd841dfbc02aa27f2084dd3db77ae",
+                "sha256:2424c8b9f41aa65bbdbd7a64e73a7450ebb4aa9ddedc6a081e7afcc4c97f7621",
+                "sha256:2d23c04e8d709444220557ae48ed01f3f1086439f12dbf11976e849a4926db56",
+                "sha256:30f36a9c70450c7878053fa1344aca0145fd47d845270b43a7ee9192a051bf39",
+                "sha256:37aa336a317209f1bb099ad177fef0da45be36a2aa664507c5d72015f956c310",
+                "sha256:4943decfc5b905748f0756fdd99d4f9498d7064815c4cf3643820c9028b711d1",
+                "sha256:57ef38a65056e7800859e5ba9e6091053cd06e1038983016effaffe0efcd594a",
+                "sha256:5bd61e9b44c543016ce1f6aef48606280e45f892a928ca7068fba30021e9b786",
+                "sha256:6482d3017a0c0327a49dddc8bd1074cc730d45db2ccb09c3bac1f8f32d1eb61b",
+                "sha256:7d3ce02c0784b7cbcc771a2da6ea51f87e8716004512493a2b69016326301c3b",
+                "sha256:a14e499c0f5955dcc3991f785f3f8e2130ed504fa3a7f44009ff458ad6bdd17f",
+                "sha256:a39f54ccbcd2757d1d63b0ec00a00980c0b382c62865b61a505163943624ab20",
+                "sha256:aabb0c5232910a20eec8563503c153a8e78bbf5459490c49ab31f6adf3f3a415",
+                "sha256:bd4ecb473a96ad0f90c20acba4f0bf0df91a4e03a1f4dd6a4bdc9ca75aa3a715",
+                "sha256:e2da3c13307eac601f3de04887624939aca8ee3c9488a0bb0eca4fb9401fc6b1",
+                "sha256:f67814c38162f4deb31f68d590771a29d5ae3b1bd64b75cf232308e5c74777e0"
+            ],
+            "version": "==1.3.0"
+        },
+        "pyyaml": {
+            "hashes": [
+                "sha256:3d7da3009c0f3e783b2c873687652d83b1bbfd5c88e9813fb7e5b03c0dd3108b",
+                "sha256:3ef3092145e9b70e3ddd2c7ad59bdd0252a94dfe3949721633e41344de00a6bf",
+                "sha256:40c71b8e076d0550b2e6380bada1f1cd1017b882f7e16f09a65be98e017f211a",
+                "sha256:558dd60b890ba8fd982e05941927a3911dc409a63dcb8b634feaa0cda69330d3",
+                "sha256:a7c28b45d9f99102fa092bb213aa12e0aaf9a6a1f5e395d36166639c1f96c3a1",
+                "sha256:aa7dd4a6a427aed7df6fb7f08a580d68d9b118d90310374716ae90b710280af1",
+                "sha256:bc558586e6045763782014934bfaf39d48b8ae85a2713117d16c39864085c613",
+                "sha256:d46d7982b62e0729ad0175a9bc7e10a566fc07b224d2c79fafb5e032727eaa04",
+                "sha256:d5eef459e30b09f5a098b9cea68bebfeb268697f78d647bd255a085371ac7f3f",
+                "sha256:e01d3203230e1786cd91ccfdc8f8454c8069c91bee3962ad93b87a4b2860f537",
+                "sha256:e170a9e6fcfd19021dd29845af83bb79236068bf5fd4df3327c1be18182b2531"
+            ],
+            "version": "==3.13"
+        },
+        "requests": {
+            "hashes": [
+                "sha256:502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e",
+                "sha256:7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b"
+            ],
+            "version": "==2.21.0"
+        },
+        "six": {
+            "hashes": [
+                "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
+                "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
+            ],
+            "version": "==1.12.0"
+        },
+        "texttable": {
+            "hashes": [
+                "sha256:119041773ff03596b56392532f9315cb3a3116e404fd6f36e76a7dc088d95c79"
+            ],
+            "version": "==0.9.1"
+        },
+        "toml": {
+            "hashes": [
+                "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c",
+                "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e"
+            ],
+            "version": "==0.10.0"
+        },
+        "urllib3": {
+            "hashes": [
+                "sha256:4c291ca23bbb55c76518905869ef34bdd5f0e46af7afe6861e8375643ffee1a0",
+                "sha256:9a247273df709c4fedb38c711e44292304f73f39ab01beda9f6b9fc375669ac3"
+            ],
+            "version": "==1.24.2"
+        },
+        "virtualenv": {
+            "hashes": [
+                "sha256:15ee248d13e4001a691d9583948ad3947bcb8a289775102e4c4aa98a8b7a6d73",
+                "sha256:bfc98bb9b42a3029ee41b96dc00a34c2f254cbf7716bec824477b2c82741a5c4"
+            ],
+            "version": "==16.5.0"
+        },
+        "websocket-client": {
+            "hashes": [
+                "sha256:1151d5fb3a62dc129164292e1227655e4bbc5dd5340a5165dfae61128ec50aa9",
+                "sha256:1fd5520878b68b84b5748bb30e592b10d0a91529d5383f74f4964e72b297fd3a"
+            ],
+            "version": "==0.56.0"
+        },
+        "zipp": {
+            "hashes": [
+                "sha256:139391b239594fd8b91d856bc530fbd2df0892b17dd8d98a91f018715954185f",
+                "sha256:8047e4575ce8d700370a3301bbfc972896a5845eb62dd535da395b86be95dfad"
+            ],
+            "version": "==0.4.0"
+        }
+    }
+}
diff --git a/README.md b/README.md
index cbf0f7c..bde3fbd 100644
--- a/README.md
+++ b/README.md
@@ -1,29 +1,34 @@
 # Poquita
 
-My setup of [Poca](https://github.com/brokkr/poca/).
+> My setup of [Poca](https://github.com/brokkr/poca/).
 
-My workflow is managing the podcast list (and config and provisioning and
-deployment scripts) via git, using
-[gitreceive](https://github.com/progrium/gitreceive/) to deploy new versions to
-the downloading machine (syncing files locally when afterward).
+My setup consists of keeping the subscriptions in git (`poca.xml`), managing
+them locally and running the downloader inside a Docker container remotely. The
+final part of syncing the downloads is using unison and is managed in my
+[rcfiles](https://www.shore.co.il/git/rcfiles) repository.
 
-## Running Poca locally
+## Requirements
 
-`tox`
+- Python 3.7
+- pipenv
 
-## Running poca-subscribe locally
+## Usage
 
-`tox -e poca-subscribe -- {add,delete,list,toggle} ...`
+Adding/ removing/ list/ toggling subscriptions:
+```
+pipenv run subscribe {add,delete,list,toggle}
+```
 
-## Provision a machine for git push
+Deploying a new version:
+```
+pipenv run deploy
+```
 
-`tox -e ansible -- -i xbmc.shore.co.il,`
+Linting (using [pre-commit](https://pre-commit.com/)):
+```
+pipenv run lint
+```
 
-## Deploying a new version
+## License
 
-    git remote add kodi git@xbmc.shore.co.il:poquita.git
-    git push kodi
-
-## Running [pre-commit](http://pre-commit.com/)
-
-`tox -e pre-commit`
+This software is licensed under the MIT license (see `LICENSE.txt`).
diff --git a/ansible.cfg b/ansible.cfg
deleted file mode 100644
index 1865bc9..0000000
--- a/ansible.cfg
+++ /dev/null
@@ -1,18 +0,0 @@
-[defaults]
-library = library
-host_key_checking = False
-retry_files_enabled = False
-roles_path = ./roles/
-command_warnings = True
-deprecation_warnings = True
-callback_whitelist = profile_tasks
-retry_files_save_path = /tmp/
-
-[ssh_connection]
-pipelining = True
-
-[privilege_escalation]
-become = True
-become_method = sudo
-become_user = root
-become_ask_pass = False
diff --git a/crontab b/crontab
new file mode 100644
index 0000000..4e24783
--- /dev/null
+++ b/crontab
@@ -0,0 +1 @@
+0 */4 * * * cd /poquita && poca --config ./
diff --git a/db/.gitkeep b/db/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..7dcf5b0
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,14 @@
+---
+version: '2'
+services:
+  - poquita:
+      build:
+        context: ./
+      restart: on-failure
+      user: '1000' # My (Nimrod) uid on the xbmc host.
+      volumes:
+        - /srv/library/nimrod/Podcasts:/poquita/Podcasts
+        - poquita:/poquita/db
+
+volumes:
+  poquita:
diff --git a/playbook.yml b/playbook.yml
deleted file mode 100644
index 6e9971c..0000000
--- a/playbook.yml
+++ /dev/null
@@ -1,43 +0,0 @@
----
-- hosts: all
-  pre_tasks:
-      - name: APT install Python3, Tox, Cron, Unison
-        apt:
-            name:
-                - python3
-                - tox
-                - cron-daemon
-                - unison
-            state: present
-            update_cache: True
-            cache_valid_time: 3600
-
-      - name: Get authorized keys
-        become: False
-        slurp:
-            src: ~/.ssh/authorized_keys
-        register: authorized_keys
-  roles:
-      - name: gitreceive
-        gitreceive_public_keys: "{{ (authorized_keys['content']|b64decode).splitlines() }}"
-        gitreceive_receiver_script: |
-            #!/bin/sh
-            set -eu
-            echo '----> Unpacking ...'
-            mkdir -p ~/poquita
-            cd ~/poquita
-            tar -xf -
-            if [ -f receiver ] && [ -x receiver ]
-            then
-                echo '----> Running receiver ...'
-                ./receiver
-            fi
-            echo '----> OK.'
-  post_tasks:
-      - name: Create Podcasts directory
-        file:
-            path: /srv/library/nimrod/Podcasts
-            state: directory
-            owner: nimrod
-            group: git
-            mode: 0o0775
diff --git a/poca.xml b/poca.xml
index 3e41a7d..df8a6fe 100644
--- a/poca.xml
+++ b/poca.xml
@@ -24,7 +24,7 @@
     </defaults>
   <subscriptions>
     <!-- The meaning of the subscription options are brifly as follows:
-        * category: A category attribute on a subscription tag is helpful in 
+        * category: A category attribute on a subscription tag is helpful in
                     organizing the output of 'poca-subscribe list'.
         * state: A state attribute is either 'active' or 'inactive'. inactive
                  subs are not updated. subs without state attribute are active.
@@ -36,7 +36,7 @@
           (see https://github.com/brokkr/poca/wiki/ID3-frames for details)
         * filters: Contains one or more of following tags (all optional)
           * filename: Filename of the entry must match this string/regex
-          * title: Same as above, only for the title in the rss 
+          * title: Same as above, only for the title in the rss
           * hour: The hour (24h-format) at which the entry was published.
           * weekdays: Only entries from one of these weekdays (as integers)
           * after_date: Only use entries published after date specified.
diff --git a/receiver b/receiver
deleted file mode 100755
index 9e6f00c..0000000
--- a/receiver
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-set -eu
-
-# shellcheck disable=SC2016
-( (crontab -l 2>/dev/null || true) | sed '/poquita/d'; echo '0 */4 * * * tox -c $HOME/poquita/tox.ini | logger' )  | crontab -
diff --git a/requirements.yml b/requirements.yml
deleted file mode 100644
index e916d11..0000000
--- a/requirements.yml
+++ /dev/null
@@ -1,3 +0,0 @@
----
-- src: adarnimrod.gitreceive
-  name: gitreceive
diff --git a/roles/.gitkeep b/roles/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/tox.ini b/tox.ini
deleted file mode 100644
index 741e837..0000000
--- a/tox.ini
+++ /dev/null
@@ -1,40 +0,0 @@
-[tox]
-skipsdist = True
-envlist = poca
-
-[testenv:poca]
-basepython = python3
-deps =
-    feedparser
-    lxml
-    mutagen
-    git+https://github.com/brokkr/poca/@v0.8
-commands =
-    poca --config ./ {posargs}
-
-[testenv:poca-subscribe]
-envdir = {toxworkdir}/poca
-basepython = python3
-deps =
-    feedparser
-    lxml
-    mutagen
-    git+https://github.com/brokkr/poca/@v0.8
-commands =
-    poca-subscribe --config ./ {posargs}
-
-[testenv:ansible]
-deps =
-    ansible==2.3.0.0
-commands =
-    ansible-galaxy install -r requirements.yml
-    ansible-playbook playbook.yml {posargs}
-passenv = HOME TERM ANSIBLE_* AWS_*
-setenv =
-    ANSIBLE_VERBOSITY=2
-
-[testenv:pre-commit]
-deps =
-    pre-commit==0.14.1
-commands =
-    pre-commit {posargs}
-- 
GitLab