Compare commits

...

93 Commits

Author SHA1 Message Date
6f92a6738d feat: Add umami
All checks were successful
Build Docker / Build Main Image (push) Successful in 37s
Build Docker / Build SLDs Image (push) Successful in 44s
2023-12-20 17:00:30 +11:00
a628be259d feat: Add analytics to tribes page
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 19s
Build Docker / Build Main Image (push) Successful in 21s
2023-12-13 15:17:18 +11:00
09ef9857d9 feat: Dynamically inject analytics into head of sites
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 19s
Build Docker / Build Main Image (push) Successful in 21s
2023-12-13 15:04:28 +11:00
bb10db2f00 feat: Add analytics to plain html 2023-12-13 15:00:12 +11:00
f65cbdb8e0 fix: Make alt tlds clickable
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 17s
Build Docker / Build Main Image (push) Successful in 20s
2023-12-13 10:54:45 +11:00
5a8d185837 feat: Add alternative tlds to account page
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 21s
Build Docker / Build Main Image (push) Successful in 22s
2023-12-13 10:52:40 +11:00
3c6829826f fix: Stop duplicating A and TLSA records and fix alts
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 19s
Build Docker / Build Main Image (push) Successful in 21s
2023-12-12 14:51:38 +11:00
f68186314b fix: Clone new TLSA and fix some typos
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 19s
Build Docker / Build Main Image (push) Successful in 21s
2023-12-12 14:43:05 +11:00
5980edbf89 feat: Start clone to alts function
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 36s
Build Docker / Build Main Image (push) Successful in 39s
2023-12-12 14:33:23 +11:00
80594ca9ac fix: Use A record instead of Alias
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 18s
Build Docker / Build Main Image (push) Successful in 19s
2023-11-23 14:01:10 +11:00
35322653a0 fix: Don't require crypto addresses
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 20s
Build Docker / Build Main Image (push) Successful in 20s
2023-11-23 13:53:00 +11:00
27039657c4 fix: Add trailing slash to tribe members
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 18s
Build Docker / Build Main Image (push) Successful in 19s
2023-11-22 13:17:45 +11:00
8ecc960c58 feat: Allow tribe renaming
All checks were successful
Build Docker / Build Main Image (push) Successful in 17s
Build Docker / Build SLDs Image (push) Successful in 19s
2023-11-22 13:16:36 +11:00
bd149f012e feat: Allow underscores in tribe names
All checks were successful
Build Docker / Build Main Image (push) Successful in 18s
Build Docker / Build SLDs Image (push) Successful in 19s
2023-11-22 13:12:38 +11:00
74ab088461 feat: Add delete tribe function
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 18s
Build Docker / Build Main Image (push) Successful in 20s
2023-11-22 13:07:55 +11:00
cd43dd3dc6 feat: Add initial tribes
All checks were successful
Build Docker / Build Main Image (push) Successful in 19s
Build Docker / Build SLDs Image (push) Successful in 20s
2023-11-22 13:00:04 +11:00
5d70dc862d feat: Start working on tribe feature
All checks were successful
Build Docker / Build Main Image (push) Successful in 19s
Build Docker / Build SLDs Image (push) Successful in 22s
2023-11-21 16:14:20 +11:00
cc62c04e6f fix: Increase contrast for icons
All checks were successful
Build Docker / Build Main Image (push) Successful in 19s
Build Docker / Build SLDs Image (push) Successful in 20s
2023-11-20 12:20:23 +11:00
5964ae5a23 fix: Add spacing for footer and set donate footer to not be absolute
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 19s
Build Docker / Build Main Image (push) Successful in 21s
2023-11-20 12:11:54 +11:00
fabf37d446 fix: Typo in templates list
All checks were successful
Build Docker / Build Main Image (push) Successful in 17s
Build Docker / Build SLDs Image (push) Successful in 18s
2023-11-20 12:01:51 +11:00
b968c90c2f fix: Exclude no data page from redirecting
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 18s
Build Docker / Build Main Image (push) Successful in 20s
2023-11-20 12:00:06 +11:00
fa5915b0df fix: Unreferenced variables if no address given
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 17s
Build Docker / Build Main Image (push) Successful in 19s
2023-11-20 11:54:33 +11:00
b805c3e655 feat: Add new templates with donate footer
All checks were successful
Build Docker / Build Main Image (push) Successful in 19s
Build Docker / Build SLDs Image (push) Successful in 21s
2023-11-20 11:51:44 +11:00
e2522a61d6 feat: Add placeholder documentation
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 19s
Build Docker / Build Main Image (push) Successful in 21s
2023-11-20 11:37:40 +11:00
cd1253d0fd feat: Add more address and logo options
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 18s
Build Docker / Build Main Image (push) Successful in 20s
2023-11-20 11:12:54 +11:00
c69a600aa1 feat: Add footer to render for template testing
All checks were successful
Build Docker / Build Main Image (push) Successful in 21s
Build Docker / Build SLDs Image (push) Successful in 20s
2023-11-20 10:44:26 +11:00
2c419d73a2 feat: Add function to allow for template testing
All checks were successful
Build Docker / Build Main Image (push) Successful in 21s
Build Docker / Build SLDs Image (push) Successful in 20s
2023-11-19 12:21:43 +11:00
8f1b141828 feat: Remove slash from HNSChat name before saving
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 19s
Build Docker / Build Main Image (push) Successful in 20s
2023-11-18 19:27:05 +11:00
1c0e0059c1 feat: Update page titles
All checks were successful
Build Docker / Build Main Image (push) Successful in 20s
Build Docker / Build SLDs Image (push) Successful in 20s
2023-11-18 19:15:28 +11:00
c7e38a7f22 feat: Add empty site page
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 18s
Build Docker / Build Main Image (push) Successful in 21s
2023-11-18 19:05:50 +11:00
07eb15bd0c fix: Increase address text box size to fit content
All checks were successful
Build Docker / Build Main Image (push) Successful in 18s
Build Docker / Build SLDs Image (push) Successful in 19s
2023-11-18 18:40:03 +11:00
3e9ff9d916 feat: Add HIP2 Display toggle
All checks were successful
Build Docker / Build Main Image (push) Successful in 19s
Build Docker / Build SLDs Image (push) Successful in 20s
2023-11-18 18:36:18 +11:00
743a8d6916 feat: Add blank template and footer part
All checks were successful
Build Docker / Build Main Image (push) Successful in 18s
Build Docker / Build SLDs Image (push) Successful in 19s
2023-11-18 17:59:28 +11:00
d5e9100634 feat: Add 2 new templates without card backgrounds
All checks were successful
Build Docker / Build Main Image (push) Successful in 19s
Build Docker / Build SLDs Image (push) Successful in 19s
2023-11-18 16:09:54 +11:00
f2801f5660 fix: Updated template comments
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 17s
Build Docker / Build Main Image (push) Successful in 19s
2023-11-18 15:39:50 +11:00
ed2994bf89 feat: Add city html template
All checks were successful
Build Docker / Build Main Image (push) Successful in 18s
Build Docker / Build SLDs Image (push) Successful in 20s
2023-11-18 15:38:00 +11:00
e1e485e619 feat: Add uptime to footer
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 19s
Build Docker / Build Main Image (push) Successful in 20s
2023-11-18 15:10:42 +11:00
5438235144 feat: Hide address div if user has addresses
All checks were successful
Build Docker / Build Main Image (push) Successful in 23s
Build Docker / Build SLDs Image (push) Successful in 27s
2023-11-18 14:44:06 +11:00
d2b78ea6cf fix: Edit page crash when no template saved
All checks were successful
Build Docker / Build Main Image (push) Successful in 17s
Build Docker / Build SLDs Image (push) Successful in 19s
2023-11-18 13:32:37 +11:00
c2d4a36da0 fix: Typo class instead of style
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 17s
Build Docker / Build Main Image (push) Successful in 19s
2023-11-18 13:30:03 +11:00
eba3b5faca fix: Colour for text outside cards
All checks were successful
Build Docker / Build Main Image (push) Successful in 18s
Build Docker / Build SLDs Image (push) Successful in 19s
2023-11-18 13:28:28 +11:00
ca10141843 feat: Add option for selecting template
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 19s
Build Docker / Build Main Image (push) Successful in 19s
2023-11-18 13:21:38 +11:00
4a21cf9a5a fix: Overriding avatar didn't update DNS record
All checks were successful
Build Docker / Build Main Image (push) Successful in 19s
Build Docker / Build SLDs Image (push) Successful in 20s
2023-11-18 12:10:37 +11:00
268721555c fix: Typo in file name
All checks were successful
Build Docker / Build Main Image (push) Successful in 17s
Build Docker / Build SLDs Image (push) Successful in 18s
2023-11-18 11:57:20 +11:00
d879aa32d6 fix: Cleanup file name on upload
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 19s
Build Docker / Build Main Image (push) Successful in 21s
2023-11-18 11:54:25 +11:00
eb53b955b8 feat: Add address validation to try to stop typos
All checks were successful
Build Docker / Build Main Image (push) Successful in 19s
Build Docker / Build SLDs Image (push) Successful in 19s
2023-11-18 11:47:28 +11:00
253b202a5f fix: Update varo with avatar edit
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 20s
Build Docker / Build Main Image (push) Successful in 21s
2023-11-18 11:39:07 +11:00
40a794c0d4 feat: Add image uploading
All checks were successful
Build Docker / Build Main Image (push) Successful in 20s
Build Docker / Build SLDs Image (push) Successful in 21s
2023-11-18 00:25:59 +11:00
cb6dda7fca feat: Add error page
All checks were successful
Build Docker / Build Main Image (push) Successful in 22s
Build Docker / Build SLDs Image (push) Successful in 27s
2023-11-17 23:36:15 +11:00
25e546d7c5 fix: Shorten metadata description
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 17s
Build Docker / Build Main Image (push) Successful in 19s
2023-11-17 13:24:27 +11:00
f1da43fbce feat: Add page metadata for social embeds
All checks were successful
Build Docker / Build Main Image (push) Successful in 18s
Build Docker / Build SLDs Image (push) Successful in 20s
2023-11-17 13:21:38 +11:00
7e5235efb8 fix: Update domain verification
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 18s
Build Docker / Build Main Image (push) Successful in 20s
2023-11-17 13:12:33 +11:00
8c895eddea fix: Update no domain data to use False instead of empty string
All checks were successful
Build Docker / Build Main Image (push) Successful in 19s
Build Docker / Build SLDs Image (push) Successful in 20s
2023-11-17 13:06:43 +11:00
f5c610b5cf fix: Add donate to mobile view
All checks were successful
Build Docker / Build Main Image (push) Successful in 19s
Build Docker / Build SLDs Image (push) Successful in 21s
2023-11-17 13:00:55 +11:00
4a0f17f1c8 fix: Lowercase domain for signup
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 16s
Build Docker / Build Main Image (push) Successful in 17s
2023-11-17 10:43:46 +11:00
cb055cc13e fix: Update domain to block starting with _
All checks were successful
Build Docker / Build Main Image (push) Successful in 18s
Build Docker / Build SLDs Image (push) Successful in 21s
2023-11-17 10:43:23 +11:00
abf9f946d0 fix: Cleaned up readme
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 18s
Build Docker / Build Main Image (push) Successful in 20s
2023-11-16 15:52:59 +11:00
9425851810 feat: Add hnschat to index info
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 17s
Build Docker / Build Main Image (push) Successful in 18s
2023-11-16 15:41:16 +11:00
727ed07304 fix: Add temp donate address
All checks were successful
Build Docker / Build Main Image (push) Successful in 18s
Build Docker / Build SLDs Image (push) Successful in 19s
2023-11-16 15:38:40 +11:00
7db16b7e85 feat: Add default site colours
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 19s
Build Docker / Build Main Image (push) Successful in 20s
2023-11-16 15:31:45 +11:00
d54d91f6a4 fix: Site data autocreation when visiting an unclaimed domain
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 19s
Build Docker / Build Main Image (push) Successful in 20s
2023-11-16 15:25:48 +11:00
0ca9a8ac91 fix: Catch errors fir no records returned via API
All checks were successful
Build Docker / Build Main Image (push) Successful in 20s
Build Docker / Build SLDs Image (push) Successful in 19s
2023-11-16 15:11:54 +11:00
f49a14c5b2 fix: Add ALIAS and TLSA for sites
All checks were successful
Build Docker / Build Main Image (push) Successful in 20s
Build Docker / Build SLDs Image (push) Successful in 18s
2023-11-16 14:55:38 +11:00
2d152de2f4 feat: Add HNSChat linking
All checks were successful
Build Docker / Build Main Image (push) Successful in 20s
Build Docker / Build SLDs Image (push) Successful in 53s
2023-11-16 14:12:24 +11:00
e5a0560f2c feat: Add ssl redirect
All checks were successful
Build Docker / Build Main Image (push) Successful in 18s
Build Docker / Build SLDs Image (push) Successful in 19s
2023-11-16 13:05:46 +11:00
ee435a6e1d fix: Error loading site editor
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 17s
Build Docker / Build Main Image (push) Successful in 19s
2023-11-16 12:56:34 +11:00
935d534e24 feat: Add email to city and cleanup display
All checks were successful
Build Docker / Build Main Image (push) Successful in 20s
Build Docker / Build SLDs Image (push) Successful in 19s
2023-11-16 12:52:12 +11:00
8067c33a38 fix: Remove contact button borders on mobile
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 19s
Build Docker / Build Main Image (push) Successful in 20s
2023-11-15 23:02:42 +11:00
f79730387e fix: Remove borders on contact buttons
All checks were successful
Build Docker / Build Main Image (push) Successful in 17s
Build Docker / Build SLDs Image (push) Successful in 19s
2023-11-15 22:59:40 +11:00
28e325da32 fix: Home link not visible on mobile
All checks were successful
Build Docker / Build Main Image (push) Successful in 19s
Build Docker / Build SLDs Image (push) Successful in 19s
2023-11-15 22:56:47 +11:00
6616e27ced fix: Home screen spacing
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 17s
Build Docker / Build Main Image (push) Successful in 18s
2023-11-15 22:55:08 +11:00
bbb47144f4 feat: Add home page info
All checks were successful
Build Docker / Build Main Image (push) Successful in 37s
Build Docker / Build SLDs Image (push) Successful in 37s
2023-11-15 22:51:30 +11:00
5be0abeccd feat: Add logos for site info and addresses
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 19s
Build Docker / Build Main Image (push) Successful in 21s
2023-11-15 22:08:49 +11:00
ffc0a2ba9a fix: Remove any quotes from error message
All checks were successful
Build Docker / Build Main Image (push) Successful in 18s
Build Docker / Build SLDs Image (push) Successful in 19s
2023-11-15 21:35:59 +11:00
f246b9d033 fix: Update error message on website load fail
All checks were successful
Build Docker / Build Main Image (push) Successful in 19s
Build Docker / Build SLDs Image (push) Successful in 18s
2023-11-15 21:32:10 +11:00
a501142f12 fix: Update address layout on other screens
All checks were successful
Build Docker / Build Main Image (push) Successful in 18s
Build Docker / Build SLDs Image (push) Successful in 19s
2023-11-15 21:30:23 +11:00
178b8ec597 feat: Hide addresses not in use
All checks were successful
Build Docker / Build Main Image (push) Successful in 19s
Build Docker / Build SLDs Image (push) Successful in 18s
2023-11-15 21:27:03 +11:00
ee49e8341c fix: Decrease width of the address section
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 18s
Build Docker / Build Main Image (push) Successful in 19s
2023-11-15 21:23:28 +11:00
d39347515a fix: Align text centre for large screens
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 20s
Build Docker / Build Main Image (push) Successful in 22s
2023-11-15 21:16:02 +11:00
26ba39ae90 fix: Increase image size on large screens
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 18s
Build Docker / Build Main Image (push) Successful in 19s
2023-11-15 21:10:58 +11:00
1a110b1170 fix: Try setting the images directly
All checks were successful
Build Docker / Build Main Image (push) Successful in 19s
Build Docker / Build SLDs Image (push) Successful in 20s
2023-11-15 21:09:03 +11:00
70fc0102d0 fix: Don't limit max px count on image
All checks were successful
Build Docker / Build Main Image (push) Successful in 18s
Build Docker / Build SLDs Image (push) Successful in 19s
2023-11-15 21:00:54 +11:00
2e02d54277 fix: Fix image size
All checks were successful
Build Docker / Build Main Image (push) Successful in 19s
Build Docker / Build SLDs Image (push) Successful in 18s
2023-11-15 20:57:50 +11:00
9e0ae8e98c fix: Image warping on small screen
All checks were successful
Build Docker / Build Main Image (push) Successful in 18s
Build Docker / Build SLDs Image (push) Successful in 18s
2023-11-15 20:52:51 +11:00
8ef4410c55 fix: mobile layout using incorrect logout label
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 18s
Build Docker / Build Main Image (push) Successful in 21s
2023-11-15 20:50:19 +11:00
10d3df6460 feat: More responsive display
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 19s
Build Docker / Build Main Image (push) Successful in 20s
2023-11-15 19:15:10 +11:00
05a67dcb2b fix: Add home link in image
All checks were successful
Build Docker / Build Main Image (push) Successful in 17s
Build Docker / Build SLDs Image (push) Successful in 17s
2023-11-15 18:39:03 +11:00
4f72525009 fix: Increase size for HNS addresses
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 17s
Build Docker / Build Main Image (push) Successful in 19s
2023-11-15 18:36:40 +11:00
8a52f04ccf fix: Error catching for old sites
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 17s
Build Docker / Build Main Image (push) Successful in 19s
2023-11-15 18:28:40 +11:00
8b3e0d4cab feat: Add more colour control
All checks were successful
Build Docker / Build Main Image (push) Successful in 18s
Build Docker / Build SLDs Image (push) Successful in 20s
2023-11-15 18:24:11 +11:00
c5cc90daac fix: Fix copy templates into cities image
All checks were successful
Build Docker / Build SLDs Image (push) Successful in 17s
Build Docker / Build Main Image (push) Successful in 20s
2023-11-15 18:06:44 +11:00
400505d472 feat: Update city page
All checks were successful
Build Docker / Build Main Image (push) Successful in 20s
Build Docker / Build SLDs Image (push) Successful in 20s
2023-11-15 18:03:43 +11:00
771debdc50 feat: Add favicon
All checks were successful
Build Docker / Build Main Image (push) Successful in 16s
Build Docker / Build SLDs Image (push) Successful in 18s
2023-11-15 16:27:27 +11:00
48 changed files with 3062 additions and 94 deletions

