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.

274 lines
9.8 KiB

import redis
import uuid
from redis_app.utils.index import create_index
DEFAULT_EXPIRE_TIME = 300
EXPIRE_REFRESH_TIME = 60
redis_connection = redis.Redis(host='localhost', port=6379, decode_responses=True)
pub_sub = redis_connection.pubsub()
create_index(redis_connection)
####################################################################################
# - PERSONS - #
####################################################################################
def getPersonIdNameRole(name, role):
query = f"@name:{name} @role:{role}"
results = redis_connection.execute_command('FT.SEARCH', 'idx:persons', query)
if results[0] > 0:
person_key = results[1]
return person_key
return False
def getPersonId(person):
return getPersonIdNameRole(person["name"], person["role"])
def getPerson(person_id):
return redis_connection.hgetall(f"person:{person_id}")
def register_redis(name, role):
query = f"@name:{name} @role:{role}"
results = redis_connection.execute_command('FT.SEARCH', 'idx:persons', query)
# First element = number of results
if results[0] > 0:
return False
person_key = f"person:{get_uuid4()}"
redis_connection.hset(person_key, mapping={
'name': name,
'role': role
})
return redis_connection.hgetall(person_key)
def login_redis(name, role):
query = f"@name:{name} @role:{role}"
results = redis_connection.execute_command('FT.SEARCH', 'idx:persons', query)
# First element = number of results
if results[0] > 0:
person_key = results[1]
return redis_connection.hgetall(person_key)
return False
def changeProfile_redis(person_id, name, role):
new_person_id = getPersonIdNameRole(name, role)
if new_person_id:
return False
redis_connection.hmset(person_id, mapping={"name": name, "role": role})
return getPerson(person_id.split(':')[1])
####################################################################################
# - COURSES - #
####################################################################################
def isExpired(course_id):
ttl = redis_connection.ttl(f"course:{course_id}")
if ttl == -2 or ttl == 0: # If -1, the key has no expiration
return True
return False
def isCourseFull(course):
students = course.get('students', '') # Because it crashes with ['students'], we have to put a default value: '' here
if not students:
return False
try:
places = int(course['places'])
if len(students.split(',')) >= places:
return True
return False
except:
return False
def getCourseId(course):
query = f"@title:{course['title']} @teacher:{course['teacher']}"
results = redis_connection.execute_command('FT.SEARCH', 'idx:courses', query)
if results[0] > 0:
course_key = results[1]
return course_key
return False
def getCourse(course_id):
return redis_connection.hgetall(f"course:{course_id}")
def delete_course(course_id):
course = redis_connection.hgetall(f"course:{course_id}")
if not course:
return False
redis_connection.delete(f"course:{course_id}")
return True
def create_course(course_title, course_summary, course_level, course_places, course_teacher):
course_id = get_uuid4()
redis_connection.hset(f"course:{course_id}", mapping={
"title": course_title,
"summary": course_summary,
"level": course_level,
"places": course_places,
"teacher": course_teacher
})
redis_connection.expire(f"course:{course_id}", DEFAULT_EXPIRE_TIME)
def update_course(course_id, course_title, course_summary, course_level, course_places, course_teacher):
redis_connection.hset(f"course:{course_id}", mapping={
"title": course_title,
"summary": course_summary,
"level": course_level,
"places": course_places,
"teacher": course_teacher
})
redis_connection.expire(f"course:{course_id}", DEFAULT_EXPIRE_TIME)
publish(course_id, f"UPDATE: Course:{course_id} is now: Title: {course_title}, Summary: {course_summary}, Level: {course_level}, Places: {course_places}, Teacher: {course_teacher}")
def course_register(course_id, person_id):
course = redis_connection.hgetall(f"course:{course_id}")
person = redis_connection.hgetall(f"person:{person_id}")
if not course or not person:
return False
students = course.get('students', '')
if person_id in students.split(','):
return True
try:
places = int(course['places'])
if students != '':
students_nb = len(students.split(','))
if students_nb and students_nb >= places:
return False
except:
return False
if not students:
new_students = person_id
else:
new_students = students + "," + person_id
redis_connection.hset(f"course:{course_id}", "students", new_students)
return True
def course_unregister(course_id, person_id):
course = redis_connection.hgetall(f"course:{course_id}")
person = redis_connection.hgetall(f"person:{person_id}")
if not course or not person:
return False
students = course.get('students', '')
if person_id not in students.split(','):
return True
students_list = students.split(",")
if len(students_list) == 1:
new_students = ""
else:
new_students = ",".join([student for student in students_list if student != person_id])
redis_connection.hset(f"course:{course_id}", "students", new_students)
return True
def refresh_expire(course_id):
course = redis_connection.hgetall(f"course:{course_id}")
if not course:
return False
ttl = redis_connection.ttl(f"course:{course_id}")
if ttl <= 0:
return False
redis_connection.expire(f"course:{course_id}", ttl + EXPIRE_REFRESH_TIME)
return True
####################################################################################
# - LINKS - #
####################################################################################
def getCoursesFromPerson(person_id):
course_keys = redis_connection.keys(f"course:*")
courses = []
person = redis_connection.hgetall(f"person:{person_id}")
for key in course_keys:
course_data = redis_connection.hgetall(key)
if person['role'] == "Student":
if person_id in course_data.get('students', '').split(","):
course_id = getCourseId(course_data)
if course_id == False:
continue
course_data['id'] = course_id.split(":")[1]
courses.append(course_data)
else:
teacher_id = course_data["teacher"]
if teacher_id == person_id:
course_id = getCourseId(course_data)
if course_id == False:
continue
course_data['id'] = course_id.split(":")[1]
courses.append(course_data)
return courses
def isPersonRegisteredToCourse(course, person):
if not person:
return False
person_id = getPersonId(person).split(":")[1]
if not person_id:
return False
course_id = getCourseId(course)
if not course_id:
return False
course_keys = redis_connection.keys(f"course:*")
for key in course_keys:
course_data = redis_connection.hgetall(key)
if person['role'] == "Student":
if person_id in course_data.get('students', '').split(","):
current_course_id = getCourseId(course_data)
if current_course_id == False:
continue
if course_id == current_course_id:
return True
return False
####################################################################################
# - UTILS - #
####################################################################################
def get_uuid4():
return str(uuid.uuid4()).replace('-', '')
def publish(course_id, message):
redis_connection.publish(course_id, message)
def search_redis(keywords):
courses = []
for keyword in keywords.split(' '):
if not keyword: # When the users end his keywords with a ' '
continue
title_query = f"@title:{keyword}"
summary_query = f"@summary:{keyword}"
level_query = f"@level:{keyword}"
teacher_query = f"@teacher:{keyword}"
title_results = redis_connection.execute_command('FT.SEARCH', 'idx:courses', title_query)
summary_results = redis_connection.execute_command('FT.SEARCH', 'idx:courses', summary_query)
level_results = redis_connection.execute_command('FT.SEARCH', 'idx:courses', level_query)
teacher_results = redis_connection.execute_command('FT.SEARCH', 'idx:courses', teacher_query)
for i in range(1, len(title_results), 2):
courses.append(title_results[i])
for i in range(1, len(summary_results), 2):
courses.append(summary_results[i])
for i in range(1, len(level_results), 2):
courses.append(level_results[i])
for i in range(1, len(teacher_results), 2):
courses.append(teacher_results[i])
return courses
def notifications_redis(*courses_id):
pub_sub.punsubscribe()
pub_sub.psubscribe(*courses_id)
for message in pub_sub.listen():
if message["type"] != 'pmessage':
continue
break
return message