Difference between revisions of "User:Saul"
m (Expanded technologies.) |
(A test for the webhooks.) |
||
(109 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
− | I | + | This page contains my notes and documentation of various technologies, mostly related to the tech stack I use. |
+ | |||
+ | == Useful Links In This Wiki == | ||
+ | *[[LibP2P]] | ||
+ | *[[User:Saul/networking]] | ||
+ | *[[User:Saul/pwa]] | ||
+ | *[[User:Saul/linode]] | ||
+ | *[[User:Saul/Raspberry_Pi]] | ||
+ | *[[User:Saul/Open_WRT]] | ||
+ | *[[User:Saul/nginx]] | ||
+ | *[[User:Saul/vue]] | ||
+ | *[[User:Saul/wasm]] | ||
+ | *[[User:Saul/feathers]] | ||
+ | *[[User:Saul/Realtime_app]] | ||
+ | *[[User:Saul/electron]] | ||
+ | *[[User:Saul/nativescript]] | ||
+ | *[[TypeScript]] | ||
+ | *[[User:Saul/eslint]] | ||
+ | *[[User:Saul/testing]] | ||
+ | *[[User:Saul/Mongodb]] | ||
+ | *[[User:Saul/c_sharp]] | ||
+ | *[[User:Saul/C]] | ||
+ | *[[Wordpress]] | ||
+ | *[[MySQL]] | ||
+ | *[[Linux_commands]] | ||
+ | *[[User:Saul/editors]] | ||
+ | * '''Math''' | ||
+ | ** [[User:Saul/cs_and_math]] | ||
+ | ** [[User:Saul/matrices]] | ||
+ | ** [[User:Saul/algebra]] | ||
+ | ** [[User:Saul/calculus]] | ||
+ | ** [[User:Saul/probability]] | ||
+ | ** [https://eater.net/quaternions Understanding Quaternions] | ||
+ | * '''Other''' | ||
+ | ** [[User:Saul/brewing]] | ||
+ | ** [[User:Saul/guitar]] | ||
+ | |||
+ | == My Crypto Links In This Wiki == | ||
+ | *[[User:Saul/Insane]] | ||
+ | *[[Blockstack]] | ||
+ | |||
+ | == My Troubleshooting Pages == | ||
+ | *[[User:Saul/Sound_card]] | ||
+ | *[[User:Saul/3d_printer]] | ||
+ | *[[User:Saul/duel_boot]] | ||
+ | *[[User:Saul/soarer]] | ||
+ | *[[User:Saul/Laptop]] | ||
+ | *[[User:Saul/Guitarix]] | ||
+ | |||
+ | == Cool Projects == | ||
+ | *[https://libraryofbabel.info/ Library Of Babel] | ||
+ | *[http://www.dictionaryofobscuresorrows.com/ Book of Obscure Sorrows] | ||
+ | *[https://github.com/NVIDIA/vid2vid Nvidia Vid2Vid] | ||
+ | *[https://alicevision.github.io/#meshroom 3d Scanning] | ||
+ | *[https://unsplash.com Unsplash - Free Image Library] | ||
+ | *[https://thenounproject.com/ The Noun Project - Free SVG Library] | ||
+ | *[https://www.gutenberg.org/ Gutenberg - Free E-book Library] | ||
+ | *[https://archive.org/ Archive of the Internet] | ||
+ | *[https://easings.net/ Easing cheat Sheet] | ||
+ | *[https://github.com/3b1b/manim Mathematical animations for python] | ||
+ | *[https://www.myabandonware.com/ Abandoned Games Archive] | ||
+ | *[https://the-eye.eu/ The Eye - Digital Archive] | ||
+ | **[https://the-eye.eu/alvro/ The Eye - Older Games] | ||
== Snippets: == | == Snippets: == | ||
=== BASH: === | === BASH: === | ||
+ | |||
+ | ==== Copy File To Server ==== | ||
+ | To copy a file from or to a server over ssh run: | ||
+ | <source lang="bash"> | ||
+ | # scp SOURCE DESTINATION | ||
+ | scp -r USER@IP:~/SOME_FOLDER ~/SOME_FOLDER | ||
+ | </source> | ||
+ | |||
+ | ==== VPS Proxy ==== | ||
+ | To proxy traffic over port 1080 run: | ||
+ | <source lang="bash"> | ||
+ | ssh -NCD 1080 user@ip | ||
+ | </source> | ||
+ | Then in Firefox go: Edit -> Preferences -> General -> Network Proxy (near the bottom) and modify the following settings: | ||
+ | <source> | ||
+ | Manual Proxy Configuration | ||
+ | Socks Host: localhost | ||
+ | port: 1080 | ||
+ | </source> | ||
==== Alias ==== | ==== Alias ==== | ||
To save a command run: | To save a command run: | ||
<source lang="bash"> | <source lang="bash"> | ||
− | alias COMMANDNAME="COMMAND" | + | alias COMMANDNAME="COMMAND" |
</source> | </source> | ||
This will be lost on reboot however so to save it run: | This will be lost on reboot however so to save it run: | ||
<source lang="bash"> | <source lang="bash"> | ||
− | echo "alias COMMANDNAME=\"COMMAND\";" >> ~/.bashrc | + | echo "alias COMMANDNAME=\"COMMAND\";" >> ~/.bash_aliases # OR directly into the rc file (~/.bashrc) |
</source> | </source> | ||
Line 17: | Line 98: | ||
A useful command to generate a random password of 10 characters: | A useful command to generate a random password of 10 characters: | ||
<source lang="bash"> | <source lang="bash"> | ||
− | + | </dev/urandom tr -dc 'A-Za-z0-9!#$%&()*+,-./:;<=>?@[\]^_`{|}~' | head -c 10 ; echo | |
+ | </source> | ||
+ | Or even better use [https://code.organicdesign.nz/tools/blob/master/mkpwd.pl this]. | ||
+ | |||
+ | ==== SSH Tunnel ==== | ||
+ | A SSH tunnel can allow you to make queries on a local machine and have them tunneled onto a remote machine. | ||
+ | |||
+ | <source lang="bash"> | ||
+ | # Open tunnel | ||
+ | ssh -M -\ | ||
+ | S ~/tunnel-file \ | ||
+ | -o "ExitOnForwardFailure yes" \ | ||
+ | -fN root@example.com \ | ||
+ | -L 4040:localhost:4040 | ||
+ | |||
+ | # Listen to port | ||
+ | nc -lv localhost \ | ||
+ | -p 4040 | ||
+ | |||
+ | # send data on port | ||
+ | cat < /dev/urandom > /dev/tcp/localhost/4040 | ||
+ | </source> | ||
+ | |||
+ | ==== Block Non-VPN Network Activity ==== | ||
+ | <source lang="bash"> | ||
+ | # Name of VPN network adapter | ||
+ | VPN_IF=tun0 | ||
+ | |||
+ | VPN_SERVER=1.2.3.4 | ||
+ | VPN_PORT=1194 | ||
+ | |||
+ | # Reset the IP Tables | ||
+ | sudo iptables -F | ||
+ | |||
+ | # Allow inbound connections related to things you initiate on any interface | ||
+ | sudo iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT | ||
+ | # Allow loopback | ||
+ | sudo iptables -A INPUT -i lo -j ACCEPT | ||
+ | sudo iptables -A OUTPUT -o lo -j ACCEPT | ||
+ | # Allow all out to VPN | ||
+ | sudo iptables -A OUTPUT -o $VPN_IF -j ACCEPT | ||
+ | # Assuming UDP | ||
+ | sudo iptables -A OUTPUT -p udp --dport $VPN_PORT -d $VPN_SERVER -j ACCEPT | ||
+ | # Allow DHCP | ||
+ | sudo iptables -A OUTPUT -p udp --dport 67 -j ACCEPT | ||
+ | sudo iptables -A INPUT -p udp --dport 68 -j ACCEPT | ||
+ | # Default drop the rest | ||
+ | sudo iptables -A INPUT -j DROP | ||
+ | sudo iptables -A OUTPUT -j DROP | ||
+ | </source> | ||
+ | |||
+ | To reset: | ||
+ | <source lang="bash"> | ||
+ | sudo iptables -F | ||
+ | </source> | ||
+ | |||
+ | * https://security.stackexchange.com/questions/212666/for-security-purposes-can-i-use-vpn-with-ufw-to-allow-traffic-only-from-the-vpn | ||
+ | |||
+ | ==== Archiving ==== | ||
+ | Parameters: | ||
+ | * -f Specify file | ||
+ | * -v Verbose | ||
+ | * -z Use gzip | ||
+ | * -c Compress | ||
+ | * -x Extract | ||
+ | |||
+ | <source lang="bash"> | ||
+ | # Compress (GZIP) | ||
+ | tar -czvf <ARCHIVE NAME>.tar.gz <DIRECTORY TO ARCHIVE> | ||
+ | |||
+ | # Decompress (GZIP) | ||
+ | tar -xzvf <ARCHIVE NAME>.tar.gz -C <DIRECTORY TO Extract To> | ||
+ | |||
+ | # LZ4 Install | ||
+ | apt-get install liblz4-tool | ||
+ | |||
+ | # Compress (LZ4) | ||
+ | tar -cvf - <DIRECTORY TO ARCHIVE> | lz4 - <ARCHIVE NAME>.tar.lz4 | ||
+ | |||
+ | # Decompress (LZ4) | ||
+ | lz4 -c -d <ARCHIVE NAME>.tar.lz4 | tar -xvfC <DIRECTORY TO Extract To> | ||
+ | tar --use-compress-program=lz4 -xvf <ARCHIVE NAME>.tar.lz4 -C <DIRECTORY TO Extract To> # Alternative | ||
+ | </source> | ||
+ | |||
+ | ==== Open Encrypted Home Folders ==== | ||
+ | To mount an encrypted home directory you will need to run the following commands: | ||
+ | |||
+ | <source lang="bash"> | ||
+ | sudo su; | ||
+ | mkdir /mnt/home; | ||
+ | ecryptfs-unwrap-passphrase /media/mint/UUID/home/.ecryptfs/USER/.ecryptfs/wrapped-passphrase; # Replace 'UUID' and 'USER' | ||
+ | |||
+ | # The last command will output a string, copy it somewhere for later. | ||
+ | |||
+ | sudo ecryptfs-add-passphrase --fnek # Input the string from the last command | ||
+ | |||
+ | # This will provide 2 sig outputs copy the last one somewhere for later. (it looks like a hash and is in between square brackets). | ||
+ | |||
+ | mount -t ecryptfs /media/mint/UUID/home/.ecryptfs/USER/.Private /mnt/home; # Replace 'UUID' and 'USER' | ||
+ | # 1. Choose opt. #1 'passphrase' and input the passphrase you copied earlier. | ||
+ | # 2. Choose 'aes' (default) | ||
+ | # 3. Choose '16' (default) for key bytes. | ||
+ | # 4. Choose 'no' (default) for Enable plaintext passthrough | ||
+ | # 5. Choose 'yes' for Enable filename encryption | ||
+ | # 6. Input the sig output you copied earlier. | ||
+ | </source> | ||
+ | |||
+ | The home directory should now be mounted at '''/mnt/home''' | ||
+ | |||
+ | * https://forums.linuxmint.com/viewtopic.php?t=315207 | ||
+ | |||
+ | ==== Joining mp3s ==== | ||
+ | |||
+ | <source lang="bash"> | ||
+ | sudo apt-get install mp3wrap | ||
+ | mp3wrap output.mp3 *.mp3 | ||
+ | </source> | ||
+ | |||
+ | ''There is also mp3split for splitting mp3s'' | ||
+ | |||
+ | ==== Fix mp3 Meta ==== | ||
+ | |||
+ | <source lang="bash"> | ||
+ | mp3val damaged.mp3 -f | ||
+ | </source> | ||
+ | |||
+ | ==== LVM Resize Disk ==== | ||
+ | Display volume group data: | ||
+ | |||
+ | <source lang="bash"> | ||
+ | vgdisplay | ||
+ | </source> | ||
+ | |||
+ | Get the value under '''LV Path'''. | ||
+ | |||
+ | <source lang="bash"> | ||
+ | sudo lvextend -L+500GB <LV_PATH> | ||
+ | </source> | ||
+ | |||
+ | Then you need to resize the filesystem: | ||
+ | <source lang="bash"> | ||
+ | sudo resize2fs <LV_PATH> | ||
</source> | </source> | ||
=== CSS: === | === CSS: === | ||
− | ==== | + | ==== Sticky Footer ==== |
<source lang="CSS"> | <source lang="CSS"> | ||
body .site{ | body .site{ | ||
Line 36: | Line 258: | ||
Note: in Wordpress the user bar will make the page need to scroll so logout to see it properly. | Note: in Wordpress the user bar will make the page need to scroll so logout to see it properly. | ||
− | ==== | + | ==== Hide ReCaptcha ==== |
+ | <source lang="css"> | ||
+ | body:not(.page-id-16) .grecaptcha-badge { | ||
+ | display: none; | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | ==== Same Height Columns: ==== | ||
<source lang="CSS"> | <source lang="CSS"> | ||
.Container{ | .Container{ | ||
Line 47: | Line 276: | ||
</source> | </source> | ||
− | == | + | === Javascript === |
− | + | ||
− | + | ==== Git Web Hooks ==== | |
− | + | <source lang="javascript"> | |
− | + | const http = require("http"); | |
− | * | + | const crypto = require("crypto"); |
+ | const exec = require("child_process").exec; | ||
+ | |||
+ | const repo = "<DIRECTORY OF YOUR REPO>"; | ||
+ | const secret = "<YOUR SECRET>"; | ||
+ | |||
+ | http.createServer((req, res) => { | ||
+ | req.on("data", chunk => { | ||
+ | try { | ||
+ | const body = JSON.parse(chunk.toString()); | ||
+ | |||
+ | // Github | ||
+ | const sig = "sha1=" + crypto.createHmac("sha1", secret).update(chunk.toString()).digest("hex"); | ||
+ | |||
+ | // Gitea | ||
+ | //const sig = crypto.createHmac("sha256", secret).update(chunk.toString()).digest("hex"); | ||
+ | |||
+ | const isMaster = body?.ref === "refs/heads/master"; | ||
+ | |||
+ | // Gitea needs "x-gitea-signature" | ||
+ | if (req.headers["x-hub-signature"] == sig && isMaster) { | ||
+ | if (isMaster) | ||
+ | exec(`cd ${repo} && git pull`); | ||
+ | |||
+ | res.writeHead(200); | ||
+ | res.end("Success!"); | ||
+ | } else { | ||
+ | console.error("Failed verification."); | ||
+ | res.writeHead(403); | ||
+ | res.end("Failed verification."); | ||
+ | } | ||
+ | } catch (e) { | ||
+ | console.error(e); | ||
+ | res.writeHead(403); | ||
+ | res.end(`Somthing went wrong.`); | ||
+ | } | ||
+ | }); | ||
+ | }).listen(8080); | ||
+ | </source> | ||
+ | |||
+ | Add it as a service: '''/etc/systemd/system/webhook.service''' | ||
+ | <source> | ||
+ | [Unit] | ||
+ | Description=Git webhook | ||
+ | After=network.target | ||
+ | |||
+ | [Service] | ||
+ | Environment=NODE_PORT=8080 | ||
+ | Type=simple | ||
+ | User=root | ||
+ | ExecStart=/usr/bin/nodejs <WEBHOOK DIRECTORY> | ||
+ | Restart=on-failure | ||
+ | |||
+ | [Install] | ||
+ | WantedBy=multi-user.target | ||
+ | </source> | ||
+ | |||
+ | ==== Higher Order Functions ==== | ||
+ | Higher order functions are functions that accept or return a function. These are useful of abstracting and reducing your code.<br> | ||
+ | <source lang="javascript"> | ||
+ | // ES6+ | ||
+ | const fetchResource = (resource, id) => fetch(`api/${resource}/${id}`); | ||
+ | |||
+ | const makeFetcher = resource => id => fetchResource(resource, id); | ||
+ | |||
+ | const fetchUser = makeFetcher("users"); | ||
+ | const fetchGroup = makeFetcher("group"); | ||
+ | |||
+ | const user = fetchUser("123"); | ||
+ | const group = fetchGroup("10"); | ||
+ | |||
+ | // ES5 | ||
+ | function fetchResource (resource, id) { | ||
+ | return fetch("api/" + resource + "/" + id); | ||
+ | } | ||
+ | |||
+ | function makeFetcher (resource) { | ||
+ | return function (id) { | ||
+ | fetchResource(resource, id); | ||
+ | }; | ||
+ | } | ||
+ | |||
+ | function fetchUser () { | ||
+ | return makeFetcher("users"); | ||
+ | } | ||
+ | |||
+ | function fetchGroup () { | ||
+ | return makeFetcher("group"); | ||
+ | } | ||
+ | |||
+ | var user = fetchUser("123"); | ||
+ | var group = fetchGroup("10"); | ||
+ | </source> | ||
+ | This example helps show how higher order functions can be useful. If the api location changes you only need to change one function to get your code working again.<br> | ||
+ | The fetchResource function is just a simple function that calls the fetch function with its parameters. The makeFetcher is a closure function that returns another function that calls our first, therefore when make fetcher gets called it returns a function that only needs the id due to the resource being saved due to the first function acting a a closure. Then you can quickly make your fethcUser, fetchGroup functions and so on. | ||
+ | |||
+ | ==== Unpacking Objects And Arrays ==== | ||
+ | Arrays can be unpacked into a variables list like this example: | ||
+ | <source lang="javascript"> | ||
+ | let list = ["apples", "bananas", "carrots", "pears", "corn"]; | ||
+ | |||
+ | let [itemOne, itemTwo, ItemThree, ItemFour] = list; | ||
+ | |||
+ | console.log(itemOne); // Output: "apples" | ||
+ | console.log(itemThree); // Output: "carrots" | ||
+ | </source> | ||
+ | You can use this syntax to switch the variables too! | ||
+ | <source lang="javascript"> | ||
+ | [itemOne, itemTwo] = [itemTwo, itemOne]; | ||
+ | |||
+ | console.log(itemOne); // Output: "bananas" | ||
+ | </source> | ||
+ | Objects can be unpacked using similar syntax: | ||
+ | <source lang="javascript"> | ||
+ | let person = { | ||
+ | name: "sam", | ||
+ | height: 2, | ||
+ | food: "pizza" | ||
+ | } | ||
+ | |||
+ | {name, height, food} = person; | ||
+ | |||
+ | console.log(name); // Output: "sam" | ||
+ | console.log(food); // Output: "pizza" | ||
+ | |||
+ | ({height, food, name}) = person; | ||
+ | |||
+ | console.log(name); // Output: "sam" | ||
+ | console.log(height); // Output: 2 | ||
+ | </source> | ||
+ | Note that the variable names must match the object properties, if you want different names you can do it like this: | ||
+ | <source lang="javascript"> | ||
+ | ({name: n}) = person; | ||
+ | |||
+ | console.log(n); // Output: "sam" | ||
+ | </source> | ||
+ | Using this syntax you can also set default values for properties like so: | ||
+ | <source lang="javascript"> | ||
+ | ({name: n, pet: favouriteAnimal = "dragon"}) = person; | ||
+ | </source> | ||
+ | |||
+ | ==== Node Fetch and Ipv6 ==== | ||
+ | Node's fetch can sometimes fail due to IPv6 selection failing and it only gives a timeout error. | ||
+ | |||
+ | <source lang="javascript"> | ||
+ | // Fix package 'node-fetch' | ||
+ | import http, { Agent } from 'https' | ||
+ | |||
+ | http.globalAgent = new Agent({ family: 4 }) | ||
+ | </source> | ||
+ | |||
+ | <source lang="javascript"> | ||
+ | // Fix default node fetch implementation (undici) | ||
+ | import undici, { fetch, Agent } from 'undici' | ||
+ | |||
+ | const agent = new Agent({ | ||
+ | autoSelectFamily: true, | ||
+ | autoSelectFamilyAttemptTimeout: 1000 | ||
+ | }) | ||
+ | |||
+ | // Per fetch call: | ||
+ | await fetch('your url here', { | ||
+ | dispatcher: agent | ||
+ | }) | ||
+ | |||
+ | // Globally: | ||
+ | undici.setGlobalDispatcher(agent) | ||
+ | </source> | ||
+ | |||
+ | === C === | ||
+ | Printing the raw bits of a variable: | ||
+ | <source lang="c"> | ||
+ | // Change "unsigned char" to the type you would like to inspect. | ||
+ | void printbits (unsigned char v) { | ||
+ | int i; | ||
+ | for(i = sizeof(v) * 8 - 1; i >= 0; i--) putchar('0' + ((v >> i) & 1)); | ||
+ | } | ||
+ | </source> | ||
− | + | <!-- Test --> | |
− |
Latest revision as of 19:05, 11 November 2024
This page contains my notes and documentation of various technologies, mostly related to the tech stack I use.
Contents
Useful Links In This Wiki
- LibP2P
- User:Saul/networking
- User:Saul/pwa
- User:Saul/linode
- User:Saul/Raspberry_Pi
- User:Saul/Open_WRT
- User:Saul/nginx
- User:Saul/vue
- User:Saul/wasm
- User:Saul/feathers
- User:Saul/Realtime_app
- User:Saul/electron
- User:Saul/nativescript
- TypeScript
- User:Saul/eslint
- User:Saul/testing
- User:Saul/Mongodb
- User:Saul/c_sharp
- User:Saul/C
- Wordpress
- MySQL
- Linux_commands
- User:Saul/editors
- Math
- Other
My Crypto Links In This Wiki
My Troubleshooting Pages
- User:Saul/Sound_card
- User:Saul/3d_printer
- User:Saul/duel_boot
- User:Saul/soarer
- User:Saul/Laptop
- User:Saul/Guitarix
Cool Projects
- Library Of Babel
- Book of Obscure Sorrows
- Nvidia Vid2Vid
- 3d Scanning
- Unsplash - Free Image Library
- The Noun Project - Free SVG Library
- Gutenberg - Free E-book Library
- Archive of the Internet
- Easing cheat Sheet
- Mathematical animations for python
- Abandoned Games Archive
- The Eye - Digital Archive
Snippets:
BASH:
Copy File To Server
To copy a file from or to a server over ssh run:
# scp SOURCE DESTINATION
scp -r USER@IP:~/SOME_FOLDER ~/SOME_FOLDER
VPS Proxy
To proxy traffic over port 1080 run:
ssh -NCD 1080 user@ip
Then in Firefox go: Edit -> Preferences -> General -> Network Proxy (near the bottom) and modify the following settings:
Manual Proxy Configuration
Socks Host: localhost
port: 1080
Alias
To save a command run:
alias COMMANDNAME="COMMAND"
This will be lost on reboot however so to save it run:
echo "alias COMMANDNAME=\"COMMAND\";" >> ~/.bash_aliases # OR directly into the rc file (~/.bashrc)
Random Password Generation
A useful command to generate a random password of 10 characters:
</dev/urandom tr -dc 'A-Za-z0-9!#$%&()*+,-./:;<=>?@[\]^_`{|}~' | head -c 10 ; echo
Or even better use this.
SSH Tunnel
A SSH tunnel can allow you to make queries on a local machine and have them tunneled onto a remote machine.
# Open tunnel
ssh -M -\
S ~/tunnel-file \
-o "ExitOnForwardFailure yes" \
-fN root@example.com \
-L 4040:localhost:4040
# Listen to port
nc -lv localhost \
-p 4040
# send data on port
cat < /dev/urandom > /dev/tcp/localhost/4040
Block Non-VPN Network Activity
# Name of VPN network adapter
VPN_IF=tun0
VPN_SERVER=1.2.3.4
VPN_PORT=1194
# Reset the IP Tables
sudo iptables -F
# Allow inbound connections related to things you initiate on any interface
sudo iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# Allow loopback
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A OUTPUT -o lo -j ACCEPT
# Allow all out to VPN
sudo iptables -A OUTPUT -o $VPN_IF -j ACCEPT
# Assuming UDP
sudo iptables -A OUTPUT -p udp --dport $VPN_PORT -d $VPN_SERVER -j ACCEPT
# Allow DHCP
sudo iptables -A OUTPUT -p udp --dport 67 -j ACCEPT
sudo iptables -A INPUT -p udp --dport 68 -j ACCEPT
# Default drop the rest
sudo iptables -A INPUT -j DROP
sudo iptables -A OUTPUT -j DROP
To reset:
sudo iptables -F
Archiving
Parameters:
- -f Specify file
- -v Verbose
- -z Use gzip
- -c Compress
- -x Extract
# Compress (GZIP)
tar -czvf <ARCHIVE NAME>.tar.gz <DIRECTORY TO ARCHIVE>
# Decompress (GZIP)
tar -xzvf <ARCHIVE NAME>.tar.gz -C <DIRECTORY TO Extract To>
# LZ4 Install
apt-get install liblz4-tool
# Compress (LZ4)
tar -cvf - <DIRECTORY TO ARCHIVE> | lz4 - <ARCHIVE NAME>.tar.lz4
# Decompress (LZ4)
lz4 -c -d <ARCHIVE NAME>.tar.lz4 | tar -xvfC <DIRECTORY TO Extract To>
tar --use-compress-program=lz4 -xvf <ARCHIVE NAME>.tar.lz4 -C <DIRECTORY TO Extract To> # Alternative
Open Encrypted Home Folders
To mount an encrypted home directory you will need to run the following commands:
sudo su;
mkdir /mnt/home;
ecryptfs-unwrap-passphrase /media/mint/UUID/home/.ecryptfs/USER/.ecryptfs/wrapped-passphrase; # Replace 'UUID' and 'USER'
# The last command will output a string, copy it somewhere for later.
sudo ecryptfs-add-passphrase --fnek # Input the string from the last command
# This will provide 2 sig outputs copy the last one somewhere for later. (it looks like a hash and is in between square brackets).
mount -t ecryptfs /media/mint/UUID/home/.ecryptfs/USER/.Private /mnt/home; # Replace 'UUID' and 'USER'
# 1. Choose opt. #1 'passphrase' and input the passphrase you copied earlier.
# 2. Choose 'aes' (default)
# 3. Choose '16' (default) for key bytes.
# 4. Choose 'no' (default) for Enable plaintext passthrough
# 5. Choose 'yes' for Enable filename encryption
# 6. Input the sig output you copied earlier.
The home directory should now be mounted at /mnt/home
Joining mp3s
sudo apt-get install mp3wrap
mp3wrap output.mp3 *.mp3
There is also mp3split for splitting mp3s
Fix mp3 Meta
mp3val damaged.mp3 -f
LVM Resize Disk
Display volume group data:
vgdisplay
Get the value under LV Path.
sudo lvextend -L+500GB <LV_PATH>
Then you need to resize the filesystem:
sudo resize2fs <LV_PATH>
CSS:
body .site{
display: flex !important;
min-height: 100vh !important;
flex-direction: column !important;
}
#content {
flex: 1 !important;
}
Note: in Wordpress the user bar will make the page need to scroll so logout to see it properly.
Hide ReCaptcha
body:not(.page-id-16) .grecaptcha-badge {
display: none;
}
Same Height Columns:
.Container{
display: flex;
}
.Column{
flex: 1; /* optional to equalize widths */
}
Javascript
Git Web Hooks
const http = require("http");
const crypto = require("crypto");
const exec = require("child_process").exec;
const repo = "<DIRECTORY OF YOUR REPO>";
const secret = "<YOUR SECRET>";
http.createServer((req, res) => {
req.on("data", chunk => {
try {
const body = JSON.parse(chunk.toString());
// Github
const sig = "sha1=" + crypto.createHmac("sha1", secret).update(chunk.toString()).digest("hex");
// Gitea
//const sig = crypto.createHmac("sha256", secret).update(chunk.toString()).digest("hex");
const isMaster = body?.ref === "refs/heads/master";
// Gitea needs "x-gitea-signature"
if (req.headers["x-hub-signature"] == sig && isMaster) {
if (isMaster)
exec(`cd ${repo} && git pull`);
res.writeHead(200);
res.end("Success!");
} else {
console.error("Failed verification.");
res.writeHead(403);
res.end("Failed verification.");
}
} catch (e) {
console.error(e);
res.writeHead(403);
res.end(`Somthing went wrong.`);
}
});
}).listen(8080);
Add it as a service: /etc/systemd/system/webhook.service
[Unit]
Description=Git webhook
After=network.target
[Service]
Environment=NODE_PORT=8080
Type=simple
User=root
ExecStart=/usr/bin/nodejs <WEBHOOK DIRECTORY>
Restart=on-failure
[Install]
WantedBy=multi-user.target
Higher Order Functions
Higher order functions are functions that accept or return a function. These are useful of abstracting and reducing your code.
// ES6+
const fetchResource = (resource, id) => fetch(`api/${resource}/${id}`);
const makeFetcher = resource => id => fetchResource(resource, id);
const fetchUser = makeFetcher("users");
const fetchGroup = makeFetcher("group");
const user = fetchUser("123");
const group = fetchGroup("10");
// ES5
function fetchResource (resource, id) {
return fetch("api/" + resource + "/" + id);
}
function makeFetcher (resource) {
return function (id) {
fetchResource(resource, id);
};
}
function fetchUser () {
return makeFetcher("users");
}
function fetchGroup () {
return makeFetcher("group");
}
var user = fetchUser("123");
var group = fetchGroup("10");
This example helps show how higher order functions can be useful. If the api location changes you only need to change one function to get your code working again.
The fetchResource function is just a simple function that calls the fetch function with its parameters. The makeFetcher is a closure function that returns another function that calls our first, therefore when make fetcher gets called it returns a function that only needs the id due to the resource being saved due to the first function acting a a closure. Then you can quickly make your fethcUser, fetchGroup functions and so on.
Unpacking Objects And Arrays
Arrays can be unpacked into a variables list like this example:
let list = ["apples", "bananas", "carrots", "pears", "corn"];
let [itemOne, itemTwo, ItemThree, ItemFour] = list;
console.log(itemOne); // Output: "apples"
console.log(itemThree); // Output: "carrots"
You can use this syntax to switch the variables too!
[itemOne, itemTwo] = [itemTwo, itemOne];
console.log(itemOne); // Output: "bananas"
Objects can be unpacked using similar syntax:
let person = {
name: "sam",
height: 2,
food: "pizza"
}
{name, height, food} = person;
console.log(name); // Output: "sam"
console.log(food); // Output: "pizza"
({height, food, name}) = person;
console.log(name); // Output: "sam"
console.log(height); // Output: 2
Note that the variable names must match the object properties, if you want different names you can do it like this:
({name: n}) = person;
console.log(n); // Output: "sam"
Using this syntax you can also set default values for properties like so:
({name: n, pet: favouriteAnimal = "dragon"}) = person;
Node Fetch and Ipv6
Node's fetch can sometimes fail due to IPv6 selection failing and it only gives a timeout error.
// Fix package 'node-fetch'
import http, { Agent } from 'https'
http.globalAgent = new Agent({ family: 4 })
// Fix default node fetch implementation (undici)
import undici, { fetch, Agent } from 'undici'
const agent = new Agent({
autoSelectFamily: true,
autoSelectFamilyAttemptTimeout: 1000
})
// Per fetch call:
await fetch('your url here', {
dispatcher: agent
})
// Globally:
undici.setGlobalDispatcher(agent)
C
Printing the raw bits of a variable:
// Change "unsigned char" to the type you would like to inspect.
void printbits (unsigned char v) {
int i;
for(i = sizeof(v) * 8 - 1; i >= 0; i--) putchar('0' + ((v >> i) & 1));
}