New Membership Page and other changes #4

Merged
kumi merged 29 commits from membership-page into main 2024-05-30 10:15:10 +00:00
33 changed files with 860 additions and 421 deletions

View file

@ -24,3 +24,8 @@ The website will be available at `http://localhost:9810`.
This project is licensed under the MIT License - see the [LICENSE](LICENSE) This project is licensed under the MIT License - see the [LICENSE](LICENSE)
file for details. file for details.
## Attribution
This website is built using the [Bootstrap](https://getbootstrap.com) framework
and [Phosphor Icons](https://phosphoricons.com).

View file

@ -85,6 +85,48 @@ h5 {
margin-top: 10px; margin-top: 10px;
} }
.currency-col {
width: 200px;
white-space: nowrap;
text-align: right;
}
.table-transparency td:not(:first-child) {
text-align: right;
}
.section {
padding: 20px 0;
border-bottom: 1px solid #e0e0e0;
}
.alert-warning {
background-color: #fff3cd;
border-color: #ffeeba;
color: #856404;
padding: 15px;
margin-bottom: 20px;
border-radius: 4px;
}
.alert-warning .alert-link {
color: #856404;
font-weight: bold;
text-decoration: underline;
}
.alert-warning .alert-link:hover {
color: #604c2e;
}
.bs-icon.bs-icon-primary svg {
fill: var(--bs-primary-bg-subtle);
}
.bs-icon.bs-icon-lg svg {
fill: var(--bs-primary)
}
/* Responsive Styles */ /* Responsive Styles */
@media (max-width: 768px) { @media (max-width: 768px) {
.navbar .container { .navbar .container {

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M128,96H232a8,8,0,0,1,0,16H128a8,8,0,0,1,0-16Zm104,32H128a8,8,0,0,0,0,16H232a8,8,0,0,0,0-16Zm0,32H80a8,8,0,0,0,0,16H232a8,8,0,0,0,0-16Zm0,32H80a8,8,0,0,0,0,16H232a8,8,0,0,0,0-16ZM96,144a8,8,0,0,0,0-16H88V64h32v8a8,8,0,0,0,16,0V56a8,8,0,0,0-8-8H32a8,8,0,0,0-8,8V72a8,8,0,0,0,16,0V64H72v64H64a8,8,0,0,0,0,16Z"></path></svg>

After

Width:  |  Height:  |  Size: 430 B

1
assets/dist/icons/calendar.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M208,32H184V24a8,8,0,0,0-16,0v8H88V24a8,8,0,0,0-16,0v8H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM72,48v8a8,8,0,0,0,16,0V48h80v8a8,8,0,0,0,16,0V48h24V80H48V48ZM208,208H48V96H208V208Zm-96-88v64a8,8,0,0,1-16,0V132.94l-4.42,2.22a8,8,0,0,1-7.16-14.32l16-8A8,8,0,0,1,112,120Zm59.16,30.45L152,176h16a8,8,0,0,1,0,16H136a8,8,0,0,1-6.4-12.8l28.78-38.37A8,8,0,1,0,145.07,132a8,8,0,1,1-13.85-8A24,24,0,0,1,176,136,23.76,23.76,0,0,1,171.16,150.45Z"></path></svg>

After

Width:  |  Height:  |  Size: 604 B

1
assets/dist/icons/chats.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M216,80H184V48a16,16,0,0,0-16-16H40A16,16,0,0,0,24,48V176a8,8,0,0,0,13,6.22L72,154V184a16,16,0,0,0,16,16h93.59L219,230.22a8,8,0,0,0,5,1.78,8,8,0,0,0,8-8V96A16,16,0,0,0,216,80ZM66.55,137.78,40,159.25V48H168v88H71.58A8,8,0,0,0,66.55,137.78ZM216,207.25l-26.55-21.47a8,8,0,0,0-5-1.78H88V152h80a16,16,0,0,0,16-16V96h32Z"></path></svg>

After

Width:  |  Height:  |  Size: 438 B

1
assets/dist/icons/coffee.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M80,56V24a8,8,0,0,1,16,0V56a8,8,0,0,1-16,0Zm40,8a8,8,0,0,0,8-8V24a8,8,0,0,0-16,0V56A8,8,0,0,0,120,64Zm32,0a8,8,0,0,0,8-8V24a8,8,0,0,0-16,0V56A8,8,0,0,0,152,64Zm96,56v8a40,40,0,0,1-37.51,39.91,96.59,96.59,0,0,1-27,40.09H208a8,8,0,0,1,0,16H32a8,8,0,0,1,0-16H56.54A96.3,96.3,0,0,1,24,136V88a8,8,0,0,1,8-8H208A40,40,0,0,1,248,120ZM200,96H40v40a80.27,80.27,0,0,0,45.12,72h69.76A80.27,80.27,0,0,0,200,136Zm32,24a24,24,0,0,0-16-22.62V136a95.78,95.78,0,0,1-1.2,15A24,24,0,0,0,232,128Z"></path></svg>

After

Width:  |  Height:  |  Size: 600 B

1
assets/dist/icons/database.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M128,24C74.17,24,32,48.6,32,80v96c0,31.4,42.17,56,96,56s96-24.6,96-56V80C224,48.6,181.83,24,128,24Zm80,104c0,9.62-7.88,19.43-21.61,26.92C170.93,163.35,150.19,168,128,168s-42.93-4.65-58.39-13.08C55.88,147.43,48,137.62,48,128V111.36c17.06,15,46.23,24.64,80,24.64s62.94-9.68,80-24.64ZM69.61,53.08C85.07,44.65,105.81,40,128,40s42.93,4.65,58.39,13.08C200.12,60.57,208,70.38,208,80s-7.88,19.43-21.61,26.92C170.93,115.35,150.19,120,128,120s-42.93-4.65-58.39-13.08C55.88,99.43,48,89.62,48,80S55.88,60.57,69.61,53.08ZM186.39,202.92C170.93,211.35,150.19,216,128,216s-42.93-4.65-58.39-13.08C55.88,195.43,48,185.62,48,176V159.36c17.06,15,46.23,24.64,80,24.64s62.94-9.68,80-24.64V176C208,185.62,200.12,195.43,186.39,202.92Z"></path></svg>

After

Width:  |  Height:  |  Size: 834 B

1
assets/dist/icons/envelope.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M224,48H32a8,8,0,0,0-8,8V192a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A8,8,0,0,0,224,48Zm-96,85.15L52.57,64H203.43ZM98.71,128,40,181.81V74.19Zm11.84,10.85,12,11.05a8,8,0,0,0,10.82,0l12-11.05,58,53.15H52.57ZM157.29,128,216,74.18V181.82Z"></path></svg>

After

Width:  |  Height:  |  Size: 360 B

1
assets/dist/icons/git-branch.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M232,64a32,32,0,1,0-40,31v17a8,8,0,0,1-8,8H96a23.84,23.84,0,0,0-8,1.38V95a32,32,0,1,0-16,0v66a32,32,0,1,0,16,0V144a8,8,0,0,1,8-8h88a24,24,0,0,0,24-24V95A32.06,32.06,0,0,0,232,64ZM64,64A16,16,0,1,1,80,80,16,16,0,0,1,64,64ZM96,192a16,16,0,1,1-16-16A16,16,0,0,1,96,192ZM200,80a16,16,0,1,1,16-16A16,16,0,0,1,200,80Z"></path></svg>

After

Width:  |  Height:  |  Size: 435 B

1
assets/dist/icons/images.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M216,40H72A16,16,0,0,0,56,56V72H40A16,16,0,0,0,24,88V200a16,16,0,0,0,16,16H184a16,16,0,0,0,16-16V184h16a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40ZM72,56H216v62.75l-10.07-10.06a16,16,0,0,0-22.63,0l-20,20-44-44a16,16,0,0,0-22.62,0L72,109.37ZM184,200H40V88H56v80a16,16,0,0,0,16,16H184Zm32-32H72V132l36-36,49.66,49.66a8,8,0,0,0,11.31,0L194.63,120,216,141.38V168ZM160,84a12,12,0,1,1,12,12A12,12,0,0,1,160,84Z"></path></svg>

After

Width:  |  Height:  |  Size: 525 B

1
assets/dist/icons/leaf.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M223.45,40.07a8,8,0,0,0-7.52-7.52C139.8,28.08,78.82,51,52.82,94a87.09,87.09,0,0,0-12.76,49c.57,15.92,5.21,32,13.79,47.85l-19.51,19.5a8,8,0,0,0,11.32,11.32l19.5-19.51C81,210.73,97.09,215.37,113,215.94q1.67.06,3.33.06A86.93,86.93,0,0,0,162,203.18C205,177.18,227.93,116.21,223.45,40.07ZM153.75,189.5c-22.75,13.78-49.68,14-76.71.77l88.63-88.62a8,8,0,0,0-11.32-11.32L65.73,179c-13.19-27-13-54,.77-76.71,22.09-36.47,74.6-56.44,141.31-54.06C210.2,114.89,190.22,167.41,153.75,189.5Z"></path></svg>

After

Width:  |  Height:  |  Size: 598 B

1
assets/dist/icons/lightbulb.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M176,232a8,8,0,0,1-8,8H88a8,8,0,0,1,0-16h80A8,8,0,0,1,176,232Zm40-128a87.55,87.55,0,0,1-33.64,69.21A16.24,16.24,0,0,0,176,186v6a16,16,0,0,1-16,16H96a16,16,0,0,1-16-16v-6a16,16,0,0,0-6.23-12.66A87.59,87.59,0,0,1,40,104.49C39.74,56.83,78.26,17.14,125.88,16A88,88,0,0,1,216,104Zm-16,0a72,72,0,0,0-73.74-72c-39,.92-70.47,33.39-70.26,72.39a71.65,71.65,0,0,0,27.64,56.3A32,32,0,0,1,96,186v6h64v-6a32.15,32.15,0,0,1,12.47-25.35A71.65,71.65,0,0,0,200,104Zm-16.11-9.34a57.6,57.6,0,0,0-46.56-46.55,8,8,0,0,0-2.66,15.78c16.57,2.79,30.63,16.85,33.44,33.45A8,8,0,0,0,176,104a9,9,0,0,0,1.35-.11A8,8,0,0,0,183.89,94.66Z"></path></svg>

After

Width:  |  Height:  |  Size: 728 B

1
assets/dist/icons/link.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M240,88.23a54.43,54.43,0,0,1-16,37L189.25,160a54.27,54.27,0,0,1-38.63,16h-.05A54.63,54.63,0,0,1,96,119.84a8,8,0,0,1,16,.45A38.62,38.62,0,0,0,150.58,160h0a38.39,38.39,0,0,0,27.31-11.31l34.75-34.75a38.63,38.63,0,0,0-54.63-54.63l-11,11A8,8,0,0,1,135.7,59l11-11A54.65,54.65,0,0,1,224,48,54.86,54.86,0,0,1,240,88.23ZM109,185.66l-11,11A38.41,38.41,0,0,1,70.6,208h0a38.63,38.63,0,0,1-27.29-65.94L78,107.31A38.63,38.63,0,0,1,144,135.71a8,8,0,0,0,16,.45A54.86,54.86,0,0,0,144,96a54.65,54.65,0,0,0-77.27,0L32,130.75A54.62,54.62,0,0,0,70.56,224h0a54.28,54.28,0,0,0,38.64-16l11-11A8,8,0,0,0,109,185.66Z"></path></svg>

After

Width:  |  Height:  |  Size: 714 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M229.66,218.34l-50.07-50.06a88.11,88.11,0,1,0-11.31,11.31l50.06,50.07a8,8,0,0,0,11.32-11.32ZM40,112a72,72,0,1,1,72,72A72.08,72.08,0,0,1,40,112Z"></path></svg>

After

Width:  |  Height:  |  Size: 267 B

1
assets/dist/icons/markdown-logo.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M232,48H24A16,16,0,0,0,8,64V192a16,16,0,0,0,16,16H232a16,16,0,0,0,16-16V64A16,16,0,0,0,232,48Zm0,144H24V64H232V192ZM128,104v48a8,8,0,0,1-16,0V123.31L93.66,141.66a8,8,0,0,1-11.32,0L64,123.31V152a8,8,0,0,1-16,0V104a8,8,0,0,1,13.66-5.66L88,124.69l26.34-26.35A8,8,0,0,1,128,104Zm77.66,18.34a8,8,0,0,1,0,11.32l-24,24a8,8,0,0,1-11.32,0l-24-24a8,8,0,0,1,11.32-11.32L168,132.69V104a8,8,0,0,1,16,0v28.69l10.34-10.35A8,8,0,0,1,205.66,122.34Z"></path></svg>

After

Width:  |  Height:  |  Size: 555 B

1
assets/dist/icons/mastodon-logo.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M184,32H72A40,40,0,0,0,32,72V192a40,40,0,0,0,40,40h88a8,8,0,0,0,0-16H72a24,24,0,0,1-24-24v-8H184a40,40,0,0,0,40-40V72A40,40,0,0,0,184,32Zm24,112a24,24,0,0,1-24,24H48V72A24,24,0,0,1,72,48H184a24,24,0,0,1,24,24Zm-24-40v32a8,8,0,0,1-16,0V104a16,16,0,0,0-32,0v32a8,8,0,0,1-16,0V104a16,16,0,0,0-32,0v32a8,8,0,0,1-16,0V104a32,32,0,0,1,56-21.13A32,32,0,0,1,184,104Z"></path></svg>

After

Width:  |  Height:  |  Size: 482 B

1
assets/dist/icons/matrix-logo.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M72,216a8,8,0,0,1-8,8H40a8,8,0,0,1-8-8V40a8,8,0,0,1,8-8H64a8,8,0,0,1,0,16H48V208H64A8,8,0,0,1,72,216ZM216,32H192a8,8,0,0,0,0,16h16V208H192a8,8,0,0,0,0,16h24a8,8,0,0,0,8-8V40A8,8,0,0,0,216,32Zm-32,88a32,32,0,0,0-56-21.13,31.93,31.93,0,0,0-40.71-6.15A8,8,0,0,0,72,96v64a8,8,0,0,0,16,0V120a16,16,0,0,1,32,0v40a8,8,0,0,0,16,0V120a16,16,0,0,1,32,0v40a8,8,0,0,0,16,0Z"></path></svg>

After

Width:  |  Height:  |  Size: 485 B

1
assets/dist/icons/network.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M232,112H136V88h8a16,16,0,0,0,16-16V40a16,16,0,0,0-16-16H112A16,16,0,0,0,96,40V72a16,16,0,0,0,16,16h8v24H24a8,8,0,0,0,0,16H56v32H48a16,16,0,0,0-16,16v32a16,16,0,0,0,16,16H80a16,16,0,0,0,16-16V176a16,16,0,0,0-16-16H72V128H184v32h-8a16,16,0,0,0-16,16v32a16,16,0,0,0,16,16h32a16,16,0,0,0,16-16V176a16,16,0,0,0-16-16h-8V128h32a8,8,0,0,0,0-16ZM112,40h32V72H112ZM80,208H48V176H80Zm128,0H176V176h32Z"></path></svg>

After

Width:  |  Height:  |  Size: 516 B

1
assets/dist/icons/pencil-ruler.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M208,32H160a16,16,0,0,0-16,16V208a16,16,0,0,0,16,16h48a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32Zm0,176H160V176h24a8,8,0,0,0,0-16H160V136h24a8,8,0,0,0,0-16H160V96h24a8,8,0,0,0,0-16H160V48h48V208ZM77.66,26.34a8,8,0,0,0-11.32,0l-32,32A8,8,0,0,0,32,64V208a16,16,0,0,0,16,16H96a16,16,0,0,0,16-16V64a8,8,0,0,0-2.34-5.66ZM48,176V80H64v96ZM80,80H96v96H80ZM72,43.31,92.69,64H51.31ZM48,208V192H96v16Z"></path></svg>

After

Width:  |  Height:  |  Size: 513 B

1
assets/dist/icons/video.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M164.44,105.34l-48-32A8,8,0,0,0,104,80v64a8,8,0,0,0,12.44,6.66l48-32a8,8,0,0,0,0-13.32ZM120,129.05V95l25.58,17ZM216,40H40A16,16,0,0,0,24,56V168a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40Zm0,128H40V56H216V168Zm16,40a8,8,0,0,1-8,8H32a8,8,0,0,1,0-16H224A8,8,0,0,1,232,208Z"></path></svg>

After

Width:  |  Height:  |  Size: 412 B

1
assets/dist/icons/webcam.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M168,104a40,40,0,1,0-40,40A40,40,0,0,0,168,104Zm-64,0a24,24,0,1,1,24,24A24,24,0,0,1,104,104Zm120,96H136V183.6a80,80,0,1,0-16,0V200H32a8,8,0,0,0,0,16H224a8,8,0,0,0,0-16ZM64,104a64,64,0,1,1,64,64A64.07,64.07,0,0,1,64,104Z"></path></svg>

After

Width:  |  Height:  |  Size: 343 B

33
data/finances.json Normal file
View file

@ -0,0 +1,33 @@
{
"2024": {
"4": {
"Membership Fees": {
"EUR": 365
},
"Donations": {},
"Server Costs": {
"EUR": -216.57
},
"Domain Names": {},
"Operating Expenses": {
"EUR": -36.10
},
"Conversions": {}
},
"5": {
"Membership Fees": {
"EUR": 390
},
"Donations": {
"BTC": 0.000434,
"XMR": 0.447661805527
},
"Server Costs": {
"EUR": -430.04
},
"Domain Names": {},
"Operating Expenses": {},
"Conversions": {}
}
}
}

View file

@ -12,6 +12,7 @@
"url": "https://element.private.coffee" "url": "https://element.private.coffee"
} }
], ],
"icon": "matrix-logo",
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": true "exclude_from_simple": true
}, },
@ -27,6 +28,7 @@
"url": "https://cryptpad.private.coffee" "url": "https://cryptpad.private.coffee"
} }
], ],
"icon": "article-ny-times",
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": false "exclude_from_simple": false
}, },
@ -42,6 +44,7 @@
"url": "https://piped.private.coffee" "url": "https://piped.private.coffee"
} }
], ],
"icon": "video",
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": false "exclude_from_simple": false
}, },
@ -57,6 +60,7 @@
"url": "https://myip.coffee" "url": "https://myip.coffee"
} }
], ],
"icon": "network",
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": false "exclude_from_simple": false
}, },
@ -72,6 +76,7 @@
"url": "https://invidious.private.coffee" "url": "https://invidious.private.coffee"
} }
], ],
"icon": "video",
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": false "exclude_from_simple": false
}, },
@ -91,6 +96,7 @@
"url": "https://skrt.social" "url": "https://skrt.social"
} }
], ],
"icon": "mastodon-logo",
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": false "exclude_from_simple": false
}, },
@ -106,6 +112,7 @@
"url": "https://git.private.coffee" "url": "https://git.private.coffee"
} }
], ],
"icon": "git-branch",
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": false "exclude_from_simple": false
}, },
@ -121,6 +128,7 @@
"url": "https://bbb.private.coffee" "url": "https://bbb.private.coffee"
} }
], ],
"icon": "webcam",
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": false "exclude_from_simple": false
}, },
@ -136,6 +144,7 @@
"url": "https://hedgedoc.private.coffee" "url": "https://hedgedoc.private.coffee"
} }
], ],
"icon": "markdown-logo",
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": false "exclude_from_simple": false
}, },
@ -151,6 +160,7 @@
"url": "https://gothub.private.coffee" "url": "https://gothub.private.coffee"
} }
], ],
"icon": "git-branch",
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": false "exclude_from_simple": false
}, },
@ -166,6 +176,7 @@
"url": "https://redlib.private.coffee" "url": "https://redlib.private.coffee"
} }
], ],
"icon": "chats",
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": false "exclude_from_simple": false
}, },
@ -181,6 +192,7 @@
"url": "https://alltube.private.coffee" "url": "https://alltube.private.coffee"
} }
], ],
"icon": "video",
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": false "exclude_from_simple": false
}, },
@ -196,6 +208,7 @@
"url": "https://structables.private.coffee" "url": "https://structables.private.coffee"
} }
], ],
"icon": "lightbulb",
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": false "exclude_from_simple": false
}, },
@ -211,6 +224,7 @@
"url": "https://nocodb.private.coffee" "url": "https://nocodb.private.coffee"
} }
], ],
"icon": "database",
"exclude_from_index": true, "exclude_from_index": true,
"exclude_from_simple": true "exclude_from_simple": true
}, },
@ -226,6 +240,7 @@
"url": "https://penpot.private.coffee" "url": "https://penpot.private.coffee"
} }
], ],
"icon": "pencil-ruler",
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": false "exclude_from_simple": false
}, },
@ -241,6 +256,7 @@
"url": "https://pcof.fi" "url": "https://pcof.fi"
} }
], ],
"icon": "link",
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": false "exclude_from_simple": false
}, },
@ -256,6 +272,7 @@
"url": "https://rallly.private.coffee" "url": "https://rallly.private.coffee"
} }
], ],
"icon": "calendar",
"exclude_from_index": true, "exclude_from_index": true,
"exclude_from_simple": true "exclude_from_simple": true
}, },
@ -271,6 +288,7 @@
"url": "https://librey.private.coffee" "url": "https://librey.private.coffee"
} }
], ],
"icon": "magnifying-glass",
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": false "exclude_from_simple": false
}, },
@ -286,6 +304,7 @@
"url": "https://overleaf.private.coffee" "url": "https://overleaf.private.coffee"
} }
], ],
"icon": "leaf",
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": false "exclude_from_simple": false
}, },
@ -301,44 +320,9 @@
"url": "https://binternet.private.coffee" "url": "https://binternet.private.coffee"
} }
], ],
"icon": "images",
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": false "exclude_from_simple": false
},
{
"name": "Nitter",
"url": "https://nitter.private.coffee",
"short_description": "Nitter is a privacy-friendly alternative front-end to Twitter.",
"long_description": "Nitter is a privacy-friendly alternative front-end to Twitter. It allows you to browse Twitter without being tracked.",
"status": "NOK",
"links": [
{
"name": "Go to Nitter",
"url": "https://nitter.private.coffee",
"alternatives": [
{
"name": "Tor (.onion)",
"url": "http://nitter.coffee2m3bjsrrqqycx6ghkxrnejl2q6nl7pjw2j4clchjj6uk5zozad.onion/"
}
]
}
],
"exclude_from_index": true,
"exclude_from_simple": true
},
{
"name": "Proxigram",
"url": "https://proxigram.private.coffee",
"short_description": "Proxigram is a privacy-friendly alternative front-end to Instagram.",
"long_description": "Proxigram is a privacy-friendly alternative front-end to Instagram. It allows you to browse Instagram without being tracked.",
"status": "NOK",
"links": [
{
"name": "Go to Proxigram",
"url": "https://proxigram.private.coffee"
}
],
"exclude_from_index": true,
"exclude_from_simple": true
} }
] ]
} }

