util.py 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. from collections.abc import Callable, Coroutine
  2. from typing import TypeVar, Any
  3. from datetime import datetime
  4. from logging import Logger
  5. from aiohttp import ClientSession
  6. from ..types import Message, Context, Attachment, Command
  7. from .base import Injector, InjectorWithCleanup, Simple
  8. __all__ = [
  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. "LoggerInjector",
  23. "Config",
  24. "Lazy",
  25. ]
  26. MessageInjector = Simple[Message](lambda m, c: m)
  27. ContextInjector = Simple[Context](lambda m, c: c)
  28. Origin = Simple[str](lambda m, c: m.origin_id)
  29. Channel = Simple[str](lambda m, c: m.channel_id)
  30. Sender = Simple[str](lambda m, c: m.sender_id)
  31. Timestamp = Simple[datetime](lambda m, c: m.timestamp)
  32. OriginAdmin = Simple[bool](lambda m, c: m.origin_admin)
  33. ChannelAdmin = Simple[bool](lambda m, c: m.channel_admin)
  34. Text = Simple[str](lambda m, c: m.text)
  35. Attachments = Simple[list[Attachment]](lambda m, c: m.attachments)
  36. CommandInjector = Simple[Command](lambda m, c: m.command)
  37. Request = Simple[ClientSession](lambda m, c: c.request)
  38. Respond = Simple[Callable[[], Coroutine[None, None, None]]](lambda m, c: c.respond)
  39. # TODO might be nice to auto format with command name
  40. LoggerInjector = Simple[Logger](lambda m, c: c.logger)
  41. class Config(Injector[Any]):
  42. def __init__(self, key: str):
  43. self.key = key
  44. async def inject(self, message: Message, context: Context) -> Any:
  45. return context.config(self.key)
  46. Dep = TypeVar("Dep")
  47. class Lazy(InjectorWithCleanup[Callable[[], Coroutine[None, None, Dep]]]):
  48. def __init__(self, deferred: Injector[Dep]):
  49. self.deferred = deferred
  50. async def inject(
  51. self, message: Message, context: Context
  52. ) -> Callable[[], Coroutine[None, None, Dep]]:
  53. class _Wrapper:
  54. def __init__(self, deferred):
  55. self._calculated = None
  56. async def call():
  57. if self._calculated is None:
  58. self._calculated = await deferred.inject(message, context)
  59. return self._calculated
  60. self._call = call
  61. def __call__(self):
  62. return self._call()
  63. return _Wrapper(self.deferred)
  64. async def cleanup(self, dep: Callable[[], Coroutine[None, None, Dep]]):
  65. if isinstance(self.deferred, InjectorWithCleanup) and dep._calculated is not None:
  66. await self.deferred.cleanup(dep._calculated)