From 94e57f51f51f6889b865a30378a891146e9fd397 Mon Sep 17 00:00:00 2001 From: Thibaud Date: Thu, 12 Mar 2020 23:15:20 +0100 Subject: [PATCH] Initial commit --- .gitignore | 11 ++++++ LICENSE | 24 ++++++++++++ README.md | 3 ++ config.ini | 7 ++++ dev-requirements.txt | 3 ++ requirements.txt | 2 + wallabag_mass_import.py | 85 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 135 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 config.ini create mode 100644 dev-requirements.txt create mode 100644 requirements.txt create mode 100644 wallabag_mass_import.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..73f4803 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..17f8efb --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +Copyright (c) 2020, Thibaud Gasser +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..f0815d0 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Wallabag tools + +Python tools using the wallabag API. diff --git a/config.ini b/config.ini new file mode 100644 index 0000000..89f2bf1 --- /dev/null +++ b/config.ini @@ -0,0 +1,7 @@ +[Wallabag Configuration] +host= +grant_type = +client_id = +client_secret = +username = +password = diff --git a/dev-requirements.txt b/dev-requirements.txt new file mode 100644 index 0000000..c410fe2 --- /dev/null +++ b/dev-requirements.txt @@ -0,0 +1,3 @@ +black==19.10b0 +mypy==0.770 +pylint==2.4.4 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..729f57f --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +aiohttp==3.6.2 +wallabag-api==1.2.3 diff --git a/wallabag_mass_import.py b/wallabag_mass_import.py new file mode 100644 index 0000000..7ae4dd4 --- /dev/null +++ b/wallabag_mass_import.py @@ -0,0 +1,85 @@ +import asyncio +import configparser +import logging +import json +import os +from typing import Any, Dict, List + +import aiohttp +from wallabag_api.wallabag import Wallabag + +logging.basicConfig(level=logging.DEBUG) + +ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) +CONFIG_PATH = os.path.join(ROOT_DIR, "config.ini") +ARTICLES_PATH = os.path.join(ROOT_DIR, "articles.json") + + +def load_configuration(path): + config = configparser.ConfigParser() + config.read(path) + return config["Wallabag Configuration"] + + +async def connect_to_wallabag( + configuration: Dict[str, str], session: aiohttp.ClientSession +) -> Wallabag: + configuration["access_token"] = await Wallabag.get_token(**configuration) + + return Wallabag( + host=configuration["host"], + token=configuration["access_token"], + client_id=configuration["client_id"], + client_secret=configuration["client_secret"], + aio_sess=session, + ) + + +def read_urls_file(f): + while True: + line = f.readline() + if line: + yield line + else: + break + + +async def import_articles(w_api: Wallabag, path: str, limit=0): + entries_id = [] + with open(path) as f: + for index, item in enumerate(json.load(f)): + if limit > 0 and index == limit: + break + + entry = await w_api.post_entries( + url=item["url"], + archive=item["is_archived"], + starred=item["is_starred"], + original_url=item["origin_url"], + tags=",".join(item["tags"]), + ) + logging.info( + f"Entry url {item['url']} posted to wallabag with id {entry['id']}" + ) + entries_id.append(entry["id"]) + + return entries_id + + +async def delete_all_entries(ids: List[int], w_api: Wallabag): + for id in ids: + entry = await w_api.delete_entries(id) + logging.info(f"Deleted wallabag entry with id {entry['id']}") + + +async def main(): + async with aiohttp.ClientSession(loop=asyncio.get_event_loop()) as session: + configuration = dict(load_configuration(CONFIG_PATH)) + w_api = await connect_to_wallabag(configuration, session) + + entries_id = await import_articles(w_api, "articles.json", limit=1) + await delete_all_entries(entries_id, w_api) + + +if __name__ == "__main__": + asyncio.run(main())