201
helpers/finances.py Normal file
View file

@ -0,0 +1,201 @@
from decimal import Decimal
def get_latest_month(data):
years = sorted(data.keys())
latest_year = years[-1]
months = sorted(data[latest_year].keys())
latest_month = months[-1]
return int(latest_month), int(latest_year)
def get_transparency_data(data, year=None, month=None):
if year is None:
year = max(data.keys())
if month is None:
month = max(data[year].keys())
assert year in data, f"Year {year} not found in data"
assert month in data[year], f"Month {month}-{year} not found in data"
# Initialize balances
balances = {}
incomes = {}
expenses = {}
start_balance = {}
end_balance = {}
for y in sorted(data.keys()):
if int(y) > int(year):
break
for m in sorted(data[y].keys()):
if int(y) == int(year) and int(m) > int(month):
break
# If the month is the one we are interested in, capture the start balance
if int(y) == int(year) and int(m) == int(month):
start_balance = {k: Decimal(v) for k, v in balances.items()}
for category in data[y][m]:
for currency, amount in data[y][m][category].items():
if currency not in balances:
balances[currency] = Decimal(0)
balances[currency] += Decimal(str(amount))
# Track incomes and expenses
if int(y) == int(year) and int(m) == int(month):
if Decimal(str(amount)) > 0:
if category not in incomes:
incomes[category] = {}
if currency not in incomes[category]:
incomes[category][currency] = Decimal(0)
incomes[category][currency] += Decimal(str(amount))
else:
if category not in expenses:
expenses[category] = {}
if currency not in expenses[category]:
expenses[category][currency] = Decimal(0)
expenses[category][currency] += Decimal(str(amount))
# If the month is the one we are interested in, capture the end balance
if int(y) == int(year) and int(m) == int(month):
end_balance = {k: Decimal(v) for k, v in balances.items()}
# Calculate accumulated sums of incomes and expenses
accumulated_incomes = {
currency: sum(incomes[cat].get(currency, Decimal(0)) for cat in incomes)
for currency in balances
}
accumulated_expenses = {
currency: sum(expenses[cat].get(currency, Decimal(0)) for cat in expenses)
for currency in balances
}
return {
"start_balance": start_balance,
"end_balance": end_balance,
"incomes": incomes,
"expenses": expenses,
"accumulated_incomes": accumulated_incomes,
"accumulated_expenses": accumulated_expenses,
}
def generate_transparency_table(result, currencies=None):
def extract_currencies(data):
return ["EUR"] + (
list(
set(
list(data["start_balance"].keys())
+ list(data["end_balance"].keys())
+ list(data["accumulated_incomes"].keys())
+ list(data["accumulated_expenses"].keys())
)
- {"EUR"}
)
)
def format_currency(value, currency):
if currency == "EUR":
return f"{value:,.2f}"
elif currency in ["BTC", "ETH", "XMR"]:
return f"{value:,.9f} {currency}"
else:
return f"{value} {currency}"
def format_value(value, currency):
if value == 0:
return f"{format_currency(value, currency)}"
elif value > 0:
return f"+ {format_currency(value, currency)}"
else:
return f"- {format_currency(abs(value), currency)}"
html = """
<table class="table table-bordered table-transparency">
<thead class="table-light">
<tr>
<th scope="col">Category</th>
"""
if currencies is None:
currencies = extract_currencies(result)
# Add currency headers
for currency in currencies:
if currency == "EUR":
html += '<th class="currency-col" scope="col">Euros (€)</th>'
elif currency == "BTC":
html += '<th class="currency-col" scope="col">Bitcoin (BTC)</th>'
elif currency == "ETH":
html += '<th class="currency-col" scope="col">Ethereum (ETH)</th>'
elif currency == "XMR":
html += '<th class="currency-col" scope="col">Monero (XMR)</th>'
else:
html += f'<th class="currency-col" scope="col">{currency}</th>'
html += """
</tr>
</thead>
<tbody>
"""
# Add start balance row
html += "<tr><td>Account Balance (start of month)</td>"
for currency in currencies:
value = result["start_balance"].get(currency, Decimal(0))
html += f"<td>{format_value(value, currency)}</td>"
html += "</tr>"
# Add income rows
for category, transactions in result["incomes"].items():
html += f"<tr><td>{category}</td>"
for currency in currencies:
value = transactions.get(currency, "")
if value != "":
html += f"<td>{format_value(value, currency)}</td>"
else:
html += "<td></td>"
html += "</tr>"
# Add expense rows
for category, transactions in result["expenses"].items():
html += f"<tr><td>{category}</td>"
for currency in currencies:
value = transactions.get(currency, "")
if value != "":
html += f"<td>{format_value(value, currency)}</td>"
else:
html += "<td></td>"
html += "</tr>"
# Add total income row
html += '<tr class="table-secondary"><td><b>Total Income</b></td>'
for currency in currencies:
value = result["accumulated_incomes"].get(currency, Decimal(0))
html += f"<td><b>{format_value(value, currency)}</b></td>"
html += "</tr>"
# Add total expenses row
html += '<tr class="table-secondary"><td><b>Total Expenses</b></td>'
for currency in currencies:
value = result["accumulated_expenses"].get(currency, Decimal(0))
html += f"<td><b>{format_value(value, currency)}</b></td>"
html += "</tr>"
# Add end balance row
html += '<tr class="table-secondary"><td><b>Account Balance (end of month)</b></td>'
for currency in currencies:
value = result["end_balance"].get(currency, Decimal(0))
html += f"<td><b>{format_value(value, currency)}</b></td>"
html += "</tr>"
html += """
</tbody>
</table>
"""
return html

