mirror of
https://github.com/PR0M3TH3AN/VoxVera.git
synced 2025-09-07 14:38:42 +00:00
Move data inside package and update references
This commit is contained in:
@@ -17,11 +17,13 @@ ROOT = Path(__file__).resolve().parent.parent
|
||||
|
||||
|
||||
def _template_res(*parts) -> Traversable:
|
||||
return resources.files(__package__).joinpath('..', 'templates', *parts)
|
||||
"""Return a Traversable for files under the packaged ``templates`` folder."""
|
||||
return resources.files(__package__).joinpath('templates', *parts)
|
||||
|
||||
|
||||
def _src_res(*parts) -> Traversable:
|
||||
return resources.files(__package__).joinpath('..', 'src', *parts)
|
||||
"""Return a Traversable for files under the packaged ``src`` folder."""
|
||||
return resources.files(__package__).joinpath('src', *parts)
|
||||
|
||||
|
||||
def require_cmd(cmd: str):
|
||||
|
144
voxvera/src/README.md
Normal file
144
voxvera/src/README.md
Normal file
@@ -0,0 +1,144 @@
|
||||
# HTML/CSS/JS Obfuscation Script
|
||||
|
||||
This repository contains two Bash scripts that obfuscate and minify the flyer's HTML files. `obfuscate_index.sh` processes `index-master.html` into `index.html`, and `obfuscate_nostr.sh` does the same for `nostr-master.html` to produce `nostr.html`.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **Debian/Ubuntu**: This script is designed to work on Debian-based systems.
|
||||
- **Node.js**: Terser and html-minifier-terser require Node.js to be installed.
|
||||
- **qrencode**: Generates the QR codes used in the flyers.
|
||||
|
||||
### Install Node.js and npm on Debian
|
||||
|
||||
1. **Update your package list:**
|
||||
```bash
|
||||
sudo apt update
|
||||
```
|
||||
|
||||
2. **Install Node.js and npm:**
|
||||
```bash
|
||||
sudo apt install nodejs npm -y
|
||||
```
|
||||
|
||||
3. **Verify the installation:**
|
||||
```bash
|
||||
node -v
|
||||
npm -v
|
||||
```
|
||||
|
||||
### Install Additional Packages
|
||||
|
||||
The helper scripts rely on a few system utilities:
|
||||
|
||||
```bash
|
||||
sudo apt install -y jq qrencode imagemagick poppler-utils
|
||||
```
|
||||
|
||||
### Install Required Tools
|
||||
|
||||
Install the Node-based tools used by the obfuscation scripts:
|
||||
|
||||
```bash
|
||||
npm install -g javascript-obfuscator html-minifier-terser
|
||||
```
|
||||
|
||||
You can also run `../setup.sh` from the repository root to install all
|
||||
prerequisites automatically.
|
||||
|
||||
## Script Usage
|
||||
|
||||
### Running the Scripts
|
||||
|
||||
1. **Ensure both `obfuscate_index.sh` and `obfuscate_nostr.sh` are available.**
|
||||
2. **Make the script executable:**
|
||||
```bash
|
||||
chmod +x obfuscate_index.sh obfuscate_nostr.sh
|
||||
```
|
||||
3. **Run the desired script:**
|
||||
```bash
|
||||
./obfuscate_index.sh or ./obfuscate_nostr.sh
|
||||
```
|
||||
|
||||
### Script Details
|
||||
|
||||
- **Input Files:** `obfuscate_index.sh` expects `index-master.html` and `obfuscate_nostr.sh` uses `nostr-master.html`.
|
||||
- **Output Files:** `obfuscate_index.sh` writes `index.html` and `obfuscate_nostr.sh` writes `nostr.html`.
|
||||
- **Error Handling:** Each script verifies that its input file exists before proceeding. Missing files result in an error.
|
||||
- **Terser and HTML-Minifier-Terser:** The script first uses Terser to obfuscate any embedded JavaScript, then minifies the entire HTML file, including embedded CSS and JavaScript.
|
||||
|
||||
### Script Example
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# Input and output file names
|
||||
input_file="index-master.html"
|
||||
output_file="index.html"
|
||||
|
||||
# Check if the input file exists
|
||||
if [ ! -f "$input_file" ]; then
|
||||
echo "Input file $input_file does not exist."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Obfuscate embedded JavaScript using terser
|
||||
terser_output=$(mktemp)
|
||||
terser --compress --mangle -- "$input_file" > "$terser_output"
|
||||
|
||||
# Minify HTML, including the embedded CSS and the obfuscated JavaScript
|
||||
html-minifier-terser \
|
||||
--collapse-whitespace \
|
||||
--minify-css true \
|
||||
--minify-js true \
|
||||
--remove-comments \
|
||||
--remove-empty-attributes \
|
||||
--output "$output_file" \
|
||||
"$terser_output"
|
||||
|
||||
# Clean up temporary file
|
||||
rm "$terser_output"
|
||||
|
||||
echo "Obfuscation and minification complete. Output saved as $output_file."
|
||||
```
|
||||
A similar script `obfuscate_nostr.sh` follows the same pattern but operates on `nostr-master.html` and outputs `nostr.html`.
|
||||
|
||||
## Editing the Script in Visual Studio Code (VSCode)
|
||||
|
||||
If you prefer to use Visual Studio Code to edit and run these scripts:
|
||||
|
||||
1. **Install VSCode:**
|
||||
- Follow the official [Visual Studio Code installation guide](https://code.visualstudio.com/docs/setup/linux) for Debian-based systems.
|
||||
|
||||
2. **Open your project in VSCode:**
|
||||
```bash
|
||||
code /path/to/your/project
|
||||
```
|
||||
|
||||
3. **Edit** `obfuscate_index.sh` or `obfuscate_nostr.sh` in the file explorer.
|
||||
|
||||
4. **Run the desired script** within the VSCode terminal:
|
||||
- Open the terminal in VSCode: `View > Terminal`.
|
||||
- Run the script:
|
||||
```bash
|
||||
./obfuscate_index.sh or ./obfuscate_nostr.sh
|
||||
```
|
||||
## Creating and Hosting a Flyer
|
||||
|
||||
The `voxvera` CLI automates filling `config.json`, building the HTML files, and copying everything into a new directory under `host/`.
|
||||
|
||||
### Usage
|
||||
|
||||
```bash
|
||||
# interactive mode
|
||||
voxvera init && voxvera build
|
||||
|
||||
# use an alternate config file
|
||||
voxvera init --config path/to/custom.json && voxvera build --config path/to/custom.json
|
||||
|
||||
# use an existing filled PDF form
|
||||
voxvera init --from-pdf path/to/form.pdf && voxvera build
|
||||
```
|
||||
|
||||
By default the script updates `src/config.json`. Use the `-c` option to specify a different file. After answering the prompts (or extracting from the PDF), `index.html` and `nostr.html` are generated and copied along with the QR code images and PDFs. The files end up in `host/<subdomain>` which can be served statically.
|
||||
|
||||
QR codes are built automatically during this process. After the configuration is updated, the CLI regenerates the QR codes by invoking `generate_qr.sh` to read the URLs from `config.json` and produce `qrcode-content.png` and `qrcode-tear-offs.png`.
|
12
voxvera/src/config.json
Normal file
12
voxvera/src/config.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "Vox Vera Printable Flyers",
|
||||
"subdomain": "voxvera",
|
||||
"title": "TOP SECRET",
|
||||
"subtitle": "DO <span class=\\\"redacted\\\">NOT</span> DISTRIBUTE",
|
||||
"headline": "OPERATION VOX VERA",
|
||||
"content": "Break free from censorship with VoxVera. An anonymous guerrilla marketing and message-spreading tool. Whether online or in the physical world, it can empower you to spread your ideas boldly, shielded by complete anonymity (if you host over Tor). Download the code, design a flyer site, host it online and amplify your message.\\n\\nUse memetic power to share your ideas in your school, workplace, online communities, or even globally. VoxVera ensures your message resonates far and wide, with tear-off sections featuring unique URLs and QR codes for easy reprinting.\\n\\nPrivacy can be maintained. Flyers can be shared via the Tor network, protecting hoster and users from censorship.\\n\\nJoin us in a revolution that values truth and transparency. Together, we can build a network of informed citizens who are unafraid to speak out.\n",
|
||||
"url_message": "Follow this link to learn more. Use Tor Browser.",
|
||||
"url": "https://voxvera.org/",
|
||||
"tear_off_link": "https://voxvera.org/",
|
||||
"binary_message": "0110010 0101011 0110010 0111101 0110100"
|
||||
}
|
10
voxvera/src/create_flyer.sh
Normal file
10
voxvera/src/create_flyer.sh
Normal file
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
# Legacy wrapper for voxvera Python CLI
|
||||
|
||||
set -e
|
||||
|
||||
if command -v voxvera >/dev/null 2>&1; then
|
||||
voxvera "$@"
|
||||
else
|
||||
python3 -m voxvera "$@"
|
||||
fi
|
BIN
voxvera/src/example.pdf
Normal file
BIN
voxvera/src/example.pdf
Normal file
Binary file not shown.
29
voxvera/src/generate_qr.sh
Normal file
29
voxvera/src/generate_qr.sh
Normal file
@@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
CONFIG="${1:-config.json}"
|
||||
|
||||
# Ensure dependencies
|
||||
command -v jq >/dev/null 2>&1 || { echo "jq is required" >&2; exit 1; }
|
||||
command -v qrencode >/dev/null 2>&1 || { echo "qrencode is required" >&2; exit 1; }
|
||||
command -v convert >/dev/null 2>&1 || { echo "ImageMagick convert is required" >&2; exit 1; }
|
||||
|
||||
url=$(jq -r '.url' "$CONFIG")
|
||||
tear=$(jq -r '.tear_off_link' "$CONFIG")
|
||||
|
||||
[ -n "$url" ] || { echo "URL missing in $CONFIG" >&2; exit 1; }
|
||||
[ -n "$tear" ] || { echo "tear_off_link missing in $CONFIG" >&2; exit 1; }
|
||||
|
||||
tmp_content=$(mktemp)
|
||||
tmp_tear=$(mktemp)
|
||||
|
||||
qrencode -o "$tmp_content" -s 10 -m 0 "$url"
|
||||
qrencode -o "$tmp_tear" -s 10 -m 0 "$tear"
|
||||
|
||||
convert "$tmp_content" -resize 128x128 "qrcode-content.png"
|
||||
convert "$tmp_tear" -resize 128x128 "qrcode-tear-offs.png"
|
||||
|
||||
rm -f "$tmp_content" "$tmp_tear"
|
||||
|
||||
echo "QR codes generated"
|
21
voxvera/src/import_from_json.sh
Normal file
21
voxvera/src/import_from_json.sh
Normal file
@@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
IMPORT_DIR="imports"
|
||||
shopt -s nullglob
|
||||
files=("$IMPORT_DIR"/*.json)
|
||||
|
||||
if [[ ${#files[@]} -eq 0 ]]; then
|
||||
echo "No JSON files found in $IMPORT_DIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
for json in "${files[@]}"; do
|
||||
echo "Processing $json"
|
||||
cp "$json" src/config.json
|
||||
subdomain=$(jq -r '.subdomain' "$json")
|
||||
dest="host/$subdomain"
|
||||
rm -rf "$dest"
|
||||
voxvera build --config src/config.json
|
||||
done
|
501
voxvera/src/index-master.html
Normal file
501
voxvera/src/index-master.html
Normal file
@@ -0,0 +1,501 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=1024, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
<title id="site-title">Vox Vera Printable Flyers</title> <!-- Title will be replaced -->
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #b80000;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
|
||||
.wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: 11in;
|
||||
width: 8.5in;
|
||||
border: 1px solid #000;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
|
||||
.print-button-container {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.print-button {
|
||||
padding: 10px 20px;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
.print-button:hover {
|
||||
background-color: #444;
|
||||
}
|
||||
|
||||
.download-button {
|
||||
padding: 10px 20px;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
.download-button:hover {
|
||||
background-color: #444;
|
||||
}
|
||||
|
||||
.left-tear-offs {
|
||||
width: 3.75in;
|
||||
padding: 8px;
|
||||
border-right: 1px dashed #000;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
gap: 5px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tear-off {
|
||||
display: flex;
|
||||
padding: 5px;
|
||||
border: 1px dashed #000;
|
||||
font-size: 10px;
|
||||
box-sizing: border-box;
|
||||
page-break-inside: avoid;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.tear-off-text {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.tear-off a {
|
||||
color: #b80000;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.tear-off a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.qr-code {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border: 0px solid #000;
|
||||
margin-left: 10px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.qr-code img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: calc(8.5in - 3.75in);
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
page-break-inside: avoid;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
margin-bottom: 10px;
|
||||
font-size: 24px;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.distribute {
|
||||
font-size: 18px;
|
||||
letter-spacing: 6px;
|
||||
}
|
||||
|
||||
.redacted {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.message {
|
||||
flex: 1;
|
||||
margin-top: 10px;
|
||||
font-size: 14px;
|
||||
line-height: 1.4;
|
||||
text-align: left;
|
||||
overflow-wrap: break-word;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
white-space: pre-wrap;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.text-container {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
outline: none;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 14px;
|
||||
line-height: 1.4;
|
||||
white-space: pre-wrap;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.qr-code-body {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 10px;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.qr-code-body img {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
object-fit: contain;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.qr-code-url {
|
||||
font-size: 12px;
|
||||
text-align: left;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
hyphens: auto;
|
||||
flex-grow: 1;
|
||||
margin-right: 10px;
|
||||
max-width: 60%;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: none;
|
||||
border-top: 1px solid #000;
|
||||
width: 100%;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.footer {
|
||||
font-size: 10px;
|
||||
overflow-wrap: break-word;
|
||||
text-align: center;
|
||||
align-self: center;
|
||||
width: 100%;
|
||||
padding: 10px 0;
|
||||
box-sizing: border-box;
|
||||
border-top: 1px solid #000;
|
||||
}
|
||||
|
||||
.footer p {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.footer .binary {
|
||||
margin-bottom: 5px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.footer .credit {
|
||||
font-size: 12px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
@media print {
|
||||
body, html {
|
||||
width: 8.5in;
|
||||
height: 11in;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.container {
|
||||
box-shadow: none;
|
||||
border: none;
|
||||
page-break-inside: avoid;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 8.5in;
|
||||
height: 11in;
|
||||
}
|
||||
|
||||
.print-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.download-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
body {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
.print-button {
|
||||
margin-top: 20px;
|
||||
padding: 10px 20px;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
.print-button:hover {
|
||||
background-color: #444;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="left-tear-offs">
|
||||
<div class="tear-off">
|
||||
<div class="tear-off-text">
|
||||
Use Tor Browser<br><br>
|
||||
to help spread this message go to<br>
|
||||
<a class="tear-off-link" href="#">Loading...</a><br> <!-- The class is used instead of an id -->
|
||||
click the button below to print
|
||||
</div>
|
||||
<div class="qr-code">
|
||||
<img src="qrcode-tear-offs.png" alt="QR Code">
|
||||
</div>
|
||||
</div>
|
||||
<div class="tear-off">
|
||||
<div class="tear-off-text">
|
||||
Use Tor Browser<br><br>
|
||||
to help spread this message go to<br>
|
||||
<a class="tear-off-link" href="#">Loading...</a><br> <!-- The class is used instead of an id -->
|
||||
click the button below to print
|
||||
</div>
|
||||
<div class="qr-code">
|
||||
<img src="qrcode-tear-offs.png" alt="QR Code">
|
||||
</div>
|
||||
</div>
|
||||
<div class="tear-off">
|
||||
<div class="tear-off-text">
|
||||
Use Tor Browser<br><br>
|
||||
to help spread this message go to<br>
|
||||
<a class="tear-off-link" href="#">Loading...</a><br> <!-- The class is used instead of an id -->
|
||||
click the button below to print
|
||||
</div>
|
||||
<div class="qr-code">
|
||||
<img src="qrcode-tear-offs.png" alt="QR Code">
|
||||
</div>
|
||||
</div>
|
||||
<div class="tear-off">
|
||||
<div class="tear-off-text">
|
||||
Use Tor Browser<br><br>
|
||||
to help spread this message go to<br>
|
||||
<a class="tear-off-link" href="#">Loading...</a><br> <!-- The class is used instead of an id -->
|
||||
click the button below to print
|
||||
</div>
|
||||
<div class="qr-code">
|
||||
<img src="qrcode-tear-offs.png" alt="QR Code">
|
||||
</div>
|
||||
</div>
|
||||
<div class="tear-off">
|
||||
<div class="tear-off-text">
|
||||
Use Tor Browser<br><br>
|
||||
to help spread this message go to<br>
|
||||
<a class="tear-off-link" href="#">Loading...</a><br> <!-- The class is used instead of an id -->
|
||||
click the button below to print
|
||||
</div>
|
||||
<div class="qr-code">
|
||||
<img src="qrcode-tear-offs.png" alt="QR Code">
|
||||
</div>
|
||||
</div>
|
||||
<div class="tear-off">
|
||||
<div class="tear-off-text">
|
||||
Use Tor Browser<br><br>
|
||||
to help spread this message go to<br>
|
||||
<a class="tear-off-link" href="#">Loading...</a><br> <!-- The class is used instead of an id -->
|
||||
click the button below to print
|
||||
</div>
|
||||
<div class="qr-code">
|
||||
<img src="qrcode-tear-offs.png" alt="QR Code">
|
||||
</div>
|
||||
</div>
|
||||
<div class="tear-off">
|
||||
<div class="tear-off-text">
|
||||
Use Tor Browser<br><br>
|
||||
to help spread this message go to<br>
|
||||
<a class="tear-off-link" href="#">Loading...</a><br> <!-- The class is used instead of an id -->
|
||||
click the button below to print
|
||||
</div>
|
||||
<div class="qr-code">
|
||||
<img src="qrcode-tear-offs.png" alt="QR Code">
|
||||
</div>
|
||||
</div>
|
||||
<div class="tear-off">
|
||||
<div class="tear-off-text">
|
||||
Use Tor Browser<br><br>
|
||||
to help spread this message go to<br>
|
||||
<a class="tear-off-link" href="#">Loading...</a><br> <!-- The class is used instead of an id -->
|
||||
click the button below to print
|
||||
</div>
|
||||
<div class="qr-code">
|
||||
<img src="qrcode-tear-offs.png" alt="QR Code">
|
||||
</div>
|
||||
</div>
|
||||
<div class="tear-off">
|
||||
<div class="tear-off-text">
|
||||
Use Tor Browser<br><br>
|
||||
to help spread this message go to<br>
|
||||
<a class="tear-off-link" href="#">Loading...</a><br> <!-- The class is used instead of an id -->
|
||||
click the button below to print
|
||||
</div>
|
||||
<div class="qr-code">
|
||||
<img src="qrcode-tear-offs.png" alt="QR Code">
|
||||
</div>
|
||||
</div>
|
||||
<div class="tear-off">
|
||||
<div class="tear-off-text">
|
||||
Use Tor Browser<br><br>
|
||||
to help spread this message go to<br>
|
||||
<a class="tear-off-link" href="#">Loading...</a><br> <!-- The class is used instead of an id -->
|
||||
click the button below to print
|
||||
</div>
|
||||
<div class="qr-code">
|
||||
<img src="qrcode-tear-offs.png" alt="QR Code">
|
||||
</div>
|
||||
</div>
|
||||
<!-- Repeat similar structure for other tear-offs -->
|
||||
</div>
|
||||
<div class="content">
|
||||
<h1 id="top-secret-title">Loading...</h1> <!-- "Top Secret" title will be replaced -->
|
||||
<div class="distribute" id="do-not-distribute">Loading...</div> <!-- "DO NOT DISTRIBUTE" message will be replaced -->
|
||||
<h1 id="operation-title-2"><br>Loading...</h1> <!-- "Operation Vox Vera" title will be replaced -->
|
||||
<hr>
|
||||
<div class="message">
|
||||
<div class="text-container" id="main-content" contenteditable="false"> <!-- Content will be replaced -->
|
||||
Loading content...
|
||||
</div>
|
||||
<div class="qr-code-body">
|
||||
<div class="qr-code-url">
|
||||
<span class="url-message">Loading message...</span><br><br> <!-- The message will be replaced -->
|
||||
<a id="qr-link-2" href="#">Loading...</a> <!-- The href and text will be replaced -->
|
||||
</div>
|
||||
<img src="qrcode-content.png" alt="QR Code">
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="footer">
|
||||
<p>
|
||||
spread your true voice just like this by filling out <a href="submission_form.pdf">this form</a><br>
|
||||
and submitting it to <a href="nostr.html">this Nostr Address</a>. We use <a href="https://nostr.how/en/what-is-nostr">Nostr</a>, <a href="https://www.torproject.org/download/">Tor Browser</a>, and <a href="https://wallet.cashu.me/">Cashu eCash</a> to protect your identity.<br>
|
||||
Your flyer will be hosted on <a href="https://en.wikipedia.org/wiki/Tor_(network)">The Tor Network</a>.<br>
|
||||
</p>
|
||||
<p class="credit">built with <a href="https://github.com/PR0M3TH3AN/VoxVera">voxvera</a></p>
|
||||
<p class="binary" id="binary-message"><br>
|
||||
<br>Loading...<br> <!-- Binary message will be replaced -->
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="print-button" onclick="window.print()">Print this page</button>
|
||||
<a class="download-button" href="download/download.zip" download>Download</a>
|
||||
|
||||
<script>
|
||||
// Fetch the configuration JSON file
|
||||
fetch('config.json')
|
||||
.then(response => response.json())
|
||||
.then(config => {
|
||||
// Update the site title
|
||||
document.getElementById('site-title').innerText = config.name;
|
||||
|
||||
// Update the "Top Secret" title
|
||||
document.getElementById('top-secret-title').innerText = config.title;
|
||||
|
||||
// Update the "DO NOT DISTRIBUTE" message
|
||||
document.getElementById('do-not-distribute').innerHTML = config.subtitle;
|
||||
|
||||
// Update the operation titles
|
||||
document.getElementById('operation-title-2').innerText = config.headline;
|
||||
|
||||
// Update the main content
|
||||
document.getElementById('main-content').innerText =
|
||||
config.content.replace(/\\n/g, '\n');
|
||||
|
||||
// Update the URL message
|
||||
document.querySelectorAll('.url-message').forEach(msg => {
|
||||
msg.innerText = config.url_message;
|
||||
});
|
||||
|
||||
// Update the QR URL link in the main content
|
||||
document.getElementById('qr-link-2').innerText = config.url;
|
||||
document.getElementById('qr-link-2').href = config.url;
|
||||
document.getElementById('qr-link-2').target = "_blank"; // Opens in a new tab
|
||||
|
||||
// Update all tear-off links
|
||||
document.querySelectorAll('.tear-off-link').forEach(link => {
|
||||
link.innerText = config.tear_off_link;
|
||||
link.href = config.tear_off_link;
|
||||
link.target = "_blank"; // Opens in a new tab
|
||||
});
|
||||
|
||||
// Update the binary message
|
||||
document.getElementById('binary-message').innerText = config.binary_message;
|
||||
})
|
||||
.catch(error => console.error('Error loading config:', error));
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
1
voxvera/src/index.html
Normal file
1
voxvera/src/index.html
Normal file
File diff suppressed because one or more lines are too long
102
voxvera/src/nostr-master.html
Normal file
102
voxvera/src/nostr-master.html
Normal file
@@ -0,0 +1,102 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Connect with Me on KeyChat</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100vh;
|
||||
margin: 0;
|
||||
background-color: white;
|
||||
}
|
||||
.container {
|
||||
background-color: white;
|
||||
padding: 20px;
|
||||
border: 1px solid #000000;
|
||||
text-align: center;
|
||||
max-width: 400px;
|
||||
width: 90%;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
h1 {
|
||||
color: #333;
|
||||
}
|
||||
p {
|
||||
font-size: 16px;
|
||||
color: #666;
|
||||
}
|
||||
.code-box {
|
||||
background-color: white;
|
||||
border: 1px solid #000000;
|
||||
padding: 10px;
|
||||
margin: 20px 0;
|
||||
font-size: 18px;
|
||||
color: #333;
|
||||
word-wrap: break-word;
|
||||
word-break: break-word;
|
||||
overflow-wrap: break-word;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
.copy-btn {
|
||||
background-color: #000000;
|
||||
color: white;
|
||||
padding: 10px 20px;
|
||||
border: 1px solid #000000;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
.copy-btn:hover {
|
||||
background-color: #3d3d3d;
|
||||
}
|
||||
footer {
|
||||
margin-top: 20px;
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.credit {
|
||||
font-size: 12px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
a {
|
||||
color: #a30000;
|
||||
text-decoration: none;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Nostr</h1>
|
||||
<p>Use a secure file shareing tool like <a href="https://onionshare.org/" target="_blank">Onion Share</a> or <a href="https://wormhole.app/" target="_blank">WormHole</a> to send your completed <a href="submission_form.pdf" target="_blank">submission form PDF</a> to the following <a href="https://www.0xchat.com/#/" target="_blank">Nostr</a> npub account:</p>
|
||||
<p></p><a href="index.html">Back to Home</a></p>
|
||||
<div class="code-box" id="keyChatCode">npub1ln8efl52vsyh6lg59c9v3kut56wev489lzcma0sv2mf8nm6jhwjqeteygt</div>
|
||||
<button class="copy-btn" onclick="copyCode()">Copy Code</button>
|
||||
</div>
|
||||
<footer>
|
||||
<p>Not on Nostr yet? <a href="https://nostr.how/en/what-is-nostr" target="_blank">Learn more here</a>.</p>
|
||||
<p class="credit">built with <a href="https://github.com/PR0M3TH3AN/VoxVera">voxvera</a></p>
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
function copyCode() {
|
||||
var copyText = document.getElementById("keyChatCode").innerText;
|
||||
navigator.clipboard.writeText(copyText).then(function() {
|
||||
alert("Code copied to clipboard!");
|
||||
}, function(err) {
|
||||
alert("Failed to copy code: ", err);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
1
voxvera/src/nostr.html
Normal file
1
voxvera/src/nostr.html
Normal file
@@ -0,0 +1 @@
|
||||
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Connect with Me on KeyChat</title><style>body{font-family:'Courier New',Courier,monospace;display:flex;flex-direction:column;align-items:center;justify-content:center;height:100vh;margin:0;background-color:#fff}.container{background-color:#fff;padding:20px;border:1px solid #000;text-align:center;max-width:400px;width:90%;box-shadow:0 0 10px rgba(0,0,0,.1)}h1{color:#333}p{font-size:16px;color:#666}.code-box{background-color:#fff;border:1px solid #000;padding:10px;margin:20px 0;font-size:18px;color:#333;word-wrap:break-word;word-break:break-word;overflow-wrap:break-word;cursor:pointer;user-select:none}.copy-btn{background-color:#000;color:#fff;padding:10px 20px;border:1px solid #000;cursor:pointer;font-size:16px;transition:background-color .3s ease}.copy-btn:hover{background-color:#3d3d3d}footer{margin-top:20px;font-size:14px;color:#999}.credit{font-size:12px;margin-top:10px}a{color:#a30000;text-decoration:none}a:hover{text-decoration:underline}</style></head><body><div class="container"><h1>Nostr</h1><p>Use a secure file shareing tool like <a href="https://onionshare.org/" target="_blank">Onion Share</a> or <a href="https://wormhole.app/" target="_blank">WormHole</a> to send your completed <a href="submission_form.pdf" target="_blank">submission form PDF</a> to the following <a href="https://www.0xchat.com/#/" target="_blank">Nostr</a> npub account:</p><p></p><a href="index.html">Back to Home</a><p></p><div class="code-box" id="keyChatCode">npub1ln8efl52vsyh6lg59c9v3kut56wev489lzcma0sv2mf8nm6jhwjqeteygt</div><button class="copy-btn" onclick="copyCode()">Copy Code</button></div><footer><p>Not on Nostr yet? <a href="https://nostr.how/en/what-is-nostr" target="_blank">Learn more here</a>.</p><p class="credit">built with <a href="https://github.com/PR0M3TH3AN/VoxVera">voxvera</a></p></footer><script>function a0_0x55b4(){var _0xeeb36b=['Failed\x20to\x20copy\x20code:\x20','36973gPfEDk','3hjGEPG','keyChatCode','clipboard','2471RXzkOy','2005220SDqWBz','then','8464mvqASw','24965hDeypK','468jCVegU','3143720lhnwYU','innerText','Code\x20copied\x20to\x20clipboard!','2722248cDzJJD','9411952bWAcnc','2gKXLTl'];a0_0x55b4=function(){return _0xeeb36b;};return a0_0x55b4();}function a0_0x2f09(_0x591295,_0x18ad6e){var _0x55b435=a0_0x55b4();return a0_0x2f09=function(_0x2f098f,_0x3b879c){_0x2f098f=_0x2f098f-0x103;var _0x38cd8a=_0x55b435[_0x2f098f];return _0x38cd8a;},a0_0x2f09(_0x591295,_0x18ad6e);}(function(_0x460aa5,_0xdd901b){var _0x26f888=a0_0x2f09,_0x58db54=_0x460aa5();while(!![]){try{var _0x40318b=parseInt(_0x26f888(0x10d))/0x1*(parseInt(_0x26f888(0x10b))/0x2)+-parseInt(_0x26f888(0x10e))/0x3*(-parseInt(_0x26f888(0x112))/0x4)+parseInt(_0x26f888(0x104))/0x5*(parseInt(_0x26f888(0x105))/0x6)+parseInt(_0x26f888(0x111))/0x7*(-parseInt(_0x26f888(0x103))/0x8)+parseInt(_0x26f888(0x109))/0x9+parseInt(_0x26f888(0x106))/0xa+-parseInt(_0x26f888(0x10a))/0xb;if(_0x40318b===_0xdd901b)break;else _0x58db54['push'](_0x58db54['shift']());}catch(_0x5c0367){_0x58db54['push'](_0x58db54['shift']());}}}(a0_0x55b4,0x4d04e));function copyCode(){var _0x263cfe=a0_0x2f09,_0x201a80=document['getElementById'](_0x263cfe(0x10f))[_0x263cfe(0x107)];navigator[_0x263cfe(0x110)]['writeText'](_0x201a80)[_0x263cfe(0x113)](function(){var _0x2c37ce=_0x263cfe;alert(_0x2c37ce(0x108));},function(_0x3011e9){var _0x5238cb=_0x263cfe;alert(_0x5238cb(0x10c),_0x3011e9);});}</script></body></html>
|
67
voxvera/src/obfuscate_index.sh
Normal file
67
voxvera/src/obfuscate_index.sh
Normal file
@@ -0,0 +1,67 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
CONFIG_PATH="${1:-config.json}"
|
||||
|
||||
require_cmd() {
|
||||
command -v "$1" >/dev/null 2>&1 || {
|
||||
echo "Error: required command '$1' not found" >&2
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
for cmd in javascript-obfuscator html-minifier-terser node; do
|
||||
require_cmd "$cmd"
|
||||
done
|
||||
|
||||
# Detect whether mktemp supports the --suffix option. If not, fall back to a
|
||||
# portable template-based approach (e.g., on macOS).
|
||||
if tmp=$(mktemp --suffix=.test 2>/dev/null); then
|
||||
rm -f "$tmp"
|
||||
mktemp_with_suffix() { mktemp --suffix="$1"; }
|
||||
else
|
||||
mktemp_with_suffix() { mktemp "${TMPDIR:-/tmp}/tmp.XXXXXX$1"; }
|
||||
fi
|
||||
|
||||
# Input and output file names
|
||||
input_file="index-master.html"
|
||||
output_file="index.html"
|
||||
temp_js_file=$(mktemp_with_suffix .js) # Temporary .js file for extracting JavaScript
|
||||
temp_js_obfuscated_file=$(mktemp_with_suffix .js) # Temporary file for obfuscated JavaScript
|
||||
temp_html_file=$(mktemp) # Temporary file for processing HTML without JS
|
||||
|
||||
# Check if the input file exists
|
||||
if [ ! -f "$input_file" ]; then
|
||||
echo "Input file $input_file does not exist."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Extract embedded JavaScript into a temporary .js file
|
||||
awk '/<script>/,/<\/script>/' "$input_file" | sed '1d;$d' > "$temp_js_file"
|
||||
|
||||
# Obfuscate the extracted JavaScript
|
||||
javascript-obfuscator "$temp_js_file" --output "$temp_js_obfuscated_file"
|
||||
|
||||
# Read the obfuscated JavaScript into a variable
|
||||
obfuscated_js=$(cat "$temp_js_obfuscated_file")
|
||||
|
||||
# Escape slashes in the obfuscated JavaScript
|
||||
escaped_js=$(echo "$obfuscated_js" | sed 's/[\/&]/\\&/g')
|
||||
|
||||
# Replace the original JavaScript in the HTML with the obfuscated version
|
||||
sed -e "/<script>/,/<\/script>/c\<script>$escaped_js<\/script>" "$input_file" > "$temp_html_file"
|
||||
|
||||
# Minify HTML, including the obfuscated embedded JavaScript and CSS
|
||||
html-minifier-terser \
|
||||
--collapse-whitespace \
|
||||
--minify-css true \
|
||||
--remove-comments \
|
||||
--remove-empty-attributes \
|
||||
--output "$output_file" \
|
||||
"$temp_html_file"
|
||||
|
||||
# Clean up temporary files
|
||||
rm "$temp_js_file" "$temp_js_obfuscated_file" "$temp_html_file"
|
||||
|
||||
echo "Obfuscation and minification complete. Output saved as $output_file."
|
67
voxvera/src/obfuscate_nostr.sh
Normal file
67
voxvera/src/obfuscate_nostr.sh
Normal file
@@ -0,0 +1,67 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
CONFIG_PATH="${1:-config.json}"
|
||||
|
||||
require_cmd() {
|
||||
command -v "$1" >/dev/null 2>&1 || {
|
||||
echo "Error: required command '$1' not found" >&2
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
for cmd in javascript-obfuscator html-minifier-terser node; do
|
||||
require_cmd "$cmd"
|
||||
done
|
||||
|
||||
# Detect whether mktemp supports the --suffix option. If not, fall back to a
|
||||
# portable template-based approach (e.g., on macOS).
|
||||
if tmp=$(mktemp --suffix=.test 2>/dev/null); then
|
||||
rm -f "$tmp"
|
||||
mktemp_with_suffix() { mktemp --suffix="$1"; }
|
||||
else
|
||||
mktemp_with_suffix() { mktemp "${TMPDIR:-/tmp}/tmp.XXXXXX$1"; }
|
||||
fi
|
||||
|
||||
# Input and output file names
|
||||
input_file="nostr-master.html"
|
||||
output_file="nostr.html"
|
||||
temp_js_file=$(mktemp_with_suffix .js) # Temporary .js file for extracting JavaScript
|
||||
temp_js_obfuscated_file=$(mktemp_with_suffix .js) # Temporary file for obfuscated JavaScript
|
||||
temp_html_file=$(mktemp) # Temporary file for processing HTML without JS
|
||||
|
||||
# Check if the input file exists
|
||||
if [ ! -f "$input_file" ]; then
|
||||
echo "Input file $input_file does not exist."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Extract embedded JavaScript into a temporary .js file
|
||||
awk '/<script>/,/<\/script>/' "$input_file" | sed '1d;$d' > "$temp_js_file"
|
||||
|
||||
# Obfuscate the extracted JavaScript
|
||||
javascript-obfuscator "$temp_js_file" --output "$temp_js_obfuscated_file"
|
||||
|
||||
# Read the obfuscated JavaScript into a variable
|
||||
obfuscated_js=$(cat "$temp_js_obfuscated_file")
|
||||
|
||||
# Escape slashes in the obfuscated JavaScript
|
||||
escaped_js=$(echo "$obfuscated_js" | sed 's/[\/&]/\\&/g')
|
||||
|
||||
# Replace the original JavaScript in the HTML with the obfuscated version
|
||||
sed -e "/<script>/,/<\/script>/c\<script>$escaped_js<\/script>" "$input_file" > "$temp_html_file"
|
||||
|
||||
# Minify HTML, including the obfuscated embedded JavaScript and CSS
|
||||
html-minifier-terser \
|
||||
--collapse-whitespace \
|
||||
--minify-css true \
|
||||
--remove-comments \
|
||||
--remove-empty-attributes \
|
||||
--output "$output_file" \
|
||||
"$temp_html_file"
|
||||
|
||||
# Clean up temporary files
|
||||
rm "$temp_js_file" "$temp_js_obfuscated_file" "$temp_html_file"
|
||||
|
||||
echo "Obfuscation and minification complete. Output saved as $output_file."
|
BIN
voxvera/src/qrcode-content.png
Normal file
BIN
voxvera/src/qrcode-content.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
BIN
voxvera/src/qrcode-tear-offs.png
Normal file
BIN
voxvera/src/qrcode-tear-offs.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
BIN
voxvera/src/submission_form.docx
Normal file
BIN
voxvera/src/submission_form.docx
Normal file
Binary file not shown.
BIN
voxvera/src/submission_form.oform
Normal file
BIN
voxvera/src/submission_form.oform
Normal file
Binary file not shown.
BIN
voxvera/src/submission_form.pdf
Normal file
BIN
voxvera/src/submission_form.pdf
Normal file
Binary file not shown.
2
voxvera/src/to-do.txt
Normal file
2
voxvera/src/to-do.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
1. Make content field smaller max number.
|
||||
2. URL for content not getting pulled into the config.json correctly every time.
|
117
voxvera/templates/blank/extract_form_fields.sh
Normal file
117
voxvera/templates/blank/extract_form_fields.sh
Normal file
@@ -0,0 +1,117 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Define the input PDF, output text file, and output JSON
|
||||
pdf_file="./from_client/submission_form.pdf"
|
||||
text_file="submission_form.txt"
|
||||
json_file="config.json"
|
||||
|
||||
# Log the start of the script
|
||||
echo "Starting script..."
|
||||
echo "Looking for PDF at: $pdf_file"
|
||||
echo "Config JSON: $json_file"
|
||||
|
||||
# Convert PDF to text
|
||||
echo "Converting PDF to text..."
|
||||
pdftotext -layout "$pdf_file" "$text_file"
|
||||
|
||||
# Extract individual fields using grep, logging each step
|
||||
echo "Extracting fields from the text file..."
|
||||
|
||||
# Adjusting the extraction of the name field
|
||||
name=$(grep -A 3 'name (max 25 characters):' "$text_file" | tail -n 1 | awk '{$1=$1;print}')
|
||||
echo "Extracted name: '$name'"
|
||||
|
||||
subdomain=$(grep -A 1 'subdomain (max 30 characters):' "$text_file" | tail -n 1 | awk '{$1=$1;print}')
|
||||
echo "Extracted subdomain: '$subdomain'"
|
||||
|
||||
title=$(grep -A 1 'title (max 30 characters):' "$text_file" | tail -n 1 | awk '{$1=$1;print}')
|
||||
echo "Extracted title: '$title'"
|
||||
|
||||
subtitle=$(grep -A 1 'subtitle (max 45 characters):' "$text_file" | tail -n 1 | awk '{$1=$1;print}')
|
||||
echo "Extracted subtitle: '$subtitle'"
|
||||
|
||||
headline=$(grep -A 1 'headline (max 50 characters):' "$text_file" | tail -n 1 | awk '{$1=$1;print}')
|
||||
echo "Extracted headline: '$headline'"
|
||||
|
||||
# Process the content to remove soft wraps while keeping hard returns
|
||||
content=$(grep -A 100 'content (max 1,400 characters):' "$text_file" | sed -n '2,/url_message/p' | sed '$d' | awk '
|
||||
{
|
||||
if (NR == 1) {
|
||||
prev = $0;
|
||||
next;
|
||||
}
|
||||
|
||||
# Handle paragraph breaks explicitly
|
||||
if ($0 ~ /^[[:space:]]*$/) {
|
||||
if (prev) print prev "\n";
|
||||
prev = "";
|
||||
}
|
||||
# Handle sentences that should stay together
|
||||
else if (prev ~ /[.?!]$/ && $0 ~ /^[[:upper:]]/) {
|
||||
prev = prev " " $0;
|
||||
}
|
||||
# Join lines that are part of the same sentence (soft wrap)
|
||||
else if (prev !~ /[.?!]$/) {
|
||||
prev = prev " " $0;
|
||||
}
|
||||
# Otherwise, treat as a new sentence/paragraph
|
||||
else {
|
||||
if (prev) print prev;
|
||||
prev = $0;
|
||||
}
|
||||
}
|
||||
END { if (prev) print prev }' | sed -E 's/\n\n[[:space:]]+/\n\n/g' | sed -E 's/^[[:space:]]+//g')
|
||||
|
||||
echo "Extracted content: '$content'"
|
||||
|
||||
url_message=$(grep -A 1 'url_message (max 60 characters):' "$text_file" | tail -n 1 | awk '{$1=$1;print}')
|
||||
echo "Extracted url_message: '$url_message'"
|
||||
|
||||
url=$(grep -A 1 'url (max 90 characters):' "$text_file" | tail -n 1 | awk '{$1=$1;print}')
|
||||
echo "Extracted url: '$url'"
|
||||
|
||||
# Construct the URLs with the subdomain
|
||||
onion_base="6dshf2gnj7yzxlfcaczlyi57up4mvbtd5orinuj5bjsfycnhz2w456yd.onion"
|
||||
constructed_url="http://$subdomain.$onion_base"
|
||||
|
||||
# Use an existing tear_off_link from the config if provided; otherwise default
|
||||
# to the constructed onion URL.
|
||||
existing_tear_off_link=$(jq -r '.tear_off_link // empty' "$json_file")
|
||||
tear_off_link="${existing_tear_off_link:-http://$subdomain.$onion_base}"
|
||||
|
||||
echo "Constructed URL: '$constructed_url'"
|
||||
echo "Using Tear-off Link: '$tear_off_link'"
|
||||
|
||||
# Check if the extracted fields are not empty
|
||||
if [ -z "$name" ] || [ -z "$subdomain" ] || [ -z "$title" ] || [ -z "$subtitle" ] || [ -z "$headline" ] || [ -z "$content" ] || [ -z "$url_message" ] || [ -z "$url" ]; then
|
||||
echo "Error: One or more extracted fields are empty. Please check the PDF form and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Update the JSON using jq and log the operation
|
||||
echo "Updating config.json..."
|
||||
jq --arg name "$name" \
|
||||
--arg subdomain "$subdomain" \
|
||||
--arg title "$title" \
|
||||
--arg subtitle "$subtitle" \
|
||||
--arg headline "$headline" \
|
||||
--arg content "$content" \
|
||||
--arg url_message "$url_message" \
|
||||
--arg url "$url" \
|
||||
--arg tear_off_link "$tear_off_link" \
|
||||
'.name = $name |
|
||||
.subdomain = $subdomain |
|
||||
.title = $title |
|
||||
.subtitle = $subtitle |
|
||||
.headline = $headline |
|
||||
.content = $content |
|
||||
.url_message = $url_message |
|
||||
.url = $url |
|
||||
.tear_off_link = $tear_off_link' "$json_file" > tmp.json && mv tmp.json "$json_file"
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "Config file updated successfully."
|
||||
else
|
||||
echo "Error: Failed to update config file."
|
||||
exit 1
|
||||
fi
|
12
voxvera/templates/voxvera/config.json
Normal file
12
voxvera/templates/voxvera/config.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "Vox Vera Printable Flyers",
|
||||
"subdomain": "voxvera",
|
||||
"title": "TOP SECRET",
|
||||
"subtitle": "DO <span class=\\\"redacted\\\">NOT</span> DISTRIBUTE",
|
||||
"headline": "OPERATION VOX VERA",
|
||||
"content": "Break free from censorship with VoxVera. An anonymous guerrilla marketing and message-spreading tool. Whether online or in the physical world, it can empower you to spread your ideas boldly, shielded by complete anonymity (if you host over Tor). Download the code, design a flyer site, host it online and amplify your message.\\n\\nUse memetic power to share your ideas in your school, workplace, online communities, or even globally. VoxVera ensures your message resonates far and wide, with tear-off sections featuring unique URLs and QR codes for easy reprinting.\\n\\nPrivacy can be maintained. Flyers can be shared via the Tor network, protecting hoster and users from censorship.\\n\\nJoin us in a revolution that values truth and transparency. Together, we can build a network of informed citizens who are unafraid to speak out.\n",
|
||||
"url_message": "Follow this link to learn more. Use Tor Browser.",
|
||||
"url": "https://voxvera.org/",
|
||||
"tear_off_link": "https://voxvera.org/",
|
||||
"binary_message": "0110010 0101011 0110010 0111101 0110100"
|
||||
}
|
0
voxvera/templates/voxvera/download/.gitkeep
Normal file
0
voxvera/templates/voxvera/download/.gitkeep
Normal file
BIN
voxvera/templates/voxvera/example.pdf
Normal file
BIN
voxvera/templates/voxvera/example.pdf
Normal file
Binary file not shown.
1
voxvera/templates/voxvera/index.html
Normal file
1
voxvera/templates/voxvera/index.html
Normal file
File diff suppressed because one or more lines are too long
1
voxvera/templates/voxvera/nostr.html
Normal file
1
voxvera/templates/voxvera/nostr.html
Normal file
@@ -0,0 +1 @@
|
||||
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Connect with Me on KeyChat</title><style>body{font-family:'Courier New',Courier,monospace;display:flex;flex-direction:column;align-items:center;justify-content:center;height:100vh;margin:0;background-color:#fff}.container{background-color:#fff;padding:20px;border:1px solid #000;text-align:center;max-width:400px;width:90%;box-shadow:0 0 10px rgba(0,0,0,.1)}h1{color:#333}p{font-size:16px;color:#666}.code-box{background-color:#fff;border:1px solid #000;padding:10px;margin:20px 0;font-size:18px;color:#333;word-wrap:break-word;word-break:break-word;overflow-wrap:break-word;cursor:pointer;user-select:none}.copy-btn{background-color:#000;color:#fff;padding:10px 20px;border:1px solid #000;cursor:pointer;font-size:16px;transition:background-color .3s ease}.copy-btn:hover{background-color:#3d3d3d}footer{margin-top:20px;font-size:14px;color:#999}.credit{font-size:12px;margin-top:10px}a{color:#a30000;text-decoration:none}a:hover{text-decoration:underline}</style></head><body><div class="container"><h1>Nostr</h1><p>Use a secure file shareing tool like <a href="https://onionshare.org/" target="_blank">Onion Share</a> or <a href="https://wormhole.app/" target="_blank">WormHole</a> to send your completed <a href="submission_form.pdf" target="_blank">submission form PDF</a> to the following <a href="https://www.0xchat.com/#/" target="_blank">Nostr</a> npub account:</p><p></p><a href="index.html">Back to Home</a><p></p><div class="code-box" id="keyChatCode">npub1ln8efl52vsyh6lg59c9v3kut56wev489lzcma0sv2mf8nm6jhwjqeteygt</div><button class="copy-btn" onclick="copyCode()">Copy Code</button></div><footer><p>Not on Nostr yet? <a href="https://nostr.how/en/what-is-nostr" target="_blank">Learn more here</a>.</p><p class="credit">Flyer generated with <a href="https://github.com/PR0M3TH3AN/VoxVera">Vox Vera</a>.</p></footer><script>function a0_0x55b4(){var _0xeeb36b=['Failed\x20to\x20copy\x20code:\x20','36973gPfEDk','3hjGEPG','keyChatCode','clipboard','2471RXzkOy','2005220SDqWBz','then','8464mvqASw','24965hDeypK','468jCVegU','3143720lhnwYU','innerText','Code\x20copied\x20to\x20clipboard!','2722248cDzJJD','9411952bWAcnc','2gKXLTl'];a0_0x55b4=function(){return _0xeeb36b;};return a0_0x55b4();}function a0_0x2f09(_0x591295,_0x18ad6e){var _0x55b435=a0_0x55b4();return a0_0x2f09=function(_0x2f098f,_0x3b879c){_0x2f098f=_0x2f098f-0x103;var _0x38cd8a=_0x55b435[_0x2f098f];return _0x38cd8a;},a0_0x2f09(_0x591295,_0x18ad6e);}(function(_0x460aa5,_0xdd901b){var _0x26f888=a0_0x2f09,_0x58db54=_0x460aa5();while(!![]){try{var _0x40318b=parseInt(_0x26f888(0x10d))/0x1*(parseInt(_0x26f888(0x10b))/0x2)+-parseInt(_0x26f888(0x10e))/0x3*(-parseInt(_0x26f888(0x112))/0x4)+parseInt(_0x26f888(0x104))/0x5*(parseInt(_0x26f888(0x105))/0x6)+parseInt(_0x26f888(0x111))/0x7*(-parseInt(_0x26f888(0x103))/0x8)+parseInt(_0x26f888(0x109))/0x9+parseInt(_0x26f888(0x106))/0xa+-parseInt(_0x26f888(0x10a))/0xb;if(_0x40318b===_0xdd901b)break;else _0x58db54['push'](_0x58db54['shift']());}catch(_0x5c0367){_0x58db54['push'](_0x58db54['shift']());}}}(a0_0x55b4,0x4d04e));function copyCode(){var _0x263cfe=a0_0x2f09,_0x201a80=document['getElementById'](_0x263cfe(0x10f))[_0x263cfe(0x107)];navigator[_0x263cfe(0x110)]['writeText'](_0x201a80)[_0x263cfe(0x113)](function(){var _0x2c37ce=_0x263cfe;alert(_0x2c37ce(0x108));},function(_0x3011e9){var _0x5238cb=_0x263cfe;alert(_0x5238cb(0x10c),_0x3011e9);});}</script></body></html>
|
BIN
voxvera/templates/voxvera/qrcode-content.png
Normal file
BIN
voxvera/templates/voxvera/qrcode-content.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
BIN
voxvera/templates/voxvera/qrcode-tear-offs.png
Normal file
BIN
voxvera/templates/voxvera/qrcode-tear-offs.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
BIN
voxvera/templates/voxvera/submission_form.pdf
Normal file
BIN
voxvera/templates/voxvera/submission_form.pdf
Normal file
Binary file not shown.
Reference in New Issue
Block a user