Merge pull request #19 from Rushilwiz/development

Development
This commit is contained in:
Rushil Umaretiya 2020-06-16 21:49:39 -04:00 committed by GitHub
commit ee51f3d192
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 167624 additions and 769 deletions

1
.2023rumaretiprofile Normal file
View File

@ -0,0 +1 @@
{"username": "2022rkhondak", "grade": 9, "is_student": true, "password": "hackgroup1"}

1
.rushilwizprofile Normal file
View File

@ -0,0 +1 @@
{"username": "rushilwiz", "grade": 69, "is_student": true, "password": "a"}

View File

@ -1 +0,0 @@
{"username": "2022rkhondak", "grade": 10, "is_student": true, "password": "hackgroup1"}

1
2023rumareti Submodule

@ -0,0 +1 @@
Subproject commit ca356ef8532873bf52ec67a647fbb91a25ca1cb7

View File

@ -9,77 +9,128 @@ import time
import pyperclip import pyperclip
import datetime import datetime
#git clone student directory ==> <student-id>/classes/assignments
#get teacher info from api # git clone student directory ==> <student-id>/classes/assignments
def getStudent(ion_user):
URL = "http://127.0.0.1:8000/api/students/" + ion_user + "/"
r = requests.get(url = URL, auth=('raffukhondaker','hackgroup1'))
if(r.status_code == 200):
data = r.json()
return data
elif(r.status_code == 404):
return None
print("Make new account!")
elif(r.status_code == 403):
return None
print("Invalid username/password")
else:
return None
print(r.status_code)
def getDB(url): # get teacher info from api
r = requests.get(url = url, auth=('raffukhondaker','hackgroup1')) def getStudent(ion_user, password):
URL = "http://127.0.0.1:8000/api/students/" + ion_user + "/"
r = requests.get(url=URL, auth=(ion_user, password))
if (r.status_code == 200):
data = r.json()
return data
elif (r.status_code == 404):
return None
print("Make new account!")
elif (r.status_code == 403):
return None
print("Invalid username/password")
else:
return None
print(r.status_code)
#makes a GET request to given url, returns dict
def getDB(user, pwd, url):
"""
Sends a GET request to url
:param user: username
:param pwd: password
:param url: URL for request
:return: json request response
"""
r = requests.get(url=url, auth=(user, pwd))
print("GET:" + str(r.status_code)) print("GET:" + str(r.status_code))
return(r.json()) return(r.json())
def postDB(data, url): #makes a PATCH (updates instance) request to given url, returns dict
r = requests.post(url = url, data=data, auth=('raffukhondaker','hackgroup1')) def patchDB(user, pwd, data, url):
"""
Sends a PATCH request to url
:param user: username
:param pwd: password
:param url: URL for request
:param data: data to request
:return: json request response
"""
r = requests.patch(url=url, data=data, auth=(user, pwd))
print("PATCH:" + str(r.status_code))
return r.json()
#makes a POST (makes new instance) request to given url, returns dict
def postDB(user, pwd, data, url):
"""
Sends a POST request to url
:param user: username
:param pwd: password
:param url: URL for request
:param data: data to request
:return: json request response
"""
r = requests.post(url=url, data=data, auth=(user, pwd))
print("POST:" + str(r.status_code)) print("POST:" + str(r.status_code))
return(r.json()) return r.json()
def putDB(data, url):
r = requests.put(url = url, data=data, auth=('raffukhondaker','hackgroup1')) #makes a PUT (overwrites instance) request to given url, returns dict
def putDB(user, pwd, data, url):
"""
Sends a PUT request to url
:param user: username
:param pwd: password
:param url: URL for request
:param data: data to request
:return: json request response
"""
r = requests.put(url=url, data=data, auth=(user, pwd))
print("PUT:" + str(r.status_code)) print("PUT:" + str(r.status_code))
return(r.json()) return r.json()
def patchDB(data, url):
r = requests.patch(url = url, data=data, auth=('raffukhondaker','hackgroup1'))
print("PATH:" + str(r.status_code))
return(r.json())
def delDB(url): #makes a DELETE (delete instance) request to given url, returns dict
r = requests.delete(url = url, auth=('raffukhondaker','hackgroup1')) def delDB(user, pwd, url):
"""
Sends a DELETE request to url
:param user: username
:param pwd: password
:param url: URL for request
:return: json request response
"""
r = requests.delete(url=url, auth=(user, pwd))
print("DELETE:" + str(r.status_code)) print("DELETE:" + str(r.status_code))
return None return None
def command(command): def command(command):
ar = [] ar = []
command = command.split(" ") command = command.split(" ")
for c in command: for c in command:
ar.append(c) ar.append(c)
process = subprocess.Popen(ar, stdout=subprocess.PIPE,stderr=subprocess.PIPE) process = subprocess.Popen(ar, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p=process.poll() p = process.poll()
output = process.communicate()[0] output = process.communicate()[0]
print(output.decode('utf-8')) print(output.decode('utf-8'))
return output.decode('utf-8') return output.decode('utf-8')
#################################################################################################################################### ####################################################################################################################################
#public methods: deleteClass, makeClass, update # public methods: deleteClass, makeClass, update
class Student: class Student:
def __init__(self, data): def __init__(self, data, password):
# teacher info already stored in API # teacher info already stored in API
# intitialze fields after GET request # intitialze fields after GET request
self.git=data['git'] self.git = data['git']
self.username=data['ion_user'] self.username = data['ion_user']
self.url= "http://127.0.0.1:8000/api/students/" + self.username + "/" self.url = "http://127.0.0.1:8000/api/students/" + self.username + "/"
self.grade = data['grade'] self.grade = data['grade']
self.completed = data['completed'] self.completed = data['completed']
self.user = data['user'] self.user = data['user']
#classes in id form (Example: 4,5) self.password = password
#storing actual classes self.completed = data['completed']
cid=data['classes'].split(",") # classes in id form (Example: 4,5)
# storing actual classes
cid = data['classes'].split(",")
try: try:
cid.remove('') cid.remove('')
except: except:
@ -88,16 +139,16 @@ class Student:
cid.remove("") cid.remove("")
except: except:
pass pass
classes=[] classes = []
for c in cid: for c in cid:
url = "http://127.0.0.1:8000/api/classes/" + str(c) + "/" url = "http://127.0.0.1:8000/api/classes/" + str(c) + "/"
classes.append(getDB(url)) classes.append(getDB(self.username, self.password,url))
self.classes = classes self.classes = classes
self.sclass=str(data['classes']) self.sclass = str(data['classes'])
#storing added_to classes # storing added_to classes
nid=data['added_to'].split(",") nid = data['added_to'].split(",")
try: try:
nid.remove('') nid.remove('')
except: except:
@ -106,21 +157,21 @@ class Student:
nid.remove("") nid.remove("")
except: except:
pass pass
nclasses=[] nclasses = []
for c in nid: for c in nid:
url = "http://127.0.0.1:8000/api/classes/" + str(c) + "/" url = "http://127.0.0.1:8000/api/classes/" + str(c) + "/"
nclasses.append(getDB(url)) nclasses.append(getDB(self.username, self.password,url))
self.new = nclasses self.new = nclasses
self.snew=str(data['added_to']) self.snew = str(data['added_to'])
self.repo = data['repo'] self.repo = data['repo']
if(os.path.isdir(self.username) == False): if (os.path.isdir(self.username) == False):
if(self.repo == ""): if (self.repo == ""):
user= self.git user = self.git
pwd= input("Enter Github password: ") pwd = input("Enter Github password: ")
#curl -i -u USER:PASSWORD -d '{"name":"REPO"}' https://api.github.com/user/repos # curl -i -u USER:PASSWORD -d '{"name":"REPO"}' https://api.github.com/user/repos
url= "curl -i -u " + user + ":" + pwd + " -d '" + '{"name":"' + self.username + '"}' + "' " + "https://api.github.com/user/repos" url = "curl -i -u " + user + ":" + pwd + " -d '" + '{"name":"' + self.username + '"}' + "' " + "https://api.github.com/user/repos"
print(url) print(url)
os.system(url) os.system(url)
cdir = os.getcwd() cdir = os.getcwd()
@ -133,11 +184,11 @@ class Student:
command('git push -u origin master') command('git push -u origin master')
os.chdir(cdir) os.chdir(cdir)
self.repo = 'https://github.com/' + self.git + '/' + self.username + '.git' self.repo = 'https://github.com/' + self.git + '/' + self.username + '.git'
data={ data = {
'repo':self.repo 'repo': self.repo
} }
print(patchDB(data, self.url)) print(patchDB(self.username, self.password,data, self.url))
print("Synced to " + self.username) print("Synced to " + self.username)
def getClasses(self): def getClasses(self):
classes = self.classes classes = self.classes
@ -151,29 +202,29 @@ class Student:
print(c['name']) print(c['name'])
alist = c['assignments'] alist = c['assignments']
for a in alist: for a in alist:
ass = getDB("http://127.0.0.1:8000/api/assignments/" + a) ass = getDB(self.username, self.password,"http://127.0.0.1:8000/api/assignments/" + a)
now = datetime.datetime.now() now = datetime.datetime.now()
try: try:
due = ass['due_date'].replace("T", " ").replace("Z", "") due = ass['due_date'].replace("T", " ").replace("Z", "")
due = datetime.datetime.strptime(due, '%Y-%m-%d %H:%M:%S.%f') due = datetime.datetime.strptime(due, '%Y-%m-%d %H:%M:%S.%f')
diff = now - due diff = now - due
zero = datetime.timedelta(0,0) zero = datetime.timedelta(0, 0)
#check due ddate is in span range is now past date (- timdelta) # check due ddate is in span range is now past date (- timdelta)
if(diff < span and diff > zero): if (diff < span and diff > zero):
print(a + " due in:" + str(now-due)) print(a + " due in:" + str(now - due))
except Exception as e: except Exception as e:
print(e) print(e)
pass pass
#update API and Github, all assignments / classes # update API and Github, all assignments / classes
def update(self): def update(self):
cdir = os.getcwd() cdir = os.getcwd()
os.chdir(self.username) os.chdir(self.username)
command("git checkout master") command("git checkout master")
for c in self.classes: for c in self.classes:
print("UPDATING CLASS: " + str(c['name'])) print("UPDATING CLASS: " + str(c['name']))
data = getDB("http://127.0.0.1:8000/api/classes/" + str(c['name'])) data = getDB(self.username, self.password,"http://127.0.0.1:8000/api/classes/" + str(c['name']))
# command("git checkout master") # command("git checkout master")
command("git checkout " + data['name']) command("git checkout " + data['name'])
command("git add .") command("git add .")
@ -187,10 +238,10 @@ class Student:
self.addClass(str(c['name'])) self.addClass(str(c['name']))
command("git checkout master") command("git checkout master")
print(os.getcwd()) print(os.getcwd())
#updates 1 class, does not switch to master # updates 1 class, does not switch to master
def updateClass(self, course): def updateClass(self, course):
if((course in self.sclass) == False): if ((course in self.sclass) == False):
print("Class not found") print("Class not found")
return return
cdir = os.getcwd() cdir = os.getcwd()
@ -201,45 +252,46 @@ class Student:
command("git pull origin " + course) command("git pull origin " + course)
command("git push -u origin " + course) command("git push -u origin " + course)
#class name format: <course-name>_<ion_user> # class name format: <course-name>_<ion_user>
#add classes from 'new' field # add classes from 'new' field
def addClass(self, cid): def addClass(self, cid):
data = getDB('http://127.0.0.1:8000/api/classes/'+ str(cid)) data = getDB(self.username, self.password,'http://127.0.0.1:8000/api/classes/' + str(cid))
if((cid in self.snew) == False or (self.username in data['confirmed'])): if ((cid in self.snew) == False or (self.username in data['confirmed'])):
print("Already enrolled in this class.") print("Already enrolled in this class.")
return None return None
if((cid in self.sclass) or (self.username in data['unconfirmed']) == False): if ((cid in self.sclass) or (self.username in data['unconfirmed']) == False):
print("Not added by teacher yet.") print("Not added by teacher yet.")
return None return None
#add class teacher as cocllaborator to student repo # add class teacher as cocllaborator to student repo
print(os.getcwd()) print(os.getcwd())
pwd= input("Enter Github password: ") pwd = input("Enter Github password: ")
tgit = getDB("http://127.0.0.1:8000/api/teachers/" + data['teacher'] + "/")['git'] tgit = getDB(self.username, self.password,"http://127.0.0.1:8000/api/teachers/" + data['teacher'] + "/")['git']
url= "curl -i -u " + self.git + ":" + pwd + " -X PUT -d '' " + "'https://api.github.com/repos/" + self.git + "/" + self.username + "/collaborators/" + tgit + "'" url = "curl -i -u " + self.git + ":" + pwd + " -X PUT -d '' " + "'https://api.github.com/repos/" + self.git + "/" + self.username + "/collaborators/" + tgit + "'"
print(url) print(url)
os.system(url) os.system(url)
cdir = os.getcwd() cdir = os.getcwd()
path1 = self.username + "/" + self.username
path2 = self.username
if(os.path.isdir(path1)):
os.chdir(path1)
else:
os.chdir(self.username)
command("git clone " + self.repo)
os.chdir(self.username)
#push to git, start at master
os.chdir(self.username) os.chdir(self.username)
# path1 = self.username + "/" + self.username
# path2 = self.username
# if(os.path.isdir(path1)):
# os.chdir(path1)
# else:
# os.chdir(self.username)
# command("git clone " + self.repo)
# os.chdir(self.username)
# push to git, start at master
#os.chdir(self.username)
command("git checkout master") command("git checkout master")
command("git branch " + data['name']) command("git branch " + data['name'])
command("git commit -m initial") command("git commit -m initial")
command("git push origin " + data['name']) command("git push origin " + data['name'])
command("git checkout master") command("git checkout master")
#git clone --single-branch --branch <branchname> <remote-repo> # git clone --single-branch --branch <branchname> <remote-repo>
os.chdir(cdir) os.chdir(cdir)
# data['unconfirmed'] = data['unconfirmed'].replace("," + self.username, "") # data['unconfirmed'] = data['unconfirmed'].replace("," + self.username, "")
@ -250,79 +302,79 @@ class Student:
# print(data['confirmed']) # print(data['confirmed'])
# print(putDB(data, 'http://127.0.0.1:8000/api/classes/'+ str(cid) + "/")) # print(putDB(data, 'http://127.0.0.1:8000/api/classes/'+ str(cid) + "/"))
#add teacher as collaborator # add teacher as collaborator
#curl -i -u "USER:PASSWORDD" -X PUT -d '' 'https://api.github.com/repos/USER/REPO/collaborators/COLLABORATOR' # curl -i -u "USER:PASSWORDD" -X PUT -d '' 'https://api.github.com/repos/USER/REPO/collaborators/COLLABORATOR'
user = self.git user = self.git
self.classes.append(data) self.classes.append(data)
if(len(self.sclass)==0): if (len(self.sclass) == 0):
self.sclass = data['name'] self.sclass = data['name']
else: else:
self.sclass = self.sclass + "," + str(data['name']) self.sclass = self.sclass + "," + str(data['name'])
#upddate self.new # upddate self.new
snew="" snew = ""
new = [] new = []
for i in range(len(self.new)): for i in range(len(self.new)):
if(self.new[i]['name'] == data['name']): if (self.new[i]['name'] == data['name']):
del self.new[i] del self.new[i]
#recreate sclass field, using ids # recreate sclass field, using ids
for c in self.new: for c in self.new:
snew = snew + str(c['name']) + "," snew = snew + str(c['name']) + ","
new.append(getDB("http://127.0.0.1:8000/api/classes/" + str(cid))) new.append(getDB(self.username, self.password,"http://127.0.0.1:8000/api/classes/" + str(cid)))
self.snew=snew self.snew = snew
self.new=new self.new = new
break break
#update teacher instance in db, classes field # update teacher instance in db, classes field
data={ data = {
'user':self.user, 'user': self.user,
'added_to':self.snew, 'added_to': self.snew,
'classes':self.sclass 'classes': self.sclass
} }
print(self.url) print(self.url)
print(patchDB(data, self.url)) print(patchDB(self.username, self.password,data, self.url))
return data return data
def submit(self, path): def submit(self, path):
#2022rkhondak/English11_eharris1/Essay1 # 2022rkhondak/English11_eharris1/Essay1
#check if valid assignment # check if valid assignment
parts = path.split("/") parts = path.split("/")
if(len(parts) != 3): if (len(parts) != 3):
print("Assignment path too short") print("Assignment path too short")
return return
isclass = False isclass = False
for c in self.classes: for c in self.classes:
if(c['name'] == parts[1]): if (c['name'] == parts[1]):
isclass==True isclass == True
break break
if(parts[0] != self.username and isclass and os.path.isdir(path) == False): if (parts[0] != self.username and isclass and os.path.isdir(path) == False):
print("Not valid assignment") print("Not valid assignment")
return return
if((parts[1] + "/" + parts[2]) in self.completed): if ((parts[1] + "/" + parts[2]) in self.completed):
print(parts[2] + " already submited. ") print(parts[2] + " already submited. ")
# return # return
resp = input("Are you sure you want to submit? You cannot do this again.(y/N) ") resp = input("Are you sure you want to submit? You cannot do this again.(y/N) ")
if(resp == 'y'): if (resp == 'y'):
os.chdir(self.username + "/" + parts[1]) os.chdir(self.username + "/" + parts[1])
command("git add .") command("git add .")
command("git commit -m submit") command("git commit -m submit")
command("git tag " + parts[1] + "-final") command("git tag " + parts[1] + "-final")
command("git push -u origin " + self.username + " --tags") command("git push -u origin " + self.username + " --tags")
self.completed = self.completed + "," + parts[1] + "/" + parts[2] self.completed = self.completed + "," + parts[1] + "/" + parts[2]
data={ data = {
'user':self.user, 'user': self.user,
'git':self.git, 'git': self.git,
'ion_user':self.username, 'ion_user': self.username,
'student_id':self.student_id, 'student_id': self.student_id,
'added_to':self.snew, 'added_to': self.snew,
'url':self.url, 'url': self.url,
'classes':self.sclass, 'classes': self.sclass,
'grade':self.grade, 'grade': self.grade,
'completed':self.completed 'completed': self.completed
} }
#print(putDB(data, "http://127.0.0.1:8000/api/students/" + self.username + "/")) # print(putDB(data, "http://127.0.0.1:8000/api/students/" + self.username + "/"))
def viewClass(self, courses): def viewClass(self, courses):
self.update() self.update()
cdir = os.getcwd() cdir = os.getcwd()
@ -331,16 +383,17 @@ class Student:
if c['name'] == courses: if c['name'] == courses:
command("git checkout " + courses) command("git checkout " + courses)
print(os.listdir()) print(os.listdir())
break os.chdir(cdir)
return
os.chdir(cdir) os.chdir(cdir)
print("Class not found") print("Class not found")
return return
def exitCLI(self): def exitCLI(self):
print(os.getcwd()) print(os.getcwd())
self.update() self.update()
command("git checkout master") command("git checkout master")
def submit(self, course, assignment): def submit(self, course, assignment):
cdir = os.getcwd() cdir = os.getcwd()
os.chdir(self.username) os.chdir(self.username)
@ -348,14 +401,15 @@ class Student:
command("git add .") command("git add .")
command("git commit -m update") command("git commit -m update")
command('git checkout ' + course) command('git checkout ' + course)
time.sleep(5)
ass = os.listdir() ass = os.listdir()
oname = ''
inclass = False inclass = False
for a in ass: for a in ass:
if a == assignment: if a in assignment:
inclass = True inclass = True
oname = a + "_" + course
break break
if(inclass == False): if (inclass == False):
print(assignment + " not an assignment of " + course) print(assignment + " not an assignment of " + course)
command('git checkout master') command('git checkout master')
os.chdir(cdir) os.chdir(cdir)
@ -367,10 +421,16 @@ class Student:
command("git tag " + assignment + "-final") command("git tag " + assignment + "-final")
command("git push -u origin " + course + " --tags") command("git push -u origin " + course + " --tags")
command('git checkout master') command('git checkout master')
self.completed = assignment + "," + self.completed
data = {
'completed': self.completed
}
patchDB(self.username, self.password, data, self.url)
os.chdir(cdir) os.chdir(cdir)
# data = getStudent("2022rkhondak")
# s = Student(data) #data = getStudent("2022rkhondak", "PWD")
#s = Student(data, "PWD")
# s.viewClass("APLit_eharris1") # s.viewClass("APLit_eharris1")
# #s.addClass("APLit_eharris1") # #s.addClass("APLit_eharris1")
# # #s.update() # # #s.update()
@ -379,6 +439,7 @@ class Student:
def main(): def main():
pass pass
if __name__ == "__main__": if __name__ == "__main__":
# stuff only to run when not called via 'import' here # stuff only to run when not called via 'import' here
main() main()

View File

@ -8,7 +8,9 @@ import shutil
import time import time
import pyperclip import pyperclip
from distutils.dir_util import copy_tree from distutils.dir_util import copy_tree
from datetime import datetime from datetime import datetime
# from django.conf import settings # from django.conf import settings
# import django # import django
@ -21,306 +23,425 @@ from datetime import datetime
# django.setup() # django.setup()
# from ..Website.api.models import * # from ..Website.api.models import *
#git clone student directory ==> <student-id>/classes/assignments # git clone student directory ==> <student-id>/classes/assignments
#get teacher info from api # get teacher info from api
def getTeacher(ion_user): def getTeacher(ion_user, password):
URL = "http://127.0.0.1:8000/api/teachers/" + ion_user + "/" """
r = requests.get(url = URL, auth=('raffukhondaker','hackgroup1')) Gets information about a teacher from the api
if(r.status_code == 200): :param ion_user: a teacher
data = r.json() :param password: the teacher's password
return data :return: teacher information or error
elif(r.status_code == 404): """
return None URL = "http://127.0.0.1:8000/api/teachers/" + ion_user + "/"
print("Make new account!") r = requests.get(url=URL, auth=(ion_user,password))
elif(r.status_code == 403): print(r.json())
return None if r.status_code == 200:
print("Invalid username/password") data = r.json()
else: return data
return None elif r.status_code == 404:
print(r.status_code) return None
print("Make new account!")
elif r.status_code == 403:
return None
print("Invalid username/password")
else:
return None
print(r.status_code)
def getDB(url): #makes a GET request to given url, returns dict
r = requests.get(url = url, auth=('raffukhondaker','hackgroup1')) def getDB(user, pwd, url):
"""
Sends a GET request to url
:param user: username
:param pwd: password
:param url: URL for request
:return: json request response
"""
r = requests.get(url=url, auth=(user, pwd))
print("GET:" + str(r.status_code)) print("GET:" + str(r.status_code))
return(r.json()) return(r.json())
def patchDB(data, url):
r = requests.patch(url = url, data=data, auth=('raffukhondaker','hackgroup1')) #makes a PATCH (updates instance) request to given url, returns dict
def patchDB(user, pwd, data, url):
"""
Sends a PATCH request to url
:param user: username
:param pwd: password
:param url: URL for request
:param data: data to request
:return: json request response
"""
r = requests.patch(url=url, data=data, auth=(user, pwd))
print("PATCH:" + str(r.status_code)) print("PATCH:" + str(r.status_code))
return(r.json()) return r.json()
def postDB(data, url):
r = requests.post(url = url, data=data, auth=('raffukhondaker','hackgroup1')) #makes a POST (makes new instance) request to given url, returns dict
def postDB(user, pwd, data, url):
"""
Sends a POST request to url
:param user: username
:param pwd: password
:param url: URL for request
:param data: data to request
:return: json request response
"""
r = requests.post(url=url, data=data, auth=(user, pwd))
print("POST:" + str(r.status_code)) print("POST:" + str(r.status_code))
return(r.json()) return r.json()
def putDB(data, url):
r = requests.put(url = url, data=data, auth=('raffukhondaker','hackgroup1')) #makes a PUT (overwrites instance) request to given url, returns dict
def putDB(user, pwd, data, url):
"""
Sends a PUT request to url
:param user: username
:param pwd: password
:param url: URL for request
:param data: data to request
:return: json request response
"""
r = requests.put(url=url, data=data, auth=(user, pwd))
print("PUT:" + str(r.status_code)) print("PUT:" + str(r.status_code))
return(r.json()) return r.json()
def delDB(url):
r = requests.delete(url = url, auth=('raffukhondaker','hackgroup1')) #makes a DELETE (delete instance) request to given url, returns dict
def delDB(user, pwd, url):
"""
Sends a DELETE request to url
:param user: username
:param pwd: password
:param url: URL for request
:return: json request response
"""
r = requests.delete(url=url, auth=(user, pwd))
print("DELETE:" + str(r.status_code)) print("DELETE:" + str(r.status_code))
return None return None
def command(command): def command(command):
"""
Runs a shell command
:param command: shell command
"""
ar = [] ar = []
command = command.split(" ") command = command.split(" ")
for c in command: for c in command:
ar.append(c) ar.append(c)
process = subprocess.Popen(ar, stdout=subprocess.PIPE,stderr=subprocess.PIPE) process = subprocess.Popen(ar, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p=process.poll() p = process.poll()
output = process.communicate()[1] output = process.communicate()[1]
print(output.decode('utf-8')) print(output.decode('utf-8'))
#################################################################################################################################### ####################################################################################################################################
#public methods: deleteClass, makeClass, update # public methods: deleteClass, makeClass, update
class Teacher: class Teacher:
def __init__(self, data): def __init__(self, data, password):
# teacher info already stored in API # teacher info already stored in API
# intitialze fields after GET request # intitialze fields after GET request
self.git=data['git'] """
self.username=data['ion_user'] Initializes a Teacher with the data from the api
self.url= "http://127.0.0.1:8000/api/teachers/" + self.username + "/" :param data: api data
"""
self.git = data['git']
self.username = data['ion_user']
self.url = "http://127.0.0.1:8000/api/teachers/" + self.username + "/"
self.id = data['user'] self.id = data['user']
#classes in id form (Example: 4,5) self.password = password
# classes in id form (Example: 4,5)
#array
self.classes=data['classes'] # array
if(os.path.isdir(self.username + "/Students")): self.classes = data['classes']
print("Synced to " + self.username) if os.path.isdir(self.username + "/Students"):
print("Synced to " + self.username)
existing_classes = os.listdir(self.username)
for c in self.classes:
if not c in str(existing_classes):
os.mkdir(self.username + "/" + c)
print("Updated: " + c)
command("touch " + self.username + "/" + c + "/README.md")
os.makedirs(self.username + "/Students/" + c)
else: else:
os.makedirs(self.username + "/Students") os.makedirs(self.username + "/Students")
#2020-05-11 12:25:00 # 2020-05-11 12:25:00
# class name format: <course-name>_<ion_user>
#class name format: <course-name>_<ion_user> # turn existing directory into class, Pre-condition: directory exists
# relative path to class: 2022rkhondak/Math4
#turn existing directory into class, Pre-condition: directory exists def checkClass(self, path):
#relative path to class: 2022rkhondak/Math4 """
def checkClass(self,path): Checks if a directory is valid for creating a class
:param path: path to the new class directory
"""
cname = path.split("/") cname = path.split("/")
cname = cname[len(cname)-1] cname = cname[len(cname) - 1]
if(os.path.isfile(path)): if os.path.isfile(path):
print(path + " must be in a Class directory.") print(path + " must be in a Class directory.")
return False return False
if(("_" + self.username) in cname) == False: if not (("_" + self.username) in cname):
print("Incorrect class name: Must be in the format: " + self.username+ "/<course-name>_<ion_user>, not " + path) print(
"Incorrect class name: Must be in the format: " + self.username + "/<course-name>_<ion_user>, not " + path)
return False return False
dirs = os.listdir(path) dirs = os.listdir(path)
#checks if there is a file (not within Assignments) in class, need at least 1 # checks if there is a file (not within Assignments) in class, need at least 1
deffile = False deffile = False
#checks if there is a file in an Assignment, need at least 1 (default True in case no assignments) # checks if there is a file in an Assignment, need at least 1 (default True in case no assignments)
as_file = True as_file = True
as_bad = "" as_bad = ""
for d in dirs: for d in dirs:
if(os.path.isfile(d)): if os.path.isfile(d):
deffile=True deffile = True
else: else:
#checks if there is a file in an Assignment, need at least 1 # checks if there is a file in an Assignment, need at least 1
as_file = False as_file = False
asdir = os.listdir(path + "/" + d) asdir = os.listdir(path + "/" + d)
for a in asdir: for a in asdir:
if(os.path.isfile(path + "/" + d + "/" +a)): if os.path.isfile(path + "/" + d + "/" + a):
as_file=True as_file = True
if(as_file==False): if not as_file:
as_bad = d as_bad = d
break break
if(as_file==False): if not as_file:
print("Assignment '" + as_bad + "' does not have a default file!") print("Assignment '" + as_bad + "' does not have a default file!")
return False return False
if(deffile==False): if not deffile:
print("Need a default file in the " + path + " Directory!") print("Need a default file in the " + path + " Directory!")
return False return False
return True return True
def checkInDB(self, path): def checkInDB(self, path):
n = path.split("/") """
n = n[len(n)-1] Checks if "path" is in the database
:param path: path to directory
"""
n = path.split("/")
n = n[len(n) - 1]
for c in self.classes: for c in self.classes:
if(n == c['name']): if n == c['name']:
return True return True
return False return False
#make class from existing directory, add to git and api # make class from existing directory, add to git and api
def addClass(self, path): def addClass(self, path):
"""
Creates a class from an existing directory, adding it to the proper git repository and the api
:param path:
"""
cname = path.split("/") cname = path.split("/")
cname = cname[len(cname)-1] cname = cname[len(cname) - 1]
for c in self.classes: for c in self.classes:
if c == cname: if c == cname:
print(cname + " already exists.") print(cname + " already exists.")
return return
if (self.checkClass(path)): if self.checkClass(path):
cpath = self.username + "/" + cname cpath = self.username + "/" + cname
subject = cname.split("_")[0]
period = int(input("Enter period: "))
while(not (type(period) is int and period >= 0)):
print("Incorrect format")
period = int(input("Enter period: "))
data = { data = {
"name": cname, "name": cname,
"repo": "", "repo": "",
"path": cpath, "path": cpath,
"subject": subject,
"period":period,
"teacher": self.username, "teacher": self.username,
"owner":self.id "owner": self.id
} }
#make class instance in db # make class instance in db
postDB(data, 'http://127.0.0.1:8000/api/classes/') postDB(self.username, self.password, data, 'http://127.0.0.1:8000/api/classes/')
time.sleep(1)
self.classes.append(cname) self.classes.append(cname)
#add to instance # add to instance
#upate self.classes # update self.classes
data = { data = {
'classes':self.classes 'classes': self.classes
} }
print(self.username) print(self.classes)
print(patchDB(data, 'http://127.0.0.1:8000/api/teachers/' + self.username + "/")) print(patchDB(self.username, self.password, data, 'http://127.0.0.1:8000/api/teachers/' + self.username + "/"))
#make a new class from scratch # make a new class from scratch
#subject: string, assignments: list # subject: string, assignments: list
#class name must be: <subject>_<ion_user> # class name must be: <subject>_<ion_user>
def makeClass(self, cname): def makeClass(self, cname):
#check if class exists """
Makes a class with its own new directory
:param cname: name of class
"""
# check if class exists
path = self.username + "/" + cname path = self.username + "/" + cname
isclass = False isclass = False
acourses = getDB("http://127.0.0.1:8000/api/classes/")['results'] acourses = getDB(self.username, self.password, "http://127.0.0.1:8000/api/classes/")['results']
for c in acourses: for c in acourses:
if c['name'] == cname: if c['name'] == cname:
isclass=True isclass = True
break break
if(os.path.exists(path) or isclass): if os.path.exists(path) or isclass:
print("Class already exists: " + cname) print("Class already exists: " + cname)
if(isclass): if isclass:
print("Class already exists in Database") print("Class already exists in Database")
return return
else: else:
if((("_" + self.username) in cname) == False): if not (("_" + self.username) in cname):
print("class name must be: "+ cname + "_" + self.username) print("class name must be: " + cname + "_" + self.username)
return return
cdir = os.getcwd() cdir = os.getcwd()
os.mkdir(path) os.mkdir(path)
f=open(path + "/README.md", "w") f = open(path + "/README.md", "w")
f.close() f.close()
#push to remote repo os.makedirs(self.username + "/Students/" + cname)
# push to remote repo
# os.chdir(path) # os.chdir(path)
# for a in assignments: # for a in assignments:
# os.mkdir(a) # os.mkdir(a)
# f=open(a + "/instructions.txt", "w") # f=open(a + "/instructions.txt", "w")
# f.close() # f.close()
# os.chdir(cdir) # os.chdir(cdir)
self.addClass(path) self.addClass(path)
def deleteClass(self, path): def deleteClass(self, path):
if(os.path.exists(path) == False): """
Deletes an existing class
:param path: class directory path
"""
if not os.path.exists(path):
print(path + " does not exist locally.") print(path + " does not exist locally.")
resp = input("Do you want to delete " + path + " from the SkoolOS system? (y/N) ") resp = input("Do you want to delete " + path + " from the SkoolOS system? (y/N) ")
if(resp != 'y'): if resp != 'y':
return return
cname = path.split("/") cname = path.split("/")
cname = cname[len(cname)-1] cname = cname[len(cname) - 1]
repo = '' repo = ''
print("DELETE: " + self.classes[i]['name']) print("DELETE: " + self.classes[i]['name'])
for i in range(len(self.classes)): for i in range(len(self.classes)):
c = self.classes[i] c = self.classes[i]
if(c == cname): if c == cname:
del self.classes[i] del self.classes[i]
# data={ # data={
# 'classes':self.classes, # 'classes':self.classes,
# } # }
# print(patchDB(data, self.url)) # print(patchDB(data, self.url))
delDB("http://127.0.0.1:8000/api/classes/" + cname + "/") delDB(self.username, self.password, "http://127.0.0.1:8000/api/classes/" + cname + "/")
break break
#remove locally # remove locally
try: try:
shutil.rmtree(path) shutil.rmtree(path)
except: except:
pass pass
#remove from student directories
# remove from student directories
def isStudent(self, student): def isStudent(self, student):
r = requests.get(url = "http://127.0.0.1:8000/api/students/" + student + "/", auth=('raffukhondaker','hackgroup1')) """
if(r.status_code != 200): Checks if the student exists
:param student: a student
:return: True if student exists, False otherwise
"""
r = requests.get(url="http://127.0.0.1:8000/api/students/" + student + "/",
auth=(self.username, self.password))
if r.status_code != 200:
return False return False
return True return True
def reqStudent(self, sname, cname): def reqStudent(self, sname, cname):
if(self.isStudent(sname) == False): """
Request student informatiion from the api
:param sname: student's name
:param cname: class name
:return: True if successful
"""
if not self.isStudent(sname):
print(sname + " does not exist.") print(sname + " does not exist.")
return False return False
course = getDB("http://127.0.0.1:8000/api/classes/" + cname) course = getDB(self.username, self.password, "http://127.0.0.1:8000/api/classes/" + cname)
if(sname in str(course['unconfirmed'])): if sname in str(course['unconfirmed']):
print (sname + " already requested.") print(sname + " already requested.")
return True return True
if(sname in str(course['confirmed'])): if sname in str(course['confirmed']):
print (sname + " alredy enrolled.") print(sname + " already enrolled.")
return False return False
student = getDB("http://127.0.0.1:8000/api/students/" + sname) student = getDB(self.username, self.password, "http://127.0.0.1:8000/api/students/" + sname)
try: try:
if(student['added_to']==""): if student['added_to'] == "":
student['added_to']=course['name'] student['added_to'] = course['name']
else: else:
student['added_to']=student['added_to']+ "," + course['name'] student['added_to'] = student['added_to'] + "," + course['name']
except: except:
print(sname + " does not exist.") print(sname + " does not exist.")
return False return False
print(student['added_to']) print(student['added_to'])
data={ data = {
'added_to':student['added_to'], 'added_to': student['added_to'],
} }
student = patchDB(data, "http://localhost:8000/api/students/" + student['ion_user'] + "/") student = patchDB(self.username, self.password, data, "http://localhost:8000/api/students/" + student['ion_user'] + "/")
student = getDB( "http://localhost:8000/api/students/" + (sname)+ "/") student = getDB(self.username, self.password, "http://localhost:8000/api/students/" + sname + "/")
if(course['unconfirmed']==[]): if not course['unconfirmed']:
course['unconfirmed']=student['ion_user'] course['unconfirmed'] = student['ion_user']
else: else:
course['unconfirmed']=course['unconfirmed'].append(student['ion_user']) course['unconfirmed'] = course['unconfirmed'].append(student['ion_user'])
cinfo = { cinfo = {
"unconfirmed": course['unconfirmed'] "unconfirmed": course['unconfirmed']
} }
print(cinfo) print(cinfo)
patchDB(cinfo, "http://localhost:8000/api/classes/" + course['name'] + "/") patchDB(self.username, self.password, cinfo, "http://localhost:8000/api/classes/" + course['name'] + "/")
return True return True
#Student should have confirmed on their endd, but class had not been updated yet # Student should have confirmed on their endd, but class had not been updated yet
#git clone confirmed student repo, copy files into repo and push branch # git clone confirmed student repo, copy files into repo and push branch
def addStudent(self, sname, cname): def addStudent(self, sname, cname):
if(self.isStudent(sname) == False): """
Adds a student to a class
:param sname: student name
:param cname: class name
:return:
"""
if not self.isStudent(sname):
print(sname + " does not exist.") print(sname + " does not exist.")
return False return False
student = getDB("http://127.0.0.1:8000/api/students/" + sname) student = getDB(self.username, self.password, "http://127.0.0.1:8000/api/students/" + sname)
course = getDB("http://127.0.0.1:8000/api/classes/" + cname) course = getDB(self.username, self.password, "http://127.0.0.1:8000/api/classes/" + cname)
if(os.path.exists(self.username + "/Students/" + cname + "/" + student['ion_user']) or (student['ion_user'] in course['confirmed']) == True): if (os.path.exists(self.username + "/Students/" + cname + "/" + student['ion_user']) or (
student['ion_user'] in course['confirmed']) == True):
print(student['ion_user'] + " already added to class") print(student['ion_user'] + " already added to class")
return True return True
if((cname in student['added_to']) == True or (cname in student['classes']) == False): if (cname in student['added_to']) or not (cname in student['classes']):
print(student['ion_user']+ " has not confirmed class yet") print(student['ion_user'] + " has not confirmed class yet")
return False return False
if((student['ion_user'] in course['unconfirmed']) == False): if not (student['ion_user'] in course['unconfirmed']):
print(course['unconfirmed']) print(course['unconfirmed'])
print(student['ion_user']+" has not been requested to join yet.") print(student['ion_user'] + " has not been requested to join yet.")
return False return False
#git clone and make student/class directories # git clone and make student/class directories
cdir = os.getcwd() cdir = os.getcwd()
cpath = self.username + "/" + cname cpath = self.username + "/" + cname
path = self.username + "/Students/" + cname path = self.username + "/Students/" + cname
spath = self.username + "/Students/" + cname + "/" + student['ion_user'] spath = self.username + "/Students/" + cname + "/" + student['ion_user']
if(os.path.isdir(path) == False): if not os.path.isdir(path):
os.makedirs(path) os.makedirs(path)
if(os.path.isdir(spath) == False): if not os.path.isdir(spath):
os.chdir(path) os.chdir(path)
command("git clone " + student['repo']) command("git clone " + student['repo'])
os.chdir(cdir) os.chdir(cdir)
#push to git # push to git
os.chdir(spath) os.chdir(spath)
command('git checkout ' + cname) command('git checkout ' + cname)
command('git pull origin ' + cname) command('git pull origin ' + cname)
@ -332,15 +453,15 @@ class Teacher:
command('git push -u origin ' + cname) command('git push -u origin ' + cname)
os.chdir(cdir) os.chdir(cdir)
if(course['confirmed']==[]): if not course['confirmed']:
course['confirmed']=student['ion_user'] course['confirmed'] = student['ion_user']
else: else:
course['confirmed'].append(student['ion_user']) course['confirmed'].append(student['ion_user'])
#only 1 pereson on confirmeed # only 1 pereson on confirmeed
if(len(course['unconfirmed']) == 1): if len(course['unconfirmed']) == 1:
course['unconfirmed']=[] course['unconfirmed'] = []
#mutiple # mutiple
else: else:
course['unconfirmed'].remove(student['ion_user']) course['unconfirmed'].remove(student['ion_user'])
@ -348,37 +469,50 @@ class Teacher:
"confirmed": course["confirmed"], "confirmed": course["confirmed"],
"unconfirmed": course['unconfirmed'] "unconfirmed": course['unconfirmed']
} }
print(putDB(course, "http://localhost:8000/api/classes/" + course['name'] + "/")) print(putDB(self.username, self.password, course, "http://localhost:8000/api/classes/" + course['name'] + "/"))
return True return True
#goes through list of studennts, tries to add, then request, return unconfirmed students # goes through list of studennts, tries to add, then request, return unconfirmed students
def reqAddStudentList(self, array, cname): def reqAddStudentList(self, array, cname):
"""
Runs addStudent() on all students in array
:param array: an array of students
:param cname: class name
:return: students that have not confirmed the request
"""
unconf = [] unconf = []
for i in range(len(array)): for i in range(len(array)):
a = array[i] a = array[i]
if(self.addStudent(a, cname) == False): if not self.addStudent(a, cname):
self.reqStudent(a, cname) self.reqStudent(a, cname)
unconf.append(a) unconf.append(a)
return unconf return unconf
#add local path to student directory, make new instance in api # add local path to student directory, make new instance in api
def addAssignment(self, path, course, due): def addAssignment(self, path, course, due):
"""
Creates an assignment for "course" that is due on "due"
:param path: directory of assignment
:param course: course name
:param due: due date
:return: False if unsuccessful
"""
parts = path.split("/") parts = path.split("/")
aname = parts[len(parts)-1] aname = parts[len(parts) - 1]
oname = aname + "_" + course oname = aname + "_" + course
if(os.path.isdir(path) == 0 or len(parts) < 3) or aname in str(self.classes): if (os.path.isdir(path) == 0 or len(parts) < 3) or aname in str(self.classes):
print("Not valid path.") print("Not valid path.")
return False return False
if((parts[1] in str(self.classes)) == False): if not (parts[1] in str(self.classes)):
print("Not in valid class directory") print("Not in valid class directory")
return False return False
#parts of assignment name (Essay1, APLit) # parts of assignment name (Essay1, APLit)
# if((course in aname) == False): # if((course in aname) == False):
# print("Assignment named incorrectly; could be "+ aname + "_" + course) # print("Assignment named incorrectly; could be "+ aname + "_" + course)
# return False # return False
ar = [x[2] for x in os.walk(path)] ar = [x[2] for x in os.walk(path)]
print(ar) print(ar)
for folder in ar: for folder in ar:
if len(folder) == 0: if len(folder) == 0:
@ -393,25 +527,25 @@ class Teacher:
except: except:
print("Due-date format is incorrect") print("Due-date format is incorrect")
return False return False
course = getDB("http://127.0.0.1:8000/api/classes/" + course) course = getDB(self.username, self.password, "http://127.0.0.1:8000/api/classes/" + course)
if(aname in str(course['assignments'])): if aname in str(course['assignments']):
print("Assignment name already taken.") print("Assignment name already taken.")
return False return False
print(course['assignments']) print(course['assignments'])
print(aname) print(aname)
#################### FINISH VERIFYING #################### FINISH VERIFYING
if(os.path.exists(os.getcwd() + "/" + self.username + "/Students/" + course['name']) == False): if not os.path.exists(os.getcwd() + "/" + self.username + "/Students/" + course['name']):
print("No students in this class yet") print("No students in this class yet")
return True return True
slist = os.listdir(os.getcwd() + "/" + self.username + "/Students/" + course['name']) slist = os.listdir(os.getcwd() + "/" + self.username + "/Students/" + course['name'])
cdir = os.getcwd() cdir = os.getcwd()
for st in slist: for st in slist:
if st in str(course['confirmed']): if st in str(course['confirmed']):
spath = os.path.join(os.getcwd() + "/" + self.username + "/Students/" + course['name'], st) spath = os.path.join(os.getcwd() + "/" + self.username + "/Students/" + course['name'], st)
if(os.path.exists(spath + "/" + aname) == False): if not os.path.exists(spath + "/" + aname):
os.mkdir(spath + "/" + aname) os.mkdir(spath + "/" + aname)
print(st) print(st)
print(copy_tree(path, spath + "/" + aname)) print(copy_tree(path, spath + "/" + aname))
os.chdir(spath) os.chdir(spath)
@ -423,71 +557,72 @@ class Teacher:
os.chdir(cdir) os.chdir(cdir)
else: else:
print(st + " already has assignment") print(st + " already has assignment")
#check if assignment already exists # check if assignment already exists
r = requests.get(url = 'http://127.0.0.1:8000/api/assignments/' + aname, auth=('raffukhondaker','hackgroup1')) r = requests.get(url='http://127.0.0.1:8000/api/assignments/' + aname, auth=(self.username, self.password))
if(r.status_code != 200): if r.status_code != 200:
ass = { ass = {
'name': oname, 'name': oname,
'path':path, 'path': path,
'classes':course['name'], 'classes': course['name'],
'teacher':self.username, 'teacher': self.username,
'due_date':due 'due_date': due,
'owner':self.id
} }
postDB(ass, 'http://127.0.0.1:8000/api/assignments/') postDB(self.username, self.password, ass, 'http://127.0.0.1:8000/api/assignments/')
course['assignments'].append(oname) course['assignments'].append(oname)
cinfo = { cinfo = {
"assignments": course['assignments'], "assignments": course['assignments'],
} }
print(patchDB(cinfo, "http://127.0.0.1:8000/api/classes/" + course['name'] + "/")) print(patchDB(self.username, self.password, cinfo, "http://127.0.0.1:8000/api/classes/" + course['name'] + "/"))
return True return True
else: else:
print("Assignment already addedd") print("Assignment already addedd")
return True return True
#try to avoid # try to avoid
#copy modified assignments to student directories # copy modified assignments to student directories
def updateAssignment(self, path, course, due): def updateAssignment(self, path, course, due):
parts = path.split("/") parts = path.split("/")
aname = parts[len(parts)-1] aname = parts[len(parts) - 1]
oname=aname + "_" + course oname = aname + "_" + course
if(os.path.isdir(path) == False): if not os.path.isdir(path):
print(path + " is not an assignment.") print(path + " is not an assignment.")
return return
try: try:
if(due != None or due == ""): if due != None or due == "":
datetime.strptime(due, '%Y-%m-%d %H:%M:%S.%f') datetime.strptime(due, '%Y-%m-%d %H:%M:%S.%f')
d = { d = {
'due_date':due, 'due_date': due,
} }
print(patchDB(d, 'http://localhost:8000/api/assignments/' + oname + "/")) print(patchDB(self.username, self.password, d, 'http://localhost:8000/api/assignments/' + oname + "/"))
print("Due-date changed " + due) print("Due-date changed " + due)
except: except:
print("Due-date is the same") print("Due-date is the same")
input() input()
course = getDB("http://127.0.0.1:8000/api/classes/" + course) course = getDB(self.username, self.password, "http://127.0.0.1:8000/api/classes/" + course)
slist = os.listdir(os.getcwd() + "/" + self.username + "/Students/" + course['name']) slist = os.listdir(os.getcwd() + "/" + self.username + "/Students/" + course['name'])
cdir = os.getcwd() cdir = os.getcwd()
for st in slist: for st in slist:
if st in course['confirmed']: if st in course['confirmed']:
spath = os.path.join(os.getcwd() + "/" + self.username + "/Students/" + course['name'], st) spath = os.path.join(os.getcwd() + "/" + self.username + "/Students/" + course['name'], st)
print(st) print(st)
print(copy_tree(path, spath + "/" + aname)) print(copy_tree(path, spath + "/" + aname))
os.chdir(spath) os.chdir(spath)
#command('git checkout ' + course['name']) # command('git checkout ' + course['name'])
command('git add .') command('git add .')
command('git commit -m Hello') command('git commit -m Hello')
command('git pull origin ' + course['name']) command('git pull origin ' + course['name'])
command('git push -u origin ' + course['name']) command('git push -u origin ' + course['name'])
os.chdir(cdir) os.chdir(cdir)
#pull student's work, no modifications # pull student's work, no modifications
def getStudents(self, course): def getStudents(self, course):
if((course in self.sclass) == False): if not (course in str(self.classes)):
print(course + " not a class.") print(course + " not a class.")
return return
path = self.username + "/Students/" + course path = self.username + "/Students/" + course
slist = os.listdir(path) slist = os.listdir(path)
cdir = os.getcwd() cdir = os.getcwd()
for st in slist: for st in slist:
@ -497,9 +632,9 @@ class Teacher:
os.chdir(cdir) os.chdir(cdir)
def getCommits(self, student, course, commits): def getCommits(self, student, course, commits):
course = getDB("http://127.0.0.1:8000/api/classes/" + course) course = getDB(self.username, self.password, "http://127.0.0.1:8000/api/classes/" + course)
try: try:
if((student in course['confirmed']) == False): if not (student in course['confirmed']):
print("Student not in class") print("Student not in class")
return return
except: except:
@ -508,19 +643,20 @@ class Teacher:
cdir = os.getcwd() cdir = os.getcwd()
os.chdir(self.username + "/Students/" + course['name'] + "/" + student) os.chdir(self.username + "/Students/" + course['name'] + "/" + student)
process = subprocess.Popen(['git', 'log', '-' + str(commits), course['name']], stdout=subprocess.PIPE,stderr=subprocess.PIPE) process = subprocess.Popen(['git', 'log', '-' + str(commits), course['name']], stdout=subprocess.PIPE,
p=process.poll() stderr=subprocess.PIPE)
p = process.poll()
output = process.communicate()[0].decode('utf-8').split('\n\n') output = process.communicate()[0].decode('utf-8').split('\n\n')
months = ['Jan', 'Feb', 'Mar', "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"] months = ['Jan', 'Feb', 'Mar', "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"]
fout = [] fout = []
for i in range(len(output)): for i in range(len(output)):
if("Date" in output[i]): if "Date" in output[i]:
c = output[i].split("\n") c = output[i].split("\n")
for k in range(len(c)): for k in range(len(c)):
temp = [] temp = []
if('commit' in c[k]): if 'commit' in c[k]:
c[k] = c[k].replace('commit', '').strip() c[k] = c[k].replace('commit', '').strip()
elif('Date:' in c[k]): elif 'Date:' in c[k]:
c[k] = c[k].replace('Date:', '').strip() c[k] = c[k].replace('Date:', '').strip()
date = c[2].split(" ") date = c[2].split(" ")
times = date[3].split(":") times = date[3].split(":")
@ -529,58 +665,66 @@ class Teacher:
if date[1] == months[m]: if date[1] == months[m]:
mon = m mon = m
d1 = datetime(int(date[4]), mon, int(date[2]), int(times[0]), int(times[1])) d1 = datetime(int(date[4]), mon, int(date[2]), int(times[0]), int(times[1]))
#datetime1 = datetime.strptime('07/11/2019 02:45PM', '%m/%d/%Y %I:%M%p') # datetime1 = datetime.strptime('07/11/2019 02:45PM', '%m/%d/%Y %I:%M%p')
fout.append([c[0],d1]) fout.append([c[0], d1])
#output[i] = [c[0], d1] # output[i] = [c[0], d1]
#print(output[i]) # print(output[i])
print(fout) print(fout)
os.chdir(cdir) os.chdir(cdir)
return fout return fout
def getChanges(self, student, course, commits): def getChanges(self, student, course, commits):
course = getDB("http://127.0.0.1:8000/api/classes/" + course + "/") """
Checks for new submissions by a student
:param student: the student
:param course: the course
:param commits: commits the CLI has made for the assignment
"""
course = getDB(self.username, self.password, "http://127.0.0.1:8000/api/classes/" + course + "/")
ar = self.getCommits(student, course['name'], commits) ar = self.getCommits(student, course['name'], commits)
commit = ar[len(ar)-1][0] commit = ar[len(ar) - 1][0]
start = "" start = ""
print("END:" + commit) print("END:" + commit)
print("START: " + start) print("START: " + start)
cdir = os.getcwd() cdir = os.getcwd()
os.chdir(self.username + "/Students/" + course['name'] + "/" + student) os.chdir(self.username + "/Students/" + course['name'] + "/" + student)
process = subprocess.Popen(['git', 'diff', commit, '--name-status'], stdout=subprocess.PIPE,stderr=subprocess.PIPE) process = subprocess.Popen(['git', 'diff', commit, '--name-status'], stdout=subprocess.PIPE,
p=process.poll() stderr=subprocess.PIPE)
p = process.poll()
output = process.communicate()[0].decode('utf-8') output = process.communicate()[0].decode('utf-8')
print(output) print(output)
os.chdir(cdir) os.chdir(cdir)
''' '''
assignment = { assignment = {
'name': English11_eharris1, 'name': English11_eharris1,
'due_date': 2020-06-11 16:58:33.383124 'due_date': 2020-06-11 16:58:33.383124
} }
''' '''
#check if assignment changed after due date # check if assignment changed after due date
def afterSubmit(self, course, assignment, student): def afterSubmit(self, course, assignment, student):
assignment = getDB("http://127.0.0.1:8000/api/assignments/" + assignment) assignment = getDB(self.username, self.password, "http://127.0.0.1:8000/api/assignments/" + assignment)
# assignment = { # assignment = {
# 'name': assignment, # 'name': assignment,
# 'due_date': "2020-04-11 16:58:33.383124", # 'due_date': "2020-04-11 16:58:33.383124",
# 'classes':course # 'classes':course
# } # }
log = self.getCommits(student, course, 30) log = self.getCommits(student, course, 30)
assignment['due_date'] = datetime.strptime(assignment['due_date'], '%Y-%m-%d %H:%M:%S.%f') assignment['due_date'] = datetime.strptime(assignment['due_date'], '%Y-%m-%dT%H:%M:%S.%fZ')
late = False late = False
cdir = os.getcwd() cdir = os.getcwd()
os.chdir(self.username + "/Students/" + course + "/" + student) os.chdir(self.username + "/Students/" + course + "/" + student)
for l in log: for l in log:
process = subprocess.Popen(['git', 'show', l[0]], stdout=subprocess.PIPE,stderr=subprocess.PIPE) process = subprocess.Popen(['git', 'show', l[0]], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p=process.poll() p = process.poll()
output = process.communicate()[0].decode('utf-8') output = process.communicate()[0].decode('utf-8')
if(assignment['name'] in output): if assignment['name'] in output:
print(l[1]) print(l[1])
print(assignment['due_date']) print(assignment['due_date'])
print("--------------") print("--------------")
if(l[1] > assignment['due_date']): if l[1] > assignment['due_date']:
print("LATE") print("LATE")
os.chdir(cdir) os.chdir(cdir)
return True return True
@ -589,17 +733,22 @@ class Teacher:
return False return False
def comment(self): def comment(self):
"""
The ultimate form of laughter
:return: pure joy
"""
print("heheheh") print("heheheh")
# data = getTeacher("eharris1") # data = getTeacher("eharris1","PWD")
# t = Teacher(data) # print(data)
#t.makeClass("APLit_eharris1") #t = Teacher(data, "PWD")
# t.makeClass("APLit_eharris1")
# t.updateAssignment("eharris1/APLit_eharris1/BookReport", "APLit_eharris1", '2020-08-11 16:58:33.383124') # t.updateAssignment("eharris1/APLit_eharris1/BookReport", "APLit_eharris1", '2020-08-11 16:58:33.383124')
#ar = ['2022rkhondak','2022inafi','2023rumareti'] # ar = ['2022rkhondak','2022inafi','2023rumareti']
#extra = t.reqAddStudentList(ar, "APLit_eharris1") # extra = t.reqAddStudentList(ar, "APLit_eharris1")
#print(extra) # print(extra)
#t.addStudent('2022rkhondak', 'APLit_eharris1') # t.addStudent('2022rkhondak', 'APLit_eharris1')
# t.getChanges('2022rkhondak','APLit_eharris1', 10) # t.getChanges('2022rkhondak','APLit_eharris1', 10)
''' '''
@ -614,4 +763,3 @@ TO-DO
- check differences between commits - check differences between commits
- check if student changes file after submissionn deadline - check if student changes file after submissionn deadline
''' '''

View File

@ -8,6 +8,7 @@ class Student(models.Model):
user = models.OneToOneField(User, blank=True, on_delete=models.CASCADE) user = models.OneToOneField(User, blank=True, on_delete=models.CASCADE)
ion_user = models.CharField(max_length=100, primary_key=True) ion_user = models.CharField(max_length=100, primary_key=True)
grade = models.IntegerField(default=0, blank=True) grade = models.IntegerField(default=0, blank=True)
log = models.TextField(default="", blank=True)
git=models.CharField(default="", max_length=100, blank=True) git=models.CharField(default="", max_length=100, blank=True)
repo=models.URLField(default="", blank=True) repo=models.URLField(default="", blank=True)
classes=models.CharField(max_length=100, default="", blank=True) classes=models.CharField(max_length=100, default="", blank=True)
@ -18,31 +19,32 @@ class Student(models.Model):
super(Student, self).save(*args, **kwargs) super(Student, self).save(*args, **kwargs)
def __str__(self): def __str__(self):
return f"{self.user.username}'s Profile" return f"{self.user.first_name} {self.user.last_name} ({self.user.username})"
class Assignment(models.Model): class Assignment(models.Model):
owner = models.ForeignKey(User, null=True, blank=True, related_name='aowner', on_delete=models.CASCADE) owner = models.ForeignKey(User, null=True, blank=True, related_name='aowner', on_delete=models.CASCADE)
name=models.CharField(max_length=100, primary_key=True) name=models.CharField(max_length=100, primary_key=True)
due_date=models.DateTimeField() due_date=models.DateTimeField()
# files = models.ManyToManyField(DefFiles) # files = models.ManyToManyField(DefFiles)
files=models.CharField(max_length=100, default="", blank=True) files=models.CharField(max_length=100, default="", blank=True)
path=models.CharField(max_length=100) path=models.CharField(max_length=100, default="", blank=True)
classes=models.CharField(max_length=100) classes=models.CharField(max_length=100, default="", blank=True)
teacher=models.CharField(max_length=100) teacher=models.CharField(max_length=100, default="", blank=True)
def __str__(self): def __str__(self):
return '%s' % (self.name) return f'{self.name}'
class Class(models.Model): class Class(models.Model):
owner = models.ForeignKey(User, null=True, blank=True, related_name='cowner', on_delete=models.CASCADE) owner = models.ForeignKey(User, null=True, blank=True, related_name='cowner', on_delete=models.CASCADE)
teacher = models.CharField(max_length=100) teacher = models.CharField(max_length=100, blank=True)
subject = models.CharField(max_length=50, blank=True)
period = models.PositiveIntegerField(null=True, blank=True, default=0)
name = models.CharField(primary_key=True, max_length=100) name = models.CharField(primary_key=True, max_length=100)
id = models.CharField(max_length=8, blank=True, null=True) id = models.CharField(max_length=8, blank=True, null=True)
description = models.CharField(default="Class Description", max_length=500) description = models.CharField(default="Class Description", max_length=500, blank=True)
repo=models.URLField(default="", blank=True) repo=models.URLField(default="", blank=True)
path=models.CharField(max_length=100, default="") path=models.CharField(max_length=100, default="", blank=True)
assignments=models.ManyToManyField(Assignment, blank=True) assignments=models.ManyToManyField(Assignment, blank=True)
default_file=models.CharField(max_length=100, default="", blank=True) default_file=models.CharField(max_length=100, default="", blank=True)
confirmed=models.ManyToManyField(Student, blank=True, related_name='confirmed') confirmed=models.ManyToManyField(Student, blank=True, related_name='confirmed')
@ -60,7 +62,7 @@ class Class(models.Model):
return super(Class, self).save(*args, **kwargs) return super(Class, self).save(*args, **kwargs)
def __str__(self): def __str__(self):
return self.name return f"{self.name}"
class Teacher(models.Model): class Teacher(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE) user = models.OneToOneField(User, on_delete=models.CASCADE)
@ -69,7 +71,7 @@ class Teacher(models.Model):
ion_user=models.CharField(primary_key=True, max_length=100) ion_user=models.CharField(primary_key=True, max_length=100)
def __str__(self): def __str__(self):
return f"{self.user.username}'s Profile" return f"{self.user.first_name} {self.user.last_name} ({self.user.username})"
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
super(Teacher, self).save(*args, **kwargs) super(Teacher, self).save(*args, **kwargs)

View File

@ -34,7 +34,7 @@ class ClassSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Class model = Class
# fields = ['url','name', 'repo','path', "teacher",'assignments',"default_file", 'confirmed', 'unconfirmed','owner'] # fields = ['url','name', 'repo','path', "teacher",'assignments',"default_file", 'confirmed', 'unconfirmed','owner']
fields = ['name', 'repo','path','assignments',"teacher","default_file", 'confirmed', 'unconfirmed','owner'] fields = ['name', 'repo','path','subject','period','assignments',"teacher","default_file", 'confirmed', 'unconfirmed','owner']
class StudentSerializer(serializers.ModelSerializer): class StudentSerializer(serializers.ModelSerializer):
# Class = ClassSerializer(many=True, read_only=True,allow_null=True) # Class = ClassSerializer(many=True, read_only=True,allow_null=True)

View File

@ -1,6 +1,6 @@
from django import forms from django import forms
from django.contrib.auth.models import User from django.contrib.auth.models import User
from api.models import Student, Teacher from api.models import Student, Teacher, Class, Assignment
import re import re
class UserUpdateForm(forms.ModelForm): class UserUpdateForm(forms.ModelForm):
@ -26,3 +26,33 @@ class TeacherUpdateForm(forms.ModelForm):
class Meta: class Meta:
model = Teacher model = Teacher
fields = ['git'] fields = ['git']
class ClassCreationForm (forms.ModelForm):
subject = forms.CharField(max_length=50)
period = forms.IntegerField(min_value=0, max_value=9)
description = forms.CharField(widget=forms.Textarea)
unconfirmed = forms.ModelMultipleChoiceField(queryset=Student.objects.all(), label="Invite students")
def clean_period(self):
pd = self.cleaned_data['period']
if pd < 1 or pd > 9:
raise forms.ValidationError("Invalid period")
return pd;
def __init__(self, *args, **kwargs):
super(ClassCreationForm, self).__init__(*args, **kwargs)
self.fields['period'].widget.attrs['min'] = 0
# Only in case we build the form from an instance
# (otherwise, 'unconfirmed' list should be empty)
if kwargs.get('instance'):
# We get the 'initial' keyword argument or initialize it
# as a dict if it didn't exist.
initial = kwargs.setdefault('initial', {})
# The widget for a ModelMultipleChoiceField expects
# a list of primary key for the selected data.
initial['unconfirmed'] = [t.pk for t in kwargs['instance'].unconfirmed.all()]
class Meta:
model = Class
fields = ['subject', 'period', 'description', 'unconfirmed']

View File

@ -92,3 +92,13 @@ a.article-title:hover {
.account-heading { .account-heading {
font-size: 2.5rem; font-size: 2.5rem;
} }
.class-card {
text-decoration: none;
color: gray;
}
.class-card:hover {
text-decoration: none;
color: black;
}

View File

@ -34,6 +34,11 @@
<!-- Navbar Right Side --> <!-- Navbar Right Side -->
<div class="navbar-nav"> <div class="navbar-nav">
{% if user.is_authenticated %} {% if user.is_authenticated %}
{% if isTeacher %}
<a class="nav-item nav-link" href="{% url 'create-class' %}">Create Class</a>
{% else %}
{% endif %}
<a class="nav-item nav-link" href="{% url 'profile' %}">{{ user.username }}</a> <a class="nav-item nav-link" href="{% url 'profile' %}">{{ user.username }}</a>
<a class="nav-item nav-link" href="{% url 'logout' %}">Logout</a> <a class="nav-item nav-link" href="{% url 'logout' %}">Logout</a>
{% endif %} {% endif %}

View File

@ -11,6 +11,12 @@
<small class="text-muted">Due: {{ assignment.due_date|date:"F d, Y" }}</small> <small class="text-muted">Due: {{ assignment.due_date|date:"F d, Y" }}</small>
</div> </div>
</article> </article>
{% empty %}
{% if isTeacher %}
<p class="mr-2">Looks like you haven't made any assignments yet, hit the button in the top right to get started</p>
{% else %}
<p class="mr-2">Looks like there aren't any assignments at the moment, you got lucky this time!</p>
{% endif %}
{% endfor %} {% endfor %}
</div> </div>
@ -20,6 +26,8 @@
<ul> <ul>
{% for teacher in teachers %} {% for teacher in teachers %}
<li>{{ teacher.user.first_name }} {{ teacher.user.last_name }} ({{teacher.ion_user}})</li> <li>{{ teacher.user.first_name }} {{ teacher.user.last_name }} ({{teacher.ion_user}})</li>
{% empty %}
<li>No Teachers, weird...</li>
{% endfor %} {% endfor %}
</ul> </ul>
</div> </div>

View File

@ -0,0 +1,26 @@
{% extends "skoolos/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<legend class="border-bottom mb-4">Classes</legend>
<ul>
{% for class in classes %}
<li>{{ class.name }}</li>
{% empty %}
<li>Not teaching any classes</li>
{% endfor %}
</ul>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4"> Create a new class </legend>
{{ classForm|crispy }}
<!-- mmmm crispy yummm -->
<small class="text-secondary">Use ctrl to select multiple students</small>
</fieldset>
<div class="form-group">
<button type="submit" class="btn btn-outline-info">Create</button>
</div>
</form>
</div>
</div>
{% endblock content %}

View File

@ -3,13 +3,25 @@
<div class="content-section"> <div class="content-section">
{% for class in classes %} {% for class in classes %}
<div class="card-columns"> <div class="card-columns">
<a class="card" href="/class/{{ class.id }}" style="text-decoration: none;"> <a class="card class-card" href="/class/{{ class.id }}" style="">
<div class="card-body"> <div class="card-body">
<h5 class="card-title">{{ class.name }}</h5> <h5 class="card-title">{{ class.subject }}</h5>
{% if class.period != 0 %}
<small>Period: {{ class.period }}<br></small>
{% endif %}
{% if class.name %}
<small style="font-size:.75em"><i>{{ class.name }}</i></small>
{% endif %}
<p class="card-text">{{ class.description }}</p> <p class="card-text">{{ class.description }}</p>
</div> </div>
</a> </a>
</div> </div>
{% empty %}
{% if isTeacher %}
<p>Looks like you haven't created any classes yet, hit the button in the top right to get started.</p>
{% else %}
<p>Looks like you're not enrolled in any classes at the moment! Ask your teacher if you think this is wrong.</p>
{% endif %}
{% endfor %} {% endfor %}
</div> </div>
{% endblock content %} {% endblock content %}

View File

@ -5,6 +5,7 @@
<div class="media"> <div class="media">
<div class="media-body"> <div class="media-body">
<h2 class="account-heading">{{ user.username }}</h2> <h2 class="account-heading">{{ user.username }}</h2>
<p class="text-secondary">Student</p>
<large>{{ user.first_name }} {{ user.last_name }}</large> <large>{{ user.first_name }} {{ user.last_name }}</large>
<p class="text-secondary"> <p class="text-secondary">
{{ user.email }} {{ user.email }}
@ -16,6 +17,8 @@
<ul> <ul>
{% for class in classes %} {% for class in classes %}
<li>{{ class.name }}</li> <li>{{ class.name }}</li>
{% empty %}
<li>No classes</li>
{% endfor %} {% endfor %}
</ul> </ul>
<form method="post" enctype="multipart/form-data"> <form method="post" enctype="multipart/form-data">

View File

@ -5,6 +5,7 @@
<div class="media"> <div class="media">
<div class="media-body"> <div class="media-body">
<h2 class="account-heading">{{ user.username }}</h2> <h2 class="account-heading">{{ user.username }}</h2>
<p class="text-secondary">Teacher</p>
<large>{{ user.first_name }} {{ user.last_name }}</large> <large>{{ user.first_name }} {{ user.last_name }}</large>
<p class="text-secondary"> <p class="text-secondary">
{{ user.email }} {{ user.email }}
@ -16,6 +17,8 @@
<ul> <ul>
{% for class in classes %} {% for class in classes %}
<li>{{ class.name }}</li> <li>{{ class.name }}</li>
{% empty %}
<li>Not teaching any classes</li>
{% endfor %} {% endfor %}
</ul> </ul>
<form method="post" enctype="multipart/form-data"> <form method="post" enctype="multipart/form-data">

View File

@ -7,4 +7,5 @@ urlpatterns = [
path('', views.home, name='home'), path('', views.home, name='home'),
path('profile/', views.profile, name='profile'), path('profile/', views.profile, name='profile'),
path("class/<str:id>", views.classDetail, name="class"), path("class/<str:id>", views.classDetail, name="class"),
path("create-class/", views.createClass, name="create-class"),
] ]

View File

@ -5,7 +5,12 @@ from django.contrib import messages
from django.contrib.auth.models import User from django.contrib.auth.models import User
from .forms import UserUpdateForm, StudentUpdateForm, TeacherUpdateForm from .forms import (
UserUpdateForm,
StudentUpdateForm,
TeacherUpdateForm,
ClassCreationForm,
)
from api.models import Student, Teacher, Class, Assignment from api.models import Student, Teacher, Class, Assignment
@ -14,14 +19,14 @@ from api.models import Student, Teacher, Class, Assignment
@login_required() @login_required()
def home (request): def home (request):
try: try:
student = Student.objects.get(user=request.user) student = request.user.student
return render(request, "skoolos/home.html", {'classes': student.confirmed.all()}) return render(request, "skoolos/home.html", {'classes': student.confirmed.all(), 'isTeacher': False})
except Student.DoesNotExist: except Student.DoesNotExist:
pass pass
try: try:
teacher = Teacher.objects.get(user=request.user) teacher = request.user.teacher
return render(request, "skoolos/home.html", {'classes': teacher.classes.all()}) return render(request, "skoolos/home.html", {'classes': teacher.classes.all(), 'isTeacher': True})
except Teacher.DoesNotExist: except Teacher.DoesNotExist:
pass pass
@ -36,38 +41,37 @@ def classDetail (request, id):
classObj = Class.objects.get(id=id) classObj = Class.objects.get(id=id)
try: try:
student = Student.objects.get(user=request.user) student = request.user.student
except Student.DoesNotExist: except Student.DoesNotExist:
pass pass
else: else:
if classObj.confirmed.filter(user=student.user).count() != 1: if classObj.confirmed.filter(user=student.user).count() != 1:
return redirect('/') return redirect('/')
else: else:
return render(request, "skoolos/class_detail.html", {'class': classObj,'assignments': classObj.assignments.all(), 'teachers': classObj.classes.all()}) return render(request, "skoolos/class_detail.html", {'class': classObj,'assignments': classObj.assignments.all(), 'teachers': classObj.classes.all(), 'isTeacher': False})
try: try:
teacher = Teacher.objects.get(user=request.user) teacher = request.user.teacher
return render(request, "skoolos/home.html", {'classes': teacher.classes.all()})
except Teacher.DoesNotExist: except Teacher.DoesNotExist:
pass pass
else: else:
if classObj.confirmed.filter(user=student.user).count() != 1: if teacher.classes.filter(id=classObj.id).count() != 1:
return redirect('/') return redirect('/')
else: else:
return render(request, "skoolos/class_detail.html", {'class': classObj,'assignments': classObj.assignments.all(), 'teachers': classObj.classes.all()}) return render(request, "skoolos/class_detail.html", {'class': classObj,'assignments': classObj.assignments.all(), 'teachers': classObj.classes.all(), 'isTeacher': True})
return redirect('/') return redirect('/')
@login_required() @login_required()
def profile (request): def profile (request):
try: try:
student = Student.objects.get(user=request.user) student = request.user.student
return student_profile(request) return student_profile(request)
except Student.DoesNotExist: except Student.DoesNotExist:
pass pass
try: try:
teacher = Teacher.objects.get(user=request.user) teacher = request.user.teacher
return teacher_profile(request) return teacher_profile(request)
except Teacher.DoesNotExist: except Teacher.DoesNotExist:
pass pass
@ -91,7 +95,8 @@ def student_profile (request):
context = { context = {
'userForm': userForm, 'userForm': userForm,
'profileForm': profileForm, 'profileForm': profileForm,
'classes': request.user.student.confirmed.all() 'classes': request.user.student.confirmed.all(),
'isTeacher': False,
} }
return render(request, 'skoolos/profile_student.html', context) return render(request, 'skoolos/profile_student.html', context)
@ -113,7 +118,55 @@ def teacher_profile (request):
context = { context = {
'userForm': userForm, 'userForm': userForm,
'profileForm': profileForm, 'profileForm': profileForm,
'classes': request.user.teacher.classes.all() 'classes': request.user.teacher.classes.all(),
'isTeacher': True,
} }
return render(request, 'skoolos/profile_teacher.html', context) return render(request, 'skoolos/profile_teacher.html', context)
@login_required()
def createClass (request):
try:
teacher = request.user.teacher
except Teacher.DoesNotExist:
pass
else:
return createClassHelper(request)
return redirect('/')
def createClassHelper(request):
teacher = request.user.teacher
if request.method == "POST":
classForm = ClassCreationForm(request.POST)
if classForm.is_valid():
cleaned_data = classForm.clean()
print(cleaned_data)
newClass = classForm.save(commit=False)
newClass.owner = request.user
newClass.teacher = request.user.username
newClass.name = cleaned_data['subject'].replace(' ', '')[:8].lower() + str(cleaned_data['period']) + "_" + teacher.user.username.lower()
newClass.save()
classObj = classForm.save_m2m()
messages.success(request, cleaned_data['subject'].capitalize() + " has been created!")
print (newClass)
teacher.classes.add(newClass)
for student in newClass.unconfirmed.all():
if student.added_to == "":
student.added_to = newClass.name
else:
student.added_to = student.added_to + "," + newClass.name
student.save()
return redirect('home')
else:
classForm = ClassCreationForm()
context = {
'teacher': teacher,
'classes': teacher.classes.all(),
'classForm': classForm
}
return render(request, "skoolos/createClass.html", context)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,14 @@
"""
A simple background service to log events in a directory,
check for git commands in bash/zsh history,
and check for non-whitelisted files in the watched directory.
"""
import time import time
import sys import sys
import os import os
import pyinotify import pyinotify
import checker import checker
from pathlib import Path
class EventHandler(pyinotify.ProcessEvent): class EventHandler(pyinotify.ProcessEvent):
@ -112,7 +118,7 @@ DIR = None
START_TIME = None START_TIME = None
def watch_dir(watched_dir="/tmp", log_dir="/tmp/skooloslogs"): def watch_dir(watched_dir=str(Path.home()), log_dir="SkoolOS/logs"):
""" """
Watches the specified directory for changes and outputs it in Watches the specified directory for changes and outputs it in
human readable format to a log file in the specified log directory. human readable format to a log file in the specified log directory.
@ -137,6 +143,7 @@ def watch_dir(watched_dir="/tmp", log_dir="/tmp/skooloslogs"):
NOTIFIER.start() NOTIFIER.start()
sys.stdout = open("/dev/null", 'w') sys.stdout = open("/dev/null", 'w')
wm.add_watch(watched_dir, mask, rec=True) wm.add_watch(watched_dir, mask, rec=True)
time.sleep(1)
sys.stdout = logfile sys.stdout = logfile
print("Start time: " + print("Start time: " +
time.strftime("%A, %B %d, %Y %H:%M:%S", time.localtime()) + "\n") time.strftime("%A, %B %d, %Y %H:%M:%S", time.localtime()) + "\n")
@ -162,4 +169,3 @@ def stop_watching():
+ "The paths to these files are listed below:\n") + "The paths to these files are listed below:\n")
print(*suspicious_files, sep='\n') print(*suspicious_files, sep='\n')
sys.stdout = STDOUT sys.stdout = STDOUT
print("Done watching.\n")

3
bgservice/bgservice.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
python3 bgservice.py

2
bgservice/run.py Normal file
View File

@ -0,0 +1,2 @@
import bgservice as bg
bg.watch_dir()

View File

@ -1,2 +1,71 @@
Command Line Interface Command Line Interface
===================== =====================
1. Making a user:
-------
python skoolos.py
You will be redirected to a login page for the SkoolOS website. If you have already created an account on the website, enter login informatiton. If not, select
the registration button bellow and create an account. Once you create an account via Ion OAuth and SkoolOS, login. The window should close, prompting:
Enter SkoolOS Username:
Enter SkoolOS Password:
Enter the valid SkoolOS username and password. Congratialations, you have successfully logged in.
1. CLI as a teacher:
============
Start the CLI and select your username. For instance, teacher 'eharris1'
python skoolos.py
? Select User: (Use arrow keys)
1) 2022rkhondak
2) eharris1
3) Make new user
You will then be given the choice to select an existing class, Make a new class, or exit the CLI:
? Select class: (Use arrow keys)
Art12_eharris1
English12_eharris1
History12_eharris1
Make New Class
Exit SkoolOS
1. Making a new class:
-------
Select 'Make a New Class'. You will then be prompted to enter a class name. The format for every class must be <subject>_<teacher_username> (Example: Art12_eharris1).
Enter Period (must be a positive integer). You will then be prompted to add students. If you have a list of students, enter the relative path of a text file with the student usernames.
The file must be a .txt file and have one student username per line. If you add an individual student, simply enter their ion username.
one username per line.
? Select class: (Use arrow keys)
Art12_eharris1
English12_eharris1
History12_eharris1
Make New Class
Exit SkoolOS
? Add Students): (Use arrow keys)
1) Add individual student
2) Add list of students through path
3) Exit
? Add Students): 2) Add list of students through path
File must be .txt and have 1 student username per line
Relative Path: students.txt

View File

@ -1,7 +1,3 @@
.. SkoolOS documentation master file, created by
sphinx-quickstart on Tue Jun 16 11:22:02 2020.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to SkoolOS's documentation! Welcome to SkoolOS's documentation!
=================================== ===================================

View File

@ -1,2 +1,16 @@
Installation Installation
============ ============
Git clone repository:
-------
https://gitlab.tjhsst.edu/understudyathon-2020/group-1/schoolos.git
Install repository and create env
-------
cd SkoolOS
python3 -m venv env
source env/bin/activate
pip install -r requirements.txt

View File

@ -1,7 +0,0 @@
kskskksks
kskskksks
kskskksks
kskskksks
kskskksks
kskskksks
kskskksks

View File

View File

@ -1,5 +1,6 @@
appdirs==1.4.3 appdirs==1.4.3
cachecontrol==0.12.6 cachecontrol==0.12.6
chromedriver==2.24.1
click==7.1.2 click==7.1.2
colorama==0.4.3 colorama==0.4.3
contextlib2==0.6.0 contextlib2==0.6.0
@ -52,20 +53,20 @@ yapf==0.30.0
# lazy-object-proxy==1.4.3 # Installed as dependency for astroid # lazy-object-proxy==1.4.3 # Installed as dependency for astroid
# markupsafe==1.1.1 # Installed as dependency for jinja2 # markupsafe==1.1.1 # Installed as dependency for jinja2
# mccabe==0.6.1 # Installed as dependency for pylint # mccabe==0.6.1 # Installed as dependency for pylint
# msgpack==0.6.2 # Installed as dependency for pynvim, cachecontrol # msgpack==0.6.2 # Installed as dependency for cachecontrol, pynvim
# oauthlib==3.1.0 # Installed as dependency for requests-oauthlib, django-oauth-toolkit # oauthlib==3.1.0 # Installed as dependency for django-oauth-toolkit, requests-oauthlib
# packaging==20.1 # Installed as dependency for sphinx # packaging==20.1 # Installed as dependency for sphinx
# pillow==7.1.2 # Installed as dependency for wpgtk # pillow==7.1.2 # Installed as dependency for wpgtk
# prompt-toolkit==1.0.14 # Installed as dependency for pyinquirer # prompt-toolkit==1.0.14 # Installed as dependency for pyinquirer
# psycopg2-binary==2.8.5 # Installed as dependency for django-request-token # psycopg2-binary==2.8.5 # Installed as dependency for django-request-token
# pygments==2.6.1 # Installed as dependency for sphinx, pyinquirer # pygments==2.6.1 # Installed as dependency for pyinquirer, sphinx
# pyjwt==1.7.1 # Installed as dependency for django-request-token # pyjwt==1.7.1 # Installed as dependency for django-request-token
# pyparsing==2.4.6 # Installed as dependency for packaging # pyparsing==2.4.6 # Installed as dependency for packaging
# pytz==2020.1 # Installed as dependency for django, babel # pytz==2020.1 # Installed as dependency for babel, django
# pywal==3.3.0 # Installed as dependency for wpgtk # pywal==3.3.0 # Installed as dependency for wpgtk
# regex==2020.5.14 # Installed as dependency for pyinquirer # regex==2020.5.14 # Installed as dependency for pyinquirer
# requests==2.23.0 # Installed as dependency for cachecontrol, requests-oauth, django-oauth-toolkit, sphinx, requests-oauthlib # requests==2.23.0 # Installed as dependency for cachecontrol, requests-oauthlib, django-oauth-toolkit, sphinx, requests-oauth
# six==1.15.0 # Installed as dependency for astroid, prompt-toolkit, html5lib, retrying, packaging # six==1.15.0 # Installed as dependency for prompt-toolkit, astroid, retrying, html5lib, packaging
# snowballstemmer==2.0.0 # Installed as dependency for sphinx # snowballstemmer==2.0.0 # Installed as dependency for sphinx
# sphinxcontrib-applehelp==1.0.2 # Installed as dependency for sphinx # sphinxcontrib-applehelp==1.0.2 # Installed as dependency for sphinx
# sphinxcontrib-devhelp==1.0.2 # Installed as dependency for sphinx # sphinxcontrib-devhelp==1.0.2 # Installed as dependency for sphinx
@ -73,9 +74,9 @@ yapf==0.30.0
# sphinxcontrib-jsmath==1.0.1 # Installed as dependency for sphinx # sphinxcontrib-jsmath==1.0.1 # Installed as dependency for sphinx
# sphinxcontrib-qthelp==1.0.3 # Installed as dependency for sphinx # sphinxcontrib-qthelp==1.0.3 # Installed as dependency for sphinx
# sphinxcontrib-serializinghtml==1.1.4 # Installed as dependency for sphinx # sphinxcontrib-serializinghtml==1.1.4 # Installed as dependency for sphinx
# sqlparse==0.3.1 # Installed as dependency for django, django-request-token # sqlparse==0.3.1 # Installed as dependency for django-request-token, django
# toml==0.10.0 # Installed as dependency for pylint, pep517 # toml==0.10.0 # Installed as dependency for pylint, pep517
# urllib3==1.25.9 # Installed as dependency for selenium, requests # urllib3==1.25.9 # Installed as dependency for requests, selenium
# wcwidth==0.2.3 # Installed as dependency for prompt-toolkit # wcwidth==0.2.3 # Installed as dependency for prompt-toolkit
# webencodings==0.5.1 # Installed as dependency for html5lib # webencodings==0.5.1 # Installed as dependency for html5lib
# wrapt==1.12.1 # Installed as dependency for astroid # wrapt==1.12.1 # Installed as dependency for astroid

1
rushilwiz Submodule

@ -0,0 +1 @@
Subproject commit b80d7ed56b7d649a74be4e7f906d26e7be43702d

View File

@ -1,3 +1,6 @@
"""
The main program file for SkoolOS
"""
import sys import sys
from urllib.parse import urlparse from urllib.parse import urlparse
import requests import requests
@ -25,7 +28,12 @@ scope = ["read"]
USER = "" USER = ""
PWD = "" PWD = ""
def main(): def main():
"""
The Command Line Interface (CLI) for SkoolOS
Serves to allow both teachers and students to access the majority of the features of SkoolOS
"""
print("") print("")
print("░██████╗██╗░░██╗░█████╗░░█████╗░██╗░░░░░  ░█████╗░░██████╗") print("░██████╗██╗░░██╗░█████╗░░█████╗░██╗░░░░░  ░█████╗░░██████╗")
print("██╔════╝██║░██╔╝██╔══██╗██╔══██╗██║░░░░░  ██╔══██╗██╔════╝") print("██╔════╝██║░██╔╝██╔══██╗██╔══██╗██║░░░░░  ██╔══██╗██╔════╝")
@ -35,292 +43,574 @@ def main():
print("╚═════╝░╚═╝░░╚═╝░╚════╝░░╚════╝░╚══════╝  ░╚════╝░╚═════╝░") print("╚═════╝░╚═╝░░╚═╝░╚════╝░░╚════╝░╚══════╝  ░╚════╝░╚═════╝░")
print("") print("")
if not (os.path.exists(".sprofile") or os.path.exists(".tprofile")): profiles = os.listdir()
if not ("profile" in str(profiles)):
try: try:
URL = "http://127.0.0.1:8000/api/" URL = "http://127.0.0.1:8000/api/"
r = requests.get(url = URL) r = requests.get(url=URL)
except: except:
print("Run Django server on http://127.0.0.1:8000/ before continuing") print("Run Django server on http://127.0.0.1:8000/ before continuing")
sys.exit(0) sys.exit(0)
input("Welcome to SkoolOS. Press any key to create an account") input("Welcome to SkoolOS. Press any key to create an account")
#webbrowser.open("http://127.0.0.1:8000/login", new=2) # webbrowser.open("http://127.0.0.1:8000/login", new=2)
authenticate() authenticate()
profiles = os.listdir()
users = []
info = []
count = 1
for i in range(len(profiles)):
p = profiles[i]
if 'profile' in p:
f = open(p, 'r')
d = json.loads(f.read())
f.close()
info.append(d)
users.append(str(count) + ") " + d['username'])
count = count + 1
users.append(str(count) + ") Make new user")
user = [
{
'type': 'list',
'name': 'user',
'choices': users,
'message': 'Select User: ',
},
]
u = int(prompt(user)['user'].split(")")[0]) - 1
if u + 1 == count:
authenticate()
return
data = info[u]
PWD = data['password']
USER = data['username']
print(data['username'])
if data['is_student']:
studentCLI(USER, PWD)
else: else:
try: teacherCLI(USER, PWD)
f = open('.tprofile','r')
except:
f = open('.sprofile','r') #################################################################################################### STUDENT METHODS
data = json.loads(f.read())
f.close()
PWD = data['password']
USER = data['username']
print(data['username'])
if(data['is_student']):
studentCLI(USER, PWD)
else:
teacherCLI(USER, PWD)
# while True:
# pass
def studentCLI(user, password): def studentCLI(user, password):
"""
The CLI for students to access
@param user: student username
@param password: student password
"""
from CLI import student from CLI import student
data = getUser(user, password, 'student') data = getUser(user, password, 'student')
student = student.Student(data) student = student.Student(data, password)
student.update()
EXIT = False
while not EXIT:
course = chooseClassStudent(student)
if course == "Exit SkoolOS":
return
EXIT = classOptionsStudent(student, course)
# return class
def chooseClassStudent(student):
"""
Chooses a class for a student to view and work on
@param student: a student
:return: a course prompt
"""
carray = student.sclass.split(",") carray = student.sclass.split(",")
if(len(carray) == 1 and carray[0] == ""): if len(carray) == 1 and carray[0] == "":
carray.remove("")
print("No classes") print("No classes")
return
carray.append("Exit SkoolOS") carray.append("Exit SkoolOS")
courses = [ courses = [
{ {
'type': 'list', 'type': 'list',
'name': 'course', 'name': 'course',
'choices':carray, 'choices': carray,
'message': 'Select class: ', 'message': 'Select class: ',
}, },
] ]
course = prompt(courses)['course'] course = prompt(courses)['course']
print(course) print(course)
if course == "Exit SkoolOS": return course
student.exitCLI()
else:
student.viewClass(course)
student.getAssignments(course, 100)
def classOptionsStudent(student, course):
"""
Allows students to choose what they want to do related to a class
The student can save, exit, or go back
@param student: a student
@param course: a course
:return: True if exiting, False if going back
"""
student.viewClass(course)
student.getAssignments(course, 100)
choices = ["Save","Submit assignment","Back","Exit SkoolOS"]
options = [
{
'type': 'list',
'name': 'option',
'choices': choices,
'message': 'Select: ',
},
]
option = prompt(options)['option']
if option == "Save":
student.update()
print("Saved!")
classOptionsStudent(student, course)
if option == "Back":
student.exitCLI()
# dont exit cli
return False
if option == "Exit SkoolOS":
student.exitCLI()
# exit cli
return True
if(option == "Submit assignment"):
assignments = os.listdir(student.username)
tlist = []
b = True
for a in assignments:
oname = a + "_" + course
a = student.username + "/" + a
if(os.path.isdir(a) and not "." in a and not oname in student.completed):
tlist.append(a)
assignments = tlist
assignments.append("Back")
print(assignments)
options = [
{
'type': 'list',
'name': 'submit',
'choices':assignments,
'message': 'Select: ',
},
]
ass = prompt(options)['submit']
if(ass == "Back"):
return False
else:
student.submit(course, ass)
return False
#################################################################################################### TEACHER METHODS
def teacherCLI(user, password): def teacherCLI(user, password):
"""
The CLI for teachers to access
@param user: teachers username
@param password: teachers password
"""
from CLI import teacher from CLI import teacher
data = getUser(user, password, 'teacher') data = getUser(user, password, 'teacher')
print(data) print(data)
teacher = teacher.Teacher(data) teacher = teacher.Teacher(data, password)
EXIT = False
# 1. make a class # 1. make a class
# 2. add studeents to an existing class # 2. add studeents to an existing class
# 3. Get progress logs on a student # 3. Get progress logs on a student
# 2. make an assignment for a class # 2. make an assignment for a class
# 3. view student submissions for an assignment # 3. view student submissions for an assignment
carray = teacher.classes while not EXIT:
carray.append("Exit SkoolOS") # Options: '1) Request Student', "2) Add assignment", "3) View student information", "4) Exit"
carray.append("Make New Class") course = chooseGeneralTeacher(teacher)
courses = [ if course == "Exit SkoolOS":
{ EXIT = True
'type': 'list', elif course == "Make New Class":
'name': 'course', EXIT = makeClassTeacher(teacher)
'choices':carray, # selected a class
'message': 'Select class: ', else:
}, #Pull confirmed students directory
] teacher.getStudents(course)
course = prompt(courses)['course'] option = classOptionsTeacher(teacher, course)
if course == "Exit SkoolOS": if option == '1':
teacher.exitCLI() EXIT = addStudentsTeacher(teacher, course)
if course == "Make New Class": elif option == '2':
questions = [ EXIT = addAssignmentTeacher(teacher, course)
{ elif option == '3':
'type': 'input', EXIT = viewStudentsTeacher(teacher, course)
'name': 'cname', else:
'message': 'Class Name: ', EXIT = True
},
]
cname = prompt(questions)['cname']
teacher.makeClass(cname)
soption = ["1) Add individual student", "2) Add list of students through path", "3) Exit"]
questions = [
{
'type': 'list',
'choices':soption,
'name': 'students',
'message': 'Add list of students (input path): ',
},
]
choice = prompt(questions)['students'].split(")")[0]
if("1" == choice):
s = input("Student name: ")
teacher.addStudent(s, cname)
if("2" == choice):
p = input("Relativee Path: ")
if(os.path.exists(p)):
print(p + " does not exist.")
else:
print("Class: " + course) def chooseGeneralTeacher(teacher):
unconf = getDB("http://localhost:8000/api/classes/" + course)['unconfirmed'] carray = []
for s in unconf: for c in teacher.classes:
teacher.addStudent() carray.append(c)
options = ['1) Request Student', "2) Add assignment", "3) View student information"] carray.append("Make New Class")
questions = [ carray.append("Exit SkoolOS")
courses = [
{ {
'type': 'list', 'type': 'list',
'name': 'course', 'name': 'course',
'choices':options, 'choices': carray,
'message': 'Select class: ',
},
]
course = prompt(courses)['course']
return course
def makeClassTeacher(teacher):
questions = [
{
'type': 'input',
'name': 'cname',
'message': 'Class Name (Must be: <subject>_<ion_user>): ',
},
]
cname = prompt(questions)['cname']
print(cname)
while not ("_" + teacher.username) in cname:
print("Incorrect naming format")
questions = [
{
'type': 'input',
'name': 'cname',
'message': 'Class Name (Must be: <subject>_<ion_user>): ',
},
]
cname = prompt(questions)['cname']
teacher.makeClass(cname)
soption = ["1) Add individual student", "2) Add list of students through path", "3) Exit"]
questions = [
{
'type': 'list',
'choices': soption,
'name': 'students',
'message': 'Add Students): ',
},
]
choice = prompt(questions)['students'].split(")")[0]
if "1" == choice:
s = input("Student name: ")
teacher.addStudent(s, cname)
if "2" == choice:
print("File must be .txt and have 1 student username per line")
path = input("Relative Path: ")
while not os.path.exists(path):
if path == 'N':
return True
print(path + " is not a valid path")
path = input("Enter file path ('N' to exit): ")
f = open(path, 'r')
students = f.read().splitlines()
teacher.reqAddStudentList(students, cname)
return False
def classOptionsTeacher(teacher, course):
print("Class: " + course)
unconf = getDB(teacher.username, teacher.password, "http://localhost:8000/api/classes/" + course)['unconfirmed']
for s in unconf:
teacher.addStudent(s, course)
options = ['1) Request Student', "2) Add assignment", "3) View student information", "4) Exit"]
questions = [
{
'type': 'list',
'name': 'course',
'choices': options,
'message': 'Select option: ', 'message': 'Select option: ',
}, },
]
option = prompt(questions)['course'].split(")")[0]
return option
def addStudentsTeacher(teacher, course):
soption = ["1) Add individual student", "2) Add list of students through path", "3) Exit"]
questions = [
{
'type': 'list',
'choices': soption,
'name': 'students',
'message': 'Add list of students (input path): ',
},
]
schoice = prompt(questions)['students'].split(")")[0]
if schoice == '1':
questions = [
{
'type': 'input',
'name': 'student',
'message': 'Student Name: ',
},
] ]
option = prompt(questions)['course'].split(")")[0] s = prompt(questions)['student']
if(option == '1'): teacher.reqStudent(s, course)
soption = ["1) Add individual student", "2) Add list of students through path", "3) Exit"] return False
questions = [ if schoice == '2':
questions = [
{ {
'type': 'list', 'type': 'input',
'choices':soption, 'name': 'path',
'name': 'students', 'message': 'Path: ',
'message': 'Add list of students (input path): ', },
}, ]
] path = prompt(questions)['path']
schoice = prompt(questions)['students'].split(")")[0] while not os.path.exists(path):
if(schoice == '1'): if path == 'N':
questions = [
{
'type': 'input',
'name': 'student',
'message': 'Student Name: ',
},
]
s = prompt(questions)['student']
teacher.reqStudent(s, course)
if(schoice == '2'):
questions = [
{
'type': 'input',
'name': 'path',
'message': 'Path: ',
},
]
path = prompt(questions)['path']
while(not os.path.exists(path)):
if(path == 'N'):
sys.exit(0)
print(path + " is not a valid path")
path = input("Enter file path ('N' to exit): ")
f = open(path, 'r')
students = f.read().splitlines()
teacher.reqAddStudentList(students, course)
else:
sys.exit()
if(option == '2'):
nlist = os.listdir(teacher.username + "/" + course)
alist = getDB("http://localhost:8000/api/classes/" + course)['assignments']
print(nlist)
tlist = []
b = True
for n in nlist:
b = True
print(teacher.username + "/" + course + "/" + n)
for a in alist:
if(n in a or n == a):
#print("Assignments: " + n)
b = False
if(not os.path.isdir(teacher.username + "/" + course + "/" + n)):
b = False
if(b):
tlist.append(n)
nlist = tlist
if(len(nlist) == 0):
print("No new assignments found")
sys.exit(0) sys.exit(0)
questions = [ print(path + " is not a valid path")
{ path = input("Enter file path ('N' to exit): ")
'type': 'list', f = open(path, 'r')
'choices':nlist, students = f.read().splitlines()
'name': 'assignment', teacher.reqAddStudentList(students, course)
'message': 'Select new assignment: ', return False
}, else:
] return True
ass = prompt(questions)['assignment']
apath = teacher.username + "/" + course + "/" + ass
def addAssignmentTeacher(teacher, course):
nlist = os.listdir(teacher.username + "/" + course)
alist = getDB(teacher.username, teacher.password, "http://localhost:8000/api/classes/" + course)['assignments']
print(nlist)
tlist = []
b = True
for n in nlist:
b = True
print(teacher.username + "/" + course + "/" + n)
for a in alist:
if n in a or n == a:
# print("Assignments: " + n)
b = False
if not os.path.isdir(teacher.username + "/" + course + "/" + n):
b = False
if b:
tlist.append(n)
nlist = tlist
if len(nlist) == 0:
print("No new assignments found")
print(
"To make an assignment: make a subdirectory in the " + course + " folder. Add a file within the new folder")
return False
questions = [
{
'type': 'list',
'choices': nlist,
'name': 'assignment',
'message': 'Select new assignment: ',
},
]
ass = prompt(questions)['assignment']
apath = teacher.username + "/" + course + "/" + ass
due = input("Enter due date (Example: 2020-08-11 16:58): ")
due = due + ":33.383124"
due = due.strip()
f = False
while not f:
try:
datetime.datetime.strptime(due, '%Y-%m-%d %H:%M:%S.%f')
f = True
except:
print("Due-date format is incorrect.")
print(due)
due = input("Enter due date (Example: 2020-08-11 16:58): ") due = input("Enter due date (Example: 2020-08-11 16:58): ")
due = due + ":00.000000" due = due + ":33.383124"
due = due.strip() teacher.addAssignment(apath, course, due)
teacher.addAssignment(apath, course, due) return False
def viewStudentsTeacher(teacher, course):
data = getDB(teacher.username, teacher.password, "http://127.0.0.1:8000/api/classes/" + course)
students = data["confirmed"]
unconf = data['unconfirmed']
print("Studented in class: ")
for s in students:
print(s)
print("Requsted Students: ")
for s in unconf:
print(s)
student = input("View student (Enter student's ion username): ")
while((not student in str(data['confirmed'])) and (not student in str(data['unconfirmed']))):
print("Student not affiliated with class")
student = input("View student ('N' to exit): ")
if student == 'N':
return False
sinfo = getDB(teacher.username, teacher.password, "http://127.0.0.1:8000/api/students/" + student + "/")
pprint.pprint(sinfo)
print("Confirmed: " + str(student in str(data['confirmed'])))
if(student in str(data['confirmed'])):
path = teacher.username + "/Students/" + course + "/" + student
print(student + "'s work: " + path)
fin = sinfo['completed'].split(",")
alist = []
for f in fin:
if(course in f):
late = teacher.afterSubmit(course, f, student)
if(late):
s = f.split("_")[0] + " (LATE)"
else:
s = f.split("_")[0]
alist.append(s)
print("Has submitted: " + str(alist))
#put log stuff
############################################################################################################################################
def getUser(ion_user, password, utype): def getUser(ion_user, password, utype):
if('student' in utype): """
URL = "http://127.0.0.1:8000/api/students/" + ion_user + "/" Returns user information
else: @param ion_user: user
URL = "http://127.0.0.1:8000/api/teachers/" + ion_user + "/" @param password: user's password
r = requests.get(url = URL, auth=(ion_user,password)) @param utype: type of user (student or teacher
print(r.json()) :return: api user information
if(r.status_code == 200): """
data = r.json() if 'student' in utype:
print(200) URL = "http://127.0.0.1:8000/api/students/" + ion_user + "/"
return data else:
elif(r.status_code == 404): URL = "http://127.0.0.1:8000/api/teachers/" + ion_user + "/"
print("Make new account!") print(URL)
return None r = requests.get(url=URL, auth=(ion_user, password))
elif(r.status_code == 403): print(r.json())
print("Invalid username/password") if r.status_code == 200:
return None data = r.json()
else: print(200)
print(r.status_code) return data
return None elif r.status_code == 404:
def patchDB(data, url): print("Make new account!")
r = requests.patch(url = url, data=data, auth=('raffukhondaker','hackgroup1')) return None
elif r.status_code == 403:
print("Invalid username/password")
return None
else:
print(r.status_code)
return None
def patchDB(USER, PWD, url, data):
"""
Sends a PATCH request to url
@param USER: username
@param PWD: password
@param url: URL for request
@param data: data to request
:return: json request response
"""
r = requests.patch(url=url, data=data, auth=(USER, PWD))
print("PATH:" + str(r.status_code)) print("PATH:" + str(r.status_code))
return(r.json()) return r.json()
def getDB(url):
r = requests.get(url = url, auth=('raffukhondaker','hackgroup1')) def getDB(USER, PWD, url):
"""
Sends a GET request to url
@param USER: username
@param PWD: password
@param url: URL for request
:return: json request response
"""
r = requests.get(url=url, auth=(USER, PWD))
print("GET:" + str(r.status_code)) print("GET:" + str(r.status_code))
return(r.json()) return r.json()
def postDB(data, url):
r = requests.post(url = url, data=data, auth=('raffukhondaker','hackgroup1')) def postDB(USER, PWD, url, data):
"""
Sends a POST request to url
@param USER: username
@param PWD: password
@param url: URL for request
@param data: data to request
:return: json request response
"""
r = requests.post(url=url, data=data, auth=(USER, PWD))
print("POST:" + str(r.status_code)) print("POST:" + str(r.status_code))
return(r.json()) return r.json()
def putDB(data, url):
r = requests.put(url = url, data=data, auth=('raffukhondaker','hackgroup1')) def putDB(USER, PWD, url, data):
"""
Sends a PUT request to url
@param USER: username
@param PWD: password
@param url: URL for request
@param data: data to request
:return: json request response
"""
r = requests.put(url=url, data=data, auth=(USER, PWD))
print("PUT:" + str(r.status_code)) print("PUT:" + str(r.status_code))
return(r.json()) return r.json()
def delDB(url):
r = requests.delete(url = url, auth=('raffukhondaker','hackgroup1')) def delDB(USER, PWD, url):
"""
Sends a DELETE request to url
@param USER: username
@param PWD: password
@param url: URL for request
:return: json request response
"""
r = requests.delete(url=url, auth=(USER, PWD))
print("DELETE:" + str(r.status_code)) print("DELETE:" + str(r.status_code))
return None return None
def makePass(): def makePass():
"""
Prompts the user to create a password
:return: the password
"""
questions = [ questions = [
{ {
'type': 'password', 'type': 'password',
'name': 'pwd', 'name': 'pwd',
'message': 'Enter SkoolOS Password (NOT ION PASSWORD): ', 'message': 'Enter SkoolOS Password (NOT ION PASSWORD): ',
}, },
] ]
pwd = prompt(questions)['pwd'] pwd = prompt(questions)['pwd']
while(len(pwd) < 7): while len(pwd) < 7:
print("Password too short (Must be over 6 characters)") print("Password too short (Must be over 6 characters)")
pwd = prompt(questions)['pwd'] pwd = prompt(questions)['pwd']
conf = [ conf = [
{ {
'type': 'password', 'type': 'password',
'name': 'pwd', 'name': 'pwd',
'message': 'Re-enter password: ', 'message': 'Re-enter password: ',
}, },
] ]
pwd2 = prompt(conf)['pwd'] pwd2 = prompt(conf)['pwd']
while(not pwd == pwd2): while not pwd == pwd2:
print("Passwords do not match.") print("Passwords do not match.")
pwd2 = prompt(conf)['pwd'] pwd2 = prompt(conf)['pwd']
else: else:
print("PASSWORD SAVED") print("PASSWORD SAVED")
return pwd return pwd
def authenticate(): def authenticate():
"""
Authenticates the user via Ion OAuth
"""
oauth = OAuth2Session(client_id=client_id, redirect_uri=redirect_uri, scope=scope) oauth = OAuth2Session(client_id=client_id, redirect_uri=redirect_uri, scope=scope)
authorization_url, state = oauth.authorization_url("https://ion.tjhsst.edu/oauth/authorize/") authorization_url, state = oauth.authorization_url("https://ion.tjhsst.edu/oauth/authorize/")
import os
cdir = os.getcwd() cdir = os.getcwd()
#Linux: chromdriver-linux # Linux: chromdriver-linux
#Macos: chromdriver-mac # Macos: chromdriver-mac
#Windows: chromdriver.exe # Windows: chromdriver.exe
if('CLI' in os.getcwd()): print("OS: ")
path = os.path.join(os.getcwd(), '../','chromedriver-mac') print("MacOS")
else: print("Linux")
path = os.path.join(os.getcwd(), 'chromedriver-mac')
system = input("Enter OS: ")
while(system.lower() != "linux" and system.lower() != "macos"):
print("Not valid OS")
system = input("Enter OS: ")
if(system.lower() == 'macos'):
path = os.path.join(os.getcwd(), 'chromedriver', 'chromedriver-mac')
if(system.lower() == 'linux'):
path = os.path.join(os.getcwd(), 'chromedriver', 'chromedriver-linux')
browser = webdriver.Chrome(path) browser = webdriver.Chrome(path)
browser.get("localhost:8000/login") browser.get("localhost:8000/login")
@ -330,7 +620,8 @@ def authenticate():
url = browser.current_url url = browser.current_url
gets = url_decode(url.replace("http://localhost:8000/login/?", "")) gets = url_decode(url.replace("http://localhost:8000/login/?", ""))
while "http://localhost:8000/login/?username=" not in browser.current_url and (not browser.current_url == "http://localhost:8000/"): #http://localhost:8000/ while "http://localhost:8000/login/?username=" not in browser.current_url and (
not browser.current_url == "http://localhost:8000/"): # http://localhost:8000/
time.sleep(0.25) time.sleep(0.25)
url = browser.current_url url = browser.current_url
@ -341,69 +632,76 @@ def authenticate():
# print("states good") # print("states good")
browser.quit() browser.quit()
questions = [ questions = [
{ {
'type': 'input', 'type': 'input',
'name': 'username', 'name': 'username',
'message': 'Enter SkoolOS Username (Same as ION Username): ', 'message': 'Enter SkoolOS Username (Same as ION Username): ',
}, },
{ {
'type': 'password', 'type': 'password',
'name': 'pwd', 'name': 'pwd',
'message': 'Enter SkoolOS Password (NOT ION PASSWORD): ', 'message': 'Enter SkoolOS Password (NOT ION PASSWORD): ',
}, },
] ]
data =prompt(questions) data = prompt(questions)
pwd = data['pwd'] pwd = data['pwd']
user = data['username'] user = data['username']
r = requests.get(url = "http://localhost:8000/api/", auth=(user,pwd)) r = requests.get(url="http://localhost:8000/api/", auth=(user, pwd))
while(r.status_code != 200): while r.status_code != 200:
print("INCORRECT LOGIN CREDENTIALS") print("INCORRECT LOGIN CREDENTIALS")
r = requests.get(url = "http://localhost:8000/api/", auth=(user,pwd)) r = requests.get(url="http://localhost:8000/api/", auth=(user, pwd))
data =prompt(questions) data = prompt(questions)
pwd = data['pwd'] pwd = data['pwd']
user = data['username'] user = data['username']
print(r.status_code) print(r.status_code)
r = requests.get(url = "http://localhost:8000/api/students/" + user + "/", auth=(user,pwd)) r = requests.get(url="http://localhost:8000/api/students/" + user + "/", auth=(user, pwd))
is_student = False is_student = False
if(r.status_code == 200): if r.status_code == 200:
is_student = True is_student = True
print("Welcome, student " + user) print("Welcome, student " + user)
r = requests.get(url = "http://localhost:8000/api/students/" + user + "/", auth=(user,pwd)) r = requests.get(url="http://localhost:8000/api/students/" + user + "/", auth=(user, pwd))
profile = r.json() profile = r.json()
username = profile['ion_user'] username = profile['ion_user']
grade = profile['grade'] grade = profile['grade']
profile = { profile = {
'username':username, 'username': username,
'grade':grade, 'grade': grade,
'is_student':is_student, 'is_student': is_student,
'password':pwd, 'password': pwd,
} }
profileFile = open(".sprofile", "w") fname = "." + username + "profile"
profileFile = open(fname, "w")
profileFile.write(json.dumps(profile)) profileFile.write(json.dumps(profile))
profileFile.close() profileFile.close()
else: else:
print("Welcome, teacher " + user) print("Welcome, teacher " + user)
r = requests.get(url = "http://localhost:8000/api/teachers/" + user + "/", auth=(user,pwd)) r = requests.get(url="http://localhost:8000/api/teachers/" + user + "/", auth=(user, pwd))
profile = r.json() profile = r.json()
username = profile['ion_user'] username = profile['ion_user']
profile = { profile = {
'username':username, 'username': username,
'is_student':is_student, 'is_student': is_student,
'password':pwd, 'password': pwd,
} }
profileFile = open(".tprofile", "w") fname = "." + username + "profile"
profileFile = open(fname, "w")
profileFile.write(json.dumps(profile)) profileFile.write(json.dumps(profile))
profileFile.close() profileFile.close()
sys.exit sys.exit(0)
def create_server(): def create_server():
"""
Creates a simple HTTP server for creating api requests from the CLI
"""
port = 8000 port = 8000
handler = http.server.SimpleHTTPRequestHandler handler = http.server.SimpleHTTPRequestHandler
httpd = socketserver.TCPServer(("", port), handler) httpd = socketserver.TCPServer(("", port), handler)
print("serving at port:" + str(port)) print("serving at port:" + str(port))
httpd.serve_forever() httpd.serve_forever()
if __name__ == "__main__": if __name__ == "__main__":
main() main()

105
snew.py
View File

@ -1,105 +0,0 @@
import sys
from urllib.parse import urlparse
import requests
from requests_oauthlib import OAuth2Session
from selenium import webdriver
import os.path
import time
import http.server
import socketserver
from threading import Thread
from werkzeug.urls import url_decode
import pprint
from PyInquirer import prompt, print_json
import json
import os
import argparse
import webbrowser
import subprocess
from django.conf import settings
import django
from Website.config.settings import DATABASES, INSTALLED_APPS
INSTALLED_APPS.remove('users.apps.UsersConfig')
INSTALLED_APPS.remove('api')
INSTALLED_APPS.remove('skoolos.apps.SkoolosConfig')
INSTALLED_APPS.append('Website.api')
settings.configure(DATABASES=DATABASES, INSTALLED_APPS=INSTALLED_APPS)
django.setup()
from Website.api.models import *
def command(command):
ar = []
command = command.split(" ")
for c in command:
ar.append(c)
process = subprocess.Popen(ar, stdout=subprocess.PIPE,stderr=subprocess.PIPE)
p=process.poll()
output = process.communicate()[0]
print(output.decode('utf-8'))
return output.decode('utf-8')
class Students:
def __init__(self, username):
self.student = Student.objects.get(ion_user = username)
#ion id: student.user
if(os.path.isdir(self.student.user) == False):
if(self.student.repo == ""):
user= self.student.git
pwd= input("Enter Github password: ")
#curl -i -u USER:PASSWORD -d '{"name":"REPO"}' https://api.github.com/user/repos
url= "curl -i -u " + user + ":" + pwd + " -d '" + '{"name":"' + self.username + '"}' + "' " + "https://api.github.com/user/repos"
print(url)
os.system(url)
cdir = os.getcwd()
command('git clone https://github.com/' + self.git + '/' + self.username + '.git')
os.chdir(self.username)
command('git checkout master')
command('touch README.md')
command('git add README.md')
command('git commit -m "Hello"')
command('git push -u origin master')
os.chdir(cdir)
self.repo = 'https://github.com/' + self.git + '/' + self.username + '.git'
data={
'user':self.user,
'git':self.git,
'ion_user':self.username,
'added_to':self.snew,
'url':self.url,
'classes':self.sclass,
'grade':self.grade,
'completed':self.completed,
'repo':self.repo
}
print(putDB(data, self.url))
print("Synced to " + self.username)
# c = {
# 'name':'Math5'
# }
# c = Class.objects.get(name='Math5')
# data = requests.get(url = "http://localhost:8000/api/classes/Math5", auth=('raffukhondaker','hackgroup1')).json()
# r = requests.post(url = "http://localhost:8000/api/classes/", data={'name':'English11', 'teacher':'eharris1', 'owner':2}, auth=('raffukhondaker','hackgroup1'))
# print("POST:" + str(r.json()))
# # print(r.json())
# # print(c.name)
# # c = {
# # 'classes':c
# # }
# # print(c)
# r = requests.patch(url = "http://localhost:8000/api/teachers/eharris1/", data={'classes':['English11']}, auth=('raffukhondaker','hackgroup1'))
# print(r.json())
import bgservice.bgservice as bg
bg.watch_dir('2022rkhondak', 'eharris1')
time.sleep(60)
bg.stop_watching()

View File

@ -0,0 +1 @@
Subproject commit ca356ef8532873bf52ec67a647fbb91a25ca1cb7

View File

View File

@ -1 +1,2 @@
2022rkhondak 2022rkhondak
2023rmama