77
main.py
View file

@ -3,9 +3,17 @@ from jinja2 import TemplateNotFound
import json import json
import pathlib import pathlib
import os
import datetime
from argparse import ArgumentParser from argparse import ArgumentParser
from helpers.finances import (
generate_transparency_table,
get_transparency_data,
get_latest_month,
)
app = Flask(__name__) app = Flask(__name__)
@ -18,18 +26,79 @@ def send_assets(path):
@app.route("/<path:path>.html") @app.route("/<path:path>.html")
def catch_all(path): def catch_all(path):
try: try:
services = json.loads( kwargs = {}
(pathlib.Path(__file__).parent / "services.json").read_text()
) if app.development_mode:
return render_template(f"{path}.html", services=services) kwargs.update(
{
"warning": render_template("prod-warning.html"),
}
)
if path in (
"index",
"simple",
):
services = json.loads(
(pathlib.Path(__file__).parent / "data" / "services.json").read_text()
)
kwargs.update(
{
"services": services,
}
)
if path == "membership":
finances = json.loads(
(pathlib.Path(__file__).parent / "data" / "finances.json").read_text()
)
finances_month, finances_year = get_latest_month(finances)
finances_period = datetime.date(finances_year, finances_month, 1)
finances_period_str = finances_period.strftime("%B %Y")
finances_table = generate_transparency_table(
get_transparency_data(finances)
)
kwargs.update(
{
"finances": finances_table,
"finances_period": finances_period_str,
}
)
return render_template(f"{path}.html", **kwargs)
except TemplateNotFound: except TemplateNotFound:
return "404 Not Found", 404 return "404 Not Found", 404
app.development_mode = False
if os.environ.get("PRIVATECOFFEE_DEV"):
app.development_mode = True
def icon(icon_name):
file = send_from_directory("assets", f"dist/icons/{icon_name}.svg")
try:
file_content = file.response.file.read().decode("utf-8")
except AttributeError:
file_content = file.response.read().decode("utf-8")
return file_content
app.add_template_filter(icon)
if __name__ == "__main__": if __name__ == "__main__":
parser = ArgumentParser(description="Run the private.coffee web server.") parser = ArgumentParser(description="Run the private.coffee web server.")
parser.add_argument("--port", type=int, default=9810) parser.add_argument("--port", type=int, default=9810)
parser.add_argument("--debug", action="store_true") parser.add_argument("--debug", action="store_true")
parser.add_argument("--dev", action="store_true")
args = parser.parse_args() args = parser.parse_args()
app.development_mode = args.dev or app.development_mode
app.run(port=args.port, debug=args.debug) app.run(port=args.port, debug=args.debug)

