From 8fdb777ba481b480e0cbcfda13cceccfbab32521 Mon Sep 17 00:00:00 2001 From: Nathan Woodburn Date: Mon, 11 Dec 2023 20:53:26 +1100 Subject: [PATCH] feat: Add initial notifications --- account.py | 11 ++++ domains.py | 106 +++++++++++++++++++++++++++++++---- main.py | 118 ++++++++++++++++++++++++--------------- server.py | 12 ++-- templates/dashboard.html | 12 ++++ templates/info.html | 12 ++++ 6 files changed, 206 insertions(+), 65 deletions(-) diff --git a/account.py b/account.py index 33b8c53..431b354 100644 --- a/account.py +++ b/account.py @@ -150,6 +150,17 @@ def getUser(userToken:str): user = user[0] return {'id': user[0], 'email': user[1], 'admin': user[2], 'notifications': json.loads(user[3]), 'domains': json.loads(user[4]), 'created_at': user[5]} +def getUserFromID(userID:int): + conn = mysql.connector.connect(**db_config) + cursor = conn.cursor() + cursor.execute("SELECT id, email, admin, notifications, domains, created_at FROM users WHERE id = %s", (userID,)) + user = cursor.fetchall() + cursor.close() + conn.close() + + # Read json token from first user + user = user[0] + return {'id': user[0], 'email': user[1], 'admin': user[2], 'notifications': json.loads(user[3]), 'domains': json.loads(user[4]), 'created_at': user[5]} def logoutUser(userToken:str): pass diff --git a/domains.py b/domains.py index f0b0baf..e8da766 100644 --- a/domains.py +++ b/domains.py @@ -9,6 +9,7 @@ from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart import requests import re +import account dotenv.load_dotenv() @@ -122,10 +123,13 @@ def syncDomains(): userDomains = json.loads(user[1]) # Loop through user domains for userDomain in userDomains: + customNotifications = False + if 'notifications' in userDomain: + customNotifications = userDomain['notifications'] + # Check if domain is pending if (userDomain['status'] == 'pending'): try: - print('Importing domain: ' + userDomain['name']) r = requests.post('http://x:' + os.getenv('HSD_API_KEY') + '@' + os.getenv('HSD_IP') + ':' + os.getenv('HSD_WALLET_PORT'), json={'method': 'importname', 'params': [userDomain['name']]}) @@ -137,6 +141,7 @@ def syncDomains(): userDomain['transfering'] = 0 userDomain['next'] = 'none' userDomain['when'] = 0 + userDomain['records'] = '' # Update user domains conn = mysql.connector.connect(**db_config) @@ -152,16 +157,24 @@ def syncDomains(): # Get domain info r = requests.post('http://x:' + os.getenv('HSD_API_KEY') + '@' + os.getenv('HSD_IP') + ':' + os.getenv('HSD_PORT'), json={'method': 'getnameinfo', 'params': [userDomain['name']]}) - print(json.dumps(r.json(), indent=4)) if (r.status_code == 200): data = r.json() + print(json.dumps(data, indent=4)) # Check if domain is registered info = data['result']['info'] if (userDomain['transfering'] != info['transfer']): # Update domain status - alert('transfer', userDomain['name'], userID) + if (notify('transfer', customNotifications, userID)): + alert('transfer', userDomain['name'], userID) userDomain['transfering'] = info['transfer'] + if (userDomain['records'] != info['data'] and userDomain['records'] != ''): + # Update domain status + if (notify('dns', customNotifications, userID)): + alert('dns', userDomain['name'], userID) + userDomain['records'] = info['data'] + + if 'stats' in info: if 'blocksUntilExpire' in info['stats']: # Update domain status @@ -170,8 +183,10 @@ def syncDomains(): previous = userDomain['when'] userDomain['when'] = info['stats']['blocksUntilExpire'] - if (crossTimeAlert(userDomain['next'], previous, userDomain['when'])): - alert('expire', userDomain['name'], userID) + if (crossTimeAlert(previous, userDomain['when']) or True): + if (notify('expire', customNotifications, userID, + crossTimeAlert(previous, userDomain['when']))): + alert('expire', userDomain['name'], userID, crossTimeAlert(previous, userDomain['when'])) elif 'blocksUntilBidding' in info['stats']: # Update domain status @@ -192,21 +207,90 @@ def syncDomains(): return "Failed to get info about domain: " + userDomain['name'] + "
" + str(r.text) return "Finished syncing domains" -def alert(event,domain,user): - # TODO this later - pass +def alert(event,domain,userID, time=False): + notification_name = { + 'transfer': 'transfer_notifications', + 'dns': 'edit_notifications' + } -def crossTimeAlert(event,was, now): + # Get user + user = account.getUserFromID(userID) + # Check if domain has custom notifications + customNotifications = False + for domainInfo in user['domains']: + if (domainInfo['name'] == domain): + if 'notifications' in domainInfo: + customNotifications = domainInfo['notifications'] + break + + if (customNotifications): + # Send custom notification + if (event != 'expire'): + send(customNotifications[notification_name[event]], domain, event,userID) + elif (time == 'month'): + send(customNotifications['expiry_month'], domain, event,userID) + elif (time == 'week'): + send(customNotifications['expiry_week'], domain, event,userID) + + else: + if (event != 'expire'): + send(user['notifications'][notification_name[event]], domain, event,userID) + elif (time == 'month'): + send(user['notifications']['expiry_month'], domain, event,userID) + elif (time == 'week'): + send(user['notifications']['expiry_week'], domain, event,userID) + +def send(providers,domain:str,event,userID): + user = account.getUserFromID(userID) + + title = { + 'transfer': 'Transfer Alert for {domain}', + 'dns': '{domain} has had a DNS update', + 'expire': '{domain} will expire soon' + } + content = { + 'transfer': 'The domain {domain} has started a transfer to a new wallet', + 'dns': 'The domain {domain} has had a DNS update', + 'expire': '{domain} will expire in {time}' + } + + + title = title[event].replace('{domain}',domain.capitalize()+'/') + content = content[event].replace('{domain}',domain.capitalize()+'/') + if (event == 'expire'): + domainInfo = getCachedDomainInfo(domain) + content = content.replace('{time}',blocksToTime(domainInfo['when'])) + + if (providers['email']): + account.sendEmail(user['email'],title,content) + if (providers['discord']): + if ('discord' in user['notifications']): + account.sendDiscordWebhook(user['notifications']['discord'],title,content) + + +def notify(event, customNotifications, userID, time=False): + # TODO this will check if the user has notifications enabled for the event + # This should make the sync a bit faster but it's not a huge deal + if (event == 'transfer'): + return True + if (event == 'dns'): + return True + if (event == 'expire'): + return True + + return True + +def crossTimeAlert(was, now): # Check for each of these times to see if we should alert month = 4320 week = 1008 # If the time crossed the month mark if (was > month and now <= month): - return True + return "month" # If the time crossed the week mark if (was > week and now <= week): - return True + return "week" return False diff --git a/main.py b/main.py index 49dca9f..6ad9152 100644 --- a/main.py +++ b/main.py @@ -150,11 +150,27 @@ def dashboard(): } if ('expiry_month' in user['notifications']): expiry_month = user['notifications']['expiry_month'] + transfer_notifications = { + "email": True, + "discord": False, + "telegram": False + } + if ('transfer_notifications' in user['notifications']): + transfer_notifications = user['notifications']['transfer_notifications'] + edit_notifications = { + "email": True, + "discord": False, + "telegram": False + } + if ('edit_notifications' in user['notifications']): + edit_notifications = user['notifications']['edit_notifications'] + return render_template('dashboard.html', domains=domains, notifications=notifications, email=email, discord=discord, telegram=telegram, expiry_week=expiry_week,expiry_month=expiry_month, + transfer=transfer_notifications,edit=edit_notifications, error=error,success=success,admin=user['admin']) return redirect('/login') @@ -213,58 +229,52 @@ def notification_options(): # Check if user is logged in if 'user_token' in request.cookies: if (account.verifyUser(request.cookies.get('user_token'))): - # Get user data - user = account.getUser(request.cookies.get('user_token')) - expiry_week = { + notifications = { + "expiry_week": { "email": False, "discord": False, "telegram": False - } - expiry_month = { - "email": False, - "discord": False, - "telegram": False - } - + }, + "expiry_month": { + "email": False, + "discord": False, + "telegram": False + }, + "transfer_notifications": { + "email": False, + "discord": False, + "telegram": False + }, + "edit_notifications": { + "email": False, + "discord": False, + "telegram": False + } + } + # Get user data + user = account.getUser(request.cookies.get('user_token')) + for key in request.form: + if (key.endswith('_week')): + key = key[:-5] + notifications['expiry_week'][key] = True + elif (key.endswith('_month')): + key = key[:-6] + notifications['expiry_month'][key] = True + elif (key.endswith('_transfer')): + key = key[:-9] + notifications['transfer_notifications'][key] = True + elif (key.endswith('_edit')): + key = key[:-5] + notifications['edit_notifications'][key] = True if not request.form.get('domain'): - notifications = user['notifications'] - for key in request.form: - if (key.endswith('_week')): - key = key[:-5] - expiry_week[key] = True - elif (key.endswith('_month')): - key = key[:-6] - expiry_month[key] = True - - notifications['expiry_week'] = expiry_week - notifications['expiry_month'] = expiry_month + # Add user notifications + if 'discord' in user['notifications']: + notifications['discord'] = user['notifications']['discord'] + account.updateNotifications(request.cookies.get('user_token'), notifications) return redirect('/dashboard') else: - notifications = { - "expiry_week": { - "email": False, - "discord": False, - "telegram": False - }, - "expiry_month": { - "email": False, - "discord": False, - "telegram": False - } - } - domainList = user['domains'] - domain = request.form.get('domain').lower() - - - for key in request.form: - if (key.endswith('_week')): - key = key[:-5] - notifications['expiry_week'][key] = True - elif (key.endswith('_month')): - key = key[:-6] - notifications['expiry_month'][key] = True - + domain = request.form.get('domain').lower() account.updateDomainNotifications(request.cookies.get('user_token'), domain,notifications) return redirect('/' + domain + '/info') @@ -351,17 +361,33 @@ def domain(domain): "discord": False, "telegram": False } + transfer_notifications = { + "email": False, + "discord": False, + "telegram": False + } + edit_notifications = { + "email": False, + "discord": False, + "telegram": False + } + if ('notifications' in domainInfo): if ('expiry_week' in domainInfo['notifications']): expiry_week = domainInfo['notifications']['expiry_week'] if ('expiry_month' in domainInfo['notifications']): expiry_month = domainInfo['notifications']['expiry_month'] + if ('transfer_notifications' in domainInfo['notifications']): + transfer_notifications = domainInfo['notifications']['transfer_notifications'] + if ('edit_notifications' in domainInfo['notifications']): + edit_notifications = domainInfo['notifications']['edit_notifications'] return render_template('info.html', domain=str(domain).capitalize(), next=next,when_blocks=when_blocks,when_time=when_time, transfering=transfering,expiry_week=expiry_week, - expiry_month=expiry_month) + expiry_month=expiry_month, transfer=transfer_notifications, + edit=edit_notifications) else: return render_template('info.html', domain=str(domain).capitalize()) diff --git a/server.py b/server.py index 3cb7a73..a0eb45b 100644 --- a/server.py +++ b/server.py @@ -10,6 +10,7 @@ import dotenv from apscheduler.schedulers.background import BackgroundScheduler import sys import json +import domains dotenv.load_dotenv() db_config = { @@ -48,14 +49,9 @@ def establish_database_connection(): if __name__ == '__main__': - # scheduler = BackgroundScheduler() - # Run main.update_events every hour - # scheduler.add_job(update_events, 'cron', hour='*') - # Run main.reset_worship_chat every monday at 12am - # scheduler.add_job(reset_worship_chat, 'cron', day_of_week='mon', hour=0, minute=0) - # Run elvanto.refresh_all_tokens every 6 hours - # scheduler.add_job(refresh_oauth_tokens, 'interval', hours=6) - # scheduler.start() + scheduler = BackgroundScheduler() + scheduler.add_job(domains.syncDomains, 'cron', hour='*') + scheduler.start() establish_database_connection() db_init() diff --git a/templates/dashboard.html b/templates/dashboard.html index ddd59f2..1fd9da7 100644 --- a/templates/dashboard.html +++ b/templates/dashboard.html @@ -74,6 +74,18 @@ +{% endfor %} +
  • Domain transfer alerts{% for platform, enabled in transfer.items() %} +
    + + +
    +{% endfor %}
  • +
  • Domain edit alerts{% for platform, enabled in edit.items() %} +
    + + +
    {% endfor %}
  • diff --git a/templates/info.html b/templates/info.html index fd4d3d9..c802a77 100644 --- a/templates/info.html +++ b/templates/info.html @@ -62,6 +62,18 @@ +{% endfor %} +
  • Domain transfer alerts{% for platform, enabled in transfer.items() %} +
    + + +
    +{% endfor %}
  • +
  • Domain edit alerts{% for platform, enabled in edit.items() %} +
    + + +
    {% endfor %}