routes.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. from bottle import request, response, abort, redirect, static_file
  2. from kddit import app
  3. from urllib.parse import urlparse, parse_qs
  4. from kddit.settings import *
  5. from kddit.utils import req, success, get_thumbnail, ydl
  6. from kddit import html
  7. from kddit.utils import tuplefy as t
  8. from kddit.utils import verify_subreddit_option, verify_user_option
  9. from kddit.utils import get_subreddit_url, get_subreddit
  10. from kddit.utils import nsfw_mode, get_query
  11. def subreddit_content(data, subreddit, option, time, safe):
  12. content = (html.subreddit_menu(option, subreddit))
  13. if option in EXPANDED_OPTIONS:
  14. content += (html.subreddit_sort_menu(subreddit, option or DEFAULT_OPTION, time))
  15. content += (html.mixed_content(data, safe) or html.nothing,)
  16. content += html.subreddit_nav(data, subreddit, option, time)
  17. return content
  18. def search_content(data, subreddit, sort, time, query):
  19. content = html.search_sort_menu(subreddit, query)
  20. content += html.search_time_menu(subreddit, query )
  21. content += html.mixed_content(data, True) or html.nothing
  22. content += html.search_nav(data, subreddit, query)
  23. return content
  24. def domain_content(data, domain, option, time):
  25. content = html.domain_menu(option, domain)
  26. if option in EXPANDED_OPTIONS:
  27. content += html.domain_sort_menu(domain, option or DEFAULT_OPTION, time)
  28. content += html.mixed_content(data, True) or html.nothing
  29. content += html.domain_nav(data,domain, option, time)
  30. return content
  31. def user_content(data, user, option, sort):
  32. content = html.user_menu(option, user)
  33. if option != "gilded":
  34. content += html.user_sort_menu(option, sort, user)
  35. content += (html.mixed_content(data, True),)
  36. content += html.user_nav(data, user, option, sort)
  37. return content
  38. @app.route("/search", "GET")
  39. @app.route("/r/<subreddit>/search", "GET")
  40. def search_page(subreddit=None):
  41. url = f'https://old.reddit.com{get_subreddit_url()}/search/.json'
  42. query = dict(request.query)
  43. r = req(url, query)
  44. if success(r):
  45. data = r.json()
  46. time = query.get("t")
  47. sort = query.get("sort")
  48. q = query.get("q") or ""
  49. title = f"search results - {q}"
  50. header = html.page_header(subreddit=subreddit, q=q)
  51. content = search_content(data, subreddit, sort, time, query)
  52. return html.page(title, header, content).render()
  53. else:
  54. return abort(r.status_code)
  55. @app.route("/u/<user>", "GET")
  56. @app.route("/user/<user>", "GET")
  57. @app.route("/u/<user>/<option>", "GET")
  58. @app.route("/user/<user>/<option>", "GET")
  59. def user_page(user, option="overview"):
  60. verify_user_option()
  61. url = f"https://old.reddit.com/user/{user}/{option}/.json"
  62. query = dict(request.query)
  63. r = req(url, query)
  64. if success(r):
  65. data = r.json()
  66. sort = query.get("sort")
  67. title = f"{option} by {user}"
  68. header = html.page_header(user=user)
  69. content = user_content(data, user, option, sort)
  70. return html.page(title, header, content).render()
  71. else:
  72. return abort(r.status_code)
  73. @app.route("/", "GET")
  74. @app.route("/<option>", "GET")
  75. @app.route("/r/<subreddit>", "GET")
  76. @app.route("/r/<subreddit>/<option>", "GET")
  77. def subreddit_page(subreddit=None, option=None):
  78. verify_subreddit_option()
  79. url = f'https://old.reddit.com{get_subreddit_url()}/{option or DEFAULT_OPTION}.json'
  80. query = dict(request.query)
  81. r = req(url, query)
  82. if success(r):
  83. data = r.json()
  84. time = query.get("t")
  85. title = get_subreddit() or "kddit"
  86. header = html.page_header(subreddit=subreddit)
  87. safe = nsfw_mode(subreddit)
  88. content = subreddit_content(data,subreddit,option,time, safe)
  89. return html.page(title, header, content).render()
  90. return abort(r.status_code)
  91. @app.route("/domain/<domain>", "GET")
  92. @app.route("/domain/<domain>/<option>", "GET")
  93. def domain_page(domain, option=None):
  94. verify_subreddit_option()
  95. query = get_query()
  96. time = query.get("t")
  97. q = query.get("q")
  98. url = f'https://old.reddit.com/domain/{domain}/{option or DEFAULT_OPTION}.json'
  99. r = req(url, query)
  100. if success(r):
  101. data = r.json()
  102. title = domain
  103. header = html.page_header(domain=domain, q=q)
  104. content = domain_content(data, domain, option, time)
  105. return html.page(title, header, content).render()
  106. else:
  107. return abort(r.status_code)
  108. @app.route("/r/<subreddit>/comments/<post_id>/<path>", "GET")
  109. @app.route("/r/<subreddit>/comments/<post_id>/<path>/<comment_id>", "GET")
  110. def post_page(subreddit, post_id, path, comment_id=""):
  111. u = f"https://old.reddit.com/r/{subreddit}/comments/{post_id}/{path}/{comment_id}.json"
  112. query = get_query()
  113. r = req(u, query)
  114. if success(r):
  115. data = r.json()
  116. post = data[0]["data"]["children"][0]["data"]
  117. comments = data[1]["data"]["children"]
  118. title = post["title"]
  119. content = (html.post(post), html.comments(comments))
  120. header = html.page_header(subreddit=subreddit)
  121. return html.page(title, header, content).render()
  122. else:
  123. return abort(r.status_code)
  124. @app.route("/static/<file>")
  125. def static(file):
  126. return static_file(file, root=f"{ROOT}/static")
  127. @app.route("/video/<url:path>")
  128. def video_proxy(url):
  129. uri = urlparse(url)
  130. if (netloc := uri.netloc) in PROXY_ALLOW["video"]:
  131. with ydl:
  132. result = ydl.extract_info(url, download=True)
  133. return static_file(
  134. f'{result["id"]}.mp4',
  135. root=FILE_PATH)
  136. elif netloc in PROXY_ALLOW["imgur"]:
  137. iurl = url.replace(".gifv", ".mp4")
  138. r = req(iurl)
  139. if success(r):
  140. response.set_header("content-type", r.headers["content-type"])
  141. return r.content
  142. else:
  143. return abort(r.status_code)
  144. else:
  145. return abort(403)
  146. @app.route("/proxy/<url:path>")
  147. def proxy(url):
  148. uri = urlparse(url)
  149. netloc = uri.netloc
  150. query = get_query()
  151. if netloc not in PROXY_ALLOW["image"]:
  152. return abort(403)
  153. r = req(url, query)
  154. if success(r):
  155. response.set_header("content-type", r.headers["content-type"])
  156. return r.content
  157. else:
  158. return abort(r.status_code)
  159. @app.error(401)
  160. @app.error(403)
  161. @app.error(404)
  162. @app.error(405)
  163. @app.error(406)
  164. @app.error(451)
  165. @app.error(500)
  166. @app.error(503)
  167. def error_redirect(error):
  168. return html.error_page(error).render()