diff --git a/classquiz/config.py b/classquiz/config.py index 49a8476..50f8cdd 100644 --- a/classquiz/config.py +++ b/classquiz/config.py @@ -71,6 +71,7 @@ class Settings(BaseSettings): async def initialize_arq(): + # skipcq: PYL-W0603 global arq arq = await create_pool(RedisSettings.from_dsn(settings.redis)) @@ -80,8 +81,6 @@ def settings() -> Settings: return Settings() -# asyncio.run(initialize_arq()) - pool = redis_lib.ConnectionPool().from_url(settings().redis) redis: redis_base_lib.client.Redis = redis_lib.Redis(connection_pool=pool) diff --git a/classquiz/db/models.py b/classquiz/db/models.py index 7d3ef0f..3352fa8 100644 --- a/classquiz/db/models.py +++ b/classquiz/db/models.py @@ -297,7 +297,7 @@ class GameInLobby(BaseModel): game_id: uuid.UUID -# +# skipcq: PY-W0069 # class UserProfileLinks(ormar.Model): # id: int = ormar.Integer(primary_key=True, autoincrement=True) # user: Optional[User] = ormar.ForeignKey(User) diff --git a/classquiz/db/quiztivity.py b/classquiz/db/quiztivity.py index cf8c295..bc355de 100644 --- a/classquiz/db/quiztivity.py +++ b/classquiz/db/quiztivity.py @@ -41,10 +41,3 @@ class QuizTivityPage(BaseModel): title: str | None type: QuizTivityTypes data: Pdf | Memory | Markdown - - # @validator("type") - # def match_type_to_data_type(cls, v, values, **kwargs): - # print(values) - # if TYPE_CLASS_LIST[v] != type(values["data"]): - # raise ValueError("Specified Type doesn't match real data type") - # pass diff --git a/classquiz/oauth/custom.py b/classquiz/oauth/custom.py index 509515f..5f10c99 100644 --- a/classquiz/oauth/custom.py +++ b/classquiz/oauth/custom.py @@ -88,8 +88,9 @@ async def auth(request: Request, response: Response): google_uid=user_data.sub.hex, avatar=gzipped_user_avatar(), ) + # skipcq: PYL-W0703 except Exception as e: - if type(e) == asyncpg.exceptions.UniqueViolationError: + if type(e) is asyncpg.exceptions.UniqueViolationError: error = True counter = 1 while error: diff --git a/classquiz/oauth/github.py b/classquiz/oauth/github.py index 0bad0e7..80471b4 100644 --- a/classquiz/oauth/github.py +++ b/classquiz/oauth/github.py @@ -116,8 +116,9 @@ async def auth(request: Request, response: Response): auth_type=UserAuthTypes.GITHUB, avatar=gzipped_user_avatar(), ) + # skipcq: PYL-W0703 except Exception as e: - if type(e) == asyncpg.exceptions.UniqueViolationError: + if type(e) is asyncpg.exceptions.UniqueViolationError: error = True counter = 1 while error: diff --git a/classquiz/oauth/google.py b/classquiz/oauth/google.py index 3bf1d88..1c590d0 100644 --- a/classquiz/oauth/google.py +++ b/classquiz/oauth/google.py @@ -90,8 +90,9 @@ async def auth(request: Request, response: Response): google_uid=user_data.sub, avatar=gzipped_user_avatar(), ) + # skipcq: PYL-W0703 except Exception as e: - if type(e) == asyncpg.exceptions.UniqueViolationError: + if type(e) is asyncpg.exceptions.UniqueViolationError: error = True counter = 1 while error: diff --git a/classquiz/routers/avatar.py b/classquiz/routers/avatar.py index 26967fe..e80cf88 100644 --- a/classquiz/routers/avatar.py +++ b/classquiz/routers/avatar.py @@ -80,6 +80,7 @@ async def get_customized_avatar( clothe_color=clothe_color, clothe_graphic_type=clothe_graphic_type, ).render_svg() + # skipcq: PY-W0069 # print(f"skin_color: {len(AvatarItemsAsList.skin_color)},") # print(f"hair_color: {len(AvatarItemsAsList.hair_color)},") # print(f"facial_hair_type: {len(AvatarItemsAsList.facial_hair_type)},") diff --git a/classquiz/routers/box_controller/embedded.py b/classquiz/routers/box_controller/embedded.py index 288d6c3..19bcf42 100644 --- a/classquiz/routers/box_controller/embedded.py +++ b/classquiz/routers/box_controller/embedded.py @@ -109,7 +109,7 @@ button_to_index_map = {"b": 0, "g": 1, "y": 2, "r": 3} @router.websocket("/socket/{id}") async def websocket_endpoint(ws: WebSocket, game_id: str, id: str): try: - if id in wss_clients.keys(): + if id in wss_clients: await ws.close(code=status.WS_1001_GOING_AWAY) print("Client {} already exists.".format(id)) return diff --git a/classquiz/routers/box_controller/web.py b/classquiz/routers/box_controller/web.py index 72afce5..ee6abb2 100644 --- a/classquiz/routers/box_controller/web.py +++ b/classquiz/routers/box_controller/web.py @@ -26,7 +26,7 @@ def generate_code() -> str: "r", ] # Capital stands for long press, lowercase letter for short press resulting_code = "" - for i in range(specified_length): + for _ in range(specified_length): resulting_code += random.choice(buttons) return resulting_code diff --git a/classquiz/routers/editor.py b/classquiz/routers/editor.py index 7704eab..bcb0134 100644 --- a/classquiz/routers/editor.py +++ b/classquiz/routers/editor.py @@ -106,9 +106,6 @@ async def finish_edit(edit_id: str, quiz_input: QuizInput): if quiz_input.cover_image == "": quiz_input.cover_image = None - # if quiz_input.background_image is None and old_quiz_data.background_image is not None: - # mark_image_for_deletion(quiz_input.background_image) - if quiz_input.cover_image is not None and not check_image_string(quiz_input.cover_image)[0]: raise HTTPException(status_code=400, detail="image url is not valid") diff --git a/classquiz/routers/eximport.py b/classquiz/routers/eximport.py index 294548b..af5c264 100644 --- a/classquiz/routers/eximport.py +++ b/classquiz/routers/eximport.py @@ -46,9 +46,8 @@ async def export_quiz(quiz_id: uuid.UUID, user: User = Depends(get_current_user) quiz_dict["updated_at"] = quiz_dict["updated_at"].isoformat() quiz_json = json.dumps(quiz_dict) bin_data = gzip.compress(quiz_json.encode("utf-8"), compresslevel=9) - # bin_data = quiz_json.encode("utf-8") bin_data = bin_data + quiz_delimiter - for image_key in image_urls.keys(): + for image_key in image_urls: bin_data = bin_data + image_delimiter + str(image_key).encode("utf-8") + image_index_delimiter image_data = None async with ClientSession() as session, session.get( diff --git a/classquiz/routers/live.py b/classquiz/routers/live.py index 6e9d1b5..9aad7a2 100644 --- a/classquiz/routers/live.py +++ b/classquiz/routers/live.py @@ -134,8 +134,6 @@ async def get_live_game_data( @router.get("/user_count") async def get_game_user_count(game_pin: str, api_key: str, as_string: bool = False, as_array: bool = False): - # if redis_res is None: - # raise HTTPException(status_code=404, detail="Game not found") user_id = await check_api_key(api_key) redis_res = await redis.get(f"game_session:{game_pin}") if redis_res is None: @@ -149,12 +147,6 @@ async def get_game_user_count(game_pin: str, api_key: str, as_string: bool = Fal return {"players": {"count": player_count}} -# class _LivePlayersReturn(BaseModel): -# # players: list[GamePlayer | None] -# answers: list[GameAnswer1 | None] -# players: list[GamePlayer | None] - - @router.get( "/players", ) diff --git a/classquiz/routers/login.py b/classquiz/routers/login.py index 6efd0c1..7c0d1dd 100644 --- a/classquiz/routers/login.py +++ b/classquiz/routers/login.py @@ -149,7 +149,7 @@ class StepInput(BaseModel): @router.post("/step/{step_id}") -async def step_1(session_id: str, data: StepInput, request: Request, response: Response, step_id: int): +async def step_1_endpoint(session_id: str, data: StepInput, request: Request, response: Response, step_id: int): if step_id < 0 or step_id > 2: raise HTTPException(status_code=401) redis_res = await redis.get(f"login_session:{session_id}") diff --git a/classquiz/routers/quiz.py b/classquiz/routers/quiz.py index 3069cb9..6df16cd 100644 --- a/classquiz/routers/quiz.py +++ b/classquiz/routers/quiz.py @@ -83,7 +83,7 @@ def generate_code() -> str: "r", ] # Capital stands for long press, lowercase letter for short press resulting_code = "" - for i in range(specified_length): + for _ in range(specified_length): resulting_code += random.choice(buttons) return resulting_code diff --git a/classquiz/routers/results.py b/classquiz/routers/results.py index dbc8810..dd2e43a 100644 --- a/classquiz/routers/results.py +++ b/classquiz/routers/results.py @@ -49,6 +49,7 @@ async def set_note(id: UUID, data: _SetNoteInput, user: User = Depends(get_curre return await res.update() +# skipcq: PYL-W0105 """ @router.get("/export/{result_id}", response_class=StreamingResponse) async def export_result(result_id: UUID, user: User = Depends(get_current_user)): diff --git a/classquiz/routers/storage.py b/classquiz/routers/storage.py index 3bcf4a5..40cf007 100644 --- a/classquiz/routers/storage.py +++ b/classquiz/routers/storage.py @@ -221,7 +221,6 @@ async def list_images( raise HTTPException(status_code=404, detail="No items found") return_items: list[PrivateStorageItem] = [] for item in storage_items: - # print(item.quizzes) return_items.append(PrivateStorageItem.from_db_model(item)) return return_items diff --git a/classquiz/routers/users/__init__.py b/classquiz/routers/users/__init__.py index 97f7d06..5417387 100644 --- a/classquiz/routers/users/__init__.py +++ b/classquiz/routers/users/__init__.py @@ -79,7 +79,6 @@ async def create_user(user: RouteUser, background_task: BackgroundTasks) -> User if len(user.username) == 32: return JSONResponse({"details": "Username mustn't be 32 characters long"}, 400) await user.save() - # print(settings.skip_email_verification) if settings.skip_email_verification: user.verify_key = None user.verified = True diff --git a/classquiz/socket_server/__init__.py b/classquiz/socket_server/__init__.py index b2ec89f..ef72bd2 100644 --- a/classquiz/socket_server/__init__.py +++ b/classquiz/socket_server/__init__.py @@ -253,7 +253,7 @@ class ReturnQuestion(QuizQuestion): if values["type"] == QuizQuestionType.RANGE and type(v) != RangeQuizAnswerWithoutSolution: raise ValueError("Answer must be from type RangeQuizAnswer if type is RANGE") if values["type"] == QuizQuestionType.VOTING and type(v[0]) != VotingQuizAnswer: - # print("Answer must be from type VotingQuizAnswer if type is VOTING") + # skipcq: PTC-W0047 pass return v @@ -262,7 +262,6 @@ class ReturnQuestion(QuizQuestion): async def set_question_number(sid, data: str): # data is just a number (as a str) of the question session = await sio.get_session(sid) - # print("set_question_number", data, session) if session["admin"]: game_pin = session["game_pin"] game_data = PlayGame.parse_raw(await redis.get(f"game:{session['game_pin']}")) @@ -286,7 +285,6 @@ async def set_question_number(sid, data: str): temp_return["type"] = game_data.questions[int(float(data))].type if temp_return["type"] == QuizQuestionType.ORDER: random.shuffle(temp_return["answers"]) - # print("emitting") await sio.emit( "set_question_number", { @@ -375,8 +373,6 @@ async def submit_answer(sid: str, data: dict): answers = await redis.get(f"game_session:{session['game_pin']}:{data.question_index}") diff = (time_q_started - now).total_seconds() * 1000 # - timedelta(milliseconds=latency) - # print(abs(diff) - latency, latency, abs(diff)) - score = 0 if answer_right: score = calculate_score( diff --git a/classquiz/storage/local_storage.py b/classquiz/storage/local_storage.py index a352ee8..e473712 100644 --- a/classquiz/storage/local_storage.py +++ b/classquiz/storage/local_storage.py @@ -27,9 +27,10 @@ class LocalStorage: except FileNotFoundError: yield None - async def upload(self, file_name: str, data: BinaryIO, mime_type: str | None = None) -> None: + # skipcq: PYL-W0613 + async def upload(self, file_name: str, file: BinaryIO, mime_type: str | None = None) -> None: async with aiofiles.open(file=os.path.join(self.base_path, file_name), mode="wb") as f: - await aioshutil_copyfileobj(data, f) + await aioshutil_copyfileobj(file, f) async def delete(self, file_names: [str]) -> None: for i in file_names: diff --git a/classquiz/storage/s3_storage.py b/classquiz/storage/s3_storage.py index 6a1470d..50d4f3f 100644 --- a/classquiz/storage/s3_storage.py +++ b/classquiz/storage/s3_storage.py @@ -103,15 +103,13 @@ class S3Storage: + "Signature=" + signature ) - # if expiry is not None: - # authorization_header += f", Expires={expiry}" - # Send the request with the authorization header headers = {"x-amz-date": amz_date, "Authorization": authorization_header} request_url = self.base_url + path + "?" + canonical_querystring return headers, request_url + # skipcq: PYL-W0613 async def upload(self, file: BinaryIO, file_name: str, mime_type: str | None = "application/octet-stream") -> None: headers, url = self._generate_aws_signature_v4(method="PUT", path=f"/{file_name}") async with ClientSession() as session, session.put(url, headers=headers, data=file) as resp: diff --git a/classquiz/worker/storage.py b/classquiz/worker/storage.py index 2328703..01493f7 100644 --- a/classquiz/worker/storage.py +++ b/classquiz/worker/storage.py @@ -16,6 +16,7 @@ from classquiz.storage.errors import DeletionFailedError from thumbhash import image_to_thumbhash +# skipcq: PYL-W0613 async def clean_editor_images_up(ctx): print("Cleaning images up") edit_sessions = await redis.smembers("edit_sessions") @@ -52,10 +53,12 @@ async def calculate_hash(ctx, file_id_as_str: str): try: if 0 < file_data.size < 20_970_000: # greater than 0 but smaller than 20mbytes file_data.thumbhash = image_to_thumbhash(file) + # skipcq: PYL-W0703 except Exception: pass hash_obj = xxhash.xxh3_128() + # skipcq: PY-W0069 # assert hash_obj.block_size == 64 while chunk := file.read(6400): hash_obj.update(chunk) @@ -70,6 +73,7 @@ async def calculate_hash(ctx, file_id_as_str: str): await user.update() +# skipcq: PYL-W0613 async def quiz_update(ctx, old_quiz: Quiz, quiz_id: uuid.UUID): new_quiz: Quiz = await Quiz.objects.get(id=quiz_id) old_images = extract_image_ids_from_quiz(old_quiz) @@ -83,8 +87,6 @@ async def quiz_update(ctx, old_quiz: Quiz, quiz_id: uuid.UUID): removed_images = list(set(old_images) - set(new_images)) added_images = list(set(new_images) - set(old_images)) change_made = False - # print("added:", added_images) - # print("removed:", removed_images) for image in removed_images: if "--" in image: await storage.delete([image]) @@ -92,7 +94,6 @@ async def quiz_update(ctx, old_quiz: Quiz, quiz_id: uuid.UUID): item = await StorageItem.objects.get_or_none(id=uuid.UUID(image)) if item is None: continue - # print("removed item") try: await new_quiz.storageitems.remove(item) except ormar.exceptions.NoMatch: @@ -103,7 +104,6 @@ async def quiz_update(ctx, old_quiz: Quiz, quiz_id: uuid.UUID): item = await StorageItem.objects.get_or_none(id=uuid.UUID(image)) if item is None: continue - # print("added item") await new_quiz.storageitems.add(item) change_made = True if change_made: diff --git a/frontend/src/lib/dashboard/useViewportAction.js b/frontend/src/lib/dashboard/useViewportAction.js index fee000b..5704e2d 100644 --- a/frontend/src/lib/dashboard/useViewportAction.js +++ b/frontend/src/lib/dashboard/useViewportAction.js @@ -4,6 +4,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ // Stolen from https://svelte.dev/repl/c6a402704224403f96a3db56c2f48dfc?version=3.55.0 +// skipcq: JS-0119 let intersectionObserver; function ensureIntersectionObserver() { diff --git a/frontend/src/lib/hashcash.ts b/frontend/src/lib/hashcash.ts index 620dcbb..a0bc7be 100644 --- a/frontend/src/lib/hashcash.ts +++ b/frontend/src/lib/hashcash.ts @@ -42,10 +42,12 @@ export const mint = async ( // eslint-disable-next-line no-constant-condition while (true) { + // skipcq: JS-0003 const data = new TextEncoder().encode(`${challenge}:${counter.toString(16)}`); const hashBuffer = await crypto.subtle.digest('SHA-1', data); const hashArray = Array.from(new Uint8Array(hashBuffer)); const digest = hashArray.map((b) => b.toString(16).padStart(2, '0')).join(''); + // skipcq: JS-0050 if (digest.slice(0, hex_digits) == zeros) { result = counter.toString(16); break; diff --git a/frontend/src/lib/helpers.ts b/frontend/src/lib/helpers.ts index aeb6ac9..26c8880 100644 --- a/frontend/src/lib/helpers.ts +++ b/frontend/src/lib/helpers.ts @@ -10,8 +10,8 @@ export const invertColor = (hexTripletColor: string): string => { let color_int = parseInt(color, 16); // convert to integer color_int = 0xffffff ^ color_int; // invert three bytes color = color_int.toString(16); // convert to hex - color = ('000000' + color).slice(-6); // pad with leading zeros - color = '#' + color; // prepend # + color = `000000${color}`.slice(-6); // pad with leading zeros + color = `#${color}`; // prepend # return color; }; @@ -20,13 +20,6 @@ export const calculate_score = (q_time: number, time_taken: number): number => { }; export type RGB = [number, number, number]; -export const getContrast = (foregroundColor: RGB, backgroundColor: RGB) => { - const foregroundLuminance = getLuminance(foregroundColor); - const backgroundLuminance = getLuminance(backgroundColor); - return backgroundLuminance < foregroundLuminance - ? (backgroundLuminance + 0.05) / (foregroundLuminance + 0.05) - : (foregroundLuminance + 0.05) / (backgroundLuminance + 0.05); -}; export const getLuminance = (rgb: RGB): number => { const [r, g, b] = rgb.map((v) => { @@ -36,6 +29,14 @@ export const getLuminance = (rgb: RGB): number => { return r * 0.2126 + g * 0.7152 + b * 0.0722; }; +export const getContrast = (foregroundColor: RGB, backgroundColor: RGB) => { + const foregroundLuminance = getLuminance(foregroundColor); + const backgroundLuminance = getLuminance(backgroundColor); + return backgroundLuminance < foregroundLuminance + ? (backgroundLuminance + 0.05) / (foregroundLuminance + 0.05) + : (foregroundLuminance + 0.05) / (backgroundLuminance + 0.05); +}; + export const getRgbColorFromHex = (hex: string): RGB => { hex = hex.slice(1); const value = parseInt(hex, 16); diff --git a/frontend/src/lib/yupSchemas.ts b/frontend/src/lib/yupSchemas.ts index 9798626..2bc1f67 100644 --- a/frontend/src/lib/yupSchemas.ts +++ b/frontend/src/lib/yupSchemas.ts @@ -4,6 +4,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +// skipcq: JS-C1003 import * as yup from 'yup'; export const ABCDQuestionSchema = yup @@ -69,23 +70,17 @@ export const dataSchema = yup.object({ answers: yup.lazy((v) => { if (Array.isArray(v)) { if (typeof v[0].right === 'boolean') { - console.log('ABCDQuestionSchema'); return ABCDQuestionSchema; } else if (typeof v[0].case_sensitive === 'boolean') { - console.log('TextQuestionSchema'); return TextQuestionSchema; } else if (v[0].id !== undefined) { - console.log('OrderQuestionSchema'); return VotingQuestionSchema; } else if (v[0].answer !== undefined) { - console.log('VotingQuestionSchema'); return VotingQuestionSchema; } } else if (typeof v === 'string' || v instanceof String) { - console.log('StringQuestionSchema'); return yup.string().required("The slide mustn't be empty").nullable(); } else { - console.log('RangeQuestionSchema'); return RangeQuestionSchema; } }) diff --git a/frontend/src/routes/dashboard/files/+page.ts b/frontend/src/routes/dashboard/files/+page.ts index 92f4a01..17d6edc 100644 --- a/frontend/src/routes/dashboard/files/+page.ts +++ b/frontend/src/routes/dashboard/files/+page.ts @@ -7,7 +7,5 @@ import type { PageLoad } from './$types'; export const load = (async ({ fetch }) => { const res = await fetch('/api/v1/storage/list'); - if (res.ok) { - return { files: await res.json() }; - } + return { files: await res.json() }; }) satisfies PageLoad; diff --git a/migrations/versions/89c4b5d547aa_new_storage.py b/migrations/versions/89c4b5d547aa_new_storage.py index 9a795c7..cd693c8 100644 --- a/migrations/versions/89c4b5d547aa_new_storage.py +++ b/migrations/versions/89c4b5d547aa_new_storage.py @@ -138,23 +138,26 @@ def downgrade() -> None: conn = op.get_bind() session = Session(bind=conn) all_cover_images = session.execute("SELECT cover_image, id from quiz where cover_image is not null;") + stmt = text("UPDATE quiz SET cover_image = :n WHERE id=:i;") for cover_image, id in all_cover_images: new_cover_image = f"{settings.root_address}/api/v1/storage/download/{cover_image}" # print(new_cover_image, id) - session.execute(f"UPDATE quiz SET cover_image = '{new_cover_image}' WHERE id='{id}';") + session.execute(stmt, {"n": new_cover_image, "i": id}) all_background_images = session.execute("SELECT background_image, id from quiz where background_image is not null;") + stmt = text("UPDATE quiz SET cover_image = :n WHERE id=:i;") for bg_image, id in all_background_images: new_bg_image = f"{settings.root_address}/api/v1/storage/download/{bg_image}" # print(new_cover_image, id) - session.execute(f"UPDATE quiz SET cover_image = '{new_bg_image}' WHERE id='{id}';") + session.execute(stmt, {"n": new_bg_image, "i": id}) all_questions = session.execute("SELECT questions, id from quiz;") + stmt = text("UPDATE quiz SET questions = :r WHERE id=:i;") question_image_regex = r"(?=.{36}--.{36})" for question, id in all_questions: question_as_json = json.dumps(question) result = re.sub(question_image_regex, f"{settings.root_address}/api/v1/storage/download/", question_as_json) - session.execute(f"UPDATE quiz SET questions = '{result}' WHERE id='{id}';") + session.execute(stmt, {"r": result, "i": id}) ## ADDED STORAGE ITEM op.drop_table("storageitems_quiztivitys") diff --git a/simulate_players.py b/simulate_players.py index a0e093e..d46223c 100644 --- a/simulate_players.py +++ b/simulate_players.py @@ -4,6 +4,7 @@ import random import time +import sys import socketio @@ -63,4 +64,4 @@ if __name__ == "__main__": try: __main__() except KeyboardInterrupt: - exit(1) + sys.exit(1)