Dynamic realtime profile ReadMe linked with spotify
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.

152 lines
3.6 KiB

5 years ago
  1. from flask import Flask, Response, jsonify, render_template
  2. from base64 import b64encode
  3. from dotenv import load_dotenv, find_dotenv
  4. load_dotenv(find_dotenv())
  5. import requests
  6. import json
  7. import os
  8. import random
  9. print("Starting Server")
  10. SPOTIFY_CLIENT_ID = os.getenv("SPOTIFY_CLIENT_ID")
  11. SPOTIFY_SECRET_ID = os.getenv("SPOTIFY_SECRET_ID")
  12. SPOTIFY_REFRESH_TOKEN = os.getenv("SPOTIFY_REFRESH_TOKEN")
  13. # scope user-read-currently-playing,user-read-recently-played
  14. SPOTIFY_URL_REFRESH_TOKEN = "https://accounts.spotify.com/api/token"
  15. SPOTIFY_URL_NOW_PLAYING = "https://api.spotify.com/v1/me/player/currently-playing"
  16. SPOTIFY_URL_RECENTLY_PLAY = "https://api.spotify.com/v1/me/player/recently-played?limit=10"
  17. app = Flask(__name__)
  18. def get_authorization():
  19. return b64encode(f"{SPOTIFY_CLIENT_ID}:{SPOTIFY_SECRET_ID}".encode()).decode("ascii")
  20. def refresh_token():
  21. data = {
  22. "grant_type": "refresh_token",
  23. "refresh_token": SPOTIFY_REFRESH_TOKEN,
  24. }
  25. headers = {"Authorization": "Basic {}".format(get_authorization())}
  26. response = requests.post(SPOTIFY_URL_REFRESH_TOKEN, data=data, headers=headers)
  27. repsonse_json = response.json()
  28. return repsonse_json["access_token"]
  29. def get_recently_play():
  30. token = refresh_token()
  31. headers = {"Authorization": f"Bearer {token}"}
  32. response = requests.get(SPOTIFY_URL_RECENTLY_PLAY, headers=headers)
  33. if response.status_code == 204:
  34. return {}
  35. repsonse_json = response.json()
  36. return repsonse_json
  37. def get_now_playing():
  38. token = refresh_token()
  39. headers = {"Authorization": f"Bearer {token}"}
  40. response = requests.get(SPOTIFY_URL_NOW_PLAYING, headers=headers)
  41. if response.status_code == 204:
  42. return {}
  43. repsonse_json = response.json()
  44. return repsonse_json
  45. def generate_css_bar(num_bar=75):
  46. css_bar = ""
  47. left = 1
  48. for i in range(1, num_bar + 1):
  49. anim = random.randint(350, 500)
  50. css_bar += ".bar:nth-child({}) {{ left: {}px; animation-duration: {}ms; }}".format(
  51. i, left, anim
  52. )
  53. left += 4
  54. return css_bar
  55. def load_image_b64(url):
  56. resposne = requests.get(url)
  57. return b64encode(resposne.content).decode("ascii")
  58. def make_svg(data):
  59. height = 445
  60. num_bar = 75
  61. title_text = "Now playing"
  62. content_bar = "".join(["<div class='bar'></div>" for i in range(num_bar)])
  63. css_bar = generate_css_bar(num_bar)
  64. if data == {}:
  65. # Get recently play
  66. title_text = "Last listening to"
  67. content_bar = ""
  68. recent_plays = get_recently_play()
  69. size_recent_play = len(recent_plays["items"])
  70. idx = random.randint(0, size_recent_play - 1)
  71. item = recent_plays["items"][idx]["track"]
  72. else:
  73. item = data["item"]
  74. img = load_image_b64(item["album"]["images"][1]["url"])
  75. artist_name = item["artists"][0]["name"]
  76. song_name = item["name"]
  77. url = item["external_urls"]["spotify"]
  78. rendered_data = {
  79. "height": height,
  80. "num_bar": num_bar,
  81. "content_bar": content_bar,
  82. "css_bar": css_bar,
  83. "title_text": title_text,
  84. "artist_name": artist_name,
  85. "song_name": song_name,
  86. "content_bar": content_bar,
  87. "img": img,
  88. }
  89. return render_template("spotify.html.j2", **rendered_data)
  90. @app.route("/", defaults={"path": ""})
  91. @app.route("/<path:path>")
  92. def catch_all(path):
  93. data = get_now_playing()
  94. svg = make_svg(data)
  95. resp = Response(svg, mimetype="image/svg+xml")
  96. resp.headers["Cache-Control"] = "s-maxage=1"
  97. return resp
  98. if __name__ == "__main__":
  99. app.run(debug=True)