mabuseif commited on
Commit
6b97522
·
verified ·
1 Parent(s): 1003f90

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +53 -123
app.py CHANGED
@@ -5,6 +5,7 @@ import urllib.parse
5
  from datetime import datetime
6
  import pytz
7
  import pandas as pd
 
8
 
9
  # --- Constants ---
10
  MELBOURNE_TIMEZONE = 'Australia/Melbourne'
@@ -115,6 +116,26 @@ def format_metadata_html(url, author, year, scc_hash, username, task_name, curre
115
  def check_for_fragment(url):
116
  return '#:~:text=' in url
117
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  # --- Live Clock JavaScript ---
119
  def live_clock():
120
  return """
@@ -279,15 +300,6 @@ with tabs[0]:
279
  st.markdown('<div class="hash-display">', unsafe_allow_html=True)
280
  st.markdown(metadata_link, unsafe_allow_html=True)
281
  st.markdown('</div>', unsafe_allow_html=True)
282
-
283
- # Guidance on Verifying Citations
284
- st.markdown("## Guidance on Verifying Citations")
285
- st.markdown("""
286
- <div class="info-card">
287
- To verify a citation, you can recompute the hash using the original input data and compare it to the embedded hash.
288
- The <strong>'Verify Citation'</strong> tab allows you to do this easily.
289
- </div>
290
- """, unsafe_allow_html=True)
291
 
292
  st.markdown('</div>', unsafe_allow_html=True)
293
 
@@ -296,128 +308,46 @@ with tabs[1]:
296
  st.header("Verify Citation")
297
  st.markdown("""
298
  <div class="info-card">
299
- Enter the citation details below to recompute and verify the hash. This ensures the citation hasn't been tampered with or fabricated.
300
  </div>
301
  """, unsafe_allow_html=True)
302
 
303
- # Initialize session state for storing verified hashes
304
- if 'verified_hashes' not in st.session_state:
305
- st.session_state.verified_hashes = []
306
 
307
- # User Information Section
308
- st.subheader("User Information")
309
- col1, col2 = st.columns(2)
310
- with col1:
311
- verify_username = st.text_input("Username (for verification)", placeholder="e.g., john_doe")
312
- with col2:
313
- verify_task_name = st.text_input("Task Name (for verification)", placeholder="e.g., Literature Review Assignment")
314
-
315
- # Citation Info Section
316
- st.subheader("Citation Info")
317
- col3, col4 = st.columns(2)
318
- with col3:
319
- verify_author_name = st.text_input("Author(s) Name (for verification)", placeholder="e.g., Smith or Smith et al.")
320
- with col4:
321
- verify_publication_year = st.text_input("Publication Year (for verification)", placeholder="e.g., 2023")
322
-
323
- col5, col6 = st.columns(2)
324
- with col5:
325
- verify_source_url = st.text_input("Source URL (for verification)", placeholder="https://example.com/article")
326
- with col6:
327
- verify_annotated_text = st.text_input("Annotated Text (for verification)", placeholder="e.g., Thermal comfort thresholds...")
328
-
329
- col7, col8 = st.columns(2)
330
- with col7:
331
- verify_date = st.text_input("Date (YYYY-MM-DD) (for verification)", placeholder="e.g., 2025-01-08")
332
- with col8:
333
- verify_time = st.text_input("Time (HH:MM:SS) (for verification)", placeholder="e.g., 14:30:25")
334
-
335
- expected_hash = st.text_input("Expected Hash (from the citation)", placeholder="Enter the full hash from the citation")
336
-
337
- verify_button = st.button("Verify Hash", type="primary", use_container_width=True)
338
 
339
  if verify_button:
340
- if not all([verify_username, verify_task_name, verify_author_name, verify_publication_year,
341
- verify_source_url, verify_annotated_text, verify_date, verify_time, expected_hash]):
342
- st.error("Please fill in all fields before verifying the hash.")
343
  else:
344
- recomputed_hash = generate_citation_hash(
345
- verify_author_name, verify_publication_year, verify_source_url,
346
- verify_annotated_text, verify_annotated_text, verify_username, verify_task_name,
347
- verify_date, verify_time
348
- )
349
-
350
- if recomputed_hash == expected_hash:
351
- st.markdown("""
352
- <div class="success-box">
353
- <strong>Hash verified successfully!</strong> The citation is authentic and hasn't been tampered with.
354
- </div>
355
- """, unsafe_allow_html=True)
356
-
357
- st.session_state.verified_hashes.append({
358
- "Author": verify_author_name,
359
- "Year": verify_publication_year,
360
- "URL": verify_source_url,
361
- "Fragment text": verify_annotated_text,
362
- "Cited text": verify_annotated_text,
363
- "Username": verify_username,
364
- "Task name": verify_task_name,
365
- "Date": verify_date,
366
- "Time": verify_time,
367
- "Original Hash": expected_hash,
368
- "Recomputed Hash": recomputed_hash,
369
- "Status": "Verified"
370
- })
371
  else:
372
- st.markdown("""
373
- <div class="warning-box">
374
- <strong>Hash verification failed!</strong> The citation may have been altered or is not authentic.
375
- </div>
376
- """, unsafe_allow_html=True)
377
-
378
- st.session_state.verified_hashes.append({
379
- "Author": verify_author_name,
380
- "Year": verify_publication_year,
381
- "URL": verify_source_url,
382
- "Fragment text": verify_annotated_text,
383
- "Cited text": verify_annotated_text,
384
- "Username": verify_username,
385
- "Task name": verify_task_name,
386
- "Date": verify_date,
387
- "Time": verify_time,
388
- "Original Hash": expected_hash,
389
- "Recomputed Hash": recomputed_hash,
390
- "Status": "Failed"
391
- })
392
-
393
- if st.session_state.verified_hashes:
394
- st.markdown("## Verification History")
395
- df = pd.DataFrame(st.session_state.verified_hashes)
396
-
397
- st.markdown('<div class="verification-table">', unsafe_allow_html=True)
398
- st.dataframe(df, use_container_width=True)
399
- st.markdown('</div>', unsafe_allow_html=True)
400
-
401
- # Download as CSV
402
- @st.cache_data
403
- def convert_df_to_csv(df):
404
- return df.to_csv(index=False).encode('utf-8')
405
-
406
- csv = convert_df_to_csv(df)
407
-
408
- st.download_button(
409
- label="Download Verification History as CSV",
410
- data=csv,
411
- file_name="scc_verification_history.csv",
412
- mime="text/csv",
413
- use_container_width=True
414
- )
415
-
416
- # Clear history button
417
- if st.button("Clear Verification History", type="secondary"):
418
- st.session_state.verified_hashes = []
419
- st.experimental_rerun()
420
-
421
  st.markdown('</div>', unsafe_allow_html=True)
422
 
423
  # Footer
 
5
  from datetime import datetime
6
  import pytz
7
  import pandas as pd
8
+ import re
9
 
10
  # --- Constants ---
11
  MELBOURNE_TIMEZONE = 'Australia/Melbourne'
 
116
  def check_for_fragment(url):
117
  return '#:~:text=' in url
118
 
119
+ def parse_citation(citation_html):
120
+ # Parse citation HTML to extract author, year, URL, and fragment text
121
+ match = re.match(r'<a href="([^"]+)#:~:text=([^"]+)" data-hash="[^"]+">([^<]+) \((\d{4})\)</a>', citation_html)
122
+ if match:
123
+ url, encoded_fragment, author, year = match.groups()
124
+ fragment_text = urllib.parse.unquote(encoded_fragment)
125
+ return author, year, url, fragment_text
126
+ return None, None, None, None
127
+
128
+ def parse_metadata_hash(metadata_html):
129
+ # Parse metadata HTML to extract hash, username, task_name, date, time
130
+ match = re.match(r'<a href="([^"]+)#:~:text=([^"]+)" data-hash="([^"]+)">[^<]+\(\d{4}\)\. ([^<]+)</a>', metadata_html)
131
+ if match:
132
+ url, encoded_metadata, scc_hash, same_hash = match.groups()
133
+ metadata_parts = urllib.parse.unquote(encoded_metadata).split('—')
134
+ if len(metadata_parts) == 4:
135
+ username, task_name, date, time = metadata_parts
136
+ return scc_hash, username, task_name, date, time
137
+ return None, None, None, None, None
138
+
139
  # --- Live Clock JavaScript ---
140
  def live_clock():
141
  return """
 
300
  st.markdown('<div class="hash-display">', unsafe_allow_html=True)
301
  st.markdown(metadata_link, unsafe_allow_html=True)
302
  st.markdown('</div>', unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
303
 
304
  st.markdown('</div>', unsafe_allow_html=True)
305
 
 
308
  st.header("Verify Citation")
309
  st.markdown("""
310
  <div class="info-card">
311
+ Paste the generated citation and hash with their embedded links below to verify the citation's authenticity.
312
  </div>
313
  """, unsafe_allow_html=True)
314
 
315
+ # Input fields for citation and hash
316
+ citation_input = st.text_area("Paste Citation (with embedded link)", help="Paste the citation HTML, e.g., <a href='URL'>Author (Year)</a>", placeholder='<a href="https://example.com#:~:text=fragment" data-hash="hash">Author (Year)</a>')
317
+ hash_input = st.text_area("Paste Hash (with embedded link)", help="Paste the hash HTML, e.g., <a href='URL'>Author (Year). Hash</a>", placeholder='<a href="https://example.com#:~:text=metadata" data-hash="hash">Author (Year). Hash</a>')
318
 
319
+ verify_button = st.button("Verify Citation", type="primary", use_container_width=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
320
 
321
  if verify_button:
322
+ if not (citation_input and hash_input):
323
+ st.error("Please paste both the citation and hash before verifying.")
 
324
  else:
325
+ # Parse citation
326
+ author, year, url, fragment_text = parse_citation(citation_input)
327
+ # Parse hash and metadata
328
+ scc_hash, username, task_name, date, time = parse_metadata_hash(hash_input)
329
+
330
+ if not all([author, year, url, fragment_text, scc_hash, username, task_name, date, time]):
331
+ st.error("Invalid citation or hash format. Please ensure both inputs are correctly formatted HTML with embedded links.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
332
  else:
333
+ # Recompute hash
334
+ recomputed_hash = generate_citation_hash(
335
+ author, year, url, fragment_text, fragment_text, username, task_name, date, time
336
+ )
337
+
338
+ if recomputed_hash == scc_hash:
339
+ st.markdown("""
340
+ <div class="success-box">
341
+ <strong>Hash verified successfully!</strong> The citation is authentic and hasn't been tampered with.
342
+ </div>
343
+ """, unsafe_allow_html=True)
344
+ else:
345
+ st.markdown("""
346
+ <div class="warning-box">
347
+ <strong>Hash verification failed!</strong> The citation may have been altered or is not authentic.
348
+ </div>
349
+ """, unsafe_allow_html=True)
350
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
351
  st.markdown('</div>', unsafe_allow_html=True)
352
 
353
  # Footer