app.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import hashlib
  2. import json
  3. import logging
  4. import os
  5. import re
  6. import sys
  7. from datetime import datetime
  8. from email.mime.text import MIMEText
  9. from subprocess import PIPE, Popen
  10. from uuid import uuid4
  11. from flask import (Flask, abort, make_response, render_template, request,
  12. url_for)
  13. app = Flask(__name__)
  14. if "MESSAGGERIA_SETTING" in os.environ:
  15. app.config.from_envvar("MESSAGGERIA_SETTING")
  16. UPLOAD_DIR = os.getenv("UPLOAD_DIR", "./uploads/")
  17. logging.basicConfig(level=logging.DEBUG)
  18. app.logger.setLevel(logging.DEBUG)
  19. def sendmail(sender, to, subject, body):
  20. # msg = MIMEText(body)
  21. # msg["From"] = sender
  22. # msg["To"] = to
  23. # msg["Subject"] = subject
  24. # p = Popen(["/usr/sbin/sendmail", "-t", "-oi"], stdin=PIPE)
  25. args = ["/usr/bin/mail", "-s", subject, "--"] + to
  26. p = Popen(args, stdin=PIPE)
  27. # p.communicate(msg.as_bytes())
  28. p.communicate(body.encode("utf8"))
  29. def read_config():
  30. try:
  31. cfgname = os.getenv("CONFIG_FILE", "./config.json")
  32. with open(cfgname) as buf:
  33. cfg = json.load(buf)
  34. except:
  35. app.logger.exception("Error reading conf")
  36. cfg = {}
  37. cfg.setdefault("sites", {})
  38. return cfg
  39. @app.route("/")
  40. def home():
  41. return "casella di destinazione non specificata"
  42. @app.route("/<site>")
  43. def site(site):
  44. try:
  45. sitedata = read_config()["sites"][site]
  46. except KeyError:
  47. sitedata = {}
  48. return render_template("index.htm", siteid=site, sitedata=sitedata)
  49. @app.route("/upload/<site>", methods=["POST"])
  50. def upload(site):
  51. temp_fname = "_%s.ogg" % uuid4().hex
  52. temp_fpath = os.path.join(UPLOAD_DIR, temp_fname)
  53. # prima scrivi su un file temporaneo, poi fai rename
  54. h = hashlib.new("sha1")
  55. with open(temp_fpath, "wb") as buf:
  56. while True:
  57. some_data = request.stream.read(1024)
  58. if not some_data:
  59. break
  60. buf.write(some_data)
  61. h.update(some_data)
  62. # rinomina con l'hash
  63. app.logger.info("hash = %s", h.hexdigest())
  64. fname = "%s.ogg" % h.hexdigest()
  65. os.rename(temp_fpath, os.path.join(UPLOAD_DIR, fname))
  66. if site in read_config()["sites"]:
  67. to = read_config()["sites"][site].get("email", [])
  68. if to:
  69. sender = os.getenv("MAIL_FROM", "")
  70. if not sender:
  71. app.logger.info("Not sending email (unconfigured FROM)")
  72. else:
  73. app.logger.debug("Sending email for `%s` to `%s`", site, ";".join(to))
  74. url = url_for("dl", fname=fname, _external=True, _scheme="https")
  75. sendmail(
  76. sender,
  77. to,
  78. subject="Nuovo messaggio (%s)" % site,
  79. body="Alle {now:%H:%M} hai ricevuto un messaggio nella segreteria di {site}\n"
  80. "Puoi ascoltarlo cliccando su\n{url}\n"
  81. "Per scaricare l'audio, troverai un link dentro la pagina"
  82. "---\n"
  83. "Il servizio è gentilmente offerto da degenerazione.xyz".format(
  84. now=datetime.now(), site=site, url=url
  85. ),
  86. )
  87. else:
  88. logging.warn("Sito senza configurazione!")
  89. return fname
  90. @app.route("/listen/<fname>")
  91. def play(fname):
  92. # prevent path traversal or any other trick
  93. if "/" in fname or not re.match(r"^[a-z0-9]*.(ogg|wav)", fname):
  94. abort(400)
  95. fpath = os.path.join(UPLOAD_DIR, fname)
  96. if not os.path.exists(fpath):
  97. abort(404)
  98. return render_template("player.html", fname=fname)
  99. @app.route("/download/<fname>")
  100. def dl(fname):
  101. # prevent path traversal or any other trick
  102. if "/" in fname or not re.match(r"^[a-z0-9]*.(ogg|wav)", fname):
  103. abort(400)
  104. fpath = os.path.join(UPLOAD_DIR, fname)
  105. if not os.path.exists(fpath):
  106. abort(404)
  107. with open(fpath, "rb") as buf:
  108. content = buf.read()
  109. r = make_response(content)
  110. r.headers["Content-Type"] = "audio/ogg" # TODO: better detect
  111. return r
  112. @app.route("/info/license")
  113. def license():
  114. return render_template("license.html")