Another Ham Radio Logbook -- Web, Multi-user multiple-logbook, with eQSL upload support
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.

utils.py 4.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. import os
  2. import random
  3. import re
  4. import string
  5. from functools import wraps
  6. import pytz
  7. from flask import flash
  8. from flask_security import current_user
  9. from markupsafe import Markup
  10. from unidecode import unidecode
  11. from models import db, Apitoken, Band, Role, Logging
  12. _punct_re = re.compile(r'[\t !"#$%&\'()*\-/<=>?@\[\\\]^_`{|},.]+')
  13. def slugify(text, delim="_"):
  14. """
  15. Generate a slug in ASCII-only form
  16. :param text: Text to slugify
  17. :param delim: Delimiter to join
  18. :return: str slug
  19. """
  20. result = []
  21. for word in _punct_re.split(text.lower()):
  22. result.extend(unidecode(word).split())
  23. return delim.join(result)
  24. def gen_random_str(size=10):
  25. """
  26. Generate random string
  27. :param size: Size of string
  28. :return: Random string
  29. """
  30. return "".join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in range(size))
  31. def path_or_none(fbase, ftype, fname):
  32. """
  33. Return path or none
  34. :param fbase: Base directory
  35. :param ftype: Type directory
  36. :param fname: Filename
  37. :return: Full path or None
  38. """
  39. if not fbase or not ftype or not fname:
  40. return None
  41. fpath = os.path.join(fbase, ftype, fname)
  42. return fpath if os.path.isfile(fpath) else None
  43. def generate_uniques_apitoken():
  44. """
  45. Generate an unique API Token
  46. :return: Dict of token and secret pair
  47. """
  48. while 1:
  49. tmp_token = gen_random_str(20)
  50. tmp_secret = gen_random_str(20)
  51. blip = Apitoken.query.filter_by(token=tmp_token, secret=tmp_secret).first()
  52. if blip:
  53. continue
  54. else:
  55. return {"token": tmp_token, "secret": tmp_secret}
  56. return None
  57. def f7(seq):
  58. seen = set()
  59. seen_add = seen.add
  60. return [x for x in seq if not (x in seen or seen_add(x))]
  61. def dt_utc_to_user_tz(dt, user=None):
  62. if not user:
  63. user = current_user
  64. user_tz = pytz.timezone(user.timezone)
  65. if dt.tzinfo == user_tz:
  66. return dt # already converted
  67. utc_dt = pytz.timezone("UTC").localize(dt) # Makes a naive-UTC DateTime
  68. return utc_dt.astimezone(user_tz) # Then convert it to the user_tz
  69. def show_date_no_offset(dt):
  70. return dt.strftime("%Y-%m-%d %H:%M:%S")
  71. class InvalidUsage(Exception):
  72. status_code = 400
  73. def __init__(self, message, status_code=None, payload=None):
  74. Exception.__init__(self)
  75. self.message = message
  76. if status_code is not None:
  77. self.status_code = status_code
  78. self.payload = payload
  79. def to_dict(self):
  80. rv = dict(self.payload or ())
  81. rv["message"] = self.message
  82. rv["status"] = "error"
  83. rv["code"] = self.status_code
  84. return rv
  85. def check_default_profile(f):
  86. @wraps(f)
  87. def wrap(*args, **kwargs):
  88. errs = []
  89. if current_user.is_authenticated:
  90. if current_user.callsign == "N0C4LL":
  91. errs.append("Profile callsign not changed !")
  92. if current_user.locator == "JN":
  93. errs.append("Profile locator not changed !")
  94. bands = (
  95. db.session.query(Band.id)
  96. .filter(Band.modes.is_(None), Band.start.is_(None), Band.zone == current_user.zone)
  97. .count()
  98. )
  99. if bands <= 0 or not bands:
  100. errs.append(
  101. "The IARU Zone you selected doesn't have any band defined in AHRL yet. See with devs please."
  102. )
  103. if len(errs) > 0:
  104. flash(Markup("Errors:<br />{0}".format("<br />".join(errs))), "error")
  105. return f(*args, **kwargs)
  106. return wrap
  107. def is_admin():
  108. adm = Role.query.filter(Role.name == "admin").first()
  109. if not current_user or not current_user.is_authenticated or not adm:
  110. return False
  111. if adm in current_user.roles:
  112. return True
  113. return False
  114. def add_log(category, level, message):
  115. if not category or not level or not message:
  116. print("!! Fatal error in add_log() one of three variables not set")
  117. print("[LOG][{0}][{1}] {2}".format(level, category, message))
  118. a = Logging(category=category, level=level, message=message)
  119. db.session.add(a)
  120. db.session.commit()