From 8a3fffa6a84b6c26c32d0f91076f9ba716fd2e4b Mon Sep 17 00:00:00 2001 From: Lakshya Jain <147808548+lakshyajain-0291@users.noreply.github.com> Date: Fri, 22 Aug 2025 21:24:25 +0530 Subject: [PATCH 01/11] Fix URL construction for libr installation --- scripts/install-libr.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/install-libr.sh b/scripts/install-libr.sh index c278f14..c27fa92 100755 --- a/scripts/install-libr.sh +++ b/scripts/install-libr.sh @@ -27,8 +27,7 @@ echo "πŸ“¦ Installing libr $VERSION for $DISTRO ($ARCH)..." case "$DISTRO" in ubuntu|debian) - DEB_VERSION=$(echo "$VERSION") - URL="https://github.com/libr-forum/libr/releases/download/$VERSION/libr_${DEB_VERSION}_${ARCH}.deb" + URL="https://github.com/libr-forum/libr/releases/download/$VERSION/libr_${VERSION}_${ARCH}.deb" echo "⬇️ Downloading $URL..." wget -O libr.deb "$URL" || { echo "❌ Failed to download $URL"; exit 1; } sudo dpkg -i libr.deb || sudo apt-get install -f -y From fa14adddb17638e1f14ea643c41e1076edb4059e Mon Sep 17 00:00:00 2001 From: Lakshya Jain <147808548+lakshyajain-0291@users.noreply.github.com> Date: Fri, 22 Aug 2025 21:41:27 +0530 Subject: [PATCH 02/11] Improve installation script with error messages Enhanced error handling during package installation and download. --- scripts/install-libr.sh | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/scripts/install-libr.sh b/scripts/install-libr.sh index c27fa92..c32edba 100755 --- a/scripts/install-libr.sh +++ b/scripts/install-libr.sh @@ -30,19 +30,34 @@ case "$DISTRO" in URL="https://github.com/libr-forum/libr/releases/download/$VERSION/libr_${VERSION}_${ARCH}.deb" echo "⬇️ Downloading $URL..." wget -O libr.deb "$URL" || { echo "❌ Failed to download $URL"; exit 1; } - sudo dpkg -i libr.deb || sudo apt-get install -f -y + echo "βš™οΈ Installing .deb package..." + sudo dpkg -i libr.deb || { + echo "⚠️ dpkg failed, trying apt-get -f install..."; + sudo apt-get install -f -y; + } + echo "🧹 Cleaning up..." rm libr.deb ;; fedora|rhel|centos) URL="https://github.com/libr-forum/libr/releases/download/$VERSION/libr-${VERSION}.${ARCH}.rpm" - wget -qO libr.rpm "$URL" - sudo dnf install -y ./libr.rpm || sudo yum install -y ./libr.rpm + echo "⬇️ Downloading $URL..." + wget -O libr.rpm "$URL" || { echo "❌ Failed to download $URL"; exit 1; } + echo "βš™οΈ Installing .rpm package..." + if command -v dnf >/dev/null 2>&1; then + sudo dnf install -y ./libr.rpm + else + sudo yum install -y ./libr.rpm + fi + echo "🧹 Cleaning up..." rm libr.rpm ;; arch) URL="https://github.com/libr-forum/libr/releases/download/$VERSION/libr-${VERSION}-${ARCH}.pkg.tar.zst" - wget -qO libr.pkg.tar.zst "$URL" + echo "⬇️ Downloading $URL..." + wget -O libr.pkg.tar.zst "$URL" || { echo "❌ Failed to download $URL"; exit 1; } + echo "βš™οΈ Installing Arch package..." sudo pacman -U --noconfirm libr.pkg.tar.zst + echo "🧹 Cleaning up..." rm libr.pkg.tar.zst ;; *) From 4e660bf646e9f50b0e52d3423e560d008c0b2c50 Mon Sep 17 00:00:00 2001 From: Lakshya Jain <147808548+lakshyajain-0291@users.noreply.github.com> Date: Fri, 22 Aug 2025 21:50:54 +0530 Subject: [PATCH 03/11] Fix URL format for Arch package download --- scripts/install-libr.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/install-libr.sh b/scripts/install-libr.sh index c32edba..e62e12b 100755 --- a/scripts/install-libr.sh +++ b/scripts/install-libr.sh @@ -52,7 +52,7 @@ case "$DISTRO" in rm libr.rpm ;; arch) - URL="https://github.com/libr-forum/libr/releases/download/$VERSION/libr-${VERSION}-${ARCH}.pkg.tar.zst" + URL="https://github.com/libr-forum/libr/releases/download/$VERSION/libr_${VERSION}-${ARCH}.pkg.tar.zst" echo "⬇️ Downloading $URL..." wget -O libr.pkg.tar.zst "$URL" || { echo "❌ Failed to download $URL"; exit 1; } echo "βš™οΈ Installing Arch package..." From 8f6b6e8c5b3d56989963b027569e77885fc3b82a Mon Sep 17 00:00:00 2001 From: Lakshya Jain <147808548+lakshyajain-0291@users.noreply.github.com> Date: Sat, 23 Aug 2025 20:54:48 +0530 Subject: [PATCH 04/11] Update install-libr.sh --- scripts/install-libr.sh | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/scripts/install-libr.sh b/scripts/install-libr.sh index e62e12b..4949624 100755 --- a/scripts/install-libr.sh +++ b/scripts/install-libr.sh @@ -21,6 +21,19 @@ fi if [ "$INSTALLED_VERSION" = "$VERSION" ]; then echo "βœ… libr $VERSION already installed." exit 0 +elif [ "$INSTALLED_VERSION" != "none" ]; then + echo "♻️ Removing old version ($INSTALLED_VERSION)..." + case "$DISTRO" in + ubuntu|debian) + sudo apt-get remove -y libr || true + ;; + fedora|rhel|centos) + sudo dnf remove -y libr || sudo yum remove -y libr || true + ;; + arch) + sudo pacman -Rns --noconfirm libr || true + ;; + esac fi echo "πŸ“¦ Installing libr $VERSION for $DISTRO ($ARCH)..." @@ -32,11 +45,23 @@ case "$DISTRO" in wget -O libr.deb "$URL" || { echo "❌ Failed to download $URL"; exit 1; } echo "βš™οΈ Installing .deb package..." sudo dpkg -i libr.deb || { - echo "⚠️ dpkg failed, trying apt-get -f install..."; + echo "⚠️ dpkg failed, fixing dependencies..."; sudo apt-get install -f -y; } echo "🧹 Cleaning up..." rm libr.deb + + # Fix WebKitGTK compatibility issues (quietly) + echo "πŸ”§ Checking WebKitGTK compatibility..." + if ! ldconfig -p | grep -q "libwebkit2gtk-4.0.so.37"; then + sudo apt update -qq + sudo apt install -y libwebkit2gtk-4.1-0 libjavascriptcoregtk-4.1-0 + sudo ln -sf /usr/lib/x86_64-linux-gnu/libwebkit2gtk-4.1.so.0 \ + /usr/lib/x86_64-linux-gnu/libwebkit2gtk-4.0.so.37 || true + sudo ln -sf /usr/lib/x86_64-linux-gnu/libjavascriptcoregtk-4.1.so.0 \ + /usr/lib/x86_64-linux-gnu/libjavascriptcoregtk-4.0.so.18 || true + echo "βœ… WebKitGTK compatibility fixed." + fi ;; fedora|rhel|centos) URL="https://github.com/libr-forum/libr/releases/download/$VERSION/libr-${VERSION}.${ARCH}.rpm" @@ -52,7 +77,7 @@ case "$DISTRO" in rm libr.rpm ;; arch) - URL="https://github.com/libr-forum/libr/releases/download/$VERSION/libr_${VERSION}-${ARCH}.pkg.tar.zst" + URL="https://github.com/libr-forum/libr/releases/download/$VERSION/libr-${VERSION}-${ARCH}.pkg.tar.zst" echo "⬇️ Downloading $URL..." wget -O libr.pkg.tar.zst "$URL" || { echo "❌ Failed to download $URL"; exit 1; } echo "βš™οΈ Installing Arch package..." From a31e263a67d28103a65c90e4dd8f3c925a76a227 Mon Sep 17 00:00:00 2001 From: Lakshya Jain <147808548+lakshyajain-0291@users.noreply.github.com> Date: Sat, 23 Aug 2025 21:04:41 +0530 Subject: [PATCH 05/11] Refactor install-libr.sh for better error handling --- scripts/install-libr.sh | 120 ++++++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 54 deletions(-) diff --git a/scripts/install-libr.sh b/scripts/install-libr.sh index 4949624..2d437ad 100755 --- a/scripts/install-libr.sh +++ b/scripts/install-libr.sh @@ -1,94 +1,106 @@ #!/bin/bash -set -e +set -euo pipefail -# Detect distribution -source /etc/os-release -DISTRO=$ID +# ============================================================ +# LIBR Installer Script +# Supports: Ubuntu/Debian, Fedora/RHEL/CentOS, Arch +# ============================================================ + +# --- Debug logging helper --- +log() { echo -e "πŸ‘‰ $1"; } +success() { echo -e "βœ… $1"; } +error() { echo -e "❌ $1" >&2; } + +# --- Detect distribution & architecture --- +if [ -f /etc/os-release ]; then + source /etc/os-release + DISTRO=$ID +else + error "Cannot detect distribution!" + exit 1 +fi ARCH=$(dpkg --print-architecture 2>/dev/null || uname -m) -# Fetch latest or use provided version +# --- Fetch latest or use provided version --- LATEST_VERSION=$(curl -s https://api.github.com/repos/libr-forum/libr/releases/latest \ | grep tag_name | cut -d '"' -f4) VERSION=${1:-$LATEST_VERSION} -# Check installed version +# --- Check installed version --- if command -v libr >/dev/null 2>&1; then - INSTALLED_VERSION=$(libr --version | awk '{print $2}') + INSTALLED_VERSION=$(libr --version 2>/dev/null | awk '{print $2}') else INSTALLED_VERSION="none" fi if [ "$INSTALLED_VERSION" = "$VERSION" ]; then - echo "βœ… libr $VERSION already installed." + success "libr $VERSION is already installed." exit 0 -elif [ "$INSTALLED_VERSION" != "none" ]; then - echo "♻️ Removing old version ($INSTALLED_VERSION)..." +fi + +log "πŸ“¦ Installing libr $VERSION for $DISTRO ($ARCH)..." + +# --- GTK check & install (only if missing) --- +install_gtk_if_missing() { case "$DISTRO" in ubuntu|debian) - sudo apt-get remove -y libr || true + if ! dpkg -l | grep -q libgtk-3-0; then + log "Installing GTK dependencies..." + sudo apt-get update -y + sudo apt-get install -y libgtk-3-0 || log "GTK install skipped" + else + log "GTK already present, skipping." + fi ;; fedora|rhel|centos) - sudo dnf remove -y libr || sudo yum remove -y libr || true + if ! rpm -q gtk3 >/dev/null 2>&1; then + log "Installing GTK dependencies..." + sudo dnf install -y gtk3 || sudo yum install -y gtk3 || log "GTK install skipped" + else + log "GTK already present, skipping." + fi ;; arch) - sudo pacman -Rns --noconfirm libr || true + if ! pacman -Q gtk3 >/dev/null 2>&1; then + log "Installing GTK dependencies..." + sudo pacman -Sy --noconfirm gtk3 || log "GTK install skipped" + else + log "GTK already present, skipping." + fi ;; esac -fi - -echo "πŸ“¦ Installing libr $VERSION for $DISTRO ($ARCH)..." +} +# --- Main installation per distro --- case "$DISTRO" in ubuntu|debian) URL="https://github.com/libr-forum/libr/releases/download/$VERSION/libr_${VERSION}_${ARCH}.deb" - echo "⬇️ Downloading $URL..." - wget -O libr.deb "$URL" || { echo "❌ Failed to download $URL"; exit 1; } - echo "βš™οΈ Installing .deb package..." - sudo dpkg -i libr.deb || { - echo "⚠️ dpkg failed, fixing dependencies..."; - sudo apt-get install -f -y; - } - echo "🧹 Cleaning up..." - rm libr.deb - - # Fix WebKitGTK compatibility issues (quietly) - echo "πŸ”§ Checking WebKitGTK compatibility..." - if ! ldconfig -p | grep -q "libwebkit2gtk-4.0.so.37"; then - sudo apt update -qq - sudo apt install -y libwebkit2gtk-4.1-0 libjavascriptcoregtk-4.1-0 - sudo ln -sf /usr/lib/x86_64-linux-gnu/libwebkit2gtk-4.1.so.0 \ - /usr/lib/x86_64-linux-gnu/libwebkit2gtk-4.0.so.37 || true - sudo ln -sf /usr/lib/x86_64-linux-gnu/libjavascriptcoregtk-4.1.so.0 \ - /usr/lib/x86_64-linux-gnu/libjavascriptcoregtk-4.0.so.18 || true - echo "βœ… WebKitGTK compatibility fixed." - fi + log "⬇️ Downloading $URL" + wget -qO libr.deb "$URL" || { error "Failed to download $URL"; exit 1; } + sudo dpkg -i libr.deb || sudo apt-get install -f -y + rm -f libr.deb + install_gtk_if_missing ;; fedora|rhel|centos) URL="https://github.com/libr-forum/libr/releases/download/$VERSION/libr-${VERSION}.${ARCH}.rpm" - echo "⬇️ Downloading $URL..." - wget -O libr.rpm "$URL" || { echo "❌ Failed to download $URL"; exit 1; } - echo "βš™οΈ Installing .rpm package..." - if command -v dnf >/dev/null 2>&1; then - sudo dnf install -y ./libr.rpm - else - sudo yum install -y ./libr.rpm - fi - echo "🧹 Cleaning up..." - rm libr.rpm + log "⬇️ Downloading $URL" + wget -qO libr.rpm "$URL" || { error "Failed to download $URL"; exit 1; } + sudo dnf install -y ./libr.rpm || sudo yum install -y ./libr.rpm + rm -f libr.rpm + install_gtk_if_missing ;; arch) URL="https://github.com/libr-forum/libr/releases/download/$VERSION/libr-${VERSION}-${ARCH}.pkg.tar.zst" - echo "⬇️ Downloading $URL..." - wget -O libr.pkg.tar.zst "$URL" || { echo "❌ Failed to download $URL"; exit 1; } - echo "βš™οΈ Installing Arch package..." + log "⬇️ Downloading $URL" + wget -qO libr.pkg.tar.zst "$URL" || { error "Failed to download $URL"; exit 1; } sudo pacman -U --noconfirm libr.pkg.tar.zst - echo "🧹 Cleaning up..." - rm libr.pkg.tar.zst + rm -f libr.pkg.tar.zst + install_gtk_if_missing ;; *) - echo "❌ Unsupported distribution: $DISTRO" + error "Unsupported distribution: $DISTRO" exit 1 ;; esac -echo "βœ… libr $VERSION installed successfully." +success "libr $VERSION installed successfully." From 4f5dd37349538da5eb008e50be13f93fe771d8f9 Mon Sep 17 00:00:00 2001 From: Lakshya Jain <147808548+lakshyajain-0291@users.noreply.github.com> Date: Sat, 23 Aug 2025 21:09:19 +0530 Subject: [PATCH 06/11] Refactor SUPPORT.md to remove duplicates --- SUPPORT.md | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/SUPPORT.md b/SUPPORT.md index 17a9381..090fa77 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -5,7 +5,6 @@ Thanks for using LIBR! Here's how to get help when you need it. ## πŸš€ Quick Help ### πŸ› **Found a Bug?** -<<<<<<< HEAD [Create a Bug Report](https://github.com/libr-forum/libr/issues/new?template=bug_report.md) ### πŸ’‘ **Have an Idea?** @@ -13,15 +12,6 @@ Thanks for using LIBR! Here's how to get help when you need it. ### ❓ **Need Help?** [Ask in Q&A Discussions](https://github.com/libr-forum/libr/discussions/categories/q-a) -======= -[Create a Bug Report](https://github.com/libr-forum/libr/issues/new?template=bug_report.md) - -### πŸ’‘ **Have an Idea?** -[Share it in Discussions](https://github.com/libr-forum/libr/discussions/categories/ideas-feature-requests) - -### ❓ **Need Help?** -[Ask in Q&A Discussions](https://github.com/libr-forum/libr/discussions/categories/q-a) ->>>>>>> 9778abfea970abad1ec6f572173b51b742c8068d ## πŸ“š **Documentation** @@ -50,11 +40,7 @@ git checkout -b update-readme **Stuck with Git?** - **Beginner Git Guide:** [git-scm.com/book](https://git-scm.com/book) - **Interactive Git Tutorial:** [learngitbranching.js.org](https://learngitbranching.js.org/) -<<<<<<< HEAD -- **Ask for help:** [Q&A Discussions](https://github.com/libr-forum/libr/discussions/categories/q-a) -======= - **Ask for help:** [Q&A Discussions](https://github.com/libr-forum/libr/discussions/categories/q-a) ->>>>>>> 9778abfea970abad1ec6f572173b51b742c8068d ### Common Workflow Questions @@ -74,27 +60,16 @@ git rebase main **"My branch has conflicts, help!"** 1. Don't panic! 😊 -<<<<<<< HEAD 2. Ask in [Discussions](https://github.com/libr-forum/libr/discussions) -======= -2. Ask in [Discussions](https://github.com/libr-forum/libr/discussions) ->>>>>>> 9778abfea970abad1ec6f572173b51b742c8068d 3. Our maintainers will help you resolve them ## πŸ’¬ **Community Channels** ### GitHub Discussions (Primary) -<<<<<<< HEAD - **[General Discussion](https://github.com/libr-forum/libr/discussions/categories/general)** - Chat about anything LIBR-related - **[Q&A](https://github.com/libr-forum/libr/discussions/categories/q-a)** - Get help from the community - **[Ideas](https://github.com/libr-forum/libr/discussions/categories/ideas-feature-requests)** - Share feature requests and ideas - **[Show and Tell](https://github.com/libr-forum/libr/discussions/categories/show-and-tell)** - Share what you've built -======= -- **[General Discussion](https://github.com/libr-forum/libr/discussions/categories/general)** - Chat about anything LIBR-related -- **[Q&A](https://github.com/libr-forum/libr/discussions/categories/q-a)** - Get help from the community -- **[Ideas](https://github.com/libr-forum/libr/discussions/categories/ideas-feature-requests)** - Share feature requests and ideas -- **[Show and Tell](https://github.com/libr-forum/libr/discussions/categories/show-and-tell)** - Share what you've built ->>>>>>> 9778abfea970abad1ec6f572173b51b742c8068d ### Email Support For private matters or security issues: **devlup@iitj.ac.in** @@ -104,11 +79,7 @@ For private matters or security issues: **devlup@iitj.ac.in** If you're new to open source or Git/GitHub: 1. **Start here:** [New Contributor Guide](docs/BEGINNER_GUIDE.md) -<<<<<<< HEAD -2. **Look for:** Issues labeled [`good first issue`](https://github.com/libr-forum/libr/labels/good%20first%20issue) -======= 2. **Look for:** Issues labeled [`good first issue`](https://github.com/libr-forum/libr/labels/good%20first%20issue) ->>>>>>> 9778abfea970abad1ec6f572173b51b742c8068d 3. **Learn Git:** We have [branch naming guidelines](CONTRIBUTING.md#-branch-naming--workflow-guidelines) to help you! 4. **Get help:** Our [maintainers](docs/MAINTAINER_GUIDE.md) are here to help! @@ -123,11 +94,7 @@ If you're new to open source or Git/GitHub: ### Setup Issues - **Project won't build?** Run `./scripts/setup.sh` first - **Dependencies missing?** Check our [setup guide](docs/BEGINNER_GUIDE.md#first-time-setup) -<<<<<<< HEAD -- **Still stuck?** Create an issue with the [`help wanted`](https://github.com/libr-forum/libr/labels/help%20wanted) label -======= - **Still stuck?** Create an issue with the [`help wanted`](https://github.com/libr-forum/libr/labels/help%20wanted) label ->>>>>>> 9778abfea970abad1ec6f572173b51b742c8068d ### Development Questions - **Don't know which file to edit?** Ask in discussions first From 75974e7fb35c3b03f3f848a16ab9d4fd017f3bb3 Mon Sep 17 00:00:00 2001 From: Lakshya Jain <147808548+lakshyajain-0291@users.noreply.github.com> Date: Sat, 23 Aug 2025 21:14:51 +0530 Subject: [PATCH 07/11] Update install-libr.sh --- scripts/install-libr.sh | 262 +++++++++++++++++++++++++++++----------- 1 file changed, 191 insertions(+), 71 deletions(-) diff --git a/scripts/install-libr.sh b/scripts/install-libr.sh index 2d437ad..c9767ca 100755 --- a/scripts/install-libr.sh +++ b/scripts/install-libr.sh @@ -1,106 +1,226 @@ -#!/bin/bash -set -euo pipefail +#!/usr/bin/env bash +# LIBR cross-distro installer with verbose debugging +# Usage: +# curl -fsSL https://raw.githubusercontent.com/libr-forum/Libr/main/scripts/install-libr.sh | bash +# curl -fsSL .../install-libr.sh | DEBUG=1 bash -s -- v1.0.0-beta # install specific version with debug +set -Eeuo pipefail -# ============================================================ -# LIBR Installer Script -# Supports: Ubuntu/Debian, Fedora/RHEL/CentOS, Arch -# ============================================================ +DEBUG="${DEBUG:-1}" # 1/true = verbose with xtrace; 0/false = quieter +if [[ "$DEBUG" =~ ^(1|true|yes)$ ]]; then set -x; fi -# --- Debug logging helper --- -log() { echo -e "πŸ‘‰ $1"; } -success() { echo -e "βœ… $1"; } -error() { echo -e "❌ $1" >&2; } +info() { echo -e "[INFO] $*"; } +debug() { [[ "$DEBUG" =~ ^(1|true|yes)$ ]] && echo -e "[DEBUG] $*"; } +warn() { echo -e "[WARN] $*" >&2; } +err() { echo -e "[ERROR] $*" >&2; } # --- Detect distribution & architecture --- -if [ -f /etc/os-release ]; then +if [[ -f /etc/os-release ]]; then + # shellcheck disable=SC1091 source /etc/os-release - DISTRO=$ID + DISTRO="${ID:-unknown}" + DISTRO_VER="${VERSION_ID:-unknown}" + CODENAME="${VERSION_CODENAME:-}" else - error "Cannot detect distribution!" + err "Cannot detect distribution (missing /etc/os-release)." exit 1 fi -ARCH=$(dpkg --print-architecture 2>/dev/null || uname -m) -# --- Fetch latest or use provided version --- -LATEST_VERSION=$(curl -s https://api.github.com/repos/libr-forum/libr/releases/latest \ - | grep tag_name | cut -d '"' -f4) -VERSION=${1:-$LATEST_VERSION} +# Debian/Ubuntu: dpkg prints 'amd64', else fall back to uname -m +ARCH="$(dpkg --print-architecture 2>/dev/null || uname -m)" +DEB_ARCH="$ARCH" +# Map to RPM arch naming +case "$ARCH" in + amd64) RPM_ARCH="x86_64" ;; + arm64|aarch64) RPM_ARCH="aarch64" ;; + *) RPM_ARCH="$ARCH" ;; +esac +# Arch Linux typically uses uname -m like x86_64/aarch64 +PAC_ARCH="$(uname -m)" -# --- Check installed version --- -if command -v libr >/dev/null 2>&1; then - INSTALLED_VERSION=$(libr --version 2>/dev/null | awk '{print $2}') -else - INSTALLED_VERSION="none" +info "Detected: DISTRO=$DISTRO $DISTRO_VER $CODENAME ARCH=$ARCH RPM_ARCH=$RPM_ARCH PAC_ARCH=$PAC_ARCH" + +# --- Fetch latest or use provided version (tag from GitHub) --- +REPO="libr-forum/libr" +LATEST_VERSION="$(curl -fsSL "https://api.github.com/repos/${REPO}/releases/latest" | awk -F'"' '/tag_name/{print $4; exit}')" +INPUT_VERSION="${1:-}" +VERSION="${INPUT_VERSION:-$LATEST_VERSION}" + +if [[ -z "${VERSION:-}" ]]; then + err "Could not determine version (GitHub API returned no tag)." + exit 1 fi -if [ "$INSTALLED_VERSION" = "$VERSION" ]; then - success "libr $VERSION is already installed." - exit 0 +# Useful normalized variants for logging/diagnostics +VERSION_NO_V="${VERSION#v}" # v1.0.0-beta -> 1.0.0-beta +DEB_VERSION="$(printf '%s' "$VERSION_NO_V" | sed 's/-/~/g')" # 1.0.0-beta -> 1.0.0~beta +debug "Version forms: RAW_TAG=$VERSION NO_V=$VERSION_NO_V DEB_VERSION=$DEB_VERSION" + +# --- Determine installed version via package manager FIRST (avoids launching UI) --- +INSTALLED_VERSION="none" +case "$DISTRO" in + ubuntu|debian) + INSTALLED_VERSION="$(dpkg-query -W -f='${Version}\n' libr 2>/dev/null || true)" + ;; + fedora|rhel|centos) + # %EVR is epoch:version-release; we’ll log it; comparison is just a best-effort here + INSTALLED_VERSION="$(rpm -q --qf '%{EVR}\n' libr 2>/dev/null || true)" + ;; + arch) + INSTALLED_VERSION="$(pacman -Q libr 2>/dev/null | awk '{print $2}' || true)" + ;; + *) + warn "Unsupported distro for package-query; will try 'libr --version' fallback." + ;; +esac + +# Fallback: try not to launch UI; if 'libr --version' prints, capture it +if [[ -z "$INSTALLED_VERSION" || "$INSTALLED_VERSION" == "none" ]]; then + if command -v libr >/dev/null 2>&1; then + # Expect lines like: "libr 1.0.0" or "libr v1.0.0-beta" + INSTALLED_VERSION="$(libr --version 2>/dev/null | awk '{print $2}')" + fi fi -log "πŸ“¦ Installing libr $VERSION for $DISTRO ($ARCH)..." +INSTALLED_VERSION="${INSTALLED_VERSION:-none}" +info "Installed version detected: '$INSTALLED_VERSION'" + +# --- Decide if we need to install --- +# We consider a match if any of these match (helps across packaging/tag formats): +match_versions() { + local inst="$1" tag="$2" nov="$3" debv="$4" + [[ -z "$inst" || "$inst" == "none" ]] && return 1 + [[ "$inst" == "$tag" ]] && return 0 + [[ "$inst" == "$nov" ]] && return 0 + [[ "$inst" == "$debv" ]] && return 0 + return 1 +} + +if match_versions "$INSTALLED_VERSION" "$VERSION" "$VERSION_NO_V" "$DEB_VERSION"; then + info "libr is already at the requested version (match found). Skipping reinstall." + exit 0 +fi -# --- GTK check & install (only if missing) --- -install_gtk_if_missing() { +if [[ "$INSTALLED_VERSION" != "none" ]]; then + info "Removing existing libr ($INSTALLED_VERSION) before install/update…" case "$DISTRO" in - ubuntu|debian) - if ! dpkg -l | grep -q libgtk-3-0; then - log "Installing GTK dependencies..." - sudo apt-get update -y - sudo apt-get install -y libgtk-3-0 || log "GTK install skipped" - else - log "GTK already present, skipping." - fi - ;; - fedora|rhel|centos) - if ! rpm -q gtk3 >/dev/null 2>&1; then - log "Installing GTK dependencies..." - sudo dnf install -y gtk3 || sudo yum install -y gtk3 || log "GTK install skipped" - else - log "GTK already present, skipping." - fi - ;; - arch) - if ! pacman -Q gtk3 >/dev/null 2>&1; then - log "Installing GTK dependencies..." - sudo pacman -Sy --noconfirm gtk3 || log "GTK install skipped" - else - log "GTK already present, skipping." - fi - ;; + ubuntu|debian) sudo apt-get remove -y libr || true ;; + fedora|rhel|centos) sudo dnf remove -y libr || sudo yum remove -y libr || true ;; + arch) sudo pacman -Rns --noconfirm libr || true ;; + *) warn "Skip removal on unsupported distro '$DISTRO'."; ;; esac +fi + +info "Proceeding to install libr $VERSION on $DISTRO ($ARCH)…" + +# --- Helpers: probe URL & download with status --- +probe_url() { + local url="$1" + local code + code="$(curl -s -o /dev/null -w '%{http_code}' "$url" || echo 000)" + debug "HTTP probe $url -> $code" + printf '%s' "$code" } -# --- Main installation per distro --- +download_file() { + local url="$1" out="$2" + info "Downloading: $url" + local code; code="$(probe_url "$url")" + if [[ "$code" != "200" ]]; then + err "URL not reachable (HTTP $code): $url" + return 1 + fi + curl -fSL "$url" -o "$out" +} + +# --- Optional: Only apply WebKitGTK shim if the old SONAME is missing (Ubuntu/Debian only) --- +maybe_fix_webkit_ubuntu() { + # Only on Debian/Ubuntu & only on amd64 path below + [[ "$DISTRO" != "ubuntu" && "$DISTRO" != "debian" ]] && { debug "WebKit fix: not Debian/Ubuntu, skip."; return 0; } + local libdir="/usr/lib/x86_64-linux-gnu" + if [[ "$DEB_ARCH" != "amd64" || ! -d "$libdir" ]]; then + debug "WebKit fix: non-amd64 or libdir missing; skip." + return 0 + fi + + local need_fix=0 + [[ ! -e "$libdir/libwebkit2gtk-4.0.so.37" ]] && need_fix=1 + [[ ! -e "$libdir/libjavascriptcoregtk-4.0.so.18" ]] && need_fix=1 + + if [[ "$need_fix" -eq 0 ]]; then + debug "WebKit fix: 4.0 SONAMEs already present; nothing to do." + return 0 + fi + + info "Applying WebKitGTK compatibility shim (quiet)…" + sudo apt-get update -y >/dev/null 2>&1 || true + sudo apt-get install -y libwebkit2gtk-4.1-0 libjavascriptcoregtk-4.1-0 >/dev/null 2>&1 || true + sudo ln -sf "$libdir/libwebkit2gtk-4.1.so.0" "$libdir/libwebkit2gtk-4.0.so.37" || true + sudo ln -sf "$libdir/libjavascriptcoregtk-4.1.so.0" "$libdir/libjavascriptcoregtk-4.0.so.18" || true + info "WebKitGTK shim applied." +} + +# --- Install per distro (with DEBUG-friendly logging) --- case "$DISTRO" in ubuntu|debian) - URL="https://github.com/libr-forum/libr/releases/download/$VERSION/libr_${VERSION}_${ARCH}.deb" - log "⬇️ Downloading $URL" - wget -qO libr.deb "$URL" || { error "Failed to download $URL"; exit 1; } - sudo dpkg -i libr.deb || sudo apt-get install -f -y + # NOTE: Your published .deb name convention in prior messages: libr__.deb + DEB_NAME="libr_${DEB_VERSION}_${DEB_ARCH}.deb" + URL="https://github.com/${REPO}/releases/download/${VERSION}/${DEB_NAME}" + info "DEB expected filename: $DEB_NAME" + debug "DEB URL: $URL" + download_file "$URL" "libr.deb" || { err "Failed to fetch $URL"; exit 1; } + + info "Installing .deb…" + if ! sudo dpkg -i libr.deb; then + warn "dpkg reported missing deps; attempting 'apt-get -f install'…" + sudo apt-get install -f -y + fi rm -f libr.deb - install_gtk_if_missing + + maybe_fix_webkit_ubuntu ;; + fedora|rhel|centos) - URL="https://github.com/libr-forum/libr/releases/download/$VERSION/libr-${VERSION}.${ARCH}.rpm" - log "⬇️ Downloading $URL" - wget -qO libr.rpm "$URL" || { error "Failed to download $URL"; exit 1; } - sudo dnf install -y ./libr.rpm || sudo yum install -y ./libr.rpm + # Your script expects: libr-${VERSION}.${RPM_ARCH}.rpm (includes leading 'v' if present) + RPM_NAME="libr-${VERSION}.${RPM_ARCH}.rpm" + URL="https://github.com/${REPO}/releases/download/${VERSION}/${RPM_NAME}" + info "RPM expected filename: $RPM_NAME" + debug "RPM URL: $URL" + download_file "$URL" "libr.rpm" || { err "Failed to fetch $URL"; exit 1; } + + info "Installing .rpm…" + if command -v dnf >/dev/null 2>&1; then + sudo dnf install -y ./libr.rpm + else + sudo yum install -y ./libr.rpm + fi rm -f libr.rpm - install_gtk_if_missing ;; + arch) - URL="https://github.com/libr-forum/libr/releases/download/$VERSION/libr-${VERSION}-${ARCH}.pkg.tar.zst" - log "⬇️ Downloading $URL" - wget -qO libr.pkg.tar.zst "$URL" || { error "Failed to download $URL"; exit 1; } + # Your script expects: libr-${VERSION}-${PAC_ARCH}.pkg.tar.zst + PAC_NAME="libr-${VERSION}-${PAC_ARCH}.pkg.tar.zst" + URL="https://github.com/${REPO}/releases/download/${VERSION}/${PAC_NAME}" + info "Arch expected filename: $PAC_NAME" + debug "Arch URL: $URL" + download_file "$URL" "libr.pkg.tar.zst" || { err "Failed to fetch $URL"; exit 1; } + + info "Installing Arch package…" sudo pacman -U --noconfirm libr.pkg.tar.zst rm -f libr.pkg.tar.zst - install_gtk_if_missing ;; + *) - error "Unsupported distribution: $DISTRO" + err "Unsupported distribution: $DISTRO" exit 1 ;; esac -success "libr $VERSION installed successfully." +# --- Final verification --- +POST_VERSION="unknown" +case "$DISTRO" in + ubuntu|debian) POST_VERSION="$(dpkg-query -W -f='${Version}\n' libr 2>/dev/null || true)" ;; + fedora|rhel|centos) POST_VERSION="$(rpm -q --qf '%{EVR}\n' libr 2>/dev/null || true)" ;; + arch) POST_VERSION="$(pacman -Q libr 2>/dev/null | awk '{print $2}' || true)" ;; +esac +info "Installed (post-check) version: '${POST_VERSION:-unknown}'" +echo "βœ… Installation finished." From 7be06516dce1f4f41083cf66d23d40ad28c3fefc Mon Sep 17 00:00:00 2001 From: Lakshya Jain <147808548+lakshyajain-0291@users.noreply.github.com> Date: Sat, 23 Aug 2025 21:18:50 +0530 Subject: [PATCH 08/11] Refactor install-libr.sh for better structure --- scripts/install-libr.sh | 308 +++++++++++++--------------------------- 1 file changed, 101 insertions(+), 207 deletions(-) diff --git a/scripts/install-libr.sh b/scripts/install-libr.sh index c9767ca..80a503d 100755 --- a/scripts/install-libr.sh +++ b/scripts/install-libr.sh @@ -1,226 +1,120 @@ #!/usr/bin/env bash -# LIBR cross-distro installer with verbose debugging -# Usage: -# curl -fsSL https://raw.githubusercontent.com/libr-forum/Libr/main/scripts/install-libr.sh | bash -# curl -fsSL .../install-libr.sh | DEBUG=1 bash -s -- v1.0.0-beta # install specific version with debug -set -Eeuo pipefail - -DEBUG="${DEBUG:-1}" # 1/true = verbose with xtrace; 0/false = quieter -if [[ "$DEBUG" =~ ^(1|true|yes)$ ]]; then set -x; fi - -info() { echo -e "[INFO] $*"; } -debug() { [[ "$DEBUG" =~ ^(1|true|yes)$ ]] && echo -e "[DEBUG] $*"; } -warn() { echo -e "[WARN] $*" >&2; } -err() { echo -e "[ERROR] $*" >&2; } - -# --- Detect distribution & architecture --- -if [[ -f /etc/os-release ]]; then - # shellcheck disable=SC1091 - source /etc/os-release - DISTRO="${ID:-unknown}" - DISTRO_VER="${VERSION_ID:-unknown}" - CODENAME="${VERSION_CODENAME:-}" -else - err "Cannot detect distribution (missing /etc/os-release)." - exit 1 -fi - -# Debian/Ubuntu: dpkg prints 'amd64', else fall back to uname -m -ARCH="$(dpkg --print-architecture 2>/dev/null || uname -m)" -DEB_ARCH="$ARCH" -# Map to RPM arch naming -case "$ARCH" in - amd64) RPM_ARCH="x86_64" ;; - arm64|aarch64) RPM_ARCH="aarch64" ;; - *) RPM_ARCH="$ARCH" ;; -esac -# Arch Linux typically uses uname -m like x86_64/aarch64 -PAC_ARCH="$(uname -m)" - -info "Detected: DISTRO=$DISTRO $DISTRO_VER $CODENAME ARCH=$ARCH RPM_ARCH=$RPM_ARCH PAC_ARCH=$PAC_ARCH" - -# --- Fetch latest or use provided version (tag from GitHub) --- + +set -euo pipefail + +# ------------------------------- +# Configuration +# ------------------------------- +VERSION="${1:-latest}" # default = latest release +ARCH="$(uname -m)" +DEBUG="${DEBUG:-1}" # set DEBUG=0 to silence REPO="libr-forum/libr" -LATEST_VERSION="$(curl -fsSL "https://api.github.com/repos/${REPO}/releases/latest" | awk -F'"' '/tag_name/{print $4; exit}')" -INPUT_VERSION="${1:-}" -VERSION="${INPUT_VERSION:-$LATEST_VERSION}" - -if [[ -z "${VERSION:-}" ]]; then - err "Could not determine version (GitHub API returned no tag)." - exit 1 -fi - -# Useful normalized variants for logging/diagnostics -VERSION_NO_V="${VERSION#v}" # v1.0.0-beta -> 1.0.0-beta -DEB_VERSION="$(printf '%s' "$VERSION_NO_V" | sed 's/-/~/g')" # 1.0.0-beta -> 1.0.0~beta -debug "Version forms: RAW_TAG=$VERSION NO_V=$VERSION_NO_V DEB_VERSION=$DEB_VERSION" - -# --- Determine installed version via package manager FIRST (avoids launching UI) --- -INSTALLED_VERSION="none" -case "$DISTRO" in - ubuntu|debian) - INSTALLED_VERSION="$(dpkg-query -W -f='${Version}\n' libr 2>/dev/null || true)" - ;; - fedora|rhel|centos) - # %EVR is epoch:version-release; we’ll log it; comparison is just a best-effort here - INSTALLED_VERSION="$(rpm -q --qf '%{EVR}\n' libr 2>/dev/null || true)" - ;; - arch) - INSTALLED_VERSION="$(pacman -Q libr 2>/dev/null | awk '{print $2}' || true)" - ;; - *) - warn "Unsupported distro for package-query; will try 'libr --version' fallback." - ;; -esac - -# Fallback: try not to launch UI; if 'libr --version' prints, capture it -if [[ -z "$INSTALLED_VERSION" || "$INSTALLED_VERSION" == "none" ]]; then - if command -v libr >/dev/null 2>&1; then - # Expect lines like: "libr 1.0.0" or "libr v1.0.0-beta" - INSTALLED_VERSION="$(libr --version 2>/dev/null | awk '{print $2}')" + +log() { echo -e "πŸ”Ή $*"; } +debug() { [[ "$DEBUG" -eq 1 ]] && echo -e "🐞 DEBUG: $*"; } +err() { echo -e "❌ $*" >&2; exit 1; } + +# ------------------------------- +# Detect distro +# ------------------------------- +detect_distro() { + if [ -f /etc/os-release ]; then + . /etc/os-release + DISTRO=$ID + debug "Detected distro: $DISTRO" + else + err "Unable to detect distribution." fi -fi - -INSTALLED_VERSION="${INSTALLED_VERSION:-none}" -info "Installed version detected: '$INSTALLED_VERSION'" - -# --- Decide if we need to install --- -# We consider a match if any of these match (helps across packaging/tag formats): -match_versions() { - local inst="$1" tag="$2" nov="$3" debv="$4" - [[ -z "$inst" || "$inst" == "none" ]] && return 1 - [[ "$inst" == "$tag" ]] && return 0 - [[ "$inst" == "$nov" ]] && return 0 - [[ "$inst" == "$debv" ]] && return 0 - return 1 } -if match_versions "$INSTALLED_VERSION" "$VERSION" "$VERSION_NO_V" "$DEB_VERSION"; then - info "libr is already at the requested version (match found). Skipping reinstall." - exit 0 -fi - -if [[ "$INSTALLED_VERSION" != "none" ]]; then - info "Removing existing libr ($INSTALLED_VERSION) before install/update…" - case "$DISTRO" in - ubuntu|debian) sudo apt-get remove -y libr || true ;; - fedora|rhel|centos) sudo dnf remove -y libr || sudo yum remove -y libr || true ;; - arch) sudo pacman -Rns --noconfirm libr || true ;; - *) warn "Skip removal on unsupported distro '$DISTRO'."; ;; - esac -fi +# ------------------------------- +# Detect installed version +# ------------------------------- +installed_version() { + if command -v libr >/dev/null 2>&1; then + libr --version 2>/dev/null | awk '{print $2}' + else + echo "" + fi +} -info "Proceeding to install libr $VERSION on $DISTRO ($ARCH)…" +# ------------------------------- +# Get latest release from GitHub +# ------------------------------- +latest_version() { + curl -fsSL "https://api.github.com/repos/${REPO}/releases/latest" \ + | grep '"tag_name":' | cut -d'"' -f4 +} -# --- Helpers: probe URL & download with status --- -probe_url() { +# ------------------------------- +# Download + Install package +# ------------------------------- +install_pkg() { local url="$1" - local code - code="$(curl -s -o /dev/null -w '%{http_code}' "$url" || echo 000)" - debug "HTTP probe $url -> $code" - printf '%s' "$code" -} + local file="$2" -download_file() { - local url="$1" out="$2" - info "Downloading: $url" - local code; code="$(probe_url "$url")" - if [[ "$code" != "200" ]]; then - err "URL not reachable (HTTP $code): $url" - return 1 + log "⬇️ Downloading $url" + if ! curl -fL "$url" -o "$file"; then + err "Failed to download $url" fi - curl -fSL "$url" -o "$out" + + case "$DISTRO" in + ubuntu|debian) + sudo dpkg -i "$file" || sudo apt-get install -f -y + ;; + fedora|rhel|centos|rocky|almalinux|opensuse*) + sudo rpm -Uvh --force "$file" + ;; + arch|manjaro) + sudo pacman -U --noconfirm "$file" + ;; + *) + err "Unsupported distro: $DISTRO" + ;; + esac } -# --- Optional: Only apply WebKitGTK shim if the old SONAME is missing (Ubuntu/Debian only) --- -maybe_fix_webkit_ubuntu() { - # Only on Debian/Ubuntu & only on amd64 path below - [[ "$DISTRO" != "ubuntu" && "$DISTRO" != "debian" ]] && { debug "WebKit fix: not Debian/Ubuntu, skip."; return 0; } - local libdir="/usr/lib/x86_64-linux-gnu" - if [[ "$DEB_ARCH" != "amd64" || ! -d "$libdir" ]]; then - debug "WebKit fix: non-amd64 or libdir missing; skip." - return 0 +# ------------------------------- +# Main +# ------------------------------- +main() { + detect_distro + + if [[ "$VERSION" == "latest" ]]; then + VERSION="$(latest_version)" fi + debug "Target version: $VERSION" - local need_fix=0 - [[ ! -e "$libdir/libwebkit2gtk-4.0.so.37" ]] && need_fix=1 - [[ ! -e "$libdir/libjavascriptcoregtk-4.0.so.18" ]] && need_fix=1 + CURRENT="$(installed_version)" + debug "Currently installed version: ${CURRENT:-none}" - if [[ "$need_fix" -eq 0 ]]; then - debug "WebKit fix: 4.0 SONAMEs already present; nothing to do." - return 0 + if [[ "$CURRENT" == "$VERSION" ]]; then + log "βœ… libr $VERSION is already installed." + exit 0 fi - info "Applying WebKitGTK compatibility shim (quiet)…" - sudo apt-get update -y >/dev/null 2>&1 || true - sudo apt-get install -y libwebkit2gtk-4.1-0 libjavascriptcoregtk-4.1-0 >/dev/null 2>&1 || true - sudo ln -sf "$libdir/libwebkit2gtk-4.1.so.0" "$libdir/libwebkit2gtk-4.0.so.37" || true - sudo ln -sf "$libdir/libjavascriptcoregtk-4.1.so.0" "$libdir/libjavascriptcoregtk-4.0.so.18" || true - info "WebKitGTK shim applied." + case "$DISTRO" in + ubuntu|debian) + FILE="libr_${VERSION}_${ARCH}.deb" + ;; + fedora|rhel|centos|rocky|almalinux|opensuse*) + FILE="libr-${VERSION}.${ARCH}.rpm" + ;; + arch|manjaro) + FILE="libr-${VERSION}-${ARCH}.pkg.tar.zst" + ;; + *) + err "Unsupported distro: $DISTRO" + ;; + esac + + URL="https://github.com/${REPO}/releases/download/${VERSION}/${FILE}" + debug "Download URL: $URL" + debug "Local filename: $FILE" + + install_pkg "$URL" "$FILE" + + log "πŸŽ‰ libr $VERSION installed successfully!" } -# --- Install per distro (with DEBUG-friendly logging) --- -case "$DISTRO" in - ubuntu|debian) - # NOTE: Your published .deb name convention in prior messages: libr__.deb - DEB_NAME="libr_${DEB_VERSION}_${DEB_ARCH}.deb" - URL="https://github.com/${REPO}/releases/download/${VERSION}/${DEB_NAME}" - info "DEB expected filename: $DEB_NAME" - debug "DEB URL: $URL" - download_file "$URL" "libr.deb" || { err "Failed to fetch $URL"; exit 1; } - - info "Installing .deb…" - if ! sudo dpkg -i libr.deb; then - warn "dpkg reported missing deps; attempting 'apt-get -f install'…" - sudo apt-get install -f -y - fi - rm -f libr.deb - - maybe_fix_webkit_ubuntu - ;; - - fedora|rhel|centos) - # Your script expects: libr-${VERSION}.${RPM_ARCH}.rpm (includes leading 'v' if present) - RPM_NAME="libr-${VERSION}.${RPM_ARCH}.rpm" - URL="https://github.com/${REPO}/releases/download/${VERSION}/${RPM_NAME}" - info "RPM expected filename: $RPM_NAME" - debug "RPM URL: $URL" - download_file "$URL" "libr.rpm" || { err "Failed to fetch $URL"; exit 1; } - - info "Installing .rpm…" - if command -v dnf >/dev/null 2>&1; then - sudo dnf install -y ./libr.rpm - else - sudo yum install -y ./libr.rpm - fi - rm -f libr.rpm - ;; - - arch) - # Your script expects: libr-${VERSION}-${PAC_ARCH}.pkg.tar.zst - PAC_NAME="libr-${VERSION}-${PAC_ARCH}.pkg.tar.zst" - URL="https://github.com/${REPO}/releases/download/${VERSION}/${PAC_NAME}" - info "Arch expected filename: $PAC_NAME" - debug "Arch URL: $URL" - download_file "$URL" "libr.pkg.tar.zst" || { err "Failed to fetch $URL"; exit 1; } - - info "Installing Arch package…" - sudo pacman -U --noconfirm libr.pkg.tar.zst - rm -f libr.pkg.tar.zst - ;; - - *) - err "Unsupported distribution: $DISTRO" - exit 1 - ;; -esac - -# --- Final verification --- -POST_VERSION="unknown" -case "$DISTRO" in - ubuntu|debian) POST_VERSION="$(dpkg-query -W -f='${Version}\n' libr 2>/dev/null || true)" ;; - fedora|rhel|centos) POST_VERSION="$(rpm -q --qf '%{EVR}\n' libr 2>/dev/null || true)" ;; - arch) POST_VERSION="$(pacman -Q libr 2>/dev/null | awk '{print $2}' || true)" ;; -esac -info "Installed (post-check) version: '${POST_VERSION:-unknown}'" -echo "βœ… Installation finished." +main "$@" From 6d8d10649bd3b2b64b9b5bf3b8a8847a1d6c3406 Mon Sep 17 00:00:00 2001 From: kushagra0902 Date: Sun, 24 Aug 2025 04:17:17 +0530 Subject: [PATCH 09/11] added js to db --- core/db/.env | 3 +- core/db/config/config.go | 1 + core/db/config/envconfig.go | 65 +++ core/db/internal/models/models.go | 5 + core/db/internal/network/peers/functions.go | 2 +- core/db/internal/network/peers/peer.go | 46 +- core/db/internal/network/rpc.go | 2 +- core/db/internal/storage/validator.go | 6 +- core/db/internal/utils/mongodb.go | 326 ++++++++---- core/db/main.go | 64 ++- core/mod_client/main.go | 2 +- core/mod_client/peers/peer.go | 548 +++++++++++++++++++- 12 files changed, 956 insertions(+), 114 deletions(-) create mode 100644 core/db/config/envconfig.go diff --git a/core/db/.env b/core/db/.env index 07a2d53..9d4222f 100644 --- a/core/db/.env +++ b/core/db/.env @@ -2,4 +2,5 @@ DB_PATH = data/libr.db IP = 49.36.179.166 PORT = 33122 BOOTSTRAP = - +JS_ServerURL = https://libr-server.onrender.com +JS_API_KEY = qwertyuiop diff --git a/core/db/config/config.go b/core/db/config/config.go index d6c28be..7ee6b24 100644 --- a/core/db/config/config.go +++ b/core/db/config/config.go @@ -1,6 +1,7 @@ package config import ( + "database/sql" "fmt" "log" diff --git a/core/db/config/envconfig.go b/core/db/config/envconfig.go new file mode 100644 index 0000000..437e02e --- /dev/null +++ b/core/db/config/envconfig.go @@ -0,0 +1,65 @@ +package config + +import ( + "log" + "os" + "strconv" + "embed" + "github.com/joho/godotenv" +) +//go:embed .env +var _ embed.FS // Embedded .env file (unused, but required for go:embed syntax) + + + +// Config holds all configuration for the application. +type Config struct { + DBPath string + IP string + Port int + Bootstrap string + JSServerURL string + JSAPIKey string +} + +// Cfg is a global, public variable that holds the loaded configuration. + + + +// Cfg is a global, public variable that holds the loaded configuration. +var Cfg Config +func init() { + // Load the .env file. + // It's okay if it fails, we can rely on OS environment variables as a fallback. + if err := godotenv.Load(); err != nil { + log.Println("No .env file found, using OS environment variables") + } + + // Load configuration into the Cfg struct + Cfg = Config{ + DBPath: getEnv("DB_PATH", "data/default.db"), // Provide a default + IP: getEnv("IP", "0.0.0.0"), // Default to listen on all interfaces + Port: getEnvAsInt("PORT", 33122), // Default port + Bootstrap: getEnv("BOOTSTRAP", ""), // No default needed + JSServerURL: getEnv("JS_ServerURL", ""), // No default needed + JSAPIKey: getEnv("JS_API_KEY", ""), // No default needed + } + log.Println("Configuration loaded successfully") +} + +// getEnv is a helper function to read an environment variable or return a default value. +func getEnv(key, fallback string) string { + if value, exists := os.LookupEnv(key); exists { + return value + } + return fallback +} + +// getEnvAsInt is a helper to parse an environment variable as an integer. +func getEnvAsInt(key string, fallback int) int { + valueStr := getEnv(key, "") + if value, err := strconv.Atoi(valueStr); err == nil { + return value + } + return fallback +} \ No newline at end of file diff --git a/core/db/internal/models/models.go b/core/db/internal/models/models.go index c68ee65..2b16ec6 100644 --- a/core/db/internal/models/models.go +++ b/core/db/internal/models/models.go @@ -38,6 +38,11 @@ type Mod struct { PublicKey string `json:"public_key"` } +type Mods struct{ + Peerid string `json:"peer_id"` + PublicKey string `json:"public_key"` +} + type ReportMsg struct { PublicKey string `json:"public_key"` Msg Msg `json:"msg"` diff --git a/core/db/internal/network/peers/functions.go b/core/db/internal/network/peers/functions.go index f1802a3..84706c5 100644 --- a/core/db/internal/network/peers/functions.go +++ b/core/db/internal/network/peers/functions.go @@ -46,7 +46,7 @@ func RegisterLocalState(n *models.Node, rt *routing.RoutingTable) { } func initDHT() { - bootstrapAddrs, _ := utils.GetDbAddr() + bootstrapAddrs, _ := utils.GetDBFromJSServer() // 3. Init DB and routing config.InitDB() diff --git a/core/db/internal/network/peers/peer.go b/core/db/internal/network/peers/peer.go index 17e8d1d..0f6e51f 100644 --- a/core/db/internal/network/peers/peer.go +++ b/core/db/internal/network/peers/peer.go @@ -8,6 +8,8 @@ import ( "crypto/x509" "log" "math/big" + "net/http" + //"os" "sort" "context" @@ -20,6 +22,8 @@ import ( "strings" "time" + "github.com/devlup-labs/Libr/core/db/config" + "github.com/devlup-labs/Libr/core/db/internal/node" "github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p/core/host" "github.com/libp2p/go-libp2p/core/network" @@ -102,6 +106,44 @@ func NewChatPeer(relayMultiAddrList []string) (*ChatPeer, error) { return nil, err } + //pubKey := keycache.LoadPubKey() + JS_API_key := config.Cfg.JSAPIKey + JS_ServerURL := config.Cfg.JSServerURL + if JS_API_key == "" || JS_ServerURL == "" { + fmt.Println("[DEBUG] Missing JS API key or server URL") + log.Fatal("Cant load env variables") + } + node_id:=node.GenerateNodeIDFromPublicKey() + Data := map[string]string{ + "peer_id": h.ID().String(), + "node_id" : node_id, + } + + jsonData, err := json.Marshal(Data) + if(err!=nil){ + fmt.Println("Error marchalling req json for post boot") + } + req,err := http.NewRequest("POST", JS_ServerURL+"/api/postboot", bytes.NewBuffer(jsonData)) + + if err != nil { + return nil,fmt.Errorf("failed to create request: %w",err) + } + + req.Header.Set("Content-Type", "application/json") + req.Header.Set("x-api-key", JS_API_key) + + client := &http.Client{Timeout: 10 * time.Second} + resp, err := client.Do(req) + if err != nil { + return nil,fmt.Errorf("failed to send request: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil,fmt.Errorf("server returned non-200 status code: %d", resp.StatusCode) + } + + fmt.Println("Inserted bootstrap node successfully") fmt.Println("[DEBUG] Creating identify service") idSvc, err := identify.NewIDService(h) if err != nil { @@ -149,7 +191,9 @@ func NewChatPeer(relayMultiAddrList []string) (*ChatPeer, error) { sort.Slice(distmap, func(i, j int) bool { return distmap[i].dist.Cmp(distmap[j].dist) < 0 }) - + if(len(relayMultiAddrList)==0){ + log.Fatal("No relays given, please restart after some time") + } relayIDused := distmap[0].relayID fmt.Println(relayIDused) var relayAddr string diff --git a/core/db/internal/network/rpc.go b/core/db/internal/network/rpc.go index aa1a0ef..54b7a14 100644 --- a/core/db/internal/network/rpc.go +++ b/core/db/internal/network/rpc.go @@ -189,7 +189,7 @@ func SendFindValue(key string, self *models.Node, rt *routing.RoutingTable) ([]m // } func DeleteValue(key *[20]byte, repCert *models.ReportCert, self *models.Node, rt *routing.RoutingTable) ([]*models.Node, error) { - validMods, _ := utils.GetOnlineMods() + validMods, _ := utils.GetModsFromJSServer() selfDist := node.XORBigInt(self.NodeId, *key) closest := rt.FindClosest(*key, config.K) diff --git a/core/db/internal/storage/validator.go b/core/db/internal/storage/validator.go index ee50706..b670876 100644 --- a/core/db/internal/storage/validator.go +++ b/core/db/internal/storage/validator.go @@ -77,7 +77,7 @@ func ValidateRepCertFields(repCert *models.ReportCert) error { return nil } -func ValidateRepCert(repCert *models.ReportCert, validMods []*models.Mod) error { +func ValidateRepCert(repCert *models.ReportCert, validMods []*models.Mods) error { if err := ValidateRepCertFields(repCert); err != nil { return err } @@ -107,7 +107,7 @@ func ValidateRepCert(repCert *models.ReportCert, validMods []*models.Mod) error return ValidateRepModCerts(repCert, validMods) } -func ValidateRepModCerts(repCert *models.ReportCert, validMods []*models.Mod) error { +func ValidateRepModCerts(repCert *models.ReportCert, validMods []*models.Mods) error { validMap := make(map[string]struct{}) for _, mod := range validMods { validMap[mod.PublicKey] = struct{}{} @@ -165,7 +165,7 @@ func ValidateRepModCerts(repCert *models.ReportCert, validMods []*models.Mod) er func ValidateModCert(msgCert *models.MsgCert) error { apprCount := 0 rejCount := 0 - validMods, _ := utils.GetOnlineMods() + validMods, _ := utils.GetModsFromJSServer() totalMods := len(validMods) for _, modcert := range msgCert.ModCerts { payload := msgCert.Msg.Content + strconv.FormatInt(msgCert.Msg.Ts, 10) + modcert.Status diff --git a/core/db/internal/utils/mongodb.go b/core/db/internal/utils/mongodb.go index 0bf9687..1603b3b 100644 --- a/core/db/internal/utils/mongodb.go +++ b/core/db/internal/utils/mongodb.go @@ -1,137 +1,267 @@ package utils import ( - "context" + "encoding/json" "fmt" - "log" - "strings" + "net/http" + "os" "time" + "github.com/devlup-labs/Libr/core/db/config" "github.com/devlup-labs/Libr/core/db/internal/models" - "github.com/devlup-labs/Libr/core/db/internal/node" - "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" ) var MongoClient *mongo.Client // SetupMongo initializes the global MongoClient -func SetupMongo(uri string) error { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() +// func SetupMongo(uri string) error { +// ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) +// defer cancel() +// +// client, err := mongo.Connect(ctx, options.Client().ApplyURI(uri)) +// if err != nil { +// return fmt.Errorf("failed to connect to MongoDB: %w", err) +// } +// +// if err := client.Ping(ctx, nil); err != nil { +// return fmt.Errorf("failed to ping MongoDB: %w", err) +// } +// +// MongoClient = client +// log.Println("βœ… MongoDB connected") +// return nil +// } - client, err := mongo.Connect(ctx, options.Client().ApplyURI(uri)) +// DisconnectMongo gracefully closes the MongoDB connection +// func DisconnectMongo() { +// if MongoClient != nil { +// if err := MongoClient.Disconnect(context.Background()); err != nil { +// log.Println("⚠️ Error disconnecting MongoDB:", err) +// } else { +// log.Println("πŸ›‘ MongoDB disconnected") +// } +// } +// } + +// πŸš€ Uses global MongoClient and ctx +// func GetDbAddr() ([]*models.Node, error) { +// ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) +// defer cancel() +// +// collection := MongoClient.Database("Addrs").Collection("nodes") // replace with actual DB & collection +// cursor, err := collection.Find(ctx, bson.M{}) +// if err != nil { +// return nil, err +// } +// defer cursor.Close(ctx) +// +// var nodeList []*models.Node +// for cursor.Next(ctx) { +// var doc struct { +// NodeId string `bson:"node_id"` +// PeerId string `bson:"peer_id"` +// } +// if err := cursor.Decode(&doc); err != nil { +// return nil, err +// } +// +// nodeId, _ := node.DecodeNodeID(doc.NodeId) +// node := &models.Node{ +// NodeId: nodeId, +// PeerId: doc.PeerId, +// } +// nodeList = append(nodeList, node) +// } +// return nodeList, nil +// } + +// func GetOnlineMods() ([]*models.Mod, error) { +// ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) +// defer cancel() +// +// collection := MongoClient.Database("Addrs").Collection("mods") +// cursor, err := collection.Find(ctx, bson.M{}) +// if err != nil { +// return nil, err +// } +// defer cursor.Close(ctx) +// +// var mods []*models.Mod +// for cursor.Next(ctx) { +// var doc struct { +// IP string `bson:"ip"` +// Port string `bson:"port"` +// PublicKey string `bson:"public_key"` +// } +// if err := cursor.Decode(&doc); err != nil { +// return nil, err +// } +// mods = append(mods, &models.Mod{ +// IP: doc.IP, +// Port: doc.Port, +// PublicKey: doc.PublicKey, +// }) +// } +// fmt.Println("Online mods:", mods) +// return mods, nil +// } + +// func GetRelayAddr() ([]string, error) { +// ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) +// defer cancel() +// +// collection := MongoClient.Database("Addrs").Collection("relays") +// cursor, err := collection.Find(ctx, bson.M{}) +// if err != nil { +// return nil, fmt.Errorf("failed to fetch relay addresses: %w", err) +// } +// defer cursor.Close(ctx) +// +// var relayList []string +// for cursor.Next(ctx) { +// var doc struct { +// Address string `bson:"address"` +// } +// if err := cursor.Decode(&doc); err != nil { +// return nil, fmt.Errorf("failed to decode relay document: %w", err) +// } +// if strings.HasPrefix(doc.Address, "/") { +// relayList = append(relayList, strings.TrimSpace(doc.Address)) +// } +// } +// +// return relayList, nil +// } + +// -------------------- ACTIVE CODE -------------------- + +// type relayResp struct { +// RelayList []relays `json:"relaylist"` +// } + +type modResp struct { + ModLists []models.Mods `json:"modlist"` +} + +// type relays struct { +// Address string `json:"address"` +// } + +type NodeResp struct { + NodesLists []models.Node `json:"nodeslist"` +} + +// βœ… Fetch relay addresses +func GetRelayAddrFromJSServer() ([]string, error) { + serverURL := config.Cfg.JSServerURL + + req, err := http.NewRequest("GET", serverURL+"/api/getrelay", nil) if err != nil { - return fmt.Errorf("failed to connect to MongoDB: %w", err) + return nil, fmt.Errorf("failed to create request: %w", err) } - if err := client.Ping(ctx, nil); err != nil { - return fmt.Errorf("failed to ping MongoDB: %w", err) + client := &http.Client{Timeout: 10 * time.Second} + resp, err := client.Do(req) + if err != nil { + return nil, fmt.Errorf("failed to send request: %w", err) } + defer resp.Body.Close() - MongoClient = client - log.Println("βœ… MongoDB connected") - return nil -} + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("server returned non-200 status code: %d", resp.StatusCode) + } -// DisconnectMongo gracefully closes the MongoDB connection -func DisconnectMongo() { - if MongoClient != nil { - if err := MongoClient.Disconnect(context.Background()); err != nil { - log.Println("⚠️ Error disconnecting MongoDB:", err) - } else { - log.Println("πŸ›‘ MongoDB disconnected") - } + var payload relayResp + if err := json.NewDecoder(resp.Body).Decode(&payload); err != nil { + return nil, fmt.Errorf("failed to decode JSON response: %w", err) } + fmt.Println(resp.Body) + fmt.Println(payload) + + var addresses []string +for _, relay := range payload.RelayList.Relays { + addresses = append(addresses, relay.Address) +} + fmt.Println(addresses) + return addresses, nil } -// πŸš€ Uses global MongoClient and ctx -func GetDbAddr() ([]*models.Node, error) { - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - collection := MongoClient.Database("Addrs").Collection("nodes") // replace with actual DB & collection - cursor, err := collection.Find(ctx, bson.M{}) +type relayResp struct { + RelayList struct { + Relays []struct { + Address string `json:"address"` + } `json:"relaylist"` + } `json:"relay_list"` +} + +// βœ… Fetch mods +func GetModsFromJSServer() ([]*models.Mods, error) { + serverURL := os.Getenv("JS_ServerURL") + + req, err := http.NewRequest("GET", serverURL+"/api/getmod", nil) // πŸ”₯ corrected endpoint if err != nil { - return nil, err + return nil, fmt.Errorf("failed to create request: %w", err) } - defer cursor.Close(ctx) - - var nodeList []*models.Node - for cursor.Next(ctx) { - var doc struct { - NodeId string `bson:"node_id"` - PeerId string `bson:"peer_id"` - } - if err := cursor.Decode(&doc); err != nil { - return nil, err - } - - nodeId, _ := node.DecodeNodeID(doc.NodeId) - node := &models.Node{ - NodeId: nodeId, - PeerId: doc.PeerId, - } - nodeList = append(nodeList, node) - } - return nodeList, nil -} -func GetOnlineMods() ([]*models.Mod, error) { - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() + var ModReturnList []*models.Mods - collection := MongoClient.Database("Addrs").Collection("mods") - cursor, err := collection.Find(ctx, bson.M{}) + client := &http.Client{Timeout: 10 * time.Second} + resp, err := client.Do(req) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to send request: %w", err) } - defer cursor.Close(ctx) - - var mods []*models.Mod - for cursor.Next(ctx) { - var doc struct { - IP string `bson:"ip"` - Port string `bson:"port"` - PublicKey string `bson:"public_key"` - } - if err := cursor.Decode(&doc); err != nil { - return nil, err - } - mods = append(mods, &models.Mod{ - IP: doc.IP, - Port: doc.Port, - PublicKey: doc.PublicKey, - }) + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("server returned non-200 status code: %d", resp.StatusCode) + } + + var payload modResp + if err := json.NewDecoder(resp.Body).Decode(&payload); err != nil { + return nil, fmt.Errorf("failed to decode JSON response: %w", err) + } + + for i := range payload.ModLists { + m := payload.ModLists[i] // copy to avoid pointer bug + ModReturnList = append(ModReturnList, &m) } - fmt.Println("Online mods:", mods) - return mods, nil + + return ModReturnList, nil } -func GetRelayAddr() ([]string, error) { - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() +// βœ… Fetch DB nodes +func GetDBFromJSServer() ([]*models.Node, error) { + serverURL := os.Getenv("JS_ServerURL") + + req, err := http.NewRequest("GET", serverURL+"/api/getboot", nil) // πŸ”₯ corrected endpoint + if err != nil { + return nil, fmt.Errorf("failed to create request: %w", err) + } + + var NodeReturnList []*models.Node - collection := MongoClient.Database("Addrs").Collection("relays") - cursor, err := collection.Find(ctx, bson.M{}) + client := &http.Client{Timeout: 10 * time.Second} + resp, err := client.Do(req) if err != nil { - return nil, fmt.Errorf("failed to fetch relay addresses: %w", err) + return nil, fmt.Errorf("failed to send request: %w", err) } - defer cursor.Close(ctx) - - var relayList []string - for cursor.Next(ctx) { - var doc struct { - Address string `bson:"address"` - } - if err := cursor.Decode(&doc); err != nil { - return nil, fmt.Errorf("failed to decode relay document: %w", err) - } - if strings.HasPrefix(doc.Address, "/") { - relayList = append(relayList, strings.TrimSpace(doc.Address)) - } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("server returned non-200 status code: %d", resp.StatusCode) + } + + var payload NodeResp + if err := json.NewDecoder(resp.Body).Decode(&payload); err != nil { + return nil, fmt.Errorf("failed to decode JSON response: %w", err) + } + + for i := range payload.NodesLists { + n := payload.NodesLists[i] // copy to avoid pointer bug + NodeReturnList = append(NodeReturnList, &n) } - return relayList, nil + return NodeReturnList, nil } diff --git a/core/db/main.go b/core/db/main.go index b97bc82..5ac100d 100644 --- a/core/db/main.go +++ b/core/db/main.go @@ -1,36 +1,88 @@ package main import ( + "bytes" + "encoding/json" "fmt" + "net/http" "os" "os/signal" "syscall" "time" + "github.com/devlup-labs/Libr/core/db/config" "github.com/devlup-labs/Libr/core/db/internal/keycache" peer "github.com/devlup-labs/Libr/core/db/internal/network/peers" "github.com/devlup-labs/Libr/core/db/internal/utils" + "github.com/joho/godotenv" ) +var JS_API_key string +var JS_ServerURL string + func main() { keycache.InitKeys() - utils.SetupMongo("mongodb+srv://peer:peerhehe@cluster0.vswojqe.mongodb.net/") - relayAddrs, err := utils.GetRelayAddr() - + godotenv.Load() + JS_API_key = config.Cfg.JSAPIKey + JS_ServerURL = config.Cfg.JSServerURL + if JS_API_key == "" || JS_ServerURL == "" { + fmt.Println("[DEBUG] Missing JS API key or server URL") + return + } + //utils.SetupMongo("mongodb+srv://peer:peerhehe@cluster0.vswojqe.mongodb.net/") + //utils.SetupMongo(JS_ServerURL) + relayAddrs, err := utils.GetRelayAddrFromJSServer() + if err != nil { fmt.Println("Error while getting relay address, ", err) } - fmt.Println(relayAddrs) - - peer.StartNode(relayAddrs) + fmt.Println(relayAddrs) + peer.StartNode(relayAddrs) + sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM) <-sigChan fmt.Println("Interrupt received. Exiting gracefully.") + deleteFromJSServer() + fmt.Println("Sent delete request to JS server") if peer.GlobalRT != nil { peer.GlobalRT.SaveToDBAsync() time.Sleep(1 * time.Second) } } + + +func deleteFromJSServer() error { + deleteData := map[string]string{ + "peer_id" : peer.PeerID, + } + + jsonData, err := json.Marshal(deleteData) + if err != nil { + return fmt.Errorf("failed to marshal JSON: %w", err) + } + + req, err := http.NewRequest("DELETE", JS_ServerURL+"/api/deleteboot", bytes.NewBuffer(jsonData)) + if err != nil { + return fmt.Errorf("failed to create request: %w", err) + } + + req.Header.Set("Content-Type", "application/json") + req.Header.Set("x-api-key", JS_API_key) + + client := &http.Client{Timeout: 10 * time.Second} + resp, err := client.Do(req) + if err != nil { + return fmt.Errorf("failed to send request: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("server returned non-200 status code: %d", resp.StatusCode) + } + + fmt.Printf("Successfully deleted relay") + return nil +} \ No newline at end of file diff --git a/core/mod_client/main.go b/core/mod_client/main.go index d474eb6..46e9dae 100644 --- a/core/mod_client/main.go +++ b/core/mod_client/main.go @@ -8,7 +8,7 @@ import ( "github.com/wailsapp/wails/v2/pkg/options/assetserver" ) -//go:embed all:frontend/dist +//go:embed frontend/dist/* var assets embed.FS func main() { diff --git a/core/mod_client/peers/peer.go b/core/mod_client/peers/peer.go index e905d17..adf8644 100644 --- a/core/mod_client/peers/peer.go +++ b/core/mod_client/peers/peer.go @@ -1,3 +1,454 @@ +// package peer + +// import ( +// "bufio" +// "bytes" +// "crypto/sha256" +// "crypto/tls" +// "crypto/x509" +// "log" +// "math/big" +// "sort" + +// "context" +// "encoding/hex" +// "encoding/json" +// "fmt" + +// //"io" + +// "strings" +// "time" + +// "github.com/devlup-labs/Libr/core/mod_client/logger" +// "github.com/libp2p/go-libp2p" +// "github.com/libp2p/go-libp2p/core/host" +// "github.com/libp2p/go-libp2p/core/network" +// "github.com/libp2p/go-libp2p/core/peer" +// "github.com/libp2p/go-libp2p/core/protocol" +// "github.com/libp2p/go-libp2p/p2p/net/connmgr" +// "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/client" +// "github.com/libp2p/go-libp2p/p2p/protocol/holepunch" +// "github.com/libp2p/go-libp2p/p2p/protocol/identify" +// "github.com/multiformats/go-multiaddr" + +// "github.com/libp2p/go-libp2p/p2p/transport/tcp" +// "github.com/libp2p/go-libp2p/p2p/transport/websocket" + +// //webtransport "github.com/libp2p/go-libp2p/p2p/transport/webtransport" +// libp2ptls "github.com/libp2p/go-libp2p/p2p/security/tls" +// ) + +// const ChatProtocol = protocol.ID("/chat/1.0.0") + +// var OwnPubIP string + +// type ChatPeer struct { +// Host host.Host +// relayAddr multiaddr.Multiaddr +// relayID peer.ID +// peers map[peer.ID]string // peer ID to nickname mapping +// } + +// type reqFormat struct { +// Type string `json:"type,omitempty"` +// PeerID string `json:"peer_id,omitempty"` +// ReqParams json.RawMessage `json:"reqparams,omitempty"` +// Body json.RawMessage `json:"body,omitempty"` +// } + +// // type RelayDist struct { +// // relayID string +// // dist *big.Int +// // } + +// func NewChatPeer(relayMultiAddrList []string) (*ChatPeer, error) { + +// var relayList []string +// for _, multiaddr := range relayMultiAddrList { +// parts := strings.Split(multiaddr, "/") +// relayList = append(relayList, parts[len(parts)-1]) +// } + +// caCertPool := x509.NewCertPool() + +// fmt.Println("[DEBUG] Creating connection manager") +// connMgr, err := connmgr.NewConnManager(100, 400) +// if err != nil { +// fmt.Println("[DEBUG] Failed to create connection manager:", err) +// return nil, err +// } + +// tlsConfig := &tls.Config{ +// RootCAs: caCertPool, +// InsecureSkipVerify: true, +// // Other TLS configurations like ClientAuth, InsecureSkipVerify, etc. +// } + +// fmt.Println("[DEBUG] Creating libp2p Host") +// h, err := libp2p.New( +// libp2p.ListenAddrStrings("/ip4/0.0.0.0/tcp/0/ws"), // WebSocket +// libp2p.Security(libp2ptls.ID, libp2ptls.New), +// libp2p.ConnectionManager(connMgr), +// libp2p.EnableNATService(), +// libp2p.EnableRelay(), +// libp2p.Transport(tcp.NewTCPTransport), +// libp2p.Transport(websocket.New, websocket.WithTLSConfig(tlsConfig)), +// // libp2p.Transport(websocket.NewWithTLSConfig(tlsConfig)), +// // libp2p.Transport(websocket.New), +// ) + +// if err != nil { +// fmt.Println("[DEBUG] Failed to create Host:", err) +// return nil, err +// } + +// fmt.Println("[DEBUG] Creating identify service") +// idSvc, err := identify.NewIDService(h) +// if err != nil { +// fmt.Println("[DEBUG] Failed to create identify service:", err) +// h.Close() +// return nil, err +// } + +// getListenAddrs := func() []multiaddr.Multiaddr { +// var publicAddrs []multiaddr.Multiaddr +// for _, addr := range h.Addrs() { +// if !isPrivateAddr(addr) { +// publicAddrs = append(publicAddrs, addr) +// } +// } +// return publicAddrs +// } + +// fmt.Println("[DEBUG] Creating hole punching service") +// hps, err := holepunch.NewService(h, idSvc, getListenAddrs) +// if err != nil { +// fmt.Println("[DEBUG] Failed to create hole punching service:", err) +// h.Close() +// return nil, err +// } +// _ = hps + +// var distmap []RelayDist +// //OwnPubIP = GetPublicIP() +// h1 := sha256.New() +// h1.Write([]byte(h.ID().String())) +// peerIDhash := hex.EncodeToString(h1.Sum(nil)) + +// for _, relay := range relayList { + +// h_R := sha256.New() +// h_R.Write([]byte(relay)) +// RelayIDhash := hex.EncodeToString(h_R.Sum(nil)) + +// dist := XorHexToBigInt(peerIDhash, RelayIDhash) + +// distmap = append(distmap, RelayDist{dist: dist, relayID: relay}) +// } + +// sort.Slice(distmap, func(i, j int) bool { +// return distmap[i].dist.Cmp(distmap[j].dist) < 0 +// }) + +// relayIDused := distmap[0].relayID +// fmt.Println(relayIDused) +// var relayAddr string + +// for _, multiaddr := range relayMultiAddrList { +// parts := strings.Split(multiaddr, "/") +// if parts[len(parts)-1] == relayIDused { +// relayAddr = multiaddr +// break +// } +// } + +// fmt.Println("[DEBUG] Parsing relay address:", relayAddr) +// relayMA, err := multiaddr.NewMultiaddr(relayAddr) +// if err != nil { +// fmt.Println("[DEBUG] Failed to parse relay multiaddr:", err) +// return nil, err +// } + +// relayInfo, err := peer.AddrInfoFromP2pAddr(relayMA) +// if err != nil { +// fmt.Println("[DEBUG] Failed to extract relay peer info:", err) +// return nil, err +// } +// // Create circuit relay client +// fmt.Println("[DEBUG] Creating circuit relay client") +// // _ = client // Import for reservation function + +// cp := &ChatPeer{ +// Host: h, +// relayAddr: relayMA, +// relayID: relayInfo.ID, +// peers: make(map[peer.ID]string), +// } + +// fmt.Println(h.ID().String()) + +// fmt.Println("[DEBUG] Setting stream handler for chat protocol") +// h.SetStreamHandler(ChatProtocol, cp.handleChatStream) + +// return cp, nil +// } + +// func isPrivateAddr(addr multiaddr.Multiaddr) bool { +// addrStr := addr.String() +// return strings.Contains(addrStr, "127.0.0.1") || +// strings.Contains(addrStr, "192.168.") || +// strings.Contains(addrStr, "10.") || +// strings.Contains(addrStr, "172.16.") || +// strings.Contains(addrStr, "172.17.") || +// strings.Contains(addrStr, "172.18.") || +// strings.Contains(addrStr, "172.19.") || +// strings.Contains(addrStr, "172.2") || +// strings.Contains(addrStr, "172.30.") || +// strings.Contains(addrStr, "172.31.") +// } + +// // why???? + +// func (cp *ChatPeer) Start(ctx context.Context) error { +// fmt.Println("[DEBUG] Connecting to relay:", cp.relayAddr) +// relayInfo, _ := peer.AddrInfoFromP2pAddr(cp.relayAddr) +// if err := cp.Host.Connect(ctx, *relayInfo); err != nil { +// fmt.Println("[DEBUG] Failed to connect to relay:", err) +// return fmt.Errorf("failed to connect to relay: %w", err) +// } + +// // Make reservation with the relay +// fmt.Println("[DEBUG] Making reservation with relay...") +// reservation, err := client.Reserve(ctx, cp.Host, *relayInfo) +// if err != nil { +// fmt.Printf("[DEBUG] Failed to make reservation: %v\n", err) +// return fmt.Errorf("failed to make reservation: %w", err) +// } +// fmt.Printf("[DEBUG] Reservation successful! Expiry: %v\n", reservation.Expiration) + +// fmt.Printf("[DEBUG] Peer started!\n") +// fmt.Printf("[DEBUG] Peer ID: %s\n", cp.Host.ID()) + +// for _, addr := range cp.Host.Addrs() { +// fmt.Printf("[DEBUG] Address: %s/p2p/%s\n", addr, cp.Host.ID()) +// } + +// circuitAddr := cp.relayAddr.Encapsulate( +// multiaddr.StringCast(fmt.Sprintf("/p2p-circuit/p2p/%s", cp.Host.ID()))) + +// fmt.Printf("[INFO] Circuit Address (share this with other peers): %s\n", circuitAddr) + +// // Start a goroutine to periodically refresh reservations +// go cp.refreshReservations(ctx, *relayInfo) + +// var reqSent reqFormat +// reqSent.Type = "register" +// reqSent.PeerID = cp.Host.ID().String() // now sending the the peerID in the req to registeer in the relay +// //reqSent.PubIP = OwnPubIP // have too use a stun server to get public ip first and then send register command +// fmt.Println(reqSent.PeerID) +// logger.LogToFile("PeerID: " + reqSent.PeerID) +// stream, err := cp.Host.NewStream(context.Background(), relayInfo.ID, ChatProtocol) + +// if err != nil { +// fmt.Println("[DEBUG]Error Opening stream to relay") +// } +// fmt.Println("[DEBUG]Opened atream to relay successsfully") +// reqJson, err := json.Marshal(reqSent) +// if err != nil { +// fmt.Println("[DEBUG]Error marshalling the req to be sent") +// } +// stream.Write([]byte(reqJson)) + +// time.Sleep(1 * time.Second) + +// stream.Close() +// return nil +// } + +// func (cp *ChatPeer) refreshReservations(ctx context.Context, relayInfo peer.AddrInfo) { +// ticker := time.NewTicker(5 * time.Minute) // Refresh every 5 minutes +// defer ticker.Stop() + +// for { +// select { +// case <-ticker.C: +// fmt.Println("[DEBUG] Refreshing relay reservation...") +// if reservation, err := client.Reserve(ctx, cp.Host, relayInfo); err != nil { +// fmt.Printf("[DEBUG] Failed to refresh reservation: %v\n", err) +// } else { +// fmt.Printf("[DEBUG] Reservation refreshed! Expiry: %v\n", reservation.Expiration) +// } +// case <-ctx.Done(): +// return +// } +// } +// } + +// func (cp *ChatPeer) handleChatStream(s network.Stream) { +// fmt.Println("[DEBUG] Incoming chat stream from", s.Conn().RemotePeer()) +// defer s.Close() + +// reader := bufio.NewReader(s) +// for { + +// line, err := reader.ReadBytes('\n') +// if err != nil { +// fmt.Println("[DEBUG]Error reading the bytes from the stream") +// } +// line = bytes.TrimRight(line, "\n") +// line = bytes.TrimRight(line, "\x00") +// var reqStruct reqFormat +// err = json.Unmarshal(line, &reqStruct) + +// fmt.Println("[DEBUG] Raw input:", string(line)) + +// if err != nil { +// fmt.Println("[DEBUG]Error unmarshalling to reqStruc") +// } + +// var reqData map[string]interface{} +// reqStruct.ReqParams = bytes.TrimRight(reqStruct.ReqParams, "\x00") + +// if err := json.Unmarshal(reqStruct.ReqParams, &reqData); err != nil { +// fmt.Printf("[ERROR] Failed to unmarshal incoming request: %v\n", err) +// return +// } + +// fmt.Printf("[DEBUG]ReqData is : %+v \n", reqData) + +// if reqData["Method"] == "GET" { +// resp := ServeGetReq(reqStruct.ReqParams) +// resp = bytes.TrimRight(resp, "\x00") +// _, err = s.Write(resp) +// if err != nil { +// fmt.Println("[DEBUG]Error writing resp bytes to relay") +// return +// } +// } + +// if reqData["Method"] == "POST" { +// resp := ServePostReq(reqStruct.PeerID, reqStruct.ReqParams, reqStruct.Body) // have to set the new logic in serve post req now +// resp = bytes.TrimRight(resp, "\x00") +// _, err = s.Write(resp) +// if err != nil { +// fmt.Println("[DEBUG]Error writing resp bytes to relay") +// return +// } +// } + +// } +// } + +// func (cp *ChatPeer) Send(ctx context.Context, targetPeerID string, jsonReq []byte, body []byte) ([]byte, error) { +// //completeIP := TargetIP + ":" + targetPort + +// var req reqFormat +// req.Type = "SendMsg" +// //req.PeerID = completeIP +// req.PeerID = targetPeerID +// req.ReqParams = jsonReq +// req.Body = body +// stream, err := cp.Host.NewStream(ctx, cp.relayID, ChatProtocol) +// if err != nil { +// fmt.Println("[DEBUG]Error opneing a fetch ID stream to relay") +// return nil, err +// } + +// jsonReqRelay, err := json.Marshal(req) + +// if err != nil { +// fmt.Println("[DEBUG]Error marshalling get req to be sent to relay") +// return nil, err +// } + +// stream.Write([]byte(jsonReqRelay)) + +// fmt.Println("[DEBUG]Msg req sent to relay, waiting for ack") + +// reader := bufio.NewReader(stream) +// // ack, err := reader.ReadString('\n') + +// // if err != nil { +// // fmt.Println("[DEBUG]Error getting the acknowledgement") +// // return nil, err +// // } +// // _ = ack //can be used if required + +// var resp = make([]byte, 1024*50) +// reader.Read(resp) +// resp = bytes.TrimRight(resp, "\x00") +// defer stream.Close() + +// return resp, err +// } + +// func (cp *ChatPeer) GetConnectedPeers() []peer.ID { +// var peers []peer.ID +// for _, conn := range cp.Host.Network().Conns() { +// remotePeer := conn.RemotePeer() +// if remotePeer != cp.relayID { +// peers = append(peers, remotePeer) +// } +// } +// fmt.Printf("[DEBUG] Connected peers: %v\n", peers) +// return peers +// } + +// func (cp *ChatPeer) Close() error { +// fmt.Println("[DEBUG] Closing Host") +// return cp.Host.Close() +// } + +// // func GetPublicIP() string { +// // c, err := stun.Dial("udp4", "stun.l.google.com:19302") +// // if err != nil { +// // panic(err) +// // } +// // defer c.Close() + +// // var xorAddr stun.XORMappedAddress +// // message := stun.MustBuild(stun.TransactionID, stun.BindingRequest) +// // if err := c.Do(message, func(res stun.Event) { +// // if res.Error != nil { +// // panic(res.Error) +// // } +// // if err := xorAddr.GetFrom(res.Message); err != nil { +// // panic(err) +// // } +// // }); err != nil { +// // panic(err) +// // } + +// // if xorAddr.IP.To4() == nil { +// // panic("STUN returned an IPv6 address; IPv4 not available") +// // } + +// // peerAd := xorAddr.IP.String() + ":" + strconv.Itoa(xorAddr.Port) +// // return peerAd +// // } + +// func XorHexToBigInt(hex1, hex2 string) *big.Int { + +// bytes1, err1 := hex.DecodeString(hex1) +// bytes2, err2 := hex.DecodeString(hex2) + +// if err1 != nil || err2 != nil { +// log.Fatalf("Error decoding hex: %v %v", err1, err2) +// } + +// if len(bytes1) != len(bytes2) { +// log.Fatalf("Hex strings must be the same length") +// } + +// xorBytes := make([]byte, len(bytes1)) +// for i := 0; i < len(bytes1); i++ { +// xorBytes[i] = bytes1[i] ^ bytes2[i] +// } + +// result := new(big.Int).SetBytes(xorBytes) +// return result +// } package peer import ( @@ -8,6 +459,8 @@ import ( "crypto/x509" "log" "math/big" + "net/http" + "os" "sort" "context" @@ -20,7 +473,9 @@ import ( "strings" "time" + "github.com/devlup-labs/Libr/core/mod_client/keycache" "github.com/devlup-labs/Libr/core/mod_client/logger" + "github.com/joho/godotenv" "github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p/core/host" "github.com/libp2p/go-libp2p/core/network" @@ -42,6 +497,10 @@ import ( const ChatProtocol = protocol.ID("/chat/1.0.0") var OwnPubIP string +var PeerID string +var PubKey string +var JS_ServerURL string +var JS_API_key string type ChatPeer struct { Host host.Host @@ -70,6 +529,13 @@ func NewChatPeer(relayMultiAddrList []string) (*ChatPeer, error) { relayList = append(relayList, parts[len(parts)-1]) } + godotenv.Load() + JS_API_key = os.Getenv("JS_API_key") + JS_ServerURL = os.Getenv("JS_ServerURL") + if JS_API_key == "" || JS_ServerURL == "" { + return nil, fmt.Errorf("[DEBUG] Missing JS API key or server URL") + } + caCertPool := x509.NewCertPool() fmt.Println("[DEBUG] Creating connection manager") @@ -86,7 +552,7 @@ func NewChatPeer(relayMultiAddrList []string) (*ChatPeer, error) { } fmt.Println("[DEBUG] Creating libp2p Host") - h, err := libp2p.New( + h, _ := libp2p.New( libp2p.ListenAddrStrings("/ip4/0.0.0.0/tcp/0/ws"), // WebSocket libp2p.Security(libp2ptls.ID, libp2ptls.New), libp2p.ConnectionManager(connMgr), @@ -98,6 +564,14 @@ func NewChatPeer(relayMultiAddrList []string) (*ChatPeer, error) { // libp2p.Transport(websocket.New), ) + PubKey = keycache.LoadPubKey() + PeerID = h.ID().String() + + err = connectJSServer() + if err != nil { + fmt.Println("[DEBUG] Failed to connect to JS server:", err) + } + if err != nil { fmt.Println("[DEBUG] Failed to create Host:", err) return nil, err @@ -209,6 +683,39 @@ func isPrivateAddr(addr multiaddr.Multiaddr) bool { } // why???? +func connectJSServer() error { + postData := map[string]string{ + "peer_id": PeerID, + "public_key": PubKey, + } + + jsonData, err := json.Marshal(postData) + if err != nil { + return fmt.Errorf("failed to marshal JSON: %w", err) + } + + req, err := http.NewRequest("POST", JS_ServerURL+"/api/postnode", bytes.NewBuffer(jsonData)) + if err != nil { + return fmt.Errorf("failed to create request: %w", err) + } + + req.Header.Set("Content-Type", "application/json") + req.Header.Set("x-api-Key", JS_API_key) + + client := &http.Client{Timeout: 10 * time.Second} + resp, err := client.Do(req) + if err != nil { + return fmt.Errorf("failed to send request: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("server returned non-200 status code: %d", resp.StatusCode) + } + + fmt.Printf("Successfully connected to JS server:") + return nil +} func (cp *ChatPeer) Start(ctx context.Context) error { fmt.Println("[DEBUG] Connecting to relay:", cp.relayAddr) @@ -397,9 +904,46 @@ func (cp *ChatPeer) GetConnectedPeers() []peer.ID { func (cp *ChatPeer) Close() error { fmt.Println("[DEBUG] Closing Host") + err := deleteFromJSServer() + if err != nil { + return err + } return cp.Host.Close() } +func deleteFromJSServer() error { + deleteData := map[string]string{ + "peer_id": PeerID, + } + + jsonData, err := json.Marshal(deleteData) + if err != nil { + return fmt.Errorf("failed to marshal JSON: %w", err) + } + + req, err := http.NewRequest("DELETE", JS_ServerURL+"/api/deleteboot", bytes.NewBuffer(jsonData)) + if err != nil { + return fmt.Errorf("failed to create request: %w", err) + } + + req.Header.Set("Content-Type", "application/json") + req.Header.Set("x-api-key", JS_API_key) + + client := &http.Client{Timeout: 10 * time.Second} + resp, err := client.Do(req) + if err != nil { + return fmt.Errorf("failed to send request: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("server returned non-200 status code: %d", resp.StatusCode) + } + + fmt.Printf("Successfully deleted node") + return nil +} + // func GetPublicIP() string { // c, err := stun.Dial("udp4", "stun.l.google.com:19302") // if err != nil { @@ -448,4 +992,4 @@ func XorHexToBigInt(hex1, hex2 string) *big.Int { result := new(big.Int).SetBytes(xorBytes) return result -} +} \ No newline at end of file From db5ff4ea23c90a00a41dc060a2aa381abcf2edc1 Mon Sep 17 00:00:00 2001 From: kushagra0902 Date: Sun, 24 Aug 2025 04:40:42 +0530 Subject: [PATCH 10/11] fixed errors in routing --- core/mod_client/peers/peer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/mod_client/peers/peer.go b/core/mod_client/peers/peer.go index 1ffa404..891c39c 100644 --- a/core/mod_client/peers/peer.go +++ b/core/mod_client/peers/peer.go @@ -473,7 +473,7 @@ import ( "strings" "time" - "github.com/devlup-labs/Libr/core/mod_client/keycache" + "github.com/libr-forum/Libr/core/mod_client/keycache" "github.com/joho/godotenv" "github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p/core/host" From 9f92cbb1fe03412278740fe11319aec3d55cb0cc Mon Sep 17 00:00:00 2001 From: kushagra0902 Date: Fri, 12 Sep 2025 23:03:35 +0530 Subject: [PATCH 11/11] Added restart logic and made peerID deterministic --- core/db/internal/keycache/keycache.go | 11 ++ core/db/internal/models/models.go | 1 + core/db/internal/network/peers/peer.go | 30 ++--- core/db/internal/utils/mongodb.go | 155 ++++--------------------- core/db/main.go | 26 ++++- 5 files changed, 71 insertions(+), 152 deletions(-) diff --git a/core/db/internal/keycache/keycache.go b/core/db/internal/keycache/keycache.go index 223dab4..a7f84a0 100644 --- a/core/db/internal/keycache/keycache.go +++ b/core/db/internal/keycache/keycache.go @@ -6,6 +6,7 @@ import ( "fmt" "log" + "github.com/libp2p/go-libp2p/core/crypto" "github.com/libr-forum/Libr/core/crypto/cryptoutils" ) @@ -28,3 +29,13 @@ func LoadPubKey() string { pub, _, _ := cryptoutils.LoadKeys() return base64.StdEncoding.EncodeToString(pub) } + +func LoadPrivKey() crypto.PrivKey { + _, priv, _ := cryptoutils.LoadKeys() // priv is ed25519.PrivateKey (a []byte) + + libp2pPriv, err := crypto.UnmarshalEd25519PrivateKey(priv) + if err != nil { + panic(err) + } + return libp2pPriv +} \ No newline at end of file diff --git a/core/db/internal/models/models.go b/core/db/internal/models/models.go index 6f4774f..d7bd443 100644 --- a/core/db/internal/models/models.go +++ b/core/db/internal/models/models.go @@ -79,4 +79,5 @@ func (kb *KBucket) String() string { type DBConfig struct { API_KEY string `json:"x_api_key"` + JS_ServerURL string `json:"jsurl"` } \ No newline at end of file diff --git a/core/db/internal/network/peers/peer.go b/core/db/internal/network/peers/peer.go index 2df4b28..542c0a8 100644 --- a/core/db/internal/network/peers/peer.go +++ b/core/db/internal/network/peers/peer.go @@ -9,6 +9,7 @@ import ( "log" "math/big" "net/http" + //"os" "sort" @@ -22,8 +23,6 @@ import ( "strings" "time" - "github.com/libr-forum/Libr/core/db/config" - "github.com/libr-forum/Libr/core/db/internal/node" "github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p/core/host" "github.com/libp2p/go-libp2p/core/network" @@ -33,6 +32,9 @@ import ( "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/client" "github.com/libp2p/go-libp2p/p2p/protocol/holepunch" "github.com/libp2p/go-libp2p/p2p/protocol/identify" + "github.com/libr-forum/Libr/core/db/config" + "github.com/libr-forum/Libr/core/db/internal/keycache" + "github.com/libr-forum/Libr/core/db/internal/node" "github.com/multiformats/go-multiaddr" "github.com/libp2p/go-libp2p/p2p/transport/tcp" @@ -88,18 +90,20 @@ func NewChatPeer(relayMultiAddrList []string) (*ChatPeer, error) { // Other TLS configurations like ClientAuth, InsecureSkipVerify, etc. } + privKey := keycache.LoadPrivKey() + fmt.Println("[DEBUG] Creating libp2p Host") + h, err := libp2p.New( - libp2p.ListenAddrStrings("/ip4/0.0.0.0/tcp/0/ws"), // WebSocket - libp2p.Security(libp2ptls.ID, libp2ptls.New), - libp2p.ConnectionManager(connMgr), - libp2p.EnableNATService(), - libp2p.EnableRelay(), - libp2p.Transport(tcp.NewTCPTransport), - libp2p.Transport(websocket.New, websocket.WithTLSConfig(tlsConfig)), - // libp2p.Transport(websocket.NewWithTLSConfig(tlsConfig)), - // libp2p.Transport(websocket.New), - ) + libp2p.Identity(privKey), // βœ… ensures peer ID is derived from privKey + libp2p.ListenAddrStrings("/ip4/0.0.0.0/tcp/0/ws"), + libp2p.Security(libp2ptls.ID, libp2ptls.New), + libp2p.ConnectionManager(connMgr), + libp2p.EnableNATService(), + libp2p.EnableRelay(), + libp2p.Transport(tcp.NewTCPTransport), + libp2p.Transport(websocket.New, websocket.WithTLSConfig(tlsConfig)), +) if err != nil { fmt.Println("[DEBUG] Failed to create Host:", err) @@ -113,7 +117,7 @@ func NewChatPeer(relayMultiAddrList []string) (*ChatPeer, error) { } JS_API_key := cf.API_KEY - JS_ServerURL := "https://libr-server.onrender.com" + JS_ServerURL := cf.JS_ServerURL if(config.DBtype=="boot"){ fmt.Println("RUNNING DB AS BOOTSTRAP. APPROPRIATE CONFIG FOUND") diff --git a/core/db/internal/utils/mongodb.go b/core/db/internal/utils/mongodb.go index 313789f..9c68b2e 100644 --- a/core/db/internal/utils/mongodb.go +++ b/core/db/internal/utils/mongodb.go @@ -4,159 +4,34 @@ import ( "encoding/json" "fmt" "net/http" - "os" "time" + "github.com/libr-forum/Libr/core/db/config" "github.com/libr-forum/Libr/core/db/internal/models" - // "github.com/libr-forum/Libr/core/db/internal/node" - // "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" ) var MongoClient *mongo.Client -// SetupMongo initializes the global MongoClient -// func SetupMongo(uri string) error { -// ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) -// defer cancel() -// -// client, err := mongo.Connect(ctx, options.Client().ApplyURI(uri)) -// if err != nil { -// return fmt.Errorf("failed to connect to MongoDB: %w", err) -// } -// -// if err := client.Ping(ctx, nil); err != nil { -// return fmt.Errorf("failed to ping MongoDB: %w", err) -// } -// -// MongoClient = client -// log.Println("βœ… MongoDB connected") -// return nil -// } - -// DisconnectMongo gracefully closes the MongoDB connection -// func DisconnectMongo() { -// if MongoClient != nil { -// if err := MongoClient.Disconnect(context.Background()); err != nil { -// log.Println("⚠️ Error disconnecting MongoDB:", err) -// } else { -// log.Println("πŸ›‘ MongoDB disconnected") -// } -// } -// } - -// πŸš€ Uses global MongoClient and ctx -// func GetDbAddr() ([]*models.Node, error) { -// ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) -// defer cancel() -// -// collection := MongoClient.Database("Addrs").Collection("nodes") // replace with actual DB & collection -// cursor, err := collection.Find(ctx, bson.M{}) -// if err != nil { -// return nil, err -// } -// defer cursor.Close(ctx) -// -// var nodeList []*models.Node -// for cursor.Next(ctx) { -// var doc struct { -// NodeId string `bson:"node_id"` -// PeerId string `bson:"peer_id"` -// } -// if err := cursor.Decode(&doc); err != nil { -// return nil, err -// } -// -// nodeId, _ := node.DecodeNodeID(doc.NodeId) -// node := &models.Node{ -// NodeId: nodeId, -// PeerId: doc.PeerId, -// } -// nodeList = append(nodeList, node) -// } -// return nodeList, nil -// } - -// func GetOnlineMods() ([]*models.Mod, error) { -// ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) -// defer cancel() -// -// collection := MongoClient.Database("Addrs").Collection("mods") -// cursor, err := collection.Find(ctx, bson.M{}) -// if err != nil { -// return nil, err -// } -// defer cursor.Close(ctx) -// -// var mods []*models.Mod -// for cursor.Next(ctx) { -// var doc struct { -// IP string `bson:"ip"` -// Port string `bson:"port"` -// PublicKey string `bson:"public_key"` -// } -// if err := cursor.Decode(&doc); err != nil { -// return nil, err -// } -// mods = append(mods, &models.Mod{ -// IP: doc.IP, -// Port: doc.Port, -// PublicKey: doc.PublicKey, -// }) -// } -// fmt.Println("Online mods:", mods) -// return mods, nil -// } - -// func GetRelayAddr() ([]string, error) { -// ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) -// defer cancel() -// -// collection := MongoClient.Database("Addrs").Collection("relays") -// cursor, err := collection.Find(ctx, bson.M{}) -// if err != nil { -// return nil, fmt.Errorf("failed to fetch relay addresses: %w", err) -// } -// defer cursor.Close(ctx) -// -// var relayList []string -// for cursor.Next(ctx) { -// var doc struct { -// Address string `bson:"address"` -// } -// if err := cursor.Decode(&doc); err != nil { -// return nil, fmt.Errorf("failed to decode relay document: %w", err) -// } -// if strings.HasPrefix(doc.Address, "/") { -// relayList = append(relayList, strings.TrimSpace(doc.Address)) -// } -// } -// -// return relayList, nil -// } - -// -------------------- ACTIVE CODE -------------------- - -// type relayResp struct { -// RelayList []relays `json:"relaylist"` -// } type modResp struct { ModLists []models.Mods `json:"modlist"` } -// type relays struct { -// Address string `json:"address"` -// } type NodeResp struct { NodesLists []models.Node `json:"nodeslist"` } -// βœ… Fetch relay addresses + func GetRelayAddrFromJSServer() ([]string, error) { - serverURL := "https://libr-server.onrender.com" + cf, err := config.ReadDBConfigFile() + if err != nil { + fmt.Println("Error reading dbconfig.json:", err) + return nil, err + } + serverURL := cf.JS_ServerURL req, err := http.NewRequest("GET", serverURL+"/api/getrelay", nil) if err != nil { @@ -200,7 +75,12 @@ type relayResp struct { // βœ… Fetch mods func GetModsFromJSServer() ([]*models.Mods, error) { - serverURL := os.Getenv("JS_ServerURL") + cf, err := config.ReadDBConfigFile() + if err != nil { + fmt.Println("Error reading dbconfig.json:", err) + return nil, err + } + serverURL := cf.JS_ServerURL req, err := http.NewRequest("GET", serverURL+"/api/getmod", nil) // πŸ”₯ corrected endpoint if err != nil { @@ -235,7 +115,12 @@ func GetModsFromJSServer() ([]*models.Mods, error) { // βœ… Fetch DB nodes func GetDBFromJSServer() ([]*models.Node, error) { - serverURL := os.Getenv("JS_ServerURL") + cf, err := config.ReadDBConfigFile() + if err != nil { + fmt.Println("Error reading dbconfig.json:", err) + return nil, err + } + serverURL := cf.JS_ServerURL req, err := http.NewRequest("GET", serverURL+"/api/getboot", nil) // πŸ”₯ corrected endpoint if err != nil { diff --git a/core/db/main.go b/core/db/main.go index 1be519b..f63c9cc 100644 --- a/core/db/main.go +++ b/core/db/main.go @@ -15,6 +15,7 @@ import ( "github.com/libr-forum/Libr/core/db/config" "github.com/libr-forum/Libr/core/db/internal/keycache" peer "github.com/libr-forum/Libr/core/db/internal/network/peers" + "github.com/libr-forum/Libr/core/db/internal/node" "github.com/libr-forum/Libr/core/db/internal/routing" "github.com/libr-forum/Libr/core/db/internal/utils" ) @@ -35,7 +36,7 @@ func main() { } JS_API_key = cf.API_KEY - JS_ServerURL = "https://libr-server.onrender.com" + JS_ServerURL = cf.JS_ServerURL //utils.SetupMongo("mongodb+srv://peer:peerhehe@cluster0.vswojqe.mongodb.net/") //utils.SetupMongo(JS_ServerURL) @@ -46,8 +47,25 @@ func main() { } fmt.Println(relayAddrs) - peer.StartNode(relayAddrs) - + + go func() { + for { + // Close old host if it exists + if peer.Peer != nil && peer.Peer.Host != nil { + fmt.Println("[DEBUG] Closing host") + peer.Peer.Host.Close() + } + + // Start a new node right away + fmt.Println("[DEBUG] Starting new node...") + peer.StartNode(relayAddrs) + + // ⏰ Calculate how long to wait until the next o'clock + time.Sleep(55*time.Minute) + } +}() + + sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM) @@ -66,7 +84,7 @@ func main() { func deleteFromJSServer() error { deleteData := map[string]string{ - "peer_id" : peer.PeerID, + "node_id" : node.GenerateNodeIDFromPublicKey(), } jsonData, err := json.Marshal(deleteData)