├── .gitignore
├── API
├── Procfile
├── init.py
└── requirements.txt
├── LICENSE
├── README.md
├── assets
├── downloadIcon.png
├── excelFile.png
├── file.png
├── icon128.png
├── icon16.png
├── icon48.png
├── pdfFile.png
├── powerpointFile.png
└── wordFile.png
├── background.js
├── build
├── assets
│ ├── downloadIcon.png
│ ├── excelFile.png
│ ├── file.png
│ ├── icon128.png
│ ├── icon16.png
│ ├── icon48.png
│ ├── pdfFile.png
│ ├── powerpointFile.png
│ └── wordFile.png
├── background.js
├── content.js
├── fonts
│ ├── orbitronFont
│ │ └── static
│ │ │ └── Orbitron-Black.woff
│ └── poppinsFont
│ │ └── Poppins-SemiBold.woff
├── manifest.json
├── pop.html
└── styles.css
├── content.js
├── fonts
├── orbitronFont
│ └── static
│ │ └── Orbitron-Black.woff
└── poppinsFont
│ └── Poppins-SemiBold.woff
├── manifest.json
├── pop.html
└── styles.css
/.gitignore:
--------------------------------------------------------------------------------
1 | # packaged
2 | *.zip
--------------------------------------------------------------------------------
/API/Procfile:
--------------------------------------------------------------------------------
1 | web: gunicorn init:app
2 |
--------------------------------------------------------------------------------
/API/init.py:
--------------------------------------------------------------------------------
1 | import flask as Flask
2 | from flask import Flask, request, jsonify, Response, send_file
3 | from flask_cors import CORS
4 | import os
5 | import json
6 | import sys
7 | import wget
8 | import zipfile
9 | import io
10 | import pathlib
11 | import ssl
12 | import certifi
13 |
14 | app = Flask(__name__)
15 | app.use_x_sendfile = True
16 | CORS(app, support_credentials=True)
17 |
18 | #-----Routes------
19 |
20 | # default api endpoint [TEST]
21 | @app.route('/', methods=['GET'])
22 | def hello_world():
23 | response = jsonify({'data': 'Default API Endpoint'})
24 | return response
25 |
26 |
27 | # return article data sent from ext
28 | ssl._create_default_https_context = ssl._create_unverified_context
29 |
30 | @app.route('/RetPost', methods=['POST'])
31 | def return_article_post_test():
32 | print('called /RetPost')
33 | req = json.loads(request.data)
34 | for i in req["URL"]:
35 | print(i)
36 | request_zip(i)
37 | return req
38 |
39 |
40 | #download and zip file
41 | @app.route('/download-zip')
42 | def request_zip(url):
43 | for _ in url:
44 | a= os.path.dirname(__file__)
45 | wget.download(url, out=)
46 | base_path =pathlib.Path(a)
47 |
48 | data = io.BytesIO()
49 | with zipfile.ZipFile(data, mode='w') as z:
50 | for f_name in base_path.iterdir():
51 | z.write(f_name)
52 | print(f_name)
53 | data.seek(0)
54 |
55 | return send_file(
56 | data,
57 | mimetype='application/zip',
58 | as_attachment=True,
59 | attachment_filename='data.zip'
60 |
61 | )
62 |
63 | if __name__ == '__main__':
64 | app.run(debug=True)
65 |
66 |
--------------------------------------------------------------------------------
/API/requirements.txt:
--------------------------------------------------------------------------------
1 | Flask_Cors==3.0.9
2 | wget==3.2
3 | certifi==2020.4.5.2
4 | Flask==1.1.2
5 | gunicorn
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Microsoft Learn Student Ambassadors SRM
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # StudEaz for Google Classroom
2 | 
3 | 
4 | 
5 | 
6 |
7 | StudEaz is a browser extension to download multiple documents from a Google Classroom in a few clicks.
8 | ## Built With:
9 | | Software/ Language | Version |
10 | |----------|---------|
11 | | JavaScript | ES6 |
12 | | Google Chrome Browser | 87.0.4280.141 |
13 | | Visual Studio Code | 1.52 |
14 | ## Support:
15 | | Software | Tested with |
16 | |----------|-------------|
17 | | Google Chrome Browser | 87.0.4280.141 |
18 | | Microsoft Chromium Edge | 87.0.4280.141 |
19 | | Mozilla Firefox Browser | 84.0.2 |
20 | ## Installation:
21 | StudEaz is now available as a browser extension. It can be downloaded from here
22 | * [Chrome Store Link](https://chrome.google.com/webstore/detail/studeaz-for-google-classr/ddmpckcmhpnpgfcgfgeklphbbigknjgf/related?hl=en)
23 | * [Mozilla add-on store Link](https://addons.mozilla.org/en-US/firefox/addon/studeaz-for-google-classroom)
24 | * [Microsoft Edge Add-on Link](https://chrome.google.com/webstore/detail/studeaz-for-google-classr/ddmpckcmhpnpgfcgfgeklphbbigknjgf/related?hl=en)
25 |
26 | ## Usage:
27 | * In a Google Classroom, click on the extension's launcher on the toolbar of your browser.
28 |
29 | 
30 |
31 | * Click on "Extract Links".
32 |
33 | 
34 |
35 | * Select the files that you want to download using the checkbox.
36 | * Click on "Download Files". The selected files will get downloaded to your default Downloads folder (for Windows) and in the selected folder (for Macintosh)
37 |
38 | 
39 |
40 | ## Installing (from source code):
41 |
42 | * Clone this repository to your local machine.
43 | ```
44 | git clone https://github.com/MLSA-SRM/GCR-Extension
45 | ```
46 |
47 | - Enable Developer Mode in your browser (see Support for tested Browsers)
48 |
49 | - chrome://extensions for Google Chrome
50 | - edge://extensions for Chromium Edge
51 | - about:addons for Mozilla Firefox
52 |
53 |
54 |
55 | 
56 | - Use "Load Unpacked" and select folder "~/GCR-Extension-main".
57 |
58 | 
59 | 
60 |
61 | - Finally you should have successfully added our extension.
62 |
63 | 
64 |
65 |
66 |
67 | ## Troubleshooting:
68 |
69 | * In case of cases where empty .docx files are visible in the extension, reload the page and run the extension again.
70 |
71 | 
72 |
73 | * While running the extension in the incognito mode, it would display a 403 Forbidden error. In this case, log into Google Classroom into your browser and run the extension again.
74 |
75 | ## Contributors:
76 |
77 | * [Mihir Singh](https://github.com/mihirs16)
78 | * [Kushagra Gupta](https://github.com/KG-1510)
79 | * [Samarpan Das](https://github.com/SamarpanDas)
80 | * [Vidushi Gupta](https://github.com/Vidushi-Gupta)
81 |
--------------------------------------------------------------------------------
/assets/downloadIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSA-SRM/GCR-Extension/170a8f2450f43498f32642c4d158907731b4b2bb/assets/downloadIcon.png
--------------------------------------------------------------------------------
/assets/excelFile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSA-SRM/GCR-Extension/170a8f2450f43498f32642c4d158907731b4b2bb/assets/excelFile.png
--------------------------------------------------------------------------------
/assets/file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSA-SRM/GCR-Extension/170a8f2450f43498f32642c4d158907731b4b2bb/assets/file.png
--------------------------------------------------------------------------------
/assets/icon128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSA-SRM/GCR-Extension/170a8f2450f43498f32642c4d158907731b4b2bb/assets/icon128.png
--------------------------------------------------------------------------------
/assets/icon16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSA-SRM/GCR-Extension/170a8f2450f43498f32642c4d158907731b4b2bb/assets/icon16.png
--------------------------------------------------------------------------------
/assets/icon48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSA-SRM/GCR-Extension/170a8f2450f43498f32642c4d158907731b4b2bb/assets/icon48.png
--------------------------------------------------------------------------------
/assets/pdfFile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSA-SRM/GCR-Extension/170a8f2450f43498f32642c4d158907731b4b2bb/assets/pdfFile.png
--------------------------------------------------------------------------------
/assets/powerpointFile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSA-SRM/GCR-Extension/170a8f2450f43498f32642c4d158907731b4b2bb/assets/powerpointFile.png
--------------------------------------------------------------------------------
/assets/wordFile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSA-SRM/GCR-Extension/170a8f2450f43498f32642c4d158907731b4b2bb/assets/wordFile.png
--------------------------------------------------------------------------------
/background.js:
--------------------------------------------------------------------------------
1 | // Scrolls page automatically for upto 25 seconds
2 | function pageScroll() {
3 | var startTime = new Date().getTime();
4 | var interval = setInterval(function () {
5 | if (new Date().getTime() - startTime > 25000) {
6 | clearInterval(interval);
7 | buttonClicked();
8 | return;
9 | }
10 | window.scrollBy(0, 10000);
11 | }, 2000);
12 | }
13 | var titles = [];
14 | var fileDOM = [];
15 | function buttonClicked() {
16 | // Extracts the URLs for all the elements with the given class name having all the documents
17 | var anchorTags = document.getElementsByTagName("a");
18 | var hrefs = [];
19 | for (var i = 0; i < anchorTags.length; i++) {
20 | var hrefString = anchorTags[i].href;
21 |
22 | if (hrefString.includes("drive.google.com") && !hrefString.includes("drive.google.com/drive/folders/")) {
23 | if (!hrefs.includes(hrefString)) {
24 | hrefs.push(hrefString);
25 | var titleString = anchorTags[i].textContent;
26 | titles.push(titleString);
27 | }
28 | else if(hrefs.includes(hrefString)){
29 | fileDOM.push(anchorTags[i]);
30 | }
31 | }
32 | }
33 | var titleLinks = { hrefList: hrefs, titleList: titles };
34 |
35 | // Send the javascript object of title of document and link of document to the extension javascript file
36 | chrome.runtime.sendMessage(titleLinks);
37 | }
38 | // Receives request from content.js to scroll a document into view
39 | chrome.runtime.onMessage.addListener(function (response, sender, sendResponse) {
40 | var elementIndex = titles.indexOf(response);
41 | var element = fileDOM[elementIndex];
42 | element.scrollIntoView({
43 | behavior: "smooth",
44 | block: "center",
45 | inline: "nearest",
46 | });
47 | });
48 |
49 | // Function call to initiate auto page scrolling
50 | pageScroll();
51 |
--------------------------------------------------------------------------------
/build/assets/downloadIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSA-SRM/GCR-Extension/170a8f2450f43498f32642c4d158907731b4b2bb/build/assets/downloadIcon.png
--------------------------------------------------------------------------------
/build/assets/excelFile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSA-SRM/GCR-Extension/170a8f2450f43498f32642c4d158907731b4b2bb/build/assets/excelFile.png
--------------------------------------------------------------------------------
/build/assets/file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSA-SRM/GCR-Extension/170a8f2450f43498f32642c4d158907731b4b2bb/build/assets/file.png
--------------------------------------------------------------------------------
/build/assets/icon128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSA-SRM/GCR-Extension/170a8f2450f43498f32642c4d158907731b4b2bb/build/assets/icon128.png
--------------------------------------------------------------------------------
/build/assets/icon16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSA-SRM/GCR-Extension/170a8f2450f43498f32642c4d158907731b4b2bb/build/assets/icon16.png
--------------------------------------------------------------------------------
/build/assets/icon48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSA-SRM/GCR-Extension/170a8f2450f43498f32642c4d158907731b4b2bb/build/assets/icon48.png
--------------------------------------------------------------------------------
/build/assets/pdfFile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSA-SRM/GCR-Extension/170a8f2450f43498f32642c4d158907731b4b2bb/build/assets/pdfFile.png
--------------------------------------------------------------------------------
/build/assets/powerpointFile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSA-SRM/GCR-Extension/170a8f2450f43498f32642c4d158907731b4b2bb/build/assets/powerpointFile.png
--------------------------------------------------------------------------------
/build/assets/wordFile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSA-SRM/GCR-Extension/170a8f2450f43498f32642c4d158907731b4b2bb/build/assets/wordFile.png
--------------------------------------------------------------------------------
/build/background.js:
--------------------------------------------------------------------------------
1 | function pageScroll(){var e=(new Date).getTime(),t=setInterval(function(){if((new Date).getTime()-e>25e3)return clearInterval(t),void buttonClicked();window.scrollBy(0,1e4)},2e3)}var titles=[],fileDOM=[];function buttonClicked(){for(var e=document.getElementsByTagName("a"),t=[],i=0;i{document.getElementById("runScript").addEventListener("click",getLinks)});
--------------------------------------------------------------------------------
/build/fonts/orbitronFont/static/Orbitron-Black.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSA-SRM/GCR-Extension/170a8f2450f43498f32642c4d158907731b4b2bb/build/fonts/orbitronFont/static/Orbitron-Black.woff
--------------------------------------------------------------------------------
/build/fonts/poppinsFont/Poppins-SemiBold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSA-SRM/GCR-Extension/170a8f2450f43498f32642c4d158907731b4b2bb/build/fonts/poppinsFont/Poppins-SemiBold.woff
--------------------------------------------------------------------------------
/build/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "manifest_version": 2,
3 | "name": "StudEaz for Google Classroom",
4 | "version": "1.3",
5 | "description": "Get rid of all the hassle of manually downloading materials from Google Classroom. Download multiple documents in a few clicks.",
6 | "permissions": [
7 | "activeTab"
8 | ],
9 | "content_scripts": [
10 | {
11 | "matches": [
12 | "https://classroom.google.com/*",
13 | "http://classroom.google.com/*"
14 | ],
15 | "js": [
16 | "content.js"
17 | ]
18 | }
19 | ],
20 | "icons": {
21 | "16": "assets/icon16.png",
22 | "48": "assets/icon48.png",
23 | "128": "assets/icon128.png"
24 | },
25 | "browser_action": {
26 | "default_icon": "assets/icon16.png",
27 | "default_popup": "pop.html",
28 | "default_title": "StudEaz for Google Classroom"
29 | }
30 | }
--------------------------------------------------------------------------------
/build/pop.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | StudEaz
14 | StudEaz
15 |
16 |
17 | Download all your documents.
Just in few click!
18 |
19 |
20 |
21 |
22 |
23 |
24 | Select All
25 |
26 |
27 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/build/styles.css:
--------------------------------------------------------------------------------
1 | /* orbitron-900*/
2 | @font-face {
3 | font-family: 'Orbitron';
4 | font-style: normal;
5 | font-weight: 900;
6 | src: url('fonts/orbitronFont/static/Orbitron-Black.woff') format('woff'); /* Modern Browsers */
7 | }
8 | /* poppins-600*/
9 | @font-face {
10 | font-family: 'Poppins';
11 | font-style: normal;
12 | font-weight: 600;
13 | src: url('fonts/poppinsFont/Poppins-SemiBold.woff') format('woff'); /* Modern Browsers */
14 | }
15 | html,
16 | body {
17 | margin: 0;
18 | min-height: 500px;
19 | width: 350px;
20 | background-color: #121b53;
21 | color: #ecf4ff;
22 | font-family: "Poppins", sans-serif;
23 | max-width: 100%;
24 | overflow-x: hidden !important;
25 | overflow: overlay;
26 | scrollbar-color: #444649 rgba(255, 255, 255, 0);
27 | scrollbar-width: thin;
28 | }
29 | h1 {
30 | font-family: "Orbitron", sans-serif;
31 | width: 191px;
32 | height: 50px;
33 | margin: 60px 80px 40px 80px;
34 | font-weight: 900;
35 | font-size: 40px;
36 | line-height: 50px;
37 | }
38 | #titleEaz {
39 | font-family: "Orbitron", sans-serif;
40 | color: #14cae4;
41 | font-weight: 900;
42 | font-size: 40px;
43 | line-height: 50px;
44 | margin: 0;
45 | }
46 | #titleSmall {
47 | display: none;
48 | font-family: "Orbitron", sans-serif;
49 | font-weight: 900;
50 | font-size: 18px;
51 | line-height: 23px;
52 | padding-left: 20px;
53 | text-align: left;
54 | font-size: 1.5rem;
55 | }
56 | #titleEazSmall {
57 | font-family: "Orbitron", sans-serif;
58 | color: #14cae4;
59 | }
60 | h2 {
61 | text-align: center;
62 | width: 350px;
63 | height: 50px;
64 | margin: auto;
65 | padding-top: 35px;
66 | margin-left: -2px;
67 | font-size: 1rem;
68 | padding-left: 3px;
69 | padding-right: 14px;
70 | }
71 | #runScript {
72 | -webkit-border-radius: 10px;
73 | -moz-border-radius: 10px;
74 | border-radius: 10px;
75 | line-height: 42px;
76 | color: #001623;
77 | width: 142px;
78 | font-size: 18px;
79 | font-weight: 600;
80 | font-family: "Poppins", sans-serif;
81 | padding: 7px;
82 | background-color: #14cae4;
83 | border: solid #14cae4 1px;
84 | text-decoration: none;
85 | display: inline-block;
86 | cursor: pointer;
87 | text-align: center;
88 | margin: 70px 100px 130px 100px;
89 | }
90 | #runScript:hover {
91 | background: #05a3bb;
92 | border: solid #05a3bb 1px;
93 | -webkit-border-radius: 10px;
94 | -moz-border-radius: 10px;
95 | border-radius: 10px;
96 | text-decoration: none;
97 | }
98 | #links {
99 | text-align: center;
100 | line-height: 1.4rem;
101 | font-size: 18px;
102 | }
103 | li:hover {
104 | cursor: pointer;
105 | }
106 | .check {
107 | display: inline-block;
108 | transform: translate(280px, -23px);
109 | }
110 | #titleList {
111 | line-height: 1.4rem;
112 | font-size: 1rem;
113 | margin-bottom: 0;
114 | }
115 | #selectedCount {
116 | text-align: center;
117 | font-size: 1.2rem;
118 | }
119 | #SAText {
120 | display: none;
121 | margin-left: 42%;
122 | transform: translate(19px, -23px);
123 | font-size: 0.8rem;
124 | }
125 | #selAllCheck {
126 | display: none;
127 | margin-left: 40%;
128 | }
129 | #dwnbtn {
130 | display: none;
131 | -webkit-border-radius: 6px;
132 | -moz-border-radius: 6px;
133 | border-radius: 6px;
134 | height: 50px;
135 | line-height: 1rem;
136 | color: #fff;
137 | font-family: "Poppins", sans-serif;
138 | width: 195px;
139 | font-size: 16px;
140 | font-weight: 600;
141 | background-color: #2ccc33;
142 | border: solid #2ccc33 1px;
143 | text-decoration: none;
144 | cursor: pointer;
145 | text-align: center;
146 | padding-bottom: 40px;
147 | margin: 40px 50px 5px 85px;
148 | }
149 | #dwnbtn:hover {
150 | background: #23ae28;
151 | border: solid #23ae28 1px;
152 | -webkit-border-radius: 6px;
153 | -moz-border-radius: 6px;
154 | border-radius: 6px;
155 | text-decoration: none;
156 | }
157 | #downloadImg {
158 | background-color: transparent;
159 | transform: translate(-2px, 7px);
160 | margin-top: 5px;
161 | }
162 | .titleBox {
163 | display: none;
164 | background-color: #fff;
165 | color: #000;
166 | padding-top: 20px;
167 | margin-bottom: 0;
168 | }
169 | .cancelBox {
170 | display: none;
171 | background-color: #121b53;
172 | margin-top: 0;
173 | padding-top: 20px;
174 | padding-bottom: 20px;
175 | text-align: center;
176 | }
177 | #cancel {
178 | -webkit-border-radius: 6px;
179 | -moz-border-radius: 6px;
180 | border-radius: 6px;
181 | height: 30px;
182 | line-height: 26px;
183 | color: #f8f8f8;
184 | font-family: "Poppins", sans-serif;
185 | width: 102px;
186 | font-size: 19px;
187 | font-weight: 600;
188 | padding: 3px;
189 | background-color: #d93c3c;
190 | border: solid #d93c3c 1px;
191 | text-decoration: none;
192 | cursor: pointer;
193 | text-align: center;
194 | }
195 | #cancel:hover {
196 | background: #9a2929;
197 | border: solid #9a2929 1px;
198 | -webkit-border-radius: 6px;
199 | -moz-border-radius: 6px;
200 | border-radius: 6px;
201 | text-decoration: none;
202 | }
203 | .loadingAni {
204 | margin-top: 9.5rem;
205 | display: none;
206 | }
207 | .wrapper {
208 | width: 200px;
209 | height: 60px;
210 | position: absolute;
211 | padding-top: 1rem;
212 | padding-bottom: 4rem;
213 | left: 50%;
214 | top: 50%;
215 | transform: translate(-50%, -50%);
216 | }
217 | .circle {
218 | width: 20px;
219 | height: 20px;
220 | position: absolute;
221 | border-radius: 50%;
222 | background-color: #14cae4;
223 | left: 15%;
224 | transform-origin: 50%;
225 | animation: circle 0.5s alternate infinite ease;
226 | }
227 | @keyframes circle {
228 | 0% {
229 | top: 60px;
230 | height: 5px;
231 | border-radius: 50px 50px 25px 25px;
232 | transform: scaleX(1.7);
233 | }
234 | 40% {
235 | height: 20px;
236 | border-radius: 50%;
237 | transform: scaleX(1);
238 | }
239 | 100% {
240 | top: 0%;
241 | }
242 | }
243 | .circle:nth-child(2) {
244 | left: 45%;
245 | animation-delay: 0.2s;
246 | }
247 | .circle:nth-child(3) {
248 | left: auto;
249 | right: 15%;
250 | animation-delay: 0.3s;
251 | }
252 | .shadow {
253 | width: 20px;
254 | height: 4px;
255 | border-radius: 50%;
256 | background-color: rgba(0, 0, 0, 0.5);
257 | position: absolute;
258 | top: 62px;
259 | transform-origin: 50%;
260 | z-index: -1;
261 | left: 15%;
262 | filter: blur(1px);
263 | animation: shadow 0.5s alternate infinite ease;
264 | }
265 | @keyframes shadow {
266 | 0% {
267 | transform: scaleX(1.5);
268 | }
269 | 40% {
270 | transform: scaleX(1);
271 | opacity: 0.7;
272 | }
273 | 100% {
274 | transform: scaleX(0.2);
275 | opacity: 0.4;
276 | }
277 | }
278 | .shadow:nth-child(4) {
279 | left: 45%;
280 | animation-delay: 0.2s;
281 | }
282 | .shadow:nth-child(5) {
283 | left: auto;
284 | right: 15%;
285 | animation-delay: 0.3s;
286 | }
287 | input[type="checkbox"] {
288 | position: relative;
289 | width: 1.5em;
290 | height: 1.5em;
291 | color: #363839;
292 | border: 2px solid #121b53;
293 | border-radius: 2px;
294 | appearance: none;
295 | margin-right: 3px;
296 | margin-left: -2px;
297 | outline: 0;
298 | cursor: pointer;
299 | transition: background 175ms cubic-bezier(0.1, 0.1, 0.25, 1);
300 | }
301 | input[type="checkbox"]::before {
302 | position: absolute;
303 | content: "";
304 | display: block;
305 | top: -2px;
306 | left: 4px;
307 | width: 7px;
308 | height: 14px;
309 | border-style: solid;
310 | border-color: #fff;
311 | border-width: 0 2px 2px 0;
312 | transform: rotate(45deg);
313 | opacity: 0;
314 | }
315 | input[type="checkbox"]:checked {
316 | color: #fff;
317 | border-color: #06842c;
318 | background: #06842c;
319 | }
320 | input[type="checkbox"]:checked::before {
321 | opacity: 1;
322 | }
323 | #selAllCheck {
324 | border: 2px solid #fff;
325 | }
326 | #selAllCheck:checked {
327 | border-color: #06842c;
328 | background: #06842c;
329 | }
330 | ::-webkit-scrollbar {
331 | width: 7px;
332 | z-index: 10px;
333 | }
334 | ::-webkit-scrollbar-track {
335 | border-radius: 2px;
336 | background-color: transparent;
337 | }
338 | ::-webkit-scrollbar-thumb {
339 | background: #444649;
340 | border-radius: 2px;
341 | }
342 | ::-webkit-scrollbar-thumb:hover {
343 | background: #252729;
344 | }
345 |
--------------------------------------------------------------------------------
/content.js:
--------------------------------------------------------------------------------
1 | // Waits for receiving the list of extracted links from background.js
2 | chrome.runtime.onMessage.addListener(function (response, sender, sendResponse) {
3 | // Toggling visibility state of various HTML elements ONLY when they are loaded
4 |
5 | var loadingAnimation = document.querySelector(".loadingAni");
6 | if (loadingAnimation) {
7 | document.querySelector(".loadingAni").style.display = "none";
8 | }
9 | document.querySelector("h1").style.display = "none";
10 |
11 | var titlesmall = document.querySelector("#titleSmall");
12 | if (titlesmall) {
13 | document.querySelector("#titleSmall").style.display = "block";
14 | }
15 |
16 | var downloadButton = document.querySelector("#dwnbtn");
17 | if (downloadButton) {
18 | document.querySelector("#dwnbtn").style.display = "block";
19 | }
20 |
21 | var titlebox = document.querySelector(".titleBox");
22 | if (titlebox) {
23 | document.querySelector(".titleBox").style.display = "block";
24 | }
25 |
26 | var cancelbox = document.querySelector(".cancelBox");
27 | if (cancelbox) {
28 | document.querySelector(".cancelBox").style.backgroundColor = "#ffffff";
29 | }
30 |
31 | var sh = document.querySelector("#subheading");
32 | if (sh) {
33 | document.querySelector("#subheading").style.fontSize = "2rem";
34 | }
35 |
36 | var ul = document.getElementById("titleList");
37 | if (response["titleList"]) {
38 | for (var i = 0; i < response["titleList"].length; i++) {
39 | console.log(response);
40 | // Create a new list item for every document extracted from page
41 | var li = document.createElement("li");
42 | li.setAttribute("class", "titleItems");
43 | var checkBox = document.createElement("INPUT");
44 | checkBox.setAttribute("type", "checkbox");
45 | checkBox.setAttribute("value", i);
46 | checkBox.className = "check";
47 |
48 | // Parse the extension name received and display the corresponding filetype icon
49 | var fileName = response["titleList"][i];
50 | var filePath = "";
51 | if (fileName.includes(".xlsx") || fileName.includes(".xls")) {
52 | filePath = "url('assets/excelFile.png')";
53 | }
54 | else if (fileName.includes(".docx") || fileName.includes(".doc")) {
55 | filePath = "url('assets/wordFile.png')";
56 | }
57 | else if (fileName.includes(".pptx") || fileName.includes(".ppt")) {
58 | filePath = "url('assets/powerpointFile.png')";
59 | }
60 | else if (fileName.includes(".pdf")) {
61 | filePath = "url('assets/pdfFile.png')";
62 | }
63 | else {
64 | filePath = "url('assets/file.png')";
65 | }
66 | // Appends newly made list item of file names into the unordered list
67 | li.appendChild(document.createTextNode(response["titleList"][i]));
68 | li.style.listStyleImage = filePath;
69 | ul.appendChild(li);
70 | ul.appendChild(checkBox);
71 | document.querySelector("h2").innerHTML = (i + 1) + " files found!"
72 | }
73 | document.querySelector("#dwnbtn").style.display = "block";
74 | document.querySelector("#selAllCheck").style.display = "block";
75 | document.querySelector("#SAText").style.display = "block";
76 |
77 | document.getElementById("selAllCheck").addEventListener("click", selectAllFunc);
78 |
79 |
80 | // Function to select all/deselect all checkboxes
81 | function selectAllFunc() {
82 | if (this.checked == true) {
83 | for (var i = 0; i < response["titleList"].length; i++) {
84 | document.querySelectorAll(".check")[i].checked = true;
85 | document.getElementById("selectedCount").innerHTML = response["titleList"].length + " / " + response["titleList"].length + " selected";
86 |
87 | }
88 | }
89 | else if (this.checked == false) {
90 | for (var i = 0; i < response["titleList"].length; i++) {
91 | document.querySelectorAll(".check")[i].checked = false;
92 | document.getElementById("selectedCount").innerHTML = "0" + " / " + response["titleList"].length + " selected";
93 |
94 | }
95 | }
96 | }
97 |
98 |
99 | var numberOfCheckedItems = 0;
100 | for (var j = 0; j < response["titleList"].length; j++) {
101 | document.querySelectorAll(".check")[j].addEventListener("click", checkedCount);
102 | }
103 |
104 | // Counter for number of items that are selected
105 | function checkedCount() {
106 | if (this.checked == true) {
107 | ++numberOfCheckedItems;
108 | }
109 | else if (this.checked == false) {
110 | --numberOfCheckedItems;
111 | }
112 | document.getElementById("selectedCount").innerHTML = numberOfCheckedItems + " / " + response["titleList"].length + " selected";
113 | }
114 |
115 | // Function triggered when "Download Files" button is clicked
116 | document.getElementById("dwnbtn").addEventListener("click", function () {
117 | var checkboxes = document.getElementsByClassName("check");
118 | var selectedFiles = [];
119 | var selectedLinks = [];
120 | for (var i = 0; i < checkboxes.length; i++) {
121 | if (checkboxes[i].checked) {
122 | selectedFiles.push(parseInt(checkboxes[i].value));
123 | }
124 |
125 | }
126 | for (j = 0; j < selectedFiles.length; j++) {
127 | var selectedValue = selectedFiles[j];
128 | selectedLinks.push(response["hrefList"][selectedValue]);
129 | }
130 |
131 | // Manipulation of drive links to make it downloadable document
132 | var downloadWindows = [];
133 | for (var k = 0; k < selectedFiles.length; k++) {
134 | var str = selectedLinks[k];
135 | var downloadableLink = str.replace("open", "uc");
136 | downloadableLink = downloadableLink + "&export=download";
137 | var downloadWindow = window.open(downloadableLink, "_blank", "fullscreen=yes");
138 | downloadWindows.push(downloadWindow);
139 |
140 | }
141 | setTimeout(function () {
142 | for (var l = 0; l < downloadWindows.length; l++) {
143 | downloadWindows[l].close();
144 | }
145 | }, 20000);
146 | });
147 |
148 | // Function to scrollIntoView the document name that is clicked
149 | for (var j = 0; j < response["titleList"].length; j++) {
150 | document.querySelectorAll(".titleItems")[j].addEventListener("click", sendFileName);
151 | }
152 | function sendFileName() {
153 | var fileClicked = this.innerHTML;
154 | chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
155 | chrome.tabs.sendMessage(tabs[0].id, fileClicked)
156 | });
157 | }
158 | }
159 | });
160 |
161 | // Reload the extension HTML page when cancel button is clicked
162 | var cancelElement = document.getElementById("cancel");
163 | if (cancelElement) {
164 | document.getElementById("cancel").addEventListener("click", function () {
165 | chrome.tabs.executeScript({ code: `location.reload();` });
166 | location.reload();
167 | });
168 | }
169 |
170 | document.addEventListener("DOMContentLoaded", () => { document.getElementById("runScript").addEventListener("click", getLinks) });
171 |
172 | // Function executed to run background scripts
173 | function getLinks() {
174 | chrome.tabs.executeScript({ file: "background.js" });
175 | document.querySelector("h2").innerHTML = "Please wait while we scroll through the page and extract links!";
176 | document.getElementById("runScript").style.display = "none";
177 | document.querySelector(".loadingAni").style.display = "block";
178 | document.querySelector(".cancelBox").style.display = "block";
179 |
180 | }
181 |
182 |
183 |
184 |
--------------------------------------------------------------------------------
/fonts/orbitronFont/static/Orbitron-Black.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSA-SRM/GCR-Extension/170a8f2450f43498f32642c4d158907731b4b2bb/fonts/orbitronFont/static/Orbitron-Black.woff
--------------------------------------------------------------------------------
/fonts/poppinsFont/Poppins-SemiBold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSA-SRM/GCR-Extension/170a8f2450f43498f32642c4d158907731b4b2bb/fonts/poppinsFont/Poppins-SemiBold.woff
--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "manifest_version": 2,
3 | "name": "StudEaz for Google Classroom",
4 | "version": "1.3",
5 | "description": "Get rid of all the hassle of manually downloading materials from Google Classroom. Download multiple documents in a few clicks.",
6 |
7 | "permissions":
8 | [
9 | "activeTab"
10 | ],
11 |
12 | "content_scripts":
13 | [
14 | {
15 | "matches":
16 | [
17 | "https://classroom.google.com/*",
18 | "http://classroom.google.com/*"
19 | ],
20 |
21 | "js":
22 | [
23 | "content.js"
24 | ]
25 | }
26 | ],
27 |
28 | "icons":
29 | {
30 | "16": "assets/icon16.png",
31 | "48": "assets/icon48.png",
32 | "128": "assets/icon128.png"
33 | },
34 |
35 | "browser_action":
36 | {
37 | "default_icon": "assets/icon16.png",
38 | "default_popup": "pop.html",
39 | "default_title": "StudEaz for Google Classroom"
40 | }
41 | }
--------------------------------------------------------------------------------
/pop.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | StudEaz
14 | StudEaz
15 |
16 |
17 | Download all your documents.
Just in few click!
18 |
19 |
20 |
21 |
22 |
23 |
24 | Select All
25 |
26 |
27 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/styles.css:
--------------------------------------------------------------------------------
1 | /* orbitron-900*/
2 | @font-face {
3 | font-family: 'Orbitron';
4 | font-style: normal;
5 | font-weight: 900;
6 | src: url('fonts/orbitronFont/static/Orbitron-Black.woff') format('woff'); /* Modern Browsers */
7 | }
8 | /* poppins-600*/
9 | @font-face {
10 | font-family: 'Poppins';
11 | font-style: normal;
12 | font-weight: 600;
13 | src: url('fonts/poppinsFont/Poppins-SemiBold.woff') format('woff'); /* Modern Browsers */
14 | }
15 | html,
16 | body {
17 | margin: 0;
18 | min-height: 500px;
19 | width: 350px;
20 | background-color: #121b53;
21 | color: #ecf4ff;
22 | font-family: "Poppins", sans-serif;
23 | max-width: 100%;
24 | overflow-x: hidden !important;
25 | overflow: overlay;
26 | scrollbar-color: #444649 rgba(255, 255, 255, 0);
27 | scrollbar-width: thin;
28 | }
29 | h1 {
30 | font-family: "Orbitron", sans-serif;
31 | width: 191px;
32 | height: 50px;
33 | margin: 60px 80px 40px 80px;
34 | font-weight: 900;
35 | font-size: 40px;
36 | line-height: 50px;
37 | }
38 | #titleEaz {
39 | font-family: "Orbitron", sans-serif;
40 | color: #14cae4;
41 | font-weight: 900;
42 | font-size: 40px;
43 | line-height: 50px;
44 | margin: 0;
45 | }
46 | #titleSmall {
47 | display: none;
48 | font-family: "Orbitron", sans-serif;
49 | font-weight: 900;
50 | font-size: 18px;
51 | line-height: 23px;
52 | padding-left: 20px;
53 | text-align: left;
54 | font-size: 1.5rem;
55 | }
56 | #titleEazSmall {
57 | font-family: "Orbitron", sans-serif;
58 | color: #14cae4;
59 | }
60 | h2 {
61 | text-align: center;
62 | width: 350px;
63 | height: 50px;
64 | margin: auto;
65 | padding-top: 35px;
66 | margin-left: -2px;
67 | font-size: 1rem;
68 | padding-left: 3px;
69 | padding-right: 14px;
70 | }
71 | #runScript {
72 | -webkit-border-radius: 10px;
73 | -moz-border-radius: 10px;
74 | border-radius: 10px;
75 | line-height: 42px;
76 | color: #001623;
77 | width: 142px;
78 | font-size: 18px;
79 | font-weight: 600;
80 | font-family: "Poppins", sans-serif;
81 | padding: 7px;
82 | background-color: #14cae4;
83 | border: solid #14cae4 1px;
84 | text-decoration: none;
85 | display: inline-block;
86 | cursor: pointer;
87 | text-align: center;
88 | margin: 70px 100px 130px 100px;
89 | }
90 | #runScript:hover {
91 | background: #05a3bb;
92 | border: solid #05a3bb 1px;
93 | -webkit-border-radius: 10px;
94 | -moz-border-radius: 10px;
95 | border-radius: 10px;
96 | text-decoration: none;
97 | }
98 | #links {
99 | text-align: center;
100 | line-height: 1.4rem;
101 | font-size: 18px;
102 | }
103 | li:hover {
104 | cursor: pointer;
105 | }
106 | .check {
107 | display: inline-block;
108 | transform: translate(280px, -23px);
109 | }
110 | #titleList {
111 | line-height: 1.4rem;
112 | font-size: 1rem;
113 | margin-bottom: 0;
114 | }
115 | #selectedCount {
116 | text-align: center;
117 | font-size: 1.2rem;
118 | }
119 | #SAText {
120 | display: none;
121 | margin-left: 42%;
122 | transform: translate(19px, -23px);
123 | font-size: 0.8rem;
124 | }
125 | #selAllCheck {
126 | display: none;
127 | margin-left: 40%;
128 | }
129 | #dwnbtn {
130 | display: none;
131 | -webkit-border-radius: 6px;
132 | -moz-border-radius: 6px;
133 | border-radius: 6px;
134 | height: 50px;
135 | line-height: 1rem;
136 | color: #fff;
137 | font-family: "Poppins", sans-serif;
138 | width: 195px;
139 | font-size: 16px;
140 | font-weight: 600;
141 | background-color: #2ccc33;
142 | border: solid #2ccc33 1px;
143 | text-decoration: none;
144 | cursor: pointer;
145 | text-align: center;
146 | padding-bottom: 40px;
147 | margin: 40px 50px 5px 85px;
148 | }
149 | #dwnbtn:hover {
150 | background: #23ae28;
151 | border: solid #23ae28 1px;
152 | -webkit-border-radius: 6px;
153 | -moz-border-radius: 6px;
154 | border-radius: 6px;
155 | text-decoration: none;
156 | }
157 | #downloadImg {
158 | background-color: transparent;
159 | transform: translate(-2px, 7px);
160 | margin-top: 5px;
161 | }
162 | .titleBox {
163 | display: none;
164 | background-color: #fff;
165 | color: #000;
166 | padding-top: 20px;
167 | margin-bottom: 0;
168 | }
169 | .cancelBox {
170 | display: none;
171 | background-color: #121b53;
172 | margin-top: 0;
173 | padding-top: 20px;
174 | padding-bottom: 20px;
175 | text-align: center;
176 | }
177 | #cancel {
178 | -webkit-border-radius: 6px;
179 | -moz-border-radius: 6px;
180 | border-radius: 6px;
181 | height: 30px;
182 | line-height: 26px;
183 | color: #f8f8f8;
184 | font-family: "Poppins", sans-serif;
185 | width: 102px;
186 | font-size: 19px;
187 | font-weight: 600;
188 | padding: 3px;
189 | background-color: #d93c3c;
190 | border: solid #d93c3c 1px;
191 | text-decoration: none;
192 | cursor: pointer;
193 | text-align: center;
194 | }
195 | #cancel:hover {
196 | background: #9a2929;
197 | border: solid #9a2929 1px;
198 | -webkit-border-radius: 6px;
199 | -moz-border-radius: 6px;
200 | border-radius: 6px;
201 | text-decoration: none;
202 | }
203 | .loadingAni {
204 | margin-top: 9.5rem;
205 | display: none;
206 | }
207 | .wrapper {
208 | width: 200px;
209 | height: 60px;
210 | position: absolute;
211 | padding-top: 1rem;
212 | padding-bottom: 4rem;
213 | left: 50%;
214 | top: 50%;
215 | transform: translate(-50%, -50%);
216 | }
217 | .circle {
218 | width: 20px;
219 | height: 20px;
220 | position: absolute;
221 | border-radius: 50%;
222 | background-color: #14cae4;
223 | left: 15%;
224 | transform-origin: 50%;
225 | animation: circle 0.5s alternate infinite ease;
226 | }
227 | @keyframes circle {
228 | 0% {
229 | top: 60px;
230 | height: 5px;
231 | border-radius: 50px 50px 25px 25px;
232 | transform: scaleX(1.7);
233 | }
234 | 40% {
235 | height: 20px;
236 | border-radius: 50%;
237 | transform: scaleX(1);
238 | }
239 | 100% {
240 | top: 0%;
241 | }
242 | }
243 | .circle:nth-child(2) {
244 | left: 45%;
245 | animation-delay: 0.2s;
246 | }
247 | .circle:nth-child(3) {
248 | left: auto;
249 | right: 15%;
250 | animation-delay: 0.3s;
251 | }
252 | .shadow {
253 | width: 20px;
254 | height: 4px;
255 | border-radius: 50%;
256 | background-color: rgba(0, 0, 0, 0.5);
257 | position: absolute;
258 | top: 62px;
259 | transform-origin: 50%;
260 | z-index: -1;
261 | left: 15%;
262 | filter: blur(1px);
263 | animation: shadow 0.5s alternate infinite ease;
264 | }
265 | @keyframes shadow {
266 | 0% {
267 | transform: scaleX(1.5);
268 | }
269 | 40% {
270 | transform: scaleX(1);
271 | opacity: 0.7;
272 | }
273 | 100% {
274 | transform: scaleX(0.2);
275 | opacity: 0.4;
276 | }
277 | }
278 | .shadow:nth-child(4) {
279 | left: 45%;
280 | animation-delay: 0.2s;
281 | }
282 | .shadow:nth-child(5) {
283 | left: auto;
284 | right: 15%;
285 | animation-delay: 0.3s;
286 | }
287 | input[type="checkbox"] {
288 | position: relative;
289 | width: 1.5em;
290 | height: 1.5em;
291 | color: #363839;
292 | border: 2px solid #121b53;
293 | border-radius: 2px;
294 | appearance: none;
295 | margin-right: 3px;
296 | margin-left: -2px;
297 | outline: 0;
298 | cursor: pointer;
299 | transition: background 175ms cubic-bezier(0.1, 0.1, 0.25, 1);
300 | }
301 | input[type="checkbox"]::before {
302 | position: absolute;
303 | content: "";
304 | display: block;
305 | top: -2px;
306 | left: 4px;
307 | width: 7px;
308 | height: 14px;
309 | border-style: solid;
310 | border-color: #fff;
311 | border-width: 0 2px 2px 0;
312 | transform: rotate(45deg);
313 | opacity: 0;
314 | }
315 | input[type="checkbox"]:checked {
316 | color: #fff;
317 | border-color: #06842c;
318 | background: #06842c;
319 | }
320 | input[type="checkbox"]:checked::before {
321 | opacity: 1;
322 | }
323 | #selAllCheck {
324 | border: 2px solid #fff;
325 | }
326 | #selAllCheck:checked {
327 | border-color: #06842c;
328 | background: #06842c;
329 | }
330 | ::-webkit-scrollbar {
331 | width: 7px;
332 | z-index: 10px;
333 | }
334 | ::-webkit-scrollbar-track {
335 | border-radius: 2px;
336 | background-color: transparent;
337 | }
338 | ::-webkit-scrollbar-thumb {
339 | background: #444649;
340 | border-radius: 2px;
341 | }
342 | ::-webkit-scrollbar-thumb:hover {
343 | background: #252729;
344 | }
345 |
--------------------------------------------------------------------------------