View file

@ -51,6 +51,7 @@
</ul><a class="btn btn-primary shadow navbar-btn" role="button" href="/membership.html">JOIN &amp; REBEL</a> </ul><a class="btn btn-primary shadow navbar-btn" role="button" href="/membership.html">JOIN &amp; REBEL</a>
</div> </div>
</nav> </nav>
{% if warning %}{{ warning|safe }}{% endif %}
{% block content %}{% endblock %} {% block content %}{% endblock %}
<footer class="bg-primary-gradient"> <footer class="bg-primary-gradient">
<div class="container py-4 py-lg-5"> <div class="container py-4 py-lg-5">
@ -74,26 +75,12 @@
<div class="fw-bold d-flex align-items-center mb-2"> <div class="fw-bold d-flex align-items-center mb-2">
<span <span
class="bs-icon-sm bs-icon-circle bs-icon-primary d-flex justify-content-center align-items-center bs-icon me-2" class="bs-icon-sm bs-icon-circle bs-icon-primary d-flex justify-content-center align-items-center bs-icon me-2"
><svg >{{ "coffee" | icon | safe }}</span
xmlns="http://www.w3.org/2000/svg"
width="1em"
height="1em"
fill="currentColor"
viewBox="0 0 16 16"
class="bi bi-bezier"
>
<path
fill-rule="evenodd"
d="M0 10.5A1.5 1.5 0 0 1 1.5 9h1A1.5 1.5 0 0 1 4 10.5v1A1.5 1.5 0 0 1 2.5 13h-1A1.5 1.5 0 0 1 0 11.5zm1.5-.5a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5zm10.5.5A1.5 1.5 0 0 1 13.5 9h1a1.5 1.5 0 0 1 1.5 1.5v1a1.5 1.5 0 0 1-1.5 1.5h-1a1.5 1.5 0 0 1-1.5-1.5zm1.5-.5a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5zM6 4.5A1.5 1.5 0 0 1 7.5 3h1A1.5 1.5 0 0 1 10 4.5v1A1.5 1.5 0 0 1 8.5 7h-1A1.5 1.5 0 0 1 6 5.5zM7.5 4a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5z"
></path>
<path
d="M6 4.5H1.866a1 1 0 1 0 0 1h2.668A6.517 6.517 0 0 0 1.814 9H2.5c.123 0 .244.015.358.043a5.517 5.517 0 0 1 3.185-3.185A1.503 1.503 0 0 1 6 5.5zm3.957 1.358A1.5 1.5 0 0 0 10 5.5v-1h4.134a1 1 0 1 1 0 1h-2.668a6.517 6.517 0 0 1 2.72 3.5H13.5c-.123 0-.243.015-.358.043a5.517 5.517 0 0 0-3.185-3.185z"
></path></svg></span
><span>Private.coffee</span> ><span>Private.coffee</span>
</div> </div>
<p class="text-muted"> <p class="text-muted">
Private.coffee is a collection of services that respect your Private.coffee is a privacy-focused non-profit association, dedicated
privacy. to supporting privacy and digital sovereignty.
</p> </p>
</div> </div>
</div> </div>

View file

