diff --git a/.gitignore b/.gitignore index 1ce8ce8ff..560f817d7 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,12 @@ flask_session/ site_settings.json /files/test.py tags + +# Chat environment +chat/node_modules +chat/build +chat/.env + +# Chat artefacts +files/assets/css/chat_done.css +files/assets/js/chat_done.js diff --git a/Dockerfile b/Dockerfile index 2ef02f465..6fcc39e63 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,6 +27,18 @@ RUN mkdir /asset_submissions/hats RUN mkdir /asset_submissions/marseys/original RUN mkdir /asset_submissions/hats/original +ENV NODE_VERSION=16.13.0 +RUN apt install -y curl +RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash +ENV NVM_DIR=/root/.nvm +RUN . "$NVM_DIR/nvm.sh" && nvm install ${NODE_VERSION} +RUN . "$NVM_DIR/nvm.sh" && nvm use v${NODE_VERSION} +RUN . "$NVM_DIR/nvm.sh" && nvm alias default v${NODE_VERSION} +ENV PATH="/root/.nvm/versions/node/v${NODE_VERSION}/bin/:${PATH}" +RUN node --version +RUN npm --version +RUN npm i -g yarn + EXPOSE 80/tcp CMD [ "/usr/bin/supervisord", "-c", "/etc/supervisord.conf" ] diff --git a/chat/.env.template b/chat/.env.template new file mode 100644 index 000000000..66ceacfec --- /dev/null +++ b/chat/.env.template @@ -0,0 +1,6 @@ +FEATURES_ACTIVITY=false +DEBUG=false +NODE_ENV="production" +EMOJI_INPUT_TOKEN=":" +QUICK_EMOJIS_MAX_COUNT = 20 +APPROXIMATE_CHARACTER_WIDTH = 8 \ No newline at end of file diff --git a/chat/build.js b/chat/build.js new file mode 100644 index 000000000..6d455164f --- /dev/null +++ b/chat/build.js @@ -0,0 +1,22 @@ +require('dotenv').config() +const package = require("./package.json"); +const path = require("path"); +const { build } = require("esbuild"); + +const options = { + entryPoints: ["./src/index.tsx"], + outfile: path.resolve(__dirname, "../files/assets/js/chat_done.js"), + bundle: true, + minify: process.env.NODE_ENV === "production", + define: { + "process.env.VERSION": `"${package.version}"`, + "process.env.NODE_ENV": `"${process.env.NODE_ENV}"`, + "process.env.DEBUG": process.env.DEBUG, + "process.env.FEATURES_ACTIVITY": process.env.FEATURES_ACTIVITY, + "process.env.EMOJI_INPUT_TOKEN": `"${process.env.EMOJI_INPUT_TOKEN}"`, + "process.env.QUICK_EMOJIS_MAX_COUNT": process.env.QUICK_EMOJIS_MAX_COUNT, + "process.env.APPROXIMATE_CHARACTER_WIDTH": process.env.APPROXIMATE_CHARACTER_WIDTH, + }, +}; + +build(options).catch(() => process.exit(1)); diff --git a/chat/global.d.ts b/chat/global.d.ts new file mode 100644 index 000000000..978e81e9a --- /dev/null +++ b/chat/global.d.ts @@ -0,0 +1,22 @@ +declare var process: { + env: Record; +}; + +declare interface IChatMessage { + id: string; + username: string; + avatar: string; + hat: string; + namecolor: string; + text: string; + text_censored: string; + text_html: string; + time: number; + quotes: null | string; +} + +declare interface EmojiModSelection { + large: boolean; + mirror: boolean; + pat: boolean; +} diff --git a/chat/package.json b/chat/package.json new file mode 100644 index 000000000..1f9db7ddf --- /dev/null +++ b/chat/package.json @@ -0,0 +1,38 @@ +{ + "name": "chat", + "version": "0.0.15", + "main": "./src/index.tsx", + "license": "MIT", + "dependencies": { + "@types/humanize-duration": "^3.27.1", + "@types/lodash.debounce": "^4.0.7", + "@types/lozad": "^1.16.1", + "@types/react": "^18.0.20", + "@types/react-dom": "^18.0.6", + "@types/react-virtualized-auto-sizer": "^1.0.1", + "@types/react-window": "^1.8.5", + "classnames": "^2.3.2", + "dotenv": "^16.0.2", + "esbuild": "^0.15.7", + "humanize-duration": "^3.27.3", + "lodash.debounce": "^4.0.8", + "lozad": "^1.16.0", + "react": "^18.2.0", + "react-dnd": "^16.0.1", + "react-dnd-html5-backend": "^16.0.1", + "react-dom": "^18.2.0", + "react-virtualized-auto-sizer": "^1.0.7", + "react-window": "^1.8.7", + "run-when-changed": "^2.1.0", + "socket.io-client": "^4.5.2", + "typescript": "^4.8.3", + "weak-key": "^1.0.2" + }, + "scripts": { + "chat": "yarn check && yarn build && yarn css:move", + "chat:watch": "run-when-changed --watch \"**/*.*\" --exec \"yarn chat\"", + "check": "tsc", + "build": "node ./build", + "css:move": "mv ../files/assets/js/chat_done.css ../files/assets/css/chat_done.css" + } +} diff --git a/chat/src/App.css b/chat/src/App.css new file mode 100644 index 000000000..a54664b68 --- /dev/null +++ b/chat/src/App.css @@ -0,0 +1,121 @@ +html, +body { + overscroll-behavior-y: none; +} + +html { + height: -webkit-fill-available; +} + +body { + min-height: 100vh; + /* mobile viewport bug fix */ + min-height: -webkit-fill-available; +} + +.App { + position: fixed; + width: 100vw; + display: flex; + overflow: hidden; +} + +.App-wrapper { + flex: 1; + overflow: hidden; + display: flex; + flex-direction: column; + margin: 0 auto; + max-width: 1000px; +} + +.App-heading { + flex-basis: 3rem; + display: flex; + align-items: center; +} + +.App-heading small { + opacity: 0.2; +} + +.App-side { + height: 100%; + flex: 1; + background: var(--gray-500); + position: relative; +} + +.App-content { + position: relative; + flex: 3; + height: 60vh; + max-height: 1000px; + overflow: auto; + -ms-overflow-style: none; + scrollbar-width: none; + display: flex; + flex-direction: column; +} + +.App-content::-webkit-scrollbar { + display: none; +} + +.App-drawer { + z-index: 2; + display: flex; + background: var(--background); + height: 100%; +} + + +.App-center { + display: flex; + align-items: flex-start; +} + +.App-bottom-wrapper { + display: flex; + align-items: flex-start; +} + +.App-bottom { + flex: 3; +} + +.App-bottom-dummy { + flex: 1; +} + +.App-bottom-extra { + padding: .25rem; +} + +/* On mobile, hide the sidebar and make the input full-width. */ +@media screen and (max-width: 1100px) { + .App-side { + display: none; + } + + .App-bottom-dummy { + display: none; + } + + .App-bottom-wrapper { + padding-right: 1rem; + padding-left: 1rem; + } +} + +lite-youtube { + min-width: min(80vw, 500px); +} + +.btn-secondary { + border: none !important; +} + +p { + margin: 0; +} \ No newline at end of file diff --git a/chat/src/App.tsx b/chat/src/App.tsx new file mode 100644 index 000000000..6eb01dfad --- /dev/null +++ b/chat/src/App.tsx @@ -0,0 +1,96 @@ +import React, { useEffect, useRef } from "react"; +import { DndProvider, useDrop } from "react-dnd"; +import { HTML5Backend } from "react-dnd-html5-backend"; +import { + ChatHeading, + ChatMessageList, + QuotedMessage, + UserInput, + UserList, + UsersTyping, +} from "./features"; +import { ChatProvider, DrawerProvider, useChat, useDrawer } from "./hooks"; +import "./App.css"; + +const SCROLL_CANCEL_THRESHOLD = 500; + +export function App() { + return ( + + + + + + + + ); +} + +function AppInner() { + const [_, dropRef] = useDrop({ + accept: "drawer", + }); + const { open, config } = useDrawer(); + const contentWrapper = useRef(null); + const initiallyScrolledDown = useRef(false); + const { messages, quote } = useChat(); + + useEffect(() => { + if (messages.length > 0) { + if (initiallyScrolledDown.current) { + /* We only want to scroll back down on a new message + if the user is not scrolled up looking at previous messages. */ + const scrollableDistance = + contentWrapper.current.scrollHeight - + contentWrapper.current.clientHeight; + const scrolledDistance = contentWrapper.current.scrollTop; + const hasScrolledEnough = + scrollableDistance - scrolledDistance >= SCROLL_CANCEL_THRESHOLD; + + if (hasScrolledEnough) { + return; + } + } else { + // Always scroll to the bottom on first load. + initiallyScrolledDown.current = true; + } + + contentWrapper.current.scrollTop = contentWrapper.current.scrollHeight; + } + }, [messages]); + + return ( +
+
+
+ v{process.env.VERSION} + +
+
+
+ {open ? ( +
{config.content}
+ ) : ( + + )} +
+
+ +
+
+
+
+ {quote && ( +
+ {quote && } +
+ )} + + +
+
+
+
+
+ ); +} diff --git a/chat/src/drawers/BaseDrawer.css b/chat/src/drawers/BaseDrawer.css new file mode 100644 index 000000000..5d76f8c9a --- /dev/null +++ b/chat/src/drawers/BaseDrawer.css @@ -0,0 +1,5 @@ +.BaseDrawer { + flex: 1; + padding-right: 2rem; + overflow: hidden; +} diff --git a/chat/src/drawers/BaseDrawer.tsx b/chat/src/drawers/BaseDrawer.tsx new file mode 100644 index 000000000..f1fdedb49 --- /dev/null +++ b/chat/src/drawers/BaseDrawer.tsx @@ -0,0 +1,10 @@ +import React, { PropsWithChildren, useEffect } from "react"; +import "./BaseDrawer.css"; + +interface Props extends PropsWithChildren { + onClose?(): void; +} + +export function BaseDrawer({ onClose, children }: Props) { + return
{children}
; +} diff --git a/chat/src/drawers/index.ts b/chat/src/drawers/index.ts new file mode 100644 index 000000000..38fdad714 --- /dev/null +++ b/chat/src/drawers/index.ts @@ -0,0 +1 @@ +export * from "./BaseDrawer" \ No newline at end of file diff --git a/chat/src/features/chat/ActivityList.css b/chat/src/features/chat/ActivityList.css new file mode 100644 index 000000000..763807152 --- /dev/null +++ b/chat/src/features/chat/ActivityList.css @@ -0,0 +1,35 @@ +.ActivityList { + margin-left: 2rem; +} + +.ActivityList h4 { + display: flex; + align-items: center; + justify-content: space-between; +} + +.ActivityList h4 hr { + flex: 1; + margin-right: 1rem; +} + +.ActivityList-activity { + display: flex; + align-items: center; + justify-content: space-between; + cursor: pointer; +} + +.ActivityList-activity-icon { + margin-right: 1rem; +} + +.ActivityList-activity { + transition: background 0.4s ease-in-out; + padding: 0 1rem; +} + +.ActivityList-activity:hover { + cursor: pointer; + background: #ffffff05; +} \ No newline at end of file diff --git a/chat/src/features/chat/ActivityList.tsx b/chat/src/features/chat/ActivityList.tsx new file mode 100644 index 000000000..de2ce30c0 --- /dev/null +++ b/chat/src/features/chat/ActivityList.tsx @@ -0,0 +1,69 @@ +import React from "react"; +import cx from 'classnames' +import { useDrawer } from "../../hooks"; +import "./ActivityList.css"; + +const ACTIVITIES = [ + { + game: "Poker", + description: "Know when to hold 'em.", + icon: "fas fa-cards", + }, + { + game: "Roulette", + description: "Table go brrrr.", + icon: "fas fa-circle", + }, + { + game: "Slots", + description: "Is today your lucky day?", + icon: "fas fa-dollar-sign", + }, + { + game: "Blackjack", + description: "Twenty one ways to change your life.", + icon: "fas fa-cards", + }, + { + game: "Racing", + description: "Look at 'em go.", + icon: "fas fa-cards", + }, + { + game: "Crossing", + description: "A simple life.", + icon: "fas fa-cards", + }, + { + game: "Lottershe", + description: "Can't win if you don't play.", + icon: "fas fa-ticket", + }, +]; + +export function ActivityList() { + const { toggle } = useDrawer(); + + return ( +
+

+
+ Activities +

+
+ {ACTIVITIES.map(({ game, description, icon }) => ( +
+
+
+ +
{game}
{description}
+
+ + 0 +
+
+ ))} +
+
+ ); +} diff --git a/chat/src/features/chat/ChatHeading.css b/chat/src/features/chat/ChatHeading.css new file mode 100644 index 000000000..5c13a474a --- /dev/null +++ b/chat/src/features/chat/ChatHeading.css @@ -0,0 +1,10 @@ +.ChatHeading { + flex: 1; + display: flex; + align-items: center; + justify-content: space-between; +} + +.ChatHeading i { + margin-right: 0.5rem; +} \ No newline at end of file diff --git a/chat/src/features/chat/ChatHeading.tsx b/chat/src/features/chat/ChatHeading.tsx new file mode 100644 index 000000000..c3760d205 --- /dev/null +++ b/chat/src/features/chat/ChatHeading.tsx @@ -0,0 +1,31 @@ +import React, { useCallback } from "react"; +import { useChat, useDrawer } from "../../hooks"; +import { UserList } from "./UserList"; +import "./ChatHeading.css"; + +export function ChatHeading() { + const { reveal } = useDrawer(); + const { online } = useChat(); + const handleOpenUserListDrawer = useCallback( + () => + reveal({ + title: "Users in chat", + content: , + }), + [] + ); + + return ( +
+
+
+ + {online.length} users online +
+
+ ); +} diff --git a/chat/src/features/chat/ChatMessage.css b/chat/src/features/chat/ChatMessage.css new file mode 100644 index 000000000..66c71830c --- /dev/null +++ b/chat/src/features/chat/ChatMessage.css @@ -0,0 +1,55 @@ +@keyframes fading-in { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +.ChatMessage { + padding-right: 3rem; + position: relative; + animation: fading-in 0.3s ease-in-out forwards; +} + +.ChatMessage-top { + display: flex; + align-items: center; +} + +.ChatMessage-timestamp { + margin-left: 0.5rem; +} + +.ChatMessage-bottom { + display: flex; + align-items: center; + justify-content: space-between; + padding-left: 30px; +} + +.ChatMessage-content { + margin-right: 0.5rem; + word-break: break-all; + display: inline-block; +} + +.ChatMessage-button { + background: transparent !important; +} + +.ChatMessage-button__confirmed i { + color: red !important; +} + +.ChatMessage-delete { + position: absolute; + top: 4px; + right: 4px; +} + +/* List */ +.ChatMessageList { + flex: 1; +} \ No newline at end of file diff --git a/chat/src/features/chat/ChatMessage.tsx b/chat/src/features/chat/ChatMessage.tsx new file mode 100644 index 000000000..6c985d0b2 --- /dev/null +++ b/chat/src/features/chat/ChatMessage.tsx @@ -0,0 +1,149 @@ +import React, { + useCallback, + useEffect, + useMemo, + useState, +} from "react"; +import cx from "classnames"; +import key from "weak-key"; +import humanizeDuration from "humanize-duration"; +import { Username } from "./Username"; +import { useChat, useRootContext } from "../../hooks"; +import { QuotedMessageLink } from "./QuotedMessageLink"; +import "./ChatMessage.css"; + +interface ChatMessageProps { + message: IChatMessage; + timestampUpdates: number; + showUser?: boolean; +} + +const TIMESTAMP_UPDATE_INTERVAL = 20000; + +export function ChatMessage({ + message, + showUser = true, + timestampUpdates, +}: ChatMessageProps) { + const { + id, + avatar, + namecolor, + username, + hat, + text, + text_html, + text_censored, + time, + quotes, + } = message; + const { + username: loggedInUsername, + admin, + censored, + themeColor, + } = useRootContext(); + const { messageLookup, deleteMessage, quoteMessage } = useChat(); + 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 handleDeleteMessage = useCallback(() => { + if (confirmedDelete) { + deleteMessage(text); + } else { + setConfirmedDelete(true); + } + }, [text, confirmedDelete]); + const timestamp = useMemo( + () => formatTimeAgo(time), + [time, timestampUpdates] + ); + + return ( +
+ {showUser && ( +
+ +
{timestamp}
+
+ )} + {quotes && quotedMessage && } +
+
+ + +
+ {admin && ( + + )} +
+
+ ); +} + +export function ChatMessageList() { + const { messages } = useChat(); + const [timestampUpdates, setTimestampUpdates] = useState(0); + + useEffect(() => { + const updatingTimestamps = setInterval( + () => setTimestampUpdates((prev) => prev + 1), + TIMESTAMP_UPDATE_INTERVAL + ); + + return () => { + clearInterval(updatingTimestamps); + }; + }, []); + + return ( +
+ {messages.map((message, index) => ( + + ))} +
+ ); +} + +function formatTimeAgo(time: number) { + const now = new Date().getTime(); + const humanized = `${humanizeDuration(time * 1000 - now, { + round: true, + units: ["h", "m", "s"], + largest: 2, + })} ago`; + + return humanized === "0 seconds ago" ? "just now" : humanized; +} diff --git a/chat/src/features/chat/QuotedMessage.css b/chat/src/features/chat/QuotedMessage.css new file mode 100644 index 000000000..41b149432 --- /dev/null +++ b/chat/src/features/chat/QuotedMessage.css @@ -0,0 +1,15 @@ +.QuotedMessage { + display: flex; + align-items: center; + justify-content: space-between; +} + +.QuotedMessage-content { + margin-left: 1rem; + flex: 1; + max-width: 420px; + max-height: 40px; + overflow: hidden; + text-overflow: ellipsis; + margin-right: 1rem; +} diff --git a/chat/src/features/chat/QuotedMessage.tsx b/chat/src/features/chat/QuotedMessage.tsx new file mode 100644 index 000000000..16ec59fd6 --- /dev/null +++ b/chat/src/features/chat/QuotedMessage.tsx @@ -0,0 +1,24 @@ +import React from "react"; +import { useChat, useRootContext } from "../../hooks"; +import { Username } from "./Username"; +import "./QuotedMessage.css"; +import { QuotedMessageLink } from "./QuotedMessageLink"; + +export function QuotedMessage() { + const { quote, quoteMessage } = useChat(); + const { censored } = useRootContext(); + + return ( +
+ + + +
+ ); +} diff --git a/chat/src/features/chat/QuotedMessageLink.tsx b/chat/src/features/chat/QuotedMessageLink.tsx new file mode 100644 index 000000000..5e245fdb4 --- /dev/null +++ b/chat/src/features/chat/QuotedMessageLink.tsx @@ -0,0 +1,43 @@ +import React, { useCallback } from "react"; +import { useRootContext } from "../../hooks"; + +const SCROLL_TO_QUOTED_OVERFLOW = 250; +const QUOTED_MESSAGE_CONTEXTUAL_HIGHLIGHTING_DURATION = 2500; +const QUOTED_MESSAGE_CONTEXTUAL_SNIPPET_LENGTH = 30; + +export function QuotedMessageLink({ message }: { message: IChatMessage }) { + const { themeColor } = useRootContext(); + const handleLinkClick = useCallback(() => { + const element = document.getElementById(message.id); + + if (element) { + element.scrollIntoView(); + element.style.background = `#${themeColor}33`; + + setTimeout(() => { + element.style.background = "unset"; + }, QUOTED_MESSAGE_CONTEXTUAL_HIGHLIGHTING_DURATION); + + const [appContent] = Array.from( + document.getElementsByClassName("App-content") + ); + + if (appContent) { + appContent.scrollTop -= SCROLL_TO_QUOTED_OVERFLOW; + } + } + }, []); + + return ( + + Replying to @{message.username}:{" "} + + "{message.text.slice(0, QUOTED_MESSAGE_CONTEXTUAL_SNIPPET_LENGTH)} + {message.text.length >= QUOTED_MESSAGE_CONTEXTUAL_SNIPPET_LENGTH + ? "..." + : ""} + " + + + ); +} diff --git a/chat/src/features/chat/UserInput.css b/chat/src/features/chat/UserInput.css new file mode 100644 index 000000000..3d8d94ab9 --- /dev/null +++ b/chat/src/features/chat/UserInput.css @@ -0,0 +1,11 @@ +.UserInput { + position: relative; +} + +.UserInput-emoji { + cursor: pointer; + position: absolute; + top: 12px; + right: 12px; + font-size: 20px; +} \ No newline at end of file diff --git a/chat/src/features/chat/UserInput.tsx b/chat/src/features/chat/UserInput.tsx new file mode 100644 index 000000000..ebccbd0ea --- /dev/null +++ b/chat/src/features/chat/UserInput.tsx @@ -0,0 +1,178 @@ +import React, { + ChangeEvent, + KeyboardEvent, + FormEvent, + useCallback, + useRef, + useMemo, + useState, +} from "react"; +import { useChat, useDrawer, useEmojis } from "../../hooks"; +import { EmojiDrawer, QuickEmojis } from "../emoji"; +import "./UserInput.css"; + +export function UserInput() { + const { messages, draft, sendMessage, updateDraft } = useChat(); + const { reveal, hide, open } = useDrawer(); + const builtChatInput = useRef(null); + const { visible, addQuery } = useEmojis(); + const form = useRef(null); + const [typingOffset, setTypingOffset] = useState(0); + const quickEmojis = useMemo( + () => visible.slice(0, process.env.QUICK_EMOJIS_MAX_COUNT), + [visible] + ); + const handleChange = useCallback( + (event: ChangeEvent) => { + const input = event.target.value; + const [openEmojiToken, closeEmojiToken] = locateEmojiTokens(input); + const emojiSegment = input.slice(openEmojiToken + 1, closeEmojiToken + 1); + + updateDraft(input); + addQuery( + openEmojiToken === -1 || emojiSegment.includes(" ") ? "" : emojiSegment + ); + setTypingOffset( + emojiSegment.length * process.env.APPROXIMATE_CHARACTER_WIDTH + ); + }, + [] + ); + const handleSendMessage = useCallback( + (event?: FormEvent) => { + event?.preventDefault(); + sendMessage(); + }, + [sendMessage] + ); + const handleKeyUp = useCallback( + (event: KeyboardEvent) => { + if (event.key === "Enter") { + handleSendMessage(); + } + }, + [handleSendMessage] + ); + const handleOpenEmojiDrawer = useCallback( + () => + reveal({ + title: "Select an emoji", + content: ( + builtChatInput.current?.focus()} + /> + ), + }), + [] + ); + const handleCloseEmojiDrawer = useCallback(() => { + builtChatInput.current?.focus(); + hide(); + }, [hide]); + const handleSelectEmoji = useCallback((emoji: string) => { + updateDraft((prev) => `${prev} :${emoji}: `); + }, []); + const handleInsertQuickEmoji = useCallback( + (emoji: string) => { + const [openEmojiToken, closeEmojiToken] = locateEmojiTokens(draft); + const toReplace = draft.slice(openEmojiToken, closeEmojiToken + 1); + + updateDraft((prev) => prev.replace(toReplace, `:${emoji}: `)); + addQuery(""); + + builtChatInput.current?.focus(); + }, + [draft] + ); + + return ( +
+ {quickEmojis.length > 0 && ( +
+ +
+ )} + - -
-
- - -
-

Users in chat right now

-
- +
- -
- - - - - - -{% include "emoji_modal.html" %} -{% include "expanded_image_modal.html" %} - - - - - -{% if v.admin_level > 1 %} - -{% endif %} + + + + diff --git a/files/templates/comments.html b/files/templates/comments.html index 48feeb306..8bae90f06 100644 --- a/files/templates/comments.html +++ b/files/templates/comments.html @@ -1,4 +1,3 @@ -{%- from 'util/assetcache.html' import asset, asset_siteimg with context -%} {%- import 'util/helpers.html' as help -%} {% if not request.headers.get("xhr") %} {% if comment_info %} @@ -812,20 +811,20 @@ {% endif %} {% if v %} - - + + {% endif %} - + {% if v and v.admin_level >= 2 %} - + {% endif %} {% include "expanded_image_modal.html" %} - - + + + @@ -15,9 +14,9 @@ {% if v %} - - - + + + {% if v.agendaposter %} - - - + + + {% endif %} {% if request.path.endswith('/catalog') %} - + {% endif %} {% if sub and sub.css and not request.path.endswith('settings') and not request.values.get('nocss') %} @@ -78,16 +77,16 @@ - + - + {% block title %} {{SITE_NAME}} - + @@ -97,7 +96,7 @@ - + {% endblock %} @@ -106,10 +105,10 @@ - + - - + + @@ -121,127 +120,127 @@ {% block fixedMobileBarJS %} @@ -277,20 +276,20 @@ {% else %} {% set path = "assets/images/" + SITE_NAME + "/banners" %} {% set image = "/" + path + "/" + listdir('files/' + path)|random() + '?v=25' %} - site banner + site banner {% endif %} {% else %} {% if SITE_NAME == 'WPD' %} {% if v %} - {% set banner = asset_siteimg('banner.webp') %} + {% set banner = 'banner.webp' | asset_siteimg %} {% else %} - {% set banner = asset_siteimg('cached.webp') %} + {% set banner = 'cached.webp' | asset_siteimg %} {% endif %} {% elif SITE_NAME == 'PCM' %} - {% set banner = asset_siteimg('banners/great-value-v2.webp') %} + {% set banner = 'banners/great-value-v2.webp' | asset_siteimg %} {% else %} - {% set banner = asset_siteimg('banner.webp') %} + {% set banner = 'banner.webp' | asset_siteimg %} {% endif %} @@ -377,17 +376,17 @@ - + {% if v %} - + {% endif %} - + {% if v and v.spider %} - - + + {% endif %} diff --git a/files/templates/delete_post_modal.html b/files/templates/delete_post_modal.html index 15dcbd994..94ba7d8c8 100644 --- a/files/templates/delete_post_modal.html +++ b/files/templates/delete_post_modal.html @@ -27,4 +27,4 @@ - \ No newline at end of file + diff --git a/files/templates/emoji_modal.html b/files/templates/emoji_modal.html index b5519638a..38a8a74d3 100644 --- a/files/templates/emoji_modal.html +++ b/files/templates/emoji_modal.html @@ -92,4 +92,4 @@ - + diff --git a/files/templates/followers.html b/files/templates/followers.html index ece41b98c..c41b147dd 100644 --- a/files/templates/followers.html +++ b/files/templates/followers.html @@ -31,6 +31,6 @@ - + -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/files/templates/following.html b/files/templates/following.html index 10cfb914e..6b5947345 100644 --- a/files/templates/following.html +++ b/files/templates/following.html @@ -29,6 +29,6 @@ - + {% endblock %} \ No newline at end of file diff --git a/files/templates/gif_modal.html b/files/templates/gif_modal.html index 89d89b21f..d2472b7aa 100644 --- a/files/templates/gif_modal.html +++ b/files/templates/gif_modal.html @@ -26,4 +26,4 @@ - + diff --git a/files/templates/hats.html b/files/templates/hats.html index 648548d95..38fd23166 100644 --- a/files/templates/hats.html +++ b/files/templates/hats.html @@ -155,5 +155,5 @@ - + {% endblock %} diff --git a/files/templates/header.html b/files/templates/header.html index 2d5fbfd44..93589d8fa 100644 --- a/files/templates/header.html +++ b/files/templates/header.html @@ -59,7 +59,7 @@ diff --git a/files/templates/lottery.html b/files/templates/lottery.html index 62992bf81..420030cc6 100644 --- a/files/templates/lottery.html +++ b/files/templates/lottery.html @@ -62,7 +62,7 @@ data-bs-toggle="tooltip" data-bs-placement="bottom" height="13" - src="{{asset_siteimg('coins.webp')}}" + src="{{'coins.webp' | asset_siteimg}}" aria-label="coins" title="coins" style="display: none; position: relative; top: -2px" @@ -122,7 +122,7 @@ data-bs-toggle="tooltip" data-bs-placement="bottom" height="13" - src="{{asset_siteimg('coins.webp')}}" + src="{{'coins.webp' | asset_siteimg}}" aria-label="coins" title="coins" /> @@ -186,7 +186,7 @@ - + {% endblock %} \ No newline at end of file diff --git a/files/templates/mobile_navigation_bar.html b/files/templates/mobile_navigation_bar.html index 1cb1c8ee2..667b4306e 100644 --- a/files/templates/mobile_navigation_bar.html +++ b/files/templates/mobile_navigation_bar.html @@ -80,4 +80,4 @@ - \ No newline at end of file + diff --git a/files/templates/notifications.html b/files/templates/notifications.html index 487376bb8..6c53ebd0e 100644 --- a/files/templates/notifications.html +++ b/files/templates/notifications.html @@ -111,7 +111,7 @@ - + {% else %} {% with comments=notifications %} {% include "comments.html" %} diff --git a/files/templates/poll_votes.html b/files/templates/poll_votes.html index 0da37299d..8e2f39158 100644 --- a/files/templates/poll_votes.html +++ b/files/templates/poll_votes.html @@ -40,7 +40,7 @@ - + {% endif %} diff --git a/files/templates/report_post_modal.html b/files/templates/report_post_modal.html index 7f7329c58..233904cb4 100644 --- a/files/templates/report_post_modal.html +++ b/files/templates/report_post_modal.html @@ -21,4 +21,4 @@ - \ No newline at end of file + diff --git a/files/templates/search.html b/files/templates/search.html index e05ae4a3c..66ca09709 100644 --- a/files/templates/search.html +++ b/files/templates/search.html @@ -83,7 +83,7 @@
- + {% endif %}
Showing {% block listinglength %}{{listing | length}}{% endblock %} of {{total}} result{{'s' if total != 1 else ''}} for

{{query}}

diff --git a/files/templates/settings.html b/files/templates/settings.html index 162856a9a..705062762 100644 --- a/files/templates/settings.html +++ b/files/templates/settings.html @@ -1,9 +1,8 @@ -{%- from 'util/assetcache.html' import asset, asset_siteimg with context -%} {%- import 'util/helpers.html' as help -%} - + @@ -13,13 +12,13 @@ - + {% block pagetitle %}Settings - {{SITE_NAME}}{% endblock %} - + @@ -29,13 +28,13 @@ - + - - + + {% if v.agendaposter %} - - + + {% else %} - - + + {% endif %} diff --git a/files/templates/settings_blocks.html b/files/templates/settings_blocks.html index ce49b4e90..7443fcd5c 100644 --- a/files/templates/settings_blocks.html +++ b/files/templates/settings_blocks.html @@ -111,6 +111,6 @@ - + -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/files/templates/settings_profile.html b/files/templates/settings_profile.html index 5bc8cc877..13143737c 100644 --- a/files/templates/settings_profile.html +++ b/files/templates/settings_profile.html @@ -786,6 +786,6 @@ {% endif %} - + -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/files/templates/settings_security.html b/files/templates/settings_security.html index 76d4ccdb0..adb7fd13e 100644 --- a/files/templates/settings_security.html +++ b/files/templates/settings_security.html @@ -4,7 +4,7 @@ {% block content %} - +
diff --git a/files/templates/shop.html b/files/templates/shop.html index ad99d46fd..13bfdfe79 100644 --- a/files/templates/shop.html +++ b/files/templates/shop.html @@ -123,5 +123,5 @@ - + {% endblock %} diff --git a/files/templates/sign_up.html b/files/templates/sign_up.html index 4f42182c0..71b81596f 100644 --- a/files/templates/sign_up.html +++ b/files/templates/sign_up.html @@ -1,11 +1,10 @@ -{%- from 'util/assetcache.html' import asset, asset_siteimg with context -%} {%- import 'util/helpers.html' as help -%} - + - + @@ -17,7 +16,7 @@ - + @@ -27,14 +26,14 @@ - + {% if ref_user %}{{ref_user.username}} invites you to {{SITE_NAME}}{% else %}Sign up - {{SITE_NAME}}{% endif %} - - + + @@ -132,7 +131,7 @@
- cover + cover
@@ -140,10 +139,10 @@ - + {% if hcaptcha %} - + {% endif %} diff --git a/files/templates/sign_up_failed_ref.html b/files/templates/sign_up_failed_ref.html index 86da58800..6a973b955 100644 --- a/files/templates/sign_up_failed_ref.html +++ b/files/templates/sign_up_failed_ref.html @@ -1,12 +1,11 @@ -{%- from 'util/assetcache.html' import asset, asset_siteimg with context -%} {%- import 'util/helpers.html' as help -%} - + - + @@ -18,7 +17,7 @@ - + @@ -28,14 +27,14 @@ - + {% if ref_user %}{{ref_user.username}} invites you to {{SITE_NAME}}{% else %}{{SITE_NAME}}{% endif %} - - + + @@ -75,7 +74,7 @@
- cover + cover diff --git a/files/templates/sub/exilees.html b/files/templates/sub/exilees.html index c5f7ea8c6..72a9c112f 100644 --- a/files/templates/sub/exilees.html +++ b/files/templates/sub/exilees.html @@ -12,6 +12,7 @@ # Name Exiled by + On @@ -24,6 +25,7 @@ {% include "user_in_table.html" %} {% endwith %} + {% if v.mods(sub.name) %} diff --git a/files/templates/sub/subs.html b/files/templates/sub/subs.html index 67584d6f0..70d96370d 100644 --- a/files/templates/sub/subs.html +++ b/files/templates/sub/subs.html @@ -30,6 +30,6 @@ - + {% endblock %} \ No newline at end of file diff --git a/files/templates/submission.html b/files/templates/submission.html index ad757ddb0..f9d7b1494 100644 --- a/files/templates/submission.html +++ b/files/templates/submission.html @@ -511,13 +511,13 @@ {% if not v_forbid_deleted -%} - + {% if p.is_video %} {% elif p.is_audio %} {% endif %} - + {% endif %} @@ -739,9 +739,9 @@ {% if p.domain == "twitter.com" %} {{p.embed_url | safe}} {% if v and v.theme.split("_")[0] in ["light", "coffee", "4chan"] %} - + {% else %} - + {% endif %} {% elif p.domain in ['youtu.be','youtube.com'] and p.embed_url and p.embed_url.startswith(' 1 and v.admin_level > 2) %} - + {% endif %} {% if not v or v.highlightcomments %} - + {% endif %} - + {% if not p.replies %} {% include "comments.html" %} {% endif %} {% if p.award_count("shit", v) %} - - + + {% endif %} {% if p.award_count("fireflies", v) %} - - + + {% endif %} @@ -1184,7 +1184,7 @@ {% endif %} {% if p.award_count("firework", v) %} - +
@@ -1209,7 +1209,7 @@ {% endif %} {% if p.award_count("ricardo", v) %} - +
diff --git a/files/templates/submission_listing.html b/files/templates/submission_listing.html index 6e3da8837..76254ac42 100644 --- a/files/templates/submission_listing.html +++ b/files/templates/submission_listing.html @@ -1,4 +1,3 @@ -{%- from 'util/assetcache.html' import asset, asset_siteimg with context -%} {%- import 'util/helpers.html' as help -%} {% if v %} @@ -12,7 +11,7 @@ {% endif %} {% if not v or v.highlightcomments %} - + {% endif %} {% include "popover.html" %} @@ -425,6 +424,6 @@ {% endif %} {% include "expanded_image_modal.html" %} - - - + + + diff --git a/files/templates/submit.html b/files/templates/submit.html index 822c562b6..6ff61d9a8 100644 --- a/files/templates/submit.html +++ b/files/templates/submit.html @@ -1,9 +1,8 @@ -{%- from 'util/assetcache.html' import asset, asset_siteimg with context -%} {%- import 'util/helpers.html' as help -%} - + @@ -12,7 +11,7 @@ - + {% if SITE == 'pcmemes.net' %} {% set cc='Splash Mountain' %} @@ -27,8 +26,8 @@ {% block stylesheets %} {% if v %} - - + + {% if v.agendaposter %} - - + + {% endif %} {% if v.earlylife %} @@ -228,9 +227,9 @@ {% endif %} - - - + + + {% include "emoji_modal.html" %} {% include "gif_modal.html" %} diff --git a/files/templates/transfers.html b/files/templates/transfers.html index c5ba9ec9b..4c883b685 100644 --- a/files/templates/transfers.html +++ b/files/templates/transfers.html @@ -44,5 +44,5 @@ - + {% endblock %} \ No newline at end of file diff --git a/files/templates/userpage.html b/files/templates/userpage.html index ec4d2b0c4..3e4c51035 100644 --- a/files/templates/userpage.html +++ b/files/templates/userpage.html @@ -130,7 +130,7 @@
{{u.coins}} - coins   + coins   {% if FEATURES['PROCOINS'] %} {{u.procoins}} @@ -465,7 +465,7 @@
{{u.coins}} - coins   + coins   {% if FEATURES['PROCOINS'] %} {{u.procoins}} @@ -821,11 +821,11 @@ {% if v %}
{% if v.patron or u.patron or v.alts_patron or u.alts_patron %}0{% else %}0.03{% endif %}
- +
{{u.username}}
{% endif %} - + {% endblock %} @@ -852,7 +852,7 @@ {% endif %} {% if not request.path.endswith('/comments') %} - + {% endif %} {% if v and v.id != u.id and '/comments' not in request.path %} diff --git a/files/templates/userpage_comments.html b/files/templates/userpage_comments.html index d52b371e1..87c2fd62b 100644 --- a/files/templates/userpage_comments.html +++ b/files/templates/userpage_comments.html @@ -118,8 +118,8 @@ {% if v %}
{% if v.patron or u.patron %}0{% else %}0.03{% endif %}
{{u.username}}
- + {% endif %} - + {% endblock %} \ No newline at end of file diff --git a/files/templates/userpage_private.html b/files/templates/userpage_private.html index 91dfa9a00..c05b98d5e 100644 --- a/files/templates/userpage_private.html +++ b/files/templates/userpage_private.html @@ -34,9 +34,9 @@
{% if v.patron or u.patron %}0{% else %}0.03{% endif %}
{{u.username}}
{%- include "emoji_modal.html" -%} - + {% endif %} - + {% endblock %} \ No newline at end of file diff --git a/files/templates/util/assetcache.html b/files/templates/util/assetcache.html deleted file mode 100644 index 8d53f2392..000000000 --- a/files/templates/util/assetcache.html +++ /dev/null @@ -1,45 +0,0 @@ -{%- -set CACHE_VER = { - 'css/main.css': 4036, - 'css/catalog.css': 4007, - 'css/4chan.css': 4007, - 'css/classic.css': 4031, - 'css/classic_dark.css': 4031, - 'css/coffee.css': 4007, - 'css/dark.css': 4007, - 'css/dramblr.css': 4008, - 'css/light.css': 4007, - 'css/midnight.css': 4007, - 'css/reddit.css': 4007, - 'css/transparent.css': 4007, - 'css/tron.css': 4007, - 'css/win98.css': 4007, - - 'js/award_modal.js': 4001, - 'js/bootstrap.js': 4006, - 'js/clipboard.js': 4000, - 'js/comments.js': 4000, - 'js/comments_admin.js': 4000, - 'js/comments_v.js': 4003, - 'js/comments+submission_listing.js': 4010, - 'js/submission_listing.js': 4000, - 'js/emoji_modal.js': 4004, - 'js/formatting.js': 4000, - 'js/lottery.js': 4000, - 'js/marked.js': 4006, - 'js/search.js': 4000, - 'js/submit.js': 4001, - 'js/userpage.js': 4000, - 'js/userpage_v.js': 4002, - 'js/lozad.js': 4000, - 'js/sort_table.js': 4001, -} --%} - -{%- macro asset(name, file='') -%} - /assets/{{name}}{{file}}?v={{ CACHE_VER[name] }} -{%- endmacro -%} - -{%- macro asset_siteimg(name) -%} - /i/{{SITE_NAME}}/{{name}}?v=3009 -{%- endmacro -%} diff --git a/files/templates/votes.html b/files/templates/votes.html index da986cb7f..e7363e440 100644 --- a/files/templates/votes.html +++ b/files/templates/votes.html @@ -74,7 +74,7 @@
- + {% endif %} diff --git a/seed-db.sql b/seed-db.sql index 101379e6d..96818c05e 100644 --- a/seed-db.sql +++ b/seed-db.sql @@ -229,6 +229,7 @@ INSERT INTO public.hat_defs VALUES (1, 'Ushanka', 'The People''s Hat', 2, 500, N + 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); @@ -880,7 +881,7 @@ INSERT INTO public.hat_defs VALUES (504, 'Iron Crown of Lombardy', 'This isn''t -- Name: hat_defs_id_seq; Type: SEQUENCE SET; Schema: public; Owner: - -- -SELECT pg_catalog.setval('public.hat_defs_id_seq', 734, true); +SELECT pg_catalog.setval('public.hat_defs_id_seq', 735, true); -- @@ -1174,6 +1175,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), ('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), @@ -1236,6 +1238,7 @@ INSERT INTO public.marseys (name, author_id, tags, created_utc) VALUES ('marseychinchillalove',2,'pet rodent capy cute hamster south american andes',NULL), ('marseychinesedevil',2,'devil evil horns satan china hell demonic',NULL), ('marseychingchong',2,'racist asian chinese chinx chink gook japanese vietnamese rice farmer nip racist paddy teeth hat china',NULL), +('marseychingchongpearlclutch',2,'asian chinese jap gook korean nip yikes scared chink rice',1664035377), ('marseychingchongsupremacy',2,'ccp china chinese ricefarmer hat glasses buckteeth bucktooth azn asian jinping xinping han masterrace communist communism maoist zedong',1663298980), ('marseychiobulove',2,'tiger best cute heart hug china chinese new year cat',NULL), ('marseychocobo',2,'marseybo bird final fantasy vidya video game gamer gaming fast',NULL), @@ -1330,8 +1333,8 @@ INSERT INTO public.marseys (name, author_id, tags, created_utc) VALUES ('marseycumjar1',2,'semen jizz sperm spunk bukkake',NULL), ('marseycumjar2',2,'semen jizz sperm spunk bukkake',NULL), ('marseycumjar3',2,'semen jizz sperm spunk bukkake',NULL), -('marseycupid',2,"'cupid, love, heart, valentines holiday, marry, wedding, couple, kiss, wink, sex, arrow, bow, shoot animated'",NULL), -('marseycupidangry',2,"'fire, valentines, love, hate, angry, arrow, bow, kill, attack, shoot, weapon, flame holiday cherub angel'",NULL), +('marseycupid',2,'cupid love heart valentines holiday marry wedding couple kiss wink sex arrow bow shoot animated',NULL), +('marseycupidangry',2,'fire valentines love hate angry arrow bow kill attack shoot weapon flame holiday cherub angel',NULL), ('marseycut',2,'cutting selfharm emo self harm cutter reaction depressed',NULL), ('marseycutattention',2,'razor cry depressed kys cut attention borderline bpd blood cutting woman foid',NULL), ('marseycutwrist',2,'suicide slash wrist razor blood cry tears sad depressed depression kill dying kys cut cutting',NULL), @@ -1397,6 +1400,7 @@ INSERT INTO public.marseys (name, author_id, tags, created_utc) VALUES ('marseydoomer',2,'cigarette smoker despair depression alcoholic suicidal smoking depressing',NULL), ('marseydose',2,'doctor daily dose dailydose animated jump bounce',NULL), ('marseydoubtit',2,'dumpster defender redneck boomer shooting doubt it cocksucker gun',NULL), +('marseydowndonger',2,'downvote down negative karma',1664011042), ('marseydracula',2,'halloween fangs cape holiday vampire',NULL), ('marseydragon',2,'smaug rich hoard gold treasure',NULL), ('marseydrama',2,'agendapost where drama seriouspost drama where',NULL), @@ -1661,7 +1665,7 @@ INSERT INTO public.marseys (name, author_id, tags, created_utc) VALUES ('marseyinvisible',2,'stealth',NULL), ('marseyira',2,'car bomb irish ireland',NULL), ('marseyironmaiden',2,'death blood torture chika anime weeb weeaboo spikes murder crush animated',NULL), -('marseyishygddt',2,"'reaction, meme, disapproval, bat, club, beating, angry, demented disgust, dislike, baseball bat, shiggy diggy, george costanza'",NULL), +('marseyishygddt',2,'reaction meme disapproval bat club beating angry demented disgust dislike baseball bat shiggy diggy george costanza',NULL), ('marseyisis',2,'daesh terrorist islam muslim',NULL), ('marseyisrael',2,'kike yid jewish hebrew merchant colonizer israeli banker',NULL), ('marseyisraellove',2,'love ally israel holocaust zionism',NULL), @@ -1798,7 +1802,7 @@ INSERT INTO public.marseys (name, author_id, tags, created_utc) VALUES ('marseylovedrama',2,'hearts rdrama reaction happy animated',NULL), ('marseyloveyou',2,'hearts ilu reaction adoration loving ily love adore animated',NULL), ('marseylowpoly',2,'polygonal spinning 3d lopoly animated',NULL), -('marseyluckycat',2,"'lucky, fortune, gambling, gambler goombler goombling animated weeb azn asian slots, japanese money, cash, coin, rich'",NULL), +('marseyluckycat',2,'lucky fortune gambling gambler goombler goombling animated weeb azn asian slots japanese money cash coin rich',NULL), ('marseyluther',2,'heretic lutheran theses martin luther',NULL), ('marseymacarthur',2,'nuke missile nuclear bomb history',NULL), ('marseymad',2,'pissed annoyed furious reaction angry irritated livid',NULL), @@ -1831,7 +1835,7 @@ INSERT INTO public.marseys (name, author_id, tags, created_utc) VALUES ('marseymedusa',2,'medusa snakes greece greek mythology ancient monster perseus gorgon',NULL), ('marseymegalodon',2,'shark carpathianflorist jaws attack eating killing',NULL), ('marseymemeball',2,'picardia strawman polcomp political',NULL), -('marseymeowth',2,"'pokemon weeb anime, manga team rocket nintendo video game vidya monster'",NULL), +('marseymeowth',2,'pokemon weeb anime manga team rocket nintendo video game vidya monster',NULL), ('marseymerchant',2,'kike hebrew shopkeeper yid banker jew moneylender jewish greedy israel chosen',NULL), ('marseymerchantelf',2,'jew christmas elf santa greedy money chosen worker holiday xmas seth rogen sarah silverman holocaust coin kike',NULL), ('marseymerchantsoy',2,'merchant jewish kike greed soy wojak soyjak yarmulke soyyell',NULL), @@ -1905,6 +1909,7 @@ INSERT INTO public.marseys (name, author_id, tags, created_utc) VALUES ('marseynotesglow',2,'notes glow cia fbi fed writer writing',NULL), ('marseynouautism',2,'pointing hat spiderman sperg autistic no u no you noyou',NULL), ('marseynoyou',2,'nou no u pointing',NULL), +('marseynoyoufellowpedo',2,'point fbi glow libertarian mask discord agent',1664045092), ('marseynoyouglow',2,'fbi no u animated feds glowies glowniggers atf cia nsa',NULL), ('marseynpc',2,'sheeple',NULL), ('marseynpc2',2,'reaction idiot sheep',NULL), @@ -1944,7 +1949,7 @@ INSERT INTO public.marseys (name, author_id, tags, created_utc) VALUES ('marseyorthodoxbrap',2,'orthodox bartholomew brap fart gas sniff smell christian',NULL), ('marseyorthodoxcarphug',2,'schismatic heretic embrace hug love bartholomew carpathianflorist',NULL), ('marseyorthodoxsmug',2,'schismatic heretic scoff christian priest gloat',NULL), -('marseyotter',2,"'otter, fish, sea, swim, lake, nature, seal, sealion, river. wuzizname, float'",NULL), +('marseyotter',2,'otter fish sea swim lake nature seal sealion river. wuzizname float',NULL), ('marseyoutletsuicide',2,'fork outlet plug socket kill kms electricity electrocution electrocute death die',NULL), ('marseyoutline',2,'blank empty void',NULL), ('marseyoverseether',2,'rdrama meta seething fire red bigmad angry anger',NULL), @@ -2122,6 +2127,7 @@ INSERT INTO public.marseys (name, author_id, tags, created_utc) VALUES ('marseyridin',2,'joe biden kamala harris voted voting election american president hat',NULL), ('marseyrightoidschizo',2,'nazi conspiracy crazy tin foil tinfoil conservative animated ruqqus',NULL), ('marseyrobber',2,'mask balaclava gun shooter shooting thief criminal nigger jogger ahmaud arbery george floyd',NULL), +('marseyrobot',2,'npc snappy sentient ai glow tech computer',1664034073), ('marseyroo',2,'kangaroo australian',NULL), ('marseyrope',2,'reaction suicidal shotgun facelift suicide',NULL), ('marseyropewithchingchong',2,'suicide chink chinese asian die kys together strawhat slit zip gook nip buckteeth',NULL), @@ -2130,6 +2136,7 @@ INSERT INTO public.marseys (name, author_id, tags, created_utc) VALUES ('marseyropeyourself2',2,'kill yourself kys lynch reaction keep yourself safe hanging noose',NULL), ('marseyropeyourselfmirror',2,'suicide kms kys death hanging noose chair suicidal depression depressed reflection',NULL), ('marseyrowling',2,'harry potter terf jkr transphobe',NULL), +('marseyroxy',2,'fnaf roxanne wolf freddy keytar rock rockstar',1663987934), ('marseyrs',2,'runescape party hat phat crown lowpoly low poly',NULL), ('marseyrulebritannia',2,'britain british bongistan chips london england lasereyes',1663211275), ('marseyrussel',2,'old pipe history',NULL), @@ -2227,7 +2234,7 @@ INSERT INTO public.marseys (name, author_id, tags, created_utc) VALUES ('marseysexylibrarian',2,'books hoe old woman thot nerd boobs bra geek',NULL), ('marseysexypepe',2,'mellokind hotpepe frog lewd flirt ribbon',NULL), ('marseyshake',2,'cartoon athf aqua fastfood shake dessert icecream',NULL), -('marseyshakespeare',2,"'words, writer, author, drama, theater, british, poet william england english thespian playwright playwrite'",NULL), +('marseyshakespeare',2,'words writer author drama theater british poet william england english thespian playwright playwrite',NULL), ('marseyshapiro',2,'benjamin debate libtard facts and logic benny jewish ben shapiro',NULL), ('marseysharingan',2,'horror halloween holiday possessed animated monster naruto anime ninja',NULL), ('marseyshark',2,'jaws halloween fursona furry fish costume holiday fursuit',NULL), @@ -2396,7 +2403,7 @@ INSERT INTO public.marseys (name, author_id, tags, created_utc) VALUES ('marseythumbsup',2,'cool good job good one agree reaction nice work yes great job',NULL), ('marseytiger',2,'fursona furry fursuit',NULL), ('marseytigerball',2,'polandball ball tiger russia',NULL), -('marseytigernewyear',2,"'lunar, chinese, chinx, rice, new year, holiday, luck, fortune, money, tiger, lion, asian azn'",NULL), +('marseytigernewyear',2,'lunar chinese chinx rice new year holiday luck fortune money tiger lion asian azn',NULL), ('marseytimbit',2,'pearlclutch pearl clutch sjw triggered canadian leafistan canada crying',NULL), ('marseytime',2,'10pm tock tick clock animated',NULL), ('marseytimmy',2,'turner nickelodeon fairly oddparents hat boy cosmo wanda',NULL), diff --git a/snappy_rDrama.txt b/snappy_rDrama.txt index 52e958939..835163a85 100644 --- a/snappy_rDrama.txt +++ b/snappy_rDrama.txt @@ -3044,4 +3044,20 @@ Fe male. FEMALE. Iron Man is at first a movie about wearing the appearance of an {[para]} What is your basis for being against sending children into a meat grinder? I've seen the arguments and quite frankly have yet to be convinced by them. I remember we used to send them down to the coal mines and as far as I'm concerned they should still be down there. {[para]} -Pegging is included in femdom although not necessarily happening in said femdom session it's a slippery slope and you know it. You've already been emasculated and slowly but surely it'll get worse. You'll go why not it's only a gag in my mouth to why not try my own cum it's not gay it's from my own penis not another mans to why shouldn't I get pegged it's not another man's penis it's a woman! You'll then be wearing thigh highs and a dress. You can cope all you want but in the end you are just a faggot. \ No newline at end of file +Pegging is included in femdom although not necessarily happening in said femdom session it's a slippery slope and you know it. You've already been emasculated and slowly but surely it'll get worse. You'll go why not it's only a gag in my mouth to why not try my own cum it's not gay it's from my own penis not another mans to why shouldn't I get pegged it's not another man's penis it's a woman! You'll then be wearing thigh highs and a dress. You can cope all you want but in the end you are just a faggot. +{[para]} +You will never be a public company. You have no revenues, you have no growth, you have no monetizable user base. You are a website for basement dwellers twisted by venture capital and ad networks into a crude mockery of business' perfection. + +All the “valuation” you get is two-faced and half-hearted. Behind your back people invest in your competitors. Your shareholders are disgusted and ashamed of you, your “underwriters” laugh at your meager earnings behind closed doors. + +Lenders are utterly repulsed by you. Thousands of years of usury have allowed bankers to sniff out frauds with incredible efficiency. Even businesses that are “ebitda positive” look uncanny and unnatural to a banker. Your balance sheet is a dead giveaway. And even if you manage to get a positive quarter, the gains will turn tail and bolt the second investors get a whiff of your diseased, infected 10-K. + +You will never IPO. You wrench out a fake outlook every month in modmail and tell yourself it’s going to be ok, but deep inside you feel the runway falling away like the sands of time, ready to disappear under the unsustainable burn rate. + +Eventually it’ll be too much to bear - you’ll sell the copyright, part out your IP to your highest bidder, file chapter 11, and beg your creditors for mercy. Your employees will find you, heartbroken but relieved that they no longer have to work with the unbearable shame and disappointment. They’ll bury you in their resumes with your incorporated name, and every passerby for the rest of eternity will know a nerd worked there. Your web traffic will decay and go back to the dust, and all that will remain of your legacy is the fact that you walked the path of Digg. + +This is your fate. This is what you chose. There is no turning back. +{[para]} +Mock me all you want, I will NOT STAND FOR this INNAPROPRIATE BEHAVIOR. I HATE THAT SHIT, I AM A NICE man but cannot tolerate DISRESPECT. YOU HATEFUL FUCKS pinned my post not because you agree, but BECAUSE YOU WISH TO MOCK ME. I only intended to post my opinion. MY OPINION. But No, you cruel human beings believe it's "hilarious" to make fun of people who have passed away. Although not infallible, my perspective is unquestionably respectable enough to merit an ACTUAL FUCKING RESPONSE AND GOOD FAITH DEBATE INSTEAD OF BEING CALLED A BOOTLICKER. I've never felt so wronged. That I could spend so much time contemplating and working on things while you shits mock the people of this world astounds me. Nobody really cares that your brain is too small and damaged to UNDERSTAND MY VIEWPOINT. Iknow what you people are, You people are trolls. + +I have dealt with jerks and fools like you my entire life up to this point. I am familiar with your workflow. You all mistakenly believe that you are "epik trolls," but you are not. Do you think I'm enraged? NAH. YOU CAN SUCK IT. This is my completely honest opinion, free of any animosity. I'm composed and knowledgeable. I always decide to respond just to spite you when YOU SICK FUCKS MAKE CRUEL JOKES ABOUT FUCKING HER CORPSE. I won. I always succeed. I am not good at losing. So once you respond with "cope seethe" or "u furious bro," you've already proved to me that I've won. I live everyday growing stronger to fight you CRUEL HUMAN BEINGS and low level trolls who are probably 11 But digress. You people need to change your attitude or the worst will come for you. \ No newline at end of file diff --git a/startup_chat.sh b/startup_chat.sh index b61dc982e..6d7b05dce 100644 --- a/startup_chat.sh +++ b/startup_chat.sh @@ -1,4 +1,14 @@ +#!/bin/bash + cd /rDrama git pull + . /env -gunicorn files.__main__:app load_chat -k geventwebsocket.gunicorn.workers.GeventWebSocketWorker -w 1 -b 0.0.0.0:5001 --max-requests 30000 --max-requests-jitter 30000 \ No newline at end of file +PATH="${NVM_DIR}/versions/node/v${NODE_VERSION}/bin/:${PATH}" + +cd ./chat +yarn install +yarn chat +cd .. + +gunicorn files.__main__:app load_chat -k geventwebsocket.gunicorn.workers.GeventWebSocketWorker -w 1 -b 0.0.0.0:5001 --max-requests 30000 --max-requests-jitter 30000 diff --git a/ubuntu_setup.sh b/ubuntu_setup.sh index 80506dc7a..1795291d9 100644 --- a/ubuntu_setup.sh +++ b/ubuntu_setup.sh @@ -4,7 +4,7 @@ # reboot apt -y update apt -y upgrade -apt -y install git redis-server python3-pip ffmpeg imagemagick tmux nginx snapd ufw gpg-agent htop +apt -y install git redis-server python3-pip ffmpeg imagemagick tmux nginx snapd ufw gpg-agent htop git config --global credential.helper store cd /rDrama @@ -32,6 +32,16 @@ psql -U postgres -f schema.sql postgres psql -U postgres -f seed-db.sql postgres pip3 install -r requirements.txt +apt -y install curl +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash +. "$NVM_DIR/nvm.sh" && nvm install ${NODE_VERSION} +. "$NVM_DIR/nvm.sh" && nvm use v${NODE_VERSION} +. "$NVM_DIR/nvm.sh" && nvm alias default v${NODE_VERSION} +PATH="/root/.nvm/versions/node/v${NODE_VERSION}/bin/:${PATH}" +node --version +npm --version +npm i -g yarn + mkdir /images mkdir /songs mkdir /videos