pyapi.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. # Copyright (c) Daniel Sheffield 2022 - 2024
  2. # All rights reserved.
  3. from bottle import route, request, run, template, response, abort, static_file
  4. import psycopg
  5. from psycopg import Cursor
  6. from psycopg.sql import SQL, Literal
  7. import os
  8. host = f"host={os.getenv('HOST')}"
  9. db = f"dbname={os.getenv('DB', 'pgdb')}"
  10. user = f"user={os.getenv('USER', 'pgdb')}"
  11. password = f"password={os.getenv('PASSWORD','')}"
  12. if not password.split('=',1)[1]:
  13. password = ''
  14. conn: Cursor = psycopg.connect(f"{host} {db} {user} {password}")
  15. @route('/pyapi/random')
  16. def random():
  17. try:
  18. with conn.cursor() as cur:
  19. inner = SQL("""
  20. SELECT category, translation, reference, txt
  21. FROM pg_random_view_default_if_null
  22. JOIN pg_categories ON category = name
  23. ORDER BY tableid ASC
  24. """)
  25. xml = cur.execute(SQL("""
  26. SELECT query_to_xml_and_xmlschema({q}, false, false, ''::text);
  27. """).format(q=inner.as_string(cur))).fetchone()[0]
  28. finally:
  29. conn.commit()
  30. response.content_type = 'application/xhtml+xml; charset=utf-8'
  31. return template("rest/query-to-xml", title="Random Prayer Generator", xml=xml)
  32. @route('/pyapi/xslt')
  33. def table():
  34. response.content_type = 'application/xhtml+xml; charset=utf-8'
  35. return static_file("query-to-xml-xslt.xml", root="rest")
  36. @route('/pyapi/pg')
  37. def specified():
  38. kingdom = { 'a_kingdom', 'z_kingdom' }
  39. categories = [ k for k in request.query.keys() ]
  40. translations = []
  41. references = []
  42. for c in categories:
  43. try:
  44. r, t = request.query[c].split(' ', 1)
  45. except ValueError:
  46. raise abort(
  47. 400,
  48. f"Could not parse value for {c}."
  49. f" Given: {request.query[c]}"
  50. )
  51. if None in (r or None, t or None,):
  52. raise abort(
  53. 400,
  54. f"Both reference and translation must be provided for {c}."
  55. f" Given: {request.query[c]}"
  56. )
  57. references.append(r)
  58. translations.append(t)
  59. if len(kingdom - set(categories)) not in (0, 2,):
  60. raise abort(
  61. 400,
  62. f"Both of {kingdom} must be specified or neither specified."
  63. f" Missing: {kingdom - set(categories)}"
  64. )
  65. try:
  66. with conn.cursor() as cur:
  67. inner = SQL("""
  68. SELECT category, translation, reference, txt
  69. FROM getprayer(
  70. {categories}::text[],
  71. {translations}::text[],
  72. {references}::text[]
  73. ) ORDER BY ordinal ASC
  74. """).format(
  75. categories=Literal(categories),
  76. translations=Literal(translations),
  77. references=Literal(references)
  78. )
  79. xml = cur.execute(SQL("""
  80. SELECT query_to_xml_and_xmlschema({q}, false, false, ''::text);
  81. """).format(q=Literal(inner.as_string(cur)))).fetchone()[0]
  82. finally:
  83. conn.commit()
  84. response.content_type = 'application/xhtml+xml; charset=utf-8'
  85. return template("rest/query-to-xml", title="Prayer Generator", xml=xml)
  86. run(host='0.0.0.0', port=11888)