@ -29,10 +29,9 @@
<div class="col mb-5"> <div class="col mb-5">
<div class="card shadow-sm"> <div class="card shadow-sm">
<div class="card-body px-4 py-5 px-md-5"> <div class="card-body px-4 py-5 px-md-5">
<div class="bs-icon-lg d-flex justify-content-center align-items-center mb-3 bs-icon" style="top: 1rem;right: 1rem;position: absolute;"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" viewBox="0 0 16 16" class="bi bi-chat-text text-primary"> <div class="bs-icon-lg d-flex justify-content-center align-items-center mb-3 bs-icon" style="top: 1rem;right: 1rem;position: absolute;">
<path d="M2.678 11.894a1 1 0 0 1 .287.801 10.97 10.97 0 0 1-.398 2c1.395-.323 2.247-.697 2.634-.893a1 1 0 0 1 .71-.074A8.06 8.06 0 0 0 8 14c3.996 0 7-2.807 7-6 0-3.192-3.004-6-7-6S1 4.808 1 8c0 1.468.617 2.83 1.678 3.894m-.493 3.905a21.682 21.682 0 0 1-.713.129c-.2.032-.352-.176-.273-.362a9.68 9.68 0 0 0 .244-.637l.003-.01c.248-.72.45-1.548.524-2.319C.743 11.37 0 9.76 0 8c0-3.866 3.582-7 8-7s8 3.134 8 7-3.582 7-8 7a9.06 9.06 0 0 1-2.347-.306c-.52.263-1.639.742-3.468 1.105z"></path> {% if service.icon %}{{ service.icon | icon | safe }}{% endif %}
<path d="M4 5.5a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5M4 8a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7A.5.5 0 0 1 4 8m0 2.5a.5.5 0 0 1 .5-.5h4a.5.5 0 0 1 0 1h-4a.5.5 0 0 1-.5-.5"></path> </div>
</svg></div>
<h5 class="fw-bold card-title">{{ service.name }}</h5> <h5 class="fw-bold card-title">{{ service.name }}</h5>
<p class="text-muted card-text mb-4">{{ service.long_description }}</p> <p class="text-muted card-text mb-4">{{ service.long_description }}</p>
{% for link in service.links %} {% for link in service.links %}
@ -92,9 +91,7 @@
<div class="col-md-4 col-xl-4 d-flex justify-content-center justify-content-xl-start"> <div class="col-md-4 col-xl-4 d-flex justify-content-center justify-content-xl-start">
<div class="d-flex flex-wrap flex-md-column justify-content-md-start align-items-md-start h-100"> <div class="d-flex flex-wrap flex-md-column justify-content-md-start align-items-md-start h-100">
<div class="d-flex align-items-center p-3"> <div class="d-flex align-items-center p-3">
<div class="bs-icon-md bs-icon-circle bs-icon-primary shadow d-flex flex-shrink-0 justify-content-center align-items-center d-inline-block bs-icon bs-icon-md"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" viewBox="0 0 16 16" class="bi bi-envelope"> <div class="bs-icon-md bs-icon-circle bs-icon-primary shadow d-flex flex-shrink-0 justify-content-center align-items-center d-inline-block bs-icon bs-icon-md">{{ "envelope" | icon | safe }}</div>
<path d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1zm13 2.383-4.708 2.825L15 11.105zm-.034 6.876-5.64-3.471L8 9.583l-1.326-.795-5.64 3.47A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.741M1 11.105l4.708-2.897L1 5.383z"></path>
</svg></div>
<div class="px-2"> <div class="px-2">
<h6 class="fw-bold mb-0">Email</h6> <h6 class="fw-bold mb-0">Email</h6>
<p class="text-muted mb-0">support@private.coffee</p> <p class="text-muted mb-0">support@private.coffee</p>
@ -107,9 +104,7 @@
<div class="col-md-4 col-xl-4 d-flex justify-content-center justify-content-xl-start"> <div class="col-md-4 col-xl-4 d-flex justify-content-center justify-content-xl-start">
<div class="d-flex flex-wrap flex-md-column justify-content-md-start align-items-md-start h-100"> <div class="d-flex flex-wrap flex-md-column justify-content-md-start align-items-md-start h-100">
<div class="d-flex align-items-center p-3"> <div class="d-flex align-items-center p-3">
<div class="bs-icon-md bs-icon-circle bs-icon-primary shadow d-flex flex-shrink-0 justify-content-center align-items-center d-inline-block bs-icon bs-icon-md"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" viewBox="0 0 16 16" class="bi bi-envelope"> <div class="bs-icon-md bs-icon-circle bs-icon-primary shadow d-flex flex-shrink-0 justify-content-center align-items-center d-inline-block bs-icon bs-icon-md">{{ "matrix-logo" | icon | safe }}</div>
<path d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1zm13 2.383-4.708 2.825L15 11.105zm-.034 6.876-5.64-3.471L8 9.583l-1.326-.795-5.64 3.47A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.741M1 11.105l4.708-2.897L1 5.383z"></path>
</svg></div>
<div class="px-2"> <div class="px-2">
<h6 class="fw-bold mb-0">Matrix</h6> <h6 class="fw-bold mb-0">Matrix</h6>
<p class="text-muted mb-0"><a href="https://matrix.pcof.fi/#/#private.coffee:private.coffee">#private.coffee:private.coffee</a></p> <p class="text-muted mb-0"><a href="https://matrix.pcof.fi/#/#private.coffee:private.coffee">#private.coffee:private.coffee</a></p>

View file

@ -1,7 +1,7 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}Legal Notice{% endblock %} {% block title %}Legal Notice{% endblock %}
{% block content %} {% block content %}
<section class="bg-primary-gradient"> <section>
<div class="container py-5"> <div class="container py-5">
<div class="row align-items-center"> <div class="row align-items-center">
<div class="col"> <div class="col">
@ -20,7 +20,6 @@
</div> </div>
<div class="container"> <div class="container">
<h1>Legal Notice</h1>
<p>This is a legal notice for the website private.coffee</p> <p>This is a legal notice for the website private.coffee</p>
<p>The website private.coffee is run by the following entity:</p> <p>The website private.coffee is run by the following entity:</p>
<address> <address>

View file

