Nordcast is a new podcast streaming app by koyu.space
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

backend.py 8.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. #!/usr/bin/python3
  2. # -*- coding: utf-8 -*-
  3. from bottle import get, post, request, response, route, run, redirect
  4. from mastodon import Mastodon
  5. import feedparser
  6. import json
  7. import os.path
  8. import redis
  9. import uuid
  10. import requests
  11. r = redis.StrictRedis(host='localhost', port=6379, db=0)
  12. @get("/")
  13. def index():
  14. return redirect("https://nordcast.app", code=302)
  15. @get("/api/v1/getpodcast")
  16. def getpodcast():
  17. q = request.query["q"] # pylint: disable=unsubscriptable-object
  18. response.headers['Access-Control-Allow-Origin'] = '*'
  19. response.content_type = "application/json"
  20. response.set_header("Cache-Control", "public, max-age=600")
  21. return json.dumps(feedparser.parse(q), default=lambda o: '<not serializable>')
  22. @get("/api/v1/getbanner/<val>")
  23. def getbanner(val):
  24. response.headers['Access-Control-Allow-Origin'] = '*'
  25. response.content_type = "image/jpeg"
  26. f = open("banners/"+val+".jpg", "rb")
  27. img = f.read()
  28. f.close()
  29. return img
  30. @post("/api/v1/login")
  31. def login():
  32. response.headers['Access-Control-Allow-Origin'] = '*'
  33. response.content_type = "application/json"
  34. username = request.forms.get("username") # pylint: disable=no-member
  35. password = request.forms.get("password") # pylint: disable=no-member
  36. instance = request.forms.get("instance") # pylint: disable=no-member
  37. if not os.path.exists('clientcred.'+instance+'.secret'):
  38. Mastodon.create_app(
  39. 'Nordcast',
  40. api_base_url = 'https://'+instance,
  41. to_file = 'clientcred.'+instance+'.secret'
  42. )
  43. mastodon = Mastodon(
  44. client_id = 'clientcred.'+instance+'.secret',
  45. api_base_url = 'https://'+instance
  46. )
  47. mastodon.log_in(
  48. username,
  49. password,
  50. to_file = 'authtokens/'+username+'.'+instance+'.secret',
  51. )
  52. if not os.path.exists("usercred.secret"):
  53. suid = str(uuid.uuid1())
  54. r.set("nordcast/uuids/" + username + "$$" + instance, suid)
  55. return json.dumps({"login": "ok", "uuid": suid})
  56. else:
  57. return "{\"login\": \"error\"}"
  58. @get("/api/v1/login2/<username>/<uuid>/<instance>")
  59. def login2(username, uuid, instance):
  60. response.headers['Access-Control-Allow-Origin'] = '*'
  61. response.content_type = "application/json"
  62. suid = str(r.get("nordcast/uuids/" + username + "$$" + instance)).replace("b'", "").replace("'", "")
  63. try:
  64. mastodon = Mastodon(
  65. access_token = 'authtokens/'+username+'.'+instance+'.secret',
  66. api_base_url = 'https://'+instance
  67. )
  68. mastodon.account_verify_credentials().source.note
  69. except:
  70. pass
  71. if suid == uuid:
  72. return json.dumps({"login": "ok", "uuid": uuid})
  73. else:
  74. return "{\"login\": \"error\"}"
  75. @post("/api/v1/setlist/<username>/<uuid>/<instance>")
  76. def setlist(username, uuid, instance):
  77. response.headers['Access-Control-Allow-Origin'] = '*'
  78. response.content_type = "application/json"
  79. suid = str(r.get("nordcast/uuids/" + username + "$$" + instance)).replace("b'", "").replace("'", "")
  80. podlist = request.forms.get("podlist") # pylint: disable=no-member
  81. if suid == uuid:
  82. r.set("nordcast/podlist/" + username + "$$" + instance, podlist)
  83. return json.dumps({"login": "ok", "uuid": uuid, "action": "success"})
  84. else:
  85. return "{\"login\": \"error\"}"
  86. @get("/api/v1/getlist/<username>/<uuid>/<instance>")
  87. def getlist(username, uuid, instance):
  88. response.headers['Access-Control-Allow-Origin'] = '*'
  89. response.content_type = "application/json"
  90. podlist = str(r.get("nordcast/podlist/" + username + "$$" + instance)).replace("b'", "").replace("'", "")
  91. suid = str(r.get("nordcast/uuids/" + username + "$$" + instance)).replace("b'", "").replace("'", "")
  92. if suid == uuid:
  93. return json.dumps({"login": "ok", "uuid": uuid, "action": "success", "podlist": podlist})
  94. else:
  95. return "{\"login\": \"error\"}"
  96. @get("/api/v1/setpos/<username>/<uuid>/<secret>/<pos>/<instance>")
  97. def setpos(username, uuid, secret, pos, instance):
  98. response.headers['Access-Control-Allow-Origin'] = '*'
  99. response.content_type = "application/json"
  100. suid = str(r.get("nordcast/uuids/" + username + "$$" + instance)).replace("b'", "").replace("'", "")
  101. if suid == uuid:
  102. r.set("nordcast/pos/" + username + "$$" + instance + "/" + secret, pos)
  103. return json.dumps({"login": "ok", "uuid": uuid, "action": "success"})
  104. @get("/api/v1/getpos/<username>/<uuid>/<secret>/<instance>")
  105. def getpos(username, uuid, secret, instance):
  106. response.headers['Access-Control-Allow-Origin'] = '*'
  107. response.content_type = "application/json"
  108. suid = str(r.get("nordcast/uuids/" + username + "$$" + instance)).replace("b'", "").replace("'", "")
  109. if suid == uuid:
  110. pos = str(r.get("nordcast/pos/" + username + "$$" + instance + "/" + secret)).replace("b'", "").replace("'", "")
  111. return json.dumps({"login": "ok", "uuid": uuid, "action": "success", "pos": pos, "secret": secret})
  112. @get("/api/v1/getname/<username>/<uuid>/<instance>")
  113. def getname(username, uuid, instance):
  114. response.headers['Access-Control-Allow-Origin'] = '*'
  115. response.content_type = "application/json"
  116. suid = str(r.get("nordcast/uuids/" + username + "$$" + instance)).replace("b'", "").replace("'", "")
  117. if not uuid == "dummy":
  118. mastodon = Mastodon(
  119. access_token = 'authtokens/'+username+'.'+instance+'.secret',
  120. api_base_url = 'https://'+instance
  121. )
  122. userdict = mastodon.account_verify_credentials()
  123. try:
  124. if suid == uuid:
  125. ksname = userdict.display_name
  126. ksemojis = userdict.emojis
  127. return json.dumps({"login": "ok", "uuid": uuid, "action": "success", "ksname": ksname, "ksemojis": ksemojis})
  128. else:
  129. return "{\"login\": \"error\"}"
  130. except:
  131. return "{\"login\": \"error\"}"
  132. @get("/api/v1/getpic/<username>/<uuid>/<instance>")
  133. def getpic(username, uuid, instance):
  134. response.headers['Access-Control-Allow-Origin'] = '*'
  135. response.content_type = "application/json"
  136. suid = str(r.get("nordcast/uuids/" + username + "$$" + instance)).replace("b'", "").replace("'", "")
  137. if not uuid == "dummy":
  138. mastodon = Mastodon(
  139. access_token = 'authtokens/'+username+'.'+instance+'.secret',
  140. api_base_url = 'https://'+instance
  141. )
  142. userdict = mastodon.account_verify_credentials()
  143. try:
  144. if suid == uuid:
  145. kspic = userdict.avatar
  146. return json.dumps({"login": "ok", "uuid": uuid, "action": "success", "kspic": kspic})
  147. else:
  148. return "{\"login\": \"error\"}"
  149. except:
  150. return "{\"login\": \"error\"}"
  151. @get("/api/v1/getemoji/<username>/<uuid>/<instance>")
  152. def getemoji(username, uuid, instance):
  153. response.headers['Access-Control-Allow-Origin'] = '*'
  154. response.content_type = "application/json"
  155. suid = str(r.get("nordcast/uuids/" + username + "$$" + instance)).replace("b'", "").replace("'", "")
  156. if not uuid == "dummy":
  157. mastodon = Mastodon(
  158. access_token = 'authtokens/'+username+'.'+instance+'.secret',
  159. api_base_url = 'https://'+instance
  160. )
  161. userdict = mastodon.account_verify_credentials()
  162. try:
  163. if suid == uuid:
  164. ksemoji = mastodon.custom_emojis()
  165. return json.dumps({"login": "ok", "uuid": uuid, "action": "success", "ksemoji": ksemoji})
  166. else:
  167. return "{\"login\": \"error\"}"
  168. except:
  169. return "{\"login\": \"error\"}"
  170. @get("/api/v1/search/<lang>/<query>")
  171. def search(lang,query):
  172. response.headers['Access-Control-Allow-Origin'] = '*'
  173. response.content_type = "application/json"
  174. query = query.replace(" ", "%20")
  175. url = "https://itunes.apple.com/"+lang+"/search?term="+query+"&media=podcast"
  176. data = requests.get(url)
  177. return data
  178. @get("/api/v1/search/<lang>/")
  179. def searche(lang):
  180. response.headers['Access-Control-Allow-Origin'] = '*'
  181. response.content_type = "application/json"
  182. return ""
  183. @get("/api/v1/getoriginals")
  184. def getoriginals():
  185. f = open("data/originals", "r")
  186. x = f.read()
  187. f.close()
  188. response.headers['Access-Control-Allow-Origin'] = '*'
  189. response.content_type = "application/json"
  190. return json.dumps({"podlist": x})
  191. @get("/api/v1/getfeatured")
  192. def gefeatured():
  193. f = open("data/featured", "r")
  194. x = f.readlines()
  195. f.close()
  196. response.headers['Access-Control-Allow-Origin'] = '*'
  197. response.content_type = "application/json"
  198. l = []
  199. for i in x:
  200. l.append([i.split("#")[0], i.split("#")[1]])
  201. return json.dumps(l)
  202. run(server="tornado",port=9000,host="0.0.0.0")