-
+
+
+
+
+
+
-
+
+
+
+
+
+
{% endblock content %}
\ No newline at end of file
diff --git a/openlibrarian_root/almanac/templates/almanac/user_profile.html b/openlibrarian_root/almanac/templates/almanac/user_profile.html
index 8affca5..1b10d0c 100644
--- a/openlibrarian_root/almanac/templates/almanac/user_profile.html
+++ b/openlibrarian_root/almanac/templates/almanac/user_profile.html
@@ -112,7 +112,7 @@
-
+
diff --git a/openlibrarian_root/almanac/views.py b/openlibrarian_root/almanac/views.py
index 52495ff..9cae2dd 100644
--- a/openlibrarian_root/almanac/views.py
+++ b/openlibrarian_root/almanac/views.py
@@ -3,7 +3,7 @@
from utils.Session import async_logged_in, async_get_session_info, async_set_session_info, cache_get, cache_set, cache_key, cache_delete
from utils.Profile import edit_profile_info, edit_relay_list, fetch_profile_info
from utils.Login import check_nsec
-from utils.Connections import fetch_social_list
+from utils.Connections import fetch_social_list, add_follow
from nostr_sdk import Keys
# Users Settings View
@@ -173,9 +173,17 @@ async def user_friends(request):
friends = connctions['friends']
muted = connctions['muted']
+ notification = None
+
# POST requests
if request.method == 'POST':
- if request.POST.get('refresh'):
+ if request.POST.get('refresh') or request.POST.get('follow_user'):
+
+ # Attempt to add new follow
+ if request.POST.get('follow_user'):
+ notification = await add_follow(session['relays'], npub=session['npub'], nsec=session['nsec'], follow_id=request.POST.get('follow_user'))
+
+ # Fetch lists again
friends = await fetch_social_list(relays=session['relays'], npub=session['npub'], list_type="follow")
muted = await fetch_social_list(relays=session['relays'], npub=session['npub'], list_type="mute")
@@ -183,4 +191,4 @@ async def user_friends(request):
await cache_delete(await cache_key(key_str,session))
await cache_set(await cache_key(key_str,session), {'friends': friends, 'muted': muted}, 1800)
- return render(request, 'almanac/user_friends.html', {'session': session, 'friends': friends, 'muted': muted})
\ No newline at end of file
+ return render(request, 'almanac/user_friends.html', {'session': session, 'friends': friends, 'muted': muted, 'notification': notification})
\ No newline at end of file
diff --git a/openlibrarian_root/library_card/templates/library_card/card.html b/openlibrarian_root/library_card/templates/library_card/card.html
index 39148f9..a02c560 100644
--- a/openlibrarian_root/library_card/templates/library_card/card.html
+++ b/openlibrarian_root/library_card/templates/library_card/card.html
@@ -103,7 +103,7 @@
Explore my Profile or Build your Own!
-
+
diff --git a/openlibrarian_root/static/js/add-toast.js b/openlibrarian_root/static/js/add-toast.js
index 591d603..05e81ab 100644
--- a/openlibrarian_root/static/js/add-toast.js
+++ b/openlibrarian_root/static/js/add-toast.js
@@ -5,7 +5,7 @@ if (notification && notification !== "None") {
const toastContainer = document.getElementById('toastContainer');
const toast = document.createElement('div');
toast.classList.add('toast', 'align-items-center', 'text-white', 'bg-success', 'border-0');
- if (notification === "Book already in library.") {
+ if (notification === "Book already in library." || notification === "Already Following.") {
toast.classList.remove('bg-success');
toast.classList.add('bg-danger');
}
diff --git a/openlibrarian_root/static/js/copy-toast.js b/openlibrarian_root/static/js/copy-toast.js
index 39b9099..5c422f9 100644
--- a/openlibrarian_root/static/js/copy-toast.js
+++ b/openlibrarian_root/static/js/copy-toast.js
@@ -12,7 +12,7 @@ copyButtons.forEach(button => {
document.execCommand('copy');
document.body.removeChild(textarea);
- const toastContainer = document.getElementById('toastContainer');
+ const toastContainer = document.getElementById('copytoastContainer');
const toast = document.createElement('div');
toast.classList.add('toast', 'align-items-center', 'text-white', 'bg-success', 'border-0');
toast.setAttribute('role', 'alert');
diff --git a/openlibrarian_root/utils/Connections.py b/openlibrarian_root/utils/Connections.py
index 73ec04e..bf003a8 100644
--- a/openlibrarian_root/utils/Connections.py
+++ b/openlibrarian_root/utils/Connections.py
@@ -1,4 +1,4 @@
-from nostr_sdk import Client, Filter, Kind, KindEnum, Metadata, PublicKey, TagKind, SingleLetterTag, Alphabet, Keys, NostrSigner, EventBuilder, Contact
+from nostr_sdk import Client, Filter, Kind, KindEnum, Metadata, PublicKey, Keys, NostrSigner, EventBuilder, get_nip05_profile, Tag
from utils.Network import nostr_get, nostr_post
from utils.Login import check_npub, check_nsec
@@ -25,7 +25,8 @@ async def fetch_social_list(relays: dict, npub: str = None, list_type: str = "fo
follow_list = []
if eventlist:
for tag in eventlist[0].tags():
- follow_list.append(PublicKey.from_hex(tag.content()))
+ if tag.as_vec()[0] == "p":
+ follow_list.append(PublicKey.from_hex(tag.content()))
# Get following and related profile data
f = Filter().kind(Kind(0)).authors(follow_list)
@@ -101,5 +102,48 @@ async def clone_follow(relays: dict, npub: str = None, nsec: str = None):
await nostr_post(client=client, relays_dict=relays, eventbuilder=mute_builder, connect=False, disconnect=True)
+async def add_follow(relays: dict, npub: str = None, nsec: str = None, follow_id: str = None):
+ if npub in [None, ""] or check_npub(npub) is False:
+ raise Exception("Invalid or missing npub")
+ if nsec in [None, ""] or check_nsec(nsec) is False:
+ raise Exception("Invalid or missing nsec")
+ if follow_id in [None, ""]:
+ raise Exception("Missing follow value")
+
+ # Check if follow is a valid pubkey or nip05 and get key
+ if check_npub(follow_id) is True:
+ follow_key = PublicKey.parse(follow_id)
+ else:
+ try:
+ profile = await get_nip05_profile(follow_id,None)
+ follow_key = profile.public_key()
+ except:
+ return "Invalid npub or nip05"
+ # Keys
+ keys = Keys.parse(nsec)
+
+ # Signer
+ signer = NostrSigner.keys(keys)
+ client = Client(signer)
+
+ # Request profile Metadata
+ follow_filter = Filter().kind(Kind.from_enum(KindEnum.CONTACT_LIST())).author(keys.public_key()).limit(1)
+
+ # Get following list and extract p tags
+ follow_events = await nostr_get(client=client, filters=[follow_filter], relays_dict=relays, wait=10, connect=True, disconnect=True)
+
+ for follow in follow_events:
+ if Tag.public_key(follow_key) not in follow.tags():
+ follow.tags().append(Tag.public_key(follow_key))
+
+ # Build follow event
+ follow_builder = EventBuilder(kind=Kind.from_enum(KindEnum.CONTACT_LIST()), tags=follow.tags(), content="")
+
+ # Post events
+ await nostr_post(client=client, relays_dict=relays, eventbuilder=follow_builder, connect=True, disconnect=True)
+ return "Added Friend."
+
+ else:
+ return "Already Following."