@ -1,56 +1,116 @@
{% extends "base.html" %} {% extends "base.html" %} {% block title %}Membership / Donations{% endblock %}
{% block title %}Membership / Donations{% endblock %}
{% block content %} {% block content %}
<div class="container"> <div class="container my-5">
<h1>Membership/Donations</h1> <div class="text-center mb-5">
<p> <h1 class="special-header fancy-text-primary">Membership/Donations</h1>
private.coffee is a non-profit organization dedicated to supporting privacy <p class="lead">
and digital sovereignty. We fund our server infrastructure through donations Private.coffee is a non-profit organization dedicated to supporting
and membership fees. privacy and digital sovereignty. We fund our activities and running
</p> infrastructure costs through membership fees. Donations allow us to expand
<p> our services and reach more people.
Membership fees help cover the costs of server infrastructure, domain names,
and other operating expenses. Likewise, all donations contribute towards
these ongoing costs.
</p>
<p>
Supporting the private.coffee project is possible by joining our association
or by making a direct donation.
</p>
<div class="donation-details">
<p><b>Donations:</b></p>
<p>
Bank private.coffee - Verein zur Förderung von Privatsphäre und digitaler
Souveränität
</p>
<p>IBAN: AT35 2081 5000 4554 0812</p>
<p>BIC: STSPAT2GXXX</p>
<p>
For donation listing preferences, please specify in the note to payee.
</p> </p>
</div> </div>
<div class="zvr-number"> <div class="row">
<p>Central Register of Associations (ZVR) Number: 1758485319</p> <div class="col-md-4 mb-4">
<p> <div class="card shadow-sm">
Our statutes can be found in our Git <div class="card-body">
<a href="https://git.private.coffee/PrivateCoffee/statuten" <h5 class="card-title">Membership</h5>
>in German (legally binding)</a <p class="card-text">
> Membership fees help cover the costs of our day-to-day activities,
and server infrastructure, domain names, and other running operating
<a expenses. This allows us to provide services to our members and the
href="https://git.private.coffee/PrivateCoffee/Statuten/src/branch/english" public.
>in English</a </p>
>. <p class="card-text">
</p> If you're interested in joining our association, get in touch with
<p class="contact-info"> us for more information.
Interested in joining the association? Reach out via </p>
<a href="mailto:support@private.coffee">email</a> or </div>
<a href="https://matrix.private.cf/#/#private.coffee:private.coffee" </div>
>Matrix</a </div>
>
for more information. <div class="col-md-4 mb-4">
</p> <div class="card shadow-sm">
<div class="card-body">
<h5 class="card-title">Bank Donations</h5>
<p class="card-text">
Even if you're not a member, you can still support us by making a
direct donation to our bank account. Your donation will be used to
fund our activities and expand our services.
</p>
<p class="card-text"><b>Account holder:</b> Private.coffee</p>
<p class="card-text"><b>IBAN:</b> AT35 2081 5000 4554 0812</p>
<p class="card-text"><b>BIC:</b> STSPAT2GXXX</p>
</div>
</div>
</div>
<div class="col-md-4 mb-4">
<div class="card shadow-sm">
<div class="card-body">
<h5 class="card-title">Crypto Donations</h5>
<p class="card-text">
While our expenses are generally in fiat currency, we accept
donations in cryptocurrencies, too.
</p>
<p class="card-text">
<b>Bitcoin (BTC):</b>
<code>bc1qnu7r5sed4afacfpgx5za8hsyhaj4rs45dpm26k</code>
</p>
<p class="card-text">
<b>Monero (XMR):</b>
<code
>487Ny4iBk2pKGJwjyYrumFD8xFmrS6jCSXNA8e5EvVJ49GyS54CRDVz514MBnXgNT1EioKYiagHs33sLzUAFj8i3Pwg3AMS</code
>
</p>
<p class="card-text">
<b>Ethereum (ETH):</b> <code>Coming soon&trade;</code>
</p>
<p class="card-text">
If your client supports OpenAlias, you can just send your donation
to <code>private.coffee</code>.
</p>
</div>
</div>
</div>
</div>
<div class="card shadow-sm mt-4">
<div class="card-body">
<h5 class="card-title">Transparency Report for {{ finances_period }}</h5>
<p class="card-text">
We believe in transparency and accountability. Below is a summary of our
income and expenses for the last month, so you can see how your
donations are being used.
</p>
<div class="table-responsive">{{ finances|safe }}</div>
</div>
</div>
<div class="card shadow-sm mt-4">
<div class="card-body">
<h5>Central Register of Associations (ZVR) Number: 1758485319</h5>
<p>
Our statutes can be found in our Git
<a href="https://git.private.coffee/PrivateCoffee/statuten"
>in German (legally binding)</a
>
and
<a
href="https://git.private.coffee/PrivateCoffee/Statuten/src/branch/english"
>in English</a
>.
</p>
<p class="contact-info" id="contact-info">
Interested in joining the association? Reach out via
<a href="mailto:support@private.coffee">email</a> or
<a href="https://matrix.pcof.fi/#/#private.coffee:private.coffee"
>Matrix</a
>
for more information.
</p>
</div>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View file

@ -1,167 +1,187 @@
{% extends "base.html" %} {% extends "base.html" %} {% block title %}Privacy Policy{% endblock %}
{% block title %}Privacy Policy{% endblock %}
{% block content %} {% block content %}
<div class="container"> <div class="container">
<h1>Privacy Policy</h1> <div class="text-center mb-5">
<p> <h1 class="special-header fancy-text-primary">Privacy Policy</h1>
This is the privacy policy for the website private.coffee. It describes how <p class="lead">
we collect and use your personal data. This is the privacy policy for the website private.coffee. It describes
</p> how we collect and use your personal data.
<p> </p>
This privacy policy is effective as of 2024-04-26. It may be updated from </div>
time to time, so please check back regularly. <div class="section">
</p> <p>
<p> This privacy policy is effective as of 2024-04-26. It may be updated from
If you have any questions about this privacy policy, please contact us at time to time, so please check back regularly.
<a href="mailto:support@private.coffee">support@private.coffee</a>. </p>
</p> <p>
<h2>Who are we?</h2> If you have any questions about this privacy policy, please contact us at
<p>The data controller for private.coffee is:</p> <a href="mailto:support@private.coffee">support@private.coffee</a>.
<address> </p>
Private.coffee &dash; Verein zur Förderung von Privatsphäre und digitaler </div>
Souver&auml;nit&auml;t<br /> <div class="section">
c/o Klaus-Uwe Mitterer<br /> <h2>Who are we?</h2>
Gartengasse 22/7/3<br /> <p>The data controller for private.coffee is:</p>
8010 Graz<br /> <address>
Austria<br /> Private.coffee &dash; Verein zur Förderung von Privatsphäre und digitaler
</address> Souver&auml;nit&auml;t<br />
<p>Central Register of Associations (ZVR) Number: 1758485319</p> c/o Klaus-Uwe Mitterer<br />
<p> Gartengasse 22/7/3<br />
Email: 8010 Graz<br />
<a href="mailto:support@private.coffee">support@private.coffee</a> Austria<br />
</p> </address>
<h2>What data do we collect?</h2> <p>Central Register of Associations (ZVR) Number: 1758485319</p>
<p>We collect the following data from you:</p> <p>
<ul> Email:
<li> <a href="mailto:support@private.coffee">support@private.coffee</a>
Your IP address, which is automatically collected by our web server for </p>
some of our services. </div>
</li> <div class="section">
<li> <h2>What data do we collect?</h2>
Any data you provide to us, such as your email address, when you create an <p>We collect the following data from you:</p>
account on one of our services. <ul>
</li> <li>
<li> Your IP address, which is automatically collected by our web server for
Usage data that is collected automatically by our services, such as the some of our services.
time you last logged in, or the number of times you have logged in, as </li>
well as any content you create using our services. <li>
</li> Any data you provide to us, such as your email address, when you create
<li> an account on one of our services.
Any information, including personal data and payment information, that you </li>
provide to us when you make a donation or join our association. <li>
</li> Usage data that is collected automatically by our services, such as the
</ul> time you last logged in, or the number of times you have logged in, as
<h2>How do we use your data?</h2> well as any content you create using our services.
<p> </li>
We use your data to provide you with the services you requested. This <li>
includes: Any information, including personal data and payment information, that
</p> you provide to us when you make a donation or join our association.
<ul> </li>
<li>Communication between our web server and your browser</li> </ul>
<li>Storing your preferences or your created content</li> </div>
<li>Detection of abuse or resource exhaustion on our servers</li> <div class="section">
<li>Providing support to you</li> <h2>How do we use your data?</h2>
<li>Processing donations and memberships</li> <p>
</ul> We use your data to provide you with the services you requested. This
<p>All of those are what is called "legitimate interests" in legal speak.</p> includes:
<p> </p>
We do not use your data for any other purposes, including marketing, <ul>
advertising, or tracking, we do not share your data with third parties <li>Communication between our web server and your browser</li>
(unless required by law), we do not use your data to create profiles or make <li>Storing your preferences or your created content</li>
automated decisions, and we do not cross-reference your data between <li>Detection of abuse or resource exhaustion on our servers</li>
different services or any other sources. <li>Providing support to you</li>
</p> <li>Processing donations and memberships</li>
<h2>Where do we store your data?</h2> </ul>
<p> <p>
We store your data on our web servers, which are located in Austria. We also All of those are what is called "legitimate interests" in legal speak.
use servers in Germany, but those are not public-facing and do not store or </p>
process any personal data. <p>
</p> We do not use your data for any other purposes, including marketing,
<h2>How long do we store your data?</h2> advertising, or tracking, we do not share your data with third parties
<ul> (unless required by law), we do not use your data to create profiles or
<li> make automated decisions, and we do not cross-reference your data between
IP addresses collected by our web server are stored for up to 48 hours. different services or any other sources.
After that, the log files that contain them are deleted automatically. </p>
</li> </div>
<li> <div class="section">
Data associated with an account you have on one of our services is stored <h2>Where do we store your data?</h2>
for as long as you have an account on that service. If you delete your <p>
account, your data will be deleted automatically. The service will have a We store your data on our web servers, which are located in Austria. We
dedicated privacy policy, please consult that if you have any specific also use servers in Germany, but those are not public-facing and do not
questions. store or process any personal data.
</li> </p>
<li> </div>
If you send a support request to us, we will store your email address and <div class="section">
any other data you provide to us for up to 30 days in our support system. <h2>How long do we store your data?</h2>
After that, the data will be deleted automatically. <ul>
</li> <li>
<li> IP addresses collected by our web server are stored for up to 48 hours.
Data associated with a donation is stored for as long as required by law, After that, the log files that contain them are deleted automatically.
which is currently 7 years in Austria. After that, the data will be </li>
deleted. <li>
</li> Data associated with an account you have on one of our services is
<li> stored for as long as you have an account on that service. If you delete
Data associated with a membership is stored for as long as you are a your account, your data will be deleted automatically. The service will
member of our association. If you leave the association, your data will be have a dedicated privacy policy, please consult that if you have any
deleted automatically. This does not apply to data that is required by law specific questions.
to be stored for a longer period of time, such as financial records, which </li>
are stored for 7 years regardless of your membership status. <li>
</li> If you send a support request to us, we will store your email address
</ul> and any other data you provide to us for up to 30 days in our support
<h2>What are your data protection rights?</h2> system. After that, the data will be deleted automatically.
<p>You have the following data protection rights:</p> </li>
<ul> <li>
<li>You have the right to request access to your personal data.</li> Data associated with a donation is stored for as long as required by
<li>You have the right to request correction of your personal data.</li> law, which is currently 7 years in Austria. After that, the data will be
<li>You have the right to request erasure of your personal data.</li> deleted.
<li> </li>
You have the right to request restriction of processing of your personal <li>
data. Data associated with a membership is stored for as long as you are a
</li> member of our association. If you leave the association, your data will
<li>You have the right to object to processing of your personal data.</li> be deleted automatically. This does not apply to data that is required
<li>You have the right to request transfer of your personal data.</li> by law to be stored for a longer period of time, such as financial
</ul> records, which are stored for 7 years regardless of your membership
<p>If you make a request, we have one month to respond to you.</p> status.
<p> </li>
If you would like to exercise any of these rights, please contact us at </ul>
<a href="mailto:support@private.coffee">support@private.coffee</a>. </div>
</p> <div class="section">
<p> <h2>What are your data protection rights?</h2>
Your privacy is important to us - after all, that's why we're all here - and <p>You have the following data protection rights:</p>
we will do our best to respond to your request as soon as possible. Please <ul>
note that we may need to verify your identity before we can respond to your <li>You have the right to request access to your personal data.</li>
request - we will not share your data with anyone else. <li>You have the right to request correction of your personal data.</li>
</p> <li>You have the right to request erasure of your personal data.</li>
<p> <li>
If you are not satisfied with our response, or believe that we are You have the right to request restriction of processing of your personal
processing your data in a way that is not compliant with the law, you have data.
the right to lodge a complaint with the supervisory authority in your </li>
country. In Austria, this is the Austrian Data Protection Authority (<a <li>You have the right to object to processing of your personal data.</li>
href="https://www.dsb.gv.at/" <li>You have the right to request transfer of your personal data.</li>
>https://www.dsb.gv.at/</a </ul>
>). However, we like to think of ourselves as nice people and will try to <p>If you make a request, we have one month to respond to you.</p>
help you out directly, and are always open to suggestions for improvement, <p>
so please do get in touch with us if you have any questions or concerns. If you would like to exercise any of these rights, please contact us at
</p> <a href="mailto:support@private.coffee">support@private.coffee</a>.
<h2>What are cookies?</h2> </p>
<p> <p>
Cookies are small text files that are placed on your computer or mobile Your privacy is important to us - after all, that's why we're all here -
device when you visit a website. They are widely used to make websites work, and we will do our best to respond to your request as soon as possible.
or work more efficiently, as well as to provide information to the owners of Please note that we may need to verify your identity before we can respond
the site. Cookies are stored on your device, and can be accessed by the to your request - we will not share your data with anyone else.
website that created them. They are not harmful to your device, and do not </p>
directly contain any personal data, but are used by our services to identify <p>
you between multiple visits. If you are not satisfied with our response, or believe that we are
</p> processing your data in a way that is not compliant with the law, you have
<p> the right to lodge a complaint with the supervisory authority in your
Cookies are used on some of our services to provide you with a better country. In Austria, this is the Austrian Data Protection Authority (<a
experience. For example, we use cookies to remember your preferences and href="https://www.dsb.gv.at/"
settings - for example, to allow you to login to our services - and to >https://www.dsb.gv.at/</a
provide you with a better experience when browsing our services. We do not >). However, we like to think of ourselves as nice people and will try to
use cookies to track your activity, either on our services or on other help you out directly, and are always open to suggestions for improvement,
websites. In legal/technical terms, we exclusively use "strictly necessary" so please do get in touch with us if you have any questions or concerns.
first-party cookies, which is also why you don't see any cookie banners on </p>
our website. </div>
</p> <div class="section">
<h2>What are cookies?</h2>
<p>
Cookies are small text files that are placed on your computer or mobile
device when you visit a website. They are widely used to make websites
work, or work more efficiently, as well as to provide information to the
owners of the site. Cookies are stored on your device, and can be accessed
by the website that created them. They are not harmful to your device, and
do not directly contain any personal data, but are used by our services to
identify you between multiple visits.
</p>
<p>
Cookies are used on some of our services to provide you with a better
experience. For example, we use cookies to remember your preferences and
settings - for example, to allow you to login to our services - and to
provide you with a better experience when browsing our services. We do not
use cookies to track your activity, either on our services or on other
websites. In legal/technical terms, we exclusively use "strictly
necessary" first-party cookies, which is also why you don't see any cookie
banners on our website.
</p>
</div>
</div> </div>
{% endblock %} {% endblock %}

