# curse-api
----
## A simple async python Curseforge api wrapper using pydantic
Built to serve CF endpoints while providing methods and functions to assist in finding the right mod.
- Quick Install: `pip install curse-api[quick]`
- [Features](#features)
- [Quick Start](#quick-start)
- [Examples](#examples)
----
## Some backstory
A while back when I was starting to learn python further then the basics I created a small tool to download Minecraft mods from a pack manifest.
Soon after I wrote it the new API changes came and broke it. Now once more I want to return to that project idea and expand further. After first rewriting the project using [chili](https://pypi.org/project/chili/) it felt off, so returned to rewrite once more using [pydantic](https://pypi.org/project/pydantic/) for data validation and ease of access. This is mostly a pet project to learn further python.
----
## Features
Main Dependency:
- [Pydantic](https://pypi.org/project/pydantic/)
Native async library support:
- [Aiohttp](https://pypi.org/project/aiohttp/) - `pip install curse-api[aiohttp]`
- [Httpx](https://pypi.org/project/httpx/) - `pip install curse-api[httpx]`
Currently implemented:
- Important endpoint support
- Full CurseForge model
- Mediocre error handling
- Pluggable API factories
- Serialization and deserialization of models
- Python 3.7, 3.8 & 3.9 support
- Async
To Do:
- Fix to be usable with pydantic based ORM's
- Address all TODO's
- Test other games too
- Add more
- Write docs
- Update and fix error handling
- Shortcuts to import clients
CI/CD:
- Type checking
- Version testing
- Tests
----
## Examples
### Quick start
Requires an api from CF to use the API. You can get one [here](https://docs.curseforge.com/#authentication).
This example runs through most of the basics
```python
from curse_api import CurseAPI
from curse_api.clients.httpx import HttpxFactory
import os
import asyncio
async def main():
async with CurseAPI(os.environ["CF_API_KEY"], factory=HttpxFactory) as api:
"Mods"
a = await api.search_mods(searchFilter="JEI", slug="jei")
# applies the search filters to the standard of CF docs
mod = await api.get_mod(250398) # returns a singular Mod
mod_list = await api.get_mods([285109, 238222]) # returns a list of Mods
"files"
"See examples/download.py"
# TODO finish file support
files = await api.get_files([3940240]) # returns a list of Files matching their id
mod_files = await api.get_mod_files(238222) # returns all the Files of on a give Mod
"Version details - large data"
"See examples/modloader.py"
mc = await api.minecraft_versions() # returns all of minecraft version data
ml = await api.modloader_versions() # returns **ALL** modloader versions on curseforge
mc_112 = await api.get_specific_minecraft_version("1.12.2") # returns minecraft version related information
forge = await api.get_specific_minecraft_modloader("forge-36.2.39") # returns forge related version information
if __name__ == "__main__":
asyncio.run(main())
```
### Downloading to a file
This example opens a properly named file in the current working directory and writes to it.
```python
from curse_api import CurseAPI
from curse_api.clients.httpx import HttpxFactory
import os
import asyncio
async def main():
async with CurseAPI(os.environ["CF_API_KEY"], factory=HttpxFactory) as api:
# fetch the latest file from project with slug 'jei'
mod_l, page_data = await api.search_mods(slug="jei")
latest = mod_l[0].latestFiles[0]
with open(latest.fileName, "wb") as f:
down = await api.download(latest.downloadUrl) # type: ignore
async for b in down:
f.write(b)
if __name__ == "__main__":
asyncio.run(main())
```
----
### Sub project / extension ideas
- Modloader download and installation
- Minecraft Version type / parser
- MC pack installation
- DB cache extension
- Manifest parsing
Raw data
{
"_id": null,
"home_page": "https://github.com/Stinky-c/curse-api",
"name": "curse-api",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.7,<4.0",
"maintainer_email": "",
"keywords": "curseforge,api wrapper",
"author": "Stinky-c",
"author_email": "60587749+Stinky-c@users.noreply.github.com",
"download_url": "https://files.pythonhosted.org/packages/b5/28/b3977019b204f6923c2000be377cc864a1e99bc81306d94b306f019f056b/curse_api-3.1.2.tar.gz",
"platform": null,
"description": "# curse-api\n\n----\n\n## A simple async python Curseforge api wrapper using pydantic\n\nBuilt to serve CF endpoints while providing methods and functions to assist in finding the right mod.\n\n- Quick Install: `pip install curse-api[quick]`\n- [Features](#features)\n- [Quick Start](#quick-start)\n- [Examples](#examples)\n\n----\n\n## Some backstory\n\nA while back when I was starting to learn python further then the basics I created a small tool to download Minecraft mods from a pack manifest.\nSoon after I wrote it the new API changes came and broke it. Now once more I want to return to that project idea and expand further. After first rewriting the project using [chili](https://pypi.org/project/chili/) it felt off, so returned to rewrite once more using [pydantic](https://pypi.org/project/pydantic/) for data validation and ease of access. This is mostly a pet project to learn further python.\n\n----\n\n## Features\n\nMain Dependency:\n\n- [Pydantic](https://pypi.org/project/pydantic/)\n\nNative async library support:\n\n- [Aiohttp](https://pypi.org/project/aiohttp/) - `pip install curse-api[aiohttp]`\n- [Httpx](https://pypi.org/project/httpx/) - `pip install curse-api[httpx]`\n\nCurrently implemented:\n\n- Important endpoint support\n- Full CurseForge model\n- Mediocre error handling\n- Pluggable API factories\n- Serialization and deserialization of models\n- Python 3.7, 3.8 & 3.9 support\n- Async\n\nTo Do:\n\n- Fix to be usable with pydantic based ORM's\n- Address all TODO's\n- Test other games too\n- Add more\n- Write docs\n- Update and fix error handling\n- Shortcuts to import clients\n\nCI/CD:\n\n- Type checking\n- Version testing\n- Tests\n\n----\n\n## Examples\n\n### Quick start\n\nRequires an api from CF to use the API. You can get one [here](https://docs.curseforge.com/#authentication).\nThis example runs through most of the basics\n\n```python\nfrom curse_api import CurseAPI\nfrom curse_api.clients.httpx import HttpxFactory\nimport os\nimport asyncio\n\n\nasync def main():\n async with CurseAPI(os.environ[\"CF_API_KEY\"], factory=HttpxFactory) as api:\n\n \"Mods\"\n a = await api.search_mods(searchFilter=\"JEI\", slug=\"jei\")\n # applies the search filters to the standard of CF docs\n\n mod = await api.get_mod(250398) # returns a singular Mod\n mod_list = await api.get_mods([285109, 238222]) # returns a list of Mods\n\n \"files\"\n \"See examples/download.py\"\n # TODO finish file support\n files = await api.get_files([3940240]) # returns a list of Files matching their id\n mod_files = await api.get_mod_files(238222) # returns all the Files of on a give Mod\n\n \"Version details - large data\"\n \"See examples/modloader.py\"\n mc = await api.minecraft_versions() # returns all of minecraft version data\n ml = await api.modloader_versions() # returns **ALL** modloader versions on curseforge\n\n mc_112 = await api.get_specific_minecraft_version(\"1.12.2\") # returns minecraft version related information\n forge = await api.get_specific_minecraft_modloader(\"forge-36.2.39\") # returns forge related version information\n\n\nif __name__ == \"__main__\":\n asyncio.run(main())\n```\n\n### Downloading to a file\n\nThis example opens a properly named file in the current working directory and writes to it.\n\n```python\nfrom curse_api import CurseAPI\nfrom curse_api.clients.httpx import HttpxFactory\nimport os\nimport asyncio\n\n\nasync def main():\n async with CurseAPI(os.environ[\"CF_API_KEY\"], factory=HttpxFactory) as api:\n\n # fetch the latest file from project with slug 'jei'\n mod_l, page_data = await api.search_mods(slug=\"jei\")\n latest = mod_l[0].latestFiles[0]\n\n with open(latest.fileName, \"wb\") as f:\n down = await api.download(latest.downloadUrl) # type: ignore\n async for b in down:\n f.write(b)\n\n\nif __name__ == \"__main__\":\n asyncio.run(main())\n\n```\n\n----\n\n### Sub project / extension ideas\n\n- Modloader download and installation\n- Minecraft Version type / parser\n- MC pack installation\n- DB cache extension\n- Manifest parsing\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A simple curseforge api wrapper",
"version": "3.1.2",
"split_keywords": [
"curseforge",
"api wrapper"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "93d16d33540fc405cbbef5f7b897aaba5eb408140d14495f666abb1eea2c53ab",
"md5": "7c1f627ebc61bab901cbf9f3b28d9073",
"sha256": "457ae608b1f8a021ebafa0db42950f291e502a35cc77ea28afb19ad192a51ab9"
},
"downloads": -1,
"filename": "curse_api-3.1.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "7c1f627ebc61bab901cbf9f3b28d9073",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7,<4.0",
"size": 19305,
"upload_time": "2023-04-20T15:54:31",
"upload_time_iso_8601": "2023-04-20T15:54:31.680047Z",
"url": "https://files.pythonhosted.org/packages/93/d1/6d33540fc405cbbef5f7b897aaba5eb408140d14495f666abb1eea2c53ab/curse_api-3.1.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "b528b3977019b204f6923c2000be377cc864a1e99bc81306d94b306f019f056b",
"md5": "b377272ccfb2db438ae4904eb3f81d27",
"sha256": "acc2b5b7002f5ceff35562b455ca9e00f334cf55bd27c56331cc4cf19be31596"
},
"downloads": -1,
"filename": "curse_api-3.1.2.tar.gz",
"has_sig": false,
"md5_digest": "b377272ccfb2db438ae4904eb3f81d27",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7,<4.0",
"size": 17324,
"upload_time": "2023-04-20T15:54:33",
"upload_time_iso_8601": "2023-04-20T15:54:33.319833Z",
"url": "https://files.pythonhosted.org/packages/b5/28/b3977019b204f6923c2000be377cc864a1e99bc81306d94b306f019f056b/curse_api-3.1.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-04-20 15:54:33",
"github": true,
"gitlab": false,
"bitbucket": false,
"github_user": "Stinky-c",
"github_project": "curse-api",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"tox": true,
"lcname": "curse-api"
}