util.py 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. from collections.abc import Callable, Coroutine
  2. from typing import TypeVar, Any
  3. from datetime import datetime
  4. from aiohttp import ClientSession
  5. from ..types import Message, Context, Attachment, Command
  6. from .base import Injector, InjectorWithCleanup
  7. __all__ = [
  8. "Lazy",
  9. "MessageInjector",
  10. "ContextInjector",
  11. "Origin",
  12. "Channel",
  13. "Sender",
  14. "Timestamp",
  15. "OriginAdmin",
  16. "ChannelAdmin",
  17. "Text",
  18. "Attachments",
  19. "CommandInjector",
  20. "Request",
  21. "Respond",
  22. "Config",
  23. ]
  24. Dep = TypeVar("Dep")
  25. class Simple(Injector[Dep]):
  26. def __init__(self, extract: Callable[[Message, Context], Dep]):
  27. self.extract = extract
  28. async def inject(self, message: Message, context: Context) -> Dep:
  29. return self.extract(message, context)
  30. MessageInjector = Simple[Message](lambda m, c: m)
  31. ContextInjector = Simple[Context](lambda m, c: c)
  32. Origin = Simple[str](lambda m, c: m.origin_id)
  33. Channel = Simple[str](lambda m, c: m.channel_id)
  34. Sender = Simple[str](lambda m, c: m.sender_id)
  35. Timestamp = Simple[datetime](lambda m, c: m.timestamp)
  36. OriginAdmin = Simple[bool](lambda m, c: m.origin_admin)
  37. ChannelAdmin = Simple[bool](lambda m, c: m.channel_admin)
  38. Text = Simple[str](lambda m, c: m.text)
  39. Attachments = Simple[list[Attachment]](lambda m, c: m.attachments)
  40. CommandInjector = Simple[Command](lambda m, c: m.command)
  41. Request = Simple[ClientSession](lambda m, c: c.request)
  42. Respond = Simple[Callable[[], Coroutine[None, None, None]]](lambda m, c: c.respond)
  43. class Config(Injector[Any]):
  44. def __init__(self, key: str):
  45. self.key = key
  46. async def inject(self, message: Message, context: Context) -> Any:
  47. return context.config(self.key)
  48. class Lazy(InjectorWithCleanup[Callable[[], Coroutine[None, None, Dep]]]):
  49. def __init__(self, deferred: Injector[Dep]):
  50. self.deferred = deferred
  51. async def inject(
  52. self, message: Message, context: Context
  53. ) -> Callable[[], Coroutine[None, None, Dep]]:
  54. class _Wrapper:
  55. def __init__(self, deferred):
  56. self._calculated = None
  57. async def call():
  58. if self._calculated is None:
  59. self._calculated = await deferred.inject(message, context)
  60. return self._calculated
  61. self._call = call
  62. def __call__(self):
  63. return self._call()
  64. return _Wrapper(self.deferred)
  65. async def cleanup(self, dep: Callable[[], Coroutine[None, None, Dep]]):
  66. if isinstance(self.deferred, InjectorWithCleanup) and dep._calculated is not None:
  67. await self.deferred.cleanup(dep._calculated)