aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2025-03-31 19:48:21 +0200
committerLinnea Gräf <nea@nea.moe>2025-03-31 19:48:21 +0200
commit0042768a3046a52ba50a9550a6b11dc616fa6ba7 (patch)
tree11229b2ba4599ae558f78dfbf26d47c25eaf8639
parent872030a69e936305789b6417fb83db0364aef447 (diff)
downloadadultnea-0042768a3046a52ba50a9550a6b11dc616fa6ba7.tar.gz
adultnea-0042768a3046a52ba50a9550a6b11dc616fa6ba7.tar.bz2
adultnea-0042768a3046a52ba50a9550a6b11dc616fa6ba7.zip
feat: Add rust/crates.io package search
-rw-r--r--adultnea/client.py6
-rw-r--r--adultnea/modules/pkgssearch.py48
2 files changed, 44 insertions, 10 deletions
diff --git a/adultnea/client.py b/adultnea/client.py
index 01c2d6d..da2429a 100644
--- a/adultnea/client.py
+++ b/adultnea/client.py
@@ -34,7 +34,11 @@ class AdultClient(commands.Bot):
async def setup_hook(self) -> None:
await self.reload_all()
- self.http_session = aiohttp.ClientSession(loop=self.loop)
+ self.http_session = aiohttp.ClientSession(
+ loop=self.loop,
+ headers={
+ 'user-agent': aiohttp.http.SERVER_SOFTWARE + " AdultNea (github.com/nea89o/adultnea/)"
+ })
async def reload_all(self):
base_path = Path(__file__).parent / 'modules'
diff --git a/adultnea/modules/pkgssearch.py b/adultnea/modules/pkgssearch.py
index 563c230..7f6ba60 100644
--- a/adultnea/modules/pkgssearch.py
+++ b/adultnea/modules/pkgssearch.py
@@ -1,16 +1,11 @@
import abc
-import asyncio
import dataclasses
import datetime
-import logging
import urllib.parse
from abc import abstractmethod
-from sys import prefix
from typing import TypedDict, Optional
-import aiohttp
import discord.ext.commands as commands
-import discord
from adultnea.client import AdultClient, Context
from adultnea.utils import join_till_limit
@@ -85,8 +80,43 @@ class SMOSearch(Search):
return JAVA_LABELS + ['smo']
+class CratesIOSearch(Search):
+ class Response(TypedDict):
+ crates: list['CratesIOSearch.Crate']
+
+ class Crate(TypedDict):
+ id: str
+ name: str
+ max_version: str
+ description: str
+ num_versions: int
+ updated_at: str
+ """A timestamp in ISO 8601"""
+ documentation: str
+
+ def labels(self) -> list[str]:
+ return ['rust', 'rs', 'cargo', 'crate', 'crates']
+
+ async def search(self, client: AdultClient, name: str) -> list[Package]:
+ async with client.http_session.get(mkurl('https://crates.io/api/v1/crates', q=name, per_page="20")) as resp:
+ j: CratesIOSearch.Response = await resp.json()
+ return [
+ Package(
+ it['id'],
+ it['name'],
+ f'https://crates.io/crates/{it['id']}',
+ it['max_version'],
+ it['num_versions'],
+ datetime.datetime.fromisoformat(it['updated_at']),
+ 'crates.io'
+ )
+ for it in j['crates']
+ ]
+
+
searches = [
- SMOSearch()
+ SMOSearch(),
+ CratesIOSearch(),
]
assert all(tag.casefold() == tag
@@ -94,7 +124,7 @@ assert all(tag.casefold() == tag
for tag in search.labels())
-@commands.group(invoke_without_command=True)
+@commands.group(invoke_without_command=True, aliases=['pkgs'])
async def pkg(ctx: Context,
tag: str, *,
search: str):
@@ -110,8 +140,8 @@ async def pkg(ctx: Context,
return
message = join_till_limit(
'\n',
- (f'- [`{it.id}`@`{it.latestVersion}`]({it.link})' for it in packages),
- prefix=f'Packages ({len(packages)}):\n',
+ (f'- [`{it.id}`@`{it.latestVersion}`](<{it.link}>)' for it in packages),
+ prefix=f'Packages:\n',
)
await ctx.followup(message)