{"id":17399123,"url":"https://github.com/matkoniecz/osm_bot_abstraction_layer","last_synced_at":"2025-09-16T12:32:22.748Z","repository":{"id":57449708,"uuid":"139066899","full_name":"matkoniecz/osm_bot_abstraction_layer","owner":"matkoniecz","description":"OSM bot abstraction layer building upon osmapi, to make easier to automate edits without causing problems.","archived":false,"fork":false,"pushed_at":"2025-08-27T17:40:47.000Z","size":219,"stargazers_count":13,"open_issues_count":2,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-08-28T02:24:45.567Z","etag":null,"topics":["automation","openstreetmap","osmapi","python-package"],"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/matkoniecz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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,"zenodo":null}},"created_at":"2018-06-28T20:49:08.000Z","updated_at":"2025-08-27T17:40:50.000Z","dependencies_parsed_at":"2023-12-15T22:07:42.755Z","dependency_job_id":"493a7d35-da1d-4ccf-a351-a2af6773cf7b","html_url":"https://github.com/matkoniecz/osm_bot_abstraction_layer","commit_stats":{"total_commits":281,"total_committers":2,"mean_commits":140.5,"dds":"0.017793594306049876","last_synced_commit":"36fc512509aaf868e0da7a541689aaa33e7c6c45"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/matkoniecz/osm_bot_abstraction_layer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matkoniecz%2Fosm_bot_abstraction_layer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matkoniecz%2Fosm_bot_abstraction_layer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matkoniecz%2Fosm_bot_abstraction_layer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matkoniecz%2Fosm_bot_abstraction_layer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/matkoniecz","download_url":"https://codeload.github.com/matkoniecz/osm_bot_abstraction_layer/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matkoniecz%2Fosm_bot_abstraction_layer/sbom","scorecard":{"id":624967,"data":{"date":"2025-08-11","repo":{"name":"github.com/matkoniecz/osm_bot_abstraction_layer","commit":"d308d4bd51c335ac1009608b86fbf2ea4afb9396"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.6,"checks":[{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":4,"reason":"5 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 4","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 1/28 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: GNU Affero General Public License v3.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 3 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-21T06:08:24.897Z","repository_id":57449708,"created_at":"2025-08-21T06:08:24.897Z","updated_at":"2025-08-21T06:08:24.897Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275416626,"owners_count":25460913,"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","status":"online","status_checked_at":"2025-09-16T02:00:10.229Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["automation","openstreetmap","osmapi","python-package"],"created_at":"2024-10-16T15:11:45.588Z","updated_at":"2025-09-16T12:32:22.739Z","avatar_url":"https://github.com/matkoniecz.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"OSM bot abstraction layer is a python package making easier to automate OpenStreetMap edits without causing problems.\n\nThis projects contains code shared between OpenStreetMap bots, to avoid writing the same functionality more than once.\n\nFor example, automated edit may change many objects across large area. In that case it is preferable to split it into multiple edits to avoid country-sized bounding boxes. This logic is available as one of tools included in this project.\n\n# Installation\n\n```\npip install osm-bot-abstraction-layer --user\n```\n\n[![PyPI version](https://badge.fury.io/py/osm-bot-abstraction-layer.svg)](https://badge.fury.io/py/osm-bot-abstraction-layer)\n\n# Testing\n\n```\npython3 -m unittest\n```\n\n# Contributing\n\nFirst contact with any project is crucial, so please report any and all issues in this readme. If you needed tool like this but decided to not use it for some fixable reason - please open an issue!\n\nReports about how documentation can be improved, bug reports, pull requests are welcomed!\n\nPull requests are welcomed from smallest typo to big new features - though in case of huge changes it is always a good idea to start from opening an issue.\n\n# Purpose\n\nThis tool is for people who are at once\n\n- programmers\n- experienced OSM editors\n- following OSM rules\n\nAnyone who runs automated edits is responsible for all problems that appear, including ones caused by bugs in external libraries like this one.\n\nI eliminated all bugs that I noticed, after all I am using this code myself, but some are still lurking. Issue reports and pull requests are welcomed!\n\n# Reminder about OSM rules\n\nNote that automated must not be done without consultation or agreement of a community.\n\nSee the [Import/Guidelines](http://wiki.openstreetmap.org/wiki/Import/Guidelines) and [Automated Edits/Code of Conduct](http://wiki.openstreetmap.org/wiki/Automated_Edits/Code_of_Conduct) for more information.\n\nNote that automated edits violating rules mentioned above are routinely undone. Undiscussed automatic edits may be reverted by anybody, without any consultation.\n\nAnd yes, it means that some automated edits that would save time and make perfect sense were rejected and should not be made. It is still preferable over unrestricted automated edits.\n\n# Configuration\n\nSadly, we need to deal with [OAuth](https://wiki.openstreetmap.org/wiki/OAuth).\n\nCreate application at https://www.openstreetmap.org/oauth2/applications (using `urn:ietf:wg:oauth:2.0:oob` as redirect URI).\n\nCreate `secret.json` file with content like this:\n\n```json\n{\n\t\"bot_account\": {\n\t\t\"script_client_id\": \"replace\",\n\t\t\"script_secret\": \"replace\",\n\t\t\"username\": \"replace with OSM username, optional field needed only for documentation\"\n\t},\n\t\"human_account\": {\n\t\t\"script_client_id\": \"replace\",\n\t\t\"script_secret\": \"replace\",\n\t\t\"username\": \"replace with OSM username, optional field needed only for documentation\"\n\t}\n}\n```\n\nOn first run script should instruct how to obtain token that will be added to that field.\n\nAfter that it should have following format (XXXXX are placeholders):\n\n```json\n{\n\t\"bot_account\": {\n\t\t\"script_client_id\": \"replace\",\n\t\t\"script_secret\": \"replace\",\n\t\t\"username\": \"replace with OSM username, optional field needed only for documentation\",\n    \"token\": {\"access_token\": \"XXXXX\", \"token_type\": \"Bearer\", \"scope\": [\"write_api\", \"write_notes\"], \"created_at\": XXXXX}\n\t},\n\t\"human_account\": {\n\t\t\"script_client_id\": \"replace\",\n\t\t\"script_secret\": \"replace\",\n\t\t\"username\": \"replace with OSM username, optional field needed only for documentation\",\n    \"token\": {\"access_token\": \"XXXXX\", \"token_type\": \"Bearer\", \"scope\": [\"write_api\", \"write_notes\"], \"created_at\": XXXXX}\n\t}\n}\n```\n\n# Usage example\n## Bot edit\n\nFollowing is example based on a real automated edit, following [guidelines for the automatic edits](https://wiki.openstreetmap.org/wiki/Automated_Edits_code_of_conduct).\n\n  1. Relevant community was asked. In this case it affected Polish mappers, so thread appeared [in Polish section of forum.openstreetmap.org](https://forum.openstreetmap.org/viewtopic.php?id=64421). Note that different communities may use different forums or mailing lists as their communication channels.\n  1. In addition [Page documenting the automated edit was created at OSM wiki](https://wiki.openstreetmap.org/wiki/Mechanical_Edits/Mateusz_Konieczny_-_bot_account/moving_%27name:botanical%27%3D%27Platanus_%C3%97_hispanica%27_to_species%3D%27Platanus_%C3%97_hispanica%27_for_natural%3Dtree_in_Poland).\n  1. OSM community accepted the edit.\n  1. Following code was created using `run_simple_retagging_task` component. Running this script will result in:\n     - downloading OSM data using Overpass Turbo as specified in `objects_to_consider_query` parameter\n     - iterate over all and objects, ignoring ones where function passed as parameter `is_element_editable_checker_function` returns false\n     - for all other `edit_element_function` is applied\n     - changes are automatically split in multiple changesets (if necessary) to avoid too large bounding boxes or too many objects in one edit\n     - `changeset_comment`, `discussion_url`, `osm_wiki_documentation_page` parameter values are used to apply correct changeset tags\n  1. Running this code resulted in two edits: [#64628901](https://www.openstreetmap.org/changeset/64628901) and [#64628951](https://www.openstreetmap.org/changeset/64628951)\n\n```python\nfrom osm_bot_abstraction_layer.generic_bot_retagging import run_simple_retagging_task\n\ndef edit_element(tags):\n    if tags.get('amenity') != (\"atm\"):\n        return tags\n    if tags.get('name') == (\"bankomat\"):\n        tags.pop('name', None)\n    if tags.get('name') == (\"Bankomat\"):\n        tags.pop('name', None)\n    return tags\n\ndef main():\n    run_simple_retagging_task(\n        max_count_of_elements_in_one_changeset=500,\n        objects_to_consider_query=\"\"\"\n[out:xml][timeout:25000];\narea[name=\"Polska\"]-\u003e.a;\n(\n  nwr[amenity='atm'][name='Bankomat'](area.a);\n  nwr[amenity='atm'][name='bankomat'](area.a);\n);\nout body;\n\u003e;\nout skel qt;\n\"\"\",\n        cache_folder_filepath='/media/mateusz/5bfa9dfc-ed86-4d19-ac36-78df1060707c/OSM-cache',\n        is_in_manual_mode=False,\n        changeset_comment='usuwanie nazw opisowych z bankomatów (name=\"bankomat\" i name=\"Bankomat\")',\n        discussion_url='https://forum.openstreetmap.org/viewtopic.php?id=66038',\n        osm_wiki_documentation_page='https://wiki.openstreetmap.org/wiki/Mechanical_Edits/Mateusz_Konieczny_-_bot_account/fix_descriptive_name_on_ATMs_in_Poland',\n        edit_element_function=edit_element,\n    )\n\nmain()\n```\n## Downloading data\n\n### Using Overpass\n\n```python\nfrom osm_bot_abstraction_layer.overpass_downloader import download_overpass_query\n\nvienna_download = \"\"\"\n  [timeout:250];\n  (\n    nwr(48.10,16.26,48.26,16.51);\n  );\nout body;\n\u003e;\nout skel qt;\n\"\"\"\ndownload_overpass_query(vienna_download, '/tmp/vienna.osm')\n```\n\nIf I need to iterate over such file I typically use https://github.com/matkoniecz/osm_iterator\n\nFor looking at bounding boxes I typically use http://bboxfinder.com - for example see [`48.10,16.26,48.26,16.51`](http://bboxfinder.com/#48.10,16.26,48.26,16.51)\n\n### Using OSM Editing API\n\nCreate `secret.json` file with\n\n```json\n{\n\t\"bot_account\": {\n\t\t\"username\": \"OSM user name\",\n\t\t\"password\": \"password in plaintext\"\n\t}\n}\n```\n\n```python\nimport osm_bot_abstraction_layer.osm_bot_abstraction_layer as osm_bot_abstraction_layer\nimport json\n\nid = 1\ntype = \"node\"\nreturned = osm_bot_abstraction_layer.get_data(id, type)\njson.dumps(returned, default=str, indent=3)\n```\n\nit will give output like\n\n```json\n{\n   \"id\": 1,\n   \"visible\": true,\n   \"version\": 33,\n   \"changeset\": 124176968,\n   \"timestamp\": \"2022-07-28 09:47:39\",\n   \"user\": \"owene\",\n   \"uid\": 29598,\n   \"lat\": 42.7957187,\n   \"lon\": 13.5690032,\n   \"tag\": {\n      \"communication:microwave\": \"yes\",\n      \"communication:radio\": \"fm\",\n      \"description\": \"Radio Subasio\",\n      \"frequency\": \"105.5 MHz\",\n      \"man_made\": \"mast\",\n      \"name\": \"Monte Piselli - San Giacomo\",\n      \"tower:construction\": \"lattice\",\n      \"tower:type\": \"communication\"\n   }\n}\n```\n\n## Handling note spam\n\n```python\nfrom osm_bot_abstraction_layer import osm_bot_abstraction_layer\nimport osmapi\n\nfor id in range(3158344, 3158710):\n\tprint(id)\n\tdata = osm_bot_abstraction_layer.get_data(id, \"note\")\n\ttext = data['comments'][0]['text']\n\tprint(\"----\")\n\tprint(text)\n\tprint(\"----\")\n\tif text in [\"tf\"]:\n\t\ttry:\n\t\t\tosm_bot_abstraction_layer.close_note(id, \"Bot goes brrrrrrr. Spam cleanup.\", 'bot_account')\n\t\texcept osmapi.errors.NoteAlreadyClosedApiError as e:\n\t\t\tpass\n```\n\n## Show internal administrative division of Iran\n\nSee [docs at OSM Wiki](https://wiki.openstreetmap.org/wiki/Tag:boundary%3Dadministrative#admin_level.3D.2A_Country_specific_values) how internal administrative structure is tagged\n\n```python\nimport osm_bot_abstraction_layer.world_data as world_data\nprint(world_data.list_of_area_division_data('IR', 4, [\"name\", \"wikidata\"], '/tmp/boundary_data.osm'))\n```\n\nReturns list of dicts with names (from `name` tag, so should contain local ones) and wikidata codes.\n\n## Download file\n\n```python\nimport osm_bot_abstraction_layer.util_download_file\n\ndirectory = '/tmp/'\nfilename = 'planet-latest.osm.pbf.torrent'\nurl = 'https://planet.openstreetmap.org/pbf/planet-latest.osm.pbf.torrent'\nosm_bot_abstraction_layer.util_download_file.download_file_if_not_present_already(url, directory, filename)\n```\n\n## List valid `shop=` values\n\n```python\nimport osm_bot_abstraction_layer.tag_knowledge as tag_knowledge\n\nfor value in tag_knowledge.valid_shop_values():\n  print(shop, \"=\", value)\n```\n\n# Further documentation\n\nDocumentation is currently mostly missing - please, open an issue if it would be useful for you (pull requests are also welcomed).\n\n# History and etymology\nI created this library as part of writing [bot editing OpenStreetMap](https://www.openstreetmap.org/user/Mateusz%20Konieczny%20-%20bot%20account/history).\n\nParts of the project built upon [osmapi](https://github.com/metaodi/osmapi) and provide an additional abstraction layer. This part was initial and was source of the project name.\n\n# Project location\n\nThis project resides at [https://github.com/matkoniecz/osm_bot_abstraction_layer](https://github.com/matkoniecz/osm_bot_abstraction_layer)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatkoniecz%2Fosm_bot_abstraction_layer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmatkoniecz%2Fosm_bot_abstraction_layer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatkoniecz%2Fosm_bot_abstraction_layer/lists"}