Compare commits

..

No commits in common. "master" and "feature/time_machine_page" have entirely different histories.

149 changed files with 641 additions and 5634 deletions

1
.gitignore vendored
View File

@ -16,7 +16,6 @@ local/backups
/tmp
*.exe
.DS_Store
__debug_bin*
# vim session saves
Session.vim

View File

@ -4,7 +4,6 @@ const RecvAddress = "admin@example.com"
const RecvName = "Admin"
const FromName = "From Name"
const FromAddress = "from@address.com"
const ServerUsername = "username"
const ServerPassword = "password"
const FromAddressPassword = "password"
const ServerAddress = "server.address"
const ServerPort = 587

View File

@ -46,7 +46,7 @@ func sendMail(toAddress, toName, subject, contentHtml string) error {
)
return smtp.SendMail(
fmt.Sprintf("%s:%d", ServerAddress, ServerPort),
smtp.PlainAuth("", ServerUsername, ServerPassword, ServerAddress),
smtp.PlainAuth("", FromAddress, FromAddressPassword, ServerAddress),
FromAddress,
[]string{toAddress},
contents,

View File

@ -1,4 +1,4 @@
- [ ] Export with [DiscordChatExporter](https://github.com/Tyrrrz/DiscordChatExporter) CLI 2.39.1
- [ ] Export with [DiscordChatExporter](https://github.com/Tyrrrz/DiscordChatExporter) CLI 2.34
```
DiscordChatExporter.Cli.exe export -c [thread-id] -t [token] -o [fishbowl].html --media
@ -49,7 +49,7 @@
go run twemoji.go [fishbowl]-dragged.html files [fishbowl]-twemojied.html
```
- [ ] Fix timestamps, validate they look correct
- [ ] Fix timestamps
```
go run timestamps.go [fishbowl]-twemojied.html [fishbowl]-timestamped.html
@ -59,7 +59,7 @@
- [ ] Create fishbowl folder under `hmn/src/templates/src/fishbowls/`
- [ ] Copy timestamped html and files, rename html
- [ ] Remove everything from html but chatlog
- [ ] Remove js, css and ggsans from files
- [ ] Remove js, css and whitney from files
- [ ] Add content path to `fishbowl.go`
- [ ] Test locally
- [ ] Submit a pull request

View File

@ -4,13 +4,11 @@ import (
"fmt"
"os"
"regexp"
"strconv"
"time"
)
func main() {
if len(os.Args) != 3 {
fmt.Println("Usage: go run timestamps.go <fishbowl>.html <fishbowl>-timestamped.html")
fmt.Println("Usage: go run timestamps.go [fishbowl].html [fishbowl]-timestamped.html")
os.Exit(1)
}
@ -24,19 +22,17 @@ func main() {
html := string(htmlBytes)
regex := regexp.MustCompile(
`(<span class="?chatlog__timestamp"?><a href=[^>]+>)(\d+)/(\d+)/(\d+)( [^<]+</a></span>)`,
regex, err := regexp.Compile(
"(<span class=\"chatlog__timestamp\">)(\\d+)-([A-Za-z]+)-(\\d+)( [^<]+</span>)",
)
if err != nil {
panic(err)
}
htmlOut := regex.ReplaceAllStringFunc(html, func(s string) string {
match := regex.FindStringSubmatch(s)
month, err := strconv.ParseInt(match[2], 10, 64)
if err != nil {
panic(err)
}
monthStr := time.Month(month).String()
return fmt.Sprintf("%s%s %s, %s%s", match[1], monthStr, match[3], match[4], match[5])
})
htmlOut := regex.ReplaceAllString(
html,
"$1$3 $2, 20$4$5",
)
err = os.WriteFile(htmlOutPath, []byte(htmlOut), 0666)
if err != nil {

2
go.mod
View File

@ -11,7 +11,6 @@ require (
github.com/aws/aws-sdk-go-v2/credentials v1.3.3
github.com/aws/aws-sdk-go-v2/service/s3 v1.13.0
github.com/aws/smithy-go v1.7.0
github.com/emersion/go-ical v0.0.0-20220601085725-0864dccc089f
github.com/frustra/bbcode v0.0.0-20201127003707-6ef347fbe1c8
github.com/go-stack/stack v1.8.0
github.com/google/uuid v1.2.0
@ -57,7 +56,6 @@ require (
github.com/mitchellh/reflectwalk v1.0.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/teambition/rrule-go v1.7.2 // indirect
go.uber.org/atomic v1.10.0 // indirect
golang.org/x/net v0.6.0 // indirect
golang.org/x/sync v0.0.0-20220923202941-7f9b1623fab7 // indirect

4
go.sum
View File

@ -88,8 +88,6 @@ github.com/dlclark/regexp2 v1.1.6/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55k
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/emersion/go-ical v0.0.0-20220601085725-0864dccc089f h1:feGUUxxvOtWVOhTko8Cbmp33a+tU0IMZxMEmnkoAISQ=
github.com/emersion/go-ical v0.0.0-20220601085725-0864dccc089f/go.mod h1:2MKFUgfNMULRxqZkadG1Vh44we3y5gJAtTBlVsx1BKQ=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
@ -277,8 +275,6 @@ github.com/tcolgate/mp3 v0.0.0-20170426193717-e79c5a46d300 h1:XQdibLKagjdevRB6vA
github.com/tcolgate/mp3 v0.0.0-20170426193717-e79c5a46d300/go.mod h1:FNa/dfN95vAYCNFrIKRrlRo+MBLbwmR9Asa5f2ljmBI=
github.com/teacat/noire v1.1.0 h1:5IgJ1H8jodiSSYnrVadV2JjbAnEgCCjYUQxSUuaQ7Sg=
github.com/teacat/noire v1.1.0/go.mod h1:cetGlnqr+9yKJcFgRgYXOWJY66XIrrjUsGBwNlNNtAk=
github.com/teambition/rrule-go v1.7.2 h1:goEajFWYydfCgavn2m/3w5U+1b3PGqPUHx/fFSVfTy0=
github.com/teambition/rrule-go v1.7.2/go.mod h1:mBJ1Ht5uboJ6jexKdNUJg2NcwP8uUMNvStWXlJD3MvU=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/wellington/go-libsass v0.9.2 h1:6Ims04UDdBs6/CGSVK5JC8FNikR5ssrsMMKE/uaO5Q8=
github.com/wellington/go-libsass v0.9.2/go.mod h1:mxgxgam0N0E+NAUMHLcu20Ccfc3mVpDkyrLDayqfiTs=

View File

@ -1,20 +0,0 @@
#!/usr/bin/env python3
import boto3
# You must already have configured your "AWS" (DigitalOcean) credentials via the AWS CLI.
s3 = boto3.resource("s3")
bucket = s3.Bucket("hmn-backup")
for obj in bucket.objects.filter(Prefix="db"):
print(obj.key)
print()
print("Above is a list of all the available database backups.")
print("Enter the name of the one you would like to download (e.g. \"hmn_pg_dump_live_2023-09-24\"):")
filename = input()
s3 = boto3.client("s3")
s3.download_file("hmn-backup", f"db/{filename}", f"local/backups/{filename}")
print(f"Downloaded {filename} to local/backups.")

15
local/download_database.sh Executable file
View File

@ -0,0 +1,15 @@
#!/bin/bash
set -euo pipefail
s3cmd ls s3://hmn-backup/db/
echo ""
echo "Above is a list of all the available database backups."
echo "Enter the name of the one you would like to download (e.g. \"hmn_pg_dump_live_2021-09-01\"):"
read filename
s3cmd get --force s3://hmn-backup/db/$filename ./local/backups/$filename
echo ""
echo "Downloaded $filename to local/backups."

View File

@ -1 +0,0 @@
boto3

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@ -94,7 +94,7 @@
text-align: center;
}
.fishbowl .chatlog__reference-symbol, .fishbowl .chatlog__reply-symbol {
.fishbowl .chatlog__reference-symbol {
height: 10px;
margin: 6px 4px 4px 36px;
border-left: 2px solid #4f545c;
@ -122,7 +122,7 @@
min-width: 0;
}
.fishbowl .chatlog__reference, .fishbowl .chatlog__reply {
.fishbowl .chatlog__reference {
display: flex;
margin-bottom: 0.15rem;
align-items: center;
@ -133,53 +133,53 @@
text-overflow: ellipsis;
}
.fishbowl .chatlog__reference-avatar, .fishbowl .chatlog__reply-avatar {
.fishbowl .chatlog__reference-avatar {
width: 16px;
height: 16px;
margin-right: 0.25rem;
border-radius: 50%;
}
.fishbowl .chatlog__reference-author, .fishbowl .chatlog__reply-author {
.fishbowl .chatlog__reference-author {
margin-right: 0.3rem;
font-weight: 600;
}
.fishbowl .chatlog__reference-content, .fishbowl .chatlog__reply-content {
.fishbowl .chatlog__reference-content {
overflow: hidden;
text-overflow: ellipsis;
}
.fishbowl .chatlog__reference-link, .fishbowl .chatlog__reply-link {
.fishbowl .chatlog__reference-link {
cursor: pointer;
}
.fishbowl .chatlog__reference-link *, .fishbowl .chatlog__reply-link * {
.fishbowl .chatlog__reference-link * {
display: inline;
pointer-events: none;
}
.fishbowl .chatlog__reference-link .hljs, .fishbowl .chatlog__reply-link .hljs {
.fishbowl .chatlog__reference-link .hljs {
display: inline;
}
.fishbowl .chatlog__reference-link .chatlog__markdown-quote, .fishbowl .chatlog__reply-link .chatlog__markdown-quote {
.fishbowl .chatlog__reference-link .chatlog__markdown-quote {
display: inline
}
.fishbowl .chatlog__reference-link .chatlog__markdown-pre, .fishbowl .chatlog__reply-link .chatlog__markdown-pre {
.fishbowl .chatlog__reference-link .chatlog__markdown-pre {
display: inline
}
.fishbowl .chatlog__reference-link:hover, .fishbowl .chatlog__reply-link:hover {
.fishbowl .chatlog__reference-link:hover {
color: #ffffff;
}
.fishbowl .chatlog__reference-link:hover *:not(.chatlog__markdown-spoiler), .fishbowl .chatlog__reply-link:hover *:not(.chatlog__markdown-spoiler) {
.fishbowl .chatlog__reference-link:hover *:not(.chatlog__markdown-spoiler) {
color: inherit;
}
.fishbowl .chatlog__reference-edited-timestamp, .fishbowl .chatlog__reply-edited-timestamp {
.fishbowl .chatlog__reference-edited-timestamp {
margin-left: 0.25rem;
color: #a3a6aa;
font-size: 0.75rem;

View File

@ -95,7 +95,7 @@
text-align: center;
}
.fishbowl .chatlog__reference-symbol, .fishbowl .chatlog__reply-symbol {
.fishbowl .chatlog__reference-symbol {
height: 10px;
margin: 6px 4px 4px 36px;
border-left: 2px solid #c7ccd1;
@ -123,7 +123,7 @@
min-width: 0;
}
.fishbowl .chatlog__reference, .fishbowl .chatlog__reply {
.fishbowl .chatlog__reference {
display: flex;
margin-bottom: 0.15rem;
align-items: center;
@ -134,53 +134,53 @@
text-overflow: ellipsis;
}
.fishbowl .chatlog__reference-avatar, .fishbowl .chatlog__reply-avatar {
.fishbowl .chatlog__reference-avatar {
width: 16px;
height: 16px;
margin-right: 0.25rem;
border-radius: 50%;
}
.fishbowl .chatlog__reference-author, .fishbowl .chatlog__reply-author {
.fishbowl .chatlog__reference-author {
margin-right: 0.3rem;
font-weight: 600;
}
.fishbowl .chatlog__reference-content, .fishbowl .chatlog__reply-content {
.fishbowl .chatlog__reference-content {
overflow: hidden;
text-overflow: ellipsis;
}
.fishbowl .chatlog__reference-link, .fishbowl .chatlog__reply-link {
.fishbowl .chatlog__reference-link {
cursor: pointer;
}
.fishbowl .chatlog__reference-link *, .fishbowl .chatlog__reply-link * {
.fishbowl .chatlog__reference-link * {
display: inline;
pointer-events: none;
}
.fishbowl .chatlog__reference-link .hljs, .fishbowl .chatlog__reply-link .hljs {
.fishbowl .chatlog__reference-link .hljs {
display: inline;
}
.fishbowl .chatlog__reference-link .chatlog__markdown-quote, .fishbowl .chatlog__reply-link .chatlog__markdown-quote {
.fishbowl .chatlog__reference-link .chatlog__markdown-quote {
display: inline
}
.fishbowl .chatlog__reference-link .chatlog__markdown-pre, .fishbowl .chatlog__reply-link .chatlog__markdown-pre {
.fishbowl .chatlog__reference-link .chatlog__markdown-pre {
display: inline
}
.fishbowl .chatlog__reference-link:hover, .fishbowl .chatlog__reply-link:hover {
.fishbowl .chatlog__reference-link:hover {
color: #2f3136;
}
.fishbowl .chatlog__reference-link:hover *:not(.chatlog__markdown-spoiler), .fishbowl .chatlog__reply-link:hover *:not(.chatlog__markdown-spoiler) {
.fishbowl .chatlog__reference-link:hover *:not(.chatlog__markdown-spoiler) {
color: inherit;
}
.fishbowl .chatlog__reference-edited-timestamp, .fishbowl .chatlog__reply-edited-timestamp {
.fishbowl .chatlog__reference-edited-timestamp {
margin-left: 0.25rem;
color: #5e6772;
font-size: 0.75rem;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 228 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 267 KiB

View File

@ -1 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 236 253" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="books" x="0" y="0" width="235.74" height="252.97" style="fill:none;"/><path d="M77.61,252.704l0,-230.569l80.52,-0l-0,230.569l-80.52,0Zm59.686,-188.853l0,-20.883l-38.853,-0l0,20.883l38.853,0Zm0,128.926l0,-108.092l-38.853,-0l0,108.092l38.853,-0Zm-38.853,20.833l0,18.261l38.853,-0l0,-18.261l-38.853,0Zm-98.032,39.094l-0,-252.438l70.429,-0l-0,252.438l-70.429,0Zm49.596,-206.372l-0,-25.233l-28.763,-0l0,25.233l28.763,0Zm-0,142.369l-0,-121.536l-28.763,0l0,121.536l28.763,-0Zm-28.763,20.833l0,22.337c0,-0 28.763,-0 28.763,-0l-0,-22.337l-28.763,-0Zm143.656,43.17l-0,-252.438l70.429,-0l-0,252.438l-70.429,0Zm49.596,-206.372l-0,-25.233l-28.763,-0l0,25.233l28.763,0Zm-0,142.369l-0,-121.536l-28.763,0l0,121.536l28.763,-0Zm-28.763,20.833l0,22.337l28.763,-0l-0,-22.337l-28.763,-0Z"/></svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -1 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 336 233" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="lightbulb" x="0" y="0" width="335.159" height="232.656" style="fill:none;"/><path d="M197.613,202.015c0,16.576 -13.457,30.034 -30.034,30.034c-16.576,-0 -30.034,-13.458 -30.034,-30.034l60.068,-0Zm0.06,-9.97l-60.206,-0c-3.155,-16.04 -5.152,-23.793 -32.39,-57.373c-10.513,-12.96 -16.178,-29.812 -16.178,-47.773c0,-43.425 35.256,-78.68 78.68,-78.68c43.425,-0 78.68,34.8 78.68,78.224c0,17.961 -5.665,34.814 -16.177,47.774c-27.238,33.58 -29.254,41.788 -32.409,57.828Zm-16.343,-20.834c3.88,-11.276 11.569,-24.225 32.572,-50.118c7.611,-9.383 11.524,-21.647 11.524,-34.65c-0,-31.893 -25.954,-57.391 -57.847,-57.391c-31.926,0 -57.846,25.92 -57.846,57.847c-0,13.003 3.913,25.266 11.524,34.649c20.946,25.823 28.639,38.556 32.521,49.663l27.552,0Zm-160.921,-151.684c-4.694,-3.321 -5.808,-9.827 -2.488,-14.52c3.321,-4.693 9.827,-5.808 14.52,-2.488l31.239,22.101c4.694,3.321 5.808,9.827 2.488,14.52c-3.32,4.693 -9.827,5.808 -14.52,2.488l-31.239,-22.101Zm12.032,153.97c-4.693,3.32 -11.199,2.205 -14.52,-2.488c-3.32,-4.693 -2.206,-11.199 2.488,-14.52l31.239,-22.101c4.693,-3.32 11.2,-2.205 14.52,2.488c3.32,4.693 2.206,11.199 -2.488,14.52l-31.239,22.101Zm-21.856,-74.77c-5.749,-0 -10.416,-4.668 -10.416,-10.417c-0,-5.749 4.667,-10.417 10.416,-10.417l38.267,0c5.749,0 10.417,4.668 10.417,10.417c-0,5.749 -4.668,10.417 -10.417,10.417l-38.267,-0Zm292.133,-95.906c4.693,-3.32 11.199,-2.205 14.519,2.488c3.321,4.693 2.206,11.199 -2.487,14.52l-31.239,22.101c-4.694,3.32 -11.2,2.206 -14.52,-2.488c-3.321,-4.693 -2.206,-11.199 2.487,-14.52l31.24,-22.101Zm12.032,153.97c4.693,3.321 5.808,9.827 2.487,14.52c-3.32,4.694 -9.826,5.808 -14.519,2.488l-31.24,-22.101c-4.693,-3.321 -5.808,-9.827 -2.487,-14.52c3.32,-4.693 9.826,-5.808 14.52,-2.488l31.239,22.101Zm9.823,-78.595c5.75,-0 10.417,4.667 10.417,10.416c0,5.749 -4.667,10.417 -10.417,10.417l-38.266,-0c-5.75,-0 -10.417,-4.668 -10.417,-10.417c-0,-5.749 4.667,-10.416 10.417,-10.416l38.266,-0Z"/></svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@ -1 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 301 229" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="presentation" x="-0" y="0" width="300.716" height="228.578" style="fill:none;"/><path d="M124.979,14.95l175.159,0l0,152.429l-137.896,0c-1.49,-7.262 -3.898,-14.19 -7.097,-20.659l124.334,-0l-0,-111.11l-143.514,-0c-2.302,-7.632 -6.074,-14.628 -10.986,-20.66Zm-119.77,196.191c-2.997,-8.252 -4.631,-17.155 -4.631,-26.437c0,-42.797 34.745,-77.542 77.541,-77.542c42.796,0 77.541,34.745 77.541,77.542c0,9.282 -1.634,18.185 -4.631,26.437c-22.091,10.548 -46.816,16.455 -72.91,16.455c-26.094,0 -50.819,-5.907 -72.91,-16.455Zm15.522,-13.612c17.693,7.296 37.075,11.317 57.388,11.317c20.314,0 39.695,-4.021 57.389,-11.317c0.919,-4.129 1.402,-8.421 1.402,-12.825c0,-32.448 -26.343,-58.792 -58.791,-58.792c-32.448,0 -58.791,26.344 -58.791,58.792c0,4.404 0.484,8.696 1.403,12.825Zm57.388,-196.547c28.741,-0 52.075,23.334 52.075,52.074c-0,28.741 -23.334,52.075 -52.075,52.075c-28.74,-0 -52.074,-23.334 -52.074,-52.075c-0,-28.74 23.334,-52.074 52.074,-52.074Zm0,18.75c-18.392,-0 -33.324,14.932 -33.324,33.324c-0,18.392 14.932,33.325 33.324,33.325c18.392,-0 33.325,-14.933 33.325,-33.325c-0,-18.392 -14.933,-33.324 -33.325,-33.324Z"/></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -7346,6 +7346,12 @@ article code {
margin-left: auto;
margin-right: auto; }
.flex-shrink-0, .edit-form .edit-form-row > :first-child {
flex-shrink: 0; }
.flex-grow-1, .edit-form .edit-form-row > :nth-child(2) {
flex-grow: 1; }
.flex-fair {
flex-basis: 1px;
flex-grow: 1;
@ -7547,15 +7553,6 @@ article code {
.g5 {
gap: 4rem; }
.grid {
display: grid; }
.grid-1 {
grid-template-columns: 1fr; }
.grid-2 {
grid-template-columns: 1fr 1fr; }
.aspect-ratio--2x1 {
padding-bottom: 50%; }
@ -7585,25 +7582,9 @@ article code {
column-gap: 2rem; }
.cg5-ns {
column-gap: 4rem; }
.grid-1-ns {
grid-template-columns: 1fr; }
.grid-2-ns {
grid-template-columns: 1fr 1fr; }
.bg--dim-ns {
background-color: #f0f0f0;
background-color: var(--dim-background); }
.g0-ns {
gap: 0; }
.g1-ns {
gap: 0.25rem; }
.g2-ns {
gap: 0.5rem; }
.g3-ns {
gap: 1rem; }
.g4-ns {
gap: 2rem; }
.g5-ns {
gap: 4rem; } }
background-color: var(--dim-background); } }
@media screen and (min-width: 35em) and (max-width: 60em) {
.bi-avoid-m {
@ -7626,25 +7607,9 @@ article code {
column-gap: 2rem; }
.cg5-m {
column-gap: 4rem; }
.grid-1-m {
grid-template-columns: 1fr; }
.grid-2-m {
grid-template-columns: 1fr 1fr; }
.bg--dim-m {
background-color: #f0f0f0;
background-color: var(--dim-background); }
.g0-m {
gap: 0; }
.g1-m {
gap: 0.25rem; }
.g2-m {
gap: 0.5rem; }
.g3-m {
gap: 1rem; }
.g4-m {
gap: 2rem; }
.g5-m {
gap: 4rem; } }
background-color: var(--dim-background); } }
@media screen and (min-width: 60em) {
.bi-avoid-l {
@ -7667,25 +7632,9 @@ article code {
column-gap: 2rem; }
.cg5-l {
column-gap: 4rem; }
.grid-1-l {
grid-template-columns: 1fr; }
.grid-2-l {
grid-template-columns: 1fr 1fr; }
.bg--dim-l {
background-color: #f0f0f0;
background-color: var(--dim-background); }
.g0-l {
gap: 0; }
.g1-l {
gap: 0.25rem; }
.g2-l {
gap: 0.5rem; }
.g3-l {
gap: 1rem; }
.g4-l {
gap: 2rem; }
.g5-l {
gap: 4rem; } }
background-color: var(--dim-background); } }
.not-first:first-child {
display: none; }

View File

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -1,36 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 475 283" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;">
<g id="Handlebars" transform="matrix(1,0,0,1,-100,-167)">
<path d="M404,196C407.778,166.333 384.333,169 364,184" style="fill:none;stroke:white;stroke-width:9px;"/>
</g>
<g id="Seat">
</g>
<path d="M120,42L160,42C177.006,42.052 186.77,48.289 191,58" style="fill:none;stroke:white;stroke-width:9px;"/>
<g id="Frame" transform="matrix(1,0,0,1,-100,-167)">
<path d="M314,390L445,274" style="fill:none;stroke:white;stroke-width:9px;"/>
<path d="M500,375L404,196" style="fill:none;stroke:white;stroke-width:9px;stroke-linecap:butt;"/>
<path d="M266,259L437,259" style="fill:none;stroke:white;stroke-width:9px;"/>
<path d="M314,390L248,209" style="fill:none;stroke:white;stroke-width:9px;stroke-linecap:butt;"/>
<g transform="matrix(0.815396,-0.0212494,-0.0212494,0.997554,66.2531,7.62625)">
<path d="M143.044,371.322L314,390" style="fill:none;stroke:white;stroke-width:10.11px;"/>
</g>
<path d="M175,375L266,259" style="fill:none;stroke:white;stroke-width:9px;"/>
</g>
<g id="Wheel" transform="matrix(1,0,0,1,-100,-167)">
<g transform="matrix(0.980392,0,0,0.980392,-46.0784,31.3725)">
<path d="M302,293.019C302,282.522 293.478,274 282.981,274L168.019,274C157.522,274 149,282.522 149,293.019L149,407.981C149,418.478 157.522,427 168.019,427L282.981,427C293.478,427 302,418.478 302,407.981L302,293.019ZM292.82,293.019L292.82,407.981C292.82,413.411 288.411,417.82 282.981,417.82C282.981,417.82 168.019,417.82 168.019,417.82C162.589,417.82 158.18,413.411 158.18,407.981L158.18,293.019C158.18,287.589 162.589,283.18 168.019,283.18L282.981,283.18C288.411,283.18 292.82,287.589 292.82,293.019Z" style="fill:white;"/>
</g>
<g transform="matrix(1,0,0,1,-50,26)">
<path d="M237,343C237,339.689 234.311,337 231,337L219,337C215.689,337 213,339.689 213,343L213,355C213,358.311 215.689,361 219,361L231,361C234.311,361 237,358.311 237,355L237,343Z" style="fill:white;"/>
</g>
</g>
<g id="Wheel1" serif:id="Wheel" transform="matrix(1,0,0,1,225,-167)">
<g transform="matrix(0.980392,0,0,0.980392,-46.0784,31.3725)">
<path d="M302,293.019C302,282.522 293.478,274 282.981,274L168.019,274C157.522,274 149,282.522 149,293.019L149,407.981C149,418.478 157.522,427 168.019,427L282.981,427C293.478,427 302,418.478 302,407.981L302,293.019ZM292.82,293.019L292.82,407.981C292.82,413.411 288.411,417.82 282.981,417.82C282.981,417.82 168.019,417.82 168.019,417.82C162.589,417.82 158.18,413.411 158.18,407.981L158.18,293.019C158.18,287.589 162.589,283.18 168.019,283.18L282.981,283.18C288.411,283.18 292.82,287.589 292.82,293.019Z" style="fill:white;"/>
</g>
<g transform="matrix(1,0,0,1,-50,26)">
<path d="M237,343C237,339.689 234.311,337 231,337L219,337C215.689,337 213,339.689 213,343L213,355C213,358.311 215.689,361 219,361L231,361C234.311,361 237,358.311 237,355L237,343Z" style="fill:white;"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 212 KiB

View File

@ -5,28 +5,23 @@ import (
"context"
"errors"
"fmt"
"io"
"io/ioutil"
"net"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"time"
"git.handmade.network/hmn/hmn/src/assets"
"git.handmade.network/hmn/hmn/src/auth"
"git.handmade.network/hmn/hmn/src/config"
"git.handmade.network/hmn/hmn/src/db"
"git.handmade.network/hmn/hmn/src/email"
"git.handmade.network/hmn/hmn/src/hmnurl"
"git.handmade.network/hmn/hmn/src/logging"
"git.handmade.network/hmn/hmn/src/models"
"git.handmade.network/hmn/hmn/src/oops"
"git.handmade.network/hmn/hmn/src/perf"
"git.handmade.network/hmn/hmn/src/templates"
"git.handmade.network/hmn/hmn/src/utils"
"git.handmade.network/hmn/hmn/src/website"
"github.com/google/uuid"
"github.com/jackc/pgx/v5"
@ -588,34 +583,5 @@ func init() {
}
adminCommand.AddCommand(extractImage)
uploadAsset := &cobra.Command{
Use: "uploadasset <file> <content type>",
Short: "Upload a file to our asset CDN",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 2 {
cmd.Usage()
os.Exit(1)
}
fname := args[0]
contentType := args[1]
ctx := context.Background()
conn := db.NewConn()
defer conn.Close(ctx)
assetContents := utils.Must1(io.ReadAll(utils.Must1(os.Open(fname))))
assetFilename := filepath.Base(fname)
fmt.Printf("Uploading %s with content type %s...\n", assetFilename, contentType)
asset := utils.Must1(assets.Create(ctx, conn, assets.CreateInput{
Content: assetContents,
Filename: assetFilename,
ContentType: contentType,
}))
fmt.Printf("Uploaded and accessible at %s\n", hmnurl.BuildS3Asset(asset.S3Key))
},
}
adminCommand.AddCommand(uploadAsset)
addProjectCommands(adminCommand)
}

View File

@ -1,383 +0,0 @@
package calendar
import (
"bytes"
"context"
"crypto/sha1"
"io"
"net/http"
"sort"
"strings"
"sync"
"time"
"git.handmade.network/hmn/hmn/src/config"
"git.handmade.network/hmn/hmn/src/jobs"
"git.handmade.network/hmn/hmn/src/logging"
"git.handmade.network/hmn/hmn/src/oops"
"git.handmade.network/hmn/hmn/src/utils"
"github.com/emersion/go-ical"
)
type RawCalendarData struct {
Name string
Url string
Data []byte
Hash [sha1.Size]byte
}
type CalendarEvent struct {
ID string
Name string
Desc string
StartTime time.Time
EndTime time.Time
Duration time.Duration
CalName string
}
var unifiedCalendar *ical.Calendar
var rawCalendarData = make([]*RawCalendarData, 0)
var cachedICals = make(map[string][]byte)
var httpClient = http.Client{}
// NOTE(asaf): Passing an empty array for selectedCals returns all cals
func GetICal(selectedCals []string) ([]byte, error) {
if unifiedCalendar == nil {
return nil, oops.New(nil, "No calendar")
}
sort.Strings(selectedCals)
cacheKey := strings.Join(selectedCals, "##")
cachedICal, ok := cachedICals[cacheKey]
if ok {
return cachedICal, nil
}
var cal *ical.Calendar
if len(selectedCals) == 0 {
cal = unifiedCalendar
} else {
cal = newHMNCalendar()
for _, child := range unifiedCalendar.Children {
include := true
if child.Name == ical.CompEvent {
calName, _ := child.Props.Text(ical.PropComment)
if calName != "" {
found := false
for _, s := range selectedCals {
if calName == s {
found = true
}
}
if !found {
include = false
}
}
}
if include {
cal.Children = append(cal.Children, child)
}
}
}
var calBytes []byte
if len(cal.Children) > 0 {
var buffer bytes.Buffer
err := ical.NewEncoder(&buffer).Encode(cal)
if err != nil {
return nil, oops.New(err, "Failed to encode calendar to iCal")
}
calBytes = buffer.Bytes()
} else {
calBytes = emptyCalendarString()
}
cachedICals[cacheKey] = calBytes
return calBytes, nil
}
func GetFutureEvents() []CalendarEvent {
if unifiedCalendar == nil {
return nil
}
futureEvents := make([]CalendarEvent, 0)
eventObjects := unifiedCalendar.Events()
now := time.Now()
lastTime := now.Add(time.Hour * 24 * 365)
for _, ev := range eventObjects {
summary, err := ev.Props.Text(ical.PropSummary)
if err != nil {
logging.Error().Err(err).Msg("Failed to get summary for calendar event")
continue
}
startTime, err := ev.DateTimeStart(nil)
if err != nil {
logging.Error().Err(err).Str("Event name", summary).Msg("Failed to get start time for calendar event")
continue
}
var evTimes []time.Time
set, err := ev.RecurrenceSet(nil)
if err != nil {
logging.Error().Err(err).Str("Event name", summary).Msg("Failed to get recurrence set for calendar event")
continue
}
if set != nil {
evTimes = set.Between(now, lastTime, true)
} else if startTime.After(now) {
evTimes = []time.Time{startTime}
}
if len(evTimes) == 0 {
continue
}
desc, err := ev.Props.Text(ical.PropDescription)
if err != nil {
logging.Error().Err(err).Str("Event name", summary).Msg("Failed to get description for calendar event")
continue
}
calName, _ := ev.Props.Text(ical.PropComment)
uid, err := ev.Props.Text(ical.PropUID)
if err != nil {
logging.Error().Err(err).Str("Event name", summary).Msg("Failed to get uid for calendar event")
continue
}
endTime, err := ev.DateTimeStart(nil)
if err != nil {
logging.Error().Err(err).Str("Event name", summary).Msg("Failed to get end time for calendar event")
continue
}
evDuration := endTime.Sub(startTime)
for _, t := range evTimes {
futureEvents = append(futureEvents, CalendarEvent{
ID: uid,
Name: summary,
Desc: desc,
StartTime: t,
EndTime: t.Add(evDuration),
Duration: evDuration,
CalName: calName,
})
}
}
sort.Slice(futureEvents, func(i, j int) bool {
return futureEvents[i].StartTime.Before(futureEvents[j].StartTime)
})
return futureEvents
}
func MonitorCalendars(ctx context.Context) jobs.Job {
log := logging.ExtractLogger(ctx).With().Str("calendar goroutine", "calendar monitor").Logger()
if len(config.Config.Calendars) == 0 {
log.Info().Msg("No calendars specified in config")
return jobs.Noop()
}
ctx = logging.AttachLoggerToContext(&log, ctx)
job := jobs.New()
go func() {
defer func() {
log.Info().Msg("Shutting down calendar monitor")
job.Done()
}()
log.Info().Msg("Running calendar monitor")
monitorTimer := time.NewTimer(time.Second)
for {
select {
case <-monitorTimer.C:
err := func() (err error) {
defer utils.RecoverPanicAsError(&err)
ReloadCalendars(ctx)
return nil
}()
if err != nil {
logging.Error().Err(err).Msg("Panicked in MonitorCalendars")
}
monitorTimer.Reset(time.Minute)
case <-ctx.Done():
return
}
}
}()
return job
}
func ReloadCalendars(ctx context.Context) {
log := logging.ExtractLogger(ctx)
// Download calendars
calChan := make(chan RawCalendarData, len(config.Config.Calendars))
var wg sync.WaitGroup
wg.Add(len(config.Config.Calendars))
for _, c := range config.Config.Calendars {
go func(cal config.CalendarSource) {
defer func() {
wg.Done()
logging.LogPanics(log)
}()
calUrl := cal.Url
req, err := http.NewRequestWithContext(ctx, "GET", calUrl, nil)
if err != nil {
log.Error().Err(err).Msg("Failed to create request for calendar fetch")
return
}
res, err := httpClient.Do(req)
if err != nil {
log.Error().Err(err).Str("Url", calUrl).Msg("Failed to fetch calendar")
return
}
if res.StatusCode > 299 || !strings.HasPrefix(res.Header.Get("Content-Type"), "text/calendar") {
log.Error().Str("Url", calUrl).Str("Status", res.Status).Msg("Failed to fetch calendar")
io.ReadAll(res.Body)
res.Body.Close()
return
}
data, err := io.ReadAll(res.Body)
res.Body.Close()
if err != nil {
log.Error().Err(err).Str("Url", calUrl).Msg("Failed to fetch calendar")
return
}
calChan <- RawCalendarData{Name: cal.Name, Url: calUrl, Data: data}
}(c)
}
wg.Wait()
newRawCalendarData := make([]*RawCalendarData, 0, len(config.Config.Calendars))
Collect:
for {
select {
case d := <-calChan:
newRawCalendarData = append(newRawCalendarData, &d)
default:
break Collect
}
}
// Diff calendars
same := true
for _, n := range newRawCalendarData {
n.Hash = sha1.Sum(n.Data)
}
sort.Slice(newRawCalendarData, func(i, j int) bool {
return newRawCalendarData[i].Name < newRawCalendarData[j].Name
})
if len(newRawCalendarData) != len(rawCalendarData) {
same = false
} else {
for i := range newRawCalendarData {
newData := newRawCalendarData[i]
oldData := rawCalendarData[i]
if newData.Name != oldData.Name {
same = false
break
}
if newData.Hash != oldData.Hash {
same = false
break
}
}
}
if same {
return
}
// Unify calendars and clear cache
rawCalendarData = newRawCalendarData
cachedICals = make(map[string][]byte)
unified := newHMNCalendar()
var timezones []string
for _, calData := range rawCalendarData {
decoder := ical.NewDecoder(bytes.NewReader(calData.Data))
calNameProp := ical.NewProp(ical.PropComment)
calNameProp.SetText(calData.Name)
for {
cal, err := decoder.Decode()
if err == io.EOF {
break
} else if err != nil {
log.Error().Err(err).Str("Url", calData.Url).Msg("Failed to parse calendar")
break
}
for _, child := range cal.Children {
if child.Name == ical.CompTimezone {
tzid, err := child.Props.Text(ical.PropTimezoneID)
if err != nil {
found := false
for _, s := range timezones {
if s == tzid {
found = true
}
}
if found {
continue
} else {
timezones = append(timezones, tzid)
}
} else {
continue
}
}
if child.Name == ical.CompEvent {
child.Props.Set(calNameProp)
}
unified.Children = append(unified.Children, child)
}
}
}
unifiedCalendar = unified
}
func newHMNCalendar() *ical.Calendar {
cal := ical.NewCalendar()
prodID := ical.NewProp(ical.PropProductID)
prodID.SetText("Handmade Network")
cal.Props.Set(prodID)
version := ical.NewProp(ical.PropVersion)
version.SetText("1.0")
cal.Props.Set(version)
name := ical.NewProp("X-WR-CALNAME")
name.SetText("Handmade Network")
cal.Props.Set(name)
return cal
}
// NOTE(asaf): The ical library we're using doesn't like encoding empty calendars, so we have to do this manually.
func emptyCalendarString() []byte {
empty := `BEGIN:VCALENDAR
VERSION:1.0
PRODID:Handmade Network
X-WR-CALNAME:Handmade Network
END:VCALENDAR
`
return []byte(empty)
}

View File

@ -78,8 +78,6 @@ var Config = HMNConfig{
BaseUrl: "https://api.twitch.tv/helix",
BaseIDUrl: "https://id.twitch.tv/oauth2",
},
Calendars: []CalendarSource{
},
EpisodeGuide: EpisodeGuide{
CineraOutputPath: "./annotations/",
Projects: map[string]string{"hero": "code", "riscy": "riscy", "bitwise": "bitwise"},

View File

@ -28,11 +28,9 @@ type HMNConfig struct {
DigitalOcean DigitalOceanConfig
Discord DiscordConfig
Twitch TwitchConfig
Matrix MatrixConfig
EpisodeGuide EpisodeGuide
DevConfig DevConfig
PreviewGeneration PreviewGenerationConfig
Calendars []CalendarSource
}
type PostgresConfig struct {
@ -95,18 +93,6 @@ type TwitchConfig struct {
BaseIDUrl string
}
type MatrixConfig struct {
Username string
Password string
BaseUrl string
AnnouncementsRoomID string
}
type CalendarSource struct {
Name string
Url string
}
type EpisodeGuide struct {
CineraOutputPath string
Projects map[string]string // NOTE(asaf): Maps from slugs to default episode guide topic

View File

@ -23,34 +23,6 @@ import (
"github.com/jpillora/backoff"
)
type BotEvent struct {
Timestamp time.Time
Name string
Extra string
}
var botEvents = make([]BotEvent, 0, 1000)
var botEventsMutex = sync.Mutex{}
func RecordBotEvent(name, extra string) {
botEventsMutex.Lock()
defer botEventsMutex.Unlock()
if len(botEvents) > 1000 {
botEvents = botEvents[len(botEvents)-500:]
}
botEvents = append(botEvents, BotEvent{
Timestamp: time.Now(),
Name: name,
Extra: extra,
})
}
func GetBotEvents() []BotEvent {
botEventsMutex.Lock()
defer botEventsMutex.Unlock()
return botEvents[:]
}
func RunDiscordBot(ctx context.Context, dbConn *pgxpool.Pool) jobs.Job {
log := logging.ExtractLogger(ctx).With().Str("module", "discord").Logger()
ctx = logging.AttachLoggerToContext(&log, ctx)
@ -84,11 +56,6 @@ func RunDiscordBot(ctx context.Context, dbConn *pgxpool.Pool) jobs.Job {
log.Info().Msg("Connecting to the Discord gateway")
bot := newBotInstance(dbConn)
err := bot.Run(ctx)
disconnectMessage := ""
if err != nil {
disconnectMessage = err.Error()
}
RecordBotEvent("Disconnected", disconnectMessage)
if err != nil {
dur := boff.Duration()
log.Error().
@ -134,8 +101,6 @@ type botInstance struct {
conn *websocket.Conn
dbConn *pgxpool.Pool
resuming bool
heartbeatIntervalMs int
forceHeartbeat chan struct{}
@ -228,7 +193,6 @@ func (bot *botInstance) Run(ctx context.Context) (err error) {
logging.ExtractLogger(ctx).Info().Msg("Discord asked us to reconnect to the gateway")
return nil
case OpcodeInvalidSession:
RecordBotEvent("Failed to resume - invalid session", "")
// We tried to resume but the session was invalid.
// Delete the session and reconnect from scratch again.
_, err := bot.dbConn.Exec(ctx, `DELETE FROM discord_session`)
@ -300,11 +264,8 @@ func (bot *botInstance) connect(ctx context.Context) error {
}
}
RecordBotEvent("Connected", "")
if shouldResume {
RecordBotEvent("Resuming with session ID", session.ID)
// Reconnect to the previous session
bot.resuming = true
err := bot.sendGatewayMessage(ctx, GatewayMessage{
Opcode: OpcodeResume,
Data: Resume{
@ -579,20 +540,11 @@ func (bot *botInstance) processEventMsg(ctx context.Context, msg *GatewayMessage
panic(fmt.Sprintf("processEventMsg must only be used on Dispatch messages (opcode %d). Validate this before you call this function.", OpcodeDispatch))
}
if bot.resuming {
name := ""
if msg.EventName != nil {
name = *msg.EventName
}
RecordBotEvent("Got event while resuming", name)
}
switch *msg.EventName {
case "RESUMED":
// Nothing to do, but at least we can log something
logging.ExtractLogger(ctx).Info().Msg("Finished resuming gateway session")
bot.resuming = false
RecordBotEvent("Done resuming", "")
bot.createApplicationCommands(ctx)
case "MESSAGE_CREATE":
newMessage := *MessageFromMap(msg.Data, "")

View File

@ -185,7 +185,6 @@ func Scrape(ctx context.Context, dbConn *pgxpool.Pool, channelID string, earlies
return true
}
msg.Backfilled = true
err := HandleIncomingMessage(ctx, dbConn, &msg, createSnippets)
if err != nil {

View File

@ -1,17 +1,13 @@
package discord
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"math/rand"
"net/http"
"net/url"
"regexp"
"strconv"
"strings"
"time"
@ -23,15 +19,9 @@ import (
"git.handmade.network/hmn/hmn/src/models"
"git.handmade.network/hmn/hmn/src/oops"
"git.handmade.network/hmn/hmn/src/parsing"
"git.handmade.network/hmn/hmn/src/utils"
"github.com/google/uuid"
)
var autostoreChannels = []string{
config.Config.Discord.ShowcaseChannelID,
// TODO(asaf): Add jam channel
}
func HandleIncomingMessage(ctx context.Context, dbConn db.ConnOrTx, msg *Message, createSnippets bool) error {
deleted := false
var err error
@ -46,10 +36,6 @@ func HandleIncomingMessage(ctx context.Context, dbConn db.ConnOrTx, msg *Message
deleted, err = CleanUpShowcase(ctx, dbConn, msg)
}
if !deleted && err == nil {
err = ShareToMatrix(ctx, msg)
}
if !deleted && err == nil {
err = MaybeInternMessage(ctx, dbConn, msg)
}
@ -58,11 +44,6 @@ func HandleIncomingMessage(ctx context.Context, dbConn db.ConnOrTx, msg *Message
err = HandleInternedMessage(ctx, dbConn, msg, deleted, createSnippets)
}
// when we needed her most...she vanished
// if !deleted && err == nil {
// err = FreyaMode(ctx, dbConn, msg)
// }
return err
}
@ -75,7 +56,17 @@ func CleanUpShowcase(ctx context.Context, dbConn db.ConnOrTx, msg *Message) (boo
return deleted, nil
}
if !messageShouldBeStored(msg) {
hasGoodContent := true
if msg.OriginalHasFields("content") && !messageHasLinks(msg.Content) {
hasGoodContent = false
}
hasGoodAttachments := true
if msg.OriginalHasFields("attachments") && len(msg.Attachments) == 0 {
hasGoodAttachments = false
}
if !hasGoodContent && !hasGoodAttachments {
err := DeleteMessage(ctx, msg.ChannelID, msg.ID)
if err != nil {
return deleted, oops.New(err, "failed to delete message")
@ -91,7 +82,7 @@ func CleanUpShowcase(ctx context.Context, dbConn db.ConnOrTx, msg *Message) (boo
err = SendMessages(ctx, dbConn, MessageToSend{
ChannelID: channel.ID,
Req: CreateMessageRequest{
Content: "Posts in #project-showcase are required to have either an image/video or a link, or start with `!til`. Discuss showcase content in #projects.",
Content: "Posts in #project-showcase are required to have either an image/video or a link. Discuss showcase content in #projects.",
},
})
if err != nil {
@ -146,163 +137,8 @@ func CleanUpLibrary(ctx context.Context, dbConn db.ConnOrTx, msg *Message) (bool
return deleted, nil
}
func FreyaMode(ctx context.Context, dbConn db.ConnOrTx, msg *Message) error {
if msg.Author.IsBot {
return nil
}
if msg.ChannelID == config.Config.Discord.ShowcaseChannelID || msg.ChannelID == config.Config.Discord.LibraryChannelID {
return nil
}
twitteryUrls := []string{
"https://twitter.com",
"https://x.com",
"https://vxtwitter.com",
"https://fxtwitter.com",
}
isTwittery := false
for _, url := range twitteryUrls {
if strings.Contains(msg.Content, url) {
isTwittery = true
}
}
if !isTwittery {
return nil
}
// FREYA MODE ENGAGED
approvedTweets := []string{
"https://vxtwitter.com/FreyaHolmer/status/1757836988495847568",
"https://vxtwitter.com/FreyaHolmer/status/1752441092501361103",
"https://vxtwitter.com/FreyaHolmer/status/1753813557966217268",
"https://vxtwitter.com/FreyaHolmer/status/1746228932188295579",
"https://vxtwitter.com/FreyaHolmer/status/1732687685850894799",
"https://vxtwitter.com/FreyaHolmer/status/1761487879178736048",
"https://vxtwitter.com/FreyaHolmer/status/1733820461492863442",
"https://vxtwitter.com/FreyaHolmer/status/1732845451701871101",
"https://vxtwitter.com/FreyaHolmer/status/1765680355657359585",
"https://vxtwitter.com/FreyaHolmer/status/1784678195997852129",
"https://vxtwitter.com/FreyaHolmer/status/1741468609044508831",
"https://vxtwitter.com/FreyaHolmer/status/1759306434053870012",
"https://vxtwitter.com/FreyaHolmer/status/1754929898492162178",
"https://vxtwitter.com/FreyaHolmer/status/1782498313511534822",
"https://vxtwitter.com/FreyaHolmer/status/1623737764041695232",
"https://vxtwitter.com/FreyaHolmer/status/1718979996125925494",
"https://vxtwitter.com/FreyaHolmer/status/1675945798448607248",
"https://vxtwitter.com/FreyaHolmer/status/1662229911375953922",
"https://vxtwitter.com/FreyaHolmer/status/1652235944752185345",
"https://vxtwitter.com/FreyaHolmer/status/1386408507218427905",
"https://vxtwitter.com/FreyaHolmer/status/1436696408506212353",
"https://vxtwitter.com/FreyaHolmer/status/1444755552777670657",
"https://vxtwitter.com/FreyaHolmer/status/1232826293902888960",
}
tweet := approvedTweets[rand.Intn(len(approvedTweets))]
err := SendMessages(ctx, dbConn, MessageToSend{
ChannelID: msg.ChannelID,
Req: CreateMessageRequest{
Content: fmt.Sprintf("No. Only Freya is allowed to tweet. %s", tweet),
},
})
if err != nil {
return oops.New(err, "failed to send Freya tweet")
}
return nil
}
func ShareToMatrix(ctx context.Context, msg *Message) error {
if msg.Flags&MessageFlagCrossposted == 0 {
return nil
}
if config.Config.Matrix.Username == "" {
logging.ExtractLogger(ctx).Warn().Msg("No Matrix user provided; Discord announcement will not be shared")
}
fullMsg, err := GetChannelMessage(ctx, msg.ChannelID, msg.ID)
if err != nil {
return oops.New(err, "failed to get published message contents")
}
bodyMarkdown := CleanUpMarkdown(ctx, fullMsg.Content)
bodyHTML := parsing.ParseMarkdown(bodyMarkdown, parsing.DiscordMarkdown)
// Log in to Matrix (we don't bother to keep access tokens around)
var accessToken string
{
type MatrixLogin struct {
Type string `json:"type"`
User string `json:"user"`
Password string `json:"password"`
}
type MatrixLoginResponse struct {
AccessToken string `json:"access_token"`
}
body := MatrixLogin{
Type: "m.login.password",
User: config.Config.Matrix.Username,
Password: config.Config.Matrix.Password,
}
bodyBytes := utils.Must1(json.Marshal(body))
res, err := http.Post(
"https://matrix.handmadecities.com/_matrix/client/r0/login",
"application/json",
bytes.NewReader(bodyBytes),
)
if err != nil || res.StatusCode >= 300 {
return oops.New(err, "failed to log into Matrix")
}
defer res.Body.Close()
resBodyBytes := utils.Must1(io.ReadAll(res.Body))
var resBody MatrixLoginResponse
utils.Must(json.Unmarshal(resBodyBytes, &resBody))
accessToken = resBody.AccessToken
}
// Create message
{
type MessageEvent struct {
MsgType string `json:"msgtype"`
Body string `json:"body"`
Format string `json:"format,omitempty"`
FormattedBody string `json:"formatted_body,omitempty"`
}
tid := "hmn" + strconv.Itoa(rand.Int())
body := MessageEvent{
MsgType: "m.text",
Body: bodyMarkdown,
Format: "org.matrix.custom.html",
FormattedBody: bodyHTML,
}
bodyBytes := utils.Must1(json.Marshal(body))
req := utils.Must1(http.NewRequestWithContext(
ctx,
http.MethodPut,
fmt.Sprintf(
"%s/_matrix/client/v3/rooms/%s/send/m.room.message/%s",
config.Config.Matrix.BaseUrl,
config.Config.Matrix.AnnouncementsRoomID,
tid,
),
bytes.NewReader(bodyBytes),
))
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", accessToken))
req.Header.Add("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil || res.StatusCode >= 300 {
return oops.New(err, "failed to send Matrix message")
}
}
logging.ExtractLogger(ctx).Info().
Str("contents", bodyMarkdown).
Msg("Published Discord announcement to Matrix")
return nil
}
func MaybeInternMessage(ctx context.Context, dbConn db.ConnOrTx, msg *Message) error {
if messageShouldBeStored(msg) {
if msg.ChannelID == config.Config.Discord.ShowcaseChannelID {
err := InternMessage(ctx, dbConn, msg)
if errors.Is(err, errNotEnoughInfo) {
logging.ExtractLogger(ctx).Warn().
@ -354,8 +190,8 @@ func InternMessage(
_, err = dbConn.Exec(ctx,
`
INSERT INTO discord_message (id, channel_id, guild_id, url, user_id, sent_at, snippet_created, backfilled)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
INSERT INTO discord_message (id, channel_id, guild_id, url, user_id, sent_at, snippet_created)
VALUES ($1, $2, $3, $4, $5, $6, $7)
`,
msg.ID,
msg.ChannelID,
@ -364,7 +200,6 @@ func InternMessage(
msg.Author.ID,
msg.Time(),
false,
msg.Backfilled,
)
if err != nil {
return oops.New(err, "failed to save new discord message")
@ -406,7 +241,7 @@ func FetchInternedMessage(ctx context.Context, dbConn db.ConnOrTx, msgId string)
// 1. Saves/updates content
// 2. Saves/updates snippet
// 3. Deletes content/snippet
func HandleInternedMessage(ctx context.Context, dbConn db.ConnOrTx, msg *Message, removeInternedMessage bool, createSnippet bool) error {
func HandleInternedMessage(ctx context.Context, dbConn db.ConnOrTx, msg *Message, deleted bool, createSnippet bool) error {
tx, err := dbConn.Begin(ctx)
if err != nil {
return oops.New(err, "failed to start transaction")
@ -417,11 +252,7 @@ func HandleInternedMessage(ctx context.Context, dbConn db.ConnOrTx, msg *Message
if err != nil && !errors.Is(err, db.NotFound) {
return err
} else if err == nil {
if !removeInternedMessage {
removeInternedMessage = !messageShouldBeStored(msg)
}
if !removeInternedMessage {
if !deleted {
err = SaveMessageContents(ctx, tx, interned, msg)
if err != nil {
return err
@ -854,7 +685,7 @@ func HandleSnippetForInternedMessage(ctx context.Context, dbConn db.ConnOrTx, in
if interned.MessageContent == nil {
// NOTE(asaf): Can't have a snippet without content
// NOTE(asaf): Messages that only have an attachment also have a content struct with an empty content string
// NOTE(asaf): Messages that only have an attachment also have blank content
// TODO(asaf): Do we need to delete existing snippets in this case??? Not entirely sure how to trigger this through discord
return nil
}
@ -904,42 +735,43 @@ func HandleSnippetForInternedMessage(ctx context.Context, dbConn db.ConnOrTx, in
if shouldCreate {
// Get an asset ID or URL to make a snippet from
assetId, url, err := getSnippetAssetOrUrl(ctx, tx, &interned.Message)
if assetId != nil || url != nil {
contentMarkdown := interned.MessageContent.LastContent
contentHTML := parsing.ParseMarkdown(contentMarkdown, parsing.DiscordMarkdown)
contentMarkdown := interned.MessageContent.LastContent
contentHTML := parsing.ParseMarkdown(contentMarkdown, parsing.DiscordMarkdown)
_, err = tx.Exec(ctx,
`
INSERT INTO snippet (url, "when", description, _description_html, asset_id, discord_message_id, owner_id)
VALUES ($1, $2, $3, $4, $5, $6, $7)
`,
url,
interned.Message.SentAt,
contentMarkdown,
contentHTML,
assetId,
interned.Message.ID,
interned.HMNUser.ID,
)
if err != nil {
return oops.New(err, "failed to create snippet from attachment")
}
_, err = tx.Exec(ctx,
`
INSERT INTO snippet (url, "when", description, _description_html, asset_id, discord_message_id, owner_id)
VALUES ($1, $2, $3, $4, $5, $6, $7)
`,
url,
interned.Message.SentAt,
contentMarkdown,
contentHTML,
assetId,
interned.Message.ID,
interned.HMNUser.ID,
)
if err != nil {
return oops.New(err, "failed to create snippet from attachment")
}
existingSnippet, err = FetchSnippetForMessage(ctx, tx, interned.Message.ID)
if err != nil {
return oops.New(err, "failed to fetch newly-created snippet")
}
existingSnippet, err = FetchSnippetForMessage(ctx, tx, interned.Message.ID)
if err != nil {
return oops.New(err, "failed to fetch newly-created snippet")
}
_, err = tx.Exec(ctx,
`
UPDATE discord_message
SET snippet_created = TRUE
WHERE id = $1
`,
interned.Message.ID,
)
if err != nil {
return oops.New(err, "failed to mark message as having snippet")
_, err = tx.Exec(ctx,
`
UPDATE discord_message
SET snippet_created = TRUE
WHERE id = $1
`,
interned.Message.ID,
)
if err != nil {
return oops.New(err, "failed to mark message as having snippet")
}
}
}
}
@ -1081,36 +913,3 @@ func messageHasLinks(content string) bool {
return false
}
func messageShouldBeStored(msg *Message) bool {
if msg == nil {
return false
}
if strings.HasPrefix(strings.ToLower(strings.TrimSpace(msg.Content)), "!til") {
return true
}
autostore := false
for _, cid := range autostoreChannels {
if msg.ChannelID == cid {
autostore = true
break
}
}
if autostore {
hasGoodContent := true
if msg.OriginalHasFields("content") && !messageHasLinks(msg.Content) {
hasGoodContent = false
}
hasGoodAttachments := true
if msg.OriginalHasFields("attachments") && len(msg.Attachments) == 0 {
hasGoodAttachments = false
}
return hasGoodContent || hasGoodAttachments
}
return false
}

View File

@ -244,38 +244,20 @@ const (
MessageTypeGuildInviteReminder MessageType = 22
)
type MessageFlags int
const (
MessageFlagCrossposted MessageFlags = 1 << iota
MessageFlagIsCrosspost
MessageFlagSuppressEmbeds
MessageFlagSourceMessageDeleted
MessageFlagUrgent
MessageFlagHasThread
MessageFlagEphemeral
MessageFlagLoading
MessageFlagFailedToMentionSomeRolesInThread
MessageFlagSuppressNotifications
MessageFlagIsVoiceMessage
)
// https://discord.com/developers/docs/resources/channel#message-object
type Message struct {
ID string `json:"id"`
ChannelID string `json:"channel_id"`
GuildID *string `json:"guild_id"`
Content string `json:"content"`
Author *User `json:"author"` // note that this may not be an actual valid user (see the docs)
Timestamp string `json:"timestamp"`
Type MessageType `json:"type"`
Flags MessageFlags `json:"flags"`
ID string `json:"id"`
ChannelID string `json:"channel_id"`
GuildID *string `json:"guild_id"`
Content string `json:"content"`
Author *User `json:"author"` // note that this may not be an actual valid user (see the docs)
Timestamp string `json:"timestamp"`
Type MessageType `json:"type"`
Attachments []Attachment `json:"attachments"`
Embeds []Embed `json:"embeds"`
originalMap map[string]interface{}
Backfilled bool
}
func (m *Message) JumpURL() string {
@ -335,7 +317,6 @@ func MessageFromMap(m interface{}, k string) *Message {
Author: UserFromMap(m, "author"),
Timestamp: maybeString(mmap, "timestamp"),
Type: MessageType(maybeInt(mmap, "type")),
Flags: MessageFlags(maybeInt(mmap, "flags")),
originalMap: mmap,
}
@ -1022,11 +1003,3 @@ func maybeBoolP(m map[string]interface{}, k string) *bool {
boolval := val.(bool)
return &boolval
}
func maybeArray(m map[string]any, k string) []any {
val, ok := m[k]
if !ok || val == nil {
return nil
}
return val.([]any)
}

View File

@ -48,47 +48,7 @@ func SendRegistrationEmail(
perf.EndBlock()
perf.StartBlock("EMAIL", "Sending email")
err = sendMail(toAddress, toName, "[Handmade Network] Registration confirmation", contents)
if err != nil {
return oops.New(err, "Failed to send email")
}
perf.EndBlock()
perf.EndBlock()
return nil
}
type ExistingAccountEmailData struct {
Name string
Username string
HomepageUrl string
LoginUrl string
}
func SendExistingAccountEmail(
toAddress string,
toName string,
username string,
destination string,
perf *perf.RequestPerf,
) error {
perf.StartBlock("EMAIL", "Existing account email")
perf.StartBlock("EMAIL", "Rendering template")
contents, err := renderTemplate("email_account_existing.html", ExistingAccountEmailData{
Name: toName,
Username: username,
HomepageUrl: hmnurl.BuildHomepage(),
LoginUrl: hmnurl.BuildLoginPage(destination),
})
if err != nil {
return err
}
perf.EndBlock()
perf.StartBlock("EMAIL", "Sending email")
err = sendMail(toAddress, toName, "[Handmade Network] You already have an account!", contents)
err = sendMail(toAddress, toName, "[handmade.network] Registration confirmation", contents)
if err != nil {
return oops.New(err, "Failed to send email")
}
@ -120,7 +80,7 @@ func SendPasswordReset(toAddress string, toName string, username string, resetTo
perf.EndBlock()
perf.StartBlock("EMAIL", "Sending email")
err = sendMail(toAddress, toName, "[Handmade Network] Your password reset request", contents)
err = sendMail(toAddress, toName, "[handmade.network] Your password reset request", contents)
if err != nil {
return oops.New(err, "Failed to send email")
}
@ -136,12 +96,12 @@ type TimeMachineEmailData struct {
Username string
UserEmail string
DiscordUsername string
MediaUrls []string
MediaUrl string
DeviceInfo string
Description string
}
func SendTimeMachineEmail(profileUrl, username, userEmail, discordUsername string, mediaUrls []string, deviceInfo, description string, perf *perf.RequestPerf) error {
func SendTimeMachineEmail(profileUrl, username, userEmail, discordUsername, mediaUrl, deviceInfo, description string, perf *perf.RequestPerf) error {
perf.StartBlock("EMAIL", "Time machine email")
defer perf.EndBlock()
@ -150,7 +110,7 @@ func SendTimeMachineEmail(profileUrl, username, userEmail, discordUsername strin
Username: username,
UserEmail: userEmail,
DiscordUsername: discordUsername,
MediaUrls: mediaUrls,
MediaUrl: mediaUrl,
DeviceInfo: deviceInfo,
Description: description,
})
@ -158,7 +118,7 @@ func SendTimeMachineEmail(profileUrl, username, userEmail, discordUsername strin
return err
}
err = sendMail("team@handmade.network", "HMN Team", "[Time Machine] New submission", contents)
err = sendMail("team@handmade.network", "HMN Team", "[time machine] New submission", contents)
if err != nil {
return oops.New(err, "Failed to send email")
}

View File

@ -17,9 +17,8 @@ type Event struct {
type Jam struct {
Event
Name string
Slug string
UrlSlug string
Name string
Slug string
}
var WRJ2021 = Jam{
@ -27,9 +26,8 @@ var WRJ2021 = Jam{
StartTime: time.Date(2021, 9, 27, 0, 0, 0, 0, time.UTC),
EndTime: time.Date(2021, 10, 4, 0, 0, 0, 0, time.UTC),
},
Name: "Wheel Reinvention Jam 2021",
Slug: "WRJ2021",
UrlSlug: "2021",
Name: "Wheel Reinvention Jam 2021",
Slug: "WRJ2021",
}
var WRJ2022 = Jam{
@ -37,9 +35,8 @@ var WRJ2022 = Jam{
StartTime: time.Date(2022, 8, 15, 0, 0, 0, 0, utils.Must1(time.LoadLocation("America/Los_Angeles"))),
EndTime: time.Date(2022, 8, 22, 8, 0, 0, 0, utils.Must1(time.LoadLocation("America/Los_Angeles"))),
},
Name: "Wheel Reinvention Jam 2022",
Slug: "WRJ2022",
UrlSlug: "2022",
Name: "Wheel Reinvention Jam 2022",
Slug: "WRJ2022",
}
var VJ2023 = Jam{
@ -47,32 +44,10 @@ var VJ2023 = Jam{
StartTime: time.Date(2023, 4, 14, 0, 0, 0, 0, time.UTC),
EndTime: time.Date(2023, 4, 17, 0, 0, 0, 0, time.UTC),
},
Name: "Visibility Jam 2023",
Slug: "VJ2023",
UrlSlug: "visibility-2023",
Name: "Visibility Jam 2023",
Slug: "VJ2023",
}
var WRJ2023 = Jam{
Event: Event{
StartTime: time.Date(2023, 9, 25, 10, 0, 0, 0, utils.Must1(time.LoadLocation("Europe/London"))),
EndTime: time.Date(2023, 10, 1, 20, 0, 0, 0, utils.Must1(time.LoadLocation("Europe/London"))),
},
Name: "Wheel Reinvention Jam 2023",
Slug: "WRJ2023",
UrlSlug: "2023",
}
var LJ2024 = Jam{
Event: Event{
StartTime: time.Date(2024, 3, 15, 17, 0, 0, 0, time.UTC),
EndTime: time.Date(2024, 3, 25, 0, 0, 0, 0, time.UTC),
},
Name: "Learning Jam 2024",
Slug: "LJ2024",
UrlSlug: "learning-2024",
}
// Conferences
var HMS2022 = Event{
StartTime: time.Date(2022, 11, 16, 0, 0, 0, 0, utils.Must1(time.LoadLocation("America/Los_Angeles"))),
EndTime: time.Date(2022, 11, 18, 0, 0, 0, 0, utils.Must1(time.LoadLocation("America/Los_Angeles"))),
@ -88,17 +63,7 @@ var HMBoston2023 = Event{
EndTime: time.Date(2023, 8, 4, 0, 0, 0, 0, utils.Must1(time.LoadLocation("America/Los_Angeles"))),
}
var HMS2024 = Event{
StartTime: time.Date(2024, 11, 20, 0, 0, 0, 0, utils.Must1(time.LoadLocation("America/Los_Angeles"))),
EndTime: time.Date(2024, 11, 22, 0, 0, 0, 0, utils.Must1(time.LoadLocation("America/Los_Angeles"))),
}
var HMBoston2024 = Event{
StartTime: time.Date(2024, 8, 9, 0, 0, 0, 0, utils.Must1(time.LoadLocation("America/Los_Angeles"))),
EndTime: time.Date(2024, 8, 10, 0, 0, 0, 0, utils.Must1(time.LoadLocation("America/Los_Angeles"))),
}
var AllJams = []Jam{WRJ2021, WRJ2022, VJ2023, WRJ2023, LJ2024}
var AllJams = []Jam{WRJ2021, WRJ2022, VJ2023}
func CurrentJam() *Jam {
now := time.Now()
@ -110,17 +75,6 @@ func CurrentJam() *Jam {
return nil
}
func PreviousJam() *Jam {
now := time.Now()
var mostRecent *Jam
for i, jam := range AllJams {
if jam.EndTime.Before(now) {
mostRecent = &AllJams[i]
}
}
return mostRecent
}
func JamBySlug(slug string) Jam {
for _, jam := range AllJams {
if jam.Slug == slug {

View File

@ -44,6 +44,10 @@ func TestShowcase(t *testing.T) {
AssertRegexMatch(t, BuildShowcase(), RegexShowcase, nil)
}
func TestStreams(t *testing.T) {
AssertRegexMatch(t, BuildStreams(), RegexStreams, nil)
}
func TestWhenIsIt(t *testing.T) {
AssertRegexMatch(t, BuildWhenIsIt(), RegexWhenIsIt, nil)
}
@ -138,10 +142,9 @@ func TestFeed(t *testing.T) {
}
func TestProjectIndex(t *testing.T) {
AssertRegexMatch(t, BuildProjectIndex(1, ""), RegexProjectIndex, nil)
AssertRegexMatch(t, BuildProjectIndex(1, "test"), RegexProjectIndex, map[string]string{"category": "test"})
AssertRegexMatch(t, BuildProjectIndex(2, "test"), RegexProjectIndex, map[string]string{"page": "2", "category": "test"})
assert.Panics(t, func() { BuildProjectIndex(0, "") })
AssertRegexMatch(t, BuildProjectIndex(1), RegexProjectIndex, nil)
AssertRegexMatch(t, BuildProjectIndex(2), RegexProjectIndex, map[string]string{"page": "2"})
assert.Panics(t, func() { BuildProjectIndex(0) })
}
func TestProjectNew(t *testing.T) {
@ -412,57 +415,6 @@ func TestJamRecap2023_Visibility(t *testing.T) {
AssertSubdomain(t, BuildJamRecap2023_Visibility(), "")
}
func TestJamIndex2023(t *testing.T) {
AssertRegexMatch(t, BuildJamIndex2023(), RegexJamIndex2023, nil)
AssertSubdomain(t, BuildJamIndex2023(), "")
}
func TestJamFeed2023(t *testing.T) {
AssertRegexMatch(t, BuildJamFeed2023(), RegexJamFeed2023, nil)
AssertSubdomain(t, BuildJamFeed2023(), "")
}
func TestJamIndex2024_Learning(t *testing.T) {
AssertRegexMatch(t, BuildJamIndex2024_Learning(), RegexJamIndex2024_Learning, nil)
AssertSubdomain(t, BuildJamIndex2024_Learning(), "")
}
func TestJamFeed2024_Learning(t *testing.T) {
AssertRegexMatch(t, BuildJamFeed2024_Learning(), RegexJamFeed2024_Learning, nil)
AssertSubdomain(t, BuildJamFeed2024_Learning(), "")
}
func TestTimeMachine(t *testing.T) {
AssertRegexMatch(t, BuildTimeMachine(), RegexTimeMachine, nil)
AssertSubdomain(t, BuildTimeMachine(), "")
}
func TestTimeMachineSubmissions(t *testing.T) {
AssertRegexMatch(t, BuildTimeMachineSubmissions(), RegexTimeMachineSubmissions, nil)
AssertRegexMatch(t, BuildTimeMachineSubmission(123), RegexTimeMachineSubmissions, nil)
AssertSubdomain(t, BuildTimeMachineSubmissions(), "")
}
func TestTimeMachineAtomFeed(t *testing.T) {
AssertRegexMatch(t, BuildTimeMachineAtomFeed(), RegexTimeMachineAtomFeed, nil)
AssertSubdomain(t, BuildTimeMachineAtomFeed(), "")
}
func TestTimeMachineForm(t *testing.T) {
AssertRegexMatch(t, BuildTimeMachineForm(), RegexTimeMachineForm, nil)
AssertSubdomain(t, BuildTimeMachineForm(), "")
}
func TestTimeMachineFormDone(t *testing.T) {
AssertRegexMatch(t, BuildTimeMachineFormDone(), RegexTimeMachineFormDone, nil)
AssertSubdomain(t, BuildTimeMachineFormDone(), "")
}
func TestNewsletterSignup(t *testing.T) {
AssertRegexMatch(t, BuildAPINewsletterSignup(), RegexNewsletterSignup, nil)
AssertSubdomain(t, BuildAPINewsletterSignup(), "")
}
func TestProjectNewJam(t *testing.T) {
AssertRegexMatch(t, BuildProjectNewJam(), RegexProjectNew, nil)
AssertSubdomain(t, BuildProjectNewJam(), "")

View File

@ -35,6 +35,13 @@ func BuildShowcase() string {
return Url("/showcase", nil)
}
var RegexStreams = regexp.MustCompile("^/streams$")
func BuildStreams() string {
defer CatchPanic()
return Url("/streams", nil)
}
var RegexWhenIsIt = regexp.MustCompile("^/whenisit$")
func BuildWhenIsIt() string {
@ -70,27 +77,6 @@ func BuildJamIndex2022() string {
return Url("/jam/2022", nil)
}
var RegexJamFeed2022 = regexp.MustCompile("^/jam/2022/feed$")
func BuildJamFeed2022() string {
defer CatchPanic()
return Url("/jam/2022/feed", nil)
}
var RegexJamIndex2023 = regexp.MustCompile("^/jam/2023$")
func BuildJamIndex2023() string {
defer CatchPanic()
return Url("/jam/2023", nil)
}
var RegexJamFeed2023 = regexp.MustCompile("^/jam/2023/feed$")
func BuildJamFeed2023() string {
defer CatchPanic()
return Url("/jam/2023/feed", nil)
}
var RegexJamIndex2023_Visibility = regexp.MustCompile("^/jam/visibility-2023$")
func BuildJamIndex2023_Visibility() string {
@ -112,37 +98,11 @@ func BuildJamRecap2023_Visibility() string {
return Url("/jam/visibility-2023/recap", nil)
}
var RegexJamIndex2024_Learning = regexp.MustCompile("^/jam/learning-2024$")
var RegexJamFeed2022 = regexp.MustCompile("^/jam/2022/feed$")
func BuildJamIndex2024_Learning() string {
func BuildJamFeed2022() string {
defer CatchPanic()
return Url("/jam/learning-2024", nil)
}
var RegexJamFeed2024_Learning = regexp.MustCompile("^/jam/learning-2024/feed$")
func BuildJamFeed2024_Learning() string {
defer CatchPanic()
return Url("/jam/learning-2024/feed", nil)
}
var RegexJamGuidelines2024_Learning = regexp.MustCompile("^/jam/learning-2024/guidelines$")
func BuildJamGuidelines2024_Learning() string {
defer CatchPanic()
return Url("/jam/learning-2024/guidelines", nil)
}
var RegexJamSaveTheDate = regexp.MustCompile("^/jam/upcoming$")
func BuildJamSaveTheDate() string {
defer CatchPanic()
return Url("/jam/upcoming", nil)
}
func BuildJamIndexAny(slug string) string {
defer CatchPanic()
return Url(fmt.Sprintf("/jam/%s", slug), nil)
return Url("/jam/2022/feed", nil)
}
var RegexTimeMachine = regexp.MustCompile("^/timemachine$")
@ -152,25 +112,6 @@ func BuildTimeMachine() string {
return Url("/timemachine", nil)
}
var RegexTimeMachineSubmissions = regexp.MustCompile("^/timemachine/submissions$")
func BuildTimeMachineSubmissions() string {
defer CatchPanic()
return Url("/timemachine/submissions", nil)
}
func BuildTimeMachineSubmission(id int) string {
defer CatchPanic()
return UrlWithFragment("/timemachine/submissions", nil, strconv.Itoa(id))
}
var RegexTimeMachineAtomFeed = regexp.MustCompile("^/timemachine/submissions/atom$")
func BuildTimeMachineAtomFeed() string {
defer CatchPanic()
return Url("/timemachine/submissions/atom", nil)
}
var RegexTimeMachineForm = regexp.MustCompile("^/timemachine/submit$")
func BuildTimeMachineForm() string {
@ -185,20 +126,6 @@ func BuildTimeMachineFormDone() string {
return Url("/timemachine/thanks", nil)
}
var RegexCalendarIndex = regexp.MustCompile("^/calendar$")
func BuildCalendarIndex() string {
defer CatchPanic()
return Url("/calendar", nil)
}
var RegexCalendarICal = regexp.MustCompile("^/Handmade Network.ical$")
func BuildCalendarICal() string {
defer CatchPanic()
return Url("/Handmade Network.ical", nil)
}
// QUESTION(ben): Can we change these routes?
var RegexLoginAction = regexp.MustCompile("^/login$")
@ -212,11 +139,7 @@ var RegexLoginPage = regexp.MustCompile("^/login$")
func BuildLoginPage(redirectTo string) string {
defer CatchPanic()
var q []Q
if redirectTo != "" {
q = append(q, Q{Name: "redirect", Value: redirectTo})
}
return Url("/login", q)
return Url("/login", []Q{{Name: "redirect", Value: redirectTo}})
}
var RegexLoginWithDiscord = regexp.MustCompile("^/login-with-discord$")
@ -478,21 +401,17 @@ func BuildAtomFeedForShowcase() string {
* Projects
*/
var RegexProjectIndex = regexp.MustCompile(`^/projects(/(?P<category>[a-z0-9-]+)(/(?P<page>\d+))?)?$`)
var RegexProjectIndex = regexp.MustCompile("^/projects(/(?P<page>.+)?)?$")
func BuildProjectIndex(page int, category string) string {
func BuildProjectIndex(page int) string {
defer CatchPanic()
if page < 1 {
panic(oops.New(nil, "page must be >= 1"))
}
catpath := ""
if category != "" {
catpath = "/" + category
}
if page == 1 {
return Url(fmt.Sprintf("/projects%s", catpath), nil)
return Url("/projects", nil)
} else {
return Url(fmt.Sprintf("/projects%s/%d", catpath, page), nil)
return Url(fmt.Sprintf("/projects/%d", page), nil)
}
}
@ -922,12 +841,6 @@ func BuildDiscordShowcaseBacklog() string {
return Url("/discord_showcase_backlog", nil)
}
var RegexDiscordBotDebugPage = regexp.MustCompile("^/discord_bot_debug$")
func BuildDiscordBotDebugPage() string {
return Url("/discord_bot_debug", nil)
}
/*
* API
*/
@ -938,12 +851,6 @@ func BuildAPICheckUsername() string {
return Url("/api/check_username", nil)
}
var RegexAPINewsletterSignup = regexp.MustCompile("^/api/newsletter_signup$")
func BuildAPINewsletterSignup() string {
return Url("/api/newsletter_signup", nil)
}
/*
* Twitch stuff
*/
@ -1040,12 +947,6 @@ func BuildUserFile(filepath string) string {
return BuildPublic(fmt.Sprintf("media/%s", filepath), false)
}
/*
* Redirects
*/
var RegexUnwind = regexp.MustCompile(`^/unwind$`)
/*
* Other
*/

View File

@ -1,47 +0,0 @@
package migrations
import (
"context"
"time"
"git.handmade.network/hmn/hmn/src/migration/types"
"github.com/jackc/pgx/v5"
)
func init() {
registerMigration(AddBackfillToDiscordMessage{})
}
type AddBackfillToDiscordMessage struct{}
func (m AddBackfillToDiscordMessage) Version() types.MigrationVersion {
return types.MigrationVersion(time.Date(2024, 3, 28, 18, 41, 7, 0, time.UTC))
}
func (m AddBackfillToDiscordMessage) Name() string {
return "AddBackfillToDiscordMessage"
}
func (m AddBackfillToDiscordMessage) Description() string {
return "Add a backfill flag to discord messages"
}
func (m AddBackfillToDiscordMessage) Up(ctx context.Context, tx pgx.Tx) error {
_, err := tx.Exec(ctx,
`
ALTER TABLE discord_message
ADD COLUMN backfilled BOOLEAN NOT NULL default FALSE;
`,
)
return err
}
func (m AddBackfillToDiscordMessage) Down(ctx context.Context, tx pgx.Tx) error {
_, err := tx.Exec(ctx,
`
ALTER TABLE discord_message
DROP COLUMN backfilled;
`,
)
return err
}

View File

@ -1,47 +0,0 @@
package migrations
import (
"context"
"time"
"git.handmade.network/hmn/hmn/src/migration/types"
"github.com/jackc/pgx/v5"
)
func init() {
registerMigration(newsletter{})
}
type newsletter struct{}
func (m newsletter) Version() types.MigrationVersion {
return types.MigrationVersion(time.Date(2024, 5, 7, 1, 34, 32, 0, time.UTC))
}
func (m newsletter) Name() string {
return "newsletter"
}
func (m newsletter) Description() string {
return "Adds the newsletter signup"
}
func (m newsletter) Up(ctx context.Context, tx pgx.Tx) error {
_, err := tx.Exec(ctx,
`
CREATE TABLE newsletter_emails (
email VARCHAR(255) NOT NULL PRIMARY KEY
);
`,
)
return err
}
func (m newsletter) Down(ctx context.Context, tx pgx.Tx) error {
_, err := tx.Exec(ctx,
`
DROP TABLE newsletter_emails;
`,
)
return err
}

View File

@ -167,6 +167,14 @@ article code {
margin-right: auto;
}
.flex-shrink-0 {
flex-shrink: 0;
}
.flex-grow-1 {
flex-grow: 1;
}
.flex-fair {
flex-basis: 1px;
flex-grow: 1;
@ -364,18 +372,6 @@ article code {
.g4 { gap: $spacing-large; }
.g5 { gap: $spacing-extra-large; }
.grid {
display: grid;
}
.grid-1 {
grid-template-columns: 1fr;
}
.grid-2 {
grid-template-columns: 1fr 1fr;
}
.aspect-ratio--2x1 {
padding-bottom: 50%;
}
@ -396,19 +392,10 @@ article code {
.cg3-ns { column-gap: $spacing-medium; }
.cg4-ns { column-gap: $spacing-large; }
.cg5-ns { column-gap: $spacing-extra-large; }
.grid-1-ns { grid-template-columns: 1fr; }
.grid-2-ns { grid-template-columns: 1fr 1fr; }
.bg--dim-ns {
@include usevar(background-color, dim-background);
}
.g0-ns { gap: $spacing-none; }
.g1-ns { gap: $spacing-extra-small; }
.g2-ns { gap: $spacing-small; }
.g3-ns { gap: $spacing-medium; }
.g4-ns { gap: $spacing-large; }
.g5-ns { gap: $spacing-extra-large; }
}
@media #{$breakpoint-medium} {
@ -422,19 +409,10 @@ article code {
.cg3-m { column-gap: $spacing-medium; }
.cg4-m { column-gap: $spacing-large; }
.cg5-m { column-gap: $spacing-extra-large; }
.grid-1-m { grid-template-columns: 1fr; }
.grid-2-m { grid-template-columns: 1fr 1fr; }
.bg--dim-m {
@include usevar(background-color, dim-background);
}
.g0-m { gap: $spacing-none; }
.g1-m { gap: $spacing-extra-small; }
.g2-m { gap: $spacing-small; }
.g3-m { gap: $spacing-medium; }
.g4-m { gap: $spacing-large; }
.g5-m { gap: $spacing-extra-large; }
}
@media #{$breakpoint-large} {
@ -448,19 +426,10 @@ article code {
.cg3-l { column-gap: $spacing-medium; }
.cg4-l { column-gap: $spacing-large; }
.cg5-l { column-gap: $spacing-extra-large; }
.grid-1-l { grid-template-columns: 1fr; }
.grid-2-l { grid-template-columns: 1fr 1fr; }
.bg--dim-l {
@include usevar(background-color, dim-background);
}
.g0-l { gap: $spacing-none; }
.g1-l { gap: $spacing-extra-small; }
.g2-l { gap: $spacing-small; }
.g3-l { gap: $spacing-medium; }
.g4-l { gap: $spacing-large; }
.g5-l { gap: $spacing-extra-large; }
}
.not-first:first-child {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 548 B

View File

@ -8,7 +8,6 @@ import (
"strconv"
"strings"
"git.handmade.network/hmn/hmn/src/calendar"
"git.handmade.network/hmn/hmn/src/hmndata"
"git.handmade.network/hmn/hmn/src/hmnurl"
"git.handmade.network/hmn/hmn/src/models"
@ -103,9 +102,6 @@ func ProjectToTemplate(
func ProjectAndStuffToTemplate(p *hmndata.ProjectAndStuff, url string, theme string) Project {
res := ProjectToTemplate(&p.Project, url)
res.Logo = ProjectLogoUrl(&p.Project, p.LogoLightAsset, p.LogoDarkAsset, theme)
for _, o := range p.Owners {
res.Owners = append(res.Owners, UserToTemplate(o, theme))
}
return res
}
@ -531,16 +527,6 @@ func EducationArticleToTemplate(a *models.EduArticle) EduArticle {
return res
}
func CalendarEventToTemplate(ev *calendar.CalendarEvent) CalendarEvent {
return CalendarEvent{
Name: ev.Name,
Desc: ev.Desc,
StartTime: ev.StartTime.UTC(),
EndTime: ev.EndTime.UTC(),
CalName: ev.CalName,
}
}
func maybeString(s *string) string {
if s == nil {
return ""

View File

@ -39,16 +39,12 @@
{{ end }}
<!-- Main post -->
<div class="{{ if .IsProjectPage }}mb3{{ end }}">
<div class="mb3">
<div class="post-content overflow-x-auto">
{{ .MainPost.Content }}
</div>
</div>
{{ if not .IsProjectPage }}
{{ template "newsletter_signup.html" . }}
{{ end }}
<div class="optionbar"></div>
{{ range .Comments }}

View File

@ -1,92 +0,0 @@
{{ template "base.html" . }}
{{ define "content" }}
<div class="ph3 ph0-ns">
<h2>Future events</h2>
<div class="cal_toggles mb2 flex flex-row g2">
{{ range .Calendars }}
<label class="db br3 pv1 ph2 pointer b--gray ba" for="{{ . }}">
<input id="{{ . }}" autocomplete="off" type="checkbox" value="{{ . }}" checked />
<span>{{ . }}</span>
</label>
{{ end }}
</div>
<div class="">
<a class="ical_link" href="{{ .BaseICalUrl }}">Copy iCal Url</a>
</div>
<div class="flex flex-column g2">
{{ range .Events }}
<div data-calname="{{ .CalName }}" class="cal_event timeline-item pa3 br3">
<div>{{ timehtmlcontent .StartTime }}</div>
<div>
<strong class="f4 c--theme">{{ .Name }}</strong>
</div>
{{ with .Desc }}
<div class="mb2">{{ . }}</div>
{{ end }}
{{ with .CalName }}
<div class="dib br2 ba b--gray ph1 f7">{{ . }}</div>
{{ end }}
</div>
{{ end }}
</div>
</div>
<script>
let events = document.querySelectorAll(".cal_event");
let toggles = document.querySelectorAll(".cal_toggles input");
let icalLink = document.querySelector(".ical_link");
let baseICalUrl = icalLink.href;
function refreshEvents() {
let cals = {};
for (let i = 0; i < toggles.length; ++i) {
cals[toggles[i].id] = toggles[i].checked;
}
for (let i = 0; i < events.length; ++i) {
let ev = events[i];
let calName = ev.getAttribute("data-calname");
if (cals[calName]) {
ev.style.display = "block";
} else {
ev.style.display = "none";
}
}
let icalFilter = [];
let hasAll = true;
for (let i = 0; i < toggles.length; ++i) {
if (toggles[i].checked) {
icalFilter.push(toggles[i].id);
} else {
hasAll = false;
}
}
icalLink.disabled = false;
if (hasAll) {
icalLink.href = baseICalUrl;
} else if (icalFilter.length == 0) {
icalLink.removeAttribute("href");
} else {
icalFilter.sort();
let url = new URL(baseICalUrl);
let params = new URLSearchParams();
for (let i = 0; i < icalFilter.length; ++i) {
params.append(icalFilter[i], "true");
}
url.search = params.toString();
icalLink.href = url.toString();
}
}
for (let i = 0; i < toggles.length; ++i) {
toggles[i].addEventListener("input", refreshEvents);
}
icalLink.addEventListener("click", function(ev) {
ev.preventDefault();
navigator.clipboard.writeText(icalLink.href);
});
</script>
{{ end }}

View File

@ -1,22 +0,0 @@
{{ template "base.html" . }}
{{ define "content" }}
<table>
<thead>
<tr>
<td>Timestamp</td>
<td>Name</td>
<td>Extras</td>
</tr>
</thead>
<tbody>
{{ range .BotEvents }}
<tr>
<td>{{ rfc3339 .Timestamp }}</td>
<td>{{ .Name }}</td>
<td>{{ .Extra }}</td>
</tr>
{{ end }}
</tbody>
</table>
{{ end }}

View File

@ -1,16 +0,0 @@
<p>
Hello {{ .Name }} - you already have a <a href="{{ .HomepageUrl }}">Handmade Network</a> account. Welcome back!
</p>
<p>
Your username is <b>{{ .Username }}</b>. To sign in, please visit the following link and try signing in with your existing username:
</p>
<p>
<a href="{{ .LoginUrl }}">{{ .LoginUrl }}</a>
</p>
<p>Thanks,<br />
The Handmade Network staff.</p>
<hr />
<p style="font-size:small; -webkit-text-size-adjust:none; color: #666">
You are receiving this email because someone tried creating a new account with your email address at <a href="{{ .HomepageUrl }}">handmade.network</a>. If that wasn't you, kindly ignore this email.
</p>

View File

@ -5,7 +5,7 @@
To complete the registration process, please use the following link:
</p>
<p>
<a href="{{ .CompleteRegistrationUrl }}">{{ .CompleteRegistrationUrl }}</a>
<a href="{{ .CompleteRegistrationUrl }}">{{ .CompleteRegistrationUrl }}</a>.
</p>
<p>Thanks,<br />
The Handmade Network staff.</p>

View File

@ -1,10 +1,5 @@
<p>Submission by <b><a href="{{ .ProfileUrl }}">{{ .Username }}</a></b> ({{ .UserEmail }}) {{ if .DiscordUsername }} On Discord: {{ .DiscordUsername }} {{ end }}</p>
<p>Submitted urls:<p>
<ul>
{{ range .MediaUrls }}
<li><a href="{{ . }}">{{ . }}</a></li>
{{ end }}
</ul>
<p>Submitted url: <a href="{{ .MediaUrl }}">{{ .MediaUrl }}</a></p>
Device info:<br />
<pre>{{ .DeviceInfo }}</pre>
Description:<br />

View File

@ -64,7 +64,7 @@
<div class="fishbowl-banner br3 mb3">
<div class="pa3">
This is a <b>fishbowl</b>: a panel conversation held on the Handmade Network Discord where a select few participants discuss a topic in depth. We host them on a regular basis, so if you want to catch the next one, <a href="https://discord.gg/hmn" target="_blank">join the Discord!</a>
This is a <b>fishbowl</b>: a panel conversation held on the Handmade Network Discord where a select few participants discuss a topic with depth and nuance. We host them every two months, so if you want to catch the next one, <a href="https://discord.gg/hmn" target="_blank">join the Discord!</a>
</div>
</div>

View File

@ -4,7 +4,7 @@
<div class="ph3 ph0-ns">
<h2>Fishbowls</h2>
<p>Every so often on the Discord, we host a <b>fishbowl</b>: a panel conversation where a select few community members can discuss a topic in detail. Fishbowls give us the opportunity to discuss complex topics in more depth and detail than a normal chat conversation would allow. They give our best conversations room to breathe.</p>
<p>Every so often on the Discord, we host a <b>fishbowl</b>: a panel conversation where a select few community members can discuss a topic in detail. Fishbowls give us the opportunity to discuss difficult subjects with more nuance and detail than you can find anywhere else on the Internet. In many ways, they're a distillation of everything the network is about.</p>
<p>This is an archive of those conversations. If you would like to catch one live, <a href="https://discord.gg/hmn" target="_blank">join the Discord!</a></p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 228 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#662113" d="M22 33c0 2.209-1.791 3-4 3s-4-.791-4-3l1-9c0-2.209.791-2 3-2s3-.209 3 2l1 9z"/><path fill="#5C913B" d="M31.406 27.297C24.443 21.332 21.623 12.791 18 12.791c-3.623 0-6.443 8.541-13.405 14.506-2.926 2.507-1.532 3.957 2.479 3.667 3.576-.258 6.919-1.069 10.926-1.069s7.352.812 10.926 1.069c4.012.29 5.405-1.16 2.48-3.667z"/><path fill="#3E721D" d="M29.145 24.934C23.794 20.027 20.787 13 18 13c-2.785 0-5.793 7.027-11.144 11.934-4.252 3.898 5.572 4.773 11.144 0 5.569 4.773 15.396 3.898 11.145 0z"/><path fill="#5C913B" d="M29.145 20.959C23.794 16.375 20.787 9.811 18 9.811c-2.785 0-5.793 6.564-11.144 11.148-4.252 3.642 5.572 4.459 11.144 0 5.569 4.459 15.396 3.642 11.145 0z"/><path fill="#3E721D" d="M26.7 17.703C22.523 14.125 20.176 9 18 9c-2.174 0-4.523 5.125-8.7 8.703-3.319 2.844 4.35 3.482 8.7 0 4.349 3.482 12.02 2.844 8.7 0z"/><path fill="#5C913B" d="M26.7 14.726c-4.177-3.579-6.524-8.703-8.7-8.703-2.174 0-4.523 5.125-8.7 8.703-3.319 2.844 4.35 3.481 8.7 0 4.349 3.481 12.02 2.843 8.7 0z"/><path fill="#3E721D" d="M25.021 12.081C21.65 9.193 19.756 5.057 18 5.057c-1.755 0-3.65 4.136-7.021 7.024-2.679 2.295 3.511 2.809 7.021 0 3.51 2.81 9.701 2.295 7.021 0z"/><path fill="#5C913B" d="M25.021 9.839C21.65 6.951 19.756 2.815 18 2.815c-1.755 0-3.65 4.136-7.021 7.024-2.679 2.295 3.511 2.809 7.021 0 3.51 2.81 9.701 2.295 7.021 0z"/><path fill="#3E721D" d="M23.343 6.54C20.778 4.342 19.336 1.195 18 1.195c-1.335 0-2.778 3.148-5.343 5.345-2.038 1.747 2.671 2.138 5.343 0 2.671 2.138 7.382 1.746 5.343 0z"/><path fill="#5C913B" d="M23.343 5.345C20.778 3.148 19.336 0 18 0c-1.335 0-2.778 3.148-5.343 5.345-2.038 1.747 2.671 2.138 5.343 0 2.671 2.138 7.382 1.746 5.343 0z"/></svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><ellipse fill="#F5F8FA" cx="8.828" cy="18" rx="7.953" ry="13.281"/><path fill="#E1E8ED" d="M8.828 32.031C3.948 32.031.125 25.868.125 18S3.948 3.969 8.828 3.969 17.531 10.132 17.531 18s-3.823 14.031-8.703 14.031zm0-26.562C4.856 5.469 1.625 11.09 1.625 18s3.231 12.531 7.203 12.531S16.031 24.91 16.031 18 12.8 5.469 8.828 5.469z"/><circle fill="#8899A6" cx="6.594" cy="18" r="4.96"/><circle fill="#292F33" cx="6.594" cy="18" r="3.565"/><circle fill="#F5F8FA" cx="7.911" cy="15.443" r="1.426"/><ellipse fill="#F5F8FA" cx="27.234" cy="18" rx="7.953" ry="13.281"/><path fill="#E1E8ED" d="M27.234 32.031c-4.88 0-8.703-6.163-8.703-14.031s3.823-14.031 8.703-14.031S35.938 10.132 35.938 18s-3.824 14.031-8.704 14.031zm0-26.562c-3.972 0-7.203 5.622-7.203 12.531 0 6.91 3.231 12.531 7.203 12.531S34.438 24.91 34.438 18 31.206 5.469 27.234 5.469z"/><circle fill="#8899A6" cx="25" cy="18" r="4.96"/><circle fill="#292F33" cx="25" cy="18" r="3.565"/><circle fill="#F5F8FA" cx="26.317" cy="15.443" r="1.426"/></svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFDC5D" d="M30 20.145s.094-2.362-1.791-3.068c-1.667-.625-2.309.622-2.309.622s.059-1.913-1.941-2.622c-1.885-.667-2.75.959-2.75.959s-.307-1.872-2.292-2.417C17.246 13.159 16 14.785 16 14.785V2.576C16 1.618 15.458.001 13.458 0S11 1.66 11 2.576v20.5c0 1-1 1-1 0V20.41c0-3.792-2.037-6.142-2.75-6.792-.713-.65-1.667-.98-2.82-.734-1.956.416-1.529 1.92-.974 3.197 1.336 3.078 2.253 7.464 2.533 9.538.79 5.858 5.808 10.375 11.883 10.381 6.626.004 12.123-5.298 12.128-11.924v-3.931z"/></svg>

Before

Width:  |  Height:  |  Size: 553 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFDB5E" d="M34.956 17.916c0-.503-.12-.975-.321-1.404-1.341-4.326-7.619-4.01-16.549-4.221-1.493-.035-.639-1.798-.115-5.668.341-2.517-1.282-6.382-4.01-6.382-4.498 0-.171 3.548-4.148 12.322-2.125 4.688-6.875 2.062-6.875 6.771v10.719c0 1.833.18 3.595 2.758 3.885C8.195 34.219 7.633 36 11.238 36h18.044c1.838 0 3.333-1.496 3.333-3.334 0-.762-.267-1.456-.698-2.018 1.02-.571 1.72-1.649 1.72-2.899 0-.76-.266-1.454-.696-2.015 1.023-.57 1.725-1.649 1.725-2.901 0-.909-.368-1.733-.961-2.336.757-.611 1.251-1.535 1.251-2.581z"/><path fill="#EE9547" d="M23.02 21.249h8.604c1.17 0 2.268-.626 2.866-1.633.246-.415.109-.952-.307-1.199-.415-.247-.952-.108-1.199.307-.283.479-.806.775-1.361.775h-8.81c-.873 0-1.583-.71-1.583-1.583s.71-1.583 1.583-1.583H28.7c.483 0 .875-.392.875-.875s-.392-.875-.875-.875h-5.888c-1.838 0-3.333 1.495-3.333 3.333 0 1.025.475 1.932 1.205 2.544-.615.605-.998 1.445-.998 2.373 0 1.028.478 1.938 1.212 2.549-.611.604-.99 1.441-.99 2.367 0 1.12.559 2.108 1.409 2.713-.524.589-.852 1.356-.852 2.204 0 1.838 1.495 3.333 3.333 3.333h5.484c1.17 0 2.269-.625 2.867-1.632.247-.415.11-.952-.305-1.199-.416-.245-.953-.11-1.199.305-.285.479-.808.776-1.363.776h-5.484c-.873 0-1.583-.71-1.583-1.583s.71-1.583 1.583-1.583h6.506c1.17 0 2.27-.626 2.867-1.633.247-.416.11-.953-.305-1.199-.419-.251-.954-.11-1.199.305-.289.487-.799.777-1.363.777h-7.063c-.873 0-1.583-.711-1.583-1.584s.71-1.583 1.583-1.583h8.091c1.17 0 2.269-.625 2.867-1.632.247-.415.11-.952-.305-1.199-.417-.246-.953-.11-1.199.305-.289.486-.799.776-1.363.776H23.02c-.873 0-1.583-.71-1.583-1.583s.709-1.584 1.583-1.584z"/></svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#F4ABBA" d="M35.885 11.833c0-5.45-4.418-9.868-9.867-9.868-3.308 0-6.227 1.633-8.018 4.129-1.791-2.496-4.71-4.129-8.017-4.129-5.45 0-9.868 4.417-9.868 9.868 0 .772.098 1.52.266 2.241C1.751 22.587 11.216 31.568 18 34.034c6.783-2.466 16.249-11.447 17.617-19.959.17-.721.268-1.469.268-2.242z"/><path fill="#EA596E" d="M31.423 13.372c0-4.091-3.315-7.406-7.405-7.406-2.482 0-4.673 1.225-6.018 3.099-1.344-1.874-3.535-3.099-6.017-3.099-4.09 0-7.406 3.315-7.406 7.406 0 .579.074 1.141.199 1.681C5.805 21.442 12.908 28.184 18 30.034c5.091-1.851 12.195-8.592 13.223-14.98.127-.541.2-1.103.2-1.682z"/><path fill="#DD2E44" d="M27.191 14.831c0-2.801-2.27-5.072-5.07-5.072-1.7 0-3.2.839-4.121 2.123-.92-1.284-2.421-2.123-4.121-2.123-2.801 0-5.072 2.271-5.072 5.072 0 .397.05.781.136 1.151.705 4.376 5.569 8.992 9.056 10.259 3.485-1.268 8.352-5.884 9.055-10.259.088-.37.137-.755.137-1.151z"/></svg>

Before

Width:  |  Height:  |  Size: 955 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#BB1A34" d="M22 0l-4 8.028-5-5.018v7.024L3 8.028l8 8.028-11 6.02h12L6 34.118l12-8.028 11 10.035-3-14.049h10l-8-6.021 8-9.031-12 3.01L22 0z"/><path fill="#FCAB40" d="M22.914 12.924l1.86-.467L30 11.146l-3.381 3.816-1.319 1.49 1.59 1.195 2.925 2.202h-5.918l.473 2.218 1.551 7.26-5.845-5.332-1.056-.964-1.188.795-5.24 3.506 2.406-4.828 1.322-2.655H9.564l3.759-2.059 2.145-1.172-1.727-1.735-3.044-3.053 3.221.646 2.186.439V8.686l1.45 1.455 1.794 1.799 1.133-2.276 1.273-2.556"/><path fill="#F5F8FA" d="M21.512 14.301l.767-.193 2.158-.541-1.396 1.576-.545.615.656.493 1.208.909h-2.443l.195.916.641 2.997-2.413-2.201-.437-.398-.49.328-2.163 1.448.993-1.994.546-1.096H16l1.553-.85.885-.484-.713-.716-1.257-1.261 1.329.267.903.181v-1.745l.599.6.74.743.468-.939.525-1.056"/></svg>

Before

Width:  |  Height:  |  Size: 842 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#BB1A34" d="M1.728 21c-.617 0-.953-.256-1.127-.471-.171-.211-.348-.585-.225-1.165L3.104 6.658l-1.714.097h-.013c-.517 0-.892-.168-1.127-.459-.22-.272-.299-.621-.221-.98.15-.702.883-1.286 1.667-1.329l4.008-.227c.078-.005.15-.008.217-.008.147 0 .536 0 .783.306.252.312.167.709.139.839L3.719 19.454c-.187.884-.919 1.489-1.866 1.542L1.728 21zm10.743-2c-1.439 0-2.635-.539-3.459-1.559-1.163-1.439-1.467-3.651-.878-6.397 1.032-4.812 4.208-8.186 7.902-8.395 1.59-.089 2.906.452 3.793 1.549 1.163 1.439 1.467 3.651.878 6.397-1.032 4.81-4.208 8.184-7.904 8.394-.112.008-.223.011-.332.011zm3.414-13.746l-.137.004c-1.94.111-3.555 2.304-4.32 5.866-.478 2.228-.381 3.899.272 4.707.297.368.717.555 1.249.555l.14-.004c1.94-.109 3.554-2.301 4.318-5.864.478-2.228.382-3.9-.27-4.708-.296-.369-.718-.556-1.252-.556zm11.591 12.107c-1.439 0-2.637-.539-3.462-1.56-1.163-1.439-1.467-3.651-.878-6.397 1.033-4.813 4.209-8.186 7.903-8.394 1.603-.09 2.903.453 3.79 1.549 1.163 1.439 1.467 3.651.878 6.396-1.031 4.809-4.206 8.183-7.902 8.396-.112.008-.221.01-.329.01zm3.411-13.747l-.136.004c-1.941.111-3.556 2.304-4.32 5.865-.478 2.229-.381 3.901.272 4.708.297.368.719.555 1.251.555l.14-.004c1.939-.109 3.554-2.302 4.318-5.864.479-2.227.383-3.899-.27-4.707-.298-.37-.72-.557-1.255-.557zM11 35.001c-.81 0-1.572-.496-1.873-1.299-.388-1.034.136-2.187 1.17-2.575.337-.126 8.399-3.108 20.536-4.12 1.101-.096 2.067.727 2.159 1.827.092 1.101-.727 2.067-1.827 2.159-11.59.966-19.386 3.851-19.464 3.88-.23.086-.468.128-.701.128zM2.001 29c-.804 0-1.563-.488-1.868-1.283-.396-1.031.118-2.188 1.149-2.583.542-.209 13.516-5.126 32.612-6.131 1.113-.069 2.045.789 2.103 1.892.059 1.103-.789 2.045-1.892 2.103-18.423.97-31.261 5.821-31.389 5.87-.235.089-.477.132-.715.132z"/></svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CCD6DD" d="M31 2H5C3.343 2 2 3.343 2 5v26c0 1.657 1.343 3 3 3h26c1.657 0 3-1.343 3-3V5c0-1.657-1.343-3-3-3z"/><path fill="#E1E8ED" d="M31 1H5C2.791 1 1 2.791 1 5v26c0 2.209 1.791 4 4 4h26c2.209 0 4-1.791 4-4V5c0-2.209-1.791-4-4-4zm0 2c1.103 0 2 .897 2 2v4h-6V3h4zm-4 16h6v6h-6v-6zm0-2v-6h6v6h-6zM25 3v6h-6V3h6zm-6 8h6v6h-6v-6zm0 8h6v6h-6v-6zM17 3v6h-6V3h6zm-6 8h6v6h-6v-6zm0 8h6v6h-6v-6zM3 5c0-1.103.897-2 2-2h4v6H3V5zm0 6h6v6H3v-6zm0 8h6v6H3v-6zm2 14c-1.103 0-2-.897-2-2v-4h6v6H5zm6 0v-6h6v6h-6zm8 0v-6h6v6h-6zm12 0h-4v-6h6v4c0 1.103-.897 2-2 2z"/><path fill="#DD2E44" d="M4.998 33c-.32 0-.645-.076-.946-.239-.973-.523-1.336-1.736-.813-2.709l7-13c.299-.557.845-.939 1.47-1.031.626-.092 1.258.118 1.705.565l6.076 6.076 9.738-18.59c.512-.978 1.721-1.357 2.699-.843.979.512 1.356 1.721.844 2.7l-11 21c-.295.564-.841.953-1.47 1.05-.627.091-1.266-.113-1.716-.563l-6.1-6.099-5.724 10.631C6.4 32.619 5.71 33 4.998 33z"/></svg>

Before

Width:  |  Height:  |  Size: 993 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CCD6DD" d="M31 2H5C3.343 2 2 3.343 2 5v26c0 1.657 1.343 3 3 3h26c1.657 0 3-1.343 3-3V5c0-1.657-1.343-3-3-3z"/><path fill="#E1E8ED" d="M31 1H5C2.791 1 1 2.791 1 5v26c0 2.209 1.791 4 4 4h26c2.209 0 4-1.791 4-4V5c0-2.209-1.791-4-4-4zm0 2c1.103 0 2 .897 2 2v4h-6V3h4zm-4 16h6v6h-6v-6zm0-2v-6h6v6h-6zM25 3v6h-6V3h6zm-6 8h6v6h-6v-6zm0 8h6v6h-6v-6zM17 3v6h-6V3h6zm-6 8h6v6h-6v-6zm0 8h6v6h-6v-6zM3 5c0-1.103.897-2 2-2h4v6H3V5zm0 6h6v6H3v-6zm0 8h6v6H3v-6zm2 14c-1.103 0-2-.897-2-2v-4h6v6H5zm6 0v-6h6v6h-6zm8 0v-6h6v6h-6zm12 0h-4v-6h6v4c0 1.103-.897 2-2 2z"/><path fill="#3B94D9" d="M31.002 33c-.721 0-1.416-.39-1.774-1.072l-9.738-18.59-6.076 6.076c-.446.447-1.076.66-1.705.564-.626-.092-1.171-.474-1.47-1.03l-7-13c-.524-.973-.16-2.186.813-2.709.975-.523 2.186-.16 2.709.812l5.726 10.633 6.1-6.099c.45-.45 1.089-.659 1.716-.563.629.096 1.175.485 1.47 1.049l11 21c.513.979.135 2.187-.844 2.699-.297.157-.614.23-.927.23z"/></svg>

Before

Width:  |  Height:  |  Size: 990 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#292F33" d="M8 17H0v15c0 2.209 1.791 4 4 4s4-1.791 4-4c0 2.209 1.791 4 4 4h20c2.209 0 4-1.791 4-4V17H8z"/><path fill="#66757F" d="M32 10H12c-2.209 0-4 1.791-4 4 0-2.209-1.791-4-4-4s-4 1.791-4 4v15c0 2.209 1.791 4 4 4s4-1.791 4-4c0 2.209 1.791 4 4 4h20c2.209 0 4-1.791 4-4V14c0-2.209-1.791-4-4-4z"/><path fill="#C6E5B3" d="M21 16c0 1.104-.896 2-2 2h-7c-1.104 0-2-.896-2-2v-2c0-1.104.896-2 2-2h7c1.104 0 2 .896 2 2v2z"/><g fill="#CCD6DD"><circle cx="11.5" cy="21.5" r="1.5"/><circle cx="15.5" cy="21.5" r="1.5"/><circle cx="19.5" cy="21.5" r="1.5"/><circle cx="11.5" cy="25.5" r="1.5"/><circle cx="15.5" cy="25.5" r="1.5"/><circle cx="19.5" cy="25.5" r="1.5"/><circle cx="11.5" cy="29.5" r="1.5"/><circle cx="15.5" cy="29.5" r="1.5"/><circle cx="19.5" cy="29.5" r="1.5"/></g><path d="M34 21c0 .553-.447 1-1 1h-9c-.553 0-1-.447-1-1 0-.553.447-1 1-1h9c.553 0 1 .447 1 1zm0 3c0 .553-.447 1-1 1h-9c-.553 0-1-.447-1-1 0-.553.447-1 1-1h9c.553 0 1 .447 1 1zm0 3c0 .553-.447 1-1 1h-9c-.553 0-1-.447-1-1 0-.553.447-1 1-1h9c.553 0 1 .447 1 1zm0 3c0 .553-.447 1-1 1h-9c-.553 0-1-.447-1-1 0-.553.447-1 1-1h9c.553 0 1 .447 1 1z" fill="#99AAB5"/><circle fill="#CCD6DD" cx="25" cy="15" r="2"/><circle fill="#CCD6DD" cx="32" cy="15" r="2"/><path fill="#CCD6DD" d="M32 10H12V4c0-2.209 1.791-4 4-4h12c2.209 0 4 1.791 4 4v6z"/><path fill="#99AAB5" d="M30 4c0 .553-.447 1-1 1H15c-.553 0-1-.447-1-1 0-.553.447-1 1-1h14c.553 0 1 .447 1 1zm-8 3c0 .553-.447 1-1 1h-6c-.553 0-1-.447-1-1 0-.553.447-1 1-1h6c.553 0 1 .447 1 1z"/></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#F4900C" d="M35 19c0-2.062-.367-4.039-1.04-5.868-.46 5.389-3.333 8.157-6.335 6.868-2.812-1.208-.917-5.917-.777-8.164.236-3.809-.012-8.169-6.931-11.794 2.875 5.5.333 8.917-2.333 9.125-2.958.231-5.667-2.542-4.667-7.042-3.238 2.386-3.332 6.402-2.333 9 1.042 2.708-.042 4.958-2.583 5.208-2.84.28-4.418-3.041-2.963-8.333C2.52 10.965 1 14.805 1 19c0 9.389 7.611 17 17 17s17-7.611 17-17z"/><path fill="#FFCC4D" d="M28.394 23.999c.148 3.084-2.561 4.293-4.019 3.709-2.106-.843-1.541-2.291-2.083-5.291s-2.625-5.083-5.708-6c2.25 6.333-1.247 8.667-3.08 9.084-1.872.426-3.753-.001-3.968-4.007C7.352 23.668 6 26.676 6 30c0 .368.023.73.055 1.09C9.125 34.124 13.342 36 18 36s8.875-1.876 11.945-4.91c.032-.36.055-.722.055-1.09 0-2.187-.584-4.236-1.606-6.001z"/></svg>

Before

Width:  |  Height:  |  Size: 822 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#31373D" d="M36 32c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V4c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v28z"/><path fill="#E6E7E8" d="M30 28c0 1.104-.896 2-2 2H8c-1.104 0-2-.896-2-2V8c0-1.104.896-2 2-2h20c1.104 0 2 .896 2 2v20z"/></svg>

Before

Width:  |  Height:  |  Size: 311 B

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFCC4D" d="M36 18c0 9.941-8.059 18-18 18-9.94 0-18-8.059-18-18C0 8.06 8.06 0 18 0c9.941 0 18 8.06 18 18"/><path fill="#664500" d="M16 18c-.419 0-.809-.265-.949-.684C14.848 16.717 14.034 15 13 15c-1.062 0-1.888 1.827-2.051 2.316-.175.523-.738.808-1.265.632-.524-.174-.807-.741-.632-1.265C9.177 16.307 10.356 13 13 13s3.823 3.307 3.949 3.684c.175.524-.108 1.091-.632 1.265-.106.034-.213.051-.317.051zm10 0c-.419 0-.809-.265-.948-.684C24.849 16.717 24.033 15 23 15c-1.062 0-1.889 1.827-2.052 2.316-.175.523-.736.808-1.265.632-.523-.174-.807-.741-.632-1.265C19.177 16.307 20.355 13 23 13s3.823 3.307 3.948 3.684c.175.524-.108 1.091-.632 1.265-.105.034-.212.051-.316.051zm-8 4c-3.623 0-6.027-.422-9-1-.679-.131-2 0-2 2 0 4 4.595 9 11 9 6.404 0 11-5 11-9 0-2-1.321-2.132-2-2-2.973.578-5.377 1-9 1z"/><path fill="#FFF" d="M9 23s3 1 9 1 9-1 9-1-1.344 6.75-9 6.75S9 23 9 23z"/><path fill="#664500" d="M18 27.594c-3.596 0-6.272-.372-7.937-.745l-.825-1.871c.823.312 3.889.897 8.763.897 4.954 0 8.037-.616 8.864-.938l-.701 1.842c-1.634.38-4.419.815-8.164.815z"/></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFCC4D" d="M36 18c0 9.941-8.059 18-18 18-9.94 0-18-8.059-18-18C0 8.06 8.06 0 18 0c9.941 0 18 8.06 18 18"/><path fill="#664500" d="M28.457 17.797c-.06-.135-1.499-3.297-4.457-3.297-2.957 0-4.397 3.162-4.457 3.297-.092.207-.032.449.145.591.175.142.426.147.61.014.012-.009 1.262-.902 3.702-.902 2.426 0 3.674.881 3.702.901.088.066.194.099.298.099.11 0 .221-.037.312-.109.177-.142.238-.386.145-.594zm-12 0c-.06-.135-1.499-3.297-4.457-3.297-2.957 0-4.397 3.162-4.457 3.297-.092.207-.032.449.144.591.176.142.427.147.61.014.013-.009 1.262-.902 3.703-.902 2.426 0 3.674.881 3.702.901.088.066.194.099.298.099.11 0 .221-.037.312-.109.178-.142.237-.386.145-.594zM31 16c-.396 0-.772-.238-.929-.629-1.778-4.445-6.223-5.381-6.268-5.391-.541-.108-.893-.635-.784-1.177.108-.542.635-.891 1.177-.784.226.045 5.556 1.168 7.732 6.608.205.513-.045 1.095-.558 1.3-.12.05-.246.073-.37.073zM5 16c-.124 0-.249-.023-.371-.072-.513-.205-.762-.787-.557-1.3 2.176-5.44 7.506-6.563 7.732-6.608.543-.106 1.068.243 1.177.784.108.54-.242 1.066-.781 1.176-.185.038-4.506.98-6.271 5.391-.157.391-.533.629-.929.629zm13 6c-3.623 0-6.027-.422-9-1-.679-.131-2 0-2 2 0 4 4.595 9 11 9 6.404 0 11-5 11-9 0-2-1.321-2.132-2-2-2.973.578-5.377 1-9 1z"/><path fill="#FFF" d="M9 23s3 1 9 1 9-1 9-1-2 4-9 4-9-4-9-4z"/><path fill="#5DADEC" d="M10.847 28.229c-.68 2.677-3.4 4.295-6.077 3.615-2.676-.679-4.295-3.399-3.616-6.076.679-2.677 6.337-8.708 7.307-8.462.97.247 3.065 8.247 2.386 10.923zm14.286 0c.68 2.677 3.4 4.295 6.077 3.615 2.677-.679 4.296-3.399 3.616-6.076-.68-2.677-6.338-8.708-7.308-8.462-.968.247-3.064 8.247-2.385 10.923z"/></svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFCC4D" d="M36 18c0 9.941-8.059 18-18 18-9.94 0-18-8.059-18-18C0 8.06 8.06 0 18 0c9.941 0 18 8.06 18 18"/><path fill="#664500" d="M28.457 17.797c-.06-.135-1.499-3.297-4.457-3.297-2.957 0-4.397 3.162-4.457 3.297-.092.207-.032.449.145.591.175.142.426.147.61.014.012-.009 1.262-.902 3.702-.902 2.426 0 3.674.881 3.702.901.088.066.194.099.298.099.11 0 .221-.037.312-.109.177-.142.238-.386.145-.594zm-12 0c-.06-.135-1.499-3.297-4.457-3.297-2.957 0-4.397 3.162-4.457 3.297-.092.207-.032.449.144.591.176.142.427.147.61.014.013-.009 1.262-.902 3.703-.902 2.426 0 3.674.881 3.702.901.088.066.194.099.298.099.11 0 .221-.037.312-.109.178-.142.237-.386.145-.594zM18 22c-3.623 0-6.027-.422-9-1-.679-.131-2 0-2 2 0 4 4.595 9 11 9 6.404 0 11-5 11-9 0-2-1.321-2.132-2-2-2.973.578-5.377 1-9 1z"/><path fill="#FFF" d="M9 23s3 1 9 1 9-1 9-1-2 4-9 4-9-4-9-4z"/></svg>

Before

Width:  |  Height:  |  Size: 920 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFCC4D" d="M36 18c0 9.941-8.059 18-18 18-9.94 0-18-8.059-18-18C0 8.06 8.06 0 18 0c9.941 0 18 8.06 18 18"/><path fill="#664500" d="M28.457 17.797c-.06-.135-1.499-3.297-4.457-3.297-2.957 0-4.397 3.162-4.457 3.297-.092.207-.032.449.145.591.175.142.426.147.61.014.012-.009 1.262-.902 3.702-.902 2.426 0 3.674.881 3.702.901.088.066.194.099.298.099.11 0 .221-.037.312-.109.177-.142.238-.386.145-.594zm-12 0c-.06-.135-1.499-3.297-4.457-3.297-2.957 0-4.397 3.162-4.457 3.297-.092.207-.032.449.144.591.176.142.427.147.61.014.013-.009 1.262-.902 3.703-.902 2.426 0 3.674.881 3.702.901.088.066.194.099.298.099.11 0 .221-.037.312-.109.178-.142.237-.386.145-.594zM18 22c-3.623 0-6.027-.422-9-1-.679-.131-2 0-2 2 0 4 4.595 9 11 9 6.404 0 11-5 11-9 0-2-1.321-2.132-2-2-2.973.578-5.377 1-9 1z"/><path fill="#FFF" d="M9 23s3 1 9 1 9-1 9-1-2 4-9 4-9-4-9-4z"/><path fill="#5DADEC" d="M35 11c0 2.762-2.238 5-5 5s-5-2.238-5-5 4-10 5-10 5 7.238 5 10z"/></svg>

Before

Width:  |  Height:  |  Size: 1010 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFCC4D" d="M36 18c0 9.941-8.059 18-18 18-9.94 0-18-8.059-18-18C0 8.06 8.06 0 18 0c9.941 0 18 8.06 18 18"/><path fill="#664500" d="M18 22c-3.623 0-6.027-.422-9-1-.679-.131-2 0-2 2 0 4 4.595 9 11 9 6.404 0 11-5 11-9 0-2-1.321-2.132-2-2-2.973.578-5.377 1-9 1z"/><path fill="#FFF" d="M9 23s3 1 9 1 9-1 9-1-2 4-9 4-9-4-9-4z"/><path fill="#664500" d="M6.001 20c-.304 0-.604-.138-.801-.4-.332-.441-.242-1.068.2-1.399.143-.107 2.951-2.183 6.856-2.933C9.781 14.027 7.034 14 6.999 14c-.552-.002-.999-.45-.998-1.002 0-.551.447-.998.999-.998.221 0 5.452.038 8.707 3.293.286.286.372.716.217 1.09-.155.374-.52.617-.924.617-4.613 0-8.363 2.772-8.4 2.8-.18.135-.391.2-.599.2zm23.998-.001c-.208 0-.418-.064-.598-.198C29.363 19.772 25.59 17 21 17c-.404 0-.77-.243-.924-.617-.155-.374-.069-.804.217-1.09C23.549 12.038 28.779 12 29 12c.552 0 .998.447.999.998.001.552-.446 1-.997 1.002-.036 0-2.783.027-5.258 1.268 3.905.75 6.713 2.825 6.855 2.933.441.331.531.956.201 1.398-.196.261-.496.4-.801.4z"/></svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#FFCC4D" cx="18" cy="18" r="18"/><path fill="#664500" d="M27.335 22.629c-.178-.161-.444-.171-.635-.029-.039.029-3.922 2.9-8.7 2.9-4.766 0-8.662-2.871-8.7-2.9-.191-.142-.457-.13-.635.029-.177.16-.217.424-.094.628C8.7 23.472 11.788 28.5 18 28.5s9.301-5.028 9.429-5.243c.123-.205.084-.468-.094-.628zM26 19c-.419 0-.809-.265-.948-.684C24.849 17.717 24.033 16 23 16c-1.062 0-1.889 1.827-2.052 2.316-.175.523-.736.808-1.265.632-.523-.174-.807-.74-.632-1.265C19.177 17.307 20.355 14 23 14s3.823 3.307 3.948 3.684c.175.524-.108 1.091-.632 1.265-.105.034-.212.051-.316.051zm-10 0c-.419 0-.809-.265-.949-.684C14.848 17.717 14.034 16 13 16c-1.062 0-1.888 1.827-2.051 2.316-.175.523-.738.808-1.265.632-.524-.174-.807-.74-.632-1.265C9.177 17.307 10.355 14 13 14s3.823 3.307 3.949 3.684c.175.524-.108 1.091-.632 1.265-.106.034-.213.051-.317.051z"/><path fill="#FFAC33" d="M33.175 8.316s-9.042.161-15.175.161c-3.905 0-15.206-.118-15.206-.118l-.521.876c3.043 1.856 9.064 2.917 15.727 2.917 6.596 0 12.576-1.04 15.652-2.86l.078-.047s-.374-.664-.555-.929z"/><path fill="#5DADEC" d="M23.777.345c-1.212-.094-2.473-.159-3.773-.19C19.343.139 18.676.129 18 .129c-.672 0-1.336.01-1.993.025-1.302.031-2.564.096-3.777.19C5.34.88.169 2.451.169 5.287c0 3.588 8.264 5.771 17.831 5.771s17.831-2.183 17.831-5.771c0-2.835-5.168-4.405-12.054-4.942zM18 7.383c-6.861 0-12.91-.833-12.91-2.736 0-.536.494-1.023 1.339-1.449 1.153-.581 2.978-1.044 5.189-1.349 1.911-.262 4.098-.41 6.382-.41 2.291 0 4.485.148 6.4.413 2.242.31 4.086.783 5.232 1.377.807.418 1.278.894 1.278 1.418 0 1.903-6.049 2.736-12.91 2.736z"/><path fill="#3B94D9" d="M24.4 1.853c2.242.31 4.086.783 5.232 1.377l.062.017c-2.285-1.674-4.57-2.56-5.917-2.902-1.212-.094-2.473-.159-3.773-.19l.018.007L24.4 1.853zM6.429 3.199c1.153-.581 2.978-1.044 5.189-1.349L15.984.162l.023-.008c-1.302.031-2.564.096-3.777.19-1.347.342-3.633 1.227-5.919 2.902l.118-.047z"/><path fill="#FFCC4D" d="M28.472 3.375c-.66-.443-1.346-.91-2.001-1.26C23.947.765 21.063 0 18 0c-2.929 0-5.695.7-8.14 1.941-1.089.553-1.881.999-2.17 1.434h20.782z"/></svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFCC4D" d="M36 18c0 9.941-8.059 18-18 18S0 27.941 0 18 8.059 0 18 0s18 8.059 18 18"/><path fill="#664500" d="M24.327 23.622c-.153-.132-.368-.159-.551-.069l-4 2c-1.871.935-6.727.947-6.776.947-.276 0-.5.224-.5.5 0 .185.101.347.25.433v.001h.001v.001c.071.04.153.063.24.065h7.008c2.658 0 4.089-2.185 4.475-3.342.064-.192.006-.403-.147-.536zM31.001 16c-.305 0-.604-.138-.801-.4-2.641-3.521-6.061-3.599-6.206-3.6-.55-.006-.994-.456-.991-1.005.003-.551.447-.995.997-.995.184 0 4.537.05 7.8 4.4.332.442.242 1.069-.2 1.4-.18.135-.39.2-.599.2zM4.999 16c-.208 0-.419-.065-.599-.2-.442-.331-.531-.958-.2-1.4C7.462 10.05 11.816 10 12 10c.552 0 1 .448 1 1 0 .551-.445.998-.996 1-.156.002-3.569.086-6.205 3.6-.195.262-.496.4-.8.4zm10.898 1.396c.023-.052.059-.096.073-.154.134-.536-.192-1.079-.727-1.213-.18-.045-4.467-1.08-7.797 1.138-.459.306-.583.927-.277 1.387.192.29.509.446.832.446.19 0 .383-.055.554-.168 1.092-.729 2.362-.995 3.468-1.061-.009.076-.023.151-.023.229 0 1.104.896 2 2 2s2-.896 2-2c0-.212-.042-.412-.103-.604zm11.999-.001c.023-.052.059-.095.073-.152.135-.536-.191-1.079-.727-1.213-.18-.045-4.466-1.08-7.797 1.138-.46.306-.584.927-.277 1.387.192.289.51.445.833.445.19 0 .383-.055.554-.168 1.092-.729 2.361-.994 3.469-1.06-.009.076-.024.15-.024.228 0 1.104.896 2 2 2s2-.896 2-2c0-.212-.042-.413-.104-.605z"/></svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFCC4D" d="M36 18c0 9.941-8.059 18-18 18-9.94 0-18-8.059-18-18C0 8.06 8.06 0 18 0c9.941 0 18 8.06 18 18"/><ellipse fill="#66471B" cx="11.5" cy="14.5" rx="2.5" ry="3.5"/><ellipse fill="#66471B" cx="24.5" cy="14.5" rx="2.5" ry="3.5"/><path fill="#66471B" d="M7 21.262c0 3.964 4.596 9 11 9s11-5 11-9c0 0-10.333 2.756-22 0z"/><path fill="#E8596E" d="M18.545 23.604l-1.091-.005c-3.216-.074-5.454-.596-5.454-.596v6.961c0 3 2 6 6 6s6-3 6-6v-6.92c-1.922.394-3.787.542-5.455.56z"/><path fill="#DD2F45" d="M18 31.843c.301 0 .545-.244.545-.545v-7.694l-1.091-.005v7.699c.001.301.245.545.546.545z"/></svg>

Before

Width:  |  Height:  |  Size: 665 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFCC4D" d="M36 18c0 9.941-8.059 18-18 18-9.94 0-18-8.059-18-18C0 8.06 8.06 0 18 0c9.941 0 18 8.06 18 18"/><ellipse fill="#664500" cx="12" cy="13.5" rx="2.5" ry="3.5"/><ellipse fill="#664500" cx="24" cy="13.5" rx="2.5" ry="3.5"/><path fill="#FFF" d="M25 21c2.209 0 4 1.791 4 4s-1.791 4-4 4H11c-2.209 0-4-1.791-4-4s1.791-4 4-4h14z"/><path fill="#664500" d="M25 20H11c-2.757 0-5 2.243-5 5s2.243 5 5 5h14c2.757 0 5-2.243 5-5s-2.243-5-5-5zm0 2c1.483 0 2.71 1.084 2.949 2.5H24.5V22h.5zm-1.5 0v2.5h-3V22h3zm-4 0v2.5h-3V22h3zm-4 0v2.5h-3V22h3zM11 22h.5v2.5H8.051C8.29 23.084 9.517 22 11 22zm0 6c-1.483 0-2.71-1.084-2.949-2.5H11.5V28H11zm1.5 0v-2.5h3V28h-3zm4 0v-2.5h3V28h-3zm4 0v-2.5h3V28h-3zm4.5 0h-.5v-2.5h3.449C27.71 26.916 26.483 28 25 28z"/></svg>

Before

Width:  |  Height:  |  Size: 817 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFCC4D" d="M36 18c0 9.941-8.059 18-18 18S0 27.941 0 18 8.059 0 18 0s18 8.059 18 18"/><ellipse fill="#664500" cx="18" cy="25" rx="4" ry="5"/><ellipse fill="#664500" cx="12" cy="13.5" rx="2.5" ry="3.5"/><ellipse fill="#664500" cx="24" cy="13.5" rx="2.5" ry="3.5"/></svg>

Before

Width:  |  Height:  |  Size: 341 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFCC4D" d="M36 18c0 9.941-8.059 18-18 18-9.94 0-18-8.059-18-18C0 8.06 8.06 0 18 0c9.941 0 18 8.06 18 18"/><circle fill="#FF7892" cx="29" cy="23" r="5"/><circle fill="#FF7892" cx="7" cy="23" r="5"/><circle fill="#F5F8FA" cx="24.5" cy="16.5" r="5.5"/><circle fill="#F5F8FA" cx="11.5" cy="16.5" r="5.5"/><circle fill="#292F33" cx="11.5" cy="16.5" r="2.5"/><circle fill="#292F33" cx="24.5" cy="16.5" r="2.5"/><path fill="#664500" d="M22 30h-8c-.552 0-1-.447-1-1s.448-1 1-1h8c.553 0 1 .447 1 1s-.447 1-1 1zm8.001-19c-.305 0-.604-.138-.801-.4-2.64-3.521-6.061-3.598-6.206-3.6-.55-.006-.994-.456-.991-1.005C22.006 5.444 22.45 5 23 5c.184 0 4.537.05 7.8 4.4.332.442.242 1.069-.2 1.4-.18.135-.39.2-.599.2zM5.999 11c-.208 0-.419-.065-.599-.2-.442-.331-.531-.958-.2-1.4C8.462 5.05 12.816 5 13 5c.552 0 1 .448 1 1 0 .551-.445.998-.996 1-.155.002-3.568.086-6.204 3.6-.196.262-.497.4-.801.4z"/></svg>

Before

Width:  |  Height:  |  Size: 959 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#FFCC4D" cx="18" cy="18" r="18"/><path fill="#664500" d="M10.515 23.621C10.56 23.8 11.683 28 18 28c6.318 0 7.44-4.2 7.485-4.379.055-.217-.043-.442-.237-.554-.195-.111-.439-.078-.6.077C24.629 23.163 22.694 25 18 25s-6.63-1.837-6.648-1.855C11.256 23.05 11.128 23 11 23c-.084 0-.169.021-.246.064-.196.112-.294.339-.239.557z"/><ellipse fill="#664500" cx="12" cy="13.5" rx="2.5" ry="3.5"/><ellipse fill="#664500" cx="24" cy="13.5" rx="2.5" ry="3.5"/></svg>

Before

Width:  |  Height:  |  Size: 525 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#FFCB4C" cx="18" cy="17.018" r="17"/><path fill="#65471B" d="M14.524 21.036c-.145-.116-.258-.274-.312-.464-.134-.46.13-.918.59-1.021 4.528-1.021 7.577 1.363 7.706 1.465.384.306.459.845.173 1.205-.286.358-.828.401-1.211.097-.11-.084-2.523-1.923-6.182-1.098-.274.061-.554-.016-.764-.184z"/><ellipse fill="#65471B" cx="13.119" cy="11.174" rx="2.125" ry="2.656"/><ellipse fill="#65471B" cx="24.375" cy="12.236" rx="2.125" ry="2.656"/><path fill="#F19020" d="M17.276 35.149s1.265-.411 1.429-1.352c.173-.972-.624-1.167-.624-1.167s1.041-.208 1.172-1.376c.123-1.101-.861-1.363-.861-1.363s.97-.4 1.016-1.539c.038-.959-.995-1.428-.995-1.428s5.038-1.221 5.556-1.341c.516-.12 1.32-.615 1.069-1.694-.249-1.08-1.204-1.118-1.697-1.003-.494.115-6.744 1.566-8.9 2.068l-1.439.334c-.54.127-.785-.11-.404-.512.508-.536.833-1.129.946-2.113.119-1.035-.232-2.313-.433-2.809-.374-.921-1.005-1.649-1.734-1.899-1.137-.39-1.945.321-1.542 1.561.604 1.854.208 3.375-.833 4.293-2.449 2.157-3.588 3.695-2.83 6.973.828 3.575 4.377 5.876 7.952 5.048l3.152-.681z"/><path fill="#65471B" d="M9.296 6.351c-.164-.088-.303-.224-.391-.399-.216-.428-.04-.927.393-1.112 4.266-1.831 7.699-.043 7.843.034.433.231.608.747.391 1.154-.216.405-.74.546-1.173.318-.123-.063-2.832-1.432-6.278.047-.257.109-.547.085-.785-.042zm12.135 3.75c-.156-.098-.286-.243-.362-.424-.187-.442.023-.927.468-1.084 4.381-1.536 7.685.48 7.823.567.415.26.555.787.312 1.178-.242.39-.776.495-1.191.238-.12-.072-2.727-1.621-6.267-.379-.266.091-.553.046-.783-.096z"/></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFCB4C" d="M35.597 14.232c2.083 9.72-4.108 19.289-13.828 21.372C12.049 37.687 2.48 31.496.397 21.776-1.686 12.056 4.506 2.487 14.225.404c9.72-2.084 19.289 4.108 21.372 13.828"/><path fill="#F4F7F9" d="M29.284 9.012c.779 3.636-1.537 7.216-5.173 7.995-3.636.779-7.216-1.537-7.996-5.173-.779-3.636 1.537-7.216 5.173-7.995s7.217 1.536 7.996 5.173z"/><circle fill="#292F33" cx="22.306" cy="9.291" r="2.037"/><path fill="#F4F7F9" d="M14.088 14.282c.456 2.126-.899 4.219-3.025 4.675s-4.219-.899-4.675-3.025c-.456-2.126.899-4.219 3.025-4.675s4.219.899 4.675 3.025z"/><ellipse transform="rotate(-12.095 10.236 15.853)" fill="#292F33" cx="10.238" cy="15.857" rx="1.942" ry="1.942"/><path fill="#65471B" d="M18.625 20.937c-3.543.759-5.981.85-9.01.908-.691.015-1.955.419-1.536 2.375.838 3.911 6.379 7.837 12.642 6.495 6.262-1.342 9.708-7.194 8.87-11.105-.419-1.956-1.739-1.808-2.375-1.536-2.786 1.187-5.048 2.104-8.591 2.863z"/><path fill="#E8596E" d="M11 24.004v6c0 3 2 6 6 6s6-3 6-6v-6H11z"/><path fill="#DD2F45" d="M17 31.883c.301 0 .545-.244.545-.545v-6.295h-1.091v6.295c.001.301.245.545.546.545z"/><path fill="#FFF" d="M10.034 23.801s3.143.349 9.01-.908c5.867-1.257 8.591-2.864 8.591-2.864s-1.117 4.33-7.962 5.797c-6.845 1.467-9.639-2.025-9.639-2.025z"/></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFCB4C" d="M35 18.619c0-3.794-3.075-6.869-6.869-6.869-.979 0-2.752.578-2.752.578l-13.126 1.384s-2.717-1.581-4.383-1.581C4.075 12.131 1 15.206 1 19c0 .237.012.471.035.702C1.406 28.763 8.849 36 18 36c9.389 0 17-7.611 17-17 0-.052-.009-.101-.012-.153.003-.076.012-.151.012-.228z"/><path fill="#F19020" d="M30.126 13.751c-.941-.244-1.009.386-2.202.246-1.168-.137.429-.739-.195-1.092-.21-.119-.511-.144-.882-.098-1.052.129-16.954.544-17.547.83-.527.254-.839.548-1.318.101-.603-.562-1.466-.238-1.716-.051-.322.242-.389.722.234 1.277.621.42 1.673.859 3.465 1.159.197.033.365.046.522.052 1.227.041 1.397-1.67 3.13-1.716 1.136-.03 11.153 1.07 11.978.958.101-.014.207-.024.329-.024 1.563 0 1.926 1.45 3.589.316.705-.573 1.811-1.648.613-1.958z"/><path fill="#F36C24" d="M5.938 9.115c1.523 1.527 2.604 3.145 3.362 4.523.566 1.029.956 1.929 1.187 2.538 1.227.041 1.397-.67 3.13-.716 1.136-.03 1.783.769 2.623 1.229 1.502.822 2.569-.73 3.719-.73.85 0 2.219 1.207 3.176.764 1.387-.643 1.635-1.191 2.46-1.304.322-.791.741-1.696 1.252-2.609.74-1.324 1.678-2.665 2.841-3.693H5.938z"/><path fill="#CE5C1F" d="M29.306 9.435c1.281-1.263-23.039.016-22.341.788.988 1.094 2.2 3.153 2.2 3.153s4.757 2.405 8.351-.626c2.5 1.5 6 .969 7.562-1.609 0 0 1.217.453 2.451.531 0 0 .953-1.425 1.777-2.237z"/><ellipse fill="#65471B" cx="18" cy="28.638" rx="4.332" ry="4.95"/><path fill="#65471B" d="M14 20.606c0 1.473-.896 2.667-2 2.667-1.105 0-2-1.194-2-2.667 0-1.473.895-2.667 2-2.667 1.104 0 2 1.194 2 2.667zm12-.001c0 1.473-.895 2.667-2 2.667s-2-1.194-2-2.667c0-1.472.896-2.667 2-2.667 1.105.001 2 1.195 2 2.667z"/><path fill="#CCD6DD" d="M31.125 3.725c-.24 0-.467.045-.686.109-.688-.845-1.723-1.396-2.898-1.396-.087 0-.169.02-.255.026-.734-.827-1.794-1.359-2.987-1.359-1.505 0-2.8.839-3.486 2.066-.346-.798-1.139-1.357-2.064-1.357-.718 0-1.349.342-1.761.865C16.48 1.209 15.1.147 13.458.147c-1.323 0-2.48.689-3.148 1.723-.184-.029-.368-.058-.56-.058-1.432 0-2.661.812-3.293 1.992-.203-.038-.41-.063-.624-.063-1.864 0-3.375 1.511-3.375 3.375s1.511 3.375 3.375 3.375c.588 0 1.135-.159 1.614-.425.376.282.838.456 1.345.456.145 0 .285-.016.422-.043.855 1.379 2.367 2.303 4.109 2.303 1.709 0 3.206-.885 4.073-2.217.72.882 1.802 1.457 3.029 1.457 1.815 0 3.327-1.238 3.776-2.911.034.001.065.01.099.01.283 0 .559-.031.826-.087.654.556 1.491.904 2.417.904 1.174 0 2.21-.551 2.897-1.396.219.064.446.109.686.109 1.36 0 2.463-1.103 2.463-2.463s-1.104-2.463-2.464-2.463z"/><circle fill="#E1E8ED" cx="27.795" cy="5.767" r="2.121"/><path fill="#E1E8ED" d="M19.876 5.903c0-1.193-.967-2.161-2.16-2.161-.368 0-.71.101-1.013.263-.251-.601-.844-1.024-1.537-1.024-.567 0-1.067.285-1.368.718-.67-.623-1.561-1.013-2.548-1.013-1.755 0-3.216 1.21-3.625 2.838-.365-.367-.87-.595-1.429-.595-1.111 0-2.012.901-2.012 2.012s.901 2.012 2.012 2.012c.703 0 1.319-.361 1.679-.907.517 1.081 1.529 1.873 2.749 2.079.39.67 1.107 1.125 1.938 1.125 1.074 0 1.969-.754 2.193-1.76.324.18.691.292 1.087.292 1.07 0 1.962-.749 2.19-1.75 1.042-.155 1.844-1.044 1.844-2.129z"/></svg>

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#BE1931" d="M19.598.326c9.613 0 12.243 1.697 12.243 11.311 0 5.506-1.167 8.488-1.167 13.488 0 2.958-4.551 3-8.659 3-4.218 0-9.142.199-11.341-2-6-6-10.545-16.449-2-19C9.129.614 9.984.326 19.598.326z"/><path fill="#99AAB5" d="M26.736 26c2.229 0 4.264.858 4.264 2.903v3.519C31 34.467 28.965 36 26.736 36H15V26h11.736z"/><path fill="#CCD6DD" d="M22.341 26c2.454 0 4.659.858 4.659 2.903v3.519C27 34.467 24.795 36 22.341 36h-7.333C12.553 36 11 34.467 11 32.422v-3.519C11 26.858 12.553 26 15.008 26h7.333z"/><path fill="#A0041E" d="M4.292 10.948c.715-.575 1.862-1.424 2.383 1.178 1 5 3.794 9.384 3 7-1-3-1-12-1-12-2.437.727-3.806 2.097-4.383 3.822z"/><path fill="#E1E8ED" d="M21.674 28c1.105 0 2.326.538 2.326 1.459v3.333c0 .92-1.221 1.208-2.326 1.208h-5C15.57 34 15 33.712 15 32.792v-3.333c0-.921.57-1.459 1.674-1.459h5z"/></svg>

Before

Width:  |  Height:  |  Size: 895 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#5C913B" d="M29.866 24.625c2.522-.841 5.884-4.203 5.884-5.884s-2.522-.841-1.681-3.362 1.681-5.043 0-6.724-3.362 0-5.043-1.681 0-3.362-1.681-5.043-4.203-.841-6.724 0S18.939.25 17.258.25s-5.043 3.362-5.884 5.884-2.521.84-3.361 3.362c-.78 2.341.177 4.823-1.972 9.748-1.026 1.621-1.995 3.178-2.899 4.543C-.836 29.792.449 35.552.449 35.552s5.76 1.285 11.765-2.693c1.365-.904 2.922-1.873 4.543-2.899 4.925-2.15 7.407-1.192 9.748-1.972 2.521-.841.84-2.522 3.361-3.363z"/><path fill="#679E44" d="M34.253 19.017c-.103-.312-.438-.483-.75-.379-3.21 1.054-5.749.677-7.001.349 2.811-2.865 5.337-5.842 7.222-8.589.186-.271.116-.641-.154-.827-.271-.187-.641-.116-.826.154-1.082 1.576-2.403 3.251-3.878 4.944.082-1.765-.065-4.516-1.327-7.238-.139-.298-.492-.427-.789-.289-.298.138-.428.491-.289.789 1.679 3.623 1.194 7.416 1.062 8.235-1.369 1.489-2.837 2.973-4.356 4.402.156-1.873.084-4.922-1.559-7.337-.183-.271-.552-.343-.825-.158-.271.185-.342.554-.157.826 1.957 2.879 1.347 7.003 1.178 7.925-2.44 2.2-4.953 4.211-7.33 5.836 1.535-2.474 3.146-6.37 2-10.845-.082-.318-.406-.511-.723-.428-.318.082-.51.405-.428.723 1.679 6.557-3.33 11.987-3.778 12.456-5.407 3.356-8.373 4.368-8.407 4.379-.311.104-.479.439-.375.751.083.249.314.407.563.407.062 0 .125-.01.187-.03.16-.054 3.996-1.354 11.056-6.036 1.365-.905 2.768-1.936 4.176-3.05.695.426 2.288 1.141 5.162 1.141.804 0 1.706-.057 2.717-.19.325-.043.554-.342.511-.667-.042-.325-.349-.555-.667-.511-3.704.492-5.777-.136-6.717-.581 1.974-1.619 3.937-3.396 5.799-5.235.617.218 1.922.586 3.735.586 1.299 0 2.854-.189 4.592-.761.309-.105.478-.441.376-.752z"/><path fill="#3E721D" d="M12.753 24.327c.456-.09 1.009-.182 1.61-.281 3.811-.633 7.752-1.288 7.752-3.729 0-1.241-.664-1.982-1.101-2.436.25-.076.59-.147.825-.198 1.07-.227 2.402-.51 2.983-1.69.359-.729.313-1.608-.143-2.635.416-.307 1.58-.678 2.308-.909 1.796-.572 3.493-1.113 3.959-2.504.163-.484.223-1.25-.409-2.144-.008-.011-.02-.035-.028-.05-.495-.084-.989-.284-1.484-.778-.313-.313-.509-.626-.632-.939.234.645.845 2.094 1.123 2.486 2.031 2.872-7.321 2.534-6.024 5.247 1.541 3.222-2.907 2.206-3.747 3.467-.841 1.261 1.121 1.401 1.121 3.082s-5.746 2.271-8.354 2.783C7.243 24.136.448 35.552.448 35.552s.508.11 1.363.165c2.052-3.324 7.257-10.666 10.942-11.39z"/><path fill="#77B255" d="M12.512 23.101c2.608-.512 8.354-1.102 8.354-2.783s-1.961-1.821-1.121-3.082c.841-1.261 5.288-.245 3.747-3.467-1.298-2.713 8.055-2.375 6.024-5.247-.322-.455-1.094-2.335-1.205-2.729-.363-1.287.321-2.574-.967-3.861-1.681-1.681-4.203-.841-6.724 0S18.939.25 17.258.25s-5.043 3.362-5.884 5.884-2.521.84-3.361 3.362c-.78 2.341.177 4.823-1.972 9.748-1.026 1.621-1.995 3.178-2.899 4.543C-.836 29.792.449 35.552.449 35.552s6.794-11.416 12.063-12.451z"/><path fill="#A6D388" d="M28.4 8.292c-2.723-1.262-5.475-1.409-7.24-1.326 1.693-1.476 3.367-2.797 4.944-3.878.271-.186.34-.556.154-.827-.186-.27-.556-.339-.826-.154-2.747 1.884-5.724 4.411-8.589 7.222-.329-1.253-.706-3.791.349-7.001.103-.312-.067-.648-.379-.75-.31-.103-.647.067-.75.379-1.366 4.158-.55 7.265-.176 8.328-1.839 1.862-3.616 3.824-5.235 5.799-.445-.94-1.071-3.013-.58-6.719.043-.325-.186-.624-.511-.667-.32-.043-.623.184-.667.51-.613 4.63.407 6.991.951 7.879-1.115 1.408-2.145 2.811-3.05 4.176C2.112 28.323.812 32.159.759 32.318c-.104.312.065.647.376.751.062.021.125.03.188.03.249 0 .481-.157.564-.406.011-.034 1.023-2.999 4.378-8.406.463-.446 5.882-5.465 12.456-3.778.314.079.642-.111.723-.429.081-.318-.11-.642-.429-.724-4.475-1.144-8.373.468-10.848 2.003 1.625-2.378 3.637-4.893 5.838-7.334.923-.169 5.047-.777 7.925 1.18.103.069.219.103.333.103.19 0 .378-.091.492-.26.185-.271.114-.641-.157-.826-2.416-1.642-5.465-1.714-7.338-1.558 1.428-1.518 2.912-2.986 4.401-4.355.814-.134 4.598-.625 8.236 1.061.081.038.166.056.25.056.224 0 .438-.128.539-.345.142-.298.012-.652-.286-.789z"/></svg>

Before

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36" xml:space="preserve"><path fill="#FFCC4D" d="M35 18c0 9.389-7.611 17-17 17-9.388 0-17-7.611-17-17C1 8.612 8.612 1 18 1c9.389 0 17 7.612 17 17"/><ellipse fill="#65471B" cx="18" cy="28" rx="4" ry="3"/><path fill="#F4F7F9" d="M27.899 14.557a4.5 4.5 0 1 1-8.8 1.885 4.5 4.5 0 0 1 8.8-1.885z"/><ellipse fill="#292F33" cx="23.5" cy="16.498" rx="2.5" ry="2.498"/><path fill="#65471B" d="M26.963 9.931a.999.999 0 0 1-.445-.105 7.949 7.949 0 0 0-5.295-.658 1 1 0 1 1-.426-1.954 9.932 9.932 0 0 1 6.613.822 1 1 0 0 1-.447 1.895zm-17.926 0a1 1 0 0 1-.447-1.895 9.94 9.94 0 0 1 6.613-.822 1 1 0 1 1-.426 1.954 7.949 7.949 0 0 0-5.295.658.999.999 0 0 1-.445.105z"/><path fill="#F19020" d="m13.995 13.645.324-.473s.708-1.032 1.739-.324c1.032.708.325 1.739.325 1.739l-.683.997c.168.128.332.259.491.389 0 0 .708-1.032 1.739-.324 1.032.708.325 1.739.325 1.739l-1.375 1.94c.138.184.363.289.476.477 0 0 .708-1.032 1.739-.325 1.033.708.325 1.74.325 1.74l-5.661 8.257a7.51 7.51 0 0 1-10.438 1.946 7.51 7.51 0 0 1-2.465-9.559c.589-1.17 1.034-2.407 1.451-3.648l1.054-3.131s.342-1.204 1.545-.863c1.203.342.862 1.545.862 1.545l-.913 4.568c.172.118.337.24.494.366l6.037-8.784s.708-1.032 1.739-.324.324 1.739.324 1.739l.546.313z"/><path fill="#F19020" d="m34.764 24.896.844-5.591a1.069 1.069 0 0 0-.897-1.217l-.124-.019a1.07 1.07 0 0 0-1.217.898l-.517 3.422-.004.014c-.202 1.295-1.305 1.219-1.72-.769-.012-.057-.031-.108-.046-.162l-1.552-7.69a.99.99 0 0 0-1.166-.775l-.278.056c-.536.108-.839.555-.731 1.091l1.32 6.783c.005.037.004.069.012.108.281 1.395-.395 1.22-.638-.305a1.388 1.388 0 0 0-.057-.218L26.69 14.29l-.083-.411c-.116-.574-.622-.969-1.196-.853l-.138.028a1.06 1.06 0 0 0-.83 1.25l1.408 6.978c.002.135.012.276.042.43.294 1.506-.581.77-1.107.047l-.001-.001-4.418-5.991a1.062 1.062 0 0 0-1.484-.224l-.114.084a1.06 1.06 0 0 0-.224 1.483l1.149 1.499 3.132 4.294c.009.015.014.03.024.045.935 1.383.882 1.957-.038.902l-3.4-4.612c-.074-.1-.17-.163-.268-.228a1.012 1.012 0 0 0-1.167.012l-.17.126a1.027 1.027 0 0 0-.217 1.435l2.743 3.719c.519.705.974 2.768 1.553 4.247.58 1.479 3.598 5.883 8.8 3.843 4.654-1.824 4.052-5.582 4.078-7.496z"/><g fill="#B55005"><path d="m13.997 13.667-5.515 8.399a.339.339 0 0 1-.471.098.34.34 0 0 1-.098-.471l5.515-8.399.569.373zm2.25 2.303-5.005 7.826a.34.34 0 0 1-.47.103.34.34 0 0 1-.104-.47l5.005-7.826.574.367zm1.209 3.721-3.711 5.9a.34.34 0 0 1-.47.107.341.341 0 0 1-.107-.47l3.711-5.9.577.363zm2.24-1.082 4.127 5.676a.341.341 0 0 1-.274.542.338.338 0 0 1-.275-.14l-4.127-5.676.549-.402zm7.662-4.455 1.608 7.821a.34.34 0 0 1-.667.137l-1.608-7.821.667-.137z"/><path d="M17.592 20.584c-.178-.242-.225-.611-.157-.906l-.679-.093c-.114.488-.009.999.287 1.403l1.315 1.782.408-.595-1.174-1.591z"/></g></svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#BE1931" cx="11" cy="31" r="3"/><path fill="#BE1931" d="M14 23c0 1.657-1.343 3-3 3s-3-1.343-3-3V4c0-1.657 1.343-3 3-3s3 1.343 3 3v19z"/><circle fill="#BE1931" cx="25" cy="31" r="3"/><path fill="#BE1931" d="M28 23c0 1.657-1.344 3-3 3s-3-1.343-3-3V4c0-1.657 1.344-3 3-3s3 1.343 3 3v19z"/></svg>

Before

Width:  |  Height:  |  Size: 366 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EF9645" d="M26.992 19.016c-.255-.255-.799-.611-1.44-.962l-1.911-2-2.113 2h-.58l-2.509-3.634c-1.379.01-2.497 1.136-2.487 2.515l-3.556-2.112c-.817.364-1.389 1.18-1.389 2.133v.96l-4 4.168.016 2.185 9.984 10.729S27.525 19.71 27.55 19.74c-.129-.223-.513-.702-.558-.724z"/><g fill="#FFDC5D"><path d="M25.552 5.81c0-1.107-.906-2.013-2.013-2.013-1.107 0-2.013.906-2.013 2.013v12.245h4.025V5.81zm-4.605 12.244V16.01c-.008-1.103-.909-1.991-2.012-1.983-1.103.008-1.991.909-1.983 2.012l.012 2.016h3.983zM8.916 16h.168c1.059 0 1.916.858 1.916 1.917v4.166C11 23.142 10.143 24 9.084 24h-.168C7.857 24 7 23.142 7 22.083v-4.166C7 16.858 7.857 16 8.916 16zm6.918 2.96l-.056.062C15.304 19.551 15 20.233 15 21c0 .063.013.123.018.185.044.678.308 1.292.728 1.774-.071.129-.163.243-.259.353-.366.417-.89.688-1.487.688-1.104 0-2-.896-2-2v-6c0-.441.147-.845.389-1.176.364-.497.947-.824 1.611-.824 1.104 0 2 .896 2 2v2.778c-.061.055-.109.123-.166.182z"/><path d="M9.062 25c1.024 0 1.925-.526 2.45-1.322.123.183.271.346.431.497 1.185 1.115 3.034 1.044 4.167-.086.152-.152.303-.305.419-.488l-.003-.003C16.727 23.713 17 24 18 24h2.537c-.37.279-.708.623-1.024 1-1.228 1.467-2.013 3.606-2.013 6 0 .276.224.5.5.5s.5-.224.5-.5c0-2.548.956-4.775 2.377-6 .732-.631 1.584-1 2.498-1 .713.079.847-1 .125-1H18c-1.104 0-2-.896-2-2s.896-2 2-2h8c.858 0 1.66.596 1.913 1.415L29 24c.103.335.479 1.871.411 2.191C29.411 31 24.715 36 19 36c-6.537 0-11.844-5.231-11.986-11.734l.014.01c.515.445 1.176.724 1.91.724h.124z"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#77B255" d="M36 32c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V4c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v28z"/><path fill="#FFF" d="M29.28 6.362c-1.156-.751-2.704-.422-3.458.736L14.936 23.877l-5.029-4.65c-1.014-.938-2.596-.875-3.533.138-.937 1.014-.875 2.596.139 3.533l7.209 6.666c.48.445 1.09.665 1.696.665.673 0 1.534-.282 2.099-1.139.332-.506 12.5-19.27 12.5-19.27.751-1.159.421-2.707-.737-3.458z"/></svg>

Before

Width:  |  Height:  |  Size: 482 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DD2E44" d="M35.885 11.833c0-5.45-4.418-9.868-9.867-9.868-3.308 0-6.227 1.633-8.018 4.129-1.791-2.496-4.71-4.129-8.017-4.129-5.45 0-9.868 4.417-9.868 9.868 0 .772.098 1.52.266 2.241C1.751 22.587 11.216 31.568 18 34.034c6.783-2.466 16.249-11.447 17.617-19.959.17-.721.268-1.469.268-2.242z"/></svg>

Before

Width:  |  Height:  |  Size: 368 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 415 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Some files were not shown because too many files have changed in this diff Show More