web.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. from hashlib import sha256
  2. import os
  3. from pathlib import Path
  4. import json
  5. import requests
  6. from flask import Flask, g, redirect, url_for, render_template, jsonify, request, send_from_directory, render_template_string
  7. from . import content_system as h_cs
  8. from . import view_model as h_vm
  9. api = Flask(__name__, static_url_path='')
  10. @api.context_processor
  11. def add_nav_items_to_template_context ():
  12. nav_items = []
  13. route_nav = g.get('route_nav')
  14. if route_nav:
  15. nav_items += route_nav
  16. module_nav = g.get('module_nav')
  17. if module_nav:
  18. nav_items += module_nav
  19. #nav_items.sort(key = lambda ni: ni['order'])
  20. return dict(
  21. nav_items = nav_items
  22. )
  23. @api.get('/login.html')
  24. def get_login_html ():
  25. opengraph_info = dict(
  26. type = 'webpage', # threads might be article
  27. url = g.app_url,
  28. title = 'Hogumathi',
  29. description = 'An app for Twitter, Mastodon, YouTube, etc; Open Source.'
  30. )
  31. return render_template('login.html', opengraph_info=opengraph_info)
  32. @api.get('/')
  33. def index ():
  34. return redirect(url_for('.get_login_html'))
  35. @api.get('/img')
  36. def get_image ():
  37. print('GET IMG')
  38. url = request.args['url']
  39. url_hash = sha256(url.encode('utf-8')).hexdigest()
  40. path = f'.data/cache/media/{url_hash}'
  41. print(f'path = {path}')
  42. if not os.path.exists(path):
  43. resp = requests.get(url)
  44. print(f'status_code = {resp.status_code}')
  45. if resp.status_code >= 200 and resp.status_code < 300:
  46. with open(path, 'wb') as f:
  47. f.write(resp.content)
  48. with open(f'{path}.meta', 'w') as f:
  49. headers = dict(resp.headers)
  50. json.dump(headers, f)
  51. else:
  52. return 'not found.', 404
  53. with open(f'{path}.meta', 'r') as f:
  54. headers = json.load(f)
  55. #print(url)
  56. #print(url_hash)
  57. #print(headers)
  58. # not sure why some responses use lower case.
  59. mimetype = headers.get('Content-Type') or headers.get('content-type')
  60. # Flask goes relative to the module as opposed to the working directory.
  61. media_cache_dir = Path(Path.cwd(), '.data/cache/media')
  62. return send_from_directory(media_cache_dir, url_hash, mimetype=mimetype)
  63. @api.get('/content/abc123.html')
  64. def get_abc123_html ():
  65. return 'abc123'
  66. @api.get('/content/<content_id>.<response_format>')
  67. def get_content_html (content_id, response_format='json', content_kwargs=None):
  68. if not content_kwargs:
  69. content_kwargs = filter(lambda e: e[0].startswith('content:'), request.args.items())
  70. content_kwargs = dict(map(lambda e: [e[0][len('content:'):], e[1]], content_kwargs))
  71. content = h_cs.get_content(content_id, **content_kwargs)
  72. if type(content) == h_vm.FeedItem:
  73. return render_template('tweet-collection.html', tweets=[content], user = {}, query = {})
  74. elif type(content) == h_vm.CollectionPage:
  75. pagination_token = request.args.get('pagination_token')
  76. if content.next_token:
  77. print(f'next_token = {content.next_token}')
  78. return render_template('tweet-collection.html', tweets=content.items, user = {}, query = {})
  79. elif type(content) == list:
  80. return render_template('tweet-collection.html', tweets=content, user = {}, query = {})
  81. else:
  82. return jsonify(content)
  83. @api.get('/content/def456.html')
  84. def get_def456_html ():
  85. return get_content_html('brand:ispoogedaily', response_format='html')
  86. @api.get('/content/search.<response_format>')
  87. def get_content_search_html (response_format = 'html'):
  88. source_id = request.args.get('source')
  89. q = request.args.get('q')
  90. pagination_token = request.args.get('pagination_token')
  91. max_results = int(request.args.get('limit', 10))
  92. # search object store
  93. # search origin sources
  94. # populate object store with results
  95. # similar to how messages app works. Multiple sources within one app.
  96. # That app does not cache results tho, does an online search with each query.
  97. return 'ok'
  98. @api.get('/schedule/jobs.html')
  99. def get_schedule_jobs_html ():
  100. template = """
  101. {% extends "base-bs.html" %}
  102. {% block content %}
  103. {% endblock %}
  104. """
  105. view_model = {
  106. 'jobs': [
  107. {
  108. 'id': '1234',
  109. 'next_run': '',
  110. 'last_run': '',
  111. 'interval': 1,
  112. 'unit': 'minutes',
  113. 'period': '', # period vs. interval?
  114. 'latest': '',
  115. 'start_day': '',
  116. 'cancel_after': ''
  117. }
  118. ]
  119. }
  120. return render_template_string(template, **view_model)
  121. @api.get('/schedule/create-job.html')
  122. def get_schedule_create_job_html ():
  123. template = """
  124. {% extends "base-bs.html" %}
  125. {% block content %}
  126. {% endblock %}
  127. """
  128. view_model = {
  129. }
  130. return render_template_string(template, **view_model)
  131. @api.get('/health')
  132. def get_health ():
  133. return 'ok'