View file

@ -0,0 +1,6 @@
<div class="alert alert-warning text-center" role="alert">
This is a development version of the Private.coffee website. For the live
version, please visit
<a href="https://private.coffee" class="alert-link">https://private.coffee</a
>.
</div>

View file

@ -8,7 +8,15 @@
<body> <body>
<div style="font-family: Arial, sans-serif; background-color: #f2f2f2; color: #333; line-height: 1.6; padding: 20px; max-width: 600px; margin: auto;"> <div style="font-family: Arial, sans-serif; background-color: #f2f2f2; color: #333; line-height: 1.6; padding: 20px; max-width: 600px; margin: auto;">
<h2 style="color: #333;">Welcome to Private.coffee</h2> <h2 style="color: #333;">Welcome to Private.coffee</h2>
<p>Thanks for using our Element instance. Private.coffee is a collection of services that respect your privacy, here are some others:</p> <p>Thanks for using our Element instance! Now, why don't you join our rooms?</p>
<ul style="list-style: none; padding: 0;">
<li style="padding: 8px 0;"><a style="color: #1a5dab; text-decoration: none;" href="https://element.private.coffee/#/#private-coffee:private.coffee">#private-coffee:private.coffee</a> - The Private.coffee Space, containing all rooms</li>
<li style="padding: 8px 0;"><a style="color: #1a5dab; text-decoration: none;" href="https://element.private.coffee/#/#private.coffee:private.coffee">#private.coffee:private.coffee</a> - General support for our services</li>
<li style="padding: 8px 0;"><a style="color: #1a5dab; text-decoration: none;" href="https://element.private.coffee/#/#matrix:private.coffee">#matrix:private.coffee</a> - Support for our Matrix server</li>
<li style="padding: 8px 0;"><a style="color: #1a5dab; text-decoration: none;" href="https://element.private.coffee/#/#coffeebreak:private.coffee">#coffeebreak:private.coffee</a> - ☕ Coffee Break ☕ - our off-topic room</li>
</ul>
<hr>
<p>Private.coffee operates a collection of services that respect your privacy, here are some others:</p>
<ul style="list-style: none; padding: 0;"> <ul style="list-style: none; padding: 0;">
{% for service in services.services %} {% for service in services.services %}
{% if not service.exclude_from_simple %} {% if not service.exclude_from_simple %}

View file

