app.py 4.7 KB

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