diff --git a/chat/package.json b/chat/package.json index b83d3f6b6..8a0c14e79 100644 --- a/chat/package.json +++ b/chat/package.json @@ -1,11 +1,13 @@ { "name": "chat", - "version": "0.0.24", + "version": "0.1.10", "main": "./src/index.tsx", "license": "MIT", "dependencies": { "@types/humanize-duration": "^3.27.1", + "@types/lodash.clonedeep": "^4.5.7", "@types/lodash.debounce": "^4.0.7", + "@types/lodash.throttle": "^4.1.7", "@types/lozad": "^1.16.1", "@types/react": "^18.0.20", "@types/react-dom": "^18.0.6", @@ -15,7 +17,9 @@ "dotenv": "^16.0.2", "esbuild": "^0.15.7", "humanize-duration": "^3.27.3", + "lodash.clonedeep": "^4.5.0", "lodash.debounce": "^4.0.8", + "lodash.throttle": "^4.1.1", "lozad": "^1.16.0", "react": "^18.2.0", "react-dnd": "^16.0.1", diff --git a/chat/src/App.css b/chat/src/App.css index 83fa2025a..378fbaebe 100644 --- a/chat/src/App.css +++ b/chat/src/App.css @@ -1,5 +1,6 @@ html, body { + overflow: hidden; overscroll-behavior-y: none; } @@ -9,6 +10,8 @@ html { body { min-height: 100vh; + min-height: calc(var(--vh, 1vh) * 100); + overflow: hidden; /* mobile viewport bug fix */ min-height: -webkit-fill-available; } @@ -25,8 +28,8 @@ body { overflow: hidden; display: flex; flex-direction: column; - margin: 0 auto; - max-width: 1000px; + justify-content: center; + margin: 0 2rem; } .App-heading { @@ -37,6 +40,7 @@ body { .App-heading small { opacity: 0.2; + font-size: 10px; } .App-side { @@ -50,6 +54,7 @@ body { position: relative; flex: 3; height: 62vh; + height: calc(var(--vh, 1vh) * 72); max-height: 1000px; overflow: auto; -ms-overflow-style: none; @@ -94,6 +99,10 @@ body { /* On mobile, hide the sidebar and make the input full-width. */ @media screen and (max-width: 1100px) { + .App-wrapper { + margin: 0 auto; + } + .App-heading { padding: 0 1rem; } @@ -112,7 +121,7 @@ body { } .App-content__reduced { - height: 58vh; + height: calc(var(--vh, 1vh) * 65); } } @@ -122,4 +131,9 @@ lite-youtube { .btn-secondary { border: none !important; +} + +.btn-secondary:focus { + border: none !important; + box-shadow: none !important; } \ No newline at end of file diff --git a/chat/src/App.tsx b/chat/src/App.tsx index 918c93a21..4e682770a 100644 --- a/chat/src/App.tsx +++ b/chat/src/App.tsx @@ -2,6 +2,7 @@ import React, { useEffect, useRef } from "react"; import { DndProvider, useDrop } from "react-dnd"; import { HTML5Backend } from "react-dnd-html5-backend"; import cx from "classnames"; +import throttle from "lodash.throttle"; import { ChatHeading, ChatMessageList, @@ -14,6 +15,7 @@ import { ChatProvider, DrawerProvider, useChat, useDrawer } from "./hooks"; import "./App.css"; const SCROLL_CANCEL_THRESHOLD = 500; +const WINDOW_RESIZE_THROTTLE_WAIT = 250; export function App() { return ( @@ -36,6 +38,26 @@ function AppInner() { const initiallyScrolledDown = useRef(false); const { messages, quote } = useChat(); + // See: https://css-tricks.com/the-trick-to-viewport-units-on-mobile/ + useEffect(() => { + const updateViewportHeightUnit = () => { + const vh = window.innerHeight * 0.01; + document.documentElement.style.setProperty("--vh", `${vh}px`); + }; + const throttledResizeHandler = throttle( + updateViewportHeightUnit, + WINDOW_RESIZE_THROTTLE_WAIT + ); + + throttledResizeHandler(); + + window.addEventListener("resize", throttledResizeHandler); + + return () => { + window.removeEventListener("resize", throttledResizeHandler); + }; + }, []); + useEffect(() => { if (messages.length > 0) { if (initiallyScrolledDown.current) { @@ -95,7 +117,7 @@ function AppInner() {
{quote && (
- {quote && } +
)} diff --git a/chat/src/features/chat/ChatMessage.css b/chat/src/features/chat/ChatMessage.css index 066c0d88a..45018a700 100644 --- a/chat/src/features/chat/ChatMessage.css +++ b/chat/src/features/chat/ChatMessage.css @@ -1,17 +1,11 @@ -@keyframes fading-in { - from { - opacity: 0; - } - to { - opacity: 1; - } -} - .ChatMessage { position: relative; - animation: fading-in 0.3s ease-in-out forwards; - padding: 1rem; - padding-right: 3rem; + padding-right: 1.5rem; + min-height: 28px; +} + +.ChatMessage p { + margin: 0; } .ChatMessage .btn { @@ -25,6 +19,8 @@ .ChatMessage-timestamp { margin-left: 0.5rem; + opacity: 0.5; + font-size: 10px; } .ChatMessage-bottom { @@ -41,20 +37,78 @@ } .ChatMessage-button { - background: transparent !important; + margin: 0 0.5rem; } -.ChatMessage-button__confirmed i { +.ChatMessage-button i { + margin-right: 0.5rem; +} + +.ChatMessage-button__confirmed { color: red !important; } -.ChatMessage-delete { +.ChatMessage-quoted-link { + padding-left: 2rem; +} + +.ChatMessage-actions-button { position: absolute; - top: 4px; - right: 4px; + top: 0; + right: 0; + cursor: pointer; + z-index: 5; + background: none !important; + border: none !important; + box-shadow: none !important; + display: flex; + align-items: center; +} + +.ChatMessage-actions-button button { + background: none !important; + border: none !important; + padding: 0 !important; +} + +.ChatMessage-actions-button button i { + position: relative; + top: 3px; + margin-right: 1rem; +} + +.ChatMessage-actions { + z-index: 1; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: rgba(20, 20, 20, 0.85); + display: flex; + align-items: center; + justify-content: flex-end; + padding: 1rem; + padding-right: 3rem; + animation: fading-in 0.3s ease-in-out forwards; +} + +.ChatMessage-actions button { + font-size: 10px; + background: none !important; } /* List */ .ChatMessageList { flex: 1; -} \ No newline at end of file +} + +.ChatMessageList-group { + margin-bottom: 1rem; + padding: 0.3rem; + border-radius: 8px; +} + +.ChatMessageList-group:nth-child(even) { + background: rgba(255, 255, 255, 0.025); +} diff --git a/chat/src/features/chat/ChatMessage.tsx b/chat/src/features/chat/ChatMessage.tsx index 6c985d0b2..334fecc44 100644 --- a/chat/src/features/chat/ChatMessage.tsx +++ b/chat/src/features/chat/ChatMessage.tsx @@ -1,12 +1,15 @@ import React, { useCallback, useEffect, + useLayoutEffect, useMemo, + useRef, useState, } from "react"; import cx from "classnames"; import key from "weak-key"; import humanizeDuration from "humanize-duration"; +import cloneDeep from "lodash.clonedeep"; import { Username } from "./Username"; import { useChat, useRootContext } from "../../hooks"; import { QuotedMessageLink } from "./QuotedMessageLink"; @@ -16,6 +19,8 @@ interface ChatMessageProps { message: IChatMessage; timestampUpdates: number; showUser?: boolean; + actionsOpen: boolean; + onToggleActions(messageId: string): void; } const TIMESTAMP_UPDATE_INTERVAL = 20000; @@ -24,6 +29,8 @@ export function ChatMessage({ message, showUser = true, timestampUpdates, + actionsOpen, + onToggleActions, }: ChatMessageProps) { const { id, @@ -38,19 +45,25 @@ export function ChatMessage({ quotes, } = message; const { - username: loggedInUsername, + id: userId, + username: userUsername, admin, censored, themeColor, } = useRootContext(); const { messageLookup, deleteMessage, quoteMessage } = useChat(); + const [confirmedDelete, setConfirmedDelete] = useState(false); const quotedMessage = messageLookup[quotes]; const content = censored ? text_censored : text_html; - const hasMention = content.includes(loggedInUsername); - const mentionStyle = hasMention - ? { backgroundColor: `#${themeColor}55` } - : {}; - const [confirmedDelete, setConfirmedDelete] = useState(false); + const isMention = + quotedMessage?.username === userUsername || + (text_html.includes(`/id/${userId}`) && + userUsername && + username !== userUsername); + const timestamp = useMemo( + () => formatTimeAgo(time), + [time, timestampUpdates] + ); const handleDeleteMessage = useCallback(() => { if (confirmedDelete) { deleteMessage(text); @@ -58,13 +71,76 @@ export function ChatMessage({ setConfirmedDelete(true); } }, [text, confirmedDelete]); - const timestamp = useMemo( - () => formatTimeAgo(time), - [time, timestampUpdates] - ); + const handleQuoteMessageAction = useCallback(() => { + quoteMessage(message); + onToggleActions(message.id); + }, [message, onToggleActions]); + + useEffect(() => { + if (!actionsOpen) { + setConfirmedDelete(false); + } + }, [actionsOpen]); return ( -
+
+ {!actionsOpen && ( +
+ + +
+ )} + {actionsOpen && ( +
+ + {admin && ( + + )} + +
+ )} {showUser && (
{timestamp}
)} - {quotes && quotedMessage && } + {quotes && quotedMessage && ( +
+ +
+ )}
-
- {admin && ( - - )}
); } export function ChatMessageList() { + const listRef = useRef(null); const { messages } = useChat(); const [timestampUpdates, setTimestampUpdates] = useState(0); + const groupedMessages = useMemo(() => groupMessages(messages), [messages]); + const [actionsOpenForMessage, setActionsOpenForMessage] = useState< + string | null + >(null); + const handleToggleActionsForMessage = useCallback( + (messageId: string) => + setActionsOpenForMessage( + messageId === actionsOpenForMessage ? null : messageId + ), + [actionsOpenForMessage] + ); useEffect(() => { const updatingTimestamps = setInterval( @@ -123,27 +199,86 @@ export function ChatMessageList() { }; }, []); + useLayoutEffect(() => { + const images = Array.from( + listRef.current.getElementsByTagName("img") + ).filter((image) => image.dataset.src); + + for (const image of images) { + image.src = image.dataset.src; + image.dataset.src = undefined; + } + }, [messages]); + return ( -
- {messages.map((message, index) => ( - +
+ {groupedMessages.map((group) => ( +
+ {group.map((message, index) => ( + + ))} +
))}
); } function formatTimeAgo(time: number) { - const now = new Date().getTime(); - const humanized = `${humanizeDuration(time * 1000 - now, { + const shortEnglishHumanizer = humanizeDuration.humanizer({ + language: "shortEn", + languages: { + shortEn: { + y: () => "y", + mo: () => "mo", + w: () => "w", + d: () => "d", + h: () => "h", + m: () => "m", + s: () => "s", + ms: () => "ms", + }, + }, round: true, units: ["h", "m", "s"], largest: 2, - })} ago`; + spacer: "", + delimiter: ", ", + }); + const now = new Date().getTime(); + const humanized = `${shortEnglishHumanizer(time * 1000 - now)} ago`; - return humanized === "0 seconds ago" ? "just now" : humanized; + return humanized === "0s ago" ? "just now" : humanized; +} + +function groupMessages(messages: IChatMessage[]) { + const grouped: IChatMessage[][] = []; + let lastUsername = ""; + let temp: IChatMessage[] = []; + + for (const message of messages) { + if (!lastUsername) { + lastUsername = message.username; + } + + if (message.username === lastUsername) { + temp.push(message); + } else { + grouped.push(cloneDeep(temp)); + lastUsername = message.username; + temp = [message]; + } + } + + if (temp.length > 0) { + grouped.push(cloneDeep(temp)); + } + + return grouped; } diff --git a/chat/src/features/chat/QuotedMessageLink.css b/chat/src/features/chat/QuotedMessageLink.css new file mode 100644 index 000000000..e6667b8d5 --- /dev/null +++ b/chat/src/features/chat/QuotedMessageLink.css @@ -0,0 +1,3 @@ +.QuotedMessageLink { + font-size: 10px; +} \ No newline at end of file diff --git a/chat/src/features/chat/QuotedMessageLink.tsx b/chat/src/features/chat/QuotedMessageLink.tsx index 103d3a8ed..1e598a436 100644 --- a/chat/src/features/chat/QuotedMessageLink.tsx +++ b/chat/src/features/chat/QuotedMessageLink.tsx @@ -1,5 +1,6 @@ import React, { useCallback, useMemo } from "react"; import { useRootContext } from "../../hooks"; +import "./QuotedMessageLink.css"; const SCROLL_TO_QUOTED_OVERFLOW = 250; const QUOTED_MESSAGE_CONTEXTUAL_HIGHLIGHTING_DURATION = 2500; @@ -40,8 +41,8 @@ export function QuotedMessageLink({ message }: { message: IChatMessage }) { }, [message, censored]); return ( - - Replying to @{message.username}:{" "} + + @{message.username}:{" "} "{replyText}" ); diff --git a/chat/src/features/chat/UserInput.tsx b/chat/src/features/chat/UserInput.tsx index b1743db68..96dbd0f1d 100644 --- a/chat/src/features/chat/UserInput.tsx +++ b/chat/src/features/chat/UserInput.tsx @@ -47,7 +47,7 @@ export function UserInput() { ); const handleKeyUp = useCallback( (event: KeyboardEvent) => { - if (event.key === "Enter") { + if (event.key === "Enter" && !event.shiftKey) { handleSendMessage(); } }, diff --git a/chat/src/features/chat/UsersTyping.css b/chat/src/features/chat/UsersTyping.css index 5075decd5..4405bbdd4 100644 --- a/chat/src/features/chat/UsersTyping.css +++ b/chat/src/features/chat/UsersTyping.css @@ -1,4 +1,5 @@ .UsersTyping { height: 18px; display: inline-block; + font-size: 10px; } diff --git a/chat/src/hooks/useChat.tsx b/chat/src/hooks/useChat.tsx index 5e89ad5a6..34d31275b 100644 --- a/chat/src/hooks/useChat.tsx +++ b/chat/src/hooks/useChat.tsx @@ -9,7 +9,6 @@ import React, { useState, } from "react"; import { io, Socket } from "socket.io-client"; -import lozad from "lozad"; import debounce from "lodash.debounce"; import { useRootContext } from "./useRootContext"; import { useWindowFocus } from "./useWindowFocus"; @@ -178,17 +177,6 @@ export function ChatProvider({ children }: PropsWithChildren) { title.innerHTML = alertedWhileAway ? `[+${notifications}] Chat` : "Chat"; }, [notifications, focused]); - // Setup Lozad - useEffect(() => { - const { observe, observer } = lozad(); - - observe(); - - return () => { - observer.disconnect(); - }; - }, []); - return ( {children} ); diff --git a/chat/yarn.lock b/chat/yarn.lock index 2555ae935..e09683fd9 100644 --- a/chat/yarn.lock +++ b/chat/yarn.lock @@ -39,6 +39,13 @@ resolved "https://registry.yarnpkg.com/@types/humanize-duration/-/humanize-duration-3.27.1.tgz#f14740d1f585a0a8e3f46359b62fda8b0eaa31e7" integrity sha512-K3e+NZlpCKd6Bd/EIdqjFJRFHbrq5TzPPLwREk5Iv/YoIjQrs6ljdAUCo+Lb2xFlGNOjGSE0dqsVD19cZL137w== +"@types/lodash.clonedeep@^4.5.7": + version "4.5.7" + resolved "https://registry.yarnpkg.com/@types/lodash.clonedeep/-/lodash.clonedeep-4.5.7.tgz#0e119f582ed6f9e6b373c04a644651763214f197" + integrity sha512-ccNqkPptFIXrpVqUECi60/DFxjNKsfoQxSQsgcBJCX/fuX1wgyQieojkcWH/KpE3xzLoWN/2k+ZeGqIN3paSvw== + dependencies: + "@types/lodash" "*" + "@types/lodash.debounce@^4.0.7": version "4.0.7" resolved "https://registry.yarnpkg.com/@types/lodash.debounce/-/lodash.debounce-4.0.7.tgz#0285879defb7cdb156ae633cecd62d5680eded9f" @@ -46,6 +53,13 @@ dependencies: "@types/lodash" "*" +"@types/lodash.throttle@^4.1.7": + version "4.1.7" + resolved "https://registry.yarnpkg.com/@types/lodash.throttle/-/lodash.throttle-4.1.7.tgz#4ef379eb4f778068022310ef166625f420b6ba58" + integrity sha512-znwGDpjCHQ4FpLLx19w4OXDqq8+OvREa05H89obtSyXyOFKL3dDjCslsmfBz0T2FU8dmf5Wx1QvogbINiGIu9g== + dependencies: + "@types/lodash" "*" + "@types/lodash@*": version "4.14.185" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.185.tgz#c9843f5a40703a8f5edfd53358a58ae729816908" @@ -390,11 +404,21 @@ inherits@2: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== +lodash.clonedeep@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ== + lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== +lodash.throttle@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" + integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== + lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" diff --git a/files/assets/images/emojis/marseycarp4.webp b/files/assets/images/emojis/marseycarp4.webp new file mode 100644 index 000000000..878896310 Binary files /dev/null and b/files/assets/images/emojis/marseycarp4.webp differ diff --git a/files/assets/images/emojis/marseychingchongpearlclutch.webp b/files/assets/images/emojis/marseychingchongpearlclutch.webp new file mode 100644 index 000000000..655287aca Binary files /dev/null and b/files/assets/images/emojis/marseychingchongpearlclutch.webp differ diff --git a/files/assets/images/emojis/marseylibertyfireworks.webp b/files/assets/images/emojis/marseylibertyfireworks.webp new file mode 100644 index 000000000..9f1a6e9b2 Binary files /dev/null and b/files/assets/images/emojis/marseylibertyfireworks.webp differ diff --git a/files/assets/images/emojis/marseynoyoufellowpedo.webp b/files/assets/images/emojis/marseynoyoufellowpedo.webp new file mode 100644 index 000000000..3870b8cea Binary files /dev/null and b/files/assets/images/emojis/marseynoyoufellowpedo.webp differ diff --git a/files/assets/images/emojis/marseyrobot.webp b/files/assets/images/emojis/marseyrobot.webp new file mode 100644 index 000000000..ff586e928 Binary files /dev/null and b/files/assets/images/emojis/marseyrobot.webp differ diff --git a/files/assets/images/hats/Duel Wielding.webp b/files/assets/images/hats/Duel Wielding.webp new file mode 100644 index 000000000..df81c33d6 Binary files /dev/null and b/files/assets/images/hats/Duel Wielding.webp differ diff --git a/files/assets/images/hats/Kanohi Akaku (Kopaka).webp b/files/assets/images/hats/Kanohi Akaku (Kopaka).webp new file mode 100644 index 000000000..0fa883dfd Binary files /dev/null and b/files/assets/images/hats/Kanohi Akaku (Kopaka).webp differ diff --git a/files/assets/images/hats/Kanohi Avohkii (Takanuva).webp b/files/assets/images/hats/Kanohi Avohkii (Takanuva).webp new file mode 100644 index 000000000..eb9bcd01d Binary files /dev/null and b/files/assets/images/hats/Kanohi Avohkii (Takanuva).webp differ diff --git a/files/assets/images/hats/Kanohi Ignika.webp b/files/assets/images/hats/Kanohi Ignika.webp new file mode 100644 index 000000000..3e0c4a1dd Binary files /dev/null and b/files/assets/images/hats/Kanohi Ignika.webp differ diff --git a/files/assets/images/hats/Kanohi Kakama (Pohatu).webp b/files/assets/images/hats/Kanohi Kakama (Pohatu).webp new file mode 100644 index 000000000..1b788c4f2 Binary files /dev/null and b/files/assets/images/hats/Kanohi Kakama (Pohatu).webp differ diff --git a/files/assets/images/hats/Kanohi Kaukau (Gali).webp b/files/assets/images/hats/Kanohi Kaukau (Gali).webp new file mode 100644 index 000000000..c6ff93c1a Binary files /dev/null and b/files/assets/images/hats/Kanohi Kaukau (Gali).webp differ diff --git a/files/assets/images/hats/Kanohi Miru (Lewa).webp b/files/assets/images/hats/Kanohi Miru (Lewa).webp new file mode 100644 index 000000000..b736484d3 Binary files /dev/null and b/files/assets/images/hats/Kanohi Miru (Lewa).webp differ diff --git a/files/assets/images/hats/Kanohi Pakari (Onua).webp b/files/assets/images/hats/Kanohi Pakari (Onua).webp new file mode 100644 index 000000000..d838261b9 Binary files /dev/null and b/files/assets/images/hats/Kanohi Pakari (Onua).webp differ diff --git a/files/assets/images/hats/The Yakub.webp b/files/assets/images/hats/The Yakub.webp new file mode 100644 index 000000000..df94ec1e5 Binary files /dev/null and b/files/assets/images/hats/The Yakub.webp differ diff --git a/files/assets/js/bootstrap.js b/files/assets/js/bootstrap.js index 30a80beda..e043fc642 100644 --- a/files/assets/js/bootstrap.js +++ b/files/assets/js/bootstrap.js @@ -313,14 +313,27 @@ function showmore() { btn.innerHTML = 'SHOW LESS' } +function formatDate(d) { + var year = d.getFullYear(); + var monthAbbr = d.toLocaleDateString('en-us', {month: 'short'}); + var day = d.getDate(); + var hour = ("0" + d.getHours()).slice(-2); + var minute = ("0" + d.getMinutes()).slice(-2); + var second = ("0" + d.getSeconds()).slice(-2); + var tzAbbr = d.toLocaleTimeString('en-us', {timeZoneName: 'short'}).split(' ')[2]; + + return (day + " " + monthAbbr + " " + year + " " + + hour + ":" + minute + ":" + second + " " + tzAbbr); +} + const timestamps = document.querySelectorAll('[data-time]'); for (const e of timestamps) { const date = new Date(e.dataset.time*1000); - e.innerHTML = date.toString(); + e.innerHTML = formatDate(date); }; function timestamp(str, ti) { const date = new Date(ti*1000); - document.getElementById(str).setAttribute("data-bs-original-title", date.toString()); -}; \ No newline at end of file + document.getElementById(str).setAttribute("data-bs-original-title", formatDate(date)); +}; diff --git a/files/routes/settings.py b/files/routes/settings.py index 15a5e6d90..b54a27c4c 100644 --- a/files/routes/settings.py +++ b/files/routes/settings.py @@ -113,7 +113,7 @@ def settings_profile_post(v): v.spider = int(request.values.get("spider") == 'true') if v.spider: badge_grant(user=v, badge_id=179) else: - badge = v.has_badge(170) + badge = v.has_badge(179) if badge: g.db.delete(badge) elif request.values.get("bio") == "": diff --git a/seed-db.sql b/seed-db.sql index a4f447f60..965f4f7eb 100644 --- a/seed-db.sql +++ b/seed-db.sql @@ -222,16 +222,16 @@ INSERT INTO public.hat_defs VALUES (722, 'Darth Vader Helmet', 'Cool-looking guy INSERT INTO public.hat_defs VALUES (725, 'New Years Glasses', 'Happy New Year!', 2, 500, NULL, 1663892467); INSERT INTO public.hat_defs VALUES (726, 'Operator', 'This classical variables has been quantized and is now a Hermitian operator on a Hillbert space.', 2, 500, NULL, 1663893198); INSERT INTO public.hat_defs VALUES (1, 'Ushanka', 'The People''s Hat', 2, 500, NULL, 1662167687); - - - - - - - - INSERT INTO public.hat_defs VALUES (736, 'Marsey Slime Hat', 'Let this cute little slime marsey climb on your crusty head.', 2, 500, NULL, 1664085993); - +INSERT INTO public.hat_defs VALUES (728, 'Kanohi Akaku (Kopaka)', 'Toa of Ice. The obligatory lone wolf character. You''re Lego Sasuke.', 2, 500, NULL, 1663969562); +INSERT INTO public.hat_defs VALUES (729, 'Kanohi Kaukau (Gali)', 'Toa of Water. Lmao, you picked the girl one!', 2, 500, NULL, 1663969637); +INSERT INTO public.hat_defs VALUES (730, 'Kanohi Miru (Lewa)', 'Toa of Air. You''re the funny one of the group, or maybe you just know that the axe was the coolest weapon.', 2, 500, NULL, 1663969803); +INSERT INTO public.hat_defs VALUES (731, 'Kanohi Kakama (Pohatu)', 'Toa of Stone. You''re everybody''s pal and just want the team to stick together. Why is your element separate from Earth? It''s anybody''s guess!', 2, 500, NULL, 1663969919); +INSERT INTO public.hat_defs VALUES (732, 'Kanohi Avohkii (Takanuva)', 'Toa of Light. Well aren''t you just a special snowflake? Fuckin'' think you''re the Chosen One over here or something.', 2, 500, NULL, 1663970033); +INSERT INTO public.hat_defs VALUES (733, 'Kanohi Ignika', 'The Mask of Life. Matoro died for you, and you''re using your life to shitpost about trans people?', 2, 500, NULL, 1663970127); +INSERT INTO public.hat_defs VALUES (734, 'Kanohi Pakari (Onua)', 'Toa of Earth. The wisdom of the group, but wisdom is useless if you don''t share it. Why is your element separate from Stone? Answer me that, wise guy!', 2, 500, NULL, 1663970191); +INSERT INTO public.hat_defs VALUES (735, 'The Yakub', 'Proof that science has, in fact, gone too far', 2, 500, NULL, 1664054894); +INSERT INTO public.hat_defs VALUES (737, 'Duel Wielding', 'Oh shit you''re packing? My bad carry on', 2, 500, NULL, 1664088304); INSERT INTO public.hat_defs VALUES (3, 'Cat Ears I', 'Mew :3', 2, 500, NULL, 1662167687); INSERT INTO public.hat_defs VALUES (723, 'Hohol', 'Мій предок :)', 2, 500, NULL, 1663892328); INSERT INTO public.hat_defs VALUES (92, 'Top Hat (black)', 'Traditional. Classy. Elegant.', 2, 500, NULL, 1662167687); @@ -1177,7 +1177,7 @@ INSERT INTO public.marseys (name, author_id, tags, created_utc) VALUES ('marseycarp',2,'beard mohawk reaction carpathianflorist monster',NULL), ('marseycarp2',2,'harm cutting selfharm cutter reaction carpathianflorist self animated',NULL), ('marseycarp3',2,'reaction fish carpathianflorist catfish',NULL), -('marseycarp4',2,'sick sad world ban hammer pin awards janny mod admin',1664034021), +('marseycarp4',2,'sicksadworld banhammer pin awards janny mod admin',1664034021), ('marseycarpasian',2,'carpathianflorist fish azn racist hat paddy gook nip ching chong chink',NULL), ('marseycarpautism',2,'carpathianflorist special assburgers aspergers retarded janitor jannie',NULL), ('marseycarpboobs',2,'carpathianflorist boobs booba titties tiddies tits boobs breasts censored fish administrator jannie janny janitor',1663771699), @@ -1193,6 +1193,7 @@ INSERT INTO public.marseys (name, author_id, tags, created_utc) VALUES ('marseycarphug2',2,'fish love bottomfeeder carpathianflorist heart blow admin cute',NULL), ('marseycarpina',2,'carpathianflorist drag transgender admin jannie',NULL), ('marseycarplazy',2,'carpathianflorist fish couch sleeping slacker idc antiwork janitor',NULL), +('marseycarpler',2,'carp hitler nazi',1664137088), ('marseycarpmerchant',2,'jewish money redbubble merch carpathianflorist money yid heeb sheeny sheenie greedy handrubbery rubbing hands kike israeli',1663465891), ('marseycarpmerchant2',2,'jew fish greedy',1663548215), ('marseycarpmermaid',2,'carp mermaid merman mercarp siren sexy legs temptress',NULL), @@ -1770,6 +1771,7 @@ INSERT INTO public.marseys (name, author_id, tags, created_utc) VALUES ('marseyliathomas',2,'tranny transgender athlete lia thomas athletics woman valid lgbt swimmer aquamaam aqua maam',NULL), ('marseyliberty',2,'usa burger america statue lady republican democrat biden trump rightoid leftoid',NULL), ('marseyliberty2',2,'usa burger america statue lady republican democrat biden trump rightoid leftoid',NULL), +('marseylibertyfireworks',2,'independence forth july america usa eagle republican democrat united states patriot statue animated',1664123152), ('marseylibleft',2,'unemployed protest riot anarcho capitalist antifa anarchist anarchy',NULL), ('marseylibright',2,'libertarian anarcho wagecuck pedophile capitalist lolbert',NULL), ('marseylicking',2,'spongebob tongue taste',1663284181), @@ -2324,6 +2326,7 @@ INSERT INTO public.marseys (name, author_id, tags, created_utc) VALUES ('marseyspa',2,'spa towel cucumber facial relax calm selfcare foid hygiene beauty',NULL), ('marseyspecial',2,'retard reaction slow special needs sped',NULL), ('marseysperm',2,'cum swim vasectomy jizz semen spunk penis sex pregnant coom animated',NULL), +('marseysphericalcow',2,'sphere science moo physics',1664131121), ('marseysphinx',2,'sphinx egypt ancient antiquity wonder pharaoh myth riddle puzzle',NULL), ('marseyspider',2,'insect halloween arachnid holiday bug',NULL), ('marseyspider2',2,'insect halloween spiderweb arachnid holiday bug',NULL), @@ -2542,6 +2545,7 @@ INSERT INTO public.marseys (name, author_id, tags, created_utc) VALUES ('marseyyeti',2,'scary monster myth winter ice mountain himalaya asia predator giant',NULL), ('marseyyikes',2,'reaction judgment disgust oof cringe',NULL), ('marseyyinzer',2,'pittsburgh pennsylvania pens penguins steelers stillers pirates buccos buckos terrible towel pierogo yuengling beer city hat baseball football hockey nfl mlb nhl happy',NULL), +('marseyyoshi',2,'super mario nintendo snes retro video game dinosaur italian plumber pipes',1664142051), ('marseyyugi',2,'yugioh yu-gi-oh! cards trap anime',NULL), ('marseyza',2,'antlers flowers',NULL), ('marseyzaku',2,'gundam mecha robot helmet mask',NULL),