geotools.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. # ______ ______ ______ ______ ______ __ ______ ______
  2. # /\ ___\ /\ == \ /\ ___\ /\ __ \ /\__ _\ /\ \ /\___ \ /\ ___\
  3. # \ \ \____ \ \ __< \ \ __\ \ \ __ \ \/_/\ \/ \ \ \ \/_/ /__ \ \ __\
  4. # \ \_____\ \ \_\ \_\ \ \_____\ \ \_\ \_\ \ \_\ \ \_\ /\_____\ \ \_____\
  5. # \/_____/ \/_/ /_/ \/_____/ \/_/\/_/ \/_/ \/_/ \/_____/ \/_____/
  6. # Code is licensed under CC-BY-NC-ND 4.0 unless otherwise specified.
  7. # https://creativecommons.org/licenses/by-nc-nd/4.0/
  8. # You CANNOT edit this file without direct permission from the author.
  9. # You can redistribute this file without any changes.
  10. # meta developer: @creaz_mods
  11. # scope: hikka_min 1.6.2
  12. # reqires: geopy
  13. from ast import literal_eval
  14. from functools import partial
  15. from geopy import distance
  16. from geopy.geocoders import Nominatim
  17. from hikkatl import functions, types
  18. from hikkatl.types import Message
  19. from .. import loader, utils
  20. @loader.tds
  21. class GeoTools(loader.Module):
  22. """Some geographic tools"""
  23. strings = {
  24. "name": "GeoTools",
  25. "no_args": (
  26. "<emoji document_id=5260342697075416641>❌</emoji> <b>You did not specify"
  27. " arguments</b>"
  28. ),
  29. "no_place": (
  30. "<emoji document_id=5260342697075416641>❌</emoji> <b>Place {} not"
  31. " found</b>"
  32. ),
  33. "result": (
  34. "<emoji document_id=5413689758440237842>▶️</emoji> From: {fromd}\n<emoji"
  35. " document_id=5413557786980134319>▶️</emoji> To: {to}\n<emoji"
  36. " document_id=5877464772353460958>✈️</emoji> Distance: {dist} kilometers"
  37. ),
  38. "langcode": "en",
  39. "point": (
  40. "<emoji document_id=5460795800101594035>🗣️</emoji> <b>Your query:</b>"
  41. " {args}\n<emoji document_id=5206607081334906820>✔️</emoji> <b>Result:</b>"
  42. " <code>{res}</code>"
  43. ),
  44. }
  45. strings_ru = {
  46. "no_args": (
  47. "<emoji document_id=5260342697075416641>❌</emoji> <b>Вы не указали"
  48. " аргументы</b>"
  49. ),
  50. "no_place": (
  51. "<emoji document_id=5260342697075416641>❌</emoji> <b>Место {} не"
  52. " найдено</b>"
  53. ),
  54. "result": (
  55. "<emoji document_id=5413689758440237842>▶️</emoji> Из: {fromd}\n<emoji"
  56. " document_id=5413557786980134319>▶️</emoji> В: {to}\n<emoji"
  57. " document_id=5877464772353460958>✈️</emoji> Расстояние: {dist} километров"
  58. ),
  59. "langcode": "ru",
  60. "point": (
  61. "<emoji document_id=5460795800101594035>🗣️</emoji> <b>Ваш запрос:</b>"
  62. " {args}\n<emoji document_id=5206607081334906820>✔️</emoji>"
  63. " <b>Результат:</b> <code>{res}</code>"
  64. ),
  65. }
  66. strings_es = {
  67. "no_args": (
  68. "<emoji document_id = 5260342697075416641>❌</emoji> <b>No especificaste"
  69. " argumentos</b>"
  70. ),
  71. "no_place": (
  72. "<emoji document_id=5260342697075416641>❌</emoji> <b>No se encontró el"
  73. " lugar {}</b>"
  74. ),
  75. "result": (
  76. "<emoji document_id = 5413689758440237842>▶️</emoji> Desde: {fromd}\n<emoji"
  77. " document_id = 5413557786980134319>▶️</emoji> A: {to}\n<emoji"
  78. " document_id=5877464772353460958>✈️</emoji> Distancia: {dist} kilómetros"
  79. ),
  80. "langcode": "es",
  81. "point": (
  82. "<emoji document_id=5460795800101594035>🗣️</emoji> <b>Su consulta:</b>"
  83. " {args}\n<emoji document_id=5206607081334906820>✔️</emoji>"
  84. " <b>Resultado:</b> <code>{res}</code>"
  85. ),
  86. }
  87. strings_de = {
  88. "no_args": (
  89. "<emoji document_id=5260342697075416641>❌</emoji> <b>Sie haben keine"
  90. " Argumente angegeben</b>"
  91. ),
  92. "no_place": (
  93. "<emoji document_id=5260342697075416641>❌</emoji> <b>No se encontró el"
  94. " lugar {}</b>"
  95. ),
  96. "result": (
  97. "<emoji document_id=5413689758440237842>▶️</emoji> Von: {fromd}\n<emoji"
  98. " document_id=5413557786980134319>▶️</emoji> Nach: {to}\n<emoji"
  99. " document_id=5877464772353460958>✈️</emoji> Entfernung: {dist} Kilometer"
  100. ),
  101. "langcode": "de",
  102. "point": (
  103. "<emoji document_id=5460795800101594035>🗣️</emoji> <b>Ihre Abfrage:</b>"
  104. " {args}\n<emoji document_id=5206607081334906820>✔️</emoji> <b>Ergebnis:</b>"
  105. " <code>{res}</code>"
  106. ),
  107. }
  108. @loader.command(
  109. ru_doc=(
  110. "- определяет расстояние между двумя точками. Можно указать координаты в"
  111. " скобках, можно сразу указать место. Разделять два места через |"
  112. ),
  113. es_doc=(
  114. "- determina la distancia entre dos puntos. Puede especificar las"
  115. " coordenadas entre paréntesis o puede especificar el lugar directamente."
  116. " Separe los dos lugares con |"
  117. ),
  118. de_doc=(
  119. "- ermittelt die Entfernung zwischen zwei Punkten. Sie können die"
  120. " Koordinaten in Klammern angeben oder den Ort direkt angeben. Trennen Sie"
  121. " die beiden Orte mit einem |"
  122. ),
  123. )
  124. async def geodist(self, m: Message):
  125. """- specifies the distance between two points. You can specify the coordinates in brackets or just a place. Split two places via |"""
  126. args = utils.get_args_split_by(m, "|")
  127. if len(args) != 2:
  128. return await utils.answer(m, self.strings["no_args"])
  129. client = Nominatim(user_agent="Hikka")
  130. geocode = partial(client.geocode, language=self.strings["langcode"])
  131. reverse = partial(client.reverse, language=self.strings["langcode"])
  132. try:
  133. args[0] = tuple(literal_eval(args[0]))
  134. args[1] = tuple(literal_eval(args[1]))
  135. place0 = geocode(args[0])
  136. place1 = geocode(args[1])
  137. if not place0:
  138. return await utils.answer(m, self.strings["no_place"].format(args[0]))
  139. if not place1:
  140. return await utils.answer(m, self.strings["no_place"].format(args[1]))
  141. from_coord = args[0]
  142. to_coord = args[1]
  143. dist = round(distance.distance(from_coord, to_coord).km, 2)
  144. from_address = reverse(from_coord).address
  145. to_address = reverse(to_coord).address
  146. await utils.answer(
  147. m,
  148. self.strings["result"].format(
  149. fromd=from_address, to=to_address, dist=dist
  150. ),
  151. )
  152. except:
  153. place0 = geocode(args[0])
  154. place1 = geocode(args[1])
  155. if not place0:
  156. return await utils.answer(m, self.strings["no_place"].format(args[0]))
  157. if not place1:
  158. return await utils.answer(m, self.strings["no_place"].format(args[1]))
  159. from_coord = (
  160. place0.latitude,
  161. place1.longitude,
  162. )
  163. to_coord = (
  164. place0.latitude,
  165. place1.longitude,
  166. )
  167. dist = round(distance.distance(from_coord, to_coord).km, 2)
  168. await utils.answer(
  169. m,
  170. self.strings["result"].format(
  171. fromd=place0,
  172. to=place1,
  173. dist=dist,
  174. ),
  175. )
  176. @loader.command(
  177. ru_doc="- отправляет полное название места",
  178. de_doc="- sendet den vollständigen Namen eines Ortes",
  179. es_doc="- envía el nombre completo de una ubicación",
  180. )
  181. async def point(self, m: Message):
  182. """Sends the full name of a location"""
  183. args = utils.get_args_raw(m)
  184. if not (args):
  185. return await utils.answer(m, self.strings["no_args"])
  186. client = Nominatim(user_agent="Hikka")
  187. geocode = partial(client.geocode, language=self.strings["langcode"])
  188. place = geocode(args)
  189. if not place:
  190. return await utils.answer(m, self.strings["no_place"].format(args))
  191. await utils.answer(m, self.strings["point"].format(args=args, res=place))
  192. @loader.command(
  193. ru_doc="- отправляет координаты места",
  194. de_doc="- sendet die Koordinaten des Ortes",
  195. es_doc="- envía las coordenadas del lugar",
  196. )
  197. async def coords(self, m: Message):
  198. """- sends the coordinates of the location"""
  199. args = utils.get_args_raw(m)
  200. if not args:
  201. return await utils.answer(m, self.strings["no_args"])
  202. client = Nominatim(user_agent="Hikka")
  203. geocode = partial(client.geocode, language=self.strings["langcode"])
  204. place = geocode(args)
  205. if not place:
  206. return await utils.answer(m, self.strings["no_place"].format(args))
  207. await utils.answer(
  208. m,
  209. self.strings["point"].format(
  210. args=args, res=f"{place.latitude}, {place.longitude}"
  211. ),
  212. )
  213. @loader.command(
  214. ru_doc="- отправляет геопозицию",
  215. es_doc="- envía la ubicación geográfica",
  216. de_doc="- sendet den Geostandort",
  217. )
  218. async def geo(self, m: Message):
  219. """- sends geoposition"""
  220. args = utils.get_args_raw(m)
  221. if await m.get_reply_message():
  222. r = await m.get_reply_message()
  223. else:
  224. r = m
  225. if not args:
  226. return await utils.answer(m, self.strings["no_args"])
  227. client = Nominatim(user_agent="Hikka")
  228. geocode = partial(client.geocode, language=self.strings["langcode"])
  229. if "-c" in args:
  230. args = args.replace("-c", "")
  231. place = tuple(literal_eval(args))
  232. else:
  233. args = args.replace("-c", "")
  234. place = geocode(args)
  235. place = (place.latitude, place.longitude)
  236. if not place:
  237. return await utils.answer(m, self.strings["no_place"].format(args))
  238. await m.delete()
  239. await m.client(
  240. functions.messages.SendMediaRequest(
  241. peer=m.chat_id,
  242. media=types.InputMediaGeoPoint(
  243. geo_point=types.InputGeoPoint(place[0], place[1])
  244. ),
  245. message="",
  246. reply_to_msg_id=r.id,
  247. )
  248. )