-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRPSProgram.py
More file actions
190 lines (143 loc) · 7.43 KB
/
RPSProgram.py
File metadata and controls
190 lines (143 loc) · 7.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
"""
This program utilizes Selenium and Python to automate the process of checking for studies on the UCalgary SONA RPS website.
Copyright (C) 2021 Gurveer Gill
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
from time import time, sleep, strftime
from discord_webhooks import DiscordWebhooks
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
# General program parameters
USERNAME = ""
PASSWORD = ""
CODE_SLEEP_TIME = 30
WEBHOOK_URL = ("")
SEND_NOTIFICATION = True
RECORD_STUDIES = False
LOCAL_TESTING = False
BROWSER = webdriver.Firefox()
STUDY_OMISSION_LIST = [] # List to add studies already notified about, so that repeat notifications aren't sent.
def local_test():
"""Local testing function"""
import os
global WEBHOOK_URL
html_file = os.getcwd() + "//" + " " # <- Put path to html studies files here.
BROWSER.get("file:///" + html_file)
TESTING_WEBHOOK_URL = ()
WEBHOOK_URL = TESTING_WEBHOOK_URL
def start_RPS(username, password):
"""Opens the browser, logs into RPS, and opens the study view."""
# Open the RPS website
BROWSER.get("https://ucalgary.sona-systems.com/Default.aspx?ReturnUrl=%2f")
WebDriverWait(BROWSER, 3) # In case of slow loading, wait 3 seconds for page to ensure the page has fully loaded.
# Enter username and password
username_input_field = BROWSER.find_element_by_id("ctl00_ContentPlaceHolder1_userid")
password_input_field = BROWSER.find_element_by_id("ctl00_ContentPlaceHolder1_pw")
username_input_field.send_keys(username)
password_input_field.send_keys(password)
# Click authentication button
login_button = BROWSER.find_element_by_id("ctl00_ContentPlaceHolder1_default_auth_button")
login_button.click()
# Open study view
WebDriverWait(BROWSER, 3) # In case of slow loading, wait 3 seconds for page to ensure the page has fully loaded.
study_view_button = BROWSER.find_element_by_id("lnkStudySignupLink")
study_view_button.click()
def study_exists():
"""Check if RPS contains any studies."""
# If no studies exist, return false. Otherwise, return true.
if "No studies are available at this time." in BROWSER.page_source:
return False
return True
def discord_notification():
"""Sends a discord notification of an available study."""
webhook = DiscordWebhooks(WEBHOOK_URL)
# Retrieve study information
raw_study_info = BROWSER.find_element_by_xpath("//*[contains(@id, 'HyperlinkStudentStudyInfo')]").text
raw_study_credits = BROWSER.find_element_by_xpath("//*[contains(@id, 'LabelCredits')]").text.strip("()")
raw_study_description = BROWSER.find_element_by_xpath("//*[contains(@id, 'LabelStudyType')]").text
raw_study_eligibility = BROWSER.find_element_by_xpath("//*[contains(@id, 'LabelIndvitation')]").text
# Check if any of the field don't exist and, if they don't, then set their respective variable to unknown
if raw_study_info == "":
raw_study_info = "Unknown"
if raw_study_credits == "":
raw_study_credits = "Unknown"
if raw_study_description == "":
raw_study_description = "Unknown"
if raw_study_eligibility == "":
raw_study_eligibility = "Unknown"
# Set the contents of the messages
webhook.set_content(content="@everyone", title="Study Up!", url="https://ucalgary.sona"
"-systems.com/default.aspx",
color=0xFFA500)
# Attaches an author
webhook.set_author(name="RPS Study Notification Bot")
# Appends fields with study information
webhook.add_field(name="Study:", value=raw_study_info)
webhook.add_field(name="Credits:", value=raw_study_credits)
webhook.add_field(name="Description:", value=raw_study_description)
webhook.add_field(name="Eligibility:", value=raw_study_eligibility)
# Check if a notification has already been sent for the particular study
if raw_study_info not in STUDY_OMISSION_LIST:
webhook.send()
return raw_study_info, raw_study_credits, raw_study_description, raw_study_eligibility
def file_recording(study_info, study_credits, study_description, study_eligibility):
"""Record that a study was posted in a .txt file."""
if study_info not in STUDY_OMISSION_LIST:
with open("recordFile.txt", "a") as recordingFile:
recordingFile.write("Notification Sent: %s\n"
" Study Info: %s\n Credits: %s\n Description: %s\n Eligibility: %s\n"
% (str(strftime("%l:%M %p %z on %b %d, %Y")),
study_info, study_credits, study_description, study_eligibility))
def main():
if LOCAL_TESTING:
local_test()
if study_exists():
discord_notification()
else:
start_time, refresh_time = time()
hour = 0
start_RPS(USERNAME, PASSWORD)
try:
while True:
# Check if a study is up or not
if study_exists():
# Send notification if SEND_NOTIFICATION is true
if SEND_NOTIFICATION:
study_info, study_credits, study_description, study_eligibility = discord_notification()
# Record study information if RECORD_STUDIES is true
if RECORD_STUDIES:
file_recording(study_info, study_credits, study_description, study_eligibility)
STUDY_OMISSION_LIST.append(study_info)
refresh_time = time()
print("Study!\nMinutes since program execution:", (time() - start_time) / 60 + (hour * 60))
print()
# Make the program sleep for CODE_SLEEP_TIME number of minutes and then refresh the website.
sleep(CODE_SLEEP_TIME * 60)
BROWSER.refresh()
# Check if an hour has elapsed since the program began running
if (time() - start_time) / 60 >= 60:
print("\nHour Elapsed")
start_time = time()
hour += 1
# TODO: Fix the logic behind notifying of a study that was already notified about. A dictionary could be
# a potential solution, but the code would need some overall changing. A nested list wouldn't work
# because it the study info wouldn't be found in the main list as its in a nested list. So,
# go with a dict.
if (time() - refresh_time) / 60 >= 21:
for _ in range(len(STUDY_OMISSION_LIST)):
STUDY_OMISSION_LIST.pop()
refresh_time = time()
except KeyboardInterrupt:
print("Minutes since program execution:", (time() - start_time) / 60 + (hour * 60))
BROWSER.quit()
if __name__ == "__main__":
main()