@ -2,143 +2,154 @@
{% block title %}Terms of Service{% endblock %} {% block title %}Terms of Service{% endblock %}
{% block content %} {% block content %}
<div class="container"> <div class="container">
<h1>Terms of Service</h1> <div class="text-center mb-5">
<p> <h1 class="special-header fancy-text-primary">Terms of Service</h1>
These are the terms of service for the website private.coffee and all <p class="lead">
services provided under this domain and its subdomains. Please read them These are the terms of service for the website private.coffee and all
carefully. services provided under this domain and its subdomains. Please read them
</p> carefully.
<h2>1. Who are we?</h2> </p>
<p>The website private.coffee is run by:</p> </div>
<address> <div class="section">
Private.coffee &dash; Verein zur Förderung von Privatsphäre und digitaler <h2>1. Who are we?</h2>
Souver&auml;nit&auml;t<br /> <p>The website private.coffee is run by:</p>
c/o Klaus-Uwe Mitterer<br /> <address>
Gartengasse 22/7/3<br /> Private.coffee &dash; Verein zur Förderung von Privatsphäre und digitaler
8010 Graz<br /> Souver&auml;nit&auml;t<br />
Austria<br /> c/o Klaus-Uwe Mitterer<br />
</address> Gartengasse 22/7/3<br />
<p>Central Register of Associations (ZVR) Number: 1758485319</p> 8010 Graz<br />
<p> Austria<br />
Email: </address>
<a href="mailto:support@private.coffee">support@private.coffee</a> <p>Central Register of Associations (ZVR) Number: 1758485319</p>
</p> <p>
<h2>2. What services do we provide?</h2> Email:
<p> <a href="mailto:support@private.coffee">support@private.coffee</a>
The website private.coffee provides a collection of services that respect </p>
your privacy. These services include: </div>
</p> <div class="section">
<ul> <h2>2. What services do we provide?</h2>
<li> <p>
Proxy servers to several proprietary services (like YouTube, Twitter, The website private.coffee provides a collection of services that respect
etc.) your privacy. These services include:
</li> </p>
<li>Matrix server</li> <ul>
<li>etc.</li> <li>Information about the Private.coffee association</li>
</ul> <li>
<p> Proxy servers to several proprietary services (like YouTube, Twitter,
You can find more information about these services on the etc.)
<a href="/">main page</a>. </li>
</p> <li>Matrix server</li>
<h2>3. What are your obligations?</h2> <li>etc.</li>
<p> </ul>
a. We provide these services to you for free. In return, we ask you to <p>
respect our terms of service. If you do not respect our terms of service, we You can find more information about these services on the
reserve the right to terminate your account and delete your data. <a href="/">main page</a>.
</p> </p>
<p> </div>
b. We hope that our community will be diverse, respectful and friendly. As <div class="section">
such, any form of harassment, bullying, or abuse will not be tolerated. If <h2>3. What are your obligations?</h2>
you are found to be harassing, bullying, or abusing other users, spreading <p>
hate, lies or misinformation, we will terminate your account and delete your a. We provide these services to you for free. In return, we ask you to
data. Note that we may and will report you to the appropriate authorities if respect our terms of service. If you do not respect our terms of service, we
we find your actions to be illegal. If you find yourself on the receiving reserve the right to terminate your account and delete your data.
end of harassment, bullying, or abuse, please report it to us as soon as </p>
possible. <p>
</p> b. We hope that our community will be diverse, respectful and friendly. As
<p> such, any form of harassment, bullying, or abuse will not be tolerated. If
c. You are responsible for your own actions and any content you post on our you are found to be harassing, bullying, or abusing other users, spreading
services. hate, lies or misinformation, we will terminate your account and delete your
</p> data. Note that we may and will report you to the appropriate authorities if
<p> we find your actions to be illegal. If you find yourself on the receiving
d. You are responsible for keeping your passwords, devices, private keys, end of harassment, bullying, or abuse, please report it to us as soon as
etc., secure. If you lose access, we may not be able to recover your data. possible.
If third parties gain access to your account, we will not be able to prevent </p>
them from accessing your data or restore any data that was lost. <p>
</p> c. You are responsible for your own actions and any content you post on our
<p> services.
e. You are required to follow the laws governing our platform (especially </p>
the laws of Austria and the European Union) as well as any laws or <p>
regulations that apply to you personally. If you are found to be violating d. You are responsible for keeping your passwords, devices, private keys,
the law, we will terminate your account and delete your data. If we are etc., secure. If you lose access, we may not be able to recover your data.
required to do so by law, we will also report you to the authorities, or If third parties gain access to your account, we will not be able to prevent
cooperate with the authorities in any way necessary. them from accessing your data or restore any data that was lost.
</p> </p>
<p> <p>
f. You are responsible for any damage you cause to our services or other e. You are required to follow the laws governing our platform (especially
users. This includes, but is not limited to, denial of service attacks, the laws of Austria and the European Union) as well as any laws or
spamming, etc. If you are found to be causing damage to our services or regulations that apply to you personally. If you are found to be violating
other users, we will terminate your account and delete your data. We may the law, we will terminate your account and delete your data. If we are
also report you to the appropriate authorities and request compensation for required to do so by law, we will also report you to the authorities, or
any damage you caused, including legal fees. cooperate with the authorities in any way necessary.
</p> </p>
<p> <p>
g. If you are a minor, you may be legally required to have a parent's or f. You are responsible for any damage you cause to our services or other
guardian's permission to use our services. Unless otherwise stated, our users. This includes, but is not limited to, denial of service attacks,
services are not intended for minors. spamming, etc. If you are found to be causing damage to our services or
</p> other users, we will terminate your account and delete your data. We may
<p> also report you to the appropriate authorities and request compensation for
h. In the end, this is our platform, and you are our guest. We reserve the any damage you caused, including legal fees.
right to terminate your account and delete your data at any time for any </p>
reason. We will try to give you as much notice as possible before doing so, <p>
but we are not required to do so. g. If you are a minor, you may be legally required to have a parent's or
</p> guardian's permission to use our services. Unless otherwise stated, our
<h2>4. What are our obligations?</h2> services are not intended for minors.
<p> </p>
a. We will do our best to provide you with a stable and reliable service. <p>
However, we cannot guarantee that our services will be available at all h. In the end, this is our platform, and you are our guest. We reserve the
times. We may need to take our services offline for maintenance or other right to terminate your account and delete your data at any time for any
reasons. In case of scheduled outages, will try to give you as much notice reason. We will try to give you as much notice as possible before doing so,
as possible. but we are not required to do so.
</p> </p>
<p> </div>
b. We will do our best to keep your data secure. However, we cannot <div class="section">
guarantee that your data will be secure at all times. We will do our best to <h2>4. What are our obligations?</h2>
prevent unauthorized access to your data, but we cannot guarantee that we <p>
will be able to do so. If we become aware of any unauthorized access to your a. We will do our best to provide you with a stable and reliable service.
data, we will notify you as soon as possible and take all reasonable steps However, we cannot guarantee that our services will be available at all
to prevent further unauthorized access. However, we are not responsible for times. We may need to take our services offline for maintenance or other
any damage that may result from unauthorized access to your data. reasons. In case of scheduled outages, will try to give you as much notice
</p> as possible.
<p> </p>
c. We will do our best to prevent data loss. However, we cannot guarantee <p>
that your data will not be lost at any time. We will do our best to prevent b. We will do our best to keep your data secure. However, we cannot
data loss, but we cannot guarantee that we will be able to do so. If we guarantee that your data will be secure at all times. We will do our best to
become aware of any data loss, we will take all reasonable steps to restore prevent unauthorized access to your data, but we cannot guarantee that we
your data. If we are unable to restore your data, we are not responsible for will be able to do so. If we become aware of any unauthorized access to your
any damage that may result from the loss of your data. data, we will notify you as soon as possible and take all reasonable steps
</p> to prevent further unauthorized access. However, we are not responsible for
<p> any damage that may result from unauthorized access to your data.
d. We will do our best to keep our services available free of charge. If at </p>
any time we decide to cease our operations, or start charging for our <p>
services, we will give you as much notice as possible. We will also try to c. We will do our best to prevent data loss. However, we cannot guarantee
find a suitable replacement for our services and, where possible, help you that your data will not be lost at any time. We will do our best to prevent
migrate your data to the new service. data loss, but we cannot guarantee that we will be able to do so. If we
</p> become aware of any data loss, we will take all reasonable steps to restore
<p> your data. If we are unable to restore your data, we are not responsible for
e. We commit to providing you with a service that respects your privacy. We any damage that may result from the loss of your data.
will not sell your data to third parties, and we will not use your data for </p>
any purpose other than providing you with our services. We will not share <p>
your data with third parties unless we are required to do so by law. d. We will do our best to keep our services available free of charge. If at
</p> any time we decide to cease our operations, or start charging for our
<p> services, we will give you as much notice as possible. We will also try to
f. We commit to keeping our community diverse, respectful and friendly. As find a suitable replacement for our services and, where possible, help you
such, we will actively monitor and moderate our community. We will not migrate your data to the new service.
tolerate any form of harassment, bullying, or abuse. If we become aware of </p>
any harassment, bullying, or abuse, we will take all reasonable steps to <p>
prevent it from continuing. If we are unable to prevent it from continuing, e. We commit to providing you with a service that respects your privacy. We
we will terminate the accounts of the users involved and delete their data. will not sell your data to third parties, and we will not use your data for
We may also report the users involved to the appropriate authorities. any purpose other than providing you with our services. We will not share
</p> your data with third parties unless we are required to do so by law.
</p>
<p>
f. We commit to keeping our community diverse, respectful and friendly. As
such, we will actively monitor and moderate our community. We will not
tolerate any form of harassment, bullying, or abuse. If we become aware of
any harassment, bullying, or abuse, we will take all reasonable steps to
prevent it from continuing. If we are unable to prevent it from continuing,
we will terminate the accounts of the users involved and delete their data.
We may also report the users involved to the appropriate authorities.
</p>
</div>
</div> </div>
{% endblock %} {% endblock %}