feat: Add initial notifications
All checks were successful
Build Docker / Build Docker (push) Successful in 27s

This commit is contained in:
Nathan Woodburn 2023-12-11 20:53:26 +11:00
parent 64547ef6d4
commit 8fdb777ba4
Signed by: nathanwoodburn
GPG Key ID: 203B000478AD0EF1
6 changed files with 206 additions and 65 deletions

View File

@ -150,6 +150,17 @@ def getUser(userToken:str):
user = user[0] 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]} 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): def logoutUser(userToken:str):
pass pass

View File

@ -9,6 +9,7 @@ from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart from email.mime.multipart import MIMEMultipart
import requests import requests
import re import re
import account
dotenv.load_dotenv() dotenv.load_dotenv()
@ -122,10 +123,13 @@ def syncDomains():
userDomains = json.loads(user[1]) userDomains = json.loads(user[1])
# Loop through user domains # Loop through user domains
for userDomain in userDomains: for userDomain in userDomains:
customNotifications = False
if 'notifications' in userDomain:
customNotifications = userDomain['notifications']
# Check if domain is pending # Check if domain is pending
if (userDomain['status'] == 'pending'): if (userDomain['status'] == 'pending'):
try: try:
print('Importing domain: ' + userDomain['name'])
r = requests.post('http://x:' + os.getenv('HSD_API_KEY') + '@' + os.getenv('HSD_IP') 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']]}) + ':' + os.getenv('HSD_WALLET_PORT'), json={'method': 'importname', 'params': [userDomain['name']]})
@ -137,6 +141,7 @@ def syncDomains():
userDomain['transfering'] = 0 userDomain['transfering'] = 0
userDomain['next'] = 'none' userDomain['next'] = 'none'
userDomain['when'] = 0 userDomain['when'] = 0
userDomain['records'] = ''
# Update user domains # Update user domains
conn = mysql.connector.connect(**db_config) conn = mysql.connector.connect(**db_config)
@ -152,16 +157,24 @@ def syncDomains():
# Get domain info # Get domain info
r = requests.post('http://x:' + os.getenv('HSD_API_KEY') + '@' + os.getenv('HSD_IP') r = requests.post('http://x:' + os.getenv('HSD_API_KEY') + '@' + os.getenv('HSD_IP')
+ ':' + os.getenv('HSD_PORT'), json={'method': 'getnameinfo', 'params': [userDomain['name']]}) + ':' + os.getenv('HSD_PORT'), json={'method': 'getnameinfo', 'params': [userDomain['name']]})
print(json.dumps(r.json(), indent=4))
if (r.status_code == 200): if (r.status_code == 200):
data = r.json() data = r.json()
print(json.dumps(data, indent=4))
# Check if domain is registered # Check if domain is registered
info = data['result']['info'] info = data['result']['info']
if (userDomain['transfering'] != info['transfer']): if (userDomain['transfering'] != info['transfer']):
# Update domain status # Update domain status
alert('transfer', userDomain['name'], userID) if (notify('transfer', customNotifications, userID)):
alert('transfer', userDomain['name'], userID)
userDomain['transfering'] = info['transfer'] 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 'stats' in info:
if 'blocksUntilExpire' in info['stats']: if 'blocksUntilExpire' in info['stats']:
# Update domain status # Update domain status
@ -170,8 +183,10 @@ def syncDomains():
previous = userDomain['when'] previous = userDomain['when']
userDomain['when'] = info['stats']['blocksUntilExpire'] userDomain['when'] = info['stats']['blocksUntilExpire']
if (crossTimeAlert(userDomain['next'], previous, userDomain['when'])): if (crossTimeAlert(previous, userDomain['when']) or True):
alert('expire', userDomain['name'], userID) if (notify('expire', customNotifications, userID,
crossTimeAlert(previous, userDomain['when']))):
alert('expire', userDomain['name'], userID, crossTimeAlert(previous, userDomain['when']))
elif 'blocksUntilBidding' in info['stats']: elif 'blocksUntilBidding' in info['stats']:
# Update domain status # Update domain status
@ -192,21 +207,90 @@ def syncDomains():
return "Failed to get info about domain: " + userDomain['name'] + "<br>" + str(r.text) return "Failed to get info about domain: " + userDomain['name'] + "<br>" + str(r.text)
return "Finished syncing domains" return "Finished syncing domains"
def alert(event,domain,user): def alert(event,domain,userID, time=False):
# TODO this later notification_name = {
pass '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 # Check for each of these times to see if we should alert
month = 4320 month = 4320
week = 1008 week = 1008
# If the time crossed the month mark # If the time crossed the month mark
if (was > month and now <= month): if (was > month and now <= month):
return True return "month"
# If the time crossed the week mark # If the time crossed the week mark
if (was > week and now <= week): if (was > week and now <= week):
return True return "week"
return False return False

112
main.py
View File

@ -150,11 +150,27 @@ def dashboard():
} }
if ('expiry_month' in user['notifications']): if ('expiry_month' in user['notifications']):
expiry_month = user['notifications']['expiry_month'] 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, return render_template('dashboard.html', domains=domains, notifications=notifications,
email=email, discord=discord, telegram=telegram, email=email, discord=discord, telegram=telegram,
expiry_week=expiry_week,expiry_month=expiry_month, expiry_week=expiry_week,expiry_month=expiry_month,
transfer=transfer_notifications,edit=edit_notifications,
error=error,success=success,admin=user['admin']) error=error,success=success,admin=user['admin'])
return redirect('/login') return redirect('/login')
@ -213,58 +229,52 @@ def notification_options():
# Check if user is logged in # Check if user is logged in
if 'user_token' in request.cookies: if 'user_token' in request.cookies:
if (account.verifyUser(request.cookies.get('user_token'))): if (account.verifyUser(request.cookies.get('user_token'))):
# Get user data notifications = {
user = account.getUser(request.cookies.get('user_token')) "expiry_week": {
expiry_week = {
"email": False, "email": False,
"discord": False, "discord": False,
"telegram": 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
}
} }
expiry_month = { # Get user data
"email": False, user = account.getUser(request.cookies.get('user_token'))
"discord": False, for key in request.form:
"telegram": False 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'): if not request.form.get('domain'):
notifications = user['notifications'] # Add user notifications
for key in request.form: if 'discord' in user['notifications']:
if (key.endswith('_week')): notifications['discord'] = user['notifications']['discord']
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
account.updateNotifications(request.cookies.get('user_token'), notifications) account.updateNotifications(request.cookies.get('user_token'), notifications)
return redirect('/dashboard') return redirect('/dashboard')
else: 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() 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
account.updateDomainNotifications(request.cookies.get('user_token'), account.updateDomainNotifications(request.cookies.get('user_token'),
domain,notifications) domain,notifications)
return redirect('/' + domain + '/info') return redirect('/' + domain + '/info')
@ -351,17 +361,33 @@ def domain(domain):
"discord": False, "discord": False,
"telegram": False "telegram": False
} }
transfer_notifications = {
"email": False,
"discord": False,
"telegram": False
}
edit_notifications = {
"email": False,
"discord": False,
"telegram": False
}
if ('notifications' in domainInfo): if ('notifications' in domainInfo):
if ('expiry_week' in domainInfo['notifications']): if ('expiry_week' in domainInfo['notifications']):
expiry_week = domainInfo['notifications']['expiry_week'] expiry_week = domainInfo['notifications']['expiry_week']
if ('expiry_month' in domainInfo['notifications']): if ('expiry_month' in domainInfo['notifications']):
expiry_month = domainInfo['notifications']['expiry_month'] 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(), return render_template('info.html', domain=str(domain).capitalize(),
next=next,when_blocks=when_blocks,when_time=when_time, next=next,when_blocks=when_blocks,when_time=when_time,
transfering=transfering,expiry_week=expiry_week, transfering=transfering,expiry_week=expiry_week,
expiry_month=expiry_month) expiry_month=expiry_month, transfer=transfer_notifications,
edit=edit_notifications)
else: else:
return render_template('info.html', domain=str(domain).capitalize()) return render_template('info.html', domain=str(domain).capitalize())