View File

@@ -56,7 +56,7 @@ jobs:
- name: Build Docker image
run : |
cd sites
cp -r ../templates/* .
cp -r ../templates/ .
cp ../requirements.txt .
echo "${{ secrets.DOCKERGIT_TOKEN }}" | docker login git.woodburn.au -u nathanwoodburn --password-stdin

4
.gitignore vendored
View File

@@ -4,3 +4,7 @@
__pycache__/
*.json
sites/templates/
images/

134
PLACEHOLDERS.md Normal file
View File

@@ -0,0 +1,134 @@
# Template Placeholders
- [Template Placeholders](#template-placeholders)
- [Colours](#colours)
- [Background colour (bg\_colour)](#background-colour-bg_colour)
- [Text colour (text\_colour)](#text-colour-text_colour)
- [Foreground colour (fg\_colour)](#foreground-colour-fg_colour)
- [Parts](#parts)
- [Avatar](#avatar)
- [HNSChat](#hnschat)
- [Location](#location)
- [Email](#email)
- [Footer (footer)](#footer-footer)
- [Text Placeholders](#text-placeholders)
- [Main domain (main\_domain)](#main-domain-main_domain)
- [Data (data)](#data-data)
- [Crypto Address Placeholders](#crypto-address-placeholders)
- [Icons](#icons)
- [Full parts](#full-parts)
- [Address only](#address-only)
## Colours
### Background colour (bg_colour)
Use #000000 for the background colour as the app overwrites this colour
### Text colour (text_colour)
Use #1fffff for the background colour as the app overwrites this colour
### Foreground colour (fg_colour)
Use #f1ffff for the background colour as the app overwrites this colour
## Parts
### Avatar
`avatar` can be used to get the avatar of the user.
If the user doesn't have an avatar this is just
```html
<h1>domain.shakecities/</h1>
```
If the user does have an avatar this is
```html
<img src='avatar-url' width='200vw' height='200vw' style='border-radius: 50%;margin-right: 5px;'>
```
### HNSChat
If the user has a HNSChat name set this will return
```html
<a href='https://hns.chat/#message:username' target='_blank'>
<img src='hns_icon' width='20px' height='20px' style='margin-right: 5px;'>
username/
</a>
```
### Location
If the user has a location set this will return
```html
<img src='location_icon' width='20px' height='30px' style='margin-right: 5px;'>
location
```
### Email
If the user has a email set this will return
```html
<a href='mailto:email@example'>
<img src='email_icon' width='30px' height='20px' style='margin-right: 5px;margin-left:-10px;'>
email@example
</a>
```
### Footer (footer)
This is the Shakecities footer. It will always be the same "Powered by Shakecities"
## Text Placeholders
### Main domain (main_domain)
`main_domain` can be used to get the main domain of the site e.g. shakecities.com
### Data (data)
`data` can be used to get the data of the site.
This is the main body
## Crypto Address Placeholders
### Icons
These are the icons for the crypto addresses.
There are 2 versions of each icon. One with a contrast to the background colour and one without.
These return the path to the image of the icon (eg. `assets/img/HNS.png`)
They are as follows:
- hns_icon
- hns_icon_invert
- btc_icon
- btc_icon_invert
- eth_icon
- eth_icon_invert
### Full parts
These are the full parts for the crypto addresses.
They return both the icon and the address.
For example `hns` returns
```html
<img src='hns_icon' width='20px' height='20px' style='margin-right: 5px;'>hs1...
```
The list of full parts are:
- hns
- btc
- eth
- hns_invert
- btc_invert
- eth_invert
### Address only
These are plain text addresses without the icon.
Eg. `hns_address` returns
```html
hs1...
```
They are as follows:
- hns_address
- btc_address
- eth_address

View File

@@ -7,6 +7,23 @@ Every domain comes enabled with HTTPS via DANE. We have support HIP02 aliases, s
### Template testing
Replace `new` with your template name
```sh
cd <Git-REPONAME>
# Copy template
cp templates/city_template.html templates/city_new.html
# Edit template
# Test site with template
python3 -m pip install -r requirements.txt
python3 template.py city_new
```
Visit http://127.0.0.1:5000/ to view the template
Here is a list of placeholders you can use [PLACEHOLDERS.md](PLACEHOLDERS.md)
### Deployment
```
@@ -16,12 +33,17 @@ services:
image: git.woodburn.au/nathanwoodburn/shakecities:latest
depends_on:
- db
volumes:
- images:/data
environment:
DB_HOST: db
DB_USER: main
DB_PASSWORD: your-db-password
DB_NAME: main
CITY_DOMAIN: exampledomainnathan1
REG_KEY: <your-varo-apikey>
CITY_ALIAS: city.hnshosting.au # ICANN domain that points to the IP for the cities server
MAIN_DOMAIN: cities.hnshosting.au
WORKERS: 2 # number of workers to run (should be 2 * number of cores)
sites:
@@ -47,4 +69,5 @@ services:
- db_data:/var/lib/mysql
volumes:
db_data:
images:
```

View File

@@ -33,8 +33,12 @@ def generate_cookie():
# Create a new user
def create_user(email, domain, password):
if len(email) < 4 or len(domain) < 4 or len(password) < 4:
return {'success': False, 'message': 'Invalid email, domain, or password'}
if len(email) < 4:
return {'success': False, 'message': 'Unfortunatly your email is not valid'}
if len(domain) < 4:
return {'success': False, 'message': 'We only allow domains with 4 or more characters'}
if len(password) < 4:
return {'success': False, 'message': 'Your password is not complex enough'}
# Hash password
@@ -52,13 +56,13 @@ def create_user(email, domain, password):
# Check if user exists
if db.search_users(email) != []:
return {'success': False, 'message': 'User already exists'}
return {'success': False, 'message': 'It looks like someone already is using that email address'}
if db.search_users_domain(domain) != []:
return {'success': False, 'message': 'Domain already exists'}
return {'success': False, 'message': 'Someone has already claimed that domain'}
db.add_user(email, domain, hashed_password, token)
return {'success': True, 'message': 'User created', 'token': token}
return {'success': True, 'message': 'Congrats on creating an account', 'token': token}
def validate_token(token):
search = db.search_users_token(token)
@@ -83,15 +87,18 @@ def login(email,password):
# Verify email
search = db.search_users(email)
if search == []:
return {'success': False, 'message': 'Invalid email'}
return {'success': False, 'message': 'Sorry, we couldn\'t find your account<br>Check your email and password'}
user = convert_db_users(search[0])
# Verify password
if not verify_password(password, user['password']):
return {'success': False, 'message': 'Invalid password'}
return {'success': False, 'message': 'Sorry, we couldn\'t find your account<br>Check your email and password'}
# Create a cookie
token = generate_cookie()
user['tokens'].append(token)
# Get the newest 2 tokens
user['tokens'] = user['tokens'][-2:]
# Update user
db.update_tokens(user['id'], user['tokens'])
return {'success': True, 'message': 'Logged in', 'token': token}

50
avatar.py Normal file
View File

@@ -0,0 +1,50 @@
import os
import dotenv
import db
import random
import json
import varo
import re
IMAGE_LOCATION = os.getenv('IMAGE_LOCATION')
if IMAGE_LOCATION == None:
IMAGE_LOCATION = "/data"
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
MAIN_DOMAIN = os.getenv('MAIN_DOMAIN')
if MAIN_DOMAIN == None:
MAIN_DOMAIN = "shakecities.com"
if MAIN_DOMAIN == "127.0.0.1:5000":
MAIN_DOMAIN = f"http://{MAIN_DOMAIN}"
else:
MAIN_DOMAIN = f"https://{MAIN_DOMAIN}"
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
def save_avatar(file,owner):
filename = re.sub(r'[^a-zA-Z0-9.]', '', file.filename).lower()
while os.path.exists(f"{IMAGE_LOCATION}/{filename}"):
filename = f"{random.randint(0,1000000)}-{filename}"
file.save(f"{IMAGE_LOCATION}/{filename}")
user_data = db.get_website_data_raw(owner)
user_data['avatar'] = MAIN_DOMAIN + "/avatar/" + filename
db.update_website_data_raw(owner,json.dumps(user_data))
varo.update_avatar(user_data['avatar'],owner)
return filename
def clear(owner):
user_data = db.get_website_data_raw(owner)
filename = user_data['avatar'].split('/')[-1]
if filename != "":
os.remove(f"{IMAGE_LOCATION}/{filename}")
user_data['avatar'] = ""
db.update_website_data_raw(owner,json.dumps(user_data))
varo.update_avatar(user_data['avatar'],owner)

177
db.py
View File

@@ -2,6 +2,7 @@ import mysql.connector
import os
import dotenv
import json
import random
dotenv.load_dotenv()
@@ -13,9 +14,6 @@ dbargs = {
'database':os.getenv('DB_NAME')
}
def check_tables():
connection = mysql.connector.connect(**dbargs)
cursor = connection.cursor()
@@ -37,6 +35,15 @@ def check_tables():
PRIMARY KEY (id)
)
""")
cursor.execute("""
CREATE TABLE IF NOT EXISTS tribes (
id INT(11) NOT NULL AUTO_INCREMENT,
tribe VARCHAR(255) NOT NULL,
data JSON,
owner VARCHAR(255) NOT NULL,
PRIMARY KEY (id)
)
""")
cursor.close()
connection.close()
print("Checked tables")
@@ -197,6 +204,170 @@ def update_website_wallet(domain,token,address):
update_query = "UPDATE site SET data = %s WHERE domain = %s"
cursor.execute(update_query, (json.dumps(data), domain))
connection.commit()
cursor.close()
connection.close()
def get_random_sites():
connection = mysql.connector.connect(**dbargs)
cursor = connection.cursor()
cursor.execute("""
SELECT * FROM site
""")
data = cursor.fetchall()
cursor.close()
connection.close()
# Randomly pick 5
if len(data) > 5:
data = random.sample(data,5)
names = []
for site in data:
names.append(site[1])
return names
def get_tribes():
connection = mysql.connector.connect(**dbargs)
cursor = connection.cursor()
cursor.execute("""
SELECT * FROM tribes
""")
data = cursor.fetchall()
cursor.close()
connection.close()
tribes = []
for tribe in data:
tribes.append(tribe[1])
return tribes
def get_user_tribes(user):
connection = mysql.connector.connect(**dbargs)
cursor = connection.cursor()
cursor.execute("""
SELECT * FROM tribes WHERE owner = %s
""", (user,))
data = cursor.fetchall()
cursor.close()
connection.close()
# Also check members
connection = mysql.connector.connect(**dbargs)
cursor = connection.cursor()
cursor.execute("""
SELECT * FROM tribes
""")
data2 = cursor.fetchall()
cursor.close()
connection.close()
for tribe in data2:
tribe = json.loads(tribe[2])
if user in tribe['members']:
data.append(tribe)
return len(data)
def get_user_owned_tribe(user):
connection = mysql.connector.connect(**dbargs)
cursor = connection.cursor()
cursor.execute("""
SELECT * FROM tribes WHERE owner = %s
""", (user,))
data = cursor.fetchall()
cursor.close()
connection.close()
return data
def create_tribe(tribe,owner):
# Get users' tribes
if (get_user_tribes(owner) > 0):
return False
connection = mysql.connector.connect(**dbargs)
cursor = connection.cursor()
data = {
"data": "",
"members": [
owner
]
}
insert_query = "INSERT INTO tribes (data,tribe,owner) VALUES (%s,%s,%s)"
cursor.execute(insert_query, (json.dumps(data), tribe, owner))
connection.commit()
cursor.close()
connection.close()
return True
def get_tribe_data_raw(tribe):
connection = mysql.connector.connect(**dbargs)
cursor = connection.cursor()
cursor.execute("""
SELECT * FROM tribes WHERE tribe = %s
""", (tribe,))
data = cursor.fetchall()
cursor.close()
connection.close()
if len(data) == 0:
return False
return json.loads(data[0][2])
def check_tribe_owner(tribe,owner):
connection = mysql.connector.connect(**dbargs)
cursor = connection.cursor()
cursor.execute("""
SELECT * FROM tribes WHERE tribe = %s
""", (tribe,))
data = cursor.fetchall()
cursor.close()
connection.close()
if len(data) == 0:
return False
if data[0][3] == owner:
return True
else:
return False
def update_tribe_data_raw(tribe,data):
connection = mysql.connector.connect(**dbargs)
cursor = connection.cursor()
# Update json object
data = json.loads(data)
update_query = "UPDATE tribes SET data = %s WHERE tribe = %s"
cursor.execute(update_query, (json.dumps(data), tribe))
connection.commit()
cursor.close()
connection.close()
def delete_tribe(tribe):
connection = mysql.connector.connect(**dbargs)
cursor = connection.cursor()
cursor.execute("""
DELETE FROM tribes WHERE tribe = %s
""", (tribe,))
connection.commit()
cursor.close()
connection.close()
def rename_tribe(old,new):
connection = mysql.connector.connect(**dbargs)
cursor = connection.cursor()
cursor.execute("""
UPDATE tribes SET tribe = %s WHERE tribe = %s
""", (new,old))
connection.commit()
cursor.close()
connection.close()

488
main.py
View File

@@ -8,6 +8,9 @@ import time
from email_validator import validate_email, EmailNotValidError
import accounts
import db
import varo
import re
import avatar
app = Flask(__name__)
dotenv.load_dotenv()
@@ -20,21 +23,54 @@ dbargs = {
'database':os.getenv('DB_NAME')
}
CITY_DOMAIN = os.getenv('CITY_DOMAIN')
if CITY_DOMAIN == None:
CITY_DOMAIN = "exampledomainnathan1"
IMAGE_LOCATION = os.getenv('IMAGE_LOCATION')
if IMAGE_LOCATION == None:
IMAGE_LOCATION = "/data"
random_sites = ""
# Templates available for user
templates = [
'Standard',
'Original',
'No card around data',
'No card around data (2)',
'Blank',
'Standard with donate footer',
'No card with donate footer'
]
#Assets routes
@app.route('/assets/<path:path>')
def assets(path):
return send_from_directory('templates/assets', path)
@app.route('/avatar/<path:path>')
def avatar_view(path):
return send_from_directory(IMAGE_LOCATION, path)
def error(message):
return jsonify({'success': False, 'message': message}), 400
return render_template('error.html', message=message)
@app.route('/')
def index():
global random_sites
if random_sites == "":
random_sites_names = db.get_random_sites()
for site in random_sites_names:
random_sites += "<a href='https://" + site + "." + CITY_DOMAIN + "' target='_blank'>" + site + "." +CITY_DOMAIN+ "</a><br>"
tribes = db.get_tribes()
tribesHTML = ""
for tribe in tribes:
tribesHTML += "<a href='/tribe/" + tribe + "'>" + tribe.capitalize() + "</a><br>"
if 'token' in request.cookies:
token = request.cookies['token']
# Verify token
@@ -44,14 +80,19 @@ def index():
resp = make_response(redirect('/'))
resp.set_cookie('token', '', expires=0)
return resp
return render_template('index.html',account=user['email'],account_link="account",account_link_name="Account",CITY_DOMAIN=CITY_DOMAIN)
return render_template('index.html',account="Login",account_link="login",account_link_name="Login",CITY_DOMAIN=CITY_DOMAIN)
return render_template('index.html',account=user['email'],account_link="account",account_link_name="Account",CITY_DOMAIN=CITY_DOMAIN,random_sites=random_sites,tribes=tribesHTML)
return render_template('index.html',account="Login",account_link="login",account_link_name="Login",CITY_DOMAIN=CITY_DOMAIN,random_sites=random_sites,tribes=tribesHTML)
@app.route('/signup', methods=['POST'])
def signup():
email = request.form['email']
domain = request.form['domain']
domain = request.form['domain'].lower()
password = request.form['password']
# Verify domain
if not re.match("^[a-z0-9]*$", domain):
return error('Sorry domain can only contain lowercase letters and numbers')
try:
valid = validate_email(email)
email = valid.email
@@ -86,7 +127,7 @@ def edit():
token = request.cookies['token']
if not accounts.validate_token(token):
return error('Invalid token')
return error('Sorry we had an issue verifying your account')
# Verify token
user = accounts.validate_token(token)
if not user:
@@ -104,6 +145,10 @@ def edit():
location = ""
avatar = ""
bg_colour = ""
fg_colour = ""
text_colour = ""
email = ""
hip2_display = False
if 'data' in data:
html = data['data'].encode('utf-8').decode('unicode-escape')
@@ -119,19 +164,42 @@ def edit():
location = data['location']
if 'avatar' in data:
avatar = data['avatar']
if avatar != "":
avatar = "<img class='rounded-circle' width='100px' height='100px' src='"+avatar+"' style='margin-right: 25px;' />"
else:
avatar = "<p style='margin-right: 25px;'>No avatar set</p>"
if 'bg_colour' in data:
bg_colour = data['bg_colour']
if 'fg_colour' in data:
fg_colour = data['fg_colour']
else:
fg_colour = "#ffffff"
if 'text_colour' in data:
text_colour = data['text_colour']
if 'email' in data:
email = data['email']
if 'template' in data:
selected_template = data['template']
else:
selected_template = templates[0]
if 'hip2_display' in data:
hip2_display = data['hip2_display']
return render_template('edit.html',account=user['email'],account_link="account",account_link_name="Account",data=html,
hns=hns,btc=btc,eth=eth,hnschat=hnschat,location=location,avatar=avatar,
bg_colour=bg_colour,CITY_DOMAIN=CITY_DOMAIN,domain=user['domain'])
hns=hns,btc=btc,eth=eth,hnschat=hnschat,email=email,location=location,avatar=avatar,
bg_colour=bg_colour,fg_colour=fg_colour,text_colour=text_colour,templates=templates,
selected_template=selected_template,CITY_DOMAIN=CITY_DOMAIN,domain=user['domain'],hip2_display=hip2_display)
@app.route('/edit', methods=['POST'])
def send_edit():
token = request.cookies['token']
if not accounts.validate_token(token):
return error('Invalid token')
return error('Sorry we had an issue verifying your account')
# Verify token
user = accounts.validate_token(token)
if not user:
@@ -141,15 +209,26 @@ def send_edit():
return resp
# Json data
data = {}
data['data'] = request.form['data']
data['HNS'] = request.form['hns']
data['BTC'] = request.form['btc']
data['ETH'] = request.form['eth']
data['hnschat'] = request.form['hnschat']
data['location'] = request.form['location']
data['avatar'] = request.form['avatar']
data['bg_colour'] = request.form['bg_colour']
data = db.get_website_data_raw(user['domain'])
data['data'] = request.form['data'].strip()
data['HNS'] = request.form['hns'].strip()
data['BTC'] = request.form['btc'].strip()
data['ETH'] = request.form['eth'].strip()
data['hnschat'] = request.form['hnschat'].strip()
data['hnschat'] = data['hnschat'].replace("/","").strip()
data['location'] = request.form['location'].strip()
data['bg_colour'] = request.form['bg_colour'].strip()
data['fg_colour'] = request.form['fg_colour'].strip()
data['text_colour'] = request.form['text_colour'].strip()
data['email'] = request.form['email'].strip()
data['template'] = request.form['template'].strip()
if 'hip2_display' in request.form:
data['hip2_display'] = True
else:
data['hip2_display'] = False
# Convert to json
data = json.dumps(data)
@@ -162,7 +241,7 @@ def send_edit():
def logout():
token = request.cookies['token']
if not accounts.logout(token)['success']:
return error('Invalid token')
return error('Sorry we had an issue verifying your account')
# Remove cookie
resp = make_response(redirect('/'))
@@ -175,7 +254,347 @@ def claim():
domain = request.args.get('domain')
return redirect('/signup?domain=' + domain)
@app.route('/hnschat')
def hnschat():
token = request.cookies['token']
if not accounts.validate_token(token):
return error('Sorry we had an issue verifying your account')
# Verify token
user = accounts.validate_token(token)
if not user:
# Remove cookie
resp = make_response(redirect('/login'))
resp.set_cookie('token', '', expires=0)
return resp
record = varo.get_auth(user['domain'])
return render_template('hnschat.html',account=user['email'],account_link="account",account_link_name="Account",CITY_DOMAIN=CITY_DOMAIN,domain=user['domain'],hnschat=record)
@app.route('/hnschat', methods=['POST'])
def save_hnschat():
token = request.cookies['token']
if not accounts.validate_token(token):
return error('Sorry we had an issue verifying your account')
# Verify token
user = accounts.validate_token(token)
if not user:
# Remove cookie
resp = make_response(redirect('/login'))
resp.set_cookie('token', '', expires=0)
return resp
record = request.form['hnschat']
varo.update_auth(record,user['domain'])
return redirect('/hnschat')
@app.route('/upload', methods=['POST'])
def upload_avatar():
token = request.cookies['token']
if not accounts.validate_token(token):
return error('Sorry we had an issue verifying your account')
# Verify token
user = accounts.validate_token(token)
if not user:
# Remove cookie
resp = make_response(redirect('/login'))
resp.set_cookie('token', '', expires=0)
return resp
if 'file' not in request.files:
return error('We couldn\'t find a file in your request')
file = request.files['file']
if file.filename == '':
return error('We couldn\'t find a file in your request')
if file and avatar.allowed_file(file.filename):
# Save the file to the upload folder
avatar.save_avatar(file,user['domain'])
return redirect('/edit')
return error('Sorry we couldn\'t upload your file')
@app.route('/avatar/clear')
def avatar_clear():
token = request.cookies['token']
if not accounts.validate_token(token):
return error('Sorry we had an issue verifying your account')
# Verify token
user = accounts.validate_token(token)
if not user:
# Remove cookie
resp = make_response(redirect('/login'))
resp.set_cookie('token', '', expires=0)
return resp
avatar.clear(user['domain'])
return redirect('/edit')
@app.route('/tribe')
def tribe_list():
tribes = db.get_tribes()
tribesHTML = ""
for tribe in tribes:
tribesHTML += "<a href='/tribe/" + tribe + "'>" + tribe.capitalize() + "</a><br>"
# Add create link if user is logged in
if 'token' in request.cookies:
token = request.cookies['token']
# Verify token
user = accounts.validate_token(token)
if user:
tribesHTML += "<br><br><a class='btn btn-primary' role='button' style='width: 100%;' href='/new_tribe'>Create a tribe</a>"
return render_template('tribe.html',account="Account",account_link="account",account_link_name="Account",CITY_DOMAIN=CITY_DOMAIN,tribes=tribesHTML)
return render_template('tribe.html',account="Login",account_link="login",account_link_name="Login",CITY_DOMAIN=CITY_DOMAIN,tribes=tribesHTML)
@app.route('/new_tribe')
def new_tribe():
if 'token' not in request.cookies:
return redirect('/login')
token = request.cookies['token']
if not accounts.validate_token(token):
return error('Sorry we had an issue verifying your account')
# Verify token
user = accounts.validate_token(token)
if not user:
# Remove cookie
resp = make_response(redirect('/login'))
resp.set_cookie('token', '', expires=0)
return resp
return render_template('new_tribe.html',account=user['email'],account_link="account",account_link_name="Account",CITY_DOMAIN=CITY_DOMAIN)
@app.route('/new_tribe', methods=['POST'])
def create_tribe():
token = request.cookies['token']
if not accounts.validate_token(token):
return error('Sorry we had an issue verifying your account')
# Verify token
user = accounts.validate_token(token)
if not user:
# Remove cookie
resp = make_response(redirect('/login'))
resp.set_cookie('token', '', expires=0)
return resp
tribe = request.form['tribe'].strip().lower()
if not re.match("^[a-z0-9_]*$", tribe):
return error('Sorry tribe can only contain lowercase letters, numbers and underscores')
if tribe.startswith("_") or tribe.endswith("_"):
return error('Sorry tribe can\'t start or end with an underscore')
if len(tribe) < 3:
return error('Sorry tribe must be at least 3 characters long')
if len(tribe) > 255:
return error('Sorry tribe must be less than 255 characters long')
if db.create_tribe(tribe,user['domain']):
return redirect('/tribe/' + tribe)
else:
return error('Sorry you already have a tribe')
@app.route('/tribe/<tribe>')
def tribe(tribe):
tribe = tribe.lower()
if not re.match("^[a-z0-9_]*$", tribe):
return error('Sorry we couldn\'t find that tribe')
data = db.get_tribe_data_raw(tribe)
if data == None:
return error('Sorry we couldn\'t find that tribe')
html = ""
if 'data' in data:
html = data['data'].encode('utf-8').decode('unicode-escape')
html = html.replace("\n","<br>")
tribe = tribe.capitalize()
members_html = ""
members = data['members']
for member in members:
members_html += "<a href='https://" + member + "." + CITY_DOMAIN + "' target='_blank'>" + member + "." +CITY_DOMAIN+ "/</a><br>"
edit = ""
# Add edit link if user is logged in
if 'token' in request.cookies:
token = request.cookies['token']
# Verify token
user = accounts.validate_token(token)
if user:
if db.check_tribe_owner(tribe,user['domain']):
edit = "<a class='btn btn-primary' role='button' style='width: 100%;' href='/edit_tribe'>Edit tribe</a>"
elif user['domain'] not in members:
edit = "<a class='btn btn-primary' role='button' style='width: 100%;' href='/join_tribe/" + tribe + "'>Join tribe</a>"
return render_template('tribe_view.html',tribe=tribe,data=html,edit=edit,members=members_html)
@app.route('/join_tribe/<tribe>')
def join_tribe(tribe):
tribe = tribe.lower()
if not re.match("^[a-z0-9_]*$", tribe):
return error('Sorry we couldn\'t find that tribe')
data = db.get_tribe_data_raw(tribe)
if data == None:
return error('Sorry we couldn\'t find that tribe')
# Verify token
token = request.cookies['token']
if not accounts.validate_token(token):
# Remove cookie
resp = make_response(redirect('/login'))
resp.set_cookie('token', '', expires=0)
return resp
user = accounts.validate_token(token)
if not user:
# Remove cookie
resp = make_response(redirect('/login'))
resp.set_cookie('token', '', expires=0)
return resp
members = data['members']
if user['domain'] in members:
return error('Sorry you are already a member of this tribe')
members.append(user['domain'])
data['members'] = members
# Convert to json
data = json.dumps(data)
db.update_tribe_data_raw(tribe,data)
return redirect('/tribe/' + tribe)
@app.route('/edit_tribe')
def edit_tribe_view():
token = request.cookies['token']
if not accounts.validate_token(token):
return error('Sorry we had an issue verifying your account')
# Verify token
user = accounts.validate_token(token)
if not user:
# Remove cookie
resp = make_response(redirect('/'))
resp.set_cookie('token', '', expires=0)
return resp
tribeData = db.get_user_owned_tribe(user['domain'])
if len(tribeData) == 0:
return error('Sorry you don\'t own a tribe')
tribe = tribeData[0][1]
data = tribeData[0][2]
data = json.loads(data)
html = data['data'].encode('utf-8').decode('unicode-escape')
members = data['members']
members_html = ""
for member in members:
members_html += "<a href='https://" + member + "." + CITY_DOMAIN + "' target='_blank'>" + member + "." +CITY_DOMAIN+ "</a> <a href='/remove_member?member=" + member + "'>(Remove)</a><br>"
return render_template('edit_tribe.html',account=user['email'],account_link="account",account_link_name="Account",CITY_DOMAIN=CITY_DOMAIN,tribe=tribe,data=html,members=members_html)
@app.route('/edit_tribe', methods=['POST'])
def edit_tribe():
token = request.cookies['token']
if not accounts.validate_token(token):
return error('Sorry we had an issue verifying your account')
# Verify token
user = accounts.validate_token(token)
if not user:
# Remove cookie
resp = make_response(redirect('/'))
resp.set_cookie('token', '', expires=0)
return resp
tribeData = db.get_user_owned_tribe(user['domain'])
if len(tribeData) == 0:
return error('Sorry you don\'t own a tribe')
tribe = tribeData[0][1]
data = tribeData[0][2]
data = json.loads(data)
data['data'] = request.form['data'].strip()
# Convert to json
data = json.dumps(data)
db.update_tribe_data_raw(tribe,data)
# Check if tribe name changed
if tribe != request.form['tribe']:
# Verify new tribe name
new_tribe = request.form['tribe'].strip().lower()
if not re.match("^[a-z0-9_]*$", new_tribe):
return error('Sorry tribe can only contain lowercase letters, numbers and underscores')
if new_tribe.startswith("_") or new_tribe.endswith("_"):
return error('Sorry tribe can\'t start or end with an underscore')
# Delete old tribe
db.rename_tribe(tribe,new_tribe)
return redirect('/edit_tribe')
@app.route('/remove_member')
def remove_member():
token = request.cookies['token']
if not accounts.validate_token(token):
return error('Sorry we had an issue verifying your account')
member = request.args.get('member')
# Verify token
user = accounts.validate_token(token)
if not user:
# Remove cookie
resp = make_response(redirect('/'))
resp.set_cookie('token', '', expires=0)
return resp
tribeData = db.get_user_owned_tribe(user['domain'])
if len(tribeData) == 0:
return error('Sorry you don\'t own a tribe')
# Verify member isn't owner
if member == user['domain']:
return error('Sorry you can\'t remove yourself from your own tribe')
tribe = tribeData[0][1]
data = tribeData[0][2]
data = json.loads(data)
members = data['members']
if member in members:
members.remove(member)
data['members'] = members
# Convert to json
data = json.dumps(data)
db.update_tribe_data_raw(tribe,data)
return redirect('/edit_tribe')
@app.route('/delete_tribe')
def delete_tribe():
token = request.cookies['token']
if not accounts.validate_token(token):
return error('Sorry we had an issue verifying your account')
# Verify token
user = accounts.validate_token(token)
if not user:
# Remove cookie
resp = make_response(redirect('/'))
resp.set_cookie('token', '', expires=0)
return resp
tribeData = db.get_user_owned_tribe(user['domain'])
if len(tribeData) == 0:
return error('Sorry you don\'t own a tribe')
tribe = tribeData[0][1]
db.delete_tribe(tribe)
return redirect('/tribe')
@app.route('/<path:path>')
def catch_all(path):
@@ -183,7 +602,11 @@ def catch_all(path):
account_link = "login"
account_link_name = "Login"
site = "Null"
sld = ""
domain = ""
tribe_title = "Join a tribe"
tribe_link = "tribe"
if 'domain' in request.args:
domain = request.args.get('domain')
if 'token' in request.cookies:
@@ -199,7 +622,14 @@ def catch_all(path):
account_link = "account"
account_link_name = "Account"
site = user['domain'] + "." + CITY_DOMAIN
elif path != "signup" and path != "login":
sld = user['domain']
# Check if user owns tribe
tribeData = db.get_user_owned_tribe(user['domain'])
if len(tribeData) > 0:
tribe_title = "Edit your tribe"
tribe_link = "edit_tribe"
elif path != "signup" and path != "login" and path != "empty_site":
return redirect('/')
if path == "account":
@@ -208,20 +638,32 @@ def catch_all(path):
# If file exists, load it
if os.path.isfile('templates/' + path):
return render_template(path,account=account,account_link=account_link,account_link_name=account_link_name,site=site,CITY_DOMAIN=CITY_DOMAIN,domain=domain)
return render_template(path,account=account,account_link=account_link,
account_link_name=account_link_name,site=site,
CITY_DOMAIN=CITY_DOMAIN,domain=domain,sld=sld,
tribe_title=tribe_title,tribe_link=tribe_link)
# Try with .html
if os.path.isfile('templates/' + path + '.html'):
return render_template(path + '.html',account=account,account_link=account_link,account_link_name=account_link_name,site=site,CITY_DOMAIN=CITY_DOMAIN,domain=domain)
return render_template(path + '.html',account=account,account_link=account_link,
account_link_name=account_link_name,site=site,
CITY_DOMAIN=CITY_DOMAIN,domain=domain,sld=sld,
tribe_title=tribe_title,tribe_link=tribe_link)
return redirect('/') # 404 catch all
# 404 catch all
@app.errorhandler(404)
def not_found(e):
return redirect('/')
def update_random_sites():
global random_sites
random_sites_names = db.get_random_sites()
random_sites = ""
for site in random_sites_names:
random_sites += "<a href='https://" + site + "." + CITY_DOMAIN + "' target='_blank'>" + site + "." +CITY_DOMAIN+ "</a><br>"
if __name__ == '__main__':
db.check_tables()
app.run(debug=False, port=5000, host='0.0.0.0')
app.run(debug=True, port=5000, host='0.0.0.0')

View File

@@ -9,4 +9,5 @@ py3dns
passlib
argon2-cffi
mysql-connector-python
beautifulsoup4
beautifulsoup4
apscheduler

View File

@@ -8,8 +8,13 @@ import dotenv
import sys
import json
import db
from apscheduler.schedulers.background import BackgroundScheduler
def update_sites_job():
print("Updating random sites", flush=True)
main.update_random_sites()
class GunicornApp(BaseApplication):
def __init__(self, app, options=None):
self.options = options or {}
@@ -26,6 +31,12 @@ class GunicornApp(BaseApplication):
if __name__ == '__main__':
db.check_tables()
scheduler = BackgroundScheduler()
scheduler.add_job(update_sites_job, 'interval', minutes=15)
scheduler.start()
workers = os.getenv('WORKERS')
threads = os.getenv('THREADS')
if workers is None:

View File

@@ -24,7 +24,7 @@ def get_website_data(domain):
connection.close()
if data == []:
return ""
return False
parsed = data[0][2]
parsed = json.loads(parsed)
@@ -34,6 +34,24 @@ def get_website_data(domain):
return parsed
def get_website_data_raw(domain):
connection = mysql.connector.connect(**dbargs)
cursor = connection.cursor()
cursor.execute("""
SELECT * FROM site WHERE domain = %s
""", (domain,))
data = cursor.fetchall()
cursor.close()
connection.close()
if data == []:
return ""
parsed = data[0][2]
parsed = json.loads(parsed)
return parsed
def get_website_wallet(domain,token):
connection = mysql.connector.connect(**dbargs)
cursor = connection.cursor()

7
sites/parts/footer.html Normal file
View File

@@ -0,0 +1,7 @@
<div style="height: 100px;"></div>
<div style="position: fixed;bottom: 10px;width: 100%;left:25px;">
<div style="display: inline-block; background: {{fg_colour}};border-radius: 50%;padding: 10px;">
<img src="{{hns_icon}}" width="50px" height="50px">
</div>
<p style="margin-left: 25px; display:inline; color:{{fg_colour}};">Powered by <a href="https://{{main_domain}}" target="_blank">ShakeCities</a></p>
</div>

View File

@@ -30,8 +30,9 @@ def index():
# Get website data
data = db.get_website_data(host)
db_object = db.get_website_data_raw(host)
# Render as HTML
return website.render(data)
return website.render(data,db_object)
@app.route('/.well-known/wallets/<token>')
@@ -53,6 +54,21 @@ def catch_all(path):
def not_found(e):
return redirect('/')
def clean_templates():
# Clean template
for file in os.listdir('templates'):
if file.endswith('.html'):
with open('templates/' + file) as f:
data = f.read()
data = data.replace('#f1ffff', '{{fg_colour}}')
data = data.replace('#1fffff', '{{text_colour}}')
data = data.replace('#000000', '{{bg_colour}}')
# Save
with open('templates/' + file, 'w') as f:
f.write(data)
print("Cleaned " + file, flush=True)
print("Cleaned template", flush=True)
if __name__ == '__main__':
app.run(debug=False, port=5000, host='0.0.0.0')

View File

@@ -24,6 +24,8 @@ class GunicornApp(BaseApplication):
return self.application
if __name__ == '__main__':
print("Cleaning template...", flush=True)
slds.clean_templates()
workers = os.getenv('WORKERS')
threads = os.getenv('THREADS')
if workers is None:

View File

@@ -1,24 +1,229 @@
from flask import Flask, make_response, redirect, render_template_string, request, jsonify, render_template, send_from_directory
from flask import Flask, redirect, render_template_string, request
from bs4 import BeautifulSoup
import os
import dotenv
main_domain = "cities.hnshosting.au"
main_domain = "shakecities.com"
if os.getenv('MAIN_DOMAIN') != None:
main_domain = os.getenv('MAIN_DOMAIN')
def render(data):
if data == "":
FOOTER=""
if os.path.exists("parts/footer.html"):
with open("parts/footer.html") as f:
FOOTER = f.read()
elif os.path.exists("sites/parts/footer.html"):
with open("sites/parts/footer.html") as f:
FOOTER = f.read()
def render(data,db_object):
if data == False:
return redirect("https://" + main_domain + '/claim?domain=' + request.host.split('.')[0])
elif data == "":
return redirect("https://" + main_domain + '/empty_site?nodata')
# Render as HTML
html = ""
ssl = "<script src='https://nathan.woodburn/https.js'></script>"
if ("localhost" in request.host or "127.0.0.1" in request.host):
ssl = ""
try:
soup = BeautifulSoup(data, 'html.parser')
for script in soup.find_all('script'):
script.extract()
modified = str(soup)
return render_template_string(modified)
# Inject SSL
soup.append(BeautifulSoup(ssl, 'html.parser'))
html = str(soup)
except Exception as e:
return "<h1>Invalid HTML</h1><br>" + str(e)
return redirect("https://" + main_domain + '/empty_site?error='+str(e))
try:
avatar = db_object['avatar']
hnschat = db_object['hnschat']
location = db_object['location']
email = db_object['email']
hns = db_object['HNS']
if 'hip2_display' in db_object:
if db_object['hip2_display'] == True:
hns = "@"+request.host
btc = db_object['BTC']
eth = db_object['ETH']
bg_colour = db_object['bg_colour']
fg_colour = db_object['fg_colour']
text_colour = db_object['text_colour']
if (rgb_to_hex(generate_foreground_color(bg_colour)) == "#000000"):
hns_icon = "assets/img/HNSW.png"
btc_icon = "assets/img/BTCW.png"
eth_icon = "assets/img/ETHW.png"
hns_icon_invert = "assets/img/HNS.png"
btc_icon_invert = "assets/img/BTC.png"
eth_icon_invert = "assets/img/ETH.png"
else:
hns_icon = "assets/img/HNS.png"
btc_icon = "assets/img/BTC.png"
eth_icon = "assets/img/ETH.png"
hns_icon_invert = "assets/img/HNSW.png"
btc_icon_invert = "assets/img/BTCW.png"
eth_icon_invert = "assets/img/ETHW.png"
if (rgb_to_hex(generate_foreground_color(fg_colour)) == "#000000"):
hns_chat_icon = "assets/img/HNS.png"
location_icon = "assets/img/map.png"
email_icon = "assets/img/email.png"
else:
hns_chat_icon = "assets/img/HNSW.png"
location_icon = "assets/img/mapw.png"
email_icon = "assets/img/emailw.png"
hns_address = hns
btc_address = btc
eth_address = eth
hns_invert = hns_address
btc_invert = btc_address
eth_invert = eth_address
if hns != "":
hns = "<img src='" + hns_icon + "' width='20px' height='20px' style='margin-right: 5px;'>" + hns
hns_invert = "<img src='" + hns_icon_invert + "' width='20px' height='20px' style='margin-right: 5px;'>" + hns_address
if btc != "":
btc = "<img src='" + btc_icon + "' width='20px' height='25px' style='margin-right: 5px;'>" + btc
btc_invert = "<img src='" + btc_icon_invert + "' width='20px' height='25px' style='margin-right: 5px;'>" + btc_address
if eth != "":
eth = "<img src='" + eth_icon + "' width='20px' height='30px' style='margin-right: 5px;'>" + eth
eth_invert = "<img src='" + eth_icon_invert + "' width='20px' height='30px' style='margin-right: 5px;'>" + eth_address
hide_addresses = False
if hns == "" and btc == "" and eth == "":
hide_addresses = True
if hnschat != "":
hnschat = "<a href='https://hns.chat/#message:"+hnschat+"' target='_blank'><img src='"+hns_chat_icon+"' width='20px' height='20px' style='margin-right: 5px;'>" + hnschat + "/</a>"
if location != "":
location = "<img src='"+location_icon+"' width='20px' height='30px' style='margin-right: 5px;'>" + location
if email != "":
email = "<a href='mailto:"+email+"'><img src='"+email_icon+"' width='30px' height='20px' style='margin-right: 5px;margin-left:-10px;'>" + email + "</a>"
if avatar != "":
avatar = "<img src='"+avatar+"' width='200vw' height='200vw' style='border-radius: 50%;margin-right: 5px;'>"
else:
avatar = "<h1 style='color:"+fg_colour+";'>" + request.host.split(':')[0] + "/</h1>"
template = "Standard"
if 'template' in db_object:
if db_object['template'] != "":
template = db_object['template']
footer = render_template_string(FOOTER,main_domain=main_domain,fg_colour=fg_colour,hns_icon=hns_icon)
return render_template_string(get_template(template,hide_addresses),bg_colour=bg_colour,text_colour=text_colour,
fg_colour=fg_colour, avatar=avatar,main_domain=main_domain,
hnschat=hnschat,email=email,location=location, hns_icon=hns_icon,
hns=hns,btc=btc,eth=eth,hns_invert=hns_invert,btc_invert=btc_invert,
eth_invert=eth_invert,hns_address=hns_address,btc_address=btc_address,eth_address=eth_address,
hns_icon_invert=hns_icon_invert,btc_icon=btc_icon,btc_icon_invert=btc_icon_invert,
eth_icon=eth_icon,eth_icon_invert=eth_icon_invert,
data=html,footer=footer)
except Exception as e:
return redirect("https://" + main_domain + '/empty_site?error='+str(e))
def get_template(template,hide_addresses=False):
file = "templates/" +get_template_file(template)
with open(file) as f:
data = f.read()
# Read template
soup = BeautifulSoup(data, 'html.parser')
# Remove addresses div
if hide_addresses:
try:
addresses = soup.find(id="addresses")
addresses.decompose()
except:
pass
# If <!-- Matomo --> comment doesn't exist, add tracking to end of head
if 'Matomo' not in str(soup):
head = soup.find("head")
head.append(BeautifulSoup("""
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://analytics.woodburn.au/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '7']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
""", 'html.parser'))
return str(soup)
def calculate_contrast_ratio(color1, color2):
def calculate_luminance(color):
def adjust_color_value(value):
value /= 255.0
if value <= 0.03928:
return value / 12.92
return ((value + 0.055) / 1.055) ** 2.4
r, g, b = color
r = adjust_color_value(r)
g = adjust_color_value(g)
b = adjust_color_value(b)
return 0.2126 * r + 0.7152 * g + 0.0722 * b
luminance1 = calculate_luminance(color1)
luminance2 = calculate_luminance(color2)
brighter = max(luminance1, luminance2)
darker = min(luminance1, luminance2)
contrast_ratio = (brighter + 0.05) / (darker + 0.05)
return contrast_ratio
def generate_foreground_color(background_color):
# Convert to RGB tuple
background_color=background_color.lstrip('#')
background_color = tuple(int(background_color[i:i+2], 16) for i in (0, 2, 4))
contrast_color = (255, 255, 255) # White
ratio = calculate_contrast_ratio(background_color, contrast_color)
if ratio < 4.5:
return (0, 0, 0) # Black
else:
return contrast_color
def rgb_to_hex(rgb_color):
return "#{:02x}{:02x}{:02x}".format(*rgb_color)
def get_template_file(template):
if template.endswith(".html"):
return template
template = template.lower()
templates = {
"standard": "city.html",
"original": "city_old.html",
"no card around data": "city_no_card.html",
"no card around data (2)": "city_no_card_2.html",
"blank": "city_blank.html",
"standard with donate footer": "city_donate_footer.html",
"no card with donate footer": "city_no_card_donate_footer.html",
}
if template in templates:
return templates[template]
return "city.html"

71
template.py Normal file
View File

@@ -0,0 +1,71 @@
from flask import Flask, send_from_directory
import sys
import sites.website as website
import json
import os
app = Flask(__name__)
template = "city"
data = "<h1>Test site</h1><p>This is a test site</p>"
# data = "<div style=\"text-align:center;\"><h1>Nathan.Woodburn/</h1><h2>This is fully customizable!</h2><p>You can even add custom css rules like below.<br>Try hovering over this image</p><style>img.background:hover {filter: blur(5px)}</style><div class=\"profile-container\" style=\"height: 300px;margin-bottom: 2em;\"><img class=\"profile background\" src=\"https://nathan.woodburn.au/assets/img/profile.jpg\" style=\"border-radius: 50%;width: 300px;position: absolute;left: 50%;margin-left: -150px;aspect-ratio: 1;padding-top: calc(var(--s)/5);transform: scale(1);transition: .5s;\" alt=\"My Profile\"><img class=\"profile foreground\" src=\"https://nathan.woodburn.au/assets/img/pfront.webp\" alt=\"\" style=\"border-radius: 50%;pointer-events: none;width: 300px;position: absolute;left: 50%;margin-left: -150px;aspect-ratio: 1;padding-top: calc(var(--s)/5);transform: scale(1);transition: .5s;\"></div>"
db_object = {
'avatar': "https://woodburn.au/favicon.png",
'hnschat':"nathan.woodburn",
'location': "Australia",
'email': "test@email",
'HNS': "hs1qh7c98nexsrzwrmnh2avved6awe59jzpr3xx2xf",
'BTC': "bc1qhs94zzcw64qnwq4hvk056rwxwvgrkd7tq7d4xw",
'ETH' : "0x6cB4B39bEc23a921C9a20D061Bf17d4640B0d39e",
'bg_colour': "#000000",
# 'fg_colour': "#ffffff",
# 'text_colour': "#152D45",
'text_colour': "#ffffff",
'fg_colour': "#8f00db",
}
@app.route('/')
def index():
if os.path.exists("templates/"+template+".html"):
with open("templates/"+template+".html") as f:
filedata = f.read()
filedata = filedata.replace('#f1ffff', '{{fg_colour}}')
filedata = filedata.replace('#1fffff', '{{text_colour}}')
filedata = filedata.replace('#000000', '{{bg_colour}}')
# Save
with open('templates/' + template+".tmp.html", 'w') as f:
f.write(filedata)
else:
return "Template not found"
db_object['template'] = template + ".tmp.html"
render = website.render(data,db_object)
# Delete tmp
os.remove('templates/' + template+".tmp.html")
return render
@app.route('/assets/<path:path>')
def send_assets(path):
return send_from_directory('templates/assets', path)
@app.route('/.well-known/wallets/<path:path>')
def send_wallets(path):
if path in db_object:
return db_object[path]
else:
return "Not found"
if __name__ == "__main__":
# Get second arg
if len(sys.argv) > 1:
template = sys.argv[1]
else:
print("Usage: python3 template.py <template>")
sys.exit(0)
app.run(host='0.0.0.0', port=5000, debug=True)

View File

@@ -4,32 +4,70 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>shakecities</title>
<title>ShakeCities | Account</title>
<meta name="twitter:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="twitter:card" content="summary">
<meta property="og:type" content="website">
<meta property="og:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:title" content="ShakeCities">
<meta name="twitter:title" content="ShakeCities">
<meta name="twitter:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/styles.min.css">
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://analytics.woodburn.au/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '7']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
<script async src="https://umami.woodburn.au/script.js" data-website-id="9a7af01b-9ebf-49a9-8337-907ff3744a02"></script>
</head>
<body style="background: #000000;color: #ffffff;margin: auto;width: 95%;">
<section>
<section style="height: 15vh;background: url(&quot;assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp&quot;) bottom / cover no-repeat;min-height: 130px;"></section>
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="width: 30vw;border-radius: 50%;background: #000000;padding: 20px;height: 30vw;margin: auto;margin-top: -15vw;display: flex;"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></section>
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="width: 30vw;border-radius: 50%;background: #000000;padding: 20px;height: 30vw;margin: auto;margin-top: -15vw;display: flex;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="display: block;width: 100%;text-align: center;margin-top: 10px;">
<div style="display: inline-block;margin: auto;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/signup">Create your page</a><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account}}</a></div>
<div style="display: inline-block;margin: auto;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/signup">Create your page</a><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account_link_name}}</a></div>
</section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="display: block;">
<div style="width: 100%;text-align: right;margin-top: -4em;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/signup">Create a new page</a><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account_link_name}}</a></div>
</section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="width: 15vw;border-radius: 50%;background: #000000;padding: 20px;height: 15vw;margin: auto;display: flex;margin-top: -6vw;"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="width: 15vw;border-radius: 50%;background: #000000;padding: 20px;height: 15vw;margin: auto;display: flex;margin-top: -6vw;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="height: 3em;"></section>
</section>
<section style="margin-top: 50px;text-align: center;">
<h1>Welcome to ShakeCities</h1>
<p>Congratulations your site is ready for use.<br><br></p>
<div style="max-width: 10em;margin: auto;"><a class="btn btn-primary" role="button" href="https://{{site}}" style="display: block;margin: 10px;">Visit your site</a><a class="btn btn-primary" role="button" href="/edit" style="display: block;margin: 10px;">Edit your site</a><a class="btn btn-primary" role="button" href="/logout" style="display: block;margin: 10px;">Logout</a></div>
<p>Congratulations your site is ready for use.<br>Your site is available at <a href="https://{{sld}}.shakecities" target="_blank">{{sld}}.shakecities/</a> <a href="https://{{sld}}.shakec" target="_blank">{{sld}}.shakec/</a> &amp; <a href="https://{{sld}}.onsc" target="_blank">{{sld}}.onsc/</a><br><br></p>
<div style="max-width: 10em;margin: auto;"><a class="btn btn-primary" role="button" href="https://{{site}}" style="display: block;margin: 10px;" target="_blank">Visit your site</a><a class="btn btn-primary" role="button" href="/edit" style="display: block;margin: 10px;">Edit your site</a><a class="btn btn-primary" role="button" href="/{{tribe_link}}" style="display: block;margin: 10px;">{{tribe_title}}</a><a class="btn btn-primary" role="button" href="/hnschat" style="display: block;margin: 10px;">Link HNSChat</a><a class="btn btn-primary" role="button" href="/logout" style="display: block;margin: 10px;">Logout</a></div>
</section>
<section style="margin: 20px;height: 40px;text-align: center;margin-top: 40px;">
<div>
<p style="color: #ffffff;">Copyright © ShakeCities 2023</p>
<footer class="text-center bg-dark"></footer>
<div style="display: inline-block;">
<ul class="list-inline">
<li class="list-inline-item me-4" style="color: rgb(255,255,255);">Copyright © ShakeCities 2023</li>
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/54/uptime?labelPrefix=Main+Server+' style="height:1.3em;margin-bottom:-.3em;width: 13em;"></iframe></li>
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/55/uptime?labelPrefix=Cities+' style="height:1.3em;margin-bottom:-.3em;width:11em;"></iframe></li>
</ul>
</div>
</section>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>

1
templates/assets/css/city.min.css vendored Normal file
View File

@@ -0,0 +1 @@
a{color:inherit}

View File

@@ -1 +1 @@
.bs-icon{--bs-icon-size:.75rem;display:flex;flex-shrink:0;justify-content:center;align-items:center;font-size:var(--bs-icon-size);width:calc(var(--bs-icon-size) * 2);height:calc(var(--bs-icon-size) * 2);color:var(--bs-primary)}.bs-icon-xs{--bs-icon-size:1rem;width:calc(var(--bs-icon-size) * 1.5);height:calc(var(--bs-icon-size) * 1.5)}.bs-icon-sm{--bs-icon-size:1rem}.bs-icon-md{--bs-icon-size:1.5rem}.bs-icon-lg{--bs-icon-size:2rem}.bs-icon-xl{--bs-icon-size:2.5rem}.bs-icon.bs-icon-primary{color:var(--bs-white);background:var(--bs-primary)}.bs-icon.bs-icon-primary-light{color:var(--bs-primary);background:rgba(var(--bs-primary-rgb),.2)}.bs-icon.bs-icon-semi-white{color:var(--bs-primary);background:rgba(255,255,255,.5)}.bs-icon.bs-icon-rounded{border-radius:.5rem}.bs-icon.bs-icon-circle{border-radius:50%}.right-align{right:5%}
a{color:inherit}.bs-icon{--bs-icon-size:.75rem;display:flex;flex-shrink:0;justify-content:center;align-items:center;font-size:var(--bs-icon-size);width:calc(var(--bs-icon-size) * 2);height:calc(var(--bs-icon-size) * 2);color:var(--bs-primary)}.bs-icon-xs{--bs-icon-size:1rem;width:calc(var(--bs-icon-size) * 1.5);height:calc(var(--bs-icon-size) * 1.5)}.bs-icon-sm{--bs-icon-size:1rem}.bs-icon-md{--bs-icon-size:1.5rem}.bs-icon-lg{--bs-icon-size:2rem}.bs-icon-xl{--bs-icon-size:2.5rem}.bs-icon.bs-icon-primary{color:var(--bs-white);background:var(--bs-primary)}.bs-icon.bs-icon-primary-light{color:var(--bs-primary);background:rgba(var(--bs-primary-rgb),.2)}.bs-icon.bs-icon-semi-white{color:var(--bs-primary);background:rgba(255,255,255,.5)}.bs-icon.bs-icon-rounded{border-radius:.5rem}.bs-icon.bs-icon-circle{border-radius:50%}.right-align{right:0;margin-right:1%}.top-align{top:0;margin-top:1%}.sticky-bottom{width:100%;bottom:1%;left:0}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

81
templates/city.html Normal file
View File

@@ -0,0 +1,81 @@
<!DOCTYPE html>
<html data-bs-theme="light" lang="en" style="width: 100vw;height: 99vh;">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>ShakeCities</title>
<meta name="twitter:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="twitter:card" content="summary">
<meta property="og:type" content="website">
<meta property="og:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:title" content="ShakeCities">
<meta name="twitter:title" content="ShakeCities">
<meta name="twitter:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/styles.min.css">
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://analytics.woodburn.au/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '7']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
<script async src="https://umami.woodburn.au/script.js" data-website-id="9a7af01b-9ebf-49a9-8337-907ff3744a02"></script>
</head>
<body style="height: 99vh;width: 100vw;color: #1fffff;background: #000000;overflow-x: hidden;">
<div class="text-center" style="margin: 10px;">
<div>{{avatar|safe}}</div>
<div style="color: #f1ffff;">
<div>
<p style="font-size: 24px;">{{hnschat|safe}}</p>
</div>
<div>
<p style="font-size: 24px;">{{email|safe}}</p>
</div>
<div>
<p style="font-size: 24px;">{{location|safe}}</p>
</div>
</div>
</div>
<div style="background: #f1ffff;border-radius: 10px;padding: 25px;padding-top: 2%;padding-left: 2%;padding-right: 2%;padding-bottom: 2%;margin: 22px;">
<p style="font-size: 24px;">{{data|safe}}</p>
</div>
<div class="text-center" id="addresses" style="background: #f1ffff;padding: 25px;border-radius: 10px;margin: 22px;">
<h1>Donate</h1>
<div>
<div>
<p style="font-size: 24px;margin-bottom: 0px;"><a href="/.well-known/wallets/HNS" target="_blank">{{hns|safe}}</a></p>
</div>
<div>
<p style="font-size: 24px;margin-bottom: 0px;"><a href="/.well-known/wallets/BTC" target="_blank">{{btc|safe}}</a></p>
</div>
<div>
<p style="font-size: 24px;margin-bottom: 0px;"><a href="/.well-known/wallets/ETH" target="_blank">{{eth|safe}}</a></p>
</div>
</div>
</div>{{footer | safe}}
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="assets/js/script.min.js"></script>
</body>
</html>

58
templates/city_blank.html Normal file
View File

@@ -0,0 +1,58 @@
<!DOCTYPE html>
<html style="width: 100vw;height: 99vh;">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>ShakeCities</title>
<meta name="twitter:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="twitter:card" content="summary">
<meta property="og:type" content="website">
<meta property="og:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:title" content="ShakeCities">
<meta name="twitter:title" content="ShakeCities">
<meta name="twitter:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/styles.min.css">
</head>
<!-- Template colours
#f1ffff foreground colour
#1fffff text colour
#000000 background colour
These colours will be overriden with the user's colour scheme
-->
<body style="height: 99vh;width: 100vw;color: #1fffff;background: #000000;overflow-x: hidden;">
<!-- <div class="text-center" style="margin: 10px;">
<div>{{avatar|safe}}</div> This needs the safe filter to allow HTML to be rendered
<div style="color: #f1ffff;">
<p style="font-size: 24px;">{{hnschat|safe}}</p>
<p style="font-size: 24px;">{{email|safe}}</p>
<p style="font-size: 24px;">{{location|safe}}</p>
</div>
</div>
<div style="padding: 2%;margin: 22px;">
<p style="font-size: 24px;">
</p>
</div> -->
{{data|safe}} <!-- This needs the safe filter to allow HTML to be rendered -->
<!-- Footer to display the powered by ShakeCities. -->
{{footer|safe}}
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="assets/js/script.min.js"></script>
</body>
</html>

View File

@@ -0,0 +1,67 @@
<!DOCTYPE html>
<html data-bs-theme="light" lang="en" style="width: 100vw;height: 99vh;">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>ShakeCities</title>
<meta name="twitter:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="twitter:card" content="summary">
<meta property="og:type" content="website">
<meta property="og:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:title" content="ShakeCities">
<meta name="twitter:title" content="ShakeCities">
<meta name="twitter:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/styles.min.css">
</head>
<body style="height: 99vh;width: 100vw;color: #1fffff;background: #000000;overflow-x: hidden;">
<div class="text-center" style="margin: 10px;">
<div>{{avatar|safe}}</div>
<div style="color: #f1ffff;">
<div>
<p style="font-size: 24px;">{{hnschat|safe}}</p>
</div>
<div>
<p style="font-size: 24px;">{{email|safe}}</p>
</div>
<div>
<p style="font-size: 24px;">{{location|safe}}</p>
</div>
</div>
</div>
<div style="background: #f1ffff;border-radius: 10px;padding: 25px;padding-top: 2%;padding-left: 2%;padding-right: 2%;padding-bottom: 2%;margin: 22px;">
<p style="font-size: 24px;">{{data|safe}}</p>
</div>
<div id="addresses" style="width: 100%;text-align: center;">
<p style="font-size: 20px;margin-bottom: 0px;">
<a style="text-decoration: none;color: #f1ffff;" href="/.well-known/wallets/HNS" target="_blank">
<img src='{{hns_icon_invert}}' width='20px' height='20px' style='margin-right: 5px;'>
</a>
<a style="text-decoration: none;color: #f1ffff;" href="/.well-known/wallets/BTC" target="_blank">
<img src='{{btc_icon_invert}}' width='20px' height='25px' style='margin-right: 5px;'>
</a>
<a style="text-decoration: none;color: #f1ffff;" href="/.well-known/wallets/ETH" target="_blank">
<img src='{{eth_icon_invert}}' width='20px' height='30px' style='margin-right: 5px;'>
</a>
</p>
</div>
<div style="height: 25px;"></div>
{{footer | safe}}
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="assets/js/script.min.js"></script>
</body>
</html>

View File

@@ -0,0 +1,65 @@
<!DOCTYPE html>
<html style="width: 100vw;height: 99vh;">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>ShakeCities</title>
<meta name="twitter:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="twitter:card" content="summary">
<meta property="og:type" content="website">
<meta property="og:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:title" content="ShakeCities">
<meta name="twitter:title" content="ShakeCities">
<meta name="twitter:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/styles.min.css">
</head>
<!-- Template colours
#f1ffff foreground colour
#1fffff text colour
#000000 background colour
These colours will be overriden with the user's colour scheme
-->
<body style="height: 99vh;width: 100vw;color: #1fffff;background: #000000;overflow-x: hidden;">
<div class="text-center" style="margin: 10px;">
<div>{{avatar|safe}}</div> <!-- This needs the safe filter to allow HTML to be rendered -->
<div style="color: #f1ffff;">
<p style="font-size: 24px;">{{hnschat|safe}}</p>
<p style="font-size: 24px;">{{email|safe}}</p>
<p style="font-size: 24px;">{{location|safe}}</p>
</div>
</div>
<div style="padding: 2%;margin: 22px;">
<p style="font-size: 24px;">
{{data|safe}} <!-- This needs the safe filter to allow HTML to be rendered -->
</p>
</div>
<div class="text-center" id="addresses" style="background: #f1ffff;padding: 25px;border-radius: 10px;margin: 22px;"> <!-- Adding the id addresses will remove this div from the page when the user doesn't have any addresses -->
<h1>Donate</h1>
<div>
<p style="font-size: 24px;margin-bottom: 0px;"><a href="/.well-known/wallets/HNS" target="_blank">{{hns|safe}}</a></p>
<p style="font-size: 24px;margin-bottom: 0px;"><a href="/.well-known/wallets/BTC" target="_blank">{{btc|safe}}</a></p>
<p style="font-size: 24px;margin-bottom: 0px;"><a href="/.well-known/wallets/ETH" target="_blank">{{eth|safe}}</a></p>
</div>
</div>
<!-- Footer to display the powered by ShakeCities. -->
{{footer|safe}}
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="assets/js/script.min.js"></script>
</body>
</html>

View File

@@ -0,0 +1,65 @@
<!DOCTYPE html>
<html style="width: 100vw;height: 99vh;">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>ShakeCities</title>
<meta name="twitter:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="twitter:card" content="summary">
<meta property="og:type" content="website">
<meta property="og:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:title" content="ShakeCities">
<meta name="twitter:title" content="ShakeCities">
<meta name="twitter:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/styles.min.css">
</head>
<!-- Template colours
#f1ffff foreground colour
#1fffff text colour
#000000 background colour
These colours will be overriden with the user's colour scheme
-->
<body style="height: 99vh;width: 100vw;color: #1fffff;background: #000000;overflow-x: hidden;">
<div class="text-center" style="margin: 10px;">
<div>{{avatar|safe}}</div> <!-- This needs the safe filter to allow HTML to be rendered -->
<div style="color: #f1ffff;">
<p style="font-size: 24px;">{{hnschat|safe}}</p>
<p style="font-size: 24px;">{{email|safe}}</p>
<p style="font-size: 24px;">{{location|safe}}</p>
</div>
</div>
<div style="padding: 2%;margin: 22px;">
<p style="font-size: 24px;">
{{data|safe}} <!-- This needs the safe filter to allow HTML to be rendered -->
</p>
</div>
<div class="text-center" id="addresses" style="padding: 25px;border-radius: 10px;margin: 22px;"> <!-- Adding the id addresses will remove this div from the page when the user doesn't have any addresses -->
<h1>Donate</h1>
<div>
<p style="font-size: 24px;margin-bottom: 0px;"><a href="/.well-known/wallets/HNS" target="_blank">{{hns|safe}}</a></p>
<p style="font-size: 24px;margin-bottom: 0px;"><a href="/.well-known/wallets/BTC" target="_blank">{{btc|safe}}</a></p>
<p style="font-size: 24px;margin-bottom: 0px;"><a href="/.well-known/wallets/ETH" target="_blank">{{eth|safe}}</a></p>
</div>
</div>
<!-- Footer to display the powered by ShakeCities. -->
{{footer|safe}}
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="assets/js/script.min.js"></script>
</body>
</html>

View File

@@ -0,0 +1,70 @@
<!DOCTYPE html>
<html style="width: 100vw;height: 99vh;">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>ShakeCities</title>
<meta name="twitter:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="twitter:card" content="summary">
<meta property="og:type" content="website">
<meta property="og:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:title" content="ShakeCities">
<meta name="twitter:title" content="ShakeCities">
<meta name="twitter:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/styles.min.css">
</head>
<!-- Template colours
#f1ffff foreground colour
#1fffff text colour
#000000 background colour
These colours will be overriden with the user's colour scheme
-->
<body style="height: 99vh;width: 100vw;color: #1fffff;background: #000000;overflow-x: hidden;">
<div class="text-center" style="margin: 10px;">
<div>{{avatar|safe}}</div> <!-- This needs the safe filter to allow HTML to be rendered -->
<div style="color: #f1ffff;">
<p style="font-size: 24px;">{{hnschat|safe}}</p>
<p style="font-size: 24px;">{{email|safe}}</p>
<p style="font-size: 24px;">{{location|safe}}</p>
</div>
</div>
<div style="padding: 2%;margin: 22px;">
<p style="font-size: 24px;">
{{data|safe}} <!-- This needs the safe filter to allow HTML to be rendered -->
</p>
</div>
<div id="addresses" style="width: 100%;text-align: center;">
<p style="font-size: 20px;margin-bottom: 0px;">
<a style="text-decoration: none;color: #f1ffff;" href="/.well-known/wallets/HNS" target="_blank">
<img src='{{hns_icon_invert}}' width='20px' height='20px' style='margin-right: 5px;'>
</a>
<a style="text-decoration: none;color: #f1ffff;" href="/.well-known/wallets/BTC" target="_blank">
<img src='{{btc_icon_invert}}' width='20px' height='25px' style='margin-right: 5px;'>
</a>
<a style="text-decoration: none;color: #f1ffff;" href="/.well-known/wallets/ETH" target="_blank">
<img src='{{eth_icon_invert}}' width='20px' height='30px' style='margin-right: 5px;'>
</a>
</p>
</div>
<div style="height: 25px;"></div>
<!-- Footer to display the powered by ShakeCities. -->
{{footer|safe}}
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="assets/js/script.min.js"></script>
</body>
</html>

89
templates/city_old.html Normal file
View File

@@ -0,0 +1,89 @@
<!DOCTYPE html>
<html data-bs-theme="light" lang="en" style="width: 100vw;height: 99vh;">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>ShakeCities</title>
<meta name="twitter:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="twitter:card" content="summary">
<meta property="og:type" content="website">
<meta property="og:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:title" content="ShakeCities">
<meta name="twitter:title" content="ShakeCities">
<meta name="twitter:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/styles.min.css">
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://analytics.woodburn.au/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '7']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
<script async src="https://umami.woodburn.au/script.js" data-website-id="9a7af01b-9ebf-49a9-8337-907ff3744a02"></script>
</head>
<body style="height: 99vh;width: 100vw;color: #1fffff;background: #000000;overflow-x: hidden;">
<div style="margin: 10px;">
<div class="row row-cols-1 row-cols-sm-1 row-cols-md-1 row-cols-lg-1 row-cols-xl-2 row-cols-xxl-2 justify-content-center align-items-center" style="margin: 0px;">
<div class="col text-center align-self-center m-auto">
<div class="d-xl-flex align-items-xl-center" style="background: #f1ffff;padding: 10px;border-radius: 10px;">
<div>{{avatar|safe}}</div>
<div class="d-none d-sm-none d-md-none d-lg-none d-xl-block d-xxl-block" style="width: 40px;"></div>
<div>
<div>
<p style="font-size: 24px;">{{hnschat|safe}}</p>
</div>
<div>
<p style="font-size: 24px;">{{email|safe}}</p>
</div>
<div>
<p style="font-size: 24px;">{{location|safe}}</p>
</div>
</div>
</div>
</div>
<div class="col text-center align-self-center m-auto">
<div class="d-xl-flex align-items-xl-center" id="addresses" style="background: #f1ffff;padding: 10px;border-radius: 10px;">
<div>
<div>
<p style="font-size: 24px;margin-bottom: 0px;"><a href="/.well-known/wallets/HNS" target="_blank">{{hns|safe}}</a></p>
</div>
<div>
<p style="font-size: 24px;margin-bottom: 0px;"><a href="/.well-known/wallets/BTC" target="_blank">{{btc|safe}}</a></p>
</div>
<div>
<p style="font-size: 24px;margin-bottom: 0px;"><a href="/.well-known/wallets/ETH" target="_blank">{{eth|safe}}</a></p>
</div>
</div>
</div>
</div>
</div>
</div>
<div style="background: #f1ffff;border-radius: 10px;padding-top: 2%;padding-left: 2%;padding-right: 2%;padding-bottom: 2%;margin: 22px;">
<p style="font-size: 24px;">{{data|safe}}</p>
</div>{{footer | safe}}
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="assets/js/script.min.js"></script>
</body>
</html>

View File

@@ -0,0 +1,65 @@
<!DOCTYPE html>
<html style="width: 100vw;height: 99vh;">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>ShakeCities</title>
<meta name="twitter:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="twitter:card" content="summary">
<meta property="og:type" content="website">
<meta property="og:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:title" content="ShakeCities">
<meta name="twitter:title" content="ShakeCities">
<meta name="twitter:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/styles.min.css">
</head>
<!-- Template colours
#f1ffff foreground colour
#1fffff text colour
#000000 background colour
These colours will be overriden with the user's colour scheme
-->
<body style="height: 99vh;width: 100vw;color: #1fffff;background: #000000;overflow-x: hidden;">
<div class="text-center" style="margin: 10px;">
<div>{{avatar|safe}}</div> <!-- This needs the safe filter to allow HTML to be rendered -->
<div style="color: #f1ffff;">
<p style="font-size: 24px;">{{hnschat|safe}}</p>
<p style="font-size: 24px;">{{email|safe}}</p>
<p style="font-size: 24px;">{{location|safe}}</p>
</div>
</div>
<div style="background: #f1ffff;border-radius: 10px;padding: 2%;margin: 22px;">
<p style="font-size: 24px;">
{{data|safe}} <!-- This needs the safe filter to allow HTML to be rendered -->
</p>
</div>
<div class="text-center" id="addresses" style="background: #f1ffff;padding: 25px;border-radius: 10px;margin: 22px;"> <!-- Adding the id addresses will remove this div from the page when the user doesn't have any addresses -->
<h1>Donate</h1>
<div>
<p style="font-size: 24px;margin-bottom: 0px;"><a href="/.well-known/wallets/HNS" target="_blank">{{hns|safe}}</a></p>
<p style="font-size: 24px;margin-bottom: 0px;"><a href="/.well-known/wallets/BTC" target="_blank">{{btc|safe}}</a></p>
<p style="font-size: 24px;margin-bottom: 0px;"><a href="/.well-known/wallets/ETH" target="_blank">{{eth|safe}}</a></p>
</div>
</div>
<!-- Footer to display the powered by ShakeCities. -->
{{footer|safe}}
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="assets/js/script.min.js"></script>
</body>
</html>

View File

@@ -4,36 +4,94 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>shakecities</title>
<title>ShakeCities | Edit</title>
<meta name="twitter:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="twitter:card" content="summary">
<meta property="og:type" content="website">
<meta property="og:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:title" content="ShakeCities">
<meta name="twitter:title" content="ShakeCities">
<meta name="twitter:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/styles.min.css">
<link rel="stylesheet" href="https://netdna.bootstrapcdn.com/font-awesome/4.0.0/css/font-awesome.min.css">
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://analytics.woodburn.au/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '7']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
<script async src="https://umami.woodburn.au/script.js" data-website-id="9a7af01b-9ebf-49a9-8337-907ff3744a02"></script>
</head>
<body style="background: #000000;color: #ffffff;">
<body style="background: #000000;color: #ffffff;width: 95%;margin: auto;">
<section>
<section style="height: 15vh;background: url(&quot;assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp&quot;) bottom / cover no-repeat;min-height: 130px;"></section>
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="width: 30vw;border-radius: 50%;background: #000000;padding: 20px;height: 30vw;margin: auto;margin-top: -15vw;display: flex;"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></section>
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="width: 30vw;border-radius: 50%;background: #000000;padding: 20px;height: 30vw;margin: auto;margin-top: -15vw;display: flex;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="display: block;width: 100%;text-align: center;margin-top: 10px;">
<div style="display: inline-block;margin: auto;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/signup">Create your page</a><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account}}</a></div>
<div style="display: inline-block;margin: auto;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/signup">Create your page</a><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account_link_name}}</a></div>
</section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="display: block;">
<div style="width: 100%;text-align: right;margin-top: -4em;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/signup">Create a new page</a><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account_link_name}}</a></div>
</section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="width: 15vw;border-radius: 50%;background: #000000;padding: 20px;height: 15vw;margin: auto;display: flex;margin-top: -6vw;"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="width: 15vw;border-radius: 50%;background: #000000;padding: 20px;height: 15vw;margin: auto;display: flex;margin-top: -6vw;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="height: 3em;"></section>
</section>
<section style="margin-top: 50px;">
<h1 style="text-align: center;margin-bottom: 30px;">Edit your page</h1>
</section>
<section style="width: 80%;margin: auto;">
<form method="post"><input class="form-control" type="text" style="margin-top: 10px;" name="avatar" value="{{avatar}}" placeholder="Avatar URL"><input class="form-control" type="text" style="margin-top: 10px;" name="location" value="{{location}}" placeholder="Location"><input class="form-control" type="text" style="margin-top: 10px;" name="hnschat" placeholder="HNSChat" value="{{hnschat}}">
<div class="d-xl-flex justify-content-xl-center align-items-xl-center" style="margin-bottom: 10px;margin-top: 10px;"><label class="form-label" style="display: inline-block;margin-right: 15px;">Background colour&nbsp;</label><input class="form-control form-control-color" type="color" style="display: inline-block;border-radius: 50%;width: 50px;height: 50px;" name="bg_colour" value="{{bg_colour}}"></div><textarea class="form-control form-control-lg" rows="15" name="data" placeholder="HTML Content">{{data}}</textarea><input class="form-control" type="text" style="margin-top: 10px;" placeholder="HNS Address" name="hns" value="{{hns}}"><input class="form-control" type="text" style="margin-top: 10px;" name="btc" placeholder="BTC Address" value="{{btc}}"><input class="form-control" type="text" style="margin-top: 10px;" placeholder="ETH Address" name="eth" value="{{eth}}">
<form action="/upload" method="post" enctype="multipart/form-data"><label class="form-label" style="margin-right: 20px;">Avatar</label>
<div style="display: inline-block;">{{avatar|safe}}</div><input class="form-control" type="file" style="display: inline-block;width: 300px;margin-right: 25px;" name="file" accept="image/*" required=""><input class="btn btn-primary" type="submit" style="margin-right: 20px;" value="Upload"><a class="btn btn-primary" role="button" href="/avatar/clear">Clear</a>
</form>
<form class="text-center" method="post"><input class="form-control" type="text" style="margin-top: 10px;" name="location" value="{{location}}" placeholder="Location"><input class="form-control" type="text" style="margin-top: 10px;" name="hnschat" placeholder="HNSChat" value="{{hnschat}}"><input class="form-control" type="text" style="margin-top: 10px;" name="email" placeholder="Public Email" value="{{email}}">
<div class="d-xl-flex justify-content-xl-center align-items-xl-center" style="margin-bottom: 10px;margin-top: 10px;"><label class="form-label" style="display: inline-block;margin-right: 15px;">Background colour&nbsp;</label><input class="form-control form-control-color" type="color" style="display: inline-block;border-radius: 50%;width: 50px;height: 50px;" name="bg_colour" value="{{bg_colour}}"></div>
<div class="d-xl-flex justify-content-xl-center align-items-xl-center" style="margin-bottom: 10px;margin-top: 10px;"><label class="form-label" style="display: inline-block;margin-right: 15px;">Foreground colour&nbsp;</label><input class="form-control form-control-color" type="color" style="display: inline-block;border-radius: 50%;width: 50px;height: 50px;" name="fg_colour" value="{{fg_colour}}"></div>
<div class="d-xl-flex justify-content-xl-center align-items-xl-center" style="margin-bottom: 10px;margin-top: 10px;"><label class="form-label" style="display: inline-block;margin-right: 15px;">Text colour&nbsp;</label><input class="form-control form-control-color" type="color" style="display: inline-block;border-radius: 50%;width: 50px;height: 50px;" name="text_colour" value="{{text_colour}}"></div><textarea class="form-control form-control-lg" rows="15" name="data" placeholder="HTML Content">{{data}}</textarea>
<div class="text-center">
<div><input class="form-control" type="text" style="margin-top: 10px;display: inline-block;width: 500px;" placeholder="HNS Address" name="hns" value="{{hns}}" pattern="hs1[A-Za-z0-9]+"><div class="form-check form-switch form-check-inline" style="display: inline-block;margin-left: 10px;">
<input id="formCheck-1" class="form-check-input" type="checkbox" {% if hip2_display %}checked{% endif %} name="hip2_display" />
<label class="form-check-label" for="formCheck-1">Show as @{{domain}}.{{CITY_DOMAIN}}</label>
</div>
</div>
<div><input class="form-control" type="text" style="margin-top: 10px;width: 500px;display: inline-block;" name="btc" placeholder="BTC Address" value="{{btc}}"></div>
<div><input class="form-control" type="text" style="margin-top: 10px;width: 500px;display: inline-block;" placeholder="ETH Address" name="eth" value="{{eth}}" pattern="0x[A-Za-z0-9]+"></div>
</div>
<div style="margin-top: 10px;display: inline-block;"><label class="form-label" style="margin-right: 25px;">Template</label><select class="form-select" id="template" name="template" style="width:auto;display:inline-block;">
{% for template in templates %}
<option value="{{ template }}" {% if template == selected_template %}selected{% endif %}>{{ template }}</option>
{% endfor %}
</select></div>
<div style="text-align: center;"><input class="btn btn-primary" type="submit" style="margin-top: 10px;"></div>
</form>
</section>
<section style="margin: 20px;height: 40px;text-align: center;margin-top: 40px;">
<div>
<p style="color: #ffffff;">Copyright © ShakeCities 2023</p>
<footer class="text-center bg-dark"></footer>
<div style="display: inline-block;">
<ul class="list-inline">
<li class="list-inline-item me-4" style="color: rgb(255,255,255);">Copyright © ShakeCities 2023</li>
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/54/uptime?labelPrefix=Main+Server+' style="height:1.3em;margin-bottom:-.3em;width: 13em;"></iframe></li>
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/55/uptime?labelPrefix=Cities+' style="height:1.3em;margin-bottom:-.3em;width:11em;"></iframe></li>
</ul>
</div>
</section>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>

120
templates/edit_tribe.html Normal file
View File

@@ -0,0 +1,120 @@
<!DOCTYPE html>
<html data-bs-theme="light" lang="en" style="background: black;">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>ShakeCities | Tribes</title>
<meta name="twitter:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="twitter:card" content="summary">
<meta property="og:type" content="website">
<meta property="og:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:title" content="ShakeCities">
<meta name="twitter:title" content="ShakeCities">
<meta name="twitter:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/styles.min.css">
<link rel="stylesheet" href="https://netdna.bootstrapcdn.com/font-awesome/4.0.0/css/font-awesome.min.css">
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://analytics.woodburn.au/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '7']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
<script async src="https://umami.woodburn.au/script.js" data-website-id="9a7af01b-9ebf-49a9-8337-907ff3744a02"></script>
</head>
<body style="width: 95%;margin: auto;background: transparent;color: #ffffff;">
<section>
<section style="height: 15vh;background: url(&quot;assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp&quot;) bottom / cover no-repeat;min-height: 130px;"></section>
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="width: 30vw;border-radius: 50%;background: #000000;padding: 20px;height: 30vw;margin: auto;margin-top: -15vw;display: flex;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="display: block;width: 100%;text-align: center;margin-top: 10px;">
<div style="display: inline-block;margin: auto;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/signup">Create your page</a><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account_link_name}}</a></div>
</section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="display: block;">
<div style="width: 100%;text-align: right;margin-top: -4em;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account_link_name}}</a></div>
</section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="width: 15vw;border-radius: 50%;background: #000000;padding: 20px;height: 15vw;margin: auto;display: flex;margin-top: -6vw;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="height: 3em;"></section>
</section>
<section style="margin-top: 10px;">
<div class="row" style="margin: 0px;">
<div class="col" style="background: var(--bs-body-color);margin-right: 10px;border-radius: 10px;margin-top: 10px;margin-left: 10px;">
<h1 style="margin: 10px;">Edit {{tribe}} tribe</h1>
<form method="post" style="margin-bottom: 20px;"><input class="form-control" type="text" style="margin-top: 20px;" name="tribe" placeholder="Tribe Name" value="{{tribe}}"><textarea class="form-control" style="margin-top: 20px;" rows="5" placeholder="Content" name="data">{{data}}</textarea>
<p style="margin-top: 20px;">{{members|safe}}</p><input class="btn btn-primary" type="submit" style="margin-top: 20px;" value="Edit"><a class="btn btn-primary" role="button" style="margin-top: 20px;margin-left: 50px;" href="/delete_tribe">Delete Tribe</a>
</form>
</div>
</div>
</section>
<section>
<section class="d-print-none d-md-none d-lg-none d-xl-none d-xxl-none" style="background: var(--bs-body-color);text-align: center;padding-top: 10px;padding-bottom: 10px;margin-bottom: 25px;margin-top: 40px;border-radius: 10px;">
<div style="margin: 20px;">
<h1>Contact</h1>
<div class="list-group list-group-horizontal" data-bs-theme="dark" style="margin: auto;width: 80%;"><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://discord.com">Discord</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="mailto:email@example.com">Email</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://twitter.com">Twitter</a></button></div>
</div>
<div style="margin: 20px;">
<h1>Donate</h1>
<p>hs1qfqy9ewc3g4p06d4m5j8zm74qzhan7rxu7n8u9y</p>
</div>
</section>
<section class="d-none d-print-block d-md-block d-lg-block d-xl-block d-xxl-block" style="background: var(--bs-body-color);text-align: center;padding-top: 10px;padding-bottom: 10px;margin-bottom: 25px;margin-top: 40px;border-radius: 10px;">
<div style="margin: 20px;">
<h1>Contact</h1>
<div class="list-group list-group-horizontal" data-bs-theme="dark" style="margin: auto;width: 50%;"><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://l.woodburn.au/discord">Discord</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="mailto:shakecities@woodburn.au">Email</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://hnschat#channel:woodburn">HNSChat</a></button></div>
</div>
<div style="margin: 20px;">
<h1>Donate</h1>
<p data-bs-toggle="tooltip" data-bss-tooltip="" id="hns_address" title="Copy">hs1qfqy9ewc3g4p06d4m5j8zm74qzhan7rxu7n8u9y</p><script>
function copyToClipboard(element) {
const textToCopy = element.textContent;
const textArea = document.createElement('textarea');
textArea.value = textToCopy;
document.body.appendChild(textArea);
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);
}
const hns = document.getElementById('hns_address');
hns.addEventListener('click', () => {
copyToClipboard(hns);
});
</script>
</div>
</section>
</section>
<section style="margin: 20px;height: 40px;text-align: center;margin-top: 40px;">
<footer class="text-center bg-dark"></footer>
<div style="display: inline-block;">
<ul class="list-inline">
<li class="list-inline-item me-4" style="color: rgb(255,255,255);">Copyright © ShakeCities 2023</li>
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/54/uptime?labelPrefix=Main+Server+' style="height:1.3em;margin-bottom:-.3em;width: 13em;"></iframe></li>
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/55/uptime?labelPrefix=Cities+' style="height:1.3em;margin-bottom:-.3em;width:11em;"></iframe></li>
</ul>
</div>
</section>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="assets/js/script.min.js"></script>
</body>
</html>

79
templates/empty_site.html Normal file
View File

@@ -0,0 +1,79 @@
<!DOCTYPE html>
<html data-bs-theme="light" lang="en" style="background: #000000;">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>ShakeCities | Empty Site</title>
<meta name="twitter:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="twitter:card" content="summary">
<meta property="og:type" content="website">
<meta property="og:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:title" content="ShakeCities">
<meta name="twitter:title" content="ShakeCities">
<meta name="twitter:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/styles.min.css">
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://analytics.woodburn.au/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '7']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
<script async src="https://umami.woodburn.au/script.js" data-website-id="9a7af01b-9ebf-49a9-8337-907ff3744a02"></script>
</head>
<body style="background: #000000;width: 95%;margin: auto;">
<section>
<section style="height: 15vh;background: url(&quot;assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp&quot;) bottom / cover no-repeat;min-height: 130px;"></section>
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="width: 30vw;border-radius: 50%;background: #000000;padding: 20px;height: 30vw;margin: auto;margin-top: -15vw;display: flex;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="display: block;width: 100%;text-align: center;margin-top: 10px;">
<div style="display: inline-block;margin: auto;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/signup">Create your page</a><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account_link_name}}</a></div>
</section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="display: block;">
<div style="width: 100%;text-align: right;margin-top: -4em;"></div>
</section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="width: 15vw;border-radius: 50%;background: #000000;padding: 20px;height: 15vw;margin: auto;display: flex;margin-top: -6vw;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="height: 3em;"></section>
</section>
<section style="width: 50%;margin: auto;margin-top: 50px;">
<div class="card bg-dark" style="padding-bottom: 40px;">
<div class="card-body">
<h4 class="card-title" style="color: rgb(255,255,255);">Nothing here yet</h4>
</div><a class="btn btn-primary" role="button" style="margin: 10px;" href="/">Back</a>
</div>
</section>
<section style="margin: 20px;height: 40px;text-align: center;margin-top: 40px;">
<footer class="text-center bg-dark"></footer>
<div style="display: inline-block;">
<ul class="list-inline">
<li class="list-inline-item me-4" style="color: rgb(255,255,255);">Copyright © ShakeCities 2023</li>
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/54/uptime?labelPrefix=Main+Server+' style="height:1.3em;margin-bottom:-.3em;width: 13em;"></iframe></li>
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/55/uptime?labelPrefix=Cities+' style="height:1.3em;margin-bottom:-.3em;width:11em;"></iframe></li>
</ul>
</div>
</section>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="assets/js/script.min.js"></script>
</body>
</html>

80
templates/error.html Normal file
View File

@@ -0,0 +1,80 @@
<!DOCTYPE html>
<html data-bs-theme="light" lang="en" style="background: #000000;">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>ShakeCities | Error</title>
<meta name="twitter:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="twitter:card" content="summary">
<meta property="og:type" content="website">
<meta property="og:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:title" content="ShakeCities">
<meta name="twitter:title" content="ShakeCities">
<meta name="twitter:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/styles.min.css">
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://analytics.woodburn.au/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '7']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
<script async src="https://umami.woodburn.au/script.js" data-website-id="9a7af01b-9ebf-49a9-8337-907ff3744a02"></script>
</head>
<body style="background: #000000;width: 95%;margin: auto;">
<section>
<section style="height: 15vh;background: url(&quot;assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp&quot;) bottom / cover no-repeat;min-height: 130px;"></section>
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="width: 30vw;border-radius: 50%;background: #000000;padding: 20px;height: 30vw;margin: auto;margin-top: -15vw;display: flex;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="display: block;width: 100%;text-align: center;margin-top: 10px;">
<div style="display: inline-block;margin: auto;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/signup">Create your page</a><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account_link_name}}</a></div>
</section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="display: block;">
<div style="width: 100%;text-align: right;margin-top: -4em;"></div>
</section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="width: 15vw;border-radius: 50%;background: #000000;padding: 20px;height: 15vw;margin: auto;display: flex;margin-top: -6vw;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="height: 3em;"></section>
</section>
<section style="width: 50%;margin: auto;margin-top: 50px;">
<div class="card bg-dark" style="padding-bottom: 40px;">
<div class="card-body">
<h4 class="card-title" style="color: rgb(255,255,255);">Sorry we ran into an error</h4>
<p style="color: rgb(255,255,255);text-align: center;">{{message | safe}}</p>
</div><a class="btn btn-primary" role="button" style="margin: 10px;" href="javascript:history.back()">Back</a>
</div>
</section>
<section style="margin: 20px;height: 40px;text-align: center;margin-top: 40px;">
<footer class="text-center bg-dark"></footer>
<div style="display: inline-block;">
<ul class="list-inline">
<li class="list-inline-item me-4" style="color: rgb(255,255,255);">Copyright © ShakeCities 2023</li>
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/54/uptime?labelPrefix=Main+Server+' style="height:1.3em;margin-bottom:-.3em;width: 13em;"></iframe></li>
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/55/uptime?labelPrefix=Cities+' style="height:1.3em;margin-bottom:-.3em;width:11em;"></iframe></li>
</ul>
</div>
</section>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="assets/js/script.min.js"></script>
</body>
</html>

81
templates/hnschat.html Normal file
View File

@@ -0,0 +1,81 @@
<!DOCTYPE html>
<html data-bs-theme="light" lang="en" style="background: #000000;">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>ShakeCities | HNSChat</title>
<meta name="twitter:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="twitter:card" content="summary">
<meta property="og:type" content="website">
<meta property="og:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:title" content="ShakeCities">
<meta name="twitter:title" content="ShakeCities">
<meta name="twitter:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/styles.min.css">
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://analytics.woodburn.au/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '7']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
<script async src="https://umami.woodburn.au/script.js" data-website-id="9a7af01b-9ebf-49a9-8337-907ff3744a02"></script>
</head>
<body style="background: #000000;color: #ffffff;width: 95%;margin: auto;">
<section>
<section style="height: 15vh;background: url(&quot;assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp&quot;) bottom / cover no-repeat;min-height: 130px;"></section>
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="width: 30vw;border-radius: 50%;background: #000000;padding: 20px;height: 30vw;margin: auto;margin-top: -15vw;display: flex;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="display: block;width: 100%;text-align: center;margin-top: 10px;">
<div style="display: inline-block;margin: auto;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/signup">Create your page</a><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account_link_name}}</a></div>
</section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="display: block;">
<div style="width: 100%;text-align: right;margin-top: -4em;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/signup">Create a new page</a><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account_link_name}}</a></div>
</section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="width: 15vw;border-radius: 50%;background: #000000;padding: 20px;height: 15vw;margin: auto;display: flex;margin-top: -6vw;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="height: 3em;"></section>
</section>
<section style="margin-top: 50px;">
<h1 style="text-align: center;margin-bottom: 30px;">HNSChat</h1>
</section>
<section style="width: 80%;margin: auto;">
<p>Link your domain to HNSChat using Varo Auth.<br>1. Click Authenticate with Varo Auth<br>2. Enter {{domain}}<br>3. Copy TXT record (including the varo= part) into the below box and save<br>4. Verify your domain (it might take a few minutes for the cache to clear)</p>
<form method="post"><input class="form-control" type="text" style="margin-top: 10px;" name="hnschat" value="{{hnschat}}" placeholder="varo=....." required="" minlength="5">
<div style="text-align: center;"><input class="btn btn-primary" type="submit" style="margin-top: 10px;"></div>
</form>
</section>
<section style="margin: 20px;height: 40px;text-align: center;margin-top: 40px;">
<footer class="text-center bg-dark"></footer>
<div style="display: inline-block;">
<ul class="list-inline">
<li class="list-inline-item me-4" style="color: rgb(255,255,255);">Copyright © ShakeCities 2023</li>
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/54/uptime?labelPrefix=Main+Server+' style="height:1.3em;margin-bottom:-.3em;width: 13em;"></iframe></li>
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/55/uptime?labelPrefix=Cities+' style="height:1.3em;margin-bottom:-.3em;width:11em;"></iframe></li>
</ul>
</div>
</section>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="assets/js/script.min.js"></script>
</body>
</html>

View File

@@ -4,33 +4,80 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>shakecities</title>
<title>ShakeCities</title>
<meta name="twitter:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="twitter:card" content="summary">
<meta property="og:type" content="website">
<meta property="og:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:title" content="ShakeCities">
<meta name="twitter:title" content="ShakeCities">
<meta name="twitter:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "WebSite",
"name": "ShakeCities",
"url": "https://shakecities.com"
}
</script>
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/styles.min.css">
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://analytics.woodburn.au/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '7']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
<script async src="https://umami.woodburn.au/script.js" data-website-id="9a7af01b-9ebf-49a9-8337-907ff3744a02"></script>
</head>
<body style="width: 95%;margin: auto;background: transparent;color: #ffffff;">
<section>
<section style="height: 15vh;background: url(&quot;assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp&quot;) bottom / cover no-repeat;min-height: 130px;"></section>
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="width: 30vw;border-radius: 50%;background: #000000;padding: 20px;height: 30vw;margin: auto;margin-top: -15vw;display: flex;"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></section>
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="width: 30vw;border-radius: 50%;background: #000000;padding: 20px;height: 30vw;margin: auto;margin-top: -15vw;display: flex;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="display: block;width: 100%;text-align: center;margin-top: 10px;">
<div style="display: inline-block;margin: auto;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/signup">Create your page</a><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account}}</a></div>
<div style="display: inline-block;margin: auto;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/signup">Create your page</a><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account_link_name}}</a></div>
</section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="display: block;">
<div style="width: 100%;text-align: right;margin-top: -4em;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/signup">Create a new page</a><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account_link_name}}</a></div>
</section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="width: 15vw;border-radius: 50%;background: #000000;padding: 20px;height: 15vw;margin: auto;display: flex;margin-top: -6vw;"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="width: 15vw;border-radius: 50%;background: #000000;padding: 20px;height: 15vw;margin: auto;display: flex;margin-top: -6vw;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="height: 3em;"></section>
</section>
<section style="margin-top: 10px;">
<div class="row" style="margin: 0px;">
<div class="col" style="background: var(--bs-body-color);margin-right: 10px;border-radius: 10px;">
<h1 style="margin: 10px;">Heading</h1>
<p style="margin: 10px;">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris vivamus urna nisi dapibus nascetur convallis sollicitudin tempus lorem condimentum. Aptent dictumst montes id mattis molestie parturient morbi lobortis cubilia pharetra. Natoque adipiscing mollis parturient odio elit eu varius vulputate phasellus gravida. Et eget donec fringilla viverra id eu tempor ullamcorper aliquet vehicula. Et euismod magnis interdum mollis tellus lacinia at sollicitudin morbi inceptos.<br><br>Dictumst natoque imperdiet per praesent nisl morbi fermentum ultrices vivamus eu. Dictum venenatis netus orci himenaeos dictumst mattis pulvinar mattis laoreet tempor. Vulputate consequat in duis convallis mus mattis suspendisse semper netus varius. Magna placerat lectus eleifend nisi nunc laoreet lorem ipsum primis pellentesque. Fusce inceptos ante orci habitasse dui torquent dictum habitant iaculis sit. Interdum sociis eu porta inceptos parturient neque tortor lectus vivamus nunc.</p>
<div class="col" style="background: var(--bs-body-color);margin-right: 10px;border-radius: 10px;margin-top: 10px;margin-left: 10px;">
<h1 style="margin: 10px;">Introducing ShakeCities</h1>
<p style="margin: 10px;">ShakeCities is a site offering free personalizable&nbsp;websites. This is a perfect way to start your journey into Handshake domains! Step into a new experience where Handshake domains become instant sites, and where everyone can create their own unique decentralized page.<br>Secured with HTTPS powered by DANE (DNS-based Authentication of Named Entities).<br>But that's not all ShakeCities goes beyond, allowing you to seamlessly integrate crypto addresses into your site, providing an easy way to get paid. Simply send crypto to <code>@yourname.{{CITY_DOMAIN}}</code><br>Your ShakeCity domain can be used to chat on <a href="https://hns.chat" target="_blank">HNSChat</a>&nbsp;or to authenticate on any site using Varo auth<br>Join us in building a decentralized, secure, and innovative internet landscape. Embrace the future with ShakeCities where Handshake domains meet simplicity.</p>
</div>
<div class="col" style="background: var(--bs-body-color);margin-left: 10px;border-radius: 10px;">
<h1 style="margin: 10px;">Heading</h1>
<p style="margin: 10px;">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Conubia semper malesuada lobortis blandit ac leo leo potenti vel rutrum volutpat. Orci taciti arcu ipsum arcu rhoncus tortor aliquet id magna malesuada amet. Diam inceptos tempor gravida mattis mollis at imperdiet eros per cras sagittis.<br><br>Aliquet faucibus elit lacus elementum sed malesuada a vestibulum lacinia bibendum eleifend. Viverra mattis eleifend cum nulla nascetur parturient lectus vitae nostra a sem. Vel proin ullamcorper platea aenean vivamus volutpat lacus velit rutrum mi consequat. Ac gravida risus purus ligula mollis potenti duis ultricies eleifend tellus adipiscing.<br><br>Congue aenean lobortis fermentum lectus vel justo scelerisque id vitae mauris lacus. Gravida porta dolor tellus sem iaculis dictumst a mus in lorem ipsum. Dapibus pulvinar pretium ornare mauris duis sagittis non ullamcorper orci vestibulum venenatis. Imperdiet posuere penatibus sed senectus enim sollicitudin semper justo lorem aptent cras.</p>
<div class="col" style="background: var(--bs-body-color);margin-left: 10px;border-radius: 10px;margin-top: 10px;margin-right: 10px;">
<h1 style="margin: 10px;">Find a site</h1>
<p style="margin: 10px;font-size: 20px;">{{random_sites|safe}}</p>
</div>
</div>
<div class="row" style="margin: 0px;">
<div class="col" style="background: var(--bs-body-color);margin-right: 10px;border-radius: 10px;margin-top: 10px;margin-left: 10px;">
<h1 style="margin: 10px;">Tribes</h1>
<p style="margin: 10px;font-size: 20px;">{{tribes|safe}}</p>
</div>
</div>
</section>
@@ -38,21 +85,21 @@
<section class="d-print-none d-md-none d-lg-none d-xl-none d-xxl-none" style="background: var(--bs-body-color);text-align: center;padding-top: 10px;padding-bottom: 10px;margin-bottom: 25px;margin-top: 40px;border-radius: 10px;">
<div style="margin: 20px;">
<h1>Contact</h1>
<div class="list-group list-group-horizontal" data-bs-theme="dark" style="margin: auto;width: 80%;"><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://discord.com">Discord</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="mailto:email@example.com">Email</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://twitter.com">Twitter</a></button></div>
<div class="list-group list-group-horizontal" data-bs-theme="dark" style="margin: auto;width: 80%;"><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://discord.com">Discord</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="mailto:email@example.com">Email</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://twitter.com">Twitter</a></button></div>
</div>
<div style="margin: 20px;">
<h1>Donate</h1>
<p>hs1...</p>
<p>hs1qfqy9ewc3g4p06d4m5j8zm74qzhan7rxu7n8u9y</p>
</div>
</section>
<section class="d-none d-print-block d-md-block d-lg-block d-xl-block d-xxl-block" style="background: var(--bs-body-color);text-align: center;padding-top: 10px;padding-bottom: 10px;margin-bottom: 25px;margin-top: 40px;border-radius: 10px;">
<div style="margin: 20px;">
<h1>Contact</h1>
<div class="list-group list-group-horizontal" data-bs-theme="dark" style="margin: auto;width: 50%;"><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://discord.com">Discord</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="mailto:email@example.com">Email</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://twitter.com">Twitter</a></button></div>
<div class="list-group list-group-horizontal" data-bs-theme="dark" style="margin: auto;width: 50%;"><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://l.woodburn.au/discord">Discord</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="mailto:shakecities@woodburn.au">Email</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://hnschat#channel:woodburn">HNSChat</a></button></div>
</div>
<div style="margin: 20px;">
<h1>Donate</h1>
<p data-bs-toggle="tooltip" data-bss-tooltip="" id="hns_address" title="Copy">hs1.......</p><script>
<p data-bs-toggle="tooltip" data-bss-tooltip="" id="hns_address" title="Copy">hs1qfqy9ewc3g4p06d4m5j8zm74qzhan7rxu7n8u9y</p><script>
function copyToClipboard(element) {
const textToCopy = element.textContent;
const textArea = document.createElement('textarea');
@@ -72,8 +119,13 @@
</section>
</section>
<section style="margin: 20px;height: 40px;text-align: center;margin-top: 40px;">
<div>
<p style="color: #ffffff;">Copyright © ShakeCities 2023</p>
<footer class="text-center bg-dark"></footer>
<div style="display: inline-block;">
<ul class="list-inline">
<li class="list-inline-item me-4" style="color: rgb(255,255,255);">Copyright © ShakeCities 2023</li>
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/54/uptime?labelPrefix=Main+Server+' style="height:1.3em;margin-bottom:-.3em;width: 13em;"></iframe></li>
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/55/uptime?labelPrefix=Cities+' style="height:1.3em;margin-bottom:-.3em;width:11em;"></iframe></li>
</ul>
</div>
</section>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>

View File

@@ -4,22 +4,55 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>shakecities</title>
<title>ShakeCities | Login</title>
<meta name="twitter:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="twitter:card" content="summary">
<meta property="og:type" content="website">
<meta property="og:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:title" content="ShakeCities">
<meta name="twitter:title" content="ShakeCities">
<meta name="twitter:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/styles.min.css">
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://analytics.woodburn.au/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '7']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
<script async src="https://umami.woodburn.au/script.js" data-website-id="9a7af01b-9ebf-49a9-8337-907ff3744a02"></script>
</head>
<body style="background: #000000;width: 95%;margin: auto;">
<section>
<section style="height: 15vh;background: url(&quot;assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp&quot;) bottom / cover no-repeat;min-height: 130px;"></section>
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="width: 30vw;border-radius: 50%;background: #000000;padding: 20px;height: 30vw;margin: auto;margin-top: -15vw;display: flex;"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></section>
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="width: 30vw;border-radius: 50%;background: #000000;padding: 20px;height: 30vw;margin: auto;margin-top: -15vw;display: flex;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="display: block;width: 100%;text-align: center;margin-top: 10px;">
<div style="display: inline-block;margin: auto;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/signup">Create your page</a><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account}}</a></div>
<div style="display: inline-block;margin: auto;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/signup">Create your page</a><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account_link_name}}</a></div>
</section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="display: block;">
<div style="width: 100%;text-align: right;margin-top: -4em;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/signup">Create a new page</a><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account_link_name}}</a></div>
</section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="width: 15vw;border-radius: 50%;background: #000000;padding: 20px;height: 15vw;margin: auto;display: flex;margin-top: -6vw;"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="width: 15vw;border-radius: 50%;background: #000000;padding: 20px;height: 15vw;margin: auto;display: flex;margin-top: -6vw;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="height: 3em;"></section>
</section>
<section style="width: 50%;margin: auto;margin-top: 50px;">
@@ -31,8 +64,13 @@
</div>
</section>
<section style="margin: 20px;height: 40px;text-align: center;margin-top: 40px;">
<div>
<p style="color: #ffffff;">Copyright © ShakeCities 2023</p>
<footer class="text-center bg-dark"></footer>
<div style="display: inline-block;">
<ul class="list-inline">
<li class="list-inline-item me-4" style="color: rgb(255,255,255);">Copyright © ShakeCities 2023</li>
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/54/uptime?labelPrefix=Main+Server+' style="height:1.3em;margin-bottom:-.3em;width: 13em;"></iframe></li>
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/55/uptime?labelPrefix=Cities+' style="height:1.3em;margin-bottom:-.3em;width:11em;"></iframe></li>
</ul>
</div>
</section>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>

117
templates/new_tribe.html Normal file
View File

@@ -0,0 +1,117 @@
<!DOCTYPE html>
<html data-bs-theme="light" lang="en" style="background: black;">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>ShakeCities | Tribes</title>
<meta name="twitter:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="twitter:card" content="summary">
<meta property="og:type" content="website">
<meta property="og:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:title" content="ShakeCities">
<meta name="twitter:title" content="ShakeCities">
<meta name="twitter:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/styles.min.css">
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://analytics.woodburn.au/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '7']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
<script async src="https://umami.woodburn.au/script.js" data-website-id="9a7af01b-9ebf-49a9-8337-907ff3744a02"></script>
</head>
<body style="width: 95%;margin: auto;background: transparent;color: #ffffff;">
<section>
<section style="height: 15vh;background: url(&quot;assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp&quot;) bottom / cover no-repeat;min-height: 130px;"></section>
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="width: 30vw;border-radius: 50%;background: #000000;padding: 20px;height: 30vw;margin: auto;margin-top: -15vw;display: flex;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="display: block;width: 100%;text-align: center;margin-top: 10px;">
<div style="display: inline-block;margin: auto;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/signup">Create your page</a><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account_link_name}}</a></div>
</section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="display: block;">
<div style="width: 100%;text-align: right;margin-top: -4em;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account_link_name}}</a></div>
</section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="width: 15vw;border-radius: 50%;background: #000000;padding: 20px;height: 15vw;margin: auto;display: flex;margin-top: -6vw;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="height: 3em;"></section>
</section>
<section style="margin-top: 10px;">
<div class="row" style="margin: 0px;">
<div class="col" style="background: var(--bs-body-color);margin-right: 10px;border-radius: 10px;margin-top: 10px;margin-left: 10px;">
<h1 style="margin: 10px;">Create a tribe</h1>
<form method="post" style="margin-bottom: 20px;"><input class="form-control" type="text" style="margin-top: 20px;" name="tribe" placeholder="Tribe Name"><input class="btn btn-primary" type="submit" style="margin-top: 20px;" value="Create"></form>
</div>
</div>
</section>
<section>
<section class="d-print-none d-md-none d-lg-none d-xl-none d-xxl-none" style="background: var(--bs-body-color);text-align: center;padding-top: 10px;padding-bottom: 10px;margin-bottom: 25px;margin-top: 40px;border-radius: 10px;">
<div style="margin: 20px;">
<h1>Contact</h1>
<div class="list-group list-group-horizontal" data-bs-theme="dark" style="margin: auto;width: 80%;"><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://discord.com">Discord</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="mailto:email@example.com">Email</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://twitter.com">Twitter</a></button></div>
</div>
<div style="margin: 20px;">
<h1>Donate</h1>
<p>hs1qfqy9ewc3g4p06d4m5j8zm74qzhan7rxu7n8u9y</p>
</div>
</section>
<section class="d-none d-print-block d-md-block d-lg-block d-xl-block d-xxl-block" style="background: var(--bs-body-color);text-align: center;padding-top: 10px;padding-bottom: 10px;margin-bottom: 25px;margin-top: 40px;border-radius: 10px;">
<div style="margin: 20px;">
<h1>Contact</h1>
<div class="list-group list-group-horizontal" data-bs-theme="dark" style="margin: auto;width: 50%;"><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://l.woodburn.au/discord">Discord</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="mailto:shakecities@woodburn.au">Email</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://hnschat#channel:woodburn">HNSChat</a></button></div>
</div>
<div style="margin: 20px;">
<h1>Donate</h1>
<p data-bs-toggle="tooltip" data-bss-tooltip="" id="hns_address" title="Copy">hs1qfqy9ewc3g4p06d4m5j8zm74qzhan7rxu7n8u9y</p><script>
function copyToClipboard(element) {
const textToCopy = element.textContent;
const textArea = document.createElement('textarea');
textArea.value = textToCopy;
document.body.appendChild(textArea);
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);
}
const hns = document.getElementById('hns_address');
hns.addEventListener('click', () => {
copyToClipboard(hns);
});
</script>
</div>
</section>
</section>
<section style="margin: 20px;height: 40px;text-align: center;margin-top: 40px;">
<footer class="text-center bg-dark"></footer>
<div style="display: inline-block;">
<ul class="list-inline">
<li class="list-inline-item me-4" style="color: rgb(255,255,255);">Copyright © ShakeCities 2023</li>
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/54/uptime?labelPrefix=Main+Server+' style="height:1.3em;margin-bottom:-.3em;width: 13em;"></iframe></li>
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/55/uptime?labelPrefix=Cities+' style="height:1.3em;margin-bottom:-.3em;width:11em;"></iframe></li>
</ul>
</div>
</section>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="assets/js/script.min.js"></script>
</body>
</html>

View File

@@ -4,22 +4,55 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>shakecities</title>
<title>ShakeCities | Signup</title>
<meta name="twitter:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="twitter:card" content="summary">
<meta property="og:type" content="website">
<meta property="og:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:title" content="ShakeCities">
<meta name="twitter:title" content="ShakeCities">
<meta name="twitter:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/styles.min.css">
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://analytics.woodburn.au/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '7']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
<script async src="https://umami.woodburn.au/script.js" data-website-id="9a7af01b-9ebf-49a9-8337-907ff3744a02"></script>
</head>
<body style="background: #000000;width: 95%;margin: auto;">
<section>
<section style="height: 15vh;background: url(&quot;assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp&quot;) bottom / cover no-repeat;min-height: 130px;"></section>
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="width: 30vw;border-radius: 50%;background: #000000;padding: 20px;height: 30vw;margin: auto;margin-top: -15vw;display: flex;"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></section>
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="width: 30vw;border-radius: 50%;background: #000000;padding: 20px;height: 30vw;margin: auto;margin-top: -15vw;display: flex;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="display: block;width: 100%;text-align: center;margin-top: 10px;">
<div style="display: inline-block;margin: auto;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/signup">Create your page</a><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account}}</a></div>
<div style="display: inline-block;margin: auto;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/signup">Create your page</a><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account_link_name}}</a></div>
</section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="display: block;">
<div style="width: 100%;text-align: right;margin-top: -4em;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/signup">Create a new page</a><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account_link_name}}</a></div>
</section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="width: 15vw;border-radius: 50%;background: #000000;padding: 20px;height: 15vw;margin: auto;display: flex;margin-top: -6vw;"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="width: 15vw;border-radius: 50%;background: #000000;padding: 20px;height: 15vw;margin: auto;display: flex;margin-top: -6vw;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="height: 3em;"></section>
</section>
<section style="width: 50%;margin: auto;margin-top: 50px;">
@@ -33,8 +66,13 @@
</div>
</section>
<section style="margin: 20px;height: 40px;text-align: center;margin-top: 40px;">
<div>
<p style="color: #ffffff;">Copyright © ShakeCities 2023</p>
<footer class="text-center bg-dark"></footer>
<div style="display: inline-block;">
<ul class="list-inline">
<li class="list-inline-item me-4" style="color: rgb(255,255,255);">Copyright © ShakeCities 2023</li>
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/54/uptime?labelPrefix=Main+Server+' style="height:1.3em;margin-bottom:-.3em;width: 13em;"></iframe></li>
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/55/uptime?labelPrefix=Cities+' style="height:1.3em;margin-bottom:-.3em;width:11em;"></iframe></li>
</ul>
</div>
</section>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>

121
templates/tribe.html Normal file
View File

@@ -0,0 +1,121 @@
<!DOCTYPE html>
<html data-bs-theme="light" lang="en" style="background: black;">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>ShakeCities | Tribes</title>
<meta name="twitter:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="twitter:card" content="summary">
<meta property="og:type" content="website">
<meta property="og:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:title" content="ShakeCities">
<meta name="twitter:title" content="ShakeCities">
<meta name="twitter:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:description" content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="assets/img/HNS.png">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/styles.min.css">
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://analytics.woodburn.au/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '7']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
<script async src="https://umami.woodburn.au/script.js" data-website-id="9a7af01b-9ebf-49a9-8337-907ff3744a02"></script>
</head>
<body style="width: 95%;margin: auto;background: transparent;color: #ffffff;">
<section>
<section style="height: 15vh;background: url(&quot;assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp&quot;) bottom / cover no-repeat;min-height: 130px;"></section>
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="width: 30vw;border-radius: 50%;background: #000000;padding: 20px;height: 30vw;margin: auto;margin-top: -15vw;display: flex;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
<section class="d-print-none d-lg-none d-xl-none d-xxl-none" style="display: block;width: 100%;text-align: center;margin-top: 10px;">
<div style="display: inline-block;margin: auto;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/signup">Create your page</a><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account_link_name}}</a></div>
</section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="display: block;">
<div style="width: 100%;text-align: right;margin-top: -4em;"><a class="btn btn-primary" role="button" style="margin: 10px;" href="/{{account_link}}">{{account_link_name}}</a></div>
</section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="width: 15vw;border-radius: 50%;background: #000000;padding: 20px;height: 15vw;margin: auto;display: flex;margin-top: -6vw;"><a href="/"><img class="img-fluid" src="assets/img/HNSW.png" width="100%"></a></section>
<section class="d-none d-print-block d-lg-block d-xl-block d-xxl-block" style="height: 3em;"></section>
</section>
<section style="margin-top: 10px;">
<div class="row" style="margin: 0px;">
<div class="col" style="background: var(--bs-body-color);margin-right: 10px;border-radius: 10px;margin-top: 10px;margin-left: 10px;">
<h1 style="margin: 10px;">About Tribes</h1>
<p style="margin: 10px;">ShakeCities offers tribes as a way to create communities on ShakeCities. Create a tribe with your group of friends or colleagues.</p>
</div>
<div class="col" style="background: var(--bs-body-color);margin-left: 10px;border-radius: 10px;margin-top: 10px;margin-right: 10px;">
<h1 style="margin: 10px;">Find a tribe</h1>
<p style="margin: 10px;font-size: 20px;">{{tribes|safe}}</p>
</div>
</div>
</section>
<section>
<section class="d-print-none d-md-none d-lg-none d-xl-none d-xxl-none" style="background: var(--bs-body-color);text-align: center;padding-top: 10px;padding-bottom: 10px;margin-bottom: 25px;margin-top: 40px;border-radius: 10px;">
<div style="margin: 20px;">
<h1>Contact</h1>
<div class="list-group list-group-horizontal" data-bs-theme="dark" style="margin: auto;width: 80%;"><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://discord.com">Discord</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="mailto:email@example.com">Email</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://twitter.com">Twitter</a></button></div>
</div>
<div style="margin: 20px;">
<h1>Donate</h1>
<p>hs1qfqy9ewc3g4p06d4m5j8zm74qzhan7rxu7n8u9y</p>
</div>
</section>
<section class="d-none d-print-block d-md-block d-lg-block d-xl-block d-xxl-block" style="background: var(--bs-body-color);text-align: center;padding-top: 10px;padding-bottom: 10px;margin-bottom: 25px;margin-top: 40px;border-radius: 10px;">
<div style="margin: 20px;">
<h1>Contact</h1>
<div class="list-group list-group-horizontal" data-bs-theme="dark" style="margin: auto;width: 50%;"><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://l.woodburn.au/discord">Discord</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="mailto:shakecities@woodburn.au">Email</a></button><button class="list-group-item list-group-item-action" style="width: 33%;padding: 0px;margin: 10px;border-style: none;"><a class="btn btn-primary" role="button" style="width: 100%;" target="_blank" href="https://hnschat#channel:woodburn">HNSChat</a></button></div>
</div>
<div style="margin: 20px;">
<h1>Donate</h1>
<p data-bs-toggle="tooltip" data-bss-tooltip="" id="hns_address" title="Copy">hs1qfqy9ewc3g4p06d4m5j8zm74qzhan7rxu7n8u9y</p><script>
function copyToClipboard(element) {
const textToCopy = element.textContent;
const textArea = document.createElement('textarea');
textArea.value = textToCopy;
document.body.appendChild(textArea);
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);
}
const hns = document.getElementById('hns_address');
hns.addEventListener('click', () => {
copyToClipboard(hns);
});
</script>
</div>
</section>
</section>
<section style="margin: 20px;height: 40px;text-align: center;margin-top: 40px;">
<footer class="text-center bg-dark"></footer>
<div style="display: inline-block;">
<ul class="list-inline">
<li class="list-inline-item me-4" style="color: rgb(255,255,255);">Copyright © ShakeCities 2023</li>
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/54/uptime?labelPrefix=Main+Server+' style="height:1.3em;margin-bottom:-.3em;width: 13em;"></iframe></li>
<li class="list-inline-item me-4"><iframe src='https://uptime.woodburn.au/api/badge/55/uptime?labelPrefix=Cities+' style="height:1.3em;margin-bottom:-.3em;width:11em;"></iframe></li>
</ul>
</div>
</section>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="assets/js/script.min.js"></script>
</body>
</html>

83
templates/tribe_view.html Normal file
View File

@@ -0,0 +1,83 @@
<!DOCTYPE html>
<html style="width: 100vw;height: 99vh;">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>ShakeCities</title>
<meta name="twitter:description"
content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="description"
content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<meta name="twitter:card" content="summary">
<meta property="og:type" content="website">
<meta property="og:image" content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:title" content="ShakeCities">
<meta name="twitter:title" content="ShakeCities">
<meta name="twitter:image"
content="https://shakecities.com/assets/img/alexander-slattery-LI748t0BK8w-unsplash.webp">
<meta property="og:description"
content="Unlock web ownership's future with ShakeCities! Create your free, secure Handshake domain site. Integrate crypto payments, explore HNSChat, and join us in shaping the decentralized web!">
<link rel="icon" type="image/png" sizes="670x700" href="/assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="/assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="/assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="/assets/img/HNSW.png" media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" sizes="670x700" href="/assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="/assets/img/HNS.png">
<link rel="icon" type="image/png" sizes="670x700" href="/assets/img/HNS.png">
<link rel="stylesheet" href="/assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="/assets/css/styles.min.css">
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function () {
var u = "https://analytics.woodburn.au/";
_paq.push(['setTrackerUrl', u + 'matomo.php']);
_paq.push(['setSiteId', '7']);
var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0];
g.async = true; g.src = u + 'matomo.js'; s.parentNode.insertBefore(g, s);
})();
</script>
<!-- End Matomo Code -->
</head>
<body style="height: 99vh;width: 100vw;color: #ffffff;background: #000000;overflow-x: hidden;">
<h1 style="margin: auto;text-align: center;font-size: 5em;">{{tribe}}</h1>
<div style="padding: 2%;margin: 22px;text-align: center;">
<p style="font-size: 24px;">
{{data|safe}} <!-- This needs the safe filter to allow HTML to be rendered -->
</p>
</div>
<div style="padding: 2%;margin: 22px;text-align: center;">
<h2>Tribe members</h2>
<p style="font-size: 24px;">
{{members|safe}} <!-- This needs the safe filter to allow HTML to be rendered -->
</p>
</div>
<!-- Edit footer -->
<div style="height: 100px;"></div>
<div style="position: fixed;bottom: 10px;right:25px;">
<p style="color:#ffffff;">{{edit|safe}}</p>
</div>
</div>
<!-- Footer to display the powered by ShakeCities. -->
<div style="height: 100px;"></div>
<div style="position: fixed;bottom: 10px;left:25px;">
<div style="display: inline-block; background: #ffffff;border-radius: 50%;padding: 10px;">
<img src="/assets/img/HNS.png" width="50px" height="50px">
</div>
<p style="margin-left: 25px; display:inline; color:#ffffff;">Powered by <a style="color: inherit;"
href="https://shakecities.com" target="_blank">ShakeCities</a></p>
</div>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="assets/js/script.min.js"></script>
</body>
</html>

340
varo.py Normal file
View File

@@ -0,0 +1,340 @@
import requests
import os
import dotenv
dotenv.load_dotenv()
zone = ""
TLSA = ""
REG_KEY = os.getenv('REG_KEY')
city_domain = os.getenv('CITY_DOMAIN')
if city_domain == "localhost":
city_domain = "exampledomainnathan1"
alt_domains = os.getenv('ALT_DOMAINS')
if alt_domains == None:
alt_domains = []
else:
alt_domains = alt_domains.split(",")
server_ip = os.getenv('CITY_IP')
def update_auth(auth,domain):
verify_ALIAS(domain)
record = get_auth_id(domain)
if record == "":
data = {
"action": "addRecord",
"zone": zone,
"type": "TXT",
"name": domain,
"content": auth,
}
else:
data = {
"action": "updateRecord",
"zone": zone,
"record": record,
"column": "content",
"value": auth
}
if auth == "" and record == "":
return
if auth == "" and record != "":
data = {
"action": "deleteRecord",
"zone": zone,
"record": record
}
# Update TXT record
url = "https://reg.woodburn.au/api"
headers = {
'Authorization': 'Bearer '+REG_KEY,
'Content-Type': 'application/json'
}
r = requests.put(url, headers=headers, json=data)
copy_to_alts(domain)
return r.text
def get_auth_id(domain):
if zone == "":
get_zone()
data = {
"action": "getRecords",
"zone": zone,
"name": domain + "." + city_domain,
"type": "TXT",
"content": ""
}
url = "https://reg.woodburn.au/api"
headers = {
'Authorization': 'Bearer '+REG_KEY,
'Content-Type': 'application/json'
}
r = requests.post(url, headers=headers, json=data)
r = r.json()
if 'data' not in r:
return ""
for record in r['data']:
if 'profile avatar=' not in record['content']:
return record['uuid']
return ""
def get_auth(domain):
if zone == "":
get_zone()
data = {
"action": "getRecords",
"zone": zone,
"name": domain + "." + city_domain,
"type": "TXT",
"content": ""
}
url = "https://reg.woodburn.au/api"
headers = {
'Authorization': 'Bearer '+REG_KEY,
'Content-Type': 'application/json'
}
r = requests.post(url, headers=headers, json=data)
r = r.json()
if 'data' not in r:
return ""
for record in r['data']:
if 'profile avatar=' not in record['content']:
return record['content']
return ""
def get_zone():
global zone
global TLSA
url = "https://reg.woodburn.au/api"
headers = {
'Authorization': 'Bearer '+REG_KEY,
'Content-Type': 'application/json'
}
data = {
"action": "getZones"
}
r = requests.post(url, headers=headers, json=data)
r = r.json()
for domain in r['data']:
if domain['name'] == city_domain:
zone = domain['id']
data = {
"action": "getRecords",
"zone": zone,
"name": "*."+city_domain,
"type": "TLSA",
"content": ""
}
r = requests.post(url, headers=headers, json=data)
r = r.json()
for record in r['data']:
TLSA = record['content']
return zone
def update_avatar(avatar,domain):
verify_ALIAS(domain)
if zone == "":
get_zone()
data = {
"action": "getRecords",
"zone": zone,
"name": domain + "." + city_domain,
"type": "TXT",
"content": ""
}
url = "https://reg.woodburn.au/api"
headers = {
'Authorization': 'Bearer '+REG_KEY,
'Content-Type': 'application/json'
}
r = requests.post(url, headers=headers, json=data)
r = r.json()
record_id = ""
if 'data' in r:
for record in r['data']:
if record['name'] == domain + "." + city_domain:
if 'profile avatar=' in record['content']:
if record['content'].split("profile avatar=")[1] == avatar:
print("Avatar already set", flush=True)
return "Avatar already set"
record_id = record['uuid']
if record_id == "":
data = {
"action": "addRecord",
"zone": zone,
"type": "TXT",
"name": domain,
"content": "profile avatar=" + avatar,
}
else:
data = {
"action": "updateRecord",
"zone": zone,
"record": record_id,
"column": "content",
"value": "profile avatar=" + avatar
}
if avatar == "" and record_id == "":
return
if avatar == "" and record_id != "":
data = {
"action": "deleteRecord",
"zone": zone,
"record": record_id
}
r = requests.post(url, headers=headers, json=data)
copy_to_alts(domain)
return r.text
def verify_ALIAS(domain):
if zone == "":
get_zone()
data = {
"action": "getRecords",
"zone": zone,
"name": domain+"."+city_domain,
"type": "A",
"content": ""
}
url = "https://reg.woodburn.au/api"
headers = {
'Authorization': 'Bearer '+REG_KEY,
'Content-Type': 'application/json'
}
r = requests.post(url, headers=headers, json=data)
r = r.json()
if 'data' in r:
return
data = {
"action": "addRecord",
"zone": zone,
"type": "A",
"name": domain,
"content": server_ip,
}
r = requests.post(url, headers=headers, json=data)
data = {
"action": "addRecord",
"zone": zone,
"type": "TLSA",
"name": "_443._tcp."+domain+"."+city_domain,
"content": TLSA,
}
r = requests.post(url, headers=headers, json=data)
copy_to_alts(domain)
return r.text
def copy_to_alts(domain):
# Get DNS from domain and copy to each alt
data = {
"action": "getRecords",
"zone": zone,
"name": domain+"."+city_domain,
"type": "",
"content": ""
}
url = "https://reg.woodburn.au/api"
headers = {
'Authorization': 'Bearer '+REG_KEY,
'Content-Type': 'application/json'
}
r = requests.post(url, headers=headers, json=data)
r = r.json()
if 'data' not in r:
return
records = r['data']
for alt_domain in alt_domains:
# Get the zone for the alt
alt_zone = ""
data = {
"action": "getZones"
}
r = requests.post(url, headers=headers, json=data)
r = r.json()
for tmpzone in r['data']:
if tmpzone['name'] == alt_domain:
alt_zone = tmpzone['id']
print(alt_zone)
if alt_zone == "":
continue
# Delete all records from domain.alt
data = {
"action": "getRecords",
"zone": alt_zone,
"name": domain+"."+alt_domain,
"type": "",
"content": ""
}
r = requests.post(url, headers=headers, json=data)
r = r.json()
if 'data' in r:
for record in r['data']:
data = {
"action": "deleteRecord",
"zone": alt_zone,
"record": record['uuid']
}
r = requests.post(url, headers=headers, json=data)
print(r.text)
# Add each record to each alt
for record in records:
data = {
"action": "addRecord",
"zone": alt_zone,
"type": record['type'],
"name": domain+"."+alt_domain,
"content": record['content'],
}
print(data)
r = requests.post(url, headers=headers, json=data)
print(r.text)
# Add TLSA record if it doesn't exist
data = {
"action": "getRecords",
"zone": alt_zone,
"name": "_443._tcp."+domain+"."+alt_domain,
"type": "TLSA",
"content": ""
}
r = requests.post(url, headers=headers, json=data)
r = r.json()
if 'data' not in r:
# Get alt TLSA from _443._tcp.alt_domain
data = {
"action": "getRecords",
"zone": alt_zone,
"name": "_443._tcp."+alt_domain,
"type": "TLSA",
"content": ""
}
r = requests.post(url, headers=headers, json=data)
r = r.json()
if 'data' not in r:
continue
for record in r['data']:
ALT_TLSA = record['content']
data = {
"action": "addRecord",
"zone": alt_zone,
"type": "TLSA",
"name": "_443._tcp."+domain+"."+alt_domain,
"content": ALT_TLSA,
}
r = requests.post(url, headers=headers, json=data)
print(r.text)