Nordcast is a 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.

612 lines
24KB

  1. #!/usr/bin/python3
  2. # -*- coding: utf-8 -*-
  3. from bottle import get, post, request, response, route, run, redirect, BaseRequest
  4. from mastodon import Mastodon
  5. from colorthief import ColorThief
  6. import feedparser
  7. import json
  8. import os.path
  9. import redis
  10. import uuid
  11. import requests
  12. import subprocess
  13. import urllib.parse
  14. from PIL import Image
  15. r = redis.StrictRedis(host='localhost', port=6379, db=0)
  16. BaseRequest.MEMFILE_MAX = 999999999
  17. if os.environ.get('DEBUG') == "true":
  18. debug = True
  19. else:
  20. debug = False
  21. if not os.environ.get('ADMINKEY') == None:
  22. ADMINKEY = os.environ.get('ADMINKEY')
  23. else:
  24. ADMINKEY = "x"
  25. @get("/")
  26. def index():
  27. response.headers['Access-Control-Allow-Origin'] = '*'
  28. return redirect("https://nordcast.app", code=302)
  29. @get("/getstatus")
  30. def status():
  31. response.headers['Access-Control-Allow-Origin'] = '*'
  32. response.content_type = "text/plain"
  33. return "ok"
  34. @get("/api/v1/getpodcast")
  35. def getpodcast():
  36. q = request.query["q"] # pylint: disable=unsubscriptable-object
  37. response.headers['Access-Control-Allow-Origin'] = '*'
  38. response.content_type = "application/json"
  39. response.set_header("Cache-Control", "public, max-age=600")
  40. return json.dumps(feedparser.parse(q), default=lambda o: '<not serializable>')
  41. @get("/api/v1/getbanner/<val>")
  42. def getbanner(val):
  43. response.headers['Access-Control-Allow-Origin'] = '*'
  44. response.content_type = "image/jpeg"
  45. f = open("banners/"+val+".jpg", "rb")
  46. img = f.read()
  47. f.close()
  48. return img
  49. @post("/api/v1/login")
  50. def login():
  51. response.headers['Access-Control-Allow-Origin'] = '*'
  52. response.content_type = "application/json"
  53. username = request.forms.get("username") # pylint: disable=no-member
  54. password = request.forms.get("password") # pylint: disable=no-member
  55. instance = request.forms.get("instance") # pylint: disable=no-member
  56. if debug:
  57. appname = "Nordcast (debug)"
  58. else:
  59. appname = "Nordcast"
  60. if not os.path.exists('clientcred.'+instance+'.secret'):
  61. Mastodon.create_app(
  62. appname,
  63. api_base_url = 'https://'+instance,
  64. to_file = 'clientcred.'+instance+'.secret'
  65. )
  66. mastodon = Mastodon(
  67. client_id = 'clientcred.'+instance+'.secret',
  68. api_base_url = 'https://'+instance
  69. )
  70. mastodon.log_in(
  71. username,
  72. password,
  73. to_file = 'authtokens/'+username+'.'+instance+'.secret',
  74. )
  75. if not os.path.exists("usercred.secret"):
  76. suid = str(uuid.uuid1())
  77. if r.get("nordcast/uuids/" + username + "$$" + instance) == None:
  78. r.set("nordcast/uuids/" + username + "$$" + instance, suid)
  79. else:
  80. r.set("nordcast/uuids/" + username + "$$" + instance, str(r.get("nordcast/uuids/" + username + "$$" + instance)).replace("b'", "").replace("'", "") + "," + suid)
  81. return json.dumps({"login": "ok", "uuid": suid})
  82. else:
  83. return "{\"login\": \"error\"}"
  84. @get("/api/v1/login2/<username>/<uuid>/<instance>")
  85. def login2(username, uuid, instance):
  86. response.headers['Access-Control-Allow-Origin'] = '*'
  87. response.content_type = "application/json"
  88. suid = str(r.get("nordcast/uuids/" + username + "$$" + instance)).replace("b'", "").replace("'", "")
  89. try:
  90. mastodon = Mastodon(
  91. access_token = 'authtokens/'+username+'.'+instance+'.secret',
  92. api_base_url = 'https://'+instance
  93. )
  94. mastodon.account_verify_credentials().source.note
  95. except:
  96. pass
  97. if uuid in suid:
  98. return json.dumps({"login": "ok", "uuid": uuid})
  99. else:
  100. return "{\"login\": \"error\"}"
  101. @post("/api/v1/setlist/<username>/<uuid>/<instance>")
  102. def setlist(username, uuid, instance):
  103. response.headers['Access-Control-Allow-Origin'] = '*'
  104. response.content_type = "application/json"
  105. suid = str(r.get("nordcast/uuids/" + username + "$$" + instance)).replace("b'", "").replace("'", "")
  106. podlist = request.forms.get("podlist") # pylint: disable=no-member
  107. if uuid in suid:
  108. r.set("nordcast/podlist/" + username + "$$" + instance, podlist)
  109. return json.dumps({"login": "ok", "uuid": uuid, "action": "success"})
  110. else:
  111. return "{\"login\": \"error\"}"
  112. @get("/api/v1/getlist/<username>/<uuid>/<instance>")
  113. def getlist(username, uuid, instance):
  114. response.headers['Access-Control-Allow-Origin'] = '*'
  115. response.content_type = "application/json"
  116. podlist = str(r.get("nordcast/podlist/" + username + "$$" + instance)).replace("b'", "").replace("'", "")
  117. suid = str(r.get("nordcast/uuids/" + username + "$$" + instance)).replace("b'", "").replace("'", "")
  118. if uuid in suid:
  119. return json.dumps({"login": "ok", "uuid": uuid, "action": "success", "podlist": podlist})
  120. else:
  121. return "{\"login\": \"error\"}"
  122. @get("/api/v1/setpos/<username>/<uuid>/<secret>/<pos>/<instance>")
  123. def setpos(username, uuid, secret, pos, instance):
  124. response.headers['Access-Control-Allow-Origin'] = '*'
  125. response.content_type = "application/json"
  126. suid = str(r.get("nordcast/uuids/" + username + "$$" + instance)).replace("b'", "").replace("'", "")
  127. if uuid in suid:
  128. r.set("nordcast/pos/" + username + "$$" + instance + "/" + secret, pos)
  129. return json.dumps({"login": "ok", "uuid": uuid, "action": "success"})
  130. @get("/api/v1/getpos/<username>/<uuid>/<secret>/<instance>")
  131. def getpos(username, uuid, secret, instance):
  132. response.headers['Access-Control-Allow-Origin'] = '*'
  133. response.content_type = "application/json"
  134. suid = str(r.get("nordcast/uuids/" + username + "$$" + instance)).replace("b'", "").replace("'", "")
  135. if uuid in suid:
  136. pos = str(r.get("nordcast/pos/" + username + "$$" + instance + "/" + secret)).replace("b'", "").replace("'", "")
  137. return json.dumps({"login": "ok", "uuid": uuid, "action": "success", "pos": pos, "secret": secret})
  138. @get("/api/v1/getname/<username>/<uuid>/<instance>")
  139. def getname(username, uuid, instance):
  140. response.headers['Access-Control-Allow-Origin'] = '*'
  141. response.content_type = "application/json"
  142. suid = str(r.get("nordcast/uuids/" + username + "$$" + instance)).replace("b'", "").replace("'", "")
  143. if not uuid == "dummy":
  144. mastodon = Mastodon(
  145. access_token = 'authtokens/'+username+'.'+instance+'.secret',
  146. api_base_url = 'https://'+instance
  147. )
  148. userdict = mastodon.account_verify_credentials()
  149. try:
  150. if uuid in suid:
  151. ksname = userdict.display_name
  152. ksemojis = userdict.emojis
  153. return json.dumps({"login": "ok", "uuid": uuid, "action": "success", "ksname": ksname, "ksemojis": ksemojis})
  154. else:
  155. return "{\"login\": \"error\"}"
  156. except:
  157. return "{\"login\": \"error\"}"
  158. @get("/api/v1/getpic/<username>/<uuid>/<instance>")
  159. def getpic(username, uuid, instance):
  160. response.headers['Access-Control-Allow-Origin'] = '*'
  161. response.content_type = "application/json"
  162. suid = str(r.get("nordcast/uuids/" + username + "$$" + instance)).replace("b'", "").replace("'", "")
  163. if not uuid == "dummy":
  164. mastodon = Mastodon(
  165. access_token = 'authtokens/'+username+'.'+instance+'.secret',
  166. api_base_url = 'https://'+instance
  167. )
  168. userdict = mastodon.account_verify_credentials()
  169. try:
  170. if uuid in suid:
  171. kspic = userdict.avatar
  172. return json.dumps({"login": "ok", "uuid": uuid, "action": "success", "kspic": kspic})
  173. else:
  174. return "{\"login\": \"error\"}"
  175. except:
  176. return "{\"login\": \"error\"}"
  177. @get("/api/v1/getemoji/<username>/<uuid>/<instance>")
  178. def getemoji(username, uuid, instance):
  179. response.headers['Access-Control-Allow-Origin'] = '*'
  180. response.content_type = "application/json"
  181. suid = str(r.get("nordcast/uuids/" + username + "$$" + instance)).replace("b'", "").replace("'", "")
  182. if not uuid == "dummy":
  183. mastodon = Mastodon(
  184. access_token = 'authtokens/'+username+'.'+instance+'.secret',
  185. api_base_url = 'https://'+instance
  186. )
  187. userdict = mastodon.account_verify_credentials() # pylint: disable=unused-variable
  188. try:
  189. if uuid in suid:
  190. ksemoji = mastodon.custom_emojis()
  191. return json.dumps({"login": "ok", "uuid": uuid, "action": "success", "ksemoji": ksemoji})
  192. else:
  193. return "{\"login\": \"error\"}"
  194. except:
  195. return "{\"login\": \"error\"}"
  196. @get("/api/v1/search/<lang>/<query>")
  197. def search(lang,query):
  198. response.headers['Access-Control-Allow-Origin'] = '*'
  199. response.content_type = "application/json"
  200. query = query.replace(" ", "%20")
  201. url = "https://itunes.apple.com/"+lang+"/search?term="+query+"&media=podcast"
  202. data = requests.get(url)
  203. return data
  204. @get("/api/v1/search/<lang>/")
  205. def searche(lang):
  206. response.headers['Access-Control-Allow-Origin'] = '*'
  207. response.content_type = "application/json"
  208. return ""
  209. @get("/api/v1/getoriginals/<lang>")
  210. def getoriginals(lang):
  211. f = open("data/"+lang+"/originals", "r")
  212. x = f.read()
  213. f.close()
  214. response.headers['Access-Control-Allow-Origin'] = '*'
  215. response.content_type = "application/json"
  216. return json.dumps({"podlist": x})
  217. @get("/api/v1/getfeatured/<lang>")
  218. def gefeatured(lang):
  219. f = open("data/"+lang+"/featured", "r")
  220. x = f.readlines()
  221. f.close()
  222. response.headers['Access-Control-Allow-Origin'] = '*'
  223. response.content_type = "application/json"
  224. l = []
  225. for i in x:
  226. l.append([i.split("#")[0], i.split("#")[1]])
  227. return json.dumps(l)
  228. @get("/api/v1/getprimarycolor")
  229. def getprimarycolor():
  230. response.headers['Access-Control-Allow-Origin'] = '*'
  231. response.content_type = "text/plain"
  232. response.set_header("Cache-Control", "public, max-age=600")
  233. url = request.query["url"] # pylint: disable=unsubscriptable-object
  234. filecache = ""
  235. filename = "files/"+url.split("/")[len(url.split("/")) - 1]
  236. if "/api/v1/getbanner" in url:
  237. filename = "banners/"+url.split("/")[len(url.split("/")) - 1]+".jpg"
  238. if os.path.exists("filecache"):
  239. f = open("filecache", "r")
  240. x = f.readlines()
  241. f.close()
  242. for i in x:
  243. if i.split("#")[0] == filename:
  244. filecache = i.split("#")[1]
  245. if not filecache == "":
  246. return filecache
  247. else:
  248. if not "/api/v1/getbanner" in url:
  249. subprocess.Popen(["wget", "-O", filename, url], shell=False).wait()
  250. color_thief = ColorThief(filename)
  251. dominant_color = color_thief.get_color()
  252. x = str(dominant_color).replace("(", "").replace(" ", "").replace(")", "")
  253. f = open("filecache", "a+")
  254. f.write(filename+"#"+x+"\n")
  255. return x
  256. else:
  257. if not "/api/v1/getbanner" in url:
  258. subprocess.Popen(["wget", "-O", filename, url], shell=False).wait()
  259. color_thief = ColorThief(filename)
  260. dominant_color = color_thief.get_color()
  261. x = str(dominant_color).replace("(", "").replace(" ", "").replace(")", "")
  262. f = open("filecache", "a+")
  263. f.write(filename+"#"+x+"\n")
  264. return x
  265. @get("/api/v1/gethiddenauthors")
  266. def gethiddenauthors():
  267. response.headers['Access-Control-Allow-Origin'] = '*'
  268. response.content_type = "text/plain"
  269. response.set_header("Cache-Control", "public, max-age=600")
  270. f = open("data/hiddenauthors")
  271. x = f.read()
  272. f.close()
  273. return x
  274. @get("/api/v1/gethiddensubtitles")
  275. def gethiddensubtitles():
  276. response.headers['Access-Control-Allow-Origin'] = '*'
  277. response.content_type = "text/plain"
  278. response.set_header("Cache-Control", "public, max-age=600")
  279. f = open("data/hiddensubtitles")
  280. x = f.read()
  281. f.close()
  282. return x
  283. @get("/api/v1/gethiddendownloads")
  284. def gethiddendownloads():
  285. response.headers['Access-Control-Allow-Origin'] = '*'
  286. response.content_type = "text/plain"
  287. response.set_header("Cache-Control", "public, max-age=600")
  288. f = open("data/hiddendownloads")
  289. x = f.read()
  290. f.close()
  291. return x
  292. @get("/api/v1/getreversed")
  293. def getreversed():
  294. response.headers['Access-Control-Allow-Origin'] = '*'
  295. response.content_type = "text/plain"
  296. response.set_header("Cache-Control", "public, max-age=600")
  297. f = open("data/reversed")
  298. x = f.read()
  299. f.close()
  300. return x
  301. @post("/api/v1/toot/<username>/<uuid>/<instance>/<visibility>")
  302. def toot(username, uuid, instance, visibility):
  303. response.headers['Access-Control-Allow-Origin'] = '*'
  304. response.content_type = "application/json"
  305. suid = str(r.get("nordcast/uuids/" + username + "$$" + instance)).replace("b'", "").replace("'", "")
  306. content = request.forms.get("content") # pylint: disable=no-member
  307. try:
  308. mastodon = Mastodon(
  309. access_token = 'authtokens/'+username+'.'+instance+'.secret',
  310. api_base_url = 'https://'+instance
  311. )
  312. mastodon.account_verify_credentials().source.note
  313. except:
  314. pass
  315. if uuid in suid:
  316. if "%20" in content:
  317. content = urllib.parse.unquote(content)
  318. mastodon.status_post(content, visibility=visibility)
  319. return json.dumps({"login": "ok", "uuid": uuid, "action": "success"})
  320. else:
  321. return "{\"login\": \"error\"}"
  322. @get("/api/v1/isfav/<username>/<uuid>/<secret>/<instance>")
  323. def isfav(username, uuid, instance, secret):
  324. response.headers['Access-Control-Allow-Origin'] = '*'
  325. response.content_type = "application/json"
  326. suid = str(r.get("nordcast/uuids/" + username + "$$" + instance)).replace("b'", "").replace("'", "")
  327. try:
  328. mastodon = Mastodon(
  329. access_token = 'authtokens/'+username+'.'+instance+'.secret',
  330. api_base_url = 'https://'+instance
  331. )
  332. mastodon.account_verify_credentials().source.note
  333. except:
  334. pass
  335. if uuid in suid:
  336. isfav = str(r.get("nordcast/isfav/" + username + "$$" + instance + "/" + secret)).replace("b'", "").replace("'", "")
  337. if isfav == "true":
  338. isfav = True
  339. else:
  340. isfav = False
  341. return json.dumps({"login": "ok", "uuid": uuid, "action": "success", "isfav": isfav, "secret": secret})
  342. @get("/api/v1/getfavs/<username>/<uuid>/<secret>/<instance>")
  343. def getfavs(username, uuid, instance, secret):
  344. response.headers['Access-Control-Allow-Origin'] = '*'
  345. response.content_type = "application/json"
  346. suid = str(r.get("nordcast/uuids/" + username + "$$" + instance)).replace("b'", "").replace("'", "")
  347. try:
  348. mastodon = Mastodon(
  349. access_token = 'authtokens/'+username+'.'+instance+'.secret',
  350. api_base_url = 'https://'+instance
  351. )
  352. mastodon.account_verify_credentials().source.note
  353. except:
  354. pass
  355. if uuid in suid:
  356. favs = str(r.get("nordcast/favs/" + secret)).replace("b'", "").replace("'", "")
  357. if favs == "None":
  358. favs = "0"
  359. return json.dumps({"login": "ok", "uuid": uuid, "action": "success", "favs": favs, "secret": secret})
  360. @get("/api/v1/addfav/<username>/<uuid>/<secret>/<instance>")
  361. def addfav(username, uuid, secret, instance):
  362. response.headers['Access-Control-Allow-Origin'] = '*'
  363. response.content_type = "application/json"
  364. suid = str(r.get("nordcast/uuids/" + username + "$$" + instance)).replace("b'", "").replace("'", "")
  365. if uuid in suid:
  366. if str(r.get("nordcast/favs/" + secret)).replace("b'", "").replace("'", "") == "None":
  367. favs = 1
  368. else:
  369. favs = int(str(r.get("nordcast/favs/" + secret)).replace("b'", "").replace("'", "")) + 1
  370. if favs < 0:
  371. favs = 0
  372. isfav = str(r.get("nordcast/isfav/" + username + "$$" + instance + "/" + secret)).replace("b'", "").replace("'", "")
  373. if isfav == "true":
  374. isfav = True
  375. else:
  376. isfav = False
  377. if isfav == False:
  378. r.set("nordcast/favs/" + secret, favs)
  379. r.set("nordcast/isfav/" + username + "$$" + instance + "/" + secret, "true")
  380. return json.dumps({"login": "ok", "uuid": uuid, "action": "success"})
  381. else:
  382. return "{\"action\": \"error\"}"
  383. @get("/api/v1/delfav/<username>/<uuid>/<secret>/<instance>")
  384. def delfav(username, uuid, secret, instance):
  385. response.headers['Access-Control-Allow-Origin'] = '*'
  386. response.content_type = "application/json"
  387. suid = str(r.get("nordcast/uuids/" + username + "$$" + instance)).replace("b'", "").replace("'", "")
  388. if uuid in suid:
  389. if str(r.get("nordcast/favs/" + secret)).replace("b'", "").replace("'", "") == "None":
  390. favs = 0
  391. else:
  392. favs = int(str(r.get("nordcast/favs/" + secret)).replace("b'", "").replace("'", "")) - 1
  393. if favs < 0:
  394. favs = 0
  395. isfav = str(r.get("nordcast/isfav/" + username + "$$" + instance + "/" + secret)).replace("b'", "").replace("'", "")
  396. if isfav == "true":
  397. isfav = True
  398. else:
  399. isfav = False
  400. if isfav == True:
  401. r.set("nordcast/favs/" + secret, favs)
  402. r.set("nordcast/isfav/" + username + "$$" + instance + "/" + secret, "false")
  403. return json.dumps({"login": "ok", "uuid": uuid, "action": "success"})
  404. else:
  405. return "{\"action\": \"error\"}"
  406. @post("/api/v1/admin/featured/<adminkey>/<lang>")
  407. def setfeatured(adminkey, lang):
  408. response.headers['Access-Control-Allow-Origin'] = '*'
  409. response.content_type = "application/json"
  410. content = request.forms.get("content") # pylint: disable=no-member
  411. if adminkey == ADMINKEY:
  412. f = open("data/"+lang+"/featured", "w")
  413. f.write(content)
  414. f.close()
  415. return json.dumps({"login": "ok", "action": "success"})
  416. else:
  417. return "{\"action\": \"error\"}"
  418. @post("/api/v1/admin/originals/<adminkey>/<lang>")
  419. def setoriginals(adminkey, lang):
  420. response.headers['Access-Control-Allow-Origin'] = '*'
  421. response.content_type = "application/json"
  422. content = request.forms.get("content") # pylint: disable=no-member
  423. if adminkey == ADMINKEY:
  424. f = open("data/"+lang+"/originals", "w")
  425. f.write(content)
  426. f.close()
  427. return json.dumps({"login": "ok", "action": "success"})
  428. else:
  429. return "{\"action\": \"error\"}"
  430. @post("/api/v1/admin/hiddenauthors/<adminkey>")
  431. def sethiddenauthors(adminkey):
  432. response.headers['Access-Control-Allow-Origin'] = '*'
  433. response.content_type = "application/json"
  434. content = request.forms.get("content") # pylint: disable=no-member
  435. if adminkey == ADMINKEY:
  436. f = open("data/hiddenauthors", "w")
  437. f.write(content)
  438. f.close()
  439. return json.dumps({"login": "ok", "action": "success"})
  440. else:
  441. return "{\"action\": \"error\"}"
  442. @post("/api/v1/admin/hiddendownloads/<adminkey>")
  443. def sethiddendownloads(adminkey):
  444. response.headers['Access-Control-Allow-Origin'] = '*'
  445. response.content_type = "application/json"
  446. content = request.forms.get("content") # pylint: disable=no-member
  447. if adminkey == ADMINKEY:
  448. f = open("data/hiddendownloads", "w")
  449. f.write(content)
  450. f.close()
  451. return json.dumps({"login": "ok", "action": "success"})
  452. else:
  453. return "{\"action\": \"error\"}"
  454. @post("/api/v1/admin/hiddensubtitles/<adminkey>")
  455. def sethiddensubtitles(adminkey):
  456. response.headers['Access-Control-Allow-Origin'] = '*'
  457. response.content_type = "application/json"
  458. content = request.forms.get("content") # pylint: disable=no-member
  459. if adminkey == ADMINKEY:
  460. f = open("data/hiddensubtitles", "w")
  461. f.write(content)
  462. f.close()
  463. return json.dumps({"login": "ok", "action": "success"})
  464. else:
  465. return "{\"action\": \"error\"}"
  466. @post("/api/v1/admin/reversed/<adminkey>")
  467. def setreversed(adminkey):
  468. response.headers['Access-Control-Allow-Origin'] = '*'
  469. response.content_type = "application/json"
  470. content = request.forms.get("content") # pylint: disable=no-member
  471. if adminkey == ADMINKEY:
  472. f = open("data/reversed", "w")
  473. f.write(content)
  474. f.close()
  475. return json.dumps({"login": "ok", "action": "success"})
  476. else:
  477. return "{\"action\": \"error\"}"
  478. @post("/api/v1/admin/banner/<adminkey>")
  479. def uploadbanner(adminkey):
  480. response.headers['Access-Control-Allow-Origin'] = '*'
  481. response.content_type = "application/json"
  482. banner = request.files.get("banner") # pylint: disable=no-member
  483. name, ext = os.path.splitext(banner.filename) # pylint: disable=unused-variable
  484. if ext not in ('.jpg'):
  485. return "{\"action\": \"error\"}"
  486. else:
  487. if adminkey == ADMINKEY:
  488. try:
  489. banner.save("banners/", overwrite=True)
  490. im = Image.open("banners/"+name+ext)
  491. width, height = im.size
  492. if width == 299 and height == 118:
  493. return json.dumps({"login": "ok", "action": "success"})
  494. else:
  495. try:
  496. os.remove("banners/"+name+ext)
  497. except:
  498. pass
  499. return "{\"action\": \"error\"}"
  500. except:
  501. try:
  502. os.remove("banners/"+name+ext)
  503. except:
  504. pass
  505. return "{\"action\": \"error\"}"
  506. else:
  507. return "{\"action\": \"error\"}"
  508. @get("/api/v1/lastplayed/<username>/<uuid>/<instance>/<feed>/<time>")
  509. def lastplayed(username, uuid, instance, feed, time):
  510. response.headers['Access-Control-Allow-Origin'] = '*'
  511. response.content_type = "application/json"
  512. suid = str(r.get("nordcast/uuids/" + username + "$$" + instance)).replace("b'", "").replace("'", "")
  513. if uuid in suid:
  514. r.set("nordcast/lastplayed/" + username + "$$" + instance + "/" + feed, time)
  515. return json.dumps({"login": "ok", "uuid": uuid, "action": "success"})
  516. @get("/api/v1/getlastplayed/<username>/<uuid>/<instance>/<feed>")
  517. def getlastplayed(username, uuid, instance, feed):
  518. response.headers['Access-Control-Allow-Origin'] = '*'
  519. response.content_type = "application/json"
  520. suid = str(r.get("nordcast/uuids/" + username + "$$" + instance)).replace("b'", "").replace("'", "")
  521. lastplayed = str(r.get("nordcast/lastplayed/" + username + "$$" + instance + "/" + feed)).replace("b'", "").replace("'", "")
  522. if uuid in suid:
  523. return json.dumps({"login": "ok", "uuid": uuid, "lastplayed": lastplayed})
  524. @post("/api/v1/admin/custom/<adminkey>/<lang>")
  525. def setcustom(adminkey, lang):
  526. response.headers['Access-Control-Allow-Origin'] = '*'
  527. response.content_type = "application/json"
  528. content = request.forms.get("content") # pylint: disable=no-member
  529. if adminkey == ADMINKEY:
  530. f = open("data/"+lang+"/custom", "w")
  531. f.write(content)
  532. f.close()
  533. return json.dumps({"login": "ok", "action": "success"})
  534. else:
  535. return "{\"action\": \"error\"}"
  536. @get("/api/v1/getcustomsection/<lang>")
  537. def getcustomsection(lang):
  538. f = open("data/"+lang+"/custom", "r")
  539. x = f.read()
  540. f.close()
  541. response.headers['Access-Control-Allow-Origin'] = '*'
  542. return x
  543. @post("/api/v1/register/<locale>/<instance>")
  544. def register(locale, instance):
  545. response.headers['Access-Control-Allow-Origin'] = '*'
  546. response.content_type = "application/json"
  547. username = request.forms.get("username") # pylint: disable=no-member
  548. email = request.forms.get("email") # pylint: disable=no-member
  549. password = request.forms.get("password") # pylint: disable=no-member
  550. agreement = True
  551. if debug:
  552. appname = "Nordcast (debug)"
  553. else:
  554. appname = "Nordcast"
  555. if not os.path.exists('clientcred.'+instance+'.secret'):
  556. Mastodon.create_app(
  557. appname,
  558. api_base_url = 'https://'+instance,
  559. to_file = 'clientcred.'+instance+'.secret'
  560. )
  561. mastodon = Mastodon(
  562. client_id = 'clientcred.'+instance+'.secret',
  563. api_base_url = 'https://'+instance
  564. )
  565. mastodon.create_account(username, password, email, agreement, locale=locale)
  566. return "{\"action\": \"success\"}"
  567. run(server="tornado",port=9000,host="0.0.0.0")