{"id":16106075,"url":"https://github.com/meonkeys/ow","last_synced_at":"2025-03-18T08:32:00.718Z","repository":{"id":66657122,"uuid":"586152174","full_name":"meonkeys/ow","owner":"meonkeys","description":" Nextcloud command-line client ","archived":false,"fork":false,"pushed_at":"2024-11-28T19:37:06.000Z","size":66,"stargazers_count":10,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-16T18:21:27.440Z","etag":null,"topics":["nextcloud","python3"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/meonkeys.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-01-07T05:37:47.000Z","updated_at":"2025-03-12T18:18:10.000Z","dependencies_parsed_at":"2024-06-15T23:22:17.878Z","dependency_job_id":"2068a3da-0b2d-42cd-98cb-f83517971684","html_url":"https://github.com/meonkeys/ow","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meonkeys%2Fow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meonkeys%2Fow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meonkeys%2Fow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meonkeys%2Fow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/meonkeys","download_url":"https://codeload.github.com/meonkeys/ow/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244184204,"owners_count":20412170,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["nextcloud","python3"],"created_at":"2024-10-09T19:11:52.584Z","updated_at":"2025-03-18T08:32:00.356Z","avatar_url":"https://github.com/meonkeys.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🦉 ow\n\n## Name\n\now - Nextcloud command-line client\n\n## Synopsis\n\n```\now action target\n```\n\n## Description\n\now (like, you're trying to say \"owl\" and almost succeed) is your handy local command-line pal for Nextcloud. ow enhances local editing, collaboration, and more by providing missing features or by providing a command-line interface for existing features.\n\nOutput is generally minimal on success. If an error occurs, messages are printed to standard error and a nonzero exit code is returned.\n\n### Quick examples\n\n```bash\n# Add all media in a folder to an album.\now dir-album \"Photos/2020/Camping trip\"\n\n# Get internal link for a file.\now internal-link ~/Nextcloud/Readme.md\n\n# Find and delete old calendar events.\now delete-old-events 'calendar=personal,minimumAge=2y'\n\n# Lock a file.\now lock ~/Nextcloud/Readme.md\n\n# Unlock a file.\now unlock ~/Nextcloud/Readme.md\n```\n\n## Install\n\n* clone this repository\n    * or just download the `ow` script\n    * put `ow` in your `$PATH` and make it executable, e.g. `ln -s ~/git/meonkeys/ow/ow ~/.local/bin`\n* install required dependencies\n    * Python 3\n    * Python `requests` library (via e.g. `pip install requests` or `apt install python3-requests`)\n* install optional dependencies\n    * Nextcloud desktop sync client (for lock, unlock, internal-url; not needed for dir-album)\n    * `xmllint` at `/usr/bin/xmllint` (for debugging API responses)\n        * on Debian/Ubuntu: `apt install libxml2-utils`\n    * `python3-argcomplete` for Bash programmable (Tab) completion\n        * must also set this up with, e.g. `eval \"$(register-python-argcomplete3 ow)\"` in your `~/.bashrc`\n    * [Temporary files lock app](https://apps.nextcloud.com/apps/files_lock) for locking and unlocking files.\n* create config file based on \"example config\" below\n\n### example config\n\nCreate `~/.config/ow/ow.ini` and customize, following the example below:\n\n```ini\n[server]\n# Must start with https\nbaseUrl = https://cloud.example.com\nusername = user\n# If you use multi-factor auth, use an app password here.\npassword = redacted\n\n[local]\n# If you use the Nextcloud Desktop client, set this to indicate where files are sync'd.\n# Required for lock, unlock, and internal-url.\n# Not needed for dir-album nor delete-old-events.\nsyncFolder = /home/user/Nextcloud\n```\n\n## Detailed usage\n\n### Help\n\nList available actions.\n\n```bash\now --help\n```\n\n### Create album from folder\n\nAdd all media in a folder to an album.\n\n```bash\now dir-album \"Photos/2020/Camping trip\"\n```\n\nThis works directly against the Nextcloud WebDAV API; the desktop client is not required.\n\nThis command expects that the provided path contains media compatible with the Photos and Memories apps (generally just photos and videos). Sub-folders and non-compatible file types are ignored.\n\nThe new album will be named by transforming the last path element. Some arbitary cleanup steps are performed. Examples:\n\n| Path                           | Album             |\n|--------------------------------|-------------------|\n| Photos/2020/Camping trip/      | Camping trip      |\n| Photos/2020-Camping trip       | 2020-Camping trip |\n| Photos/2020-04-01 Camping trip | Camping trip      |\n\n#### convert many folders to albums\n\nExample Python script for converting a bunch of folders to albums at once:\n\n```python\nimport subprocess\n\nfolders = [\n    'Photos/2020/Camping trip',\n    'Photos/2021/sunny day'\n]\n\nfor folder in folders:\n    subprocess.run(['./ow', 'dir-album', folder])\n```\n\n### Get internal link\n\nGiven a local file path sync'd by the Nextcloud desktop client, return the \"internal link\" on the Nextcloud server.\n\n```bash\now internal-link ~/Nextcloud/test.md\n# example output:\n# https://cloud.example.com/f/229\n```\n\n### Delete old calendar events\n\nFind and delete old calendar events given an event filter specification.\n\nThis will delete events older than 2 years on a calendar called \"personal\":\n\n```bash\now delete-old-events 'calendar=personal,minimumAge=2y'\n```\n\n### Lock\n\nLock a file.\n\n```bash\now lock ~/Nextcloud/Readme.md\n```\n\nLocking indicates to other users your wish to avoid conflicts in shared files.\n\n### Unock\n\nUnlock a file.\n\n```bash\now unlock ~/Nextcloud/Readme.md\n```\n\n## Contributions\n\nPatches welcome. Ask before submitting anything larger than an obvious bugfix. Create a GitHub pull request. Add your name below.\n\n### Contributors\n\n* Adam Monsen\n* Frederik Berg\n* Tom Laermans\n\n## Architecture\n\now is written in Python. It examines local files sync'd by the [Nextcloud desktop client](https://github.com/nextcloud/desktop/) for some operations, and talks with the [Nextcloud WebDAV API](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/WebDAV/basic.html) for others.\n\n## History\n\now [started](https://help.nextcloud.com/t/get-internal-link-for-a-file-in-nextcloud-from-a-local-command-line/152774) with one command (get internal link for locally sync'd file).\n\n## Ideas\n\n* testing\n    * add unit tests (very fast and specific, code-level)\n    * add integration tests (slower, maybe only run on merges)\n    * add end-to-end/acceptance tests (many things under test, complex, brittle, possibly manual)\n    * security, penetration, fuzzing, etc.\n    * use continuous integration\n    * document manual acceptance tests, perform regularly, record results\n    * document test matrix (\"tested with\" table showing all combinations of client OS, client version, server version, etc. that are tested / known / expected to work)\n* add more features\n    * post chat messages\n    * add a task\n    * add a calendar event\n    * search\n* improve setup\n    * automate install\n* improve config\n    * read and use config from Nextcloud desktop client\n    * [read and use secrets from desktop/OS password manager](https://pypi.org/project/keyring/) or smartcard\n* improve code maintainability\n    * add tests (see \"testing\")\n* improve cross-platform compatibility\n    * currently only built for and tested on recent Ubuntu LTS\n    * add Windows support\n    * add macOS support\n* pick a better name?\n* consider [cla or not](https://sfconservancy.org/blog/2014/jun/09/do-not-need-cla/), [copyright ownership](https://sfconservancy.org/blog/2021/jun/30/who-should-own-foss-copyrights/)\n* Are there other/better free software utilities like this one? List/promote them.\n* Would it make more sense to implement this and the other feature ideas (above) within the [official client](https://docs.nextcloud.com/desktop/latest/advancedusage.html)?\n    * [Do the maintainers want these features?](https://github.com/nextcloud/desktop/issues?q=label%3A%22feature%3A+%3Awhite_square_button%3A+nextcloudcmd%22+)\n* use [Nextcloud Python Framework](https://github.com/cloud-py-api/nc_py_api) instead of WebDAV API?\n\n## COPYLEFT AND LICENSE\n\n* Copyright ©2023-2024 Adam Monsen \u003chaircut@gmail.com\u003e\n* License: AGPL v3 or later (see COPYING)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmeonkeys%2Fow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmeonkeys%2Fow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmeonkeys%2Fow/lists"}