View File

@ -10,6 +10,7 @@ import dotenv
from apscheduler.schedulers.background import BackgroundScheduler from apscheduler.schedulers.background import BackgroundScheduler
import sys import sys
import json import json
import domains
dotenv.load_dotenv() dotenv.load_dotenv()
db_config = { db_config = {
@ -48,14 +49,9 @@ def establish_database_connection():
if __name__ == '__main__': if __name__ == '__main__':
# scheduler = BackgroundScheduler() scheduler = BackgroundScheduler()
# Run main.update_events every hour scheduler.add_job(domains.syncDomains, 'cron', hour='*')
# scheduler.add_job(update_events, 'cron', hour='*') scheduler.start()
# 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()
establish_database_connection() establish_database_connection()
db_init() db_init()

View File

@ -74,6 +74,18 @@
<input id="formCheck-{{ loop.index }}" class="form-check-input" type="checkbox" name="{{ platform }}_month" {% if enabled %}checked{% endif %}/> <input id="formCheck-{{ loop.index }}" class="form-check-input" type="checkbox" name="{{ platform }}_month" {% if enabled %}checked{% endif %}/>
<label class="form-check-label" for="formCheck-{{ loop.index }}">{{ platform|capitalize }}</label> <label class="form-check-label" for="formCheck-{{ loop.index }}">{{ platform|capitalize }}</label>
</div> </div>
{% endfor %}</li>
<li class="list-group-item"><span style="display: block;">Domain transfer alerts</span>{% for platform, enabled in transfer.items() %}
<div class="form-check form-switch form-check-inline">
<input id="formCheck-{{ loop.index }}" class="form-check-input" type="checkbox" name="{{ platform }}_transfer" {% if enabled %}checked{% endif %}/>
<label class="form-check-label" for="formCheck-{{ loop.index }}">{{ platform|capitalize }}</label>
</div>
{% endfor %}</li>
<li class="list-group-item"><span style="display: block;">Domain edit alerts</span>{% for platform, enabled in edit.items() %}
<div class="form-check form-switch form-check-inline">
<input id="formCheck-{{ loop.index }}" class="form-check-input" type="checkbox" name="{{ platform }}_edit" {% if enabled %}checked{% endif %}/>
<label class="form-check-label" for="formCheck-{{ loop.index }}">{{ platform|capitalize }}</label>
</div>
{% endfor %}</li> {% endfor %}</li>
</ul> </ul>
<div style="text-align: right;"><input class="btn btn-primary" type="submit" value="Save" style="margin-top: 20px;"></div> <div style="text-align: right;"><input class="btn btn-primary" type="submit" value="Save" style="margin-top: 20px;"></div>

View File

@ -62,6 +62,18 @@
<input id="formCheck-{{ loop.index }}" class="form-check-input" type="checkbox" name="{{ platform }}_month" {% if enabled %}checked{% endif %}/> <input id="formCheck-{{ loop.index }}" class="form-check-input" type="checkbox" name="{{ platform }}_month" {% if enabled %}checked{% endif %}/>
<label class="form-check-label" for="formCheck-{{ loop.index }}">{{ platform|capitalize }}</label> <label class="form-check-label" for="formCheck-{{ loop.index }}">{{ platform|capitalize }}</label>
</div> </div>
{% endfor %}</li>
<li class="list-group-item"><span style="display: block;">Domain transfer alerts</span>{% for platform, enabled in transfer.items() %}
<div class="form-check form-switch form-check-inline">
<input id="formCheck-{{ loop.index }}" class="form-check-input" type="checkbox" name="{{ platform }}_transfer" {% if enabled %}checked{% endif %}/>
<label class="form-check-label" for="formCheck-{{ loop.index }}">{{ platform|capitalize }}</label>
</div>
{% endfor %}</li>
<li class="list-group-item"><span style="display: block;">Domain edit alerts</span>{% for platform, enabled in edit.items() %}
<div class="form-check form-switch form-check-inline">
<input id="formCheck-{{ loop.index }}" class="form-check-input" type="checkbox" name="{{ platform }}_edit" {% if enabled %}checked{% endif %}/>
<label class="form-check-label" for="formCheck-{{ loop.index }}">{{ platform|capitalize }}</label>
</div>
{% endfor %}</li> {% endfor %}</li>
</ul> </ul>
<div style="text-align: right;"><input class="btn btn-primary" type="submit" value="Save" style="margin-top: 20px;"></div> <div style="text-align: right;"><input class="btn btn-primary" type="submit" value="Save" style="margin-top: 20px;"></div>