update to work with TriliumNext 0.92.6
1 parent b7f344f commit 7c57c8e86c24ad27a5e6cd9384834458d4719159
root authored on 10 Apr
Showing 2 changed files
View
91
htb2trilium/htb2trilium_challenges.py
import os
import json
import requests
import re
import unicodedata
from collections import defaultdict
from bs4 import BeautifulSoup
from datetime import datetime, timezone
from htb_client import HTBClient
total_completed = 0 # Variable to track total completed challenges
 
print(f"[i] Retrieved {len(challenges)} challenges")
 
def normalise_title(title):
# Strip accents, smart quotes, etc.
title = unicodedata.normalize("NFKD", title)
# Replace fancy punctuation
title = title.replace("’", "'").replace("`", "'").replace("–", "-").replace("“", '"').replace("”", '"')
# Remove excess whitespace
title = re.sub(r'\s+', ' ', title)
return title.strip().lower()
 
# Group challenges by their categories
for challenge in challenges:
categories[challenge['category_name']].append(challenge)
if challenge['is_owned']:
total = len(grouped_challenges)
completed = sum(1 for challenge in grouped_challenges if challenge['is_owned']) # Count completed challenges
res = ea.search_note(
search=f"note.title %= '{category}*'",
search=f"note.title %= '^{category}*'",
ancestorNoteId=trilium_challenges_folder,
ancestorDepth='eq1',
limit=1,
fastSearch=True,
)
catId = ""
if res['results'] and res['results'][0]['title'].split(' - ')[0].strip().lower() == category.lower():
# page exists - lets check if the details have changed
ea.patch_note(noteId=res['results'][0]['noteId'], title=category+" - "+str(completed)+" / "+str(total))
catId = res['results'][0]['noteId']
print(f"[i] updated category: {category} - ({completed}/{total})")
if res['results']:
matched_note = res['results'][0]
existing_category = " - ".join(matched_note['title'].split(" - ")[:-1]) # Extract category portion
if existing_category.strip().lower() == category.lower():
ea.patch_note(
noteId=matched_note['noteId'],
title=f"{category} - {completed} / {total}"
)
catId = matched_note['noteId']
print(f"[i] Updated category: {category} - ({completed}/{total})")
else:
new_note = ea.create_note(
parentNoteId=trilium_challenges_folder,
type="text",
title=category+" - "+str(completed)+" / "+str(total),
title=f"{category} - {completed} / {total}",
content=" ",
)
catId = new_note['note']['noteId']
print(f"[+] created category: {catId} {category} - ({completed}/{total})")
print(f"[+] Created category: {catId} {category} - ({completed}/{total})")
for challenge in grouped_challenges:
#print(f" - ID: {challenge['id']}, Name: {challenge['name']}, Difficulty: {challenge['difficulty']}")
escaped_name = challenge['name'].replace("'", "\\'").replace(",", "\\,")
res2 = ea.search_note(
search=f"{challenge['name']}",
search=f"note.title = '{escaped_name}'",
ancestorNoteId=catId,
ancestorDepth='eq1',
orderBy=["title"],
limit=1,
fastSearch=True,
)
# already exists update the values
if res2['results'] and res2['results'][0]['title'].lower() == challenge['name'].lower():
print(f"[i] found ID: {challenge['id']}, Name: {challenge['name']}, Difficulty: {challenge['difficulty']}")
#print(f"Search response for challenge '{challenge['name']}': {res2}")
for attribute in res2['results'][0]['attributes']:
if attribute['name'] == "Difficulty":
ea.patch_attribute(attributeId=attribute['attributeId'], value=challenge['difficulty'])
if attribute['name'] == "Released":
release_str = challenge['release_date']
release_date = datetime.strptime(release_str, "%Y-%m-%dT%H:%M:%S.%fZ")
formatted_release_date = release_date.strftime("%d %B %Y")
ea.patch_attribute(attributeId=attribute['attributeId'], value=formatted_release_date)
if attribute['name'] == "Solved":
if challenge['is_owned']:
ea.patch_attribute(attributeId=attribute['attributeId'], value="done")
else:
ea.patch_attribute(attributeId=attribute['attributeId'], value=" ")
if attribute['name'] == "cssClass":
if challenge['is_owned']:
ea.patch_attribute(attributeId=attribute['attributeId'], value="done")
else:
ea.patch_attribute(attributeId=attribute['attributeId'], value="todo")
 
if res2['results']:
note_title = normalise_title(res2['results'][0]['title'])
challenge_title = normalise_title(challenge['name'])
 
if note_title == challenge_title:
 
for attribute in res2['results'][0]['attributes']:
if attribute['name'] == "Difficulty":
ea.patch_attribute(attributeId=attribute['attributeId'], value=challenge['difficulty'])
if attribute['name'] == "Released":
release_str = challenge['release_date']
release_date = datetime.strptime(release_str, "%Y-%m-%dT%H:%M:%S.%fZ")
formatted_release_date = release_date.strftime("%d %B %Y")
ea.patch_attribute(attributeId=attribute['attributeId'], value=formatted_release_date)
if attribute['name'] == "Solved":
if challenge['is_owned']:
ea.patch_attribute(attributeId=attribute['attributeId'], value="done")
else:
ea.patch_attribute(attributeId=attribute['attributeId'], value=" ")
if attribute['name'] == "cssClass":
if challenge['is_owned']:
ea.patch_attribute(attributeId=attribute['attributeId'], value="done")
else:
ea.patch_attribute(attributeId=attribute['attributeId'], value="todo")
 
else: # doesnt already exist, create page
release_str = challenge['release_date']
release_date = datetime.strptime(release_str, "%Y-%m-%dT%H:%M:%S.%fZ")
View
13
htb2trilium/htb2trilium_machines.py
for machine in machines:
machine_count += 1
print('processing: ',machine_count, "/", len(machines), "("+machine['name']+") " , end='\r')
 
escaped_title = machine['name'].replace("'", "\\'")
res = ea.search_note(
search="\""+machine['name']+"\"",
ancestorNoteId=trilium_machines_htb_folder,
ancestorDepth='eq1',
limit=1,
fastSearch=True,
search=f"note.title = '{escaped_title}'",
ancestorNoteId=trilium_machines_htb_folder,
ancestorDepth='eq1',
limit=1,
)
 
if res['results'] and machine['name'] == res['results'][0]['title']:
if res['results'] and machine['name'].strip().lower() == res['results'][0]['title'].strip().lower():
# page exists - lets check if the details have changed
 
current_html = ea.get_note_content(noteId=res['results'][0]['noteId'])
current_soup = BeautifulSoup(current_html, 'html.parser')
Buy Me A Coffee