.git broken, restart
This commit is contained in:
Executable
+115
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
### === CONFIG ===
|
||||
ALPINE_VERSION="3.20.3"
|
||||
ALPINE_BASE_URL="https://dl-cdn.alpinelinux.org/alpine/v${ALPINE_VERSION%.*}/releases/aarch64"
|
||||
IMAGE="alpine-rpi-${ALPINE_VERSION}-aarch64.img.gz"
|
||||
SHA256SUMS="SHA256SUMS"
|
||||
SIGFILE="SHA256SUMS.asc"
|
||||
DEVICE="" # will be asked interactively
|
||||
|
||||
echo "=== Secure Alpine Installer ==="
|
||||
echo "Version: $ALPINE_VERSION"
|
||||
echo
|
||||
|
||||
### === Step 1: Download files ===
|
||||
echo "[1/5] Downloading Alpine image and verification files…"
|
||||
curl -O "${ALPINE_BASE_URL}/${IMAGE}"
|
||||
curl -O "${ALPINE_BASE_URL}/${SHA256SUMS}"
|
||||
curl -O "${ALPINE_BASE_URL}/${SIGFILE}"
|
||||
|
||||
### === Step 2: Verify SHA256 hash ===
|
||||
echo "[2/5] Verifying SHA256 checksum…"
|
||||
EXPECTED_HASH=$(grep "$IMAGE" "$SHA256SUMS" | awk '{print $1}')
|
||||
DOWNLOADED_HASH=$(sha256sum "$IMAGE" | awk '{print $1}')
|
||||
|
||||
if [[ "$EXPECTED_HASH" != "$DOWNLOADED_HASH" ]]; then
|
||||
echo "❌ ERROR: SHA256 checksum mismatch!"
|
||||
echo "Expected: $EXPECTED_HASH"
|
||||
echo "Downloaded: $DOWNLOADED_HASH"
|
||||
exit 1
|
||||
else
|
||||
echo "✔ SHA256 checksum OK"
|
||||
fi
|
||||
|
||||
### === Step 3: Verify signature (requires alpine-devel keyring) ===
|
||||
echo "[3/5] Verifying SHA256SUMS signature (GPG)…"
|
||||
|
||||
if command -v gpg >/dev/null 2>&1; then
|
||||
# Import Alpine signing keys (safe & public)
|
||||
curl -O https://alpinelinux.org/keys/alpine-devel@lists.alpinelinux.org.asc
|
||||
gpg --import alpine-devel@lists.alpinelinux.org.asc
|
||||
|
||||
if gpg --verify "$SIGFILE" "$SHA256SUMS" 2>/dev/null; then
|
||||
echo "✔ Signature verification OK"
|
||||
else
|
||||
echo "❌ Signature verification failed"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "⚠ GPG not installed — skipping signature verification."
|
||||
fi
|
||||
|
||||
### === Step 4: Select device ===
|
||||
echo "[4/5] Select your SD card device:"
|
||||
lsblk
|
||||
read -rp "Enter the device path (e.g. /dev/sdX or /dev/mmcblk0): " DEVICE
|
||||
|
||||
if [[ ! -b "$DEVICE" ]]; then
|
||||
echo "❌ ERROR: Device not found."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "⚠️ All data on $DEVICE will be erased. Continue? (yes/no)"
|
||||
read CONFIRM
|
||||
[[ "$CONFIRM" == "yes" ]] || exit 1
|
||||
|
||||
### === Step 5: Write image to SD card safely ===
|
||||
echo "[5/5] Installing Alpine image to $DEVICE…"
|
||||
gunzip -c "$IMAGE" | sudo dd of="$DEVICE" bs=4M status=progress conv=fsync
|
||||
|
||||
echo "✔ Alpine successfully written to the SD card"
|
||||
echo "You can now insert the SD card into the Raspberry Pi."
|
||||
|
||||
### === Security suggestions after first boot ===
|
||||
cat <<EOF
|
||||
|
||||
🔐 === POST-INSTALL SECURITY RECOMMENDATIONS ===
|
||||
|
||||
After first boot on the Raspberry Pi:
|
||||
|
||||
1. Change root password:
|
||||
passwd
|
||||
|
||||
2. Enable community repository:
|
||||
echo 'https://dl-cdn.alpinelinux.org/alpine/v${ALPINE_VERSION%.*}/community' >> /etc/apk/repositories
|
||||
|
||||
3. Update system:
|
||||
apk update && apk upgrade
|
||||
|
||||
4. Install security tools:
|
||||
apk add openssh-server ufw doas
|
||||
|
||||
5. Harden SSH:
|
||||
edit /etc/ssh/sshd_config
|
||||
- PermitRootLogin no
|
||||
- PasswordAuthentication no
|
||||
- UseKeychain yes
|
||||
|
||||
6. Create a non-root user:
|
||||
adduser secureuser
|
||||
echo "permit persist secureuser as root" > /etc/doas.d/doas.conf
|
||||
|
||||
7. Enable firewall:
|
||||
ufw default deny incoming
|
||||
ufw allow ssh
|
||||
ufw enable
|
||||
|
||||
8. Enable automatic security updates:
|
||||
apk add alpine-conf
|
||||
setup-automatic-updates
|
||||
|
||||
Your Alpine installation is now secure and minimal.
|
||||
EOF
|
||||
|
||||
Executable
+65
@@ -0,0 +1,65 @@
|
||||
#!/bin/bash
|
||||
set -eux
|
||||
|
||||
ISO_URL="https://dl-cdn.alpinelinux.org/alpine/v3.22/releases/x86_64/alpine-virt-3.22.2-x86_64.iso"
|
||||
|
||||
# from vm to make a shared folder
|
||||
if [ $# -lt 1 ] ; then
|
||||
echo """
|
||||
ISO=${1:-$(basename $ISO_URL)}
|
||||
IMG=${2:-disc_alpine.qcow2}
|
||||
SIZE=${3:-16G}
|
||||
RAM=${4:-2G}
|
||||
CPUS=${5:-2}
|
||||
SHARE=${6:-$PWD/share}
|
||||
"""
|
||||
echo "cheat sheet: mount -t 9p -o trans=virtio hostshare /mnt"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Configurable defaults ---
|
||||
ISO=${1:-$(basename $ISO_URL)}
|
||||
IMG=${2:-disc_alpine.qcow2}
|
||||
SIZE=${3:-16G}
|
||||
RAM=${4:-2G}
|
||||
CPUS=${5:-2}
|
||||
SHARE=${6:-$PWD/share}
|
||||
|
||||
# --- Setup ---
|
||||
mkdir -p "$SHARE"
|
||||
echo "iso = $ISO"
|
||||
[ -f "$ISO" ] || wget "$ISO_URL"
|
||||
[ -f "$IMG" ] || qemu-img create -o nocow=on -f qcow2 "$IMG" "$SIZE"
|
||||
|
||||
# --- Optional install script ---
|
||||
# Drop any file named install.sh in ./share to execute it inside the VM later:
|
||||
# e.g. `bash /mnt/share/install.sh` after mounting
|
||||
|
||||
|
||||
|
||||
qemu-system-x86_64 \
|
||||
-m $RAM \
|
||||
-nic user \
|
||||
-boot once=d \
|
||||
-cdrom $ISO \
|
||||
-drive file=$IMG \
|
||||
-device virtio-vga \
|
||||
-enable-kvm \
|
||||
-display default,show-cursor=on \
|
||||
-nic user,hostfwd=tcp::2222-:22 \
|
||||
-virtfs local,id=share,path="$SHARE",security_model=none,mount_tag=hostshare
|
||||
|
||||
## --- Run QEMU with graphics + shared folder ---
|
||||
#qemu-system-x86_64 \
|
||||
# -enable-kvm \
|
||||
# -m "$RAM" \
|
||||
# -cpu host \
|
||||
# -smp "$CPUS" \
|
||||
# -boot d \
|
||||
# -cdrom "$ISO" \
|
||||
# -drive file="$IMG",format=qcow2 \
|
||||
# -device virtio-vga \
|
||||
# -display default,show-cursor=on \
|
||||
# -nic user,hostfwd=tcp::2222-:22 \
|
||||
# -virtfs local,id=share,path="$SHARE",security_model=none,mount_tag=hostshare
|
||||
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
#!/bin/bash
|
||||
set -eux
|
||||
|
||||
# from vm to make a shared folder
|
||||
if [ $# -lt 1 ] ; then
|
||||
echo """
|
||||
IMG=${1:-disc_alpine.qcow2}
|
||||
SIZE=${2:-16G}
|
||||
RAM=${3:-2G}
|
||||
CPUS=${4:-2}
|
||||
SHARE=${5:-$PWD/share}
|
||||
"""
|
||||
echo "cheat sheet: mount -t 9p -o trans=virtio hostshare /mnt"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Configurable defaults ---
|
||||
IMG=${1:-disc_alpine.qcow2}
|
||||
SIZE=${2:-16G}
|
||||
RAM=${3:-2G}
|
||||
CPUS=${4:-2}
|
||||
SHARE=${5:-$PWD/share}
|
||||
|
||||
# --- Setup ---
|
||||
mkdir -p "$SHARE"
|
||||
|
||||
# --- Optional install script ---
|
||||
# Drop any file named install.sh in ./share to execute it inside the VM later:
|
||||
# e.g. `bash /mnt/share/install.sh` after mounting
|
||||
|
||||
|
||||
|
||||
qemu-system-x86_64 \
|
||||
-m $RAM \
|
||||
-boot once=d \
|
||||
-drive file=$IMG \
|
||||
-device virtio-vga \
|
||||
-enable-kvm \
|
||||
-display default,show-cursor=on \
|
||||
-nic user,hostfwd=tcp::2222-:22 \
|
||||
-virtfs local,id=share,path="$SHARE",security_model=none,mount_tag=hostshare
|
||||
|
||||
Executable
+14
@@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
append_cmd ()
|
||||
{
|
||||
local CMD=$1;
|
||||
local F_NAME=$2;
|
||||
echo >> $F_NAME;
|
||||
echo ${CMD} >> $F_NAME;
|
||||
echo >> $F_NAME;
|
||||
eval ${CMD} >> $F_NAME;
|
||||
echo >> $F_NAME;
|
||||
echo "###############################################" >> $F_NAME;
|
||||
echo >> $F_NAME
|
||||
}
|
||||
append_cmd "$@"
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
UUID_BOOT=$(sudo blkid | grep -E nbd[0-9a-z]+1 | grepkey PARTUUID | sed "s/\"//g")
|
||||
UUID_ROOT=$(sudo blkid | grep -E nbd[0-9a-z]+2 | grepkey PARTUUID | sed "s/\"//g")
|
||||
|
||||
echo "/dev/disk/by-uuid/$UUID_BOOT /boot vfat defaults 0 0" >> rootfs/etc/fstab
|
||||
echo "/dev/disk/by-uuid/$UUID_ROOT / ext4 defaults 0 0" >> rootfs/etc/fstab
|
||||
exit 0
|
||||
|
||||
Executable
+39
@@ -0,0 +1,39 @@
|
||||
#!/bin/bash
|
||||
set -eux
|
||||
|
||||
# from vm to make a shared folder
|
||||
echo "cheat sheet: mount -t 9p -o trans=virtio hostshare /mnt"
|
||||
|
||||
# --- Configurable defaults ---
|
||||
ISO_URL="https://mirror.arizona.edu/archlinux/iso/latest/archlinux-x86_64.iso"
|
||||
ISO=${1:-$(basename $ISO_URL)}
|
||||
IMG=${2:-disk_qemu.qcow2}
|
||||
SIZE=${3:-16G}
|
||||
RAM=${4:-2G}
|
||||
CPUS=${5:-2}
|
||||
SHARE=${6:-$PWD/share}
|
||||
|
||||
# --- Setup ---
|
||||
mkdir -p "$SHARE"
|
||||
echo "iso = $ISO"
|
||||
[ -f "$ISO" ] || wget "$ISO_URL"
|
||||
[ -f "$IMG" ] || qemu-img create -o nocow=on -f qcow2 "$IMG" "$SIZE"
|
||||
|
||||
# --- Optional install script ---
|
||||
# Drop any file named install.sh in ./share to execute it inside the VM later:
|
||||
# e.g. `bash /mnt/share/install.sh` after mounting
|
||||
|
||||
# --- Run QEMU with graphics + shared folder ---
|
||||
qemu-system-x86_64 \
|
||||
-enable-kvm \
|
||||
-m "$RAM" \
|
||||
-cpu host \
|
||||
-smp "$CPUS" \
|
||||
-boot d \
|
||||
-cdrom "$ISO" \
|
||||
-drive file="$IMG",format=qcow2 \
|
||||
-device virtio-vga \
|
||||
-display default,show-cursor=on \
|
||||
-nic user,hostfwd=tcp::2222-:22 \
|
||||
-virtfs local,id=share,path="$SHARE",security_model=none,mount_tag=hostshare
|
||||
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
FILE="install/arch.sh"
|
||||
|
||||
cd $MACHINE_DIR
|
||||
vim $FILE
|
||||
gitaddcommit $FILE
|
||||
cd -
|
||||
|
||||
exit 0
|
||||
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
aur ()
|
||||
{
|
||||
git clone https://aur.archlinux.org/$1.git
|
||||
}
|
||||
aur "$@"
|
||||
Executable
+28
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
|
||||
if [ "$#" -lt 1 ] || [ "$#" -gt 1 ]; then
|
||||
echo "Usage: $0 alias"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
F=$(which "$1")
|
||||
|
||||
if [ ! -f "$F" ]; then
|
||||
F="$BIN_DIR/$1"
|
||||
cp $MACHINE_DIR/usr/home/.vim/templates/template.sh $F
|
||||
fi
|
||||
vim "$F"
|
||||
chmod +x $F
|
||||
|
||||
cd $BIN_DIR
|
||||
git pull
|
||||
gitaddcommit
|
||||
git push
|
||||
cd -
|
||||
|
||||
|
||||
|
||||
exit 0
|
||||
|
||||
Executable
+12
@@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
basha ()
|
||||
{
|
||||
SOURCE="$HOME/.bashrc";
|
||||
F_NAME=".bash_aliases";
|
||||
FILE=$HOME/$F_NAME;
|
||||
cd "$HOME/machine";
|
||||
commit_if_modified "$FILE";
|
||||
cd -;
|
||||
source $SOURCE
|
||||
}
|
||||
basha "$@"
|
||||
Executable
+12
@@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
basha ()
|
||||
{
|
||||
SOURCE="$HOME/.bashrc";
|
||||
F_NAME=".bash_aliases";
|
||||
FILE=$HOME/$F_NAME;
|
||||
cd "$HOME/machine";
|
||||
commit_if_modified "$FILE";
|
||||
cd -;
|
||||
source $SOURCE
|
||||
}
|
||||
basha "$@"
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
bashalias ()
|
||||
{
|
||||
vim /home/.bash_aliases
|
||||
}
|
||||
bashalias "$@"
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
bashrc ()
|
||||
{
|
||||
vim ~/.bashrc
|
||||
}
|
||||
bashrc "$@"
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
vim + $BLACKLIST
|
||||
sudo -E bash "$NFT_RESET"
|
||||
|
||||
exit 0
|
||||
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
MACHINE_DIR=${1:$MACHINE_DIR}
|
||||
MACHINE_DIR=${MACHINE_DIR:-"/svr"}
|
||||
F_NAME=".bashrc";
|
||||
cd "$MACHINE_DIR/usr/home";
|
||||
commit_if_modified "$F_NAME"
|
||||
cp -f $F_NAME /home/$F_NAME;
|
||||
cd -
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then
|
||||
echo "Usage: $0 url [file out] [*]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
URL=$1
|
||||
shift
|
||||
OUT=${1:-"posts.json"}
|
||||
echo "ÖUT = $OUT"
|
||||
shift
|
||||
|
||||
bsdlpost.py $(bsurifromurl.py $URL 2>/dev/null) -o $OUT $@ 2>/dev/null
|
||||
|
||||
exit 0
|
||||
|
||||
Executable
+73
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env python3
|
||||
from atproto import Client
|
||||
import argparse
|
||||
import os
|
||||
|
||||
DEFAULT_DOMAIN = "bsky.social"
|
||||
DEFAULT_NAME = "ni-bot"
|
||||
DEFAULT_DIR = "/tmp/bs"
|
||||
|
||||
def path(tokendir, name="ni-bot"):
|
||||
return os.path.join(tokendir, name)
|
||||
|
||||
def read_file(filepath):
|
||||
with open(filepath, "r") as f:
|
||||
return f.read().strip()
|
||||
|
||||
def write_file(filepath, data):
|
||||
with open(filepath, "w") as f:
|
||||
f.write(data)
|
||||
|
||||
def get_last(tokendir=DEFAULT_DIR):
|
||||
return read_file(path(tokendir, "last"))
|
||||
|
||||
def set_last(full_name, tokendir=DEFAULT_DIR):
|
||||
write_file(path(tokendir, "last"), full_name)
|
||||
|
||||
def save_session(client, full_name, tokendir):
|
||||
write_file(path(tokendir, full_name), client.export_session_string())
|
||||
set_last(full_name, tokendir)
|
||||
|
||||
def load_session(client, full_name, tokendir):
|
||||
client.login(session_string=read_file(path(tokendir, full_name)))
|
||||
set_last(full_name, tokendir)
|
||||
return client
|
||||
|
||||
def connect(name=None, domain=DEFAULT_DOMAIN, passwd=None, token_dir=DEFAULT_DIR):
|
||||
os.makedirs(token_dir, exist_ok=True)
|
||||
full_name = f"{name}.{domain}" if name else get_last(token_dir)
|
||||
client = Client()
|
||||
try:
|
||||
if passwd:
|
||||
client.login(full_name, passwd)
|
||||
save_session(client, full_name, token_dir)
|
||||
else:
|
||||
client = load_session(client, full_name, token_dir)
|
||||
except Exception as e:
|
||||
raise SystemExit(f"Connection failed: {e}")
|
||||
return client
|
||||
|
||||
def brute(name, domain, passwdlist, tokendir):
|
||||
with open(passwdlist, 'r') as f:
|
||||
for wd in f.readlines():
|
||||
try:
|
||||
print("trying: '" + wd.strip() + "'")
|
||||
connect(name, domain, wd.strip(), tokendir)
|
||||
print("connected")
|
||||
print(wd)
|
||||
break
|
||||
except:
|
||||
continue
|
||||
|
||||
def main():
|
||||
p = argparse.ArgumentParser(description="Brute")
|
||||
p.add_argument("name", nargs="?", help="Bluesky handle (username)")
|
||||
p.add_argument("--domain", default=DEFAULT_DOMAIN)
|
||||
p.add_argument("--tokendir", default=DEFAULT_DIR)
|
||||
p.add_argument("--passwdlist", "-p", default=None, help="passwd list")
|
||||
args = p.parse_args()
|
||||
brute(args.name, args.domain, args.passwdlist, args.tokendir)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Executable
+63
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env python3
|
||||
from atproto import Client
|
||||
import argparse
|
||||
import os
|
||||
|
||||
DEFAULT_DOMAIN = "bsky.social"
|
||||
DEFAULT_NAME = "ni-bot"
|
||||
DEFAULT_DIR = "/tmp/bs"
|
||||
|
||||
def path(tokendir, name="ni-bot"):
|
||||
return os.path.join(tokendir, name)
|
||||
|
||||
def read_file(filepath):
|
||||
with open(filepath, "r") as f:
|
||||
return f.read().strip()
|
||||
|
||||
def write_file(filepath, data):
|
||||
with open(filepath, "w") as f:
|
||||
f.write(data)
|
||||
|
||||
def get_last(tokendir=DEFAULT_DIR):
|
||||
return read_file(path(tokendir, "last"))
|
||||
|
||||
def set_last(full_name, tokendir=DEFAULT_DIR):
|
||||
write_file(path(tokendir, "last"), full_name)
|
||||
|
||||
def save_session(client, full_name, tokendir):
|
||||
write_file(path(tokendir, full_name), client.export_session_string())
|
||||
set_last(full_name, tokendir)
|
||||
|
||||
def load_session(client, full_name, tokendir):
|
||||
client.login(session_string=read_file(path(tokendir, full_name)))
|
||||
set_last(full_name, tokendir)
|
||||
return client
|
||||
|
||||
def connect(name=None, domain=DEFAULT_DOMAIN, passwd=None, token_dir=DEFAULT_DIR):
|
||||
os.makedirs(token_dir, exist_ok=True)
|
||||
full_name = f"{name}.{domain}" if name else get_last(token_dir)
|
||||
client = Client()
|
||||
try:
|
||||
if passwd:
|
||||
client.login(full_name, passwd)
|
||||
save_session(client, full_name, token_dir)
|
||||
else:
|
||||
client = load_session(client, full_name, token_dir)
|
||||
except Exception as e:
|
||||
raise SystemExit(f"Connection failed: {e}")
|
||||
return client
|
||||
|
||||
def main():
|
||||
p = argparse.ArgumentParser(description="Connect to Bluesky and store session.")
|
||||
p.add_argument("name", nargs="?", help="Bluesky handle (username)")
|
||||
p.add_argument("--domain", default=DEFAULT_DOMAIN)
|
||||
p.add_argument("--tokendir", default=DEFAULT_DIR)
|
||||
p.add_argument("--passwd", "-p", default=None)
|
||||
args = p.parse_args()
|
||||
|
||||
connect(args.name, args.domain, args.passwd, args.tokendir)
|
||||
print("connected")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
if [ "$#" -lt 1 ] || [ "$#" -gt 3 ]; then
|
||||
echo "Usage: $0 arg1 [arg2] [arg3]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# interactive session check
|
||||
if [ -t 0 ]; then
|
||||
echo -n "Delete existing output files? [y/N]: "
|
||||
read ans
|
||||
case "$ans" in
|
||||
y|Y) rm -f *.school ;;
|
||||
*) echo "Aborted"; exit 0 ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# process input file
|
||||
while IFS= read -r line; do
|
||||
new_f="${line%.*}.school"
|
||||
f > "$new_f"
|
||||
done < "$FILE"
|
||||
|
||||
exit 0
|
||||
|
||||
Executable
+50
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
from bscon import connect
|
||||
from bsdlprofile import TMP_DIR
|
||||
import os
|
||||
from atproto import Client
|
||||
0
|
||||
|
||||
LIMIT_LOAD = 100
|
||||
|
||||
def save_item(post, filename, directory=""):
|
||||
filename = f"{directory}/{filename}"
|
||||
subprocess.run(["mkdir", "-p", directory])
|
||||
if not os.path.isfile(filename):
|
||||
with open(filename, 'w') as f:
|
||||
f.write(post.record.text)
|
||||
|
||||
|
||||
def get_feeds(client, profile, tmp_dir=TMP_DIR, save=False, cursor=None):
|
||||
directory = f"{tmp_dir}/{profile}"
|
||||
n = 0
|
||||
while True:
|
||||
res = client.app.bsky.feed.get_author_feed(
|
||||
params={"actor": profile, "limit": LIMIT_LOAD, **({"cursor": cursor} if cursor else {})}
|
||||
)
|
||||
for post in res["feed"]:
|
||||
save_item(post.post, post.post.record.created_at, directory)
|
||||
n += 1
|
||||
cursor = res.cursor
|
||||
if not cursor:
|
||||
break
|
||||
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Download Bluesky profile posts to JSON")
|
||||
parser.add_argument("handle", help="Bluesky handle (ex: ni-bot.bsky.social)")
|
||||
parser.add_argument("--folder", default=TMP_DIR)
|
||||
args = parser.parse_args()
|
||||
|
||||
client = connect()
|
||||
profile = get_feeds(client, args.handle, args.folder)
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Executable
+72
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from bscon import connect
|
||||
from bsdlprofile import TMP_DIR
|
||||
import requests
|
||||
import os
|
||||
import subprocess
|
||||
import re
|
||||
from atproto import Client
|
||||
from atproto_client import models
|
||||
|
||||
LIMIT_LOAD = 100
|
||||
|
||||
def save_item(filename, obj, directory=""):
|
||||
filename = f"{directory}/{filename}"
|
||||
subprocess.run(["mkdir", "-p", directory])
|
||||
with open(filename, 'w') as f:
|
||||
f.write(str(obj))
|
||||
|
||||
def save_items(obj, directory=""):
|
||||
if isinstance(obj, dict):
|
||||
for k, v in obj.items():
|
||||
new_dir = f"{directory}/{k}" if directory else k
|
||||
save_items(v, new_dir)
|
||||
elif isinstance(obj, list):
|
||||
for i, v in enumerate(obj):
|
||||
new_dir = f"{directory}[{i}]"
|
||||
save_items(v, new_dir)
|
||||
else:
|
||||
filename = ''.join(re.findall(r'[a-zA-Z0-9]', str(obj)[:20])) + '.txt'
|
||||
save_item(filename, obj, directory)
|
||||
|
||||
|
||||
def get_feeds(client, profile, tmp_dir=TMP_DIR, save=False, cursor=None):
|
||||
directory = f"{tmp_dir}/{profile}"
|
||||
n = 0
|
||||
while True:
|
||||
res = client.app.bsky.feed.get_author_feed(
|
||||
params={"actor": profile, "limit": LIMIT_LOAD, **({"cursor": cursor} if cursor else {})}
|
||||
)
|
||||
for post in res["feed"]:
|
||||
item_directory = f"{directory}/{n:05d}"
|
||||
print(f"\nsaving: {n:05d}\n\t{post.post.record.text}")
|
||||
save_items(post.model_dump(), item_directory)
|
||||
n += 1
|
||||
cursor = res.cursor
|
||||
if not cursor:
|
||||
break
|
||||
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Download Bluesky profile posts to JSON")
|
||||
parser.add_argument("handle", help="Bluesky handle (ex: ni-bot.bsky.social)")
|
||||
parser.add_argument("--folder", default=TMP_DIR)
|
||||
args = parser.parse_args()
|
||||
|
||||
client = connect()
|
||||
<<<<<<< HEAD
|
||||
profile = get_feeds(client, args.handle, args.folder, cursor=cursor)
|
||||
=======
|
||||
profile = get_feeds(client, args.handle, args.folder)
|
||||
>>>>>>> 01ee0aacb9e93bd6572ab9049f26878733f8bf85
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Executable
+68
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import json
|
||||
from bscon import connect
|
||||
|
||||
def fetch_thread(client, uri, seen=None):
|
||||
"""Recursively fetch a post thread including replies."""
|
||||
if seen is None:
|
||||
seen = set()
|
||||
if uri in seen:
|
||||
return []
|
||||
seen.add(uri)
|
||||
|
||||
resp = client.app.bsky.feed.get_post_thread({"uri": uri})
|
||||
data = resp.model_dump() # convert Pydantic Response to dict
|
||||
out = [data]
|
||||
|
||||
post = data.get("thread")
|
||||
if post and "replies" in post:
|
||||
for reply in post["replies"]:
|
||||
child_uri = reply.get("post", {}).get("uri")
|
||||
if child_uri:
|
||||
out += fetch_thread(client, child_uri, seen)
|
||||
return out
|
||||
|
||||
def fetch_all_pages(fetch_fn, client, uri, key):
|
||||
"""Generic paginated fetch (likes, reposts)."""
|
||||
results = []
|
||||
cursor = None
|
||||
while True:
|
||||
resp = fetch_fn(client, uri, cursor)
|
||||
data = resp.model_dump() # <-- convert to dict
|
||||
results.extend(data.get(key, []))
|
||||
cursor = data.get("cursor")
|
||||
if not cursor:
|
||||
break
|
||||
return results
|
||||
|
||||
def fetch_likes(client, uri, cursor=None):
|
||||
return client.app.bsky.feed.get_likes({"uri": uri, "cursor": cursor})
|
||||
|
||||
def fetch_reposts(client, uri, cursor=None):
|
||||
return client.app.bsky.feed.get_reposted_by({"uri": uri, "cursor": cursor})
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Load a Bluesky post recursively with interactions.")
|
||||
parser.add_argument("uri", help="Post URI (at://did:.../app.bsky.feed.post/...)")
|
||||
parser.add_argument("-o", "--output", default="post.json", help="Output file name")
|
||||
parser.add_argument("--likes", action="store_true", help="Include likes")
|
||||
parser.add_argument("--reposts", action="store_true", help="Include reposts")
|
||||
args = parser.parse_args()
|
||||
|
||||
client = connect()
|
||||
data = {"thread": fetch_thread(client, args.uri)}
|
||||
|
||||
if args.likes:
|
||||
data["likes"] = fetch_all_pages(fetch_likes, client, args.uri, "likes")
|
||||
if args.reposts:
|
||||
data["reposts"] = fetch_all_pages(fetch_reposts, client, args.uri, "repostedBy")
|
||||
|
||||
with open(args.output, "w") as f:
|
||||
json.dump(data, f, indent=2)
|
||||
|
||||
print(f"Saved to {args.output}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Executable
+147
@@ -0,0 +1,147 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import json
|
||||
from bscon import connect
|
||||
import requests
|
||||
import os
|
||||
import subprocess
|
||||
import json
|
||||
from atproto import Client
|
||||
from atproto_client import models
|
||||
|
||||
TMP_DIR="/tmp/profile_tmp"
|
||||
|
||||
def save_profile(profile, directory):
|
||||
avatar = requests.get(profile.avatar).content
|
||||
directory = directory + '/' + profile.handle
|
||||
subprocess.run(["mkdir", "-p", directory])
|
||||
image_file = directory + '/avatar.jpeg'
|
||||
with open(image_file, "wb") as f:
|
||||
f.write(avatar)
|
||||
description_file = directory + '/description'
|
||||
with open(description_file, "w") as f:
|
||||
f.write(str(profile.description))
|
||||
data_file = directory + '/metadata'
|
||||
with open(data_file, "w") as f:
|
||||
f.write('\n\ndid : ')
|
||||
f.write(str(profile.did))
|
||||
f.write('\n\nbanner : ')
|
||||
f.write(str(profile.banner))
|
||||
f.write("\n\nfollowers: ")
|
||||
f.write(str(profile.followers_count))
|
||||
f.write('\n\ndisplay_name : ')
|
||||
f.write(str(profile.display_name))
|
||||
f.write('\n\nfollowers_count : ')
|
||||
f.write(str(profile.followers_count))
|
||||
f.write('\n\nfollows_count : ')
|
||||
f.write(str(profile.follows_count))
|
||||
f.write('\n\npinned_post : ')
|
||||
f.write(str(profile.pinned_post))
|
||||
f.write('\n\nposts_count : ')
|
||||
f.write(str(profile.posts_count))
|
||||
metadata_file = directory + '/metadata'
|
||||
with open(metadata_file, "w") as f:
|
||||
f.write('\n\nassociated : ')
|
||||
f.write(str(profile.associated))
|
||||
f.write('\n\nconstruct : ')
|
||||
f.write(str(profile.construct))
|
||||
f.write('\n\ncopy : ')
|
||||
f.write(str(profile.copy))
|
||||
f.write('\n\ncreated_at : ')
|
||||
f.write(str(profile.created_at))
|
||||
f.write('\n\ndict : ')
|
||||
f.write(str(profile.dict))
|
||||
f.write('\n\nfrom_orm : ')
|
||||
f.write(str(profile.from_orm))
|
||||
f.write('\n\nindexed_at : ')
|
||||
f.write(str(profile.indexed_at))
|
||||
f.write('\n\njoined_via_starter_pack : ')
|
||||
f.write(str(profile.joined_via_starter_pack))
|
||||
f.write('\n\njson : ')
|
||||
f.write(str(profile.json))
|
||||
f.write('\n\nlabels : ')
|
||||
f.write(str(profile.labels))
|
||||
f.write('\n\nmodel_computed_fields : ')
|
||||
f.write(str(profile.model_computed_fields))
|
||||
f.write('\n\nmodel_config : ')
|
||||
f.write(str(profile.model_config))
|
||||
f.write('\n\nmodel_construct : ')
|
||||
f.write(str(profile.model_construct))
|
||||
f.write('\n\nmodel_copy : ')
|
||||
f.write(str(profile.model_copy))
|
||||
f.write('\n\nmodel_dump : ')
|
||||
f.write(str(profile.model_dump))
|
||||
f.write('\n\nmodel_dump_json : ')
|
||||
f.write(str(profile.model_dump_json))
|
||||
f.write('\n\nmodel_extra : ')
|
||||
f.write(str(profile.model_extra))
|
||||
f.write('\n\nmodel_fields : ')
|
||||
f.write(str(profile.model_fields))
|
||||
f.write('\n\nmodel_fields_set : ')
|
||||
f.write(str(profile.model_fields_set))
|
||||
f.write('\n\nmodel_json_schema : ')
|
||||
f.write(str(profile.model_json_schema))
|
||||
f.write('\n\nmodel_parametrized_name : ')
|
||||
f.write(str(profile.model_parametrized_name))
|
||||
f.write('\n\nmodel_post_init : ')
|
||||
f.write(str(profile.model_post_init))
|
||||
f.write('\n\nmodel_rebuild : ')
|
||||
f.write(str(profile.model_rebuild))
|
||||
f.write('\n\nmodel_validate : ')
|
||||
f.write(str(profile.model_validate))
|
||||
f.write('\n\nmodel_validate_json : ')
|
||||
f.write(str(profile.model_validate_json))
|
||||
f.write('\n\nmodel_validate_strings : ')
|
||||
f.write(str(profile.model_validate_strings))
|
||||
f.write('\n\nparse_file : ')
|
||||
f.write(str(profile.parse_file))
|
||||
f.write('\n\nparse_obj : ')
|
||||
f.write(str(profile.parse_obj))
|
||||
f.write('\n\nparse_raw : ')
|
||||
f.write(str(profile.parse_raw))
|
||||
f.write('\n\npronouns : ')
|
||||
f.write(str(profile.pronouns))
|
||||
f.write('\n\npy_type : ')
|
||||
f.write(str(profile.py_type))
|
||||
f.write('\n\nschema : ')
|
||||
f.write(str(profile.schema))
|
||||
f.write('\n\nschema_json : ')
|
||||
f.write(str(profile.schema_json))
|
||||
f.write('\n\nstatus : ')
|
||||
f.write(str(profile.status))
|
||||
f.write('\n\nupdate_forward_refs : ')
|
||||
f.write(str(profile.update_forward_refs))
|
||||
f.write('\n\nvalidate : ')
|
||||
f.write(str(profile.validate))
|
||||
f.write('\n\nverification : ')
|
||||
f.write(str(profile.verification))
|
||||
f.write('\n\nviewer : ')
|
||||
f.write(str(profile.viewer))
|
||||
f.write('\n\nwebsite : ')
|
||||
f.write(str(profile.website))
|
||||
|
||||
def get_profile(client, profile, tmp_dir=TMP_DIR, save=False):
|
||||
try:
|
||||
profile = client.app.bsky.actor.get_profile(params={"actor": profile})
|
||||
except:
|
||||
print("get_profile: check profile name")
|
||||
if save:
|
||||
save_profile(profile, tmp_dir)
|
||||
return profile
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Download Bluesky profile posts to JSON")
|
||||
parser.add_argument("handle", help="Bluesky handle (ex: ni-bot.bsky.social)")
|
||||
parser.add_argument("--folder", default=TMP_DIR)
|
||||
args = parser.parse_args()
|
||||
|
||||
client = connect()
|
||||
profile = get_profile(client, args.handle, args.folder)
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Executable
+28
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from atproto import Client
|
||||
from bscon import connect, DEFAULT_DIR, DEFAULT_DOMAIN
|
||||
import argparse
|
||||
|
||||
|
||||
def get_did(item, client=None):
|
||||
if not client:
|
||||
client = Client()
|
||||
return client.resolve_handle(item).did
|
||||
|
||||
def main():
|
||||
p = argparse.ArgumentParser(description="Connect to Bluesky and store session.")
|
||||
p.add_argument("diditem", nargs="?", help="Bluesky handle (username)")
|
||||
p.add_argument("--domain", default=DEFAULT_DOMAIN)
|
||||
p.add_argument("--tokendir", default=DEFAULT_DIR)
|
||||
p.add_argument("--passwd", "-p", help="passwd", default=None)
|
||||
p.add_argument("--user", "-u", help="for authentified request", default=None)
|
||||
args = p.parse_args()
|
||||
|
||||
client = None
|
||||
if args.user:
|
||||
client = connect(args.user, args.passwd)
|
||||
print(get_did(args.diditem, client))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+46
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env python3
|
||||
import json
|
||||
import argparse
|
||||
import html
|
||||
|
||||
def extract_post(post):
|
||||
"""Extract only the desired fields and return HTML string."""
|
||||
record = post.get("record", {})
|
||||
author = post.get("author", {})
|
||||
|
||||
text = html.escape(str(record.get("text") or ""))
|
||||
date = record.get("created_at") or post.get("created_at") or ""
|
||||
name = html.escape(str(author.get("display_name") or author.get("handle") or ""))
|
||||
avatar = author.get("avatar") or ""
|
||||
likes = post.get("like_count") or 0
|
||||
shares = post.get("repost_count") or 0
|
||||
|
||||
html_parts = ['<div class="post">']
|
||||
if avatar:
|
||||
html_parts.append(f' <img src="{avatar}" style="width:50px;height:50px">')
|
||||
html_parts.append(f' <span class="author">{name}</span>')
|
||||
html_parts.append(f' <span class="date">{date}</span>')
|
||||
html_parts.append(f' <p class="text">{text}</p>')
|
||||
html_parts.append(f' <span class="likes">Likes: {likes}</span>')
|
||||
html_parts.append(f' <span class="shares">Shares: {shares}</span>')
|
||||
html_parts.append('</div>\n')
|
||||
|
||||
return "\n".join(html_parts)
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Convert Bluesky JSON posts to minimal HTML")
|
||||
parser.add_argument("file", help="JSON input file")
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(args.file) as f:
|
||||
data = json.load(f)
|
||||
|
||||
thread = data.get("thread", [])
|
||||
for item in thread:
|
||||
post = item.get("thread", {}).get("post", {})
|
||||
if post:
|
||||
print(extract_post(post))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
ACCESS_JWT=$(cat /tmp/skY/ni-bot.bsky.social.token | jq -r .session_string | awk -F ':::' '{print $3}')
|
||||
curl -s "https://bsky.social/xrpc/app.bsky.actor.getProfile?actor=ni-bot.bsky.social" \
|
||||
-H "Authorization: Bearer $ACCESS_JWT" | jq -r .did
|
||||
|
||||
exit 0
|
||||
|
||||
Executable
+54
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
from atproto import Client
|
||||
|
||||
DEFAULT_DOMAIN = "bsky.social"
|
||||
DEFAULT_TOKEN_FILE = "/tmp/bs/last_token"
|
||||
|
||||
def load_token(token_file=DEFAULT_TOKEN_FILE):
|
||||
try:
|
||||
with open(token_file, "r") as f:
|
||||
return f.read().strip()
|
||||
except FileNotFoundError:
|
||||
return None
|
||||
|
||||
def fetch_post_uris(handle, token=None):
|
||||
client = Client()
|
||||
if token:
|
||||
client.login_with_access_token(token)
|
||||
|
||||
# Resolve handle to DID
|
||||
did = client.resolve_handle(handle).did
|
||||
|
||||
uris = []
|
||||
limit = 50
|
||||
cursor = None
|
||||
|
||||
while True:
|
||||
resp = client.app.bsky.feed.get_author_feed(
|
||||
actor=did, limit=limit, cursor=cursor
|
||||
)
|
||||
for post in resp.data.feed:
|
||||
uris.append(post.post.uri)
|
||||
|
||||
if not resp.data.cursor:
|
||||
break
|
||||
cursor = resp.data.cursor
|
||||
|
||||
return uris
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Fetch all post URIs of a Bluesky profile")
|
||||
parser.add_argument("handle", help="Bluesky handle (ex: alice.bsky.social)")
|
||||
parser.add_argument("--token-file", default=DEFAULT_TOKEN_FILE, help="File storing access token")
|
||||
args = parser.parse_args()
|
||||
|
||||
token = load_token(args.token_file)
|
||||
uris = fetch_post_uris(args.handle, token)
|
||||
|
||||
for uri in uris:
|
||||
print(uri)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from bscon import DEFAULT_DOMAIN, DEFAULT_DIR, connect
|
||||
import argparse
|
||||
|
||||
def main():
|
||||
p = argparse.ArgumentParser(description="Connect to Bluesky and store session.")
|
||||
p.add_argument("name", nargs="?", help="Bluesky handle (username)")
|
||||
p.add_argument("--domain", default=DEFAULT_DOMAIN)
|
||||
p.add_argument("--tokendir", default=DEFAULT_DIR)
|
||||
p.add_argument("--text", "-t", )
|
||||
p.add_argument("--passwd", "-p", help="passwd", default=None)
|
||||
args = p.parse_args()
|
||||
|
||||
client = connect(args.name, args.domain, args.passwd, args.tokendir)
|
||||
print(f"connected")
|
||||
client.send_post(text=args.text)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+91
@@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import json
|
||||
from html import escape
|
||||
from bscon import connect
|
||||
|
||||
def get_posts(client, handle, limit=100):
|
||||
"""Download all public posts of a profile with images."""
|
||||
posts = []
|
||||
cursor = None
|
||||
|
||||
while True:
|
||||
resp = client.app.bsky.feed.get_author_feed({
|
||||
"actor": handle,
|
||||
"limit": limit,
|
||||
"cursor": cursor,
|
||||
})
|
||||
|
||||
for item in resp.feed:
|
||||
post = item.post
|
||||
record = post.record
|
||||
|
||||
# Extract images if any
|
||||
images = []
|
||||
embed = getattr(record, "embed", None)
|
||||
if embed and hasattr(embed, "images"):
|
||||
images = [{"thumb": i.thumb, "full": i.fullsize} for i in embed.images]
|
||||
|
||||
posts.append({
|
||||
"uri": post.uri,
|
||||
"cid": post.cid,
|
||||
"createdAt": getattr(record, "createdAt", None) or getattr(record, "created_at", None),
|
||||
"text": getattr(record, "text", ""),
|
||||
"images": images
|
||||
})
|
||||
|
||||
cursor = getattr(resp, "cursor", None)
|
||||
if not cursor:
|
||||
break
|
||||
|
||||
return posts
|
||||
|
||||
def save_posts(posts, handle):
|
||||
"""Save posts to JSON."""
|
||||
out_file = f"{handle.replace('.', '_')}_posts.json"
|
||||
with open(out_file, "w", encoding="utf-8") as f:
|
||||
json.dump(posts, f, indent=2, ensure_ascii=False)
|
||||
print(f"Saved {len(posts)} posts to {out_file}")
|
||||
|
||||
def uri_to_url(uri):
|
||||
"""Convert at://did/... URIs to clickable Bluesky URLs."""
|
||||
parts = uri.split("/")
|
||||
if len(parts) >= 5 and parts[3] == "app.bsky.feed.post":
|
||||
did = parts[2]
|
||||
rkey = parts[4]
|
||||
return f"https://bsky.app/profile/{did}/post/{rkey}"
|
||||
return uri
|
||||
|
||||
def posts_to_html(posts, out_html):
|
||||
"""Generate HTML with text and image thumbnails."""
|
||||
with open(out_html, "w", encoding="utf-8") as f:
|
||||
f.write("<html><body>\n")
|
||||
for post in posts:
|
||||
text = escape(post.get("text", ""))
|
||||
url = uri_to_url(post.get("uri", ""))
|
||||
imgs_html = "".join(
|
||||
f'<a href="{escape(img["full"])}"><img src="{escape(img["thumb"])}" '
|
||||
f'style="width:120px;height:auto;margin:2px;"></a>'
|
||||
for img in post.get("images", [])
|
||||
)
|
||||
f.write(f"<div style='margin-bottom:20px;'><p>{text}</p>{imgs_html}<br>"
|
||||
f"<a href='{url}'>View post</a></div>\n")
|
||||
f.write("</body></html>\n")
|
||||
print(f"HTML saved to {out_html}")
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Download Bluesky profile posts and generate HTML.")
|
||||
parser.add_argument("handle", help="Bluesky handle (example: alice.bsky.social)")
|
||||
parser.add_argument("--limit", type=int, default=100, help="Posts per request")
|
||||
args = parser.parse_args()
|
||||
|
||||
client = connect()
|
||||
posts = get_posts(client, args.handle, args.limit)
|
||||
save_posts(posts, args.handle)
|
||||
|
||||
out_html = f"{args.handle.replace('.', '_')}_posts.html"
|
||||
posts_to_html(posts, out_html)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
|
||||
jq '.thread[] | {author: .thread.post.author.handle, text: .thread.post.record.text}' $1
|
||||
Executable
+27
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
import json
|
||||
|
||||
def generate_html(posts_file, out_file="profile.html"):
|
||||
with open(posts_file, "r", encoding="utf-8") as f:
|
||||
posts = json.load(f)
|
||||
|
||||
html = ['<html><body>']
|
||||
for post in posts:
|
||||
html.append(f"<p>{post.get('text','')}</p>")
|
||||
|
||||
# Handle embedded images if present
|
||||
media = post.get("media", [])
|
||||
for m in media:
|
||||
# Convert CID to IPFS URL
|
||||
cid = m.get("cid")
|
||||
if cid:
|
||||
url = f"https://bsky.social/ipfs/{cid}"
|
||||
html.append(f'<img src="{url}" style="width:100px;height:100px;">')
|
||||
|
||||
html.append('</body></html>')
|
||||
|
||||
with open(out_file, "w", encoding="utf-8") as f:
|
||||
f.write("\n".join(html))
|
||||
|
||||
generate_html("post.json")
|
||||
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
if [ "$#" -lt 1 ] || [ "$#" -gt 3 ]; then
|
||||
echo "Usage: $0 arg1 [arg2] [arg3]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# interactive session check
|
||||
if [ -t 0 ]; then
|
||||
echo -n "Delete existing output files? [y/N]: "
|
||||
read ans
|
||||
case "$ans" in
|
||||
y|Y) rm -f *.school ;;
|
||||
*) echo "Aborted"; exit 0 ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# process input file
|
||||
while IFS= read -r line; do
|
||||
new_f="${line%.*}.school"
|
||||
f > "$new_f"
|
||||
done < "$FILE"
|
||||
|
||||
exit 0
|
||||
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env python3
|
||||
import re
|
||||
import sys
|
||||
from bsgetdid import get_did
|
||||
|
||||
def get_post_uri(url):
|
||||
m = re.search(r'https://bsky\.app/profile/([^/]+)/post/([a-z0-9]+)', url)
|
||||
if not m:
|
||||
sys.exit("Invalid Bluesky post URL")
|
||||
handle, rkey = m.groups()
|
||||
did = get_did(handle)
|
||||
return f"at://{did}/app.bsky.feed.post/{rkey}"
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != 2:
|
||||
print(f"Usage: {sys.argv[0]} <bsky_post_url>")
|
||||
sys.exit(1)
|
||||
print(get_post_uri(sys.argv[1]))
|
||||
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
if [ "$#" -ne 1 ] ; then
|
||||
echo "Usage: $0 name"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
bluetoothctl devices | grep "$1" | awk '{print $2}'
|
||||
|
||||
exit 0
|
||||
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
echo """
|
||||
bluetoothctl
|
||||
power on
|
||||
agent on
|
||||
default-agent
|
||||
scan on
|
||||
|
||||
pair 22:22:D6:8F:28:2B
|
||||
trust 22:22:D6:8F:28:2B
|
||||
connect 22:22:D6:8F:28:2B
|
||||
|
||||
blueman-sendto 22:22:D6:8F:28:2B yourfile.jpg
|
||||
|
||||
bluetoothctl
|
||||
remove 22:22:D6:8F:28:2B
|
||||
|
||||
"""
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
if [ "$#" -ne 1 ] ; then
|
||||
echo "Usage: $0 name"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
bluetoothctl connect $(bt-addr $1)
|
||||
|
||||
exit 0
|
||||
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
if [ "$#" -ne 1 ] ; then
|
||||
echo "Usage: $0 arg1"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cat $(which $1)
|
||||
|
||||
exit 0
|
||||
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
mkdir certs
|
||||
cd certs
|
||||
|
||||
openssl genrsa -out ca.key 4096
|
||||
|
||||
openssl req -x509 -new -sha256 -days 356000 -nodes -subj "/CN=LibreWolf CA/" -key ca.key -out ca.crt
|
||||
|
||||
openssl genrsa -out librewolf.key 2048
|
||||
|
||||
openssl req -new -key librewolf.key -out librewolf.csr -subj '/CN=librewolf.local'
|
||||
|
||||
echo "subjectAltName = DNS:librewolf.local,IP:127.0.0.1" > librewolf.ext
|
||||
|
||||
openssl x509 -req -in librewolf.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out librewolf.crt -days 365 -sha256 -extfile librewolf.ext
|
||||
|
||||
cd -
|
||||
cp -r certs /srv/appdata/librewolf/config/
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
NAME="${1:-db}"
|
||||
SUBJ="${2:-myDB}"
|
||||
TIME="${3:-356000}"
|
||||
KEY="${4:-$NAME.key}"
|
||||
CERT="${5:-$NAME.crt}"
|
||||
|
||||
echo run:
|
||||
echo "openssl req -new -x509 -newkey rsa:4096 -sha256 -days $TIME -nodes \
|
||||
-subj /CN=$SUBJ/ -keyout $KEY -out $CERT"
|
||||
openssl req -new -x509 -newkey rsa:4096 -sha256 -days $TIME -nodes \
|
||||
-subj "/CN=$SUBJ/" -keyout $KEY -out $CERT
|
||||
|
||||
echo $0 name subj days
|
||||
Executable
+30
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
if [ "$#" -ne 1 ] ; then
|
||||
echo "Usage: $0 .iso"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ISO="$1"
|
||||
WORKDIR=iso_edit
|
||||
NEWISO=custom.iso
|
||||
|
||||
mkdir -p "$WORKDIR"
|
||||
mount -o loop "$ISO" "$WORKDIR"
|
||||
|
||||
echo "[*] Enter chroot (bind mounts first)"
|
||||
mount --bind /dev "$WORKDIR/dev"
|
||||
mount --bind /sys "$WORKDIR/sys"
|
||||
mount --bind /proc "$WORKDIR/proc"
|
||||
chroot "$WORKDIR" /bin/bash
|
||||
|
||||
echo """
|
||||
run:
|
||||
post-chroot-iso
|
||||
"""
|
||||
# sudo umount "$WORKDIR"/{proc,sys,dev}
|
||||
# genisoimage -o "$NEWISO" -V "CUSTOM" -R -J "$WORKDIR"
|
||||
# note : from cdrkit package
|
||||
|
||||
exit 0
|
||||
|
||||
Executable
+14
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
ARCHIVE_DIR=${2:"/tmp/clean-dict.del"}
|
||||
mkdir -p $ARCHIVE_DIR
|
||||
|
||||
if [ "$#" -lt 1 ] ; then
|
||||
find . -type f -size -"${SIZE_MIN}c" -exec mv {} $ARCHIVE_DIR \;
|
||||
exit 1
|
||||
elif
|
||||
find . -type f -size -"${SIZE_MIN}c" -delete
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
clone ()
|
||||
{
|
||||
if [ $# -ne "1" ]; then
|
||||
PROFIL_NAME="$1";
|
||||
PROJECT_NAME="$2";
|
||||
git clone --recurse-submodules git@github.com:$PROFIL_NAME/$PROJECT_NAME.git;
|
||||
else
|
||||
PROJECT_NAME="$1";
|
||||
git clone --recurse-submodules git@github.com:pain-pin/$PROJECT_NAME.git;
|
||||
fi
|
||||
}
|
||||
clone "$@"
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
commit_if_modified ()
|
||||
{
|
||||
local F_NAME=$1;
|
||||
local DEL=$2;
|
||||
#git pull;
|
||||
vim + $F_NAME;
|
||||
git add $F_NAME;
|
||||
git commit
|
||||
if [ $? -eq 0 ] ; then
|
||||
echo -n "[no modifications]";
|
||||
if [ -n "$DEL" ]; then
|
||||
rm $F_NAME;
|
||||
echo -n " -> deleted";
|
||||
return 1;
|
||||
fi;
|
||||
fi;
|
||||
return 0
|
||||
}
|
||||
commit_if_modified "$@"
|
||||
Executable
+14
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
if [ "$#" -lt 1 ] ; then
|
||||
echo "Usage: $0 USSID"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
iwctl station wlan0 scan
|
||||
iwctl station wlan0 get-networks
|
||||
echo
|
||||
iwctl station wlan0 connect $1
|
||||
|
||||
exit 0
|
||||
|
||||
Executable
+49
@@ -0,0 +1,49 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
ARCH=amd64
|
||||
BASE_URL=https://cdimage.debian.org/debian-cd/current/$ARCH/iso-cd
|
||||
|
||||
# Détection du dernier netinst ISO
|
||||
ISO=$(wget -qO- "$BASE_URL/" | grep -oP "debian-[0-9.]+-${ARCH}-netinst\.iso" | sort -V | tail -n1)
|
||||
SUMS=SHA256SUMS
|
||||
SIG=SHA256SUMS.sign
|
||||
|
||||
echo "Latest ISO found: $ISO"
|
||||
|
||||
# Téléchargement ISO seulement si absent
|
||||
if [ ! -f "$ISO" ]; then
|
||||
wget -N "$BASE_URL/$ISO"
|
||||
else
|
||||
echo "$ISO already exists, skipping download."
|
||||
fi
|
||||
|
||||
# Téléchargement des fichiers de contrôle
|
||||
wget -N "$BASE_URL/$SUMS"
|
||||
wget -N "$BASE_URL/$SIG"
|
||||
|
||||
# Import des clés Debian Archive (utile pour cohérence générale)
|
||||
KEYRING_PKG=debian-archive-keyring_2025.1_all.deb
|
||||
if [ ! -f "$KEYRING_PKG" ]; then
|
||||
wget "https://ftp.debian.org/debian/pool/main/d/debian-archive-keyring/$KEYRING_PKG"
|
||||
fi
|
||||
TMPDIR=$(mktemp -d)
|
||||
ar x "$KEYRING_PKG" --output="$TMPDIR"
|
||||
tar -xf "$TMPDIR"/data.tar.* -C "$TMPDIR"
|
||||
gpg --import "$TMPDIR/usr/share/keyrings/debian-archive-keyring.gpg" || true
|
||||
rm -rf "$TMPDIR"
|
||||
|
||||
# Import des clés Debian CD signing (officielles sur debian.org/CD/verify)
|
||||
gpg --keyserver hkps://keyring.debian.org --recv-keys \
|
||||
DF9B9C49EAA9298432589D76DA87E80D6294BE9B \
|
||||
64E6EA7D \
|
||||
E0B11894F66AEC98 || true
|
||||
|
||||
# Vérification signature
|
||||
echo "Verifying signature..."
|
||||
gpg --verify "$SIG" "$SUMS"
|
||||
|
||||
# Vérification ciblée uniquement sur l’ISO téléchargé
|
||||
echo "Verifying checksum for $ISO..."
|
||||
grep "$ISO" "$SUMS" | sha256sum -c -
|
||||
|
||||
Executable
+111
@@ -0,0 +1,111 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
import argparse
|
||||
|
||||
# ---- ensure spacy and model ----
|
||||
try:
|
||||
import spacy
|
||||
except ImportError:
|
||||
subprocess.check_call([sys.executable, "-m", "pip", "install", "spacy"])
|
||||
import spacy
|
||||
|
||||
def load_model(name="fr_core_news_sm"):
|
||||
try:
|
||||
return spacy.load(name)
|
||||
except OSError:
|
||||
subprocess.check_call([sys.executable, "-m", "spacy", "download", name])
|
||||
return spacy.load(name)
|
||||
|
||||
# ---- args ----
|
||||
argparser = argparse.ArgumentParser()
|
||||
argparser.add_argument("-v","--vault", default=".", help="Path to Obsidian vault")
|
||||
argparser.add_argument("-d","--dict", default="Dictionary", help="Name of the dictionary directory")
|
||||
args = argparser.parse_args()
|
||||
|
||||
# ---- config ----
|
||||
VAULT_DIR = Path(args.vault)
|
||||
DICT_DIR = VAULT_DIR / args.dict
|
||||
WORD_REGEX = re.compile(r"\b[a-zA-Z]{3,}\b")
|
||||
|
||||
nlp = load_model("fr_core_news_sm")
|
||||
|
||||
# ---- prep ----
|
||||
DICT_DIR.mkdir(exist_ok=True)
|
||||
lemma_map = defaultdict(lambda: {"forms": set(), "files": set()})
|
||||
|
||||
# ---- scan ----
|
||||
|
||||
nlp.Defaults.stop_words.add(os.path.basename(os.getcwd()))
|
||||
nlp.Defaults.stop_words.add("author")
|
||||
nlp.Defaults.stop_words.add("jpeg")
|
||||
nlp.Defaults.stop_words.add("jpg")
|
||||
nlp.Defaults.stop_words.add("post")
|
||||
nlp.Defaults.stop_words.add("like")
|
||||
nlp.Defaults.stop_words.add("likes")
|
||||
nlp.Defaults.stop_words.add("repost")
|
||||
nlp.Defaults.stop_words.add("avatar")
|
||||
nlp.Defaults.stop_words.add("bsky")
|
||||
nlp.Defaults.stop_words.add("media")
|
||||
nlp.Defaults.stop_words.add("thumnail")
|
||||
nlp.Defaults.stop_words.add("http")
|
||||
nlp.Defaults.stop_words.add("https")
|
||||
nlp.Defaults.stop_words.add("com")
|
||||
nlp.Defaults.stop_words.add("followers")
|
||||
nlp.Defaults.stop_words.add("following")
|
||||
nlp.Defaults.stop_words.add("unknown")
|
||||
nlp.Defaults.stop_words.add("date")
|
||||
nlp.Defaults.stop_words.add("social")
|
||||
nlp.Defaults.stop_words.add("thumbnail")
|
||||
nlp.Defaults.stop_words.add("replier")
|
||||
nlp.Defaults.stop_words.add("replie")
|
||||
nlp.Defaults.stop_words.add("for")
|
||||
nlp.Defaults.stop_words.add("you")
|
||||
nlp.Defaults.stop_words.add("from")
|
||||
nlp.Defaults.stop_words.add("to")
|
||||
nlp.Defaults.stop_words.add("script")
|
||||
nlp.Defaults.stop_words.add("grep")
|
||||
nlp.Defaults.stop_words.add("localhost")
|
||||
nlp.Defaults.stop_words.add("sudo")
|
||||
nlp.Defaults.stop_words.add("not")
|
||||
|
||||
for md_file in VAULT_DIR.rglob("*.md"):
|
||||
if "Dictionary" in md_file.parts:
|
||||
continue
|
||||
text = md_file.read_text(encoding="utf-8", errors="ignore")
|
||||
words = WORD_REGEX.findall(text.lower())
|
||||
doc = nlp(" ".join(words))
|
||||
for token in doc:
|
||||
if token.is_stop:
|
||||
continue
|
||||
lemma = token.lemma_
|
||||
if lemma.isalpha() and lemma not in nlp.Defaults.stop_words:
|
||||
lemma_map[lemma]["forms"].add(token.text)
|
||||
lemma_map[lemma]["files"].add(md_file)
|
||||
|
||||
print(f"Found {len(lemma_map)} lemmas.")
|
||||
|
||||
# ---- write ----
|
||||
for lemma, data in lemma_map.items():
|
||||
if len(data["files"]) < 2:
|
||||
continue
|
||||
file_path = DICT_DIR / f"{lemma}.md"
|
||||
with open(file_path, "w", encoding="utf-8") as f:
|
||||
f.write(f"# {lemma}\n\n---\n")
|
||||
f.write(f"lemma: {lemma}\n")
|
||||
f.write(f"forms: [{', '.join(sorted(data['forms']))}]\n---\n\n")
|
||||
f.write("## Forms\n")
|
||||
for form in sorted(data["forms"]):
|
||||
f.write(f"- {form}\n")
|
||||
f.write("\n## Found in\n")
|
||||
for md in sorted(data["files"]):
|
||||
rel_path = md.relative_to(VAULT_DIR)
|
||||
f.write(f"- [[{rel_path}]]\n")
|
||||
|
||||
|
||||
print(f"Dictionary generated in {DICT_DIR}")
|
||||
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
expresso ()
|
||||
{
|
||||
DIR="$HOME/perso/thm/interets/jeux/poker";
|
||||
HISTORY="expresso_history.md";
|
||||
SCRIPT=expresso_stat.sh;
|
||||
TAIL=${1:-1000};
|
||||
vim + $DIR/$HISTORY;
|
||||
bash $DIR/$SCRIPT $DIR/$HISTORY $TAIL
|
||||
}
|
||||
expresso "$@"
|
||||
Executable
+93
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
FILE=$1
|
||||
|
||||
if [ -z "$FILE" ]; then
|
||||
echo "Usage: $0 FILE"
|
||||
exit 1
|
||||
fi
|
||||
sed "s/[a-zA-Z€]//g" "$FILE" | sed "s/-/0/g" | sed "s/,/./g" | gawk '
|
||||
{
|
||||
if (NF < 7) next
|
||||
|
||||
BUY_IN = $3 + 0.0
|
||||
WON = $5 + 0.0
|
||||
PRIZE = $7 + 0.0
|
||||
|
||||
key = BUY_IN
|
||||
|
||||
total_cost[key] += BUY_IN
|
||||
total_won[key] += WON
|
||||
total_prize[key] += PRIZE
|
||||
nb_game[key]++
|
||||
hot_game = 0
|
||||
|
||||
if (PRIZE >= BUY_IN * 3) {
|
||||
hot_game = 1
|
||||
total_hotgame[key]++
|
||||
}
|
||||
if ($4 == 1) {
|
||||
game_won[key]++
|
||||
if (hot_game) hot_game_won[key]++
|
||||
}
|
||||
}
|
||||
|
||||
END {
|
||||
printf "%10s %6s %6s %9s %9s %9s %9s %9s %8s %8s\n", \
|
||||
"BUY_IN", "Games", "Wins", "WinRate", "HotWin%", "RealRate", "Spent", "Won", "Net", "Marge"
|
||||
for (key in nb_game) {
|
||||
if (total_cost[key] == 0) continue
|
||||
|
||||
ratio = (game_won[key] / nb_game[key]) * 300
|
||||
real_winrate = (total_won[key] / total_cost[key]) * 100
|
||||
hotrate = (total_hotgame[key] > 0) ? (300 * hot_game_won[key] / total_hotgame[key]) : 0
|
||||
net = total_won[key] - total_cost[key]
|
||||
hotness = (total_prize[key] / total_cost[key]) * 100 / 3
|
||||
|
||||
printf "%10.2f %6d %6d %8.2f%% %8.2f%% %8.2f%% %8.2f€ %8.2f€ %7.2f€ %7.2f\n", \
|
||||
key, nb_game[key], game_won[key], ratio, hotrate, real_winrate, \
|
||||
total_cost[key], total_won[key], net, hotness
|
||||
}
|
||||
}'
|
||||
|
||||
|
||||
#sed "s/[a-zA-Z€]//g" "$FILE" | sed "s/-/0/g" | sed "s/,/./g" | gawk '
|
||||
#{
|
||||
# if (NF < 7) next
|
||||
#
|
||||
# BUY_IN = $3 + 0.0
|
||||
# WON = $5 + 0.0
|
||||
# PRIZE = $7 + 0.0
|
||||
#
|
||||
# TOTAL_COST += BUY_IN
|
||||
# TOTAL_WON += WON
|
||||
# TOTAL_PRIZE += PRIZE
|
||||
# NB_GAME++
|
||||
# HOT_GAME = 0
|
||||
#
|
||||
# if ($PRIZE >= $BUY_IN) HOT_GAME = 1
|
||||
# if ($PRIZE >= $BUY_IN) TOTAL_HOTGAME++
|
||||
# if ($4 == 1) GAME_WON++
|
||||
# if (HOT_GAME && $4 == 1) HOT_GAME_WON++
|
||||
#}
|
||||
#END {
|
||||
# if (NB_GAME == 0 || TOTAL_COST == 0) {
|
||||
# print "No valid data."
|
||||
# exit
|
||||
# }
|
||||
# RATIO = (GAME_WON / NB_GAME) * 300
|
||||
# REAL_WINRATE = (TOTAL_WON / TOTAL_COST) * 100
|
||||
# NET = TOTAL_WON - TOTAL_COST
|
||||
# HOTNESS = (TOTAL_PRIZE / TOTAL_COST) * 100 / 3
|
||||
#
|
||||
# printf "Games: %d\n", NB_GAME
|
||||
# printf "Wins: %d\n", GAME_WON
|
||||
# printf "WinRate: %.2f%%\n", RATIO
|
||||
# printf "hot games WinRate: %.2f%%\n", 300 *HOT_GAME_WON / TOTAL_HOTGAME
|
||||
# printf "Real win rate: %.2f%%\n", REAL_WINRATE
|
||||
# printf "Spent: %.2f€\n", TOTAL_COST
|
||||
# printf "Won: %.2f€\n", TOTAL_WON
|
||||
# printf "Net: %.2f€\n", NET
|
||||
# printf "Marge site: %.2f\n", HOTNESS
|
||||
#}'
|
||||
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
if [ "$#" -ne 1 ] ; then
|
||||
echo "Usage: $0 keywd"
|
||||
fi
|
||||
|
||||
find -L $BIN_DIR -type f -iregex ".*${1}[^/]*" | awk -F'/' '{print $NF}'
|
||||
find -L $SBIN_DIR -type f -iregex ".*${1}[^/]*" | awk -F'/' '{print $NF}'
|
||||
|
||||
exit 0
|
||||
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
if [ "$#" -lt 1 ] ; then
|
||||
echo "Usage: $0 arg1 [arg2] [arg3]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
# Directory to search (default is current directory)
|
||||
search_dir="${1:-.}"
|
||||
|
||||
# Find all files and their inode numbers, excluding directories and other types
|
||||
find "$search_dir" -type f -exec stat --format="%i %n" {} \; | sort -n | uniq -d -w 10 | while read inode file; do
|
||||
echo "Inode: $inode"
|
||||
find "$search_dir" -type f -inum "$inode" -exec ls -l {} \;
|
||||
echo "-------------------------------"
|
||||
done
|
||||
|
||||
|
||||
exit 0
|
||||
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
gcl ()
|
||||
{
|
||||
git clone $1 $2
|
||||
}
|
||||
gcl "$@"
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
git_list_heavy ()
|
||||
{
|
||||
for B in $(git_list_heavy_commits | cut -d' ' -f1);
|
||||
do
|
||||
git rev-list --all | while read commit; do
|
||||
git ls-tree -rl $commit;
|
||||
done | grep --color=auto $B;
|
||||
done
|
||||
}
|
||||
git_list_heavy "$@"
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
git_list_heavy_commits ()
|
||||
{
|
||||
git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n -r | head -n 20
|
||||
}
|
||||
git_list_heavy_commits "$@"
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
git_rm_repo ()
|
||||
{
|
||||
KEYWORD=$1;
|
||||
git filter-repo --path-glob "$KEYWORD" --invert-paths
|
||||
}
|
||||
git_rm_repo "$@"
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
gitadd ()
|
||||
{
|
||||
make fclean;
|
||||
git add .
|
||||
}
|
||||
gitadd "$@"
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
gitaddcommit ()
|
||||
{
|
||||
gitadd;
|
||||
if [ -n "$1" ]; then
|
||||
git commit -m "$1";
|
||||
else
|
||||
git commit;
|
||||
fi
|
||||
}
|
||||
gitaddcommit "$@"
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
cat gitea_deploy.sh
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Variables
|
||||
GITEA_VERSION=1.21.11
|
||||
USER_NAME=gitea
|
||||
GITEA_PORT=9090
|
||||
DATA_DIR=/opt/gitea
|
||||
|
||||
# Installer Docker si nécessaire
|
||||
if ! command -v docker >/dev/null; then
|
||||
apt update
|
||||
apt install -y docker.io
|
||||
systemctl enable docker
|
||||
systemctl start docker
|
||||
fi
|
||||
|
||||
# Créer dossier de données
|
||||
mkdir -p ${DATA_DIR}/{data,config}
|
||||
|
||||
# Lancer Gitea (http://<ip>:9090)
|
||||
docker run -d --name gitea \
|
||||
-p ${GITEA_PORT}:3000 \
|
||||
-p 2222:22 \
|
||||
-v ${DATA_DIR}/data:/data \
|
||||
gitea/gitea:${GITEA_VERSION}
|
||||
|
||||
echo "----------------------------------------"
|
||||
echo "✅ Gitea lancé sur http://<IP>:${GITEA_PORT}"
|
||||
echo "➡️ Identifiants à créer via l'interface web"
|
||||
echo "➡️ Pour SSH : port 2222 (externe), clé à ajouter via l'UI"
|
||||
echo "----------------------------------------"
|
||||
Executable
+12
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
if [ "$#" -ne 0 ]; then
|
||||
echo "Usage: $0"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
vim + .gitignore
|
||||
gitaddcommit .gitignore
|
||||
|
||||
exit 0
|
||||
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
gitlog ()
|
||||
{
|
||||
git log --oneline --decorate --graph --all
|
||||
}
|
||||
gitlog "$@"
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
gitmain ()
|
||||
{
|
||||
if [ -z "$1" ]; then
|
||||
git checkout main;
|
||||
git reset --hard "$1";
|
||||
git push origin main --force;
|
||||
fi
|
||||
}
|
||||
gitmain "$@"
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
gitotal ()
|
||||
{
|
||||
gitaddcommit $@;
|
||||
git pull;
|
||||
if [ -n "$?" ]; then
|
||||
git push origin HEAD;
|
||||
fi
|
||||
}
|
||||
gitotal "$@"
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
# save_redundant.sh
|
||||
# Sauvegarde/redondance GNUnet : 3 duplicatas
|
||||
|
||||
# fichier source et clé de publication
|
||||
SRC="$1"
|
||||
if [ -z "$SRC" ]; then
|
||||
echo "Usage: $0 <file>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Tag public de référence
|
||||
KEYWORD="backup:$(basename "$SRC")"
|
||||
|
||||
# Publier le fichier (ajout au réseau GNUnet FS)
|
||||
gnunet-publish -n -k "$KEYWORD" -r 3 "$SRC"
|
||||
# -n : anonyme
|
||||
# -k : mot-clé (pour retrouver)
|
||||
# -r : redondance (nb de duplicatas)
|
||||
# -p : chemin du fichier
|
||||
|
||||
# Vérifie que la donnée est bien publiée
|
||||
echo "Recherche des duplicatas GNUnet pour $KEYWORD..."
|
||||
gnunet-search "$KEYWORD"
|
||||
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
#if [ "$#" -lt 1 ] || [ "$#" -gt 3 ]; then
|
||||
# echo "Usage: $0 arg1 [arg2] [arg3]"
|
||||
# exit 1
|
||||
#fi
|
||||
|
||||
echo "Sur pixel 9 taper 7 fois sur le numero de build pour entrer en mode developpeur"
|
||||
|
||||
#pacman -Sy android-udev
|
||||
#pacman -S android-tools
|
||||
|
||||
#apt install android-sdk-platform-tools-common
|
||||
#apt install android-sdk-platform-tools-common
|
||||
|
||||
#systemctl stop fwupd.service
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
grepip ()
|
||||
{
|
||||
grep --color=auto -Eo $IP_REG $@ | sortu
|
||||
}
|
||||
grepip "$@"
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
grep -Eo $IP_REG $@ | sortu
|
||||
|
||||
exit 0
|
||||
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
if [ "$#" -lt 1 ] || [ "$#" -gt 3 ]; then
|
||||
echo "Usage: $0 key"
|
||||
echo "Usage: grep values after key=value"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
awk -v key="$1" '{
|
||||
for (i = 1; i <= NF; i++)
|
||||
if ($i ~ "^"key"=") {
|
||||
split($i, a, "=")
|
||||
print a[2]
|
||||
}
|
||||
}' # | cut -d\ -f 1
|
||||
|
||||
|
||||
exit 0
|
||||
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
header_awk ()
|
||||
{
|
||||
grep --color=auto -RE $CFUNCTION src | cut -d: -f2 | sed s/\$/';'/g
|
||||
}
|
||||
header_awk "$@"
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
header_journal ()
|
||||
{
|
||||
F_NAME=$1;
|
||||
. refresh_time
|
||||
echo "$DATE" >> $F_NAME;
|
||||
echo "$TIME" >> $F_NAME;
|
||||
echo "$USER" >> $F_NAME;
|
||||
echo "$HOST" >> $F_NAME;
|
||||
echo >> $F_NAME;
|
||||
echo "###############################################" >> $F_NAME;
|
||||
echo >> $F_NAME;
|
||||
echo "$F_NAME" >> $F_NAME;
|
||||
echo >> $F_NAME
|
||||
}
|
||||
header_journal "$@"
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
history_full ()
|
||||
{
|
||||
HIST_FILE=~/.history;
|
||||
while read LINE; do
|
||||
if [ -n "$(echo "$LINE" | grep '^#')" ]; then
|
||||
date -d "$(echo $LINE | sed 's/\#/@/g')";
|
||||
else
|
||||
echo "$LINE";
|
||||
fi;
|
||||
done < $HIST_FILE
|
||||
}
|
||||
history_full "$@"
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
ipinfo ()
|
||||
{
|
||||
curl https://ipinfo.io/$1
|
||||
}
|
||||
ipinfo "$@"
|
||||
Executable
+44
@@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
journal ()
|
||||
{
|
||||
. refresh_time;
|
||||
DIR_ORIGINAL=$PWD;
|
||||
DIR="$HOME/journal/";
|
||||
DATE_DIR="$YEAR/$MONTH/$DAY";
|
||||
if [ "$#" -eq 0 ]; then
|
||||
echo "Usage: $0 [ subfolder ] < file >";
|
||||
echo "default path is $DIR";
|
||||
echo "default file name is $F_NAME";
|
||||
return 1;
|
||||
fi;
|
||||
if [ "$#" -eq 1 ]; then
|
||||
LN_DIR="fouretout";
|
||||
F_NAME=$1;
|
||||
fi;
|
||||
if [ "$#" -eq 2 ]; then
|
||||
LN_DIR="$1";
|
||||
F_NAME=$2;
|
||||
else
|
||||
echo check args
|
||||
return 1;
|
||||
fi;
|
||||
mkdir -p $DIR/$HOST
|
||||
F_NAME+=".md";
|
||||
cd $DIR;
|
||||
PATH_="${DATE_DIR}/${LN_DIR}";
|
||||
mkdir -p "$PATH_";
|
||||
FILE="${PATH_}/${F_NAME}";
|
||||
header_journal $FILE;
|
||||
echo "header done"
|
||||
if commit_if_modified $FILE; then
|
||||
mkdir -p "$DIR/$HOST/$LN_DIR";
|
||||
ln -P "$FILE" "$DIR/$HOST/$LN_DIR";
|
||||
git add . ;
|
||||
git commit -m " -> linked";
|
||||
else
|
||||
rm $FILE;
|
||||
rmdir -p "${PATH_}";
|
||||
fi;
|
||||
cd $DIR_ORIGINAL
|
||||
}
|
||||
journal "$@"
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
#!/bin/bash
|
||||
journal-perso ()
|
||||
{
|
||||
. . refresh_time;
|
||||
DIR_ORIGINAL=$PWD;
|
||||
DIR=$PERSO_DIR;
|
||||
DATE_DIR="$YEAR/$MONTH/$DAY";
|
||||
if [ "$#" -eq 0 ]; then
|
||||
echo "Usage: $0 [ subfolder ] < file >";
|
||||
echo "default path is $DIR";
|
||||
echo "default file name is $F_NAME";
|
||||
return 1;
|
||||
fi;
|
||||
if [ "$#" -eq 1 ]; then
|
||||
LN_DIR="fouretout";
|
||||
F_NAME=$1;
|
||||
fi;
|
||||
if [ "$#" -eq 2 ]; then
|
||||
LN_DIR="$1";
|
||||
F_NAME=$2;
|
||||
else
|
||||
return 1;
|
||||
fi;
|
||||
F_NAME+=".md";
|
||||
cd $DIR;
|
||||
PATH_="${DATE_DIR}/${LN_DIR}";
|
||||
mkdir -p "$PATH_";
|
||||
FILE="${PATH_}/${F_NAME}";
|
||||
header_journal $FILE;
|
||||
if commit_if_modified $FILE; then
|
||||
mkdir -p "$DIR/$LN_DIR";
|
||||
ln -P "$FILE" "$DIR/$LN_DIR/";
|
||||
git add "$DIR/$LN_DIR/$FILE";
|
||||
git commit -m "-> $FILE linked";
|
||||
else
|
||||
rm $FILE;
|
||||
rmdir -p "${PATH_}";
|
||||
fi;
|
||||
cd $DIR_ORIGINAL
|
||||
}
|
||||
|
||||
journal-perso "$@"
|
||||
Executable
+37
@@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
|
||||
REPO_PATH="$1"
|
||||
HOST_ALIAS=${2:-""} # optional, defaults to domain in remote URL
|
||||
PROFILE_ALIAS=${3:-"$USER"}
|
||||
PASSPHRASE=${4:-""}
|
||||
|
||||
[ -z "$REPO_PATH" ] && { echo "Usage: $0 /path/to/repo"; exit 1; }
|
||||
|
||||
cd "$REPO_PATH" || exit 1
|
||||
|
||||
KEY_PATH="$HOME/.ssh/$(basename "$REPO_PATH")_id_ed25519"
|
||||
ssh-keygen -t ed25519 -f "$KEY_PATH" -C "$(basename "$REPO_PATH")" -N "$PASSPHRASE"
|
||||
|
||||
eval "$(ssh-agent -s)"
|
||||
ssh-add "$KEY_PATH"
|
||||
|
||||
REMOTE_URL=$(git remote get-url origin)
|
||||
|
||||
# Extract domain from remote URL
|
||||
if [[ "$REMOTE_URL" =~ ([^/:]+(:[0-9]+)?)[/:].* ]]; then
|
||||
DOMAIN="${BASH_REMATCH[1]}"
|
||||
else
|
||||
echo "Could not parse remote domain. Please update manually."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Use provided host alias if given
|
||||
HOST_TO_USE=${HOST_ALIAS:-$DOMAIN}
|
||||
|
||||
REPO_NAME=$(basename "$REPO_PATH")
|
||||
git remote set-url origin git@$HOST_TO_USE:$PROFILE_ALIAS/$REPO_NAME.git
|
||||
echo "Remote URL updated to use SSH key for this repo."
|
||||
|
||||
cd -
|
||||
exit 0
|
||||
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
kill_all ()
|
||||
{
|
||||
if [ -z "$1" ]; then
|
||||
echo "Usage: $0 <keyword>";
|
||||
exit 1;
|
||||
fi;
|
||||
KEYWORD="$1";
|
||||
ps aux | grep --color=auto "$KEYWORD" | grep --color=auto -v "grep" | awk '{print $2}' | xargs -r kill -9
|
||||
}
|
||||
kill_all "$@"
|
||||
Executable
+27
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import spacy
|
||||
|
||||
# Charger les modèles français et anglais
|
||||
nlp_fr = spacy.load("fr_core_news_sm")
|
||||
nlp_en = spacy.load("en_core_web_sm")
|
||||
|
||||
# Lire le texte depuis stdin
|
||||
text = sys.stdin.read().strip()
|
||||
|
||||
# Détecter la langue (simple : regarder les caractères ou demander en argument)
|
||||
# Ici, on choisit automatiquement en fonction des mots
|
||||
# -> si beaucoup de mots anglais, on prend anglais, sinon français
|
||||
words = text.split()
|
||||
english_words = sum(1 for w in words if w.lower() in ["the","is","are","i","you","we","and"])
|
||||
nlp = nlp_en if english_words > len(words) / 2 else nlp_fr
|
||||
|
||||
# Lemmatiser
|
||||
doc = nlp(text)
|
||||
lemmes = [token.lemma_ for token in doc if token.is_alpha]
|
||||
|
||||
print(" ".join(lemmes))
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
NAME+=$(dmesg | tail | grep -o sd[a-z] | tail -1)
|
||||
NAME+=1
|
||||
DEV=/dev/${NAME}
|
||||
MNT_PT=/mnt/$NAME
|
||||
|
||||
echo "mount dev: $DEV at $MNT_PT"
|
||||
|
||||
mkdir $MNT_PT
|
||||
mount $DEV $MNT_PT
|
||||
cd $MNT_PT
|
||||
|
||||
exit 0
|
||||
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
mediaspi ()
|
||||
{
|
||||
if [ -z $1 ]; then
|
||||
echo "usage: $0 $DIR_NAME";
|
||||
return 1;
|
||||
fi;
|
||||
BINAME="collector_bin";
|
||||
DEST="$HOME/perso/${BINAME}";
|
||||
DIR="${1}";
|
||||
mkdir -p $DEST;
|
||||
mkdir $DIR;
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "$DIR exists, must be deleted (will be anyway)";
|
||||
return 1;
|
||||
fi;
|
||||
find . -type f -regextype egrep -iregex ".*$MEDIA_REG" -exec cp --parents -u {} -t $DIR \;;
|
||||
cp -apu $DIR -t $DEST;
|
||||
rm -rf $DIR
|
||||
}
|
||||
mediaspi "$@"
|
||||
Executable
+71
@@ -0,0 +1,71 @@
|
||||
#!/bin/bash
|
||||
# mobian_vm_signed.sh
|
||||
# Télécharge dernière image Mobian signée, lance VM, sauvegarde incrémentale
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
BASE_URL="${1:-https://images.mobian.org/amd64/weekly/}"
|
||||
WORKDIR="${2:-/var/lib/mobian_vm}"
|
||||
BACKUPDIR="${3:-/var/backups/mobian}"
|
||||
|
||||
mkdir -p "$WORKDIR" "$BACKUPDIR"
|
||||
cd "$WORKDIR"
|
||||
|
||||
echo "[1] Recherche dernière image signée"
|
||||
INDEX=$(wget -qO- "$BASE_URL")
|
||||
# cherche uniquement les images avec .img.xz et .sha256 existants
|
||||
IMG_NAME=$(echo "$INDEX" | grep -oP 'mobian-amd64-\d{6,8}\.img\.xz' | sort | tail -n1)
|
||||
|
||||
if [ -z "$IMG_NAME" ]; then
|
||||
echo "Aucune image signée trouvée dans $BASE_URL"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "→ Image trouvée: $IMG_NAME"
|
||||
|
||||
# Téléchargement
|
||||
echo "[2] Téléchargement image + signatures"
|
||||
wget -N "$BASE_URL$IMG_NAME" \
|
||||
"$BASE_URL$IMG_NAME.sha256" \
|
||||
"$BASE_URL$IMG_NAME.asc"
|
||||
|
||||
# Vérification SHA256
|
||||
echo "[3] Vérification SHA256"
|
||||
sha256sum -c "$IMG_NAME.sha256"
|
||||
|
||||
# Vérification GPG
|
||||
echo "[4] Vérification GPG"
|
||||
gpg --keyserver keyserver.ubuntu.com --recv-keys 0x1CE2AFD36DBA9F48
|
||||
gpg --verify "$IMG_NAME.asc" "$IMG_NAME"
|
||||
|
||||
RAW_IMG="${IMG_NAME%.xz}"
|
||||
|
||||
# Extraction si nécessaire
|
||||
if [ ! -f "$RAW_IMG" ]; then
|
||||
xz -dk "$IMG_NAME"
|
||||
fi
|
||||
|
||||
## Arrêt éventuelle ancienne VM
|
||||
#pkill -f "qemu-system-x86_64.*$RAW_IMG" || true
|
||||
#
|
||||
## Lancement VM
|
||||
#echo "[5] Lancement VM"
|
||||
#nohup qemu-system-x86_64 \
|
||||
# -m 2048 -smp 2 \
|
||||
# -drive file="$RAW_IMG",format=raw \
|
||||
# -nic user,hostfwd=tcp::2222-:22 \
|
||||
# -nographic >"$WORKDIR/qemu.log" 2>&1 &
|
||||
#
|
||||
## Sauvegarde incrémentale
|
||||
#echo "[6] Sauvegarde incrémentale"
|
||||
#TODAY=$(date +%F)
|
||||
#rsync -a --link-dest="$BACKUPDIR/latest" \
|
||||
# "$RAW_IMG" \
|
||||
# "$BACKUPDIR/$TODAY/"
|
||||
#ln -sfn "$BACKUPDIR/$TODAY" "$BACKUPDIR/latest"
|
||||
#
|
||||
#echo "[OK] VM active sur port 2222 (SSH/X11)."
|
||||
#echo "Depuis smartphone :"
|
||||
#echo " ssh -p 2222 -C -X user@serveur"
|
||||
#echo "Puis lancer startlxqt ou autre session graphique."
|
||||
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
monip ()
|
||||
{
|
||||
curl ifconfig.me
|
||||
}
|
||||
monip "$@"
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
netstat_tunlp ()
|
||||
{
|
||||
netstat -tunlp
|
||||
}
|
||||
netstat_tunlp "$@"
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
if [ "$#" -lt 1 ] ; then
|
||||
echo "Usage: $0 ip [polite2]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
nmap --script -T3 http-enum $1
|
||||
|
||||
exit 0
|
||||
|
||||
Executable
+26
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
if [ "$#" -lt 1 ] || [ "$#" -gt 3 ]; then
|
||||
echo "Usage: $0 arg1 [arg2] [arg3]"
|
||||
exit 1
|
||||
fi
|
||||
FILE=${1}
|
||||
DIR=${2:-"nmap-list"}
|
||||
|
||||
echo saving in $DIR
|
||||
|
||||
mkdir -p "${DIR}"
|
||||
|
||||
while IFS= read -r line; do
|
||||
IP_ADDR=$(echo $line | grep -Eo $IP_REG)
|
||||
F_OUT=$DIR/$IP_ADDR
|
||||
echo request $IP_ADDR
|
||||
if [ -n "$IP_ADDR" ] ; then
|
||||
nmap -A -T 2 -Pn "$IP_ADDR" | tee "$F_OUT"
|
||||
whois "$IP_ADDR" | tee "$F_OUT.whois"
|
||||
echo done
|
||||
fi
|
||||
done < "$FILE"
|
||||
|
||||
exit 0
|
||||
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
if [ "$#" -ne 2 ] ; then
|
||||
echo "Usage: $0 IP port"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
IP=$1
|
||||
PORT=$2
|
||||
|
||||
nmap -Pn -sV -p "$PORT" --open "$TARGET"
|
||||
|
||||
nmap --script check-port --script-args checkport.port=$PORT -p $PORT $IP
|
||||
|
||||
exit 0
|
||||
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
nmap_full ()
|
||||
{
|
||||
sudo nmap --scanflags URGACKPSHRSTSYNFIN $@
|
||||
}
|
||||
nmap_full "$@"
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
nmap_sA ()
|
||||
{
|
||||
nmap -Pn -sA --reason $@
|
||||
}
|
||||
nmap_sA "$@"
|
||||
Executable
+81
@@ -0,0 +1,81 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ -z "$1" ] ; then echo "no args" ; exit 1 ; fi
|
||||
|
||||
TARGET=$1
|
||||
DIR="$HOME/journal/net/scan/$2"
|
||||
[[ "$DIR" != */ ]] && DIR="$DIR/"
|
||||
OUTPUT_DIR=$DIR"${TARGET}_$(date +%F_%H-%M-%S).nmap"
|
||||
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
log() {
|
||||
echo "[+] $1"
|
||||
echo "[+] $1" >> "$OUTPUT_DIR/scan.log"
|
||||
}
|
||||
|
||||
log "Target: $TARGET"
|
||||
|
||||
### 1. Passive recon
|
||||
log "DNS & WHOIS"
|
||||
dig +short "$TARGET" > "$OUTPUT_DIR/dns.txt"
|
||||
whois "$TARGET" > "$OUTPUT_DIR/whois.txt"
|
||||
nslookup "$TARGET" > "$OUTPUT_DIR/nslookup.txt"
|
||||
|
||||
log "Traceroute"
|
||||
traceroute "$TARGET" > "$OUTPUT_DIR/traceroute.txt"
|
||||
|
||||
# Détection IPv4 / IPv6
|
||||
IPV4=$(dig +short A "$TARGET" | head -n1)
|
||||
IPV6=$(dig +short AAAA "$TARGET" | head -n1)
|
||||
|
||||
scan_block() {
|
||||
local mode=$1 # "IPv4" ou "IPv6"
|
||||
local opt=$2 # "" ou "-6"
|
||||
|
||||
log "=== $mode Scans ==="
|
||||
|
||||
log "Fast TCP Scan (top 100 ports)"
|
||||
sudo nmap $opt -Pn -sS -sV --top-ports 100 -T2 "$TARGET" -oN "$OUTPUT_DIR/nmap_${mode}_fast_tcp.txt"
|
||||
|
||||
log "Full TCP Scan (all 65535 ports)"
|
||||
sudo nmap $opt -Pn -sS -p- -T3 "$TARGET" -oN "$OUTPUT_DIR/nmap_${mode}_full_tcp.txt"
|
||||
|
||||
log "UDP Scan (top 50 ports)"
|
||||
sudo nmap $opt -Pn -sU --top-ports 50 -T4 "$TARGET" -oN "$OUTPUT_DIR/nmap_${mode}_udp.txt"
|
||||
|
||||
log "SCTP Init Scan (top 50 ports)"
|
||||
sudo nmap $opt -Pn -sY --top-ports 50 -T3 "$TARGET" -oN "$OUTPUT_DIR/nmap_${mode}_sctp.txt"
|
||||
|
||||
log "Service Detection (all protocols)"
|
||||
sudo nmap $opt -Pn -sV -p- -sS -sU -T2 "$TARGET" -oN "$OUTPUT_DIR/nmap_${mode}_service.txt"
|
||||
|
||||
log "OS Detection"
|
||||
sudo nmap $opt -Pn -O -A -T2 "$TARGET" -oN "$OUTPUT_DIR/nmap_${mode}_os.txt"
|
||||
|
||||
log "Nmap Vulnerability Scripts"
|
||||
sudo nmap $opt -Pn --script vuln -T2 "$TARGET" -oN "$OUTPUT_DIR/nmap_${mode}_vuln.txt"
|
||||
}
|
||||
|
||||
### 2. Lancer scans selon ce qui est dispo
|
||||
if [ -n "$IPV4" ]; then
|
||||
log "IPv4 detected: $IPV4"
|
||||
scan_block "ipv4" ""
|
||||
else
|
||||
log "No IPv4 found"
|
||||
fi
|
||||
|
||||
if [ -n "$IPV6" ]; then
|
||||
log "IPv6 detected: $IPV6"
|
||||
scan_block "ipv6" "-6"
|
||||
else
|
||||
log "No IPv6 found"
|
||||
fi
|
||||
|
||||
### 3. Fin
|
||||
log "Scan completed. Results in $OUTPUT_DIR/"
|
||||
|
||||
# Hook perso
|
||||
source "$HOME/.bashrc"
|
||||
journal "$OUTPUT_DIR" README
|
||||
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
nmap_ssh_brute ()
|
||||
{
|
||||
nmap --script "ssh-brute" $1
|
||||
}
|
||||
nmap_ssh_brute "$@"
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
nmap_version ()
|
||||
{
|
||||
echo "run : nmap -sV --version-intensity 9 -O -sC $@"
|
||||
nmap -sV --version-intensity 9 -O -sC $@
|
||||
}
|
||||
nmap_version "$@"
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
normi ()
|
||||
{
|
||||
norminette -R CheckForbiddenSourceHeader -R CheckDefine $1
|
||||
}
|
||||
normi "$@"
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/bash
|
||||
cd $MACHINE_DIR
|
||||
commit_if_modified $MACHINE_DIR/install/pacman.sh
|
||||
cd -
|
||||
exit 0
|
||||
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
echo read open port and lsof try to return the associated process
|
||||
|
||||
ss -tunl | awk '{if (NR != 1) print $5}' | awk -F: '{print $NF}' | sort | uniq | xargs -I PORT bash -c "echo port: PORT && lsof -i :PORT | awk '{if (NR != 1) print $NR}'"
|
||||
|
||||
exit 0
|
||||
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
ISO-${1:-"edited_iso"}
|
||||
WORKDIR=$(1:-"iso_edit"}
|
||||
|
||||
if [ "$#" -lt 1 ] ; then
|
||||
echo "Usage: $0 name [iso_edit]
|
||||
note: delete iso_edit and convert it in the
|
||||
named file"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
umount "$WORKDIR"/{proc,sys,dev}
|
||||
genisoimage -o $ISO -V "CUSTOM" -R -J "$WORKDIR"
|
||||
echo "note: genisoimage come from cdrkit package"
|
||||
|
||||
exit 0
|
||||
|
||||
Executable
+14
@@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
ps_parents ()
|
||||
{
|
||||
if [ "$#" -ne 1 ]; then
|
||||
echo "Usage: $0 <pid>";
|
||||
return 1;
|
||||
fi;
|
||||
pid=$1;
|
||||
while [ "$pid" -ne 1 ]; do
|
||||
ps -p $pid -o pid=,ppid=,cmd=;
|
||||
pid=$(ps -p $pid -o ppid= --no-headers);
|
||||
done
|
||||
}
|
||||
ps_parents "$@"
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
if [ "$#" -lt 1 ]
|
||||
echo "Usage: $0 arg1 [arg2] [arg3]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
shift
|
||||
python -m py_compile $@
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/bash
|
||||
vim ~/.config/qtile/config.py
|
||||
exit 0
|
||||
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
export DATE=$(date +"%y%m%d");
|
||||
export TIME=$(date +"%T")
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
if [ "$#" -lt 1 ] ; then
|
||||
echo "Usage: $0 cmd [outfile]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CMD="$1"
|
||||
OUT=${2:-"$(echo $CMD | sed s/ /_/g)"}
|
||||
#DIR=$(realpath $OUT)
|
||||
#mkdir -p $DIR
|
||||
header_journal "$OUT"
|
||||
echo "== $CMD ==" | tee -a "$OUT"
|
||||
eval "$CMD" 2>&1 | tee -a "$OUT"
|
||||
|
||||
exit 0
|
||||
|
||||
Executable
+37
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
if [ "$#" -lt 1 ] || [ "$#" -gt 3 ]; then
|
||||
echo "Usage: $0 arg1 [arg2] [arg3]"
|
||||
exit 1
|
||||
fi
|
||||
#!/bin/bash
|
||||
|
||||
IP="$1"
|
||||
DIR="${2:-${IP}_report}"
|
||||
|
||||
mkdir -p "$DIR"
|
||||
cd $DIR
|
||||
|
||||
#report-cmd "dig AAAA $IP"
|
||||
#
|
||||
#report-cmd "dig -x $IP"
|
||||
#report-cmd "host $IP"
|
||||
|
||||
report-cmd "curl -s https://ipinfo.io/$IP" ipinfo
|
||||
report-cmd "curl -s https://ipapi.co/$IP/json/" ipapi
|
||||
|
||||
#report-cmd "sipcalc $IP"
|
||||
#report-cmd "ipv6calc --in ipv6addr $IP"
|
||||
#
|
||||
#report-cmd "traceroute6 $IP"
|
||||
#report-cmd "tracepath6 $IP"
|
||||
|
||||
#report-cmd "curl -s https://api.bgpview.io/ip/$IP"
|
||||
#report-cmd "curl -s 'https://stat.ripe.net/data/prefix-overview/data.json?resource=$IP'"
|
||||
#
|
||||
#report-cmd "nmap -6 $IP"
|
||||
|
||||
cd -
|
||||
|
||||
exit 0
|
||||
|
||||
Executable
+30
@@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
report_crash ()
|
||||
{
|
||||
. refresh_time;
|
||||
NAME=$1;
|
||||
TAIL_SIZE="100";
|
||||
DIR_ORIGINAL=$PWD;
|
||||
CRASH_DIR="$(echo ${DATE}_${TIME} | sed 's/:/-/g')";
|
||||
F_NAME="${NAME}.crash";
|
||||
DIR_RELATIVE="$HOME/journal/sysadmin/crash";
|
||||
DIR_RELATIVE+="/${CRASH_DIR}";
|
||||
if [ "$#" -ne 1 ]; then
|
||||
echo "Usage: $0 FILE_NAME";
|
||||
echo "default path is $DIR_RELATIVE/FILE_NAME.crash";
|
||||
echo "write log outputs";
|
||||
return 1;
|
||||
fi;
|
||||
mkdir -p $DIR_RELATIVE;
|
||||
cd $DIR_RELATIVE;
|
||||
if [ -f $F_NAME ]; then
|
||||
BCK="/tmp/$F_NAME.backup";
|
||||
echo "File exists moved to $BCK";
|
||||
mv $F_NAME $BCK;
|
||||
fi;
|
||||
header_journal $F_NAME;
|
||||
journalctl_prettyfy "100" "1" "0" "$F_NAME";
|
||||
commit_if_modified "$F_NAME" "DELETE_IF_NOT_MODIFIED";
|
||||
cd $DIR_ORIGINAL
|
||||
}
|
||||
report_crash "$@"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user