Compare commits
2 commits
Author | SHA1 | Date | |
---|---|---|---|
1f43b3b5c7 | |||
b793711537 |
142 changed files with 628 additions and 664 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,5 +1,4 @@
|
|||
.DS_Store
|
||||
.htpasswd
|
||||
werc/etc/*
|
||||
scripts/commands.txt
|
||||
.env
|
||||
transfer/uploads/*
|
||||
|
|
|
@ -34,9 +34,7 @@ services:
|
|||
container_name: transfer
|
||||
ports:
|
||||
- "3880:8080"
|
||||
command: ["--provider", "local", "--basedir", "/uploads/", "--web-path", "/web/", "--max-upload-size", "10485760"]
|
||||
environment:
|
||||
- MAX_UPLOAD_SIZE=10485760
|
||||
command: ["--provider", "local", "--basedir", "/uploads/", "--web-path", "/web/"]
|
||||
volumes:
|
||||
- ./transfer/uploads:/uploads
|
||||
- ./transfer/tshweb:/web
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
SUBDOMAINS=("thirdculture.top" "ppl.thirdculture.top" "files.thirdculture.top" "up.thirdculture.top"
|
||||
"events.thirdculture.top" "music.thirdculture.top" "social.thirdculture.top" "visual.thirdculture.top")
|
||||
HOSTS_FILE="/etc/hosts"
|
||||
|
||||
add_subdomains() {
|
||||
echo "Adding subdomains to /etc/hosts..."
|
||||
for SUBDOMAIN in "${SUBDOMAINS[@]}"; do
|
||||
if ! grep -q "$SUBDOMAIN" "$HOSTS_FILE"; then
|
||||
echo "127.0.0.1 $SUBDOMAIN" | sudo tee -a "$HOSTS_FILE" > /dev/null
|
||||
echo "Added $SUBDOMAIN to /etc/hosts"
|
||||
else
|
||||
echo "$SUBDOMAIN is already in /etc/hosts"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
remove_subdomains() {
|
||||
echo "Removing subdomains from /etc/hosts..."
|
||||
for SUBDOMAIN in "${SUBDOMAINS[@]}"; do
|
||||
sudo sed -i "/$SUBDOMAIN/d" "$HOSTS_FILE"
|
||||
echo "Removed $SUBDOMAIN from /etc/hosts"
|
||||
done
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
add)
|
||||
add_subdomains
|
||||
;;
|
||||
remove)
|
||||
remove_subdomains
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {add|remove}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
|
@ -15,9 +15,9 @@ mkdir -p "$path/$name/_werc" "$path/$name/blog/_werc"
|
|||
|
||||
# Create the first config file (not under blog)
|
||||
cat > "$path/$name/_werc/config" <<EOF
|
||||
extraHeaders='<link rel="stylesheet" type="text/css" href="_werc/style.css">'
|
||||
conf_enable_wiki
|
||||
conf_enable_cssedit $name
|
||||
wiki_editors_groups=$name
|
||||
css_file='_werc/style.css'
|
||||
EOF
|
||||
|
||||
|
@ -27,32 +27,12 @@ conf_enable_wiki
|
|||
conf_enable_blog
|
||||
conf_blog_only_pull=0
|
||||
conf_blog_editors=$name
|
||||
wiki_editors_groups=$name
|
||||
blogTitle=''
|
||||
blogTitle='$name Feed'
|
||||
blogDesc=''
|
||||
EOF
|
||||
|
||||
# Create the style.css file
|
||||
echo "/* Put custom styles here */" > "$path/$name/_werc/style.css"
|
||||
|
||||
# Update index.html
|
||||
index_file="$path/index.html"
|
||||
|
||||
if [ -f "$index_file" ]; then
|
||||
awk -v name="$name" '
|
||||
{
|
||||
print
|
||||
if ($0 ~ /<!-- BUTTONS -->/) {
|
||||
print " <div class=\"grid-item\">"
|
||||
print " <a href=\"/" name "/\"><img src=\"/_werc/pub/img/but/" name ".gif\" alt=\"" name "\" /></a>"
|
||||
print " </div>"
|
||||
print ""
|
||||
}
|
||||
}' "$index_file" > "${index_file}.tmp" && mv "${index_file}.tmp" "$index_file"
|
||||
echo "Updated index.html with new user entry"
|
||||
else
|
||||
echo "Warning: index.html not found at $index_file"
|
||||
fi
|
||||
|
||||
# Output a success message
|
||||
echo "Folder structure created successfully at $path/$name"
|
||||
|
|
|
@ -1,100 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
CONFIG_FILE="${CONFIG_FILE:-./.env/onboard.env}"
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
echo "Error: Configuration file not found at $CONFIG_FILE"
|
||||
echo "CONFIG_FILE unset or .env/onboard.env does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source "$CONFIG_FILE"
|
||||
|
||||
usage() {
|
||||
cat << EOF
|
||||
Usage: $0 <username> <mkpasswd_hash> <htpasswd_hash>
|
||||
|
||||
Arguments:
|
||||
username The username for the new account
|
||||
mkpasswd_hash The hash generated by mkpasswd
|
||||
htpasswd_hash The hash generated by htpasswd
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
validate_input() {
|
||||
|
||||
[ $# -ne 3 ] && usage
|
||||
[[ ! "$2" =~ ^\$6\$ ]] && echo "Error: Invalid mkpasswd hash format" && exit 1
|
||||
[[ ! "$3" =~ ^\$apr1\$ ]] && echo "Error: Invalid htpasswd hash format" && exit 1
|
||||
|
||||
local required_vars=(
|
||||
"SSH_USER" "SSH_HOST" "CONTAINER_NAME" "DOMAIN" "SERVICES_URL"
|
||||
"USER_STRUCTURE_PATH" "WERC_PATH" "HTPASSWD_FILE"
|
||||
)
|
||||
|
||||
for var in "${required_vars[@]}"; do
|
||||
if [ -z "${!var}" ]; then
|
||||
echo "Error: Required variable $var is not set in $CONFIG_FILE"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
[ ! -d "$USER_STRUCTURE_PATH" ] && echo "Error: User structure path does not exist: $USER_STRUCTURE_PATH" && exit 1
|
||||
[ ! -d "$WERC_PATH" ] && echo "Error: Werc path does not exist: $WERC_PATH" && exit 1
|
||||
|
||||
}
|
||||
|
||||
create_user_structure() {
|
||||
local username="$1"
|
||||
local mkpasswd_hash="$2"
|
||||
local user_path="$USER_STRUCTURE_PATH/$username"
|
||||
mkdir -p "$user_path"
|
||||
echo "$mkpasswd_hash" > "$user_path/password"
|
||||
echo "$username:$3" >> "$HTPASSWD_FILE"
|
||||
}
|
||||
|
||||
setup_werc_structure() {
|
||||
local username="$1"
|
||||
./add_person.sh "$WERC_PATH" "$username"
|
||||
}
|
||||
|
||||
generate_invite() {
|
||||
invite=$(ssh "$SSH_USER@$SSH_HOST" "docker exec $CONTAINER_NAME prosodyctl mod_invites generate $DOMAIN" | tail -n 1)
|
||||
[ -z "$invite" ] && echo "Error: Failed to generate invite" && exit 1
|
||||
}
|
||||
|
||||
main() {
|
||||
local username="$1"
|
||||
local mkpasswd_hash="$2"
|
||||
local htpasswd_hash="$3"
|
||||
|
||||
validate_input "$@"
|
||||
|
||||
echo "Setting up user structure..."
|
||||
create_user_structure "$username" "$mkpasswd_hash" "$htpasswd_hash"
|
||||
|
||||
echo "Setting up werc structure..."
|
||||
setup_werc_structure "$username"
|
||||
|
||||
echo "Generating invite..."
|
||||
generate_invite
|
||||
|
||||
cat << EOF
|
||||
User setup completed successfully!
|
||||
Username: $username
|
||||
Services URL: $SERVICES_URL
|
||||
Invite link: $invite
|
||||
|
||||
The following paths have been updated:
|
||||
- User structure: $USER_STRUCTURE_PATH/$username
|
||||
- Werc structure: $WERC_PATH/$username
|
||||
- Password file: $USER_STRUCTURE_PATH/$username/password
|
||||
- Updated .htpasswd at: $HTPASSWD_FILE
|
||||
|
||||
Next steps:
|
||||
1. Push changes to server
|
||||
2. Send the services URL and invite link to the user
|
||||
EOF
|
||||
}
|
||||
|
||||
main "$@"
|
7
transfer/tshweb/go.mod
Normal file
7
transfer/tshweb/go.mod
Normal file
|
@ -0,0 +1,7 @@
|
|||
module filetransfer
|
||||
|
||||
go 1.23.1
|
||||
|
||||
require github.com/aws/aws-sdk-go v1.55.5
|
||||
|
||||
require github.com/jmespath/go-jmespath v0.4.0 // indirect
|
14
transfer/tshweb/go.sum
Normal file
14
transfer/tshweb/go.sum
Normal file
|
@ -0,0 +1,14 @@
|
|||
github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU=
|
||||
github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
@ -1,37 +1,78 @@
|
|||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Third Culture Upload</title>
|
||||
<link rel="stylesheet" href="styles/main.css" />
|
||||
</head>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Third Culture Upload</title>
|
||||
<link rel="stylesheet" href="styles/main.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1><span class="accent">Third Culture</span> Upload</h1>
|
||||
<form action="https://up.thirdculture.top" method="POST" enctype="multipart/form-data">
|
||||
<label for="fileInput">Choose file:</label>
|
||||
<input type="file" name="file" id="fileInput" required />
|
||||
<br><br>
|
||||
<button type="submit">Upload</button>
|
||||
</form>
|
||||
<p><br></p>
|
||||
<p>Make sure to copy the link in the next page!</p>
|
||||
<p>More info on third culture upload <a href="scripts/info.html">here</a>.</p>
|
||||
<p><br></p>
|
||||
<svg version="1.1" style="fill:none;width:75px;height:75px;" width="50" height="50" viewBox="0 0 50 50" id="svg3" sodipodi:docname="logo.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs id="defs3" />
|
||||
<path style="fill:#000000;stroke:#000000;stroke-width:1.51515px;stroke-linecap:round;stroke-linejoin:round"
|
||||
d="m 0.75757498,49.242423 v 0 V 0.75757498 H 49.242425 V 49.242423 Z" id="path1" />
|
||||
<path style="fill:none;stroke:#a4d1ad;stroke-width:1.51515px;stroke-linecap:round;stroke-linejoin:round"
|
||||
d="m 20.454546,38.636362 v 0 l 9.090908,-9.090909 m -9.090908,0 v 0 l 9.090908,9.090909" id="path2" />
|
||||
<path style="fill:none;stroke:#aea3f0;stroke-width:4.24243px;stroke-linecap:round;stroke-linejoin:round"
|
||||
d="m 6.8181812,40.151514 v 0 L 25,9.8484837 43.181819,40.151514" id="path3" />
|
||||
</svg>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
<body>
|
||||
<h1><span class="accent">Third Culture</span> Upload</h1>
|
||||
<form
|
||||
action="http://localhost:3880"
|
||||
method="POST"
|
||||
enctype="multipart/form-data"
|
||||
>
|
||||
<label for="fileInput">Choose file:</label>
|
||||
<input type="file" name="file" id="fileInput" required />
|
||||
<br /><br />
|
||||
<button type="submit">Upload</button>
|
||||
</form>
|
||||
<p><br /></p>
|
||||
<p>Make sure to copy the link in the next page!</p>
|
||||
<p>
|
||||
More info on third culture upload
|
||||
<a href="scripts/info.html">here</a>.
|
||||
</p>
|
||||
<p><br /></p>
|
||||
<svg
|
||||
version="1.1"
|
||||
style="fill: none; width: 75px; height: 75px"
|
||||
width="50"
|
||||
height="50"
|
||||
viewBox="0 0 50 50"
|
||||
id="svg3"
|
||||
sodipodi:docname="logo.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<defs id="defs3" />
|
||||
<path
|
||||
style="
|
||||
fill: #000000;
|
||||
stroke: #000000;
|
||||
stroke-width: 1.51515px;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
"
|
||||
d="m 0.75757498,49.242423 v 0 V 0.75757498 H 49.242425 V 49.242423 Z"
|
||||
id="path1"
|
||||
/>
|
||||
<path
|
||||
style="
|
||||
fill: none;
|
||||
stroke: #a4d1ad;
|
||||
stroke-width: 1.51515px;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
"
|
||||
d="m 20.454546,38.636362 v 0 l 9.090908,-9.090909 m -9.090908,0 v 0 l 9.090908,9.090909"
|
||||
id="path2"
|
||||
/>
|
||||
<path
|
||||
style="
|
||||
fill: none;
|
||||
stroke: #aea3f0;
|
||||
stroke-width: 4.24243px;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
"
|
||||
d="m 6.8181812,40.151514 v 0 L 25,9.8484837 43.181819,40.151514"
|
||||
id="path3"
|
||||
/>
|
||||
</svg>
|
||||
</body>
|
||||
</html>
|
||||
|
|
437
transfer/tshweb/transfer.go
Normal file
437
transfer/tshweb/transfer.go
Normal file
|
@ -0,0 +1,437 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
)
|
||||
|
||||
// NEED TO WORK ON ASYNC (once og fileuploaded to server, treat it as if its regular download, but run the ffmpeg and r2 upload in background)
|
||||
// Make display page for HTML during file upload
|
||||
// Make youtube esque looking page to watch the bucket files
|
||||
|
||||
// uploadToR2 uploads all files in the HLS output directory to R2
|
||||
func uploadToR2(r2Client *s3.S3, outputDir, bucketName string) error {
|
||||
// Walk through the directory and upload each file
|
||||
err := filepath.Walk(outputDir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Skip directories (not rly needed in our case)
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Open the file
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error opening file %s: %v", path, err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// Determine the key (object name) in the bucket
|
||||
// This preserves the directory structure relative to the base output directory
|
||||
relativePath, err := filepath.Rel(outputDir, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Normalize path separators for R2
|
||||
key := strings.ReplaceAll(relativePath, "\\", "/")
|
||||
|
||||
// Prepare the upload input, should upload to thirdculture bucket, with folder/key, and the files inside
|
||||
uploadInput := &s3.PutObjectInput{
|
||||
Bucket: aws.String(bucketName),
|
||||
Key: aws.String(key),
|
||||
Body: file,
|
||||
}
|
||||
|
||||
// Upload the file
|
||||
_, err = r2Client.PutObject(uploadInput)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error uploading file %s to R2: %v", path, err)
|
||||
}
|
||||
|
||||
fmt.Printf("Uploaded: %s\n", key)
|
||||
return nil
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// NewR2Client creates a new R2 client using AWS SDK
|
||||
func NewR2Client(accountId, accessKeyId, secretAccessKey string) (*s3.S3, error) {
|
||||
// Cloudflare R2 endpoint follows this format
|
||||
r2Endpoint := fmt.Sprintf("https://%s.r2.cloudflarestorage.com", accountId)
|
||||
|
||||
// Create AWS session with R2 credentials
|
||||
sess, err := session.NewSession(&aws.Config{
|
||||
Endpoint: aws.String(r2Endpoint),
|
||||
Region: aws.String("auto"), // Cloudflare uses 'auto'
|
||||
Credentials: credentials.NewStaticCredentials(accessKeyId, secretAccessKey, ""),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating AWS session: %v", err)
|
||||
}
|
||||
|
||||
// Create S3 client (used for R2)
|
||||
return s3.New(sess), nil
|
||||
}
|
||||
|
||||
// In your existing uploadHandler function, add this after HLS conversion:
|
||||
func uploadHLSToR2(r2Client *s3.S3, outputDir string) error {
|
||||
// Upload to R2 bucket
|
||||
err := uploadToR2(r2Client, outputDir, "thirdculture")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error uploading HLS files to R2: %v", err)
|
||||
}
|
||||
// After successful upload, remove the local HLS directory
|
||||
err = os.RemoveAll(outputDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error deleting local HLS directory %s: %v", outputDir, err)
|
||||
}
|
||||
|
||||
fmt.Printf("Successfully uploaded and deleted local HLS directory: %s\n", outputDir)
|
||||
return nil
|
||||
}
|
||||
|
||||
func uploadHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == http.MethodPost {
|
||||
// Parse the form
|
||||
err := r.ParseMultipartForm(15 * 1024 * 1024 * 1024) // limit 15 gb
|
||||
if err != nil {
|
||||
http.Error(w, "Unable to parse form", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
file, fileHeader, err := r.FormFile("file")
|
||||
if err != nil {
|
||||
http.Error(w, "Unable to retrieve file", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// Upload the file
|
||||
req, err := http.NewRequest("POST", "http://localhost:3880", file)
|
||||
if err != nil {
|
||||
http.Error(w, "Error creating request", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
// Filetype
|
||||
// Buffer needed to make it faster, so we only process one bit of the file instead of all
|
||||
buffer := make([]byte, 512)
|
||||
_, err = file.Read(buffer)
|
||||
if err != nil && err != io.EOF {
|
||||
http.Error(w, "Error reading the file", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
fileType := http.DetectContentType(buffer)
|
||||
file.Seek(0, 0)
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
http.Error(w, "Error uploading to transfer.sh", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Unique ID to track file for ffmpeg etc
|
||||
responseURL, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
http.Error(w, "Error reading response", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
urlParts := strings.Split(string(responseURL), "/")
|
||||
uniqueID := urlParts[len(urlParts)-1]
|
||||
|
||||
// If its a video, proceed with encoding and seperate uploads
|
||||
if strings.HasPrefix(fileType, "video/") {
|
||||
// Convert file to HLS. Work on error catching and flags tomorrow
|
||||
// IF VIDEO=DO THIS. IF NOT CONTINUE!
|
||||
// ALSO CHANGE THE CODE. IF VIDEO, REDIRECT TO S3 BUCKET
|
||||
// CURRENTLY FILE IS STANDARD UPLOAD TO SERVER
|
||||
//
|
||||
// Init r2 client
|
||||
// API KEYS PUSHED TO GIT IS BAD, I KNOW. But this stuff isnt public and were using your git so idt anyone could crawl
|
||||
// find my api keys and abuse this
|
||||
// Plus this way you can access it too
|
||||
r2Client, err := NewR2Client(
|
||||
"58916dd30d55baca3a55ad78f0883c52", // Account
|
||||
"94785bc0756ccedfe3634a7c4c7965f8", // Access
|
||||
"d5666b49c672c8584bc3a393701a938ddd8412663d5ea470e2c372179a86245e", // Secret Access
|
||||
)
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to initialize R2 client", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// File vars for ffmpeg
|
||||
inputDir := "../uploads"
|
||||
err = os.MkdirAll(inputDir, os.ModePerm)
|
||||
fileName := fileHeader.Filename
|
||||
noExtensionFilename := strings.TrimSuffix(filepath.Base(fileName), filepath.Ext(fileName))
|
||||
|
||||
//Create output basedir
|
||||
var outputBaseDir string
|
||||
var outputDir string
|
||||
if len(os.Args) >= 2 {
|
||||
outputBaseDir = os.Args[1]
|
||||
// Create dir if it doesnt exist
|
||||
err := os.MkdirAll(outputBaseDir, os.ModePerm)
|
||||
if err != nil {
|
||||
fmt.Printf("Error creating directory: %v\n", err)
|
||||
os.Exit(1)
|
||||
} else {
|
||||
// Default to $PWD
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
fmt.Printf("Error getting current directory: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
outputBaseDir = wd
|
||||
}
|
||||
}
|
||||
|
||||
// Set specific output diir
|
||||
outputDir = outputBaseDir + "/" + noExtensionFilename
|
||||
|
||||
// Check if the output directory exists
|
||||
_, err = os.Stat(outputDir)
|
||||
if err == nil {
|
||||
// If directory exists, remove it
|
||||
fmt.Printf("Output directory '%s' already exists. Removing it to avoid unused files.\n", outputDir)
|
||||
err := os.RemoveAll(outputDir) // Removes the directory and its contents
|
||||
if err != nil {
|
||||
fmt.Printf("Error removing directory: %v\n", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// FFPROBE to get frame rate
|
||||
cmdFFPROBE := exec.Command("ffprobe", "-v", "0", "-of", "default=noprint_wrappers=1:nokey=1",
|
||||
"-select_streams", "v:0", "-show_entries", "stream=avg_frame_rate", fileName)
|
||||
|
||||
outputFrame, err := cmdFFPROBE.Output()
|
||||
if err != nil {
|
||||
fmt.Printf("Error running ffprobe: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
frameRateStr := strings.TrimSpace(string(outputFrame))
|
||||
// Split the frame rate (which might be like "30/1" or "29.97")
|
||||
parts := strings.Split(frameRateStr, "/")
|
||||
var frameRateFloat float64
|
||||
|
||||
if len(parts) > 1 {
|
||||
// Handle fraction (e.g., "30/1")
|
||||
numerator, _ := strconv.ParseFloat(parts[0], 64)
|
||||
denominator, _ := strconv.ParseFloat(parts[1], 64)
|
||||
frameRateFloat = numerator / denominator
|
||||
} else {
|
||||
// Handle direct float (e.g., "29.97")
|
||||
frameRateFloat, err = strconv.ParseFloat(frameRateStr, 64)
|
||||
if err != nil {
|
||||
fmt.Printf("Framerate parsing error: %v\n", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Convert to int for GOP calculation
|
||||
GOP_SIZE := int(frameRateFloat * 4)
|
||||
gopSizeStr := strconv.Itoa(GOP_SIZE)
|
||||
|
||||
// resolution, bitrate, output slices/lists
|
||||
resolutions := []string{"1280x720", "1920x1080", "3840x2160"}
|
||||
bitrates := []string{"1200k", "2500k", "8000k"}
|
||||
outputs := []string{"720p", "1080p", "2160p"}
|
||||
playlist := []string{}
|
||||
|
||||
for i := range resolutions {
|
||||
res := resolutions[i]
|
||||
bitrate := bitrates[i]
|
||||
outputName := outputs[i]
|
||||
playlistName := outputName + ".m3u8"
|
||||
playlist = append(playlist, playlistName)
|
||||
|
||||
// Set profile and level based on res
|
||||
var profile, level string
|
||||
switch outputName {
|
||||
case "2160p":
|
||||
profile = "high"
|
||||
level = "5.1"
|
||||
case "1080p":
|
||||
profile = "high"
|
||||
level = "4.2"
|
||||
default:
|
||||
profile = "main"
|
||||
level = "3.1"
|
||||
}
|
||||
fmt.Printf("Processing %s...\n", outputName)
|
||||
|
||||
// FFmpeg command arguments
|
||||
ffmpegArgs := []string{
|
||||
"-y",
|
||||
"-i", fileName,
|
||||
"-c:v", "libx264",
|
||||
"-preset", "veryfast",
|
||||
"-profile:v", profile,
|
||||
"-level:v", level,
|
||||
"-b:v", bitrate,
|
||||
"-s", res,
|
||||
"-c:a", "aac",
|
||||
"-b:a", "128k",
|
||||
"-ac", "2",
|
||||
"-g", gopSizeStr,
|
||||
"-keyint_min", gopSizeStr,
|
||||
"-sc_threshold", "0",
|
||||
"-force_key_frames", "expr:gte(t,n_forced*4)",
|
||||
"-hls_time", "4",
|
||||
"-hls_list_size", "0",
|
||||
"-hls_flags", "independent_segments",
|
||||
"-hls_segment_filename", filepath.Join(outputDir, outputName+"_%03d.ts"),
|
||||
filepath.Join(outputDir, playlistName),
|
||||
}
|
||||
|
||||
cmd := exec.Command("ffmpeg", ffmpegArgs...)
|
||||
// Capture errors
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stderr = &stderr
|
||||
// Run command
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
fmt.Printf("Error: Failed to process %s: %v\n", outputName, err)
|
||||
fmt.Printf("FFmpeg error output: %s\n", stderr.String())
|
||||
return // or handle the error appropriately
|
||||
}
|
||||
// OKAY
|
||||
// BY HERE THE HLS ENCODING IS COMPLETE
|
||||
// NOW WE NEED TO UPLOAD TO R2 BUCKET
|
||||
// Upload HLS files to R2
|
||||
err = uploadHLSToR2(r2Client, outputDir)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("Failed to upload HLS files: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// HTML
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
fmt.Fprint(w, `
|
||||
<!DOCTYPE html>
|
||||
<html lang=en>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Third Culture Upload</title>
|
||||
<link rel="stylesheet" href="styles/main.css" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Upload Success</h1>
|
||||
<p><strong>Unique ID:</strong> %s</p>
|
||||
<p><a href="%s" target="_blank">%s</a></p>
|
||||
<a href="/">Upload Another</a>
|
||||
</body>
|
||||
</html>
|
||||
`, uniqueID, string(responseURL), string(responseURL))
|
||||
return
|
||||
}
|
||||
|
||||
// Original GET form
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
fmt.Fprint(w, `
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Third Culture Upload</title>
|
||||
<link rel="stylesheet" href="styles/main.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1><span class="accent">Third Culture</span> Upload</h1>
|
||||
<form
|
||||
action="http://localhost:3880"
|
||||
method="POST"
|
||||
enctype="multipart/form-data"
|
||||
>
|
||||
<label for="fileInput">Choose file:</label>
|
||||
<input type="file" name="file" id="fileInput" required />
|
||||
<br /><br />
|
||||
<button type="submit">Upload</button>
|
||||
</form>
|
||||
<p><br /></p>
|
||||
<p>Make sure to copy the link in the next page!</p>
|
||||
<p>
|
||||
More info on third culture upload
|
||||
<a href="scripts/info.html">here</a>.
|
||||
</p>
|
||||
<p><br /></p>
|
||||
<svg
|
||||
version="1.1"
|
||||
style="fill: none; width: 75px; height: 75px"
|
||||
width="50"
|
||||
height="50"
|
||||
viewBox="0 0 50 50"
|
||||
id="svg3"
|
||||
sodipodi:docname="logo.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<defs id="defs3" />
|
||||
<path
|
||||
style="
|
||||
fill: #000000;
|
||||
stroke: #000000;
|
||||
stroke-width: 1.51515px;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
"
|
||||
d="m 0.75757498,49.242423 v 0 V 0.75757498 H 49.242425 V 49.242423 Z"
|
||||
id="path1"
|
||||
/>
|
||||
<path
|
||||
style="
|
||||
fill: none;
|
||||
stroke: #a4d1ad;
|
||||
stroke-width: 1.51515px;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
"
|
||||
d="m 20.454546,38.636362 v 0 l 9.090908,-9.090909 m -9.090908,0 v 0 l 9.090908,9.090909"
|
||||
id="path2"
|
||||
/>
|
||||
<path
|
||||
style="
|
||||
fill: none;
|
||||
stroke: #aea3f0;
|
||||
stroke-width: 4.24243px;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
"
|
||||
d="m 6.8181812,40.151514 v 0 L 25,9.8484837 43.181819,40.151514"
|
||||
id="path3"
|
||||
/>
|
||||
</svg>
|
||||
</body>
|
||||
</html>
|
||||
`)
|
||||
}
|
||||
}
|
|
@ -6,12 +6,7 @@ fn conf_enable_cssedit {
|
|||
}
|
||||
|
||||
fn cssedit_init {
|
||||
if(! ~ $#enable_cssedit 0) {
|
||||
css_uri=`{echo $req_path | sed 's,(([^/]*)[^/]).*,\1,'}^/
|
||||
extraHeaders=$"extraHeaders ^ \
|
||||
'<link rel="stylesheet" type="text/css" href="'$css_uri'_werc/style.css">'
|
||||
}
|
||||
if(! ~ $#enable_cssedit 0 && check_user $cssedit_editors_groups && ~ $req_path $css_uri) {
|
||||
if(! ~ $#enable_cssedit 0 && check_user $cssedit_editors_groups) {
|
||||
lp=$local_path
|
||||
lp=`{echo $lp | sed 's/index$//'}
|
||||
cssedit_file=$"lp$"css_file
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
conf_enable_wiki
|
||||
conf_enable_cssedit 2fac
|
||||
wiki_editors_groups=2fac
|
||||
css_file='_werc/style.css'
|
|
@ -1 +0,0 @@
|
|||
/* Put custom styles here */
|
|
@ -1,7 +0,0 @@
|
|||
conf_enable_wiki
|
||||
conf_enable_blog
|
||||
conf_blog_only_pull=0
|
||||
conf_blog_editors=2fac
|
||||
wiki_editors_groups=2fac
|
||||
blogTitle=''
|
||||
blogDesc=''
|
|
@ -1,5 +1,4 @@
|
|||
extraHeaders='<link rel="stylesheet" type="text/css" href="_werc/style.css">'
|
||||
conf_enable_wiki
|
||||
conf_enable_cssedit mrshughhammersley
|
||||
wiki_editors_groups=mrshughhammersley
|
||||
conf_enable_cssedit nevada
|
||||
css_file='_werc/style.css'
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
conf_enable_wiki
|
||||
conf_enable_blog
|
||||
conf_blog_only_pull=0
|
||||
conf_blog_editors=mrshughhammersley
|
||||
wiki_editors_groups=mrhughhammersley
|
||||
conf_blog_editors=nevada
|
||||
blogTitle=''
|
||||
blogDesc=''
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
extraHeaders='<link rel="stylesheet" type="text/css" href="_werc/style.css">'
|
||||
conf_enable_wiki
|
||||
conf_enable_cssedit adil
|
||||
wiki_editors_groups=adil
|
||||
css_file='_werc/style.css'
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
:root {
|
||||
/* Main color scheme */
|
||||
--color-primary: #f907c5;
|
||||
--color-primary: #E4F0FEff;
|
||||
--color-secondary: #AEA3F0ff;
|
||||
--color-accent: #A4D1ADff;
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
|||
--link-hover: #5B3D8Aff;
|
||||
|
||||
/* Border colors */
|
||||
--border-primary: #f907c5;
|
||||
--border-primary: #C0CEE8ff;
|
||||
--border-secondary: #0C072Cff;
|
||||
--border-image: #000300ff;
|
||||
|
||||
|
@ -37,7 +37,3 @@
|
|||
--font-headers: 'rumeur', sans-serif;
|
||||
--font-body: verdana, helvetica, arial, sans-serif;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -2,6 +2,5 @@ conf_enable_wiki
|
|||
conf_enable_blog
|
||||
conf_blog_only_pull=0
|
||||
conf_blog_editors=adil
|
||||
wiki_editors_groups=adil
|
||||
blogTitle=''
|
||||
blogDesc=''
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
|
||||
#/ adil#
|
||||
|
||||
Hey, I'm the filmmaker of Third Culture.
|
||||
|
||||
[Blog](blog)
|
||||
|
||||
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
adil
|
|
@ -1 +0,0 @@
|
|||
Hi! I'm the film-maker of Third Culture :D
|
|
@ -1 +0,0 @@
|
|||
adil
|
|
@ -1,4 +0,0 @@
|
|||
##adil##
|
||||
|
||||
Hi! I'm the film-maker of Third Culture :D
|
||||
|
|
@ -1 +0,0 @@
|
|||
adil
|
|
@ -1,5 +0,0 @@
|
|||
##adil##
|
||||
|
||||
Hi! I'm the film-maker of Third Culture :D
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
adil
|
|
@ -1 +0,0 @@
|
|||
adil
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
#####adil#####
|
||||
|
|
@ -1 +0,0 @@
|
|||
adil
|
|
@ -1,4 +0,0 @@
|
|||
|
||||
#adil#
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
adil
|
|
@ -1,5 +0,0 @@
|
|||
|
||||
#/ adil#
|
||||
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
adil
|
|
@ -1,5 +0,0 @@
|
|||
|
||||
#/ adil#
|
||||
|
||||
Click the blog on the left sidebar cause it disappeared. Q pls fix I tried editing my page and it vanished.
|
||||
|
|
@ -1 +0,0 @@
|
|||
adil
|
|
@ -1,8 +0,0 @@
|
|||
|
||||
#/ adil#
|
||||
|
||||
Click the blog on the left sidebar cause it disappeared. Q pls fix I tried editing my page and it vanished.
|
||||
|
||||
[Blog](blog)
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
adil
|
|
@ -1,9 +0,0 @@
|
|||
|
||||
#/ adil#
|
||||
|
||||
Hey, I'm the film-maker of Third Culture.
|
||||
|
||||
[Blog](blog)
|
||||
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
adil
|
|
@ -1,10 +0,0 @@
|
|||
|
||||
#/ adil#
|
||||
|
||||
Hey, I'm the filmmaker of Third Culture.
|
||||
|
||||
[Blog](blog)
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
extraHeaders='<link rel="stylesheet" type="text/css" href="_werc/style.css">'
|
||||
conf_enable_wiki
|
||||
conf_enable_cssedit bea
|
||||
wiki_editors_groups=bea
|
||||
css_file='_werc/style.css'
|
||||
|
|
|
@ -1 +1,39 @@
|
|||
/* Put custom styles here */
|
||||
:root {
|
||||
/* Main color scheme */
|
||||
--color-primary: #E4F0FEff;
|
||||
--color-secondary: #AEA3F0ff;
|
||||
--color-accent: #A4D1ADff;
|
||||
|
||||
/* Background colors */
|
||||
--bg-primary: #000300ff;
|
||||
--bg-secondary: #1C202Fff;
|
||||
|
||||
/* Text colors */
|
||||
--text-primary: #E4F0FEff;
|
||||
--text-secondary: #989898ff;
|
||||
--text-accent: #AEA3F0ff;
|
||||
|
||||
/* Header colours */
|
||||
--header-primary:#AEA3F0ff;
|
||||
--header-secondary: #AEA3F0ff;
|
||||
--header-tertiary: #A4D1ADff;
|
||||
--header-other: #E4F0FEff;
|
||||
|
||||
/* Link colors */
|
||||
--link-color: #2667deff;
|
||||
--link-hover: #5B3D8Aff;
|
||||
|
||||
/* Border colors */
|
||||
--border-primary: #C0CEE8ff;
|
||||
--border-secondary: #0C072Cff;
|
||||
--border-image: #000300ff;
|
||||
|
||||
/* Special purpose colors */
|
||||
--code-color: #18A02Cff;
|
||||
--header-bg: #AEA3F0ff;
|
||||
--header-text: #0C072Cff;
|
||||
|
||||
/* Font families */
|
||||
--font-headers: 'rumeur', sans-serif;
|
||||
--font-body: verdana, helvetica, arial, sans-serif;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,5 @@ conf_enable_wiki
|
|||
conf_enable_blog
|
||||
conf_blog_only_pull=0
|
||||
conf_blog_editors=bea
|
||||
wiki_editors_groups=bea
|
||||
blogTitle=''
|
||||
blogDesc=''
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
conf_enable_wiki
|
||||
conf_enable_cssedit drool
|
||||
wiki_editors_groups=drool
|
||||
css_file='_werc/style.css'
|
|
@ -1 +0,0 @@
|
|||
/* Put custom styles here */
|
|
@ -1,7 +0,0 @@
|
|||
conf_enable_wiki
|
||||
conf_enable_blog
|
||||
conf_blog_only_pull=0
|
||||
conf_blog_editors=drool
|
||||
wiki_editors_groups=drool
|
||||
blogTitle=''
|
||||
blogDesc=''
|
|
@ -1,4 +1,4 @@
|
|||
extraHeaders='<link rel="stylesheet" type="text/css" href="_werc/style.css">'
|
||||
conf_enable_wiki
|
||||
conf_enable_cssedit dulien
|
||||
wiki_editors_groups=dulien
|
||||
css_file='_werc/style.css'
|
||||
|
|
|
@ -2,6 +2,5 @@ conf_enable_wiki
|
|||
conf_enable_blog
|
||||
conf_blog_only_pull=0
|
||||
conf_blog_editors=dulien
|
||||
wiki_editors_groups=dulien
|
||||
blogTitle=''
|
||||
blogDesc=''
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
extraHeaders='<link rel="stylesheet" type="text/css" href="_werc/style.css">'
|
||||
conf_enable_wiki
|
||||
conf_enable_cssedit geunf
|
||||
wiki_editors_groups=geunf
|
||||
css_file='_werc/style.css'
|
||||
|
|
|
@ -2,6 +2,5 @@ conf_enable_wiki
|
|||
conf_enable_blog
|
||||
conf_blog_only_pull=0
|
||||
conf_blog_editors=geunf
|
||||
wiki_editors_groups=geunf
|
||||
blogTitle=''
|
||||
blogDesc=''
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
extraHeaders='<link rel="stylesheet" type="text/css" href="_werc/style.css">'
|
||||
conf_enable_wiki
|
||||
conf_enable_cssedit iancobain
|
||||
wiki_editors_groups=iancobain
|
||||
css_file='_werc/style.css'
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
how to make this site not die in infancy
|
||||
-------------------------------------
|
||||
|
||||
1. HAVE TRAFFIC. make it an unavoidable step to a meaningful goal. think charging a toll on the road to the king's palace. the goal is an audience with the king, and the toll bridge is an unavoidable step that traffic will be routed over. here, the meaningful goal is to find out about upcoming shows in ottawa and to have a little y2k nostalgia trip. making MORE meaningful goals and ENSURING there are *no* alternatives is how to amplify this site. make it convenient to post more creations to thirdculture; then, if thirdculture-based music or interviews become semi-popular, and they're easily accessible on youtube, insta, twitter etc. then people just wont bother going on this website. keep it special! and if they're using those things and not this website, then they're subject to all the typical brainwashing and corporate exploitation, to being subjected to 4 hours of doomscrolling, to mindnumbing ads and forced content, to algorithms that extract all meaning out of community and creation.
|
|
@ -2,6 +2,5 @@ conf_enable_wiki
|
|||
conf_enable_blog
|
||||
conf_blog_only_pull=0
|
||||
conf_blog_editors=iancobain
|
||||
wiki_editors_groups=iancobain
|
||||
blogTitle=''
|
||||
blogDesc=''
|
||||
|
|
|
@ -33,16 +33,5 @@
|
|||
<div class="grid-item">
|
||||
<a href="/bea/"><img src="/_werc/pub/img/but/bea.gif" alt="bea" /></a>
|
||||
</div>
|
||||
<div class="grid-item">
|
||||
<a href="/drool/"><img src="/_werc/pub/img/but/drool.gif" alt="drool" /></a>
|
||||
</div>
|
||||
<div class="grid-item">
|
||||
<a href="/2fac/"><img src="/_werc/pub/img/but/2fac.gif" alt="2fac" /></a>
|
||||
</div>
|
||||
<!-- BUTTONS -->
|
||||
<div class="grid-item">
|
||||
<a href="/zacky/"><img src="/_werc/pub/img/but/zacky.gif" alt="zacky" /></a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
extraHeaders='<link rel="stylesheet" type="text/css" href="_werc/style.css">'
|
||||
conf_enable_wiki
|
||||
conf_enable_cssedit kaz
|
||||
wiki_editors_groups=kaz
|
||||
css_file='_werc/style.css'
|
||||
|
|
|
@ -2,6 +2,5 @@ conf_enable_wiki
|
|||
conf_enable_blog
|
||||
conf_blog_only_pull=0
|
||||
conf_blog_editors=kaz
|
||||
wiki_editors_groups=kaz
|
||||
blogTitle=''
|
||||
blogDesc=''
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
extraHeaders='<link rel="stylesheet" type="text/css" href="_werc/style.css">'
|
||||
conf_enable_wiki
|
||||
conf_enable_cssedit q
|
||||
wiki_editors_groups=q
|
||||
css_file='_werc/style.css'
|
||||
|
|
|
@ -5,6 +5,3 @@ So many bugs in production to fix lol
|
|||
|
||||
update: still bug hunting, I have a list now
|
||||
|
||||
update: getting some help now :)
|
||||
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
q
|
|
@ -1,10 +0,0 @@
|
|||
Launched third culture
|
||||
-------------------------------------
|
||||
|
||||
So many bugs in production to fix lol
|
||||
|
||||
update: still bug hunting, I have a list now
|
||||
|
||||
update: getting some help now :)
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
q
|
|
@ -1,10 +0,0 @@
|
|||
Launched third culture
|
||||
-------------------------------------
|
||||
|
||||
So many bugs in production to fix lol
|
||||
|
||||
update: still bug hunting, I have a list now
|
||||
|
||||
update: getting some help now :)
|
||||
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
Site Update
|
||||
-------------------------------------
|
||||
|
||||
We now have a self hosted git for hosting this page so if you are interested in development or submitting changes/bug fixes let me know. I'm pretty sure times should be fixed but I'm not 100% on that. Just mounted the time files of the server PC to this sites container. Anyway more to come I have an issues tracker on the git server to keep track of what I'm doing an my todo now.
|
|
@ -1,4 +0,0 @@
|
|||
Getting Organized
|
||||
-------------------------------------
|
||||
|
||||
Currently [https://git.thirdculture.top](https://git.thirdculture.top) has a shortlist of issues I want to solve before I start creating more content for thirdculture. Just finished it today, going to start on it today. Happy to see people adding to the site and its not just me, feels great. Want to write a bit more guides on how to use specific things as this software is a bit prone to messing up and markdown is a coding language I guess, its (friendly) anarchy right now haha. Having a lot of issues with syncing new changes on the site and then patching in my own fixes that's a major priority for me right now. Anyway bear with me, I also got a live mix to fix up still, an album to mix and master and school the latter being the most noise :(.
|
|
@ -1,6 +1,5 @@
|
|||
conf_enable_blog
|
||||
conf_blog_only_pull=0
|
||||
conf_blog_editors=q
|
||||
wiki_editors_groups=q
|
||||
blogTitle=''
|
||||
blogDesc=''
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
# Q
|
||||
|
||||
Guitarist and vocalist for moridori...
|
||||
Guitarist and vocalist for moridori.
|
||||
|
||||
![picture of me](_images/q.jpg)
|
||||
|
||||
You can find my personal releases under the name morisuki sometimes as well :)
|
||||
|
||||
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
# Q
|
||||
|
||||
Guitarist and vocalist for moridori...
|
||||
|
||||
![picture of me](_images/q.jpg)
|
||||
|
||||
You can find my personal releases under the name morisuki sometimes as well :)
|
||||
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
# Testing 1 2 3
|
||||
|
||||
Using this page for testing :)
|
|
@ -1,3 +0,0 @@
|
|||
# Testing 1 2 3
|
||||
|
||||
Using this page for testing :)
|
|
@ -1,4 +1,4 @@
|
|||
extraHeaders='<link rel="stylesheet" type="text/css" href="_werc/style.css">'
|
||||
conf_enable_wiki
|
||||
conf_enable_cssedit screenshare1112
|
||||
wiki_editors_groups=screenshare1112
|
||||
conf_enable_cssedit thomas
|
||||
css_file='_werc/style.css'
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
conf_enable_wiki
|
||||
conf_enable_blog
|
||||
conf_blog_only_pull=0
|
||||
conf_blog_editors=screenshare1112
|
||||
wiki_editors_groups=screenshare1112
|
||||
conf_blog_editors=thomas
|
||||
blogTitle=''
|
||||
blogDesc=''
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
|
||||
screenshare - tom - PLANT, blog/////
|
||||
|
||||
hi
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
screenshare1112
|
|
@ -1,5 +0,0 @@
|
|||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
extraHeaders='<link rel="stylesheet" type="text/css" href="_werc/style.css">'
|
||||
conf_enable_wiki
|
||||
conf_enable_cssedit sean
|
||||
wiki_editors_groups=sean
|
||||
css_file='_werc/style.css'
|
||||
|
|
|
@ -2,6 +2,5 @@ conf_enable_wiki
|
|||
conf_enable_blog
|
||||
conf_blog_only_pull=0
|
||||
conf_blog_editors=sean
|
||||
wiki_editors_groups=sean
|
||||
blogTitle=''
|
||||
blogDesc=''
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
extraHeaders='<link rel="stylesheet" type="text/css" href="_werc/style.css">'
|
||||
conf_enable_wiki
|
||||
conf_enable_cssedit vanne
|
||||
wiki_editors_groups=vanne
|
||||
css_file='_werc/style.css'
|
||||
|
|
|
@ -1,47 +1,39 @@
|
|||
:root {
|
||||
/* Main color scheme */
|
||||
--color-primary: #ffffffff;
|
||||
--color-secondary: #ff0000ff;
|
||||
--color-accent: #ff0000ff;
|
||||
--color-primary: #E4F0FEff;
|
||||
--color-secondary: #AEA3F0ff;
|
||||
--color-accent: #A4D1ADff;
|
||||
|
||||
/* Background colors */
|
||||
--bg-primary: #000000ff;
|
||||
--bg-secondary: #000000ff;
|
||||
--bg-primary: #000300ff;
|
||||
--bg-secondary: #1C202Fff;
|
||||
|
||||
/* Text colors */
|
||||
--text-primary: #ffffffff;
|
||||
--text-secondary: #8a8a8aff;
|
||||
--text-accent: #ff0000ff;
|
||||
--text-primary: #E4F0FEff;
|
||||
--text-secondary: #989898ff;
|
||||
--text-accent: #AEA3F0ff;
|
||||
|
||||
/* Header colours */
|
||||
--header-primary:#ff0000ff;
|
||||
--header-secondary: #ff0000ff;
|
||||
--header-tertiary: #ff0000ff;
|
||||
--header-other: #000000ff;
|
||||
--header-primary:#AEA3F0ff;
|
||||
--header-secondary: #AEA3F0ff;
|
||||
--header-tertiary: #A4D1ADff;
|
||||
--header-other: #E4F0FEff;
|
||||
|
||||
/* Link colors */
|
||||
--link-color: #b5b5b5ff;
|
||||
--link-hover: #ff0000ff;
|
||||
--link-color: #2667deff;
|
||||
--link-hover: #5B3D8Aff;
|
||||
|
||||
/* Border colors */
|
||||
--border-primary: #ff0000ff;
|
||||
--border-secondary: #ff0000ff;
|
||||
--border-image: #ff0000ff;
|
||||
--border-primary: #C0CEE8ff;
|
||||
--border-secondary: #0C072Cff;
|
||||
--border-image: #000300ff;
|
||||
|
||||
/* Special purpose colors */
|
||||
--code-color: #ff0000ff;
|
||||
--header-bg: #ff0000ff;
|
||||
--header-text: #000000ff;
|
||||
--code-color: #18A02Cff;
|
||||
--header-bg: #AEA3F0ff;
|
||||
--header-text: #0C072Cff;
|
||||
|
||||
/* Font families */
|
||||
--font-headers: courier, courier;
|
||||
--font-body: courier, courier, courier, courier;
|
||||
--font-headers: 'rumeur', sans-serif;
|
||||
--font-body: verdana, helvetica, arial, sans-serif;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -2,6 +2,5 @@ conf_enable_wiki
|
|||
conf_enable_blog
|
||||
conf_blog_only_pull=0
|
||||
conf_blog_editors=vanne
|
||||
wiki_editors_groups=vanne
|
||||
blogTitle=''
|
||||
blogDesc=''
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
conf_enable_wiki
|
||||
conf_enable_cssedit zacky
|
||||
wiki_editors_groups=zacky
|
||||
css_file='_werc/style.css'
|
|
@ -1 +0,0 @@
|
|||
/* Put custom styles here */
|
|
@ -1,7 +0,0 @@
|
|||
conf_enable_wiki
|
||||
conf_enable_blog
|
||||
conf_blog_only_pull=0
|
||||
conf_blog_editors=zacky
|
||||
wiki_editors_groups=zacky
|
||||
blogTitle=''
|
||||
blogDesc=''
|
|
@ -1,11 +0,0 @@
|
|||
How To Post An Event on Thirdculture
|
||||
====================================
|
||||
|
||||
1. make sure you have a registered account on third culture and are logged in
|
||||
2. click on the events page.
|
||||
3. click "new event" (i think)
|
||||
4. fill in basic information, which includes date, location, title, genre, and price. These details can be found by finding events themselves through websites such as ottawagigs.ca, eventbrite, and instagram. If the basic information is not found in the initial page, the rest should be available in ticket checkout.
|
||||
5. (optional) write a brief description, to just better inform people about the event really.
|
||||
6. upload.
|
||||
woohoo you did it !!! now go harass your friends to come to the show and buy merch so that these people dont starve to death on the streets
|
||||
|
|
@ -1 +0,0 @@
|
|||
iancobain
|
|
@ -1,11 +0,0 @@
|
|||
How To Post An Event on Thirdculture
|
||||
====================================
|
||||
|
||||
1. make sure you have a registered account on third culture and are logged in
|
||||
2. click on the events page.
|
||||
3. click "new event" (i think)
|
||||
4. fill in basic information, which includes date, location, title, genre, and price. These details can be found by finding events themselves through websites such as ottawagigs.ca, eventbrite, and instagram. If the basic information is not found in the initial page, the rest should be available in ticket checkout.
|
||||
5. (optional) write a brief description, to just better inform people about the event really.
|
||||
6. upload.
|
||||
woohoo you did it !!! now go harass your friends to come to the show and buy merch so that these people dont starve to death on the streets
|
||||
|
|
@ -17,16 +17,9 @@ Hotline Miami and Hotline Miami 2. Sharp and expressive use of top down pixel ar
|
|||
Metal Gear Solid (1 through 3). What more is there to say? It's the greatest action-stealth franchise with kick-ass music, boss fights, and voice acting wrapped in a conspiracy thriller that becomes more relevant each year. I like 4 and 5 too but 1 - 3 are my favourites.
|
||||
- (adil)
|
||||
|
||||
[OFF](http://gaarabis.free.fr/?catid=1)
|
||||
<p><small>Link goes to the developers official site + OFF's download link.</small></p>
|
||||
<p>I was 1 year and 364 days old when this game released. Later on it became one of my first RPG's ever.</p>
|
||||
Eerie. Spacey. Weird. Creepy and sometimes cute. Had a huge influence on the type of art I still love to this day. Oh, and the music goes insane. Pepper steak? Hard. The atmospheric, ambient tracks are very nice too. When I made shitty YouTube videos, I'd only use this OST. I love the big whale. And I love this game. Go play it.
|
||||
-☨
|
||||
|
||||
[yume nikki/yume 2kki](https://ynoproject.net/) yume nikki has real fucking aura man. I love this game and shows how unique games are as an art form. Creating a world for you to explore. Because of this novel idea there are many very cool games inspired from it, I have played many of them and their influences is in much of my work. The link is to an online project that allows you to play these amazing games in browser. (q)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
vanne
|
|
@ -1,32 +0,0 @@
|
|||
# Games
|
||||
|
||||
Cool games that have made an impact on our lives.
|
||||
|
||||
(Hey q I organized these in alphabetical order. Lmk if that's okay or if you want it by author)
|
||||
|
||||
## Video Games
|
||||
|
||||
[cave story](https://www.cavestory.org/) this is the game that inspired me to want to become an indie dev and make games for a living. This is a link to the tribute site, but play the game. (q)
|
||||
|
||||
Dishonored and Dishonored 2. Steampunk stealth-action immersive sim. Super interesting world with a lot of detail in it. You use super powers to teleport, entering the bodies of people/animals, summon man-eating rats, etc. Very engaging with a lot of replay value. Choosing between either violent/non-violent and overt/non-overt approaches changes how the world is affected around you. Despite the game being about assassination, you can beat it without killing a single person. Highly recommend.
|
||||
- (adil)
|
||||
|
||||
Hotline Miami and Hotline Miami 2. Sharp and expressive use of top down pixel art. Addicting gameplay. GOATED soundtrack. A story that seems simple on the surface but invites a lot of digging from the audience. The first game definitely has better gameplay and level design than the second game but the second one has a better score and story. It's a must-play for anyone who loves the video game medium.
|
||||
- (adil)
|
||||
|
||||
Metal Gear Solid (1 through 3). What more is there to say? It's the greatest action-stealth franchise with kick-ass music, boss fights, and voice acting wrapped in a conspiracy thriller that becomes more relevant each year. I like 4 and 5 too but 1 - 3 are my favourites.
|
||||
- (adil)
|
||||
|
||||
[OFF](http://gaarabis.free.fr/?catid=1)
|
||||
<p><small>Link goes to the developers official site + OFF's download link.</small></p>
|
||||
<p>I was 1 year and 364 days old when this game released. Later on it became one of my first RPG's ever.</p>
|
||||
Eerie. Spacey. Weird. Creepy and sometimes cute. Had a huge influence on the type of art I still love to this day. Oh, and the music goes insane. Pepper steak? Hard. The atmospheric, ambient tracks are very nice too. When I made shitty YouTube videos, I'd only use this OST. I love the big whale. And I love this game. Go play it.
|
||||
-☨
|
||||
|
||||
[yume nikki/yume 2kki](https://ynoproject.net/) yume nikki has real fucking aura man. I love this game and shows how unique games are as an art form. Creating a world for you to explore. Because of this novel idea there are many very cool games inspired from it, I have played many of them and their influences is in much of my work. The link is to an online project that allows you to play these amazing games in browser. (q)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,2 +1,8 @@
|
|||
# Music
|
||||
|
||||
Music valued by third culture and its members!
|
||||
|
||||
## Influences
|
||||
I maintain a list on my band moridori's site: [moridori's influences](https://moridori.xyz/influences.html). (q)
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
iancobain
|
|
@ -1,4 +0,0 @@
|
|||
# Music
|
||||
|
||||
Music valued by third culture and its members!
|
||||
|
|
@ -1 +0,0 @@
|
|||
iancobain
|
|
@ -1,4 +0,0 @@
|
|||
# Music
|
||||
|
||||
Music valued by third culture and its members!
|
||||
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue