From 815e86b3bba43c70b6ac8cedde60e31a32fa6204 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Tue, 17 Feb 2026 14:28:03 +0000 Subject: [PATCH 01/14] Enforce 280-character limit on bloom submission --- front-end/components/bloom-form.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/front-end/components/bloom-form.mjs b/front-end/components/bloom-form.mjs index e047f9a..7080a39 100644 --- a/front-end/components/bloom-form.mjs +++ b/front-end/components/bloom-form.mjs @@ -25,7 +25,7 @@ async function handleBloomSubmit(event) { const submitButton = form.querySelector("[data-submit]"); const originalText = submitButton.textContent; const textarea = form.querySelector("textarea"); - const content = textarea.value.trim(); + const content = textarea.value.trim().slice(0, 280); try { // Make form inert while we call the back end From 98bc0a0e5ae5cf96fe2efd7b98c55f5acdb5b652 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Tue, 17 Feb 2026 14:29:44 +0000 Subject: [PATCH 02/14] Trim bloom content to 280 characters when rendering --- front-end/components/bloom.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/front-end/components/bloom.mjs b/front-end/components/bloom.mjs index 0b4166c..907b4ca 100644 --- a/front-end/components/bloom.mjs +++ b/front-end/components/bloom.mjs @@ -27,7 +27,7 @@ const createBloom = (template, bloom) => { bloomTime.textContent = _formatTimestamp(bloom.sent_timestamp); bloomTimeLink.setAttribute("href", `/bloom/${bloom.id}`); bloomContent.replaceChildren( - ...bloomParser.parseFromString(_formatHashtags(bloom.content), "text/html") + ...bloomParser.parseFromString(_formatHashtags(bloom.content.slice(0, 280)), "text/html") .body.childNodes ); From 9e503438332f070be992503103753c557cdca7d2 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 20 Feb 2026 00:14:42 +0000 Subject: [PATCH 03/14] Remove all reference to logic that slice AS over 280 char bloom. This will later be replaced with a logic that fails the bloom altogeather. --- front-end/components/bloom-form.mjs | 2 +- front-end/components/bloom.mjs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/front-end/components/bloom-form.mjs b/front-end/components/bloom-form.mjs index 7080a39..49ca81c 100644 --- a/front-end/components/bloom-form.mjs +++ b/front-end/components/bloom-form.mjs @@ -25,7 +25,7 @@ async function handleBloomSubmit(event) { const submitButton = form.querySelector("[data-submit]"); const originalText = submitButton.textContent; const textarea = form.querySelector("textarea"); - const content = textarea.value.trim().slice(0, 280); + try { // Make form inert while we call the back end diff --git a/front-end/components/bloom.mjs b/front-end/components/bloom.mjs index 907b4ca..0b4166c 100644 --- a/front-end/components/bloom.mjs +++ b/front-end/components/bloom.mjs @@ -27,7 +27,7 @@ const createBloom = (template, bloom) => { bloomTime.textContent = _formatTimestamp(bloom.sent_timestamp); bloomTimeLink.setAttribute("href", `/bloom/${bloom.id}`); bloomContent.replaceChildren( - ...bloomParser.parseFromString(_formatHashtags(bloom.content.slice(0, 280)), "text/html") + ...bloomParser.parseFromString(_formatHashtags(bloom.content), "text/html") .body.childNodes ); From 4e9bbcea5b6aaa7539971a1368be7aa7025c5b6c Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 20 Feb 2026 00:27:05 +0000 Subject: [PATCH 04/14] reverting logic to where it was before adding new logic --- front-end/components/bloom-form.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/front-end/components/bloom-form.mjs b/front-end/components/bloom-form.mjs index 49ca81c..4bc988c 100644 --- a/front-end/components/bloom-form.mjs +++ b/front-end/components/bloom-form.mjs @@ -25,6 +25,7 @@ async function handleBloomSubmit(event) { const submitButton = form.querySelector("[data-submit]"); const originalText = submitButton.textContent; const textarea = form.querySelector("textarea"); + const content = textarea.value.trim(); try { From f0605c154a24a13cf68e8915368ca880b05d964c Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 20 Feb 2026 15:59:42 +0000 Subject: [PATCH 05/14] adding length-check for blooms being read from DB --- backend/data/blooms.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/backend/data/blooms.py b/backend/data/blooms.py index 7e280cf..6d0f991 100644 --- a/backend/data/blooms.py +++ b/backend/data/blooms.py @@ -6,6 +6,8 @@ from data.connection import db_cursor from data.users import User +MAX_BLOOM_LENGTH = 280 + @dataclass class Bloom: @@ -69,6 +71,8 @@ def get_blooms_for_user( blooms = [] for row in rows: bloom_id, sender_username, content, timestamp = row + if len(content) > MAX_BLOOM_LENGTH: + raise ValueError(f"Bloom {bloom_id} exceeds {MAX_BLOOM_LENGTH} characters") blooms.append( Bloom( id=bloom_id, @@ -81,7 +85,7 @@ def get_blooms_for_user( def get_bloom(bloom_id: int) -> Optional[Bloom]: - with db_cursor() as cur: + with db_get_bloomcursor() as cur: cur.execute( "SELECT blooms.id, users.username, content, send_timestamp FROM blooms INNER JOIN users ON users.id = blooms.sender_id WHERE blooms.id = %s", (bloom_id,), @@ -122,6 +126,8 @@ def get_blooms_with_hashtag( blooms = [] for row in rows: bloom_id, sender_username, content, timestamp = row + if len(content) > MAX_BLOOM_LENGTH: + raise ValueError(f"Bloom {bloom_id} exceeds {MAX_BLOOM_LENGTH} characters") blooms.append( Bloom( id=bloom_id, From d3a5ba54ac72d520295d002c0584f0e23dec4bb2 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 20 Feb 2026 20:40:50 +0000 Subject: [PATCH 06/14] Identify the bloom over 280 char by it's ID from the erros message in the console. Use it to skip it while fetching all blooms from backend --- backend/data/blooms.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/backend/data/blooms.py b/backend/data/blooms.py index 6d0f991..8dc201c 100644 --- a/backend/data/blooms.py +++ b/backend/data/blooms.py @@ -6,8 +6,6 @@ from data.connection import db_cursor from data.users import User -MAX_BLOOM_LENGTH = 280 - @dataclass class Bloom: @@ -71,8 +69,6 @@ def get_blooms_for_user( blooms = [] for row in rows: bloom_id, sender_username, content, timestamp = row - if len(content) > MAX_BLOOM_LENGTH: - raise ValueError(f"Bloom {bloom_id} exceeds {MAX_BLOOM_LENGTH} characters") blooms.append( Bloom( id=bloom_id, @@ -126,8 +122,6 @@ def get_blooms_with_hashtag( blooms = [] for row in rows: bloom_id, sender_username, content, timestamp = row - if len(content) > MAX_BLOOM_LENGTH: - raise ValueError(f"Bloom {bloom_id} exceeds {MAX_BLOOM_LENGTH} characters") blooms.append( Bloom( id=bloom_id, From 6cf28727298348a0a1c2ad6b121bbddd9c5b0187 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 20 Feb 2026 21:03:42 +0000 Subject: [PATCH 07/14] Get AS bloom ID from the error on on console. Use it to skip of it when blooms fetched from backend --- backend/data/blooms.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/backend/data/blooms.py b/backend/data/blooms.py index 8dc201c..271e3b3 100644 --- a/backend/data/blooms.py +++ b/backend/data/blooms.py @@ -6,6 +6,8 @@ from data.connection import db_cursor from data.users import User +AS_BLOOM_ID = 1771113371599478 + @dataclass class Bloom: @@ -69,6 +71,8 @@ def get_blooms_for_user( blooms = [] for row in rows: bloom_id, sender_username, content, timestamp = row + if bloom_id == AS_BLOOM_ID: + continue blooms.append( Bloom( id=bloom_id, @@ -122,6 +126,8 @@ def get_blooms_with_hashtag( blooms = [] for row in rows: bloom_id, sender_username, content, timestamp = row + if bloom_id == AS_BLOOM_ID: + continue blooms.append( Bloom( id=bloom_id, From d3d20ada75433ad53ed197571b42f34a40b0b763 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 20 Feb 2026 21:21:46 +0000 Subject: [PATCH 08/14] replace bloom ID logic with condition to check if bloom over 280 characters instead. --- backend/data/blooms.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/backend/data/blooms.py b/backend/data/blooms.py index 271e3b3..28e3706 100644 --- a/backend/data/blooms.py +++ b/backend/data/blooms.py @@ -6,8 +6,6 @@ from data.connection import db_cursor from data.users import User -AS_BLOOM_ID = 1771113371599478 - @dataclass class Bloom: @@ -71,7 +69,7 @@ def get_blooms_for_user( blooms = [] for row in rows: bloom_id, sender_username, content, timestamp = row - if bloom_id == AS_BLOOM_ID: + if len(content) > 280: continue blooms.append( Bloom( @@ -126,7 +124,7 @@ def get_blooms_with_hashtag( blooms = [] for row in rows: bloom_id, sender_username, content, timestamp = row - if bloom_id == AS_BLOOM_ID: + if len(content) > 280: continue blooms.append( Bloom( From b2a455c961a05c78d7d0b8c401cc43dceef50b46 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Sat, 21 Feb 2026 20:24:10 +0000 Subject: [PATCH 09/14] correct the function name --- backend/data/blooms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/data/blooms.py b/backend/data/blooms.py index 28e3706..ca8d52b 100644 --- a/backend/data/blooms.py +++ b/backend/data/blooms.py @@ -83,7 +83,7 @@ def get_blooms_for_user( def get_bloom(bloom_id: int) -> Optional[Bloom]: - with db_get_bloomcursor() as cur: + with db_cursor() as cur: cur.execute( "SELECT blooms.id, users.username, content, send_timestamp FROM blooms INNER JOIN users ON users.id = blooms.sender_id WHERE blooms.id = %s", (bloom_id,), From d1ab71d7d7e2a908d27d8ce70b7beec91360f2e1 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Sun, 22 Feb 2026 15:43:07 +0000 Subject: [PATCH 10/14] resetting branch to where it was by removing added logic in blooms.py --- backend/data/blooms.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/backend/data/blooms.py b/backend/data/blooms.py index ca8d52b..7e280cf 100644 --- a/backend/data/blooms.py +++ b/backend/data/blooms.py @@ -69,8 +69,6 @@ def get_blooms_for_user( blooms = [] for row in rows: bloom_id, sender_username, content, timestamp = row - if len(content) > 280: - continue blooms.append( Bloom( id=bloom_id, @@ -124,8 +122,6 @@ def get_blooms_with_hashtag( blooms = [] for row in rows: bloom_id, sender_username, content, timestamp = row - if len(content) > 280: - continue blooms.append( Bloom( id=bloom_id, From 44e7568d6388a7e71960cecbb358b4ba6340fbcd Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Sun, 22 Feb 2026 16:14:52 +0000 Subject: [PATCH 11/14] add length check for when blooms are created --- backend/data/blooms.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/backend/data/blooms.py b/backend/data/blooms.py index 7e280cf..e37c2c4 100644 --- a/backend/data/blooms.py +++ b/backend/data/blooms.py @@ -15,7 +15,14 @@ class Bloom: sent_timestamp: datetime.datetime + + +MAX_BLOOM_LENGTH = 280 + def add_bloom(*, sender: User, content: str) -> Bloom: + if len(content) > MAX_BLOOM_LENGTH: + raise ValueError(f"Bloom exceeds maximum length of {MAX_BLOOM_LENGTH} characters") + hashtags = [word[1:] for word in content.split(" ") if word.startswith("#")] now = datetime.datetime.now(tz=datetime.UTC) From 74503ed6e5273e35b4d4732f1f21208e6d0eec72 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Sun, 22 Feb 2026 16:47:30 +0000 Subject: [PATCH 12/14] resetting logic to start from main again --- backend/data/blooms.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/backend/data/blooms.py b/backend/data/blooms.py index e37c2c4..383e14e 100644 --- a/backend/data/blooms.py +++ b/backend/data/blooms.py @@ -16,13 +16,8 @@ class Bloom: - -MAX_BLOOM_LENGTH = 280 - def add_bloom(*, sender: User, content: str) -> Bloom: - if len(content) > MAX_BLOOM_LENGTH: - raise ValueError(f"Bloom exceeds maximum length of {MAX_BLOOM_LENGTH} characters") - + hashtags = [word[1:] for word in content.split(" ") if word.startswith("#")] now = datetime.datetime.now(tz=datetime.UTC) From e05bd04d883c39d5990b492719c17f881e4b12f5 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Sun, 22 Feb 2026 19:51:34 +0000 Subject: [PATCH 13/14] filter out long blooms (over 280 char) --- backend/endpoints.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/backend/endpoints.py b/backend/endpoints.py index 0e177a0..757da73 100644 --- a/backend/endpoints.py +++ b/backend/endpoints.py @@ -177,6 +177,7 @@ def get_bloom(id_str): return make_response((f"Bloom not found", 404)) return jsonify(bloom) +MAX_BLOOM_LENGTH = 280 @jwt_required() def home_timeline(): @@ -198,6 +199,9 @@ def home_timeline(): # Combine own blooms with followed blooms all_blooms = followed_blooms + own_blooms + # Filter long blooms (over 280 characters) + all_blooms = [bloom for bloom in all_blooms if len(bloom.content) <= MAX_BLOOM_LENGTH] + # Sort by timestamp (newest first) sorted_blooms = list( sorted(all_blooms, key=lambda bloom: bloom.sent_timestamp, reverse=True) From 03d0a63cbbf96139705cd1a0823a05e0a3dffa09 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Sun, 22 Feb 2026 22:38:36 +0000 Subject: [PATCH 14/14] Add a measure to prevent any bloom longer than 280 characters from being created --- backend/data/blooms.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/backend/data/blooms.py b/backend/data/blooms.py index 383e14e..9db06ba 100644 --- a/backend/data/blooms.py +++ b/backend/data/blooms.py @@ -15,8 +15,11 @@ class Bloom: sent_timestamp: datetime.datetime +MAX_BLOOM_LENGTH = 280 def add_bloom(*, sender: User, content: str) -> Bloom: + if len(content) > 280: + raise ValueError("Bloom exceeds 280 characters") hashtags = [word[1:] for word in content.split(" ") if word.startswith("#")]