Merge branch 'master' into feature-multiple-sub-banners
9
.cookies
|
@ -1,9 +0,0 @@
|
|||
# Netscape HTTP Cookie File
|
||||
# This file is generated by youtube-dl. Do not edit.
|
||||
|
||||
.youtube.com TRUE / TRUE 1670617632 GPS 1
|
||||
.youtube.com TRUE / TRUE 1686122687 VISITOR_INFO1_LIVE Z0qo6y1x43g
|
||||
.youtube.com TRUE / TRUE 0 YSC X7P6d8R9T4I
|
||||
.youtube.com TRUE / TRUE 1686122708 __Secure-3PAPISID V15R47kUEcecf2e6/Anq8BG6Hc8s3_B4aU
|
||||
.youtube.com TRUE / TRUE 1686122708 __Secure-3PSID Rgi3mkz3GttQzOzz5BydFq1VJYJxYYsNX7tSsaWVvdV5OjMrGX4VQesgyjqm7MEb_U9QbA.
|
||||
.youtube.com TRUE / TRUE 1702106955 __Secure-3PSIDCC AIKkIs2XJmFoUqmOzZTlvJO6WXpOpP8OwPdrLG7E2hC2DR6IFy_vz0PraZdTy36zFrYJBGuY
|
|
@ -1,4 +1,206 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
.fa-align-left:before{content:"\f036"}
|
||||
.fa-long-arrow-left:before{content:"\f177"}
|
||||
.fa-arrow-right:before{content:"\f061"}
|
||||
.fa-sign-out:before{content:"\f08b"}
|
||||
.fa-long-arrow-right:before{content:"\f178"}
|
||||
.fa-arrows-v:before{content:"\f07d"}
|
||||
.fa-award:before{content:"\f559"}
|
||||
.fa-badge:before{content:"\f335"}
|
||||
.fa-badge-check:before{content:"\f336"}
|
||||
.fa-ban:before{content:"\f05e"}
|
||||
.fa-bars:before{content:"\f0c9"}
|
||||
.fa-bell:before{content:"\f0f3"}
|
||||
.fa-bold:before{content:"\f032"}
|
||||
.fa-book:before{content:"\f02d"}
|
||||
.fa-book-open:before{content:"\f518"}
|
||||
.fa-book-dead:before{content:"\f6b7"}
|
||||
.fa-broom:before{content:"\f51a"}
|
||||
.fa-bug:before{content:"\f188"}
|
||||
.fa-bullhorn:before{content:"\f0a1"}
|
||||
.fa-calendar:before{content:"\f133"}
|
||||
.fa-calendar-day:before{content:"\f783"}
|
||||
.fa-calendar-alt:before{content:"\f073"}
|
||||
.fa-calendar-week:before{content:"\f784"}
|
||||
.fa-campfire:before{content:"\f6ba"}
|
||||
.fa-candy-cane:before{content:"\f786"}
|
||||
.fa-car-tilt:before{content:"\f5e5"}
|
||||
.fa-cat:before{content:"\f6be"}
|
||||
.fa-check:before{content:"\f00c"}
|
||||
.fa-circle:before{content:"\f111"}
|
||||
.fa-check-circle:before{content:"\f058"}
|
||||
.fa-arrow-alt-circle-down:before{content:"\f358"}
|
||||
.fa-exclamation-circle:before{content:"\f06a"}
|
||||
.fa-info-circle:before{content:"\f05a"}
|
||||
.fa-radiation-alt:before{content:"\f7ba"}
|
||||
.fa-arrow-alt-circle-up:before{content:"\f35b"}
|
||||
.fa-user-circle:before{content:"\f2bd"}
|
||||
.fa-times-circle:before{content:"\f057"}
|
||||
.fa-clipboard:before{content:"\f328"}
|
||||
.fa-clipboard-check:before{content:"\f46c"}
|
||||
.fa-clock:before{content:"\f017"}
|
||||
.fa-history:before{content:"\f1da"}
|
||||
.fa-code:before{content:"\f121"}
|
||||
.fa-comment:before{content:"\f075"}
|
||||
.fa-comment-dots:before{content:"\f4ad"}
|
||||
.fa-comments:before{content:"\f086"}
|
||||
.fa-copy:before{content:"\f0c5"}
|
||||
.fa-crown:before{content:"\f521"}
|
||||
.fa-dice-six:before{content:"\f526"}
|
||||
.fa-dollar-sign:before{content:"\24"}
|
||||
.fa-arrow-alt-down:before{content:"\f354"}
|
||||
.fa-compress-alt:before{content:"\f422"}
|
||||
.fa-ellipsis-h:before{content:"\f141"}
|
||||
.fa-envelope:before{content:"\f0e0"}
|
||||
.fa-envelope-open-text:before{content:"\f658"}
|
||||
.fa-eye:before{content:"\f06e"}
|
||||
.fa-eye-evil:before{content:"\f6db"}
|
||||
.fa-eye-slash:before{content:"\f070"}
|
||||
.fa-angry:before{content:"\f556"}
|
||||
.fa-frown:before{content:"\f119"}
|
||||
.fa-grin-beam-sweat:before{content:"\f583"}
|
||||
.fa-laugh-squint:before{content:"\f59b"}
|
||||
.fa-smile-beam:before{content:"\f5b8"}
|
||||
.fa-feather-alt:before{content:"\f56b"}
|
||||
.fa-file-signature:before{content:"\f573"}
|
||||
.fa-filter:before{content:"\f0b0"}
|
||||
.fa-fire:before{content:"\f06d"}
|
||||
.fa-fireplace:before{content:"\f79a"}
|
||||
.fa-fish:before{content:"\f578"}
|
||||
.fa-flag:before{content:"\f024"}
|
||||
.fa-flag-usa:before{content:"\f74d"}
|
||||
.fa-save:before{content:"\f0c7"}
|
||||
.fa-gavel:before{content:"\f0e3"}
|
||||
.fa-cog:before{content:"\f013"}
|
||||
.fa-ghost:before{content:"\f6e2"}
|
||||
.fa-gift:before{content:"\f06b"}
|
||||
.fa-gingerbread-man:before{content:"\f79d"}
|
||||
.fa-globe:before{content:"\f0ac"}
|
||||
.fa-home-alt:before{content:"\f015"}
|
||||
.fa-id-badge:before{content:"\f2c1"}
|
||||
.fa-id-card:before{content:"\f2c2"}
|
||||
.fa-image:before{content:"\f03e"}
|
||||
.fa-infinity:before{content:"\f534"}
|
||||
.fa-italic:before{content:"\f033"}
|
||||
.fa-knife-kitchen:before{content:"\f6f5"}
|
||||
.fa-lights-holiday:before{content:"\f7b2"}
|
||||
.fa-link:before{content:"\f0c1"}
|
||||
.fa-link-slash:before{content:"\f127"}
|
||||
.fa-lock:before{content:"\f023"}
|
||||
.fa-lock-alt:before{content:"\f30d"}
|
||||
.fa-search:before{content:"\f002"}
|
||||
.fa-cloudflare:before{content:"\e07d"}
|
||||
.fa-comment-alt-smile:before{content:"\f4aa"}
|
||||
.fa-microphone-stand:before{content:"\f8cb"}
|
||||
.fa-palette:before{content:"\f53f"}
|
||||
.fa-edit:before{content:"\f044"}
|
||||
.fa-pizza-slice:before{content:"\f818"}
|
||||
.fa-poop:before{content:"\f619"}
|
||||
.fa-quote-right:before{content:"\f10e"}
|
||||
.fa-reply:before{content:"\f3e5"}
|
||||
.fa-robot:before{content:"\f544"}
|
||||
.fa-sack-dollar:before{content:"\f81d"}
|
||||
.fa-scroll-old:before{content:"\f70f"}
|
||||
.fa-seedling:before{content:"\f4d8"}
|
||||
.fa-shield:before{content:"\f132"}
|
||||
.fa-random:before{content:"\f074"}
|
||||
.fa-smoke:before{content:"\f760"}
|
||||
.fa-snooze:before{content:"\f880"}
|
||||
.fa-snowflake:before{content:"\f2dc"}
|
||||
.fa-sparkles:before{content:"\f890"}
|
||||
.fa-ticket:before{content:"\f145"}
|
||||
.fa-cards:before{content:"\e3ed"}
|
||||
.fa-spider:before{content:"\f717"}
|
||||
.fa-square:before{content:"\f0c8"}
|
||||
.fa-stocking:before{content:"\f7d5"}
|
||||
.fa-store:before{content:"\f54e"}
|
||||
.fa-columns:before{content:"\f0db"}
|
||||
.fa-thumbtack:before{content:"\f08d"}
|
||||
.fa-train:before{content:"\f238"}
|
||||
.fa-trash-alt:before{content:"\f2ed"}
|
||||
.fa-exclamation-triangle:before{content:"\f071"}
|
||||
.fa-trophy:before{content:"\f091"}
|
||||
.fa-arrow-alt-up:before{content:"\f357"}
|
||||
.fa-expand-alt:before{content:"\f424"}
|
||||
.fa-external-link-alt:before{content:"\f35d"}
|
||||
.fa-user:before{content:"\f007"}
|
||||
.fa-user-crown:before{content:"\f6a4"}
|
||||
.fa-user-cog:before{content:"\f4fe"}
|
||||
.fa-user-friends:before{content:"\f500"}
|
||||
.fa-user-lock:before{content:"\f502"}
|
||||
.fa-user-minus:before{content:"\f503"}
|
||||
.fa-user-plus:before{content:"\f234"}
|
||||
.fa-user-slash:before{content:"\f506"}
|
||||
.fa-user-tag:before{content:"\f507"}
|
||||
.fa-user-times:before{content:"\f235"}
|
||||
.fa-users:before{content:"\f0c0"}
|
||||
.fa-volume:before{content:"\f6a8"}
|
||||
.fa-volume-mute:before{content:"\f6a9"}
|
||||
.fa-times:before{content:"\f00d"}
|
||||
.fa-mobile:before{content:"\f3ce"}
|
||||
.fa-discord:before{content:"\f392"}
|
||||
.fa-github:before{content:"\f09b"}
|
||||
.fa-twitter:before{content:"\f099"}
|
||||
.fa-git-alt:before{content:"\f841"}
|
||||
.fa-head-side:before{content:"\f6e9"}
|
||||
.fa-crab:before{content:"\e3ff"}
|
||||
.fa-socks:before{content:"\f696"}
|
||||
.fa-arrow-up:before{content:"\f062"}
|
||||
.fa-tag:before{content:"\f02b"}
|
||||
.fa-messages:before{content:"\f4b6"}
|
||||
.fa-user-secret:before{content:"\f21b"}
|
||||
.fa-gas-pump-slash:before{content:"\f5f4"}
|
||||
.fa-gas-pump:before{content:"\f52f"}
|
||||
.fa-hammer-crash:before{content:"\e414"}
|
||||
.fa-music:before{content:"\f001"}
|
||||
.fa-arrow-rotate-right:before{content:"\f01e"}
|
||||
.fa-columns-3:before{content:"\e361"}
|
||||
.fa-bahai:before{content:"\f666"}
|
||||
.fa-party-horn:before{content:"\e31b"}
|
||||
.fa-pinata:before{content:"\e3c3"}
|
||||
.fa-file:before{content:"\f15b"}
|
||||
.fa-box-open:before{content:"\f49e"}
|
||||
.fa-eyes:before{content:"\e367"}
|
||||
.fa-hexagon:before{content:"\f312"}
|
||||
.fa-arrow-right-arrow-left:before{content:"\f0ec"}
|
||||
.fa-coins:before{content:"\f51e"}
|
||||
.fa-bell-slash:before{content:"\f1f6"}
|
||||
.fa-chart-network:before{content:"\f78a"}
|
||||
.fa-square-share-nodes:before{content:"\f1e1"}
|
||||
.fa-sidebar:before{content:"\e24e"}
|
||||
.fa-panorama:before{content:"\e209"}
|
||||
.fa-external-link:before{content:"\f08e"}
|
||||
.fa-circle-info:before{content:"\f05a"}
|
||||
.fa-comment-question:before{content:"\e14b"}
|
||||
.fa-sitemap:before{content:"\f0e8"}
|
||||
.fa-grid:before{content:"\e195"}
|
||||
.fa-x:before{content:"\58"}
|
||||
.fa-paw-simple:before{content:"\f701"}
|
||||
.fa-bat:before{content:"\f6b5"}
|
||||
.fa-star-of-david:before{content:"\f69a"}
|
||||
.fa-hat-cowboy:before{content:"\f8c0"}
|
||||
.fa-cloud-rainbow:before{content:"\f73e"}
|
||||
.fa-telegram:before{content:"\f2c6"}
|
||||
.fa-css3-alt:before{content:"\f38b"}
|
||||
.fa-landscape:before{content:"\e1b5"}
|
||||
.fa-user-ninja:before{content:"\f504"}
|
||||
.fa-trees:before{content:"\f724"}
|
||||
.fa-flashlight:before{content:"\f8b8"}
|
||||
.fa-candy-corn:before{content:"\f6bd"}
|
||||
.fa-shirt:before{content:"\f553"}
|
||||
.fa-bone:before{content:"\f5d7"}
|
||||
.fa-jack-o-lantern:before{content:"\f30e"}
|
||||
.fa-cloud-bolt:before{content:"\f76c"}
|
||||
.fa-biohazard:before{content:"\f780"}
|
||||
.fa-syringe:before{content:"\f48e"}
|
||||
.fa-spider-web:before{content:"\f719"}
|
||||
.fa-coffin-cross:before{content:"\e051"}
|
||||
.fa-face-sleeping:before{content:"\e38d"}
|
||||
.fa-block-question:before{content:"\e3dd"}
|
||||
.fa-image-slash:before{content:"\e1b7"}
|
||||
.fa-play:before{content:"\f04b"}
|
||||
|
||||
button {
|
||||
background: none;
|
||||
border: none;
|
||||
|
@ -4290,8 +4492,8 @@ pre .com, code .com {
|
|||
background-color: var(--gray-600);
|
||||
}
|
||||
.custom-gutters, .user-gutters {
|
||||
padding-left: 2px;
|
||||
padding-right: 2px;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
.navbar.bg-primary {
|
||||
background-color: var(--dark) !important;
|
||||
|
@ -4894,7 +5096,7 @@ code {
|
|||
.noshadow {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
[role="button"], :not(textarea)[onclick] {
|
||||
[role="button"], :not(textarea)[onclick], th {
|
||||
cursor: pointer !important;
|
||||
}
|
||||
|
||||
|
@ -5696,6 +5898,25 @@ g {
|
|||
border-radius:.35rem;
|
||||
}
|
||||
|
||||
.video-play {
|
||||
position:absolute;
|
||||
bottom:33%;
|
||||
right:38%;
|
||||
font-size:14px;
|
||||
color:white;
|
||||
background-color:var(--primary);
|
||||
padding: 5px 6px 4px 7px;
|
||||
border-radius:.35rem;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.video-play {
|
||||
bottom:31%;
|
||||
right:36%;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------- Font Awesome ------- */
|
||||
@font-face{
|
||||
font-family:"Font Awesome 6 Pro";
|
||||
|
@ -5876,206 +6097,6 @@ g {
|
|||
.fa-stack-1x{line-height:inherit}
|
||||
.fa-stack-2x{font-size:2em}
|
||||
|
||||
.fa-align-left:before{content:"\f036"}
|
||||
.fa-long-arrow-left:before{content:"\f177"}
|
||||
.fa-arrow-right:before{content:"\f061"}
|
||||
.fa-sign-out:before{content:"\f08b"}
|
||||
.fa-long-arrow-right:before{content:"\f178"}
|
||||
.fa-arrows-v:before{content:"\f07d"}
|
||||
.fa-award:before{content:"\f559"}
|
||||
.fa-badge:before{content:"\f335"}
|
||||
.fa-badge-check:before{content:"\f336"}
|
||||
.fa-ban:before{content:"\f05e"}
|
||||
.fa-bars:before{content:"\f0c9"}
|
||||
.fa-bell:before{content:"\f0f3"}
|
||||
.fa-bold:before{content:"\f032"}
|
||||
.fa-book:before{content:"\f02d"}
|
||||
.fa-book-open:before{content:"\f518"}
|
||||
.fa-book-dead:before{content:"\f6b7"}
|
||||
.fa-broom:before{content:"\f51a"}
|
||||
.fa-bug:before{content:"\f188"}
|
||||
.fa-bullhorn:before{content:"\f0a1"}
|
||||
.fa-calendar:before{content:"\f133"}
|
||||
.fa-calendar-day:before{content:"\f783"}
|
||||
.fa-calendar-alt:before{content:"\f073"}
|
||||
.fa-calendar-week:before{content:"\f784"}
|
||||
.fa-campfire:before{content:"\f6ba"}
|
||||
.fa-candy-cane:before{content:"\f786"}
|
||||
.fa-car-tilt:before{content:"\f5e5"}
|
||||
.fa-cat:before{content:"\f6be"}
|
||||
.fa-check:before{content:"\f00c"}
|
||||
.fa-circle:before{content:"\f111"}
|
||||
.fa-check-circle:before{content:"\f058"}
|
||||
.fa-arrow-alt-circle-down:before{content:"\f358"}
|
||||
.fa-exclamation-circle:before{content:"\f06a"}
|
||||
.fa-info-circle:before{content:"\f05a"}
|
||||
.fa-radiation-alt:before{content:"\f7ba"}
|
||||
.fa-arrow-alt-circle-up:before{content:"\f35b"}
|
||||
.fa-user-circle:before{content:"\f2bd"}
|
||||
.fa-times-circle:before{content:"\f057"}
|
||||
.fa-clipboard:before{content:"\f328"}
|
||||
.fa-clipboard-check:before{content:"\f46c"}
|
||||
.fa-clock:before{content:"\f017"}
|
||||
.fa-history:before{content:"\f1da"}
|
||||
.fa-code:before{content:"\f121"}
|
||||
.fa-comment:before{content:"\f075"}
|
||||
.fa-comment-dots:before{content:"\f4ad"}
|
||||
.fa-comments:before{content:"\f086"}
|
||||
.fa-copy:before{content:"\f0c5"}
|
||||
.fa-crown:before{content:"\f521"}
|
||||
.fa-dice-six:before{content:"\f526"}
|
||||
.fa-dollar-sign:before{content:"\24"}
|
||||
.fa-arrow-alt-down:before{content:"\f354"}
|
||||
.fa-compress-alt:before{content:"\f422"}
|
||||
.fa-ellipsis-h:before{content:"\f141"}
|
||||
.fa-envelope:before{content:"\f0e0"}
|
||||
.fa-envelope-open-text:before{content:"\f658"}
|
||||
.fa-eye:before{content:"\f06e"}
|
||||
.fa-eye-evil:before{content:"\f6db"}
|
||||
.fa-eye-slash:before{content:"\f070"}
|
||||
.fa-angry:before{content:"\f556"}
|
||||
.fa-frown:before{content:"\f119"}
|
||||
.fa-grin-beam-sweat:before{content:"\f583"}
|
||||
.fa-laugh-squint:before{content:"\f59b"}
|
||||
.fa-smile-beam:before{content:"\f5b8"}
|
||||
.fa-feather-alt:before{content:"\f56b"}
|
||||
.fa-file-signature:before{content:"\f573"}
|
||||
.fa-filter:before{content:"\f0b0"}
|
||||
.fa-fire:before{content:"\f06d"}
|
||||
.fa-fireplace:before{content:"\f79a"}
|
||||
.fa-fish:before{content:"\f578"}
|
||||
.fa-flag:before{content:"\f024"}
|
||||
.fa-flag-usa:before{content:"\f74d"}
|
||||
.fa-save:before{content:"\f0c7"}
|
||||
.fa-gavel:before{content:"\f0e3"}
|
||||
.fa-cog:before{content:"\f013"}
|
||||
.fa-ghost:before{content:"\f6e2"}
|
||||
.fa-gift:before{content:"\f06b"}
|
||||
.fa-gingerbread-man:before{content:"\f79d"}
|
||||
.fa-globe:before{content:"\f0ac"}
|
||||
.fa-home-alt:before{content:"\f015"}
|
||||
.fa-id-badge:before{content:"\f2c1"}
|
||||
.fa-id-card:before{content:"\f2c2"}
|
||||
.fa-image:before{content:"\f03e"}
|
||||
.fa-infinity:before{content:"\f534"}
|
||||
.fa-italic:before{content:"\f033"}
|
||||
.fa-knife-kitchen:before{content:"\f6f5"}
|
||||
.fa-lights-holiday:before{content:"\f7b2"}
|
||||
.fa-link:before{content:"\f0c1"}
|
||||
.fa-link-slash:before{content:"\f127"}
|
||||
.fa-lock:before{content:"\f023"}
|
||||
.fa-lock-alt:before{content:"\f30d"}
|
||||
.fa-search:before{content:"\f002"}
|
||||
.fa-cloudflare:before{content:"\e07d"}
|
||||
.fa-comment-alt-smile:before{content:"\f4aa"}
|
||||
.fa-microphone-stand:before{content:"\f8cb"}
|
||||
.fa-palette:before{content:"\f53f"}
|
||||
.fa-edit:before{content:"\f044"}
|
||||
.fa-pizza-slice:before{content:"\f818"}
|
||||
.fa-poop:before{content:"\f619"}
|
||||
.fa-quote-right:before{content:"\f10e"}
|
||||
.fa-reply:before{content:"\f3e5"}
|
||||
.fa-robot:before{content:"\f544"}
|
||||
.fa-sack-dollar:before{content:"\f81d"}
|
||||
.fa-scroll-old:before{content:"\f70f"}
|
||||
.fa-seedling:before{content:"\f4d8"}
|
||||
.fa-shield:before{content:"\f132"}
|
||||
.fa-random:before{content:"\f074"}
|
||||
.fa-smoke:before{content:"\f760"}
|
||||
.fa-snooze:before{content:"\f880"}
|
||||
.fa-snowflake:before{content:"\f2dc"}
|
||||
.fa-sparkles:before{content:"\f890"}
|
||||
.fa-ticket:before{content:"\f145"}
|
||||
.fa-cards:before{content:"\e3ed"}
|
||||
.fa-spider:before{content:"\f717"}
|
||||
.fa-square:before{content:"\f0c8"}
|
||||
.fa-stocking:before{content:"\f7d5"}
|
||||
.fa-store:before{content:"\f54e"}
|
||||
.fa-columns:before{content:"\f0db"}
|
||||
.fa-thumbtack:before{content:"\f08d"}
|
||||
.fa-train:before{content:"\f238"}
|
||||
.fa-trash-alt:before{content:"\f2ed"}
|
||||
.fa-exclamation-triangle:before{content:"\f071"}
|
||||
.fa-trophy:before{content:"\f091"}
|
||||
.fa-arrow-alt-up:before{content:"\f357"}
|
||||
.fa-expand-alt:before{content:"\f424"}
|
||||
.fa-external-link-alt:before{content:"\f35d"}
|
||||
.fa-user:before{content:"\f007"}
|
||||
.fa-user-crown:before{content:"\f6a4"}
|
||||
.fa-user-cog:before{content:"\f4fe"}
|
||||
.fa-user-friends:before{content:"\f500"}
|
||||
.fa-user-lock:before{content:"\f502"}
|
||||
.fa-user-minus:before{content:"\f503"}
|
||||
.fa-user-plus:before{content:"\f234"}
|
||||
.fa-user-slash:before{content:"\f506"}
|
||||
.fa-user-tag:before{content:"\f507"}
|
||||
.fa-user-times:before{content:"\f235"}
|
||||
.fa-users:before{content:"\f0c0"}
|
||||
.fa-volume:before{content:"\f6a8"}
|
||||
.fa-volume-mute:before{content:"\f6a9"}
|
||||
.fa-times:before{content:"\f00d"}
|
||||
.fa-mobile:before{content:"\f3ce"}
|
||||
.fa-discord:before{content:"\f392"}
|
||||
.fa-github:before{content:"\f09b"}
|
||||
.fa-twitter:before{content:"\f099"}
|
||||
.fa-git-alt:before{content:"\f841"}
|
||||
.fa-head-side:before{content:"\f6e9"}
|
||||
.fa-crab:before{content:"\e3ff"}
|
||||
.fa-socks:before{content:"\f696"}
|
||||
.fa-arrow-up:before{content:"\f062"}
|
||||
.fa-tag:before{content:"\f02b"}
|
||||
.fa-messages:before{content:"\f4b6"}
|
||||
.fa-user-secret:before{content:"\f21b"}
|
||||
.fa-gas-pump-slash:before{content:"\f5f4"}
|
||||
.fa-gas-pump:before{content:"\f52f"}
|
||||
.fa-hammer-crash:before{content:"\e414"}
|
||||
.fa-music:before{content:"\f001"}
|
||||
.fa-arrow-rotate-right:before{content:"\f01e"}
|
||||
.fa-columns-3:before{content:"\e361"}
|
||||
.fa-bahai:before{content:"\f666"}
|
||||
.fa-party-horn:before{content:"\e31b"}
|
||||
.fa-pinata:before{content:"\e3c3"}
|
||||
.fa-file:before{content:"\f15b"}
|
||||
.fa-box-open:before{content:"\f49e"}
|
||||
.fa-eyes:before{content:"\e367"}
|
||||
.fa-hexagon:before{content:"\f312"}
|
||||
.fa-arrow-right-arrow-left:before{content:"\f0ec"}
|
||||
.fa-coins:before{content:"\f51e"}
|
||||
.fa-bell-slash:before{content:"\f1f6"}
|
||||
.fa-chart-network:before{content:"\f78a"}
|
||||
.fa-square-share-nodes:before{content:"\f1e1"}
|
||||
.fa-sidebar:before{content:"\e24e"}
|
||||
.fa-panorama:before{content:"\e209"}
|
||||
.fa-external-link:before{content:"\f08e"}
|
||||
.fa-circle-info:before{content:"\f05a"}
|
||||
.fa-comment-question:before{content:"\e14b"}
|
||||
.fa-sitemap:before{content:"\f0e8"}
|
||||
.fa-grid:before{content:"\e195"}
|
||||
.fa-x:before{content:"\58"}
|
||||
.fa-paw-simple:before{content:"\f701"}
|
||||
.fa-bat:before{content:"\f6b5"}
|
||||
.fa-star-of-david:before{content:"\f69a"}
|
||||
.fa-hat-cowboy:before{content:"\f8c0"}
|
||||
.fa-cloud-rainbow:before{content:"\f73e"}
|
||||
.fa-telegram:before{content:"\f2c6"}
|
||||
.fa-css3-alt:before{content:"\f38b"}
|
||||
.fa-landscape:before{content:"\e1b5"}
|
||||
.fa-user-ninja:before{content:"\f504"}
|
||||
.fa-trees:before{content:"\f724"}
|
||||
.fa-flashlight:before{content:"\f8b8"}
|
||||
.fa-candy-corn:before{content:"\f6bd"}
|
||||
.fa-shirt:before{content:"\f553"}
|
||||
.fa-bone:before{content:"\f5d7"}
|
||||
.fa-jack-o-lantern:before{content:"\f30e"}
|
||||
.fa-cloud-bolt:before{content:"\f76c"}
|
||||
.fa-biohazard:before{content:"\f780"}
|
||||
.fa-syringe:before{content:"\f48e"}
|
||||
.fa-spider-web:before{content:"\f719"}
|
||||
.fa-coffin-cross:before{content:"\e051"}
|
||||
.fa-face-sleeping:before{content:"\e38d"}
|
||||
.fa-block-question:before{content:"\e3dd"}
|
||||
.fa-image-slash:before{content:"\e1b7"}
|
||||
|
||||
.pronouns {
|
||||
font-size: 9px;
|
||||
margin-left: 0.25rem;
|
||||
|
@ -6407,7 +6428,7 @@ div.markdown {
|
|||
}
|
||||
|
||||
:root {
|
||||
--signature-max-height: 250px;
|
||||
--signature-max-height: 300px;
|
||||
}
|
||||
|
||||
.user-signature {
|
||||
|
@ -6415,10 +6436,6 @@ div.markdown {
|
|||
overflow: clip;
|
||||
}
|
||||
|
||||
.user-signature video {
|
||||
height: var(--signature-max-height);
|
||||
}
|
||||
|
||||
.award-name {
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
|
@ -6444,3 +6461,31 @@ div.markdown {
|
|||
.sub-banner-update-section .sub-settings-subsection {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.resizable {
|
||||
resize:both;
|
||||
display:inline-block;
|
||||
overflow: auto;
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
}
|
||||
.resizable::-webkit-scrollbar {
|
||||
background: transparent;
|
||||
}
|
||||
.resizable > video {
|
||||
height:100%!important;
|
||||
max-height:100%!important;
|
||||
margin:0!important;
|
||||
}
|
||||
.bigger {
|
||||
height:50vh;
|
||||
}
|
||||
|
||||
.user-signature video {
|
||||
max-height: min(var(--signature-max-height),50vh) !important;
|
||||
}
|
||||
|
||||
.comment-text lite-youtube, #post-text lite-youtube {
|
||||
max-width: 500px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
|
After Width: | Height: | Size: 539 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 243 KiB |
After Width: | Height: | Size: 244 KiB |
After Width: | Height: | Size: 244 KiB |
After Width: | Height: | Size: 267 KiB |
After Width: | Height: | Size: 243 KiB |
After Width: | Height: | Size: 247 KiB |
After Width: | Height: | Size: 270 KiB |
After Width: | Height: | Size: 248 KiB |
After Width: | Height: | Size: 248 KiB |
Before Width: | Height: | Size: 710 B After Width: | Height: | Size: 198 B |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 9.3 KiB |
After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 472 KiB |
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 9.8 KiB |
After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 9.2 KiB |
After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 24 KiB |
|
@ -233,12 +233,6 @@ function expandDesktopImage(url) {
|
|||
bootstrap.Modal.getOrCreateInstance(document.getElementById('expandImageModal')).show();
|
||||
};
|
||||
|
||||
document.addEventListener("click", function(e){
|
||||
const element = e.target
|
||||
if (element instanceof HTMLImageElement && element.alt.startsWith('![]('))
|
||||
expandDesktopImage()
|
||||
});
|
||||
|
||||
function bs_trigger(e) {
|
||||
let tooltipTriggerList = [].slice.call(e.querySelectorAll('[data-bs-toggle="tooltip"]'));
|
||||
tooltipTriggerList.map(function(element){
|
||||
|
@ -342,7 +336,7 @@ function areyousure(t) {
|
|||
else
|
||||
t.innerHTML = t.innerHTML.replace(t.textContent, 'Are you sure?')
|
||||
|
||||
t.setAttribute("onclick", t.dataset.click2);
|
||||
t.setAttribute("onclick", t.dataset.click);
|
||||
|
||||
if (t.dataset.dismiss)
|
||||
t.setAttribute("data-bs-dismiss", t.dataset.dismiss);
|
||||
|
@ -404,3 +398,51 @@ function sendFormXHRSwitch(e) {
|
|||
}
|
||||
)
|
||||
}
|
||||
|
||||
let sortAscending = {};
|
||||
|
||||
function sort_table(t) {
|
||||
const n = Array.prototype.indexOf.call(t.parentElement.children, t);
|
||||
const table = this.event.target.parentElement.parentElement.parentElement
|
||||
const rows = table.rows;
|
||||
let items = [];
|
||||
for (let i = 1; i < rows.length; i++) {
|
||||
const ele = rows[i];
|
||||
let x = rows[i].getElementsByTagName("TD")[n];
|
||||
if (!('sortKey' in x.dataset)) {
|
||||
x = x.getElementsByTagName('a')[0] || x;
|
||||
}
|
||||
let attr;
|
||||
if ('sortKey' in x.dataset) {
|
||||
attr = x.dataset.sortKey;
|
||||
} else if ('time' in x.dataset) {
|
||||
attr = parseInt(x.dataset.time);
|
||||
} else {
|
||||
attr = x.innerText
|
||||
if (/^[\d-,]+$/.test(x.innerHTML)) {
|
||||
attr = parseInt(attr.replace(/,/g, ''))
|
||||
}
|
||||
}
|
||||
items.push({ele, attr});
|
||||
}
|
||||
if (sortAscending[n]) {
|
||||
items.sort((a, b) => a.attr > b.attr ? 1 : -1);
|
||||
sortAscending[n] = false;
|
||||
} else {
|
||||
items.sort((a, b) => a.attr < b.attr ? 1 : -1);
|
||||
sortAscending[n] = true;
|
||||
}
|
||||
|
||||
for (let i = items.length - 1; i--;) {
|
||||
items[i].ele.parentNode.insertBefore(items[i].ele, items[i + 1].ele);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
document.addEventListener("click", function(e){
|
||||
const element = e.target
|
||||
if (element instanceof HTMLImageElement && element.alt.startsWith('![]('))
|
||||
expandDesktopImage()
|
||||
else if (element.tagName == "TH")
|
||||
sort_table(element)
|
||||
});
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
let sortAscending = {};
|
||||
|
||||
function sort_table(n) {
|
||||
const table = this.event.target.parentElement.parentElement.parentElement
|
||||
const rows = table.rows;
|
||||
let items = [];
|
||||
for (let i = 1; i < rows.length; i++) {
|
||||
const ele = rows[i];
|
||||
let x = rows[i].getElementsByTagName("TD")[n];
|
||||
if (!('sortKey' in x.dataset)) {
|
||||
x = x.getElementsByTagName('a')[0] || x;
|
||||
}
|
||||
let attr;
|
||||
if ('sortKey' in x.dataset) {
|
||||
attr = x.dataset.sortKey;
|
||||
} else if ('time' in x.dataset) {
|
||||
attr = parseInt(x.dataset.time);
|
||||
} else {
|
||||
attr = parseInt(x.innerHTML.replace(/,/g, ''));
|
||||
}
|
||||
items.push({ ele, attr });
|
||||
}
|
||||
if (sortAscending[n]) {
|
||||
items.sort((a, b) => a.attr > b.attr ? 1 : -1);
|
||||
sortAscending[n] = false;
|
||||
} else {
|
||||
items.sort((a, b) => a.attr < b.attr ? 1 : -1);
|
||||
sortAscending[n] = true;
|
||||
}
|
||||
|
||||
for (let i = items.length - 1; i--;) {
|
||||
items[i].ele.parentNode.insertBefore(items[i].ele, items[i + 1].ele);
|
||||
}
|
||||
}
|
|
@ -307,7 +307,8 @@ class Comment(Base):
|
|||
|
||||
if not body: return ""
|
||||
|
||||
body = censor_slurs(body, v).replace('<img loading="lazy" data-bs-toggle="tooltip" alt=":marseytrain:" title=":marseytrain:" src="/e/marseytrain.webp">', ':marseytrain:')
|
||||
body = censor_slurs(body, v).replace('<img loading="lazy" data-bs-toggle="tooltip" alt=":marseytrain:" title=":marseytrain:" src="/e/marseytrain.webp">', ':marseytrain:') \
|
||||
.replace('<img loading="lazy" data-bs-toggle="tooltip" alt=":marseysleep:" title=":marseysleep:" src="/e/marseysleep.webp">', ':marseysleep:')
|
||||
|
||||
return body
|
||||
|
||||
|
|
|
@ -153,7 +153,7 @@ class Submission(Base):
|
|||
elif self.thumburl:
|
||||
if self.thumburl.startswith('/'): return SITE_FULL + self.thumburl
|
||||
return self.thumburl
|
||||
elif self.is_youtube or self.is_video: return f"{SITE_FULL}/i/default_thumb_video.webp?v=1"
|
||||
elif self.is_youtube or self.is_video: return f"{SITE_FULL}/i/default_thumb_video.webp?v=2"
|
||||
elif self.is_audio: return f"{SITE_FULL}/i/default_thumb_audio.webp?v=1"
|
||||
elif self.domain.split('.')[0] == SITE.split('.')[0]:
|
||||
return f"{SITE_FULL}/i/{SITE_NAME}/site_preview.webp?v=3009"
|
||||
|
@ -297,7 +297,7 @@ class Submission(Base):
|
|||
body += " - <b>WINNER!</b>"
|
||||
|
||||
if not winner and v and v.admin_level >= PERMS['POST_BETS_DISTRIBUTE']:
|
||||
body += f'''<button class="btn btn-primary distribute" data-click2="postToastReload(this,'/distribute/{o.id}')" onclick="areyousure(this)">Declare winner</button>'''
|
||||
body += f'''<button class="btn btn-primary distribute" data-click="postToastReload(this,'/distribute/{o.id}')" onclick="areyousure(this)">Declare winner</button>'''
|
||||
body += "</div>"
|
||||
else:
|
||||
input_type = 'radio' if o.exclusive else 'checkbox'
|
||||
|
@ -329,7 +329,9 @@ class Submission(Base):
|
|||
body = self.body
|
||||
if not body: return ""
|
||||
|
||||
body = censor_slurs(body, v).replace('<img loading="lazy" data-bs-toggle="tooltip" alt=":marseytrain:" title=":marseytrain:" src="/e/marseytrain.webp">', ':marseytrain:')
|
||||
body = censor_slurs(body, v).replace('<img loading="lazy" data-bs-toggle="tooltip" alt=":marseytrain:" title=":marseytrain:" src="/e/marseytrain.webp">', ':marseytrain:') \
|
||||
.replace('<img loading="lazy" data-bs-toggle="tooltip" alt=":marseysleep:" title=":marseysleep:" src="/e/marseysleep.webp">', ':marseysleep:')
|
||||
|
||||
body = normalize_urls_runtime(body, v)
|
||||
|
||||
return body
|
||||
|
@ -346,7 +348,8 @@ class Submission(Base):
|
|||
def plaintitle(self, v):
|
||||
title = self.title
|
||||
|
||||
title = censor_slurs(title, v).replace('<img loading="lazy" data-bs-toggle="tooltip" alt=":marseytrain:" title=":marseytrain:" src="/e/marseytrain.webp">', ':marseytrain:')
|
||||
title = censor_slurs(title, v).replace('<img loading="lazy" data-bs-toggle="tooltip" alt=":marseytrain:" title=":marseytrain:" src="/e/marseytrain.webp">', ':marseytrain:') \
|
||||
.replace('<img loading="lazy" data-bs-toggle="tooltip" alt=":marseysleep:" title=":marseysleep:" src="/e/marseysleep.webp">', ':marseysleep:')
|
||||
|
||||
return title
|
||||
|
||||
|
|
|
@ -520,9 +520,9 @@ class User(Base):
|
|||
|
||||
@property
|
||||
@lazy
|
||||
def unban_in(self):
|
||||
def unban_string(self):
|
||||
if self.unban_utc == 0:
|
||||
return "never"
|
||||
return "permanently banned"
|
||||
|
||||
wait = self.unban_utc - int(time.time())
|
||||
|
||||
|
@ -539,43 +539,9 @@ class User(Base):
|
|||
|
||||
text = f"{days}d {hours:02d}h {mins:02d}m"
|
||||
|
||||
return text
|
||||
|
||||
|
||||
@property
|
||||
@lazy
|
||||
def unban_string(self):
|
||||
text = self.unban_in
|
||||
|
||||
if text == "never": return "permanently banned"
|
||||
|
||||
return f"Unban in {text}"
|
||||
|
||||
|
||||
@property
|
||||
@lazy
|
||||
def unchud_in(self):
|
||||
if self.agendaposter == 1:
|
||||
return "never"
|
||||
|
||||
wait = self.agendaposter - int(time.time())
|
||||
|
||||
if wait < 60:
|
||||
text = f"{wait}s"
|
||||
else:
|
||||
days = wait//(24*60*60)
|
||||
wait -= days*24*60*60
|
||||
|
||||
hours = wait//(60*60)
|
||||
wait -= hours*60*60
|
||||
|
||||
mins = wait//60
|
||||
|
||||
text = f"{days}d {hours:02d}h {mins:02d}m"
|
||||
|
||||
return text
|
||||
|
||||
|
||||
@property
|
||||
@lazy
|
||||
def received_awards(self):
|
||||
|
|
|
@ -98,7 +98,7 @@ def execute_snappy(post:Submission, v:User):
|
|||
|
||||
body += "\n\n"
|
||||
|
||||
if post.url and not post.url.startswith(SITE_FULL) and not post.url.startswith('/') and not post.url.startswith(f'https://{BAN_EVASION_DOMAIN}'):
|
||||
if post.url and not post.url.startswith('/') and not post.url.startswith(SITE_FULL) and not post.url.startswith(BAN_EVASION_FULL):
|
||||
if post.url.startswith('https://old.reddit.com/r/'):
|
||||
rev = post.url.replace('https://old.reddit.com/', '')
|
||||
rev = f"* [unddit.com](https://unddit.com/{rev})\n"
|
||||
|
@ -127,7 +127,7 @@ def execute_snappy(post:Submission, v:User):
|
|||
|
||||
|
||||
for href, title in captured:
|
||||
if href.startswith(SITE_FULL) or href.startswith(f'https://{BAN_EVASION_DOMAIN}'): continue
|
||||
if href.startswith(SITE_FULL) or href.startswith(BAN_EVASION_FULL): continue
|
||||
if "Snapshots:\n\n" not in body: body += "Snapshots:\n\n"
|
||||
if f'**[{title}]({href})**:\n\n' not in body:
|
||||
addition = f'**[{title}]({href})**:\n\n'
|
||||
|
|
|
@ -148,6 +148,7 @@ if SITE_NAME == 'rDrama':
|
|||
"it's almost as if": "I'm a retard but",
|
||||
"my brother in christ": "my brother in Allah",
|
||||
"kyle": "Kylie",
|
||||
"twitter files": 'twitter files <img loading="lazy" data-bs-toggle="tooltip" alt=":marseysleep:" title=":marseysleep:" src="/e/marseysleep.webp">',
|
||||
}
|
||||
SLURS.update(RDRAMA_SLURS)
|
||||
|
||||
|
@ -233,7 +234,6 @@ PERMS = { # Minimum admin_level to perform action.
|
|||
'HOLE_CREATE': 0,
|
||||
'EDIT_RULES': 3,
|
||||
'FLAGS_REMOVE': 2,
|
||||
'VOTES_VISIBLE': 0,
|
||||
'USER_BLOCKS_VISIBLE': 0,
|
||||
'USER_FOLLOWS_VISIBLE': 0,
|
||||
'USER_VOTERS_VISIBLE': 0,
|
||||
|
@ -399,6 +399,7 @@ POST_BODY_LENGTH_LIMIT = 20000 # do not make larger than 20000 without altering
|
|||
POST_BODY_HTML_LENGTH_LIMIT = 40000 # do not make larger than 40000 without altering the table
|
||||
COMMENT_BODY_LENGTH_LIMIT = 10000 # do not make larger than 10000 characters without altering the table
|
||||
COMMENT_BODY_HTML_LENGTH_LIMIT = 20000 # do not make larger than 20000 characters without altering the table
|
||||
CSS_LENGTH_LIMIT = 10000 # do not make larger than 20000 characters without altering the table
|
||||
COMMENT_MAX_DEPTH = 200
|
||||
TRANSFER_MESSAGE_LENGTH_LIMIT = 200 # do not make larger than 10000 characters (comment limit) without altering the table
|
||||
MIN_REPOST_CHECK_URL_LENGTH = 9 # also change the constant in checkRepost() of submit.js
|
||||
|
@ -427,38 +428,27 @@ HOLE_REQUIRED = False
|
|||
HOLE_COST = 0
|
||||
HOLE_INACTIVITY_DELETION = False
|
||||
|
||||
PRIVILEGED_USER_BOTS = ()
|
||||
GUMROAD_MESSY = ()
|
||||
|
||||
AUTOJANNY_ID = 1
|
||||
SNAPPY_ID = 2
|
||||
LONGPOSTBOT_ID = 3
|
||||
ZOZBOT_ID = 4
|
||||
BASEDBOT_ID = 0
|
||||
PRIVILEGED_USER_BOTS = ()
|
||||
|
||||
SCHIZO_ID = 0
|
||||
KIPPY_ID = 0
|
||||
MCCOX_ID = 0
|
||||
CHIOBU_ID = 0
|
||||
PIZZASHILL_ID = 0
|
||||
IMPASSIONATA_ID = 0
|
||||
HEYMOON_ID = 0
|
||||
MIMW_ID = 0
|
||||
SNUS_ID = 0
|
||||
GUMROAD_MESSY = ()
|
||||
IDIO_ID = 0
|
||||
CARP_ID = 0
|
||||
JOAN_ID = 0
|
||||
AEVANN_ID = 0
|
||||
SNAKES_ID = 0
|
||||
JUSTCOOL_ID = 0
|
||||
HOMO_ID = 0
|
||||
SOREN_ID = 0
|
||||
LAWLZ_ID = 0
|
||||
DAD_ID = 0
|
||||
MOM_ID = 0
|
||||
DONGER_ID = 0
|
||||
GEESE_ID = 0
|
||||
BLACKJACKBTZ_ID = 0
|
||||
TGTW_ID = 0
|
||||
|
||||
MODMAIL_ID = 2
|
||||
GIFT_NOTIF_ID = 5
|
||||
SIGNUP_FOLLOW_ID = 0
|
||||
|
||||
POLL_THREAD = 0
|
||||
POLL_BET_COINS = 200
|
||||
|
@ -473,8 +463,6 @@ SIDEBAR_THREAD = 0
|
|||
BANNER_THREAD = 0
|
||||
BADGE_THREAD = 0
|
||||
SNAPPY_THREAD = 0
|
||||
GIFT_NOTIF_ID = 5
|
||||
SIGNUP_FOLLOW_ID = 0
|
||||
NOTIFICATION_THREAD = 1
|
||||
|
||||
MAX_IMAGE_SIZE_BANNER_RESIZED_MB = 1
|
||||
|
@ -510,6 +498,8 @@ BADGE_BLACKLIST = { # only grantable by AEVANN_ID and SNAKES_ID except on PCM
|
|||
137, # Lottery Winner
|
||||
}
|
||||
|
||||
NOTIFIED_USERS = {}
|
||||
|
||||
if SITE == 'rdrama.net':
|
||||
FEATURES['PRONOUNS'] = True
|
||||
FEATURES['HOUSES'] = True
|
||||
|
@ -532,36 +522,58 @@ if SITE == 'rdrama.net':
|
|||
HOLE_COST = 50000
|
||||
HOLE_INACTIVITY_DELETION = True
|
||||
|
||||
PRIVILEGED_USER_BOTS = (12125,16049)
|
||||
GUMROAD_MESSY = (1230,1379)
|
||||
|
||||
AUTOJANNY_ID = 1046
|
||||
SNAPPY_ID = 261
|
||||
LONGPOSTBOT_ID = 1832
|
||||
ZOZBOT_ID = 1833
|
||||
PRIVILEGED_USER_BOTS = (12125, 16049)
|
||||
|
||||
SCHIZO_ID = 8494
|
||||
KIPPY_ID = 7150
|
||||
MCCOX_ID = 8239
|
||||
CHIOBU_ID = 5214
|
||||
PIZZASHILL_ID = 2424
|
||||
IMPASSIONATA_ID = 5800
|
||||
HEYMOON_ID = 3635
|
||||
MIMW_ID = 3377
|
||||
SNUS_ID = 8407
|
||||
GUMROAD_MESSY = (1230,1379)
|
||||
IDIO_ID = 30
|
||||
CARP_ID = 995
|
||||
JOAN_ID = 28
|
||||
AEVANN_ID = 1
|
||||
SNAKES_ID = 10288
|
||||
JUSTCOOL_ID = 4999
|
||||
HOMO_ID = 147
|
||||
SOREN_ID = 2546
|
||||
LAWLZ_ID = 3833
|
||||
DAD_ID = 2513
|
||||
MOM_ID = 4588
|
||||
DONGER_ID = 541
|
||||
GEESE_ID = 1710
|
||||
BLACKJACKBTZ_ID = 12732
|
||||
TGTW_ID = 2008
|
||||
|
||||
NOTIFIED_USERS = {
|
||||
'aevan': AEVANN_ID,
|
||||
'avean': AEVANN_ID,
|
||||
'carp': CARP_ID,
|
||||
'clit': CARP_ID,
|
||||
'snakes': SNAKES_ID,
|
||||
'sneks': SNAKES_ID,
|
||||
'snekky': SNAKES_ID,
|
||||
'snekchad': SNAKES_ID,
|
||||
'jc': JUSTCOOL_ID,
|
||||
'justcool': JUSTCOOL_ID,
|
||||
'kippy': KIPPY_ID,
|
||||
'lawlz': LAWLZ_ID,
|
||||
'transgirltradwife': TGTW_ID,
|
||||
'impassionata': IMPASSIONATA_ID,
|
||||
'pizzashill': PIZZASHILL_ID,
|
||||
|
||||
'joan': 28,
|
||||
'pewkie': 28,
|
||||
'idio3': 30,
|
||||
'idio ': 30,
|
||||
'telegram ': 30,
|
||||
'the_homocracy': 147,
|
||||
'donger': 541,
|
||||
'geese': 1710,
|
||||
'soren': 2546,
|
||||
'marseyismywaifu': 3377,
|
||||
'mimw': 3377,
|
||||
'heymoon': 3635,
|
||||
'jollymoon': 3635,
|
||||
'chiobu': 5214,
|
||||
'mccox': 8239,
|
||||
'snus': 8407,
|
||||
'schizo': 8494,
|
||||
}
|
||||
|
||||
ANTISPAM_BYPASS_IDS = {1703, 13427}
|
||||
|
||||
|
@ -714,46 +726,12 @@ bots = {AUTOJANNY_ID, SNAPPY_ID, LONGPOSTBOT_ID, ZOZBOT_ID, BASEDBOT_ID}
|
|||
COLORS = {'ff66ac','805ad5','62ca56','38a169','80ffff','2a96f3','eb4963','ff0000','f39731','30409f','3e98a7','e4432d','7b9ae4','ec72de','7f8fa6', 'f8db58','8cdbe6', DEFAULT_COLOR}
|
||||
|
||||
BAN_EVASION_DOMAIN = 'stupidpol.site'
|
||||
BAN_EVASION_FULL = f'https://{BAN_EVASION_DOMAIN}'
|
||||
|
||||
DOUBLE_XP_ENABLED = -1 # set to unixtime for when DXP begins, -1 to disable
|
||||
|
||||
### COMMENT NOTIFICATIONS ###
|
||||
|
||||
NOTIFIED_USERS = {
|
||||
'aevan': AEVANN_ID,
|
||||
'avean': AEVANN_ID,
|
||||
'joan': JOAN_ID,
|
||||
'pewkie': JOAN_ID,
|
||||
'carp': CARP_ID,
|
||||
'idio3': IDIO_ID,
|
||||
'idio ': IDIO_ID,
|
||||
'telegram ': IDIO_ID,
|
||||
'the_homocracy': HOMO_ID,
|
||||
'schizo': SCHIZO_ID,
|
||||
'snakes': SNAKES_ID,
|
||||
'sneks': SNAKES_ID,
|
||||
'snekky': SNAKES_ID,
|
||||
'snekchad': SNAKES_ID,
|
||||
'jc': JUSTCOOL_ID,
|
||||
'justcool': JUSTCOOL_ID,
|
||||
'geese': GEESE_ID,
|
||||
'clit': CARP_ID,
|
||||
'kippy': KIPPY_ID,
|
||||
'mccox': MCCOX_ID,
|
||||
|
||||
'lawlz': LAWLZ_ID,
|
||||
'chiobu': CHIOBU_ID,
|
||||
'donger': DONGER_ID,
|
||||
'soren': SOREN_ID,
|
||||
'pizzashill': PIZZASHILL_ID,
|
||||
'impassionata': IMPASSIONATA_ID,
|
||||
'heymoon': HEYMOON_ID,
|
||||
'jollymoon': HEYMOON_ID,
|
||||
'marseyismywaifu': MIMW_ID,
|
||||
'mimw': MIMW_ID,
|
||||
'snus': SNUS_ID,
|
||||
}
|
||||
|
||||
FORTUNE_REPLIES = ('<b style="color:#6023f8">Your fortune: Allah Wills It</b>','<b style="color:#d302a7">Your fortune: Inshallah, Only Good Things Shall Come To Pass</b>','<b style="color:#e7890c">Your fortune: Allah Smiles At You This Day</b>','<b style="color:#7fec11">Your fortune: Your Bussy Is In For A Blasting</b>','<b style="color:#43fd3b">Your fortune: You Will Be Propositioned By A High-Tier Twink</b>','<b style="color:#9d05da">Your fortune: Repent, You Have Displeased Allah And His Vengeance Is Nigh</b>','<b style="color:#f51c6a">Your fortune: Reply Hazy, Try Again</b>','<b style="color:#00cbb0">Your fortune: lmao you just lost 100 coins</b>','<b style="color:#2a56fb">Your fortune: Yikes 😬</b>','<b style="color:#0893e1">Your fortune: You Will Be Blessed With Many Black Bulls</b>','<b style="color:#16f174">Your fortune: NEETmax, The Day Is Lost If You Venture Outside</b>','<b style="color:#fd4d32">Your fortune: A Taste Of Jannah Awaits You Today</b>','<b style="color:#bac200">Your fortune: Watch Your Back</b>','<b style="color:#6023f8">Your fortune: Outlook good</b>','<b style="color:#d302a7">Your fortune: Godly Luck</b>','<b style="color:#e7890c">Your fortune: Good Luck</b>','<b style="color:#7fec11">Your fortune: Bad Luck</b>','<b style="color:#43fd3b">Your fortune: Good news will come to you by mail</b>','<b style="color:#9d05da">Your fortune: Very Bad Luck</b>','<b style="color:#00cbb0">Your fortune: キタ━━━━━━(゚∀゚)━━━━━━ !!!!</b>','<b style="color:#2a56fb">Your fortune: Better not tell you now</b>','<b style="color:#0893e1">Your fortune: You will meet a dark handsome stranger</b>','<b style="color:#16f174">Your fortune: ( ´_ゝ`)フーン</b>','<b style="color:#fd4d32">Your fortune: Excellent Luck</b>','<b style="color:#bac200">Your fortune: Average Luck</b>')
|
||||
FACTCHECK_REPLIES = ('<b style="color:#6023f8">Factcheck: This claim has been confirmed as correct by experts. </b>','<b style="color:#d302a7">Factcheck: This claim has been classified as misogynistic.</b>','<b style="color:#e7890c">Factcheck: This claim is currently being debunked.</b>','<b style="color:#7fec11">Factcheck: This claim is 100% true.</b>','<b style="color:#9d05da">Factcheck: This claim hurts trans lives.</b>','<b style="color:#f51c6a">Factcheck: [REDACTED].</b>','<b style="color:#00cbb0">Factcheck: This claim is both true and false.</b>','<b style="color:#2a56fb">Factcheck: You really believe that shit? Lmao dumbass nigga 🤣</b>','<b style="color:#0893e1">Factcheck: None of this is real.</b>','<b style="color:#16f174">Factcheck: Yes.</b>','<b style="color:#fd4d32">Factcheck: This claim has not been approved by experts.</b>','<b style="color:#bac200">Factcheck: This claim is a gross exageration of reality.</b>','<b style="color:#ff2200">Factcheck: WARNING! THIS CLAIM HAS BEEN CLASSIFIED AS DANGEROUS. PLEASE REMAIN STILL, AN AGENT WILL COME TO MEET YOU SHORTLY.</b>')
|
||||
EIGHTBALL_REPLIES = ('<b style="color:#7FEC11">The 8-Ball Says: It is certain.</b>', '<b style="color:#7FEC11">The 8-Ball Says: It is decidedly so.</b>', '<b style="color:#7FEC11">The 8-Ball Says: Without a doubt.</b>', '<b style="color:#7FEC11">The 8-Ball Says: Yes definitely.</b>', '<b style="color:#7FEC11">The 8-Ball Says: You may rely on it.</b>', '<b style="color:#7FEC11">The 8-Ball Says: As I see it, yes.</b>', '<b style="color:#7FEC11">The 8-Ball Says: Most likely.</b>', '<b style="color:#7FEC11">The 8-Ball Says: Outlook good.</b>', '<b style="color:#7FEC11">The 8-Ball Says: Yes.</b>', '<b style="color:#7FEC11">The 8-Ball Says: Signs point to yes.</b>', '<b style="color:#E7890C">The 8-Ball Says: Reply hazy, try again.</b>', '<b style="color:#E7890C">The 8-Ball Says: Ask again later.</b>', '<b style="color:#E7890C">The 8-Ball Says: Better not tell you now.</b>', '<b style="color:#E7890C">The 8-Ball Says: Cannot predict now.</b>', '<b style="color:#E7890C">The 8-Ball Says: Concentrate and ask again.</b>', '<b style="color:#FD4D32">The 8-Ball Says: Don\'t count on it.</b>', '<b style="color:#FD4D32">The 8-Ball Says: My reply is no.</b>', '<b style="color:#FD4D32">The 8-Ball Says: My sources say no.</b>', '<b style="color:#FD4D32">The 8-Ball Says: Outlook not so good.</b>', '<b style="color:#FD4D32">The 8-Ball Says: Very doubtful.</b>')
|
||||
|
@ -773,12 +751,12 @@ if SITE == 'rdrama.net':
|
|||
REDDIT_NOTIFS_SITE.add('justice4darrell')
|
||||
REDDIT_NOTIFS_SITE.add('cringetopia.org')
|
||||
REDDIT_NOTIFS_USERS = {
|
||||
'idio3': IDIO_ID,
|
||||
'idio3': 30,
|
||||
'aevann': AEVANN_ID,
|
||||
'carpflo': CARP_ID,
|
||||
'carpathianflorist': CARP_ID,
|
||||
'carpathian florist': CARP_ID,
|
||||
'the_homocracy': HOMO_ID,
|
||||
'the_homocracy': 147,
|
||||
'justcool393': JUSTCOOL_ID
|
||||
}
|
||||
elif SITE_NAME == 'WPD':
|
||||
|
@ -1000,6 +978,9 @@ if SITE_NAME == 'rDrama':
|
|||
'bungie.net',
|
||||
'soyjak.party',
|
||||
'teamblind.com',
|
||||
'mainchan.com',
|
||||
'encyclopediadramatica.online',
|
||||
'thecoli.com',
|
||||
|
||||
#fediverse
|
||||
'rdrama.cc',
|
||||
|
|
|
@ -236,13 +236,23 @@ MODACTION_TYPES = {
|
|||
"icon": 'fa-award',
|
||||
"color": 'bg-primary'
|
||||
},
|
||||
'set_new': {
|
||||
"str": 'changed the default sorting of comments on {self.target_link} to `new`',
|
||||
"icon": 'fa-sparkles',
|
||||
"color": 'bg-primary'
|
||||
},
|
||||
'set_hot': {
|
||||
"str": 'changed the default sorting of comments on {self.target_link} to `hot`',
|
||||
"icon": 'fa-fire',
|
||||
"color": 'bg-primary'
|
||||
},
|
||||
'set_nsfw': {
|
||||
"str": 'set nsfw on post {self.target_link}',
|
||||
"str": 'set {self.target_link} as +18',
|
||||
"icon": 'fa-eye-evil',
|
||||
"color": 'bg-danger'
|
||||
},
|
||||
'set_nsfw_comment': {
|
||||
"str": 'set nsfw on a {self.target_link}',
|
||||
"str": 'set {self.target_link} as +18',
|
||||
"icon": 'fa-eye-evil',
|
||||
"color": 'bg-danger'
|
||||
},
|
||||
|
@ -302,12 +312,12 @@ MODACTION_TYPES = {
|
|||
"color": 'bg-muted'
|
||||
},
|
||||
'unset_nsfw': {
|
||||
"str": 'un-set nsfw on post {self.target_link}',
|
||||
"str": 'unset {self.target_link} as +18',
|
||||
"icon": 'fa-eye-evil',
|
||||
"color": 'bg-success'
|
||||
},
|
||||
'unset_nsfw_comment': {
|
||||
"str": 'un-set nsfw on a {self.target_link}',
|
||||
"str": 'unset {self.target_link} as +18',
|
||||
"icon": 'fa-eye-evil',
|
||||
"color": 'bg-success'
|
||||
},
|
||||
|
|
|
@ -90,7 +90,11 @@ def _sub_inactive_purge_task():
|
|||
|
||||
posts = g.db.query(Submission).filter(Submission.sub.in_(names)).all()
|
||||
for post in posts:
|
||||
post.sub = None
|
||||
if post.sub == 'programming':
|
||||
post.sub = 'slackernews'
|
||||
else:
|
||||
post.sub = None
|
||||
|
||||
post.hole_pinned = None
|
||||
g.db.add(post)
|
||||
|
||||
|
|
|
@ -176,7 +176,7 @@ def process_image(filename:str, v, resize=0, trim=False, uploader_id:Optional[in
|
|||
path = filename.rsplit('/', 1)[0]
|
||||
kind = path.split('/')[-1]
|
||||
|
||||
if kind in ('banners','sidebar','badges'):
|
||||
if kind in ('banners','sidebar'):
|
||||
hashes = {}
|
||||
|
||||
for img in os.listdir(path):
|
||||
|
|
|
@ -40,7 +40,7 @@ controversial_regex = re.compile('["> ](https:\/\/old\.reddit\.com/r/[a-zA-Z0-9_
|
|||
|
||||
fishylinks_regex = re.compile("https?://\S+", flags=re.A)
|
||||
|
||||
spoiler_regex = re.compile('\|\|(.+)\|\|(?![^<]*<\/(code|pre|a)>)', flags=re.A)
|
||||
spoiler_regex = re.compile('\|\|(.+?)\|\|(?![^<]*<\/(code|pre|a)>)', flags=re.A)
|
||||
reddit_regex = re.compile('(^|\s|<p>)\/?((r|u)\/(\w|-){3,25})(?![^<]*<\/(code|pre|a)>)', flags=re.A)
|
||||
sub_regex = re.compile('(^|\s|<p>)\/?(h\/(\w|-){3,25})(?![^<]*<\/(code|pre|a)>)', flags=re.A)
|
||||
|
||||
|
|
|
@ -58,14 +58,12 @@ def allowed_attributes(tag, name, value):
|
|||
try: value = int(value.replace('px', ''))
|
||||
except: return False
|
||||
if 0 < value <= 250: return True
|
||||
return False
|
||||
|
||||
if tag == 'a':
|
||||
if name == 'href' and '\\' not in value and 'xn--' not in value:
|
||||
return True
|
||||
if name == 'rel' and value == 'nofollow noopener': return True
|
||||
if name == 'target' and value == '_blank': return True
|
||||
return False
|
||||
|
||||
if tag == 'img':
|
||||
if name in {'src','data-src'}: return is_safe_url(value)
|
||||
|
@ -73,38 +71,33 @@ def allowed_attributes(tag, name, value):
|
|||
if name == 'data-bs-toggle' and value == 'tooltip': return True
|
||||
if name in {'g','b','glow'} and not value: return True
|
||||
if name in {'alt','title'}: return True
|
||||
return False
|
||||
|
||||
if tag == 'lite-youtube':
|
||||
if name == 'params' and value.startswith('autoplay=1&modestbranding=1'): return True
|
||||
if name == 'videoid': return True
|
||||
return False
|
||||
|
||||
if tag == 'video':
|
||||
if name == 'controls' and value == '': return True
|
||||
if name == 'preload' and value == 'none': return True
|
||||
if name == 'src': return is_safe_url(value)
|
||||
return False
|
||||
|
||||
if tag == 'audio':
|
||||
if name == 'src': return is_safe_url(value)
|
||||
if name == 'controls' and value == '': return True
|
||||
if name == 'preload' and value == 'none': return True
|
||||
return False
|
||||
|
||||
if tag == 'p':
|
||||
if name == 'class' and value == 'mb-0': return True
|
||||
return False
|
||||
if name == 'class' and value in ('mb-0','resizable'): return True
|
||||
|
||||
if tag == 'span':
|
||||
if name == 'data-bs-toggle' and value == 'tooltip': return True
|
||||
if name == 'title': return True
|
||||
if name == 'alt': return True
|
||||
return False
|
||||
|
||||
if tag == 'table':
|
||||
if name == 'class' and value == 'table': return True
|
||||
return False
|
||||
|
||||
return False
|
||||
|
||||
def build_url_re(tlds, protocols):
|
||||
"""Builds the url regex used by linkifier
|
||||
|
@ -370,7 +363,7 @@ def sanitize(sanitized, golden=True, limit_pings=0, showmore=True, count_marseys
|
|||
|
||||
sanitized = sanitized.replace(i.group(0), htmlsource)
|
||||
|
||||
sanitized = video_sub_regex.sub(r'\1<video controls preload="none" src="\2"></video>', sanitized)
|
||||
sanitized = video_sub_regex.sub(r'\1<p class="resizable"><video controls preload="none" src="\2"></video></p>', sanitized)
|
||||
sanitized = audio_sub_regex.sub(r'\1<audio controls preload="none" src="\2"></audio>', sanitized)
|
||||
|
||||
if count_marseys:
|
||||
|
@ -429,7 +422,6 @@ def allowed_attributes_emojis(tag, name, value):
|
|||
if name == 'data-bs-toggle' and value == 'tooltip': return True
|
||||
if name == 'title': return True
|
||||
if name == 'alt': return True
|
||||
return False
|
||||
return False
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
from files.helpers.config.const import FEATURES
|
||||
|
||||
# import flask then...
|
||||
from flask import g, request, render_template, make_response, redirect, jsonify, send_from_directory, send_file
|
||||
from flask import g, request, render_template, make_response, redirect, jsonify, send_file
|
||||
|
||||
# import our app then...
|
||||
from files.__main__ import app
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import time
|
||||
from urllib.parse import quote, urlencode
|
||||
|
||||
from sqlalchemy import nullslast
|
||||
|
||||
from files.__main__ import app, cache, limiter
|
||||
from files.classes import *
|
||||
from files.helpers.actions import *
|
||||
|
@ -335,7 +337,19 @@ def revert_actions(v:User, username):
|
|||
@app.get("/admin/shadowbanned")
|
||||
@admin_level_required(PERMS['USER_SHADOWBAN'])
|
||||
def shadowbanned(v):
|
||||
users = g.db.query(User).filter(User.shadowbanned != None).order_by(User.shadowbanned).all()
|
||||
users = g.db.query(User) \
|
||||
.filter(
|
||||
User.shadowbanned != None,
|
||||
User.truescore > 0,
|
||||
not_(and_(
|
||||
User.profileurl.startswith('/e/'),
|
||||
User.customtitle==None,
|
||||
User.namecolor == DEFAULT_COLOR,
|
||||
User.patron == 0,
|
||||
))
|
||||
) \
|
||||
.order_by(nullslast(User.last_active.desc())).all()
|
||||
|
||||
return render_template("admin/shadowbanned.html", v=v, users=users)
|
||||
|
||||
|
||||
|
@ -545,6 +559,8 @@ def badge_grant_post(v):
|
|||
if '\\' in url: abort(400)
|
||||
if url.startswith(SITE_FULL):
|
||||
url = url.split(SITE_FULL, 1)[1]
|
||||
elif url.startswith(BAN_EVASION_FULL):
|
||||
url = url.split(BAN_EVASION_FULL, 1)[1]
|
||||
new_badge.url = url
|
||||
|
||||
g.db.add(new_badge)
|
||||
|
@ -1075,12 +1091,16 @@ def agendaposter(user_id, v):
|
|||
try: post = int(request.values["reason"].split("/post/")[1].split(None, 1)[0])
|
||||
except: abort(400)
|
||||
post = get_post(post)
|
||||
if post.sub == 'chudrama':
|
||||
abort(403, "You can't chud people in /h/chudrama")
|
||||
post.chuddedfor = f'{duration} by @{v.username}'
|
||||
g.db.add(post)
|
||||
elif request.values["reason"].startswith("/comment/"):
|
||||
try: comment = int(request.values["reason"].split("/comment/")[1].split(None, 1)[0])
|
||||
except: abort(400)
|
||||
comment = get_comment(comment)
|
||||
if comment.post.sub == 'chudrama':
|
||||
abort(403, "You can't chud people in /h/chudrama")
|
||||
comment.chuddedfor = f'{duration} by @{v.username}'
|
||||
g.db.add(comment)
|
||||
|
||||
|
|
|
@ -14,17 +14,7 @@ from files.__main__ import app, cache, limiter
|
|||
|
||||
ASSET_TYPES = (Marsey, HatDef)
|
||||
CAN_APPROVE_ASSETS = (AEVANN_ID, CARP_ID, SNAKES_ID)
|
||||
CAN_UPDATE_ASSETS = (AEVANN_ID, CARP_ID, SNAKES_ID, GEESE_ID, JUSTCOOL_ID)
|
||||
|
||||
@app.get('/asset_submissions/<path:path>')
|
||||
@limiter.exempt
|
||||
def asset_submissions(path):
|
||||
resp = make_response(send_from_directory('/asset_submissions', path))
|
||||
resp.headers.remove("Cache-Control")
|
||||
resp.headers.add("Cache-Control", "public, max-age=3153600")
|
||||
resp.headers.remove("Content-Type")
|
||||
resp.headers.add("Content-Type", "image/webp")
|
||||
return resp
|
||||
CAN_UPDATE_ASSETS = (AEVANN_ID, CARP_ID, SNAKES_ID)
|
||||
|
||||
@app.get("/submit/marseys")
|
||||
@auth_required
|
||||
|
|
|
@ -267,6 +267,10 @@ def award_thing(v, thing_type, id):
|
|||
else: thing.stickied_utc = t
|
||||
g.db.add(thing)
|
||||
elif kind == "agendaposter":
|
||||
if thing_type == 'post' and thing.sub == 'chudrama' \
|
||||
or thing_type == 'comment' and thing.post.sub == 'chudrama':
|
||||
abort(403, "You can't give the chud award in /h/chudrama")
|
||||
|
||||
if author.marseyawarded:
|
||||
abort(409, f"@{author.username} is under the effect of a conflicting award: Marsey award.")
|
||||
|
||||
|
|
|
@ -60,7 +60,8 @@ def post_pid_comment_cid(cid, pid=None, anything=None, v=None, sub=None):
|
|||
context -= 1
|
||||
top_comment = c
|
||||
|
||||
if v: defaultsortingcomments = v.defaultsortingcomments
|
||||
if post.new: defaultsortingcomments = 'new'
|
||||
elif v: defaultsortingcomments = v.defaultsortingcomments
|
||||
else: defaultsortingcomments = "hot"
|
||||
sort=request.values.get("sort", defaultsortingcomments)
|
||||
|
||||
|
@ -199,7 +200,7 @@ def comment(v:User):
|
|||
if v.owoify: body_for_sanitize = owoify(body_for_sanitize)
|
||||
if v.marsify: body_for_sanitize = marsify(body_for_sanitize)
|
||||
|
||||
torture = (v.agendaposter and not v.marseyawarded and post_target.sub != 'chudrama' and post_target.id not in ADMIGGER_THREADS)
|
||||
torture = (v.agendaposter and not v.marseyawarded and not (posting_to_submission and post_target.sub == 'chudrama') and post_target.id not in ADMIGGER_THREADS)
|
||||
body_html = sanitize(body_for_sanitize, limit_pings=5, count_marseys=not v.marsify, torture=torture)
|
||||
|
||||
if post_target.id not in ADMIGGER_THREADS and '!wordle' not in body.lower() and AGENDAPOSTER_PHRASE not in body.lower():
|
||||
|
|
|
@ -12,20 +12,15 @@ from files.__main__ import app, limiter
|
|||
def hats(v:User):
|
||||
owned_hat_ids = [x.hat_id for x in v.owned_hats]
|
||||
|
||||
if request.values.get("sort") == 'author_asc':
|
||||
hats = g.db.query(HatDef, User).join(HatDef.author).filter(HatDef.submitter_id == None).order_by(User.username).all()
|
||||
elif request.values.get("sort") == 'author_desc':
|
||||
hats = g.db.query(HatDef, User).join(HatDef.author).filter(HatDef.submitter_id == None).order_by(User.username.desc()).all()
|
||||
if v.equipped_hat_ids:
|
||||
equipped = g.db.query(HatDef, User).join(HatDef.author).filter(HatDef.submitter_id == None, HatDef.id.in_(owned_hat_ids), HatDef.id.in_(v.equipped_hat_ids)).order_by(HatDef.price, HatDef.name).all()
|
||||
not_equipped = g.db.query(HatDef, User).join(HatDef.author).filter(HatDef.submitter_id == None, HatDef.id.in_(owned_hat_ids), HatDef.id.notin_(v.equipped_hat_ids)).order_by(HatDef.price, HatDef.name).all()
|
||||
owned = equipped + not_equipped
|
||||
else:
|
||||
if v.equipped_hat_ids:
|
||||
equipped = g.db.query(HatDef, User).join(HatDef.author).filter(HatDef.submitter_id == None, HatDef.id.in_(owned_hat_ids), HatDef.id.in_(v.equipped_hat_ids)).order_by(HatDef.price, HatDef.name).all()
|
||||
not_equipped = g.db.query(HatDef, User).join(HatDef.author).filter(HatDef.submitter_id == None, HatDef.id.in_(owned_hat_ids), HatDef.id.notin_(v.equipped_hat_ids)).order_by(HatDef.price, HatDef.name).all()
|
||||
owned = equipped + not_equipped
|
||||
else:
|
||||
owned = g.db.query(HatDef, User).join(HatDef.author).filter(HatDef.submitter_id == None, HatDef.id.in_(owned_hat_ids)).order_by(HatDef.price, HatDef.name).all()
|
||||
owned = g.db.query(HatDef, User).join(HatDef.author).filter(HatDef.submitter_id == None, HatDef.id.in_(owned_hat_ids)).order_by(HatDef.price, HatDef.name).all()
|
||||
|
||||
not_owned = g.db.query(HatDef, User).join(HatDef.author).filter(HatDef.submitter_id == None, HatDef.id.notin_(owned_hat_ids)).order_by(HatDef.price, HatDef.name).all()
|
||||
hats = owned + not_owned
|
||||
not_owned = g.db.query(HatDef, User).join(HatDef.author).filter(HatDef.submitter_id == None, HatDef.id.notin_(owned_hat_ids)).order_by(HatDef.price, HatDef.name).all()
|
||||
hats = owned + not_owned
|
||||
|
||||
sales = g.db.query(func.sum(User.coins_spent_on_hats)).scalar()
|
||||
num_of_hats = g.db.query(HatDef).filter(HatDef.submitter_id == None).count()
|
||||
|
|
|
@ -697,6 +697,8 @@ def submit_post(v:User, sub=None):
|
|||
|
||||
if url and url.startswith(SITE_FULL):
|
||||
url = url.split(SITE_FULL)[1]
|
||||
elif url.startswith(BAN_EVASION_FULL):
|
||||
url = url.split(BAN_EVASION_FULL, 1)[1]
|
||||
|
||||
post = Submission(
|
||||
private=flag_private,
|
||||
|
@ -745,6 +747,11 @@ def submit_post(v:User, sub=None):
|
|||
post.thumburl = process_image(name2, v, resize=100)
|
||||
elif file.content_type.startswith('video/'):
|
||||
post.url = process_video(file, v)
|
||||
name = f'/images/{time.time()}'.replace('.','') + '.webp'
|
||||
subprocess.run(['ffmpeg', '-y', '-loglevel', 'warning',
|
||||
'-i', post.url, '-vf', "scale='min(300,iw)':-2",
|
||||
'-q:v', '3', '-frames:v', '1', name], check=True)
|
||||
post.thumburl = name
|
||||
elif file.content_type.startswith('audio/'):
|
||||
post.url = process_audio(file, v)
|
||||
else:
|
||||
|
@ -800,8 +807,8 @@ def submit_post(v:User, sub=None):
|
|||
execute_lawlz_actions(v, post)
|
||||
|
||||
if (SITE == 'rdrama.net'
|
||||
and v.id in (IMPASSIONATA_ID, PIZZASHILL_ID, 2008)
|
||||
and not (post.sub and post.sub.stealth)):
|
||||
and v.id in (IMPASSIONATA_ID, PIZZASHILL_ID, TGTW_ID)
|
||||
and not (post.sub and post.subr.stealth)):
|
||||
post.stickied_utc = int(time.time()) + 3600
|
||||
post.stickied = "AutoJanny"
|
||||
|
||||
|
@ -871,9 +878,9 @@ def undelete_post_pid(pid, v):
|
|||
return {"message": "Post undeleted!"}
|
||||
|
||||
|
||||
@app.post("/toggle_post_nsfw/<pid>")
|
||||
@app.post("/mark_post_nsfw/<pid>")
|
||||
@auth_required
|
||||
def toggle_post_nsfw(pid, v):
|
||||
def mark_post_nsfw(pid, v):
|
||||
post = get_post(pid)
|
||||
|
||||
if post.author_id != v.id and not v.admin_level >= PERMS['POST_COMMENT_MODERATION'] and not (post.sub and v.mods(post.sub)):
|
||||
|
@ -882,13 +889,13 @@ def toggle_post_nsfw(pid, v):
|
|||
if post.over_18 and v.is_suspended_permanently:
|
||||
abort(403)
|
||||
|
||||
post.over_18 = not post.over_18
|
||||
post.over_18 = True
|
||||
g.db.add(post)
|
||||
|
||||
if post.author_id != v.id:
|
||||
if v.admin_level >= PERMS['POST_COMMENT_MODERATION']:
|
||||
ma = ModAction(
|
||||
kind = "set_nsfw" if post.over_18 else "unset_nsfw",
|
||||
kind = "set_nsfw",
|
||||
user_id = v.id,
|
||||
target_submission_id = post.id,
|
||||
)
|
||||
|
@ -896,14 +903,48 @@ def toggle_post_nsfw(pid, v):
|
|||
else:
|
||||
ma = SubAction(
|
||||
sub = post.sub,
|
||||
kind = "set_nsfw" if post.over_18 else "unset_nsfw",
|
||||
kind = "set_nsfw",
|
||||
user_id = v.id,
|
||||
target_submission_id = post.id,
|
||||
)
|
||||
g.db.add(ma)
|
||||
send_repeatable_notification(post.author_id, f"@{v.username} (Admin) has marked [{post.title}](/post/{post.id}) as +18")
|
||||
|
||||
if post.over_18: return {"message": "Post has been marked as +18!"}
|
||||
else: return {"message": "Post has been unmarked as +18!"}
|
||||
return {"message": "Post has been marked as +18!"}
|
||||
|
||||
@app.post("/unmark_post_nsfw/<pid>")
|
||||
@auth_required
|
||||
def unmark_post_nsfw(pid, v):
|
||||
post = get_post(pid)
|
||||
|
||||
if post.author_id != v.id and not v.admin_level >= PERMS['POST_COMMENT_MODERATION'] and not (post.sub and v.mods(post.sub)):
|
||||
abort(403)
|
||||
|
||||
if post.over_18 and v.is_suspended_permanently:
|
||||
abort(403)
|
||||
|
||||
post.over_18 = False
|
||||
g.db.add(post)
|
||||
|
||||
if post.author_id != v.id:
|
||||
if v.admin_level >= PERMS['POST_COMMENT_MODERATION']:
|
||||
ma = ModAction(
|
||||
kind = "unset_nsfw",
|
||||
user_id = v.id,
|
||||
target_submission_id = post.id,
|
||||
)
|
||||
g.db.add(ma)
|
||||
else:
|
||||
ma = SubAction(
|
||||
sub = post.sub,
|
||||
kind = "unset_nsfw",
|
||||
user_id = v.id,
|
||||
target_submission_id = post.id,
|
||||
)
|
||||
g.db.add(ma)
|
||||
send_repeatable_notification(post.author_id, f"@{v.username} (Admin) has unmarked [{post.title}](/post/{post.id}) as +18")
|
||||
|
||||
return {"message": "Post has been unmarked as +18!"}
|
||||
|
||||
@app.post("/save_post/<pid>")
|
||||
@limiter.limit(DEFAULT_RATELIMIT_SLOWER)
|
||||
|
@ -949,15 +990,46 @@ def pin_post(post_id, v):
|
|||
else: return {"message": "Post unpinned!"}
|
||||
return abort(404, "Post not found!")
|
||||
|
||||
@app.route("/post/<post_id>/new", methods=["PUT", "DELETE"])
|
||||
@app.put("/post/<post_id>/new")
|
||||
@limiter.limit(DEFAULT_RATELIMIT_SLOWER)
|
||||
@auth_required
|
||||
def toggle_new_sort(post_id:int, v:User):
|
||||
def set_new_sort(post_id:int, v:User):
|
||||
post = get_post(post_id)
|
||||
if not v.can_edit(post): abort(403, "Only the post author can do that!")
|
||||
post.new = request.method == "PUT"
|
||||
post.new = True
|
||||
g.db.add(post)
|
||||
return {"message": f"Turned {'on' if post.new else 'off'} sort by new"}
|
||||
|
||||
if v.id != post.author_id:
|
||||
ma = ModAction(
|
||||
kind = "set_new",
|
||||
user_id = v.id,
|
||||
target_submission_id = post.id,
|
||||
)
|
||||
g.db.add(ma)
|
||||
send_repeatable_notification(post.author_id, f"@{v.username} (Admin) has changed the the default sorting of comments on [{post.title}](/post/{post.id}) to `new`")
|
||||
|
||||
return {"message": f"Changed the the default sorting of comments on this post to 'new'"}
|
||||
|
||||
|
||||
@app.delete("/post/<post_id>/new")
|
||||
@limiter.limit(DEFAULT_RATELIMIT_SLOWER)
|
||||
@auth_required
|
||||
def unset_new_sort(post_id:int, v:User):
|
||||
post = get_post(post_id)
|
||||
if not v.can_edit(post): abort(403, "Only the post author can do that!")
|
||||
post.new = None
|
||||
g.db.add(post)
|
||||
|
||||
if v.id != post.author_id:
|
||||
ma = ModAction(
|
||||
kind = "set_hot",
|
||||
user_id = v.id,
|
||||
target_submission_id = post.id,
|
||||
)
|
||||
g.db.add(ma)
|
||||
send_repeatable_notification(post.author_id, f"@{v.username} (Admin) has changed the the default sorting of comments on [{post.title}](/post/{post.id}) to `hot`")
|
||||
|
||||
return {"message": f"Changed the the default sorting of comments on this post to 'hot'"}
|
||||
|
||||
|
||||
extensions = IMAGE_FORMATS + VIDEO_FORMATS + AUDIO_FORMATS
|
||||
|
|
|
@ -46,7 +46,6 @@ def check_for_alts(current:User, include_current_session=True):
|
|||
past_accs.remove(past_id)
|
||||
continue
|
||||
|
||||
if past_id == MOM_ID or current_id == MOM_ID: break
|
||||
if past_id == current_id: continue
|
||||
|
||||
li = [past_id, current_id]
|
||||
|
|
|
@ -225,7 +225,14 @@ def searchcomments(v:User):
|
|||
if v.admin_level < PERMS['POST_COMMENT_MODERATION']:
|
||||
private = [x[0] for x in g.db.query(Submission.id).filter(Submission.private == True).all()]
|
||||
|
||||
comments = comments.filter(Comment.is_banned==False, Comment.deleted_utc == 0, Comment.parent_submission.notin_(private))
|
||||
comments = comments.filter(
|
||||
Comment.is_banned==False,
|
||||
Comment.deleted_utc == 0,
|
||||
or_(
|
||||
Comment.parent_submission.notin_(private),
|
||||
Comment.wall_user_id != None
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
if 'after' in criteria:
|
||||
|
|
|
@ -342,9 +342,6 @@ def settings_personal_post(v):
|
|||
if house == "None": house = ''
|
||||
v.house = house
|
||||
|
||||
if v.house == "Vampire":
|
||||
send_repeatable_notification(DAD_ID, f"@{v.username} has joined House Vampire!")
|
||||
|
||||
updated = True
|
||||
|
||||
if updated:
|
||||
|
@ -602,7 +599,7 @@ def settings_css_get(v:User):
|
|||
@ratelimit_user()
|
||||
def settings_css(v):
|
||||
if v.agendaposter: abort(400, "Agendapostered users can't edit CSS!")
|
||||
css = request.values.get("css", v.css).strip().replace('\\', '').strip()[:4000]
|
||||
css = request.values.get("css", v.css).strip().replace('\\', '').strip()[:CSS_LENGTH_LIMIT]
|
||||
if '</style' in css.lower():
|
||||
abort(400, "Please message @Aevann if you get this error")
|
||||
v.css = css
|
||||
|
@ -615,7 +612,7 @@ def settings_css(v):
|
|||
@auth_required
|
||||
@ratelimit_user()
|
||||
def settings_profilecss(v):
|
||||
profilecss = request.values.get("profilecss", v.profilecss).strip().replace('\\', '').strip()[:4000]
|
||||
profilecss = request.values.get("profilecss", v.profilecss).strip().replace('\\', '').strip()[:CSS_LENGTH_LIMIT]
|
||||
valid, error = validate_css(profilecss)
|
||||
if not valid:
|
||||
return render_template("settings/css.html", error=error, v=v)
|
||||
|
|
|
@ -245,75 +245,6 @@ def submit_contact(v):
|
|||
def archivesindex():
|
||||
return redirect("/archives/index.html")
|
||||
|
||||
@app.get('/archives/<path:path>')
|
||||
def archives(path):
|
||||
resp = make_response(send_from_directory('/archives', path))
|
||||
if request.path.endswith('.css'): resp.headers.add("Content-Type", "text/css")
|
||||
return resp
|
||||
|
||||
def static_file(dir:str, path:str, should_cache:bool, is_webp:bool) -> Response:
|
||||
resp = make_response(send_from_directory(dir, path))
|
||||
if should_cache:
|
||||
resp.headers.remove("Cache-Control")
|
||||
resp.headers.add("Cache-Control", "public, max-age=3153600")
|
||||
if is_webp:
|
||||
resp.headers.remove("Content-Type")
|
||||
resp.headers.add("Content-Type", "image/webp")
|
||||
return resp
|
||||
|
||||
@app.get('/e/<emoji>')
|
||||
@limiter.exempt
|
||||
def emoji(emoji):
|
||||
if not emoji.endswith('.webp'): abort(404)
|
||||
return static_file('assets/images/emojis', emoji, True, True)
|
||||
|
||||
@app.get('/icon.webp')
|
||||
@limiter.exempt
|
||||
def icon():
|
||||
return static_file('assets/images', f'{SITE_NAME}/icon.webp', True, True)
|
||||
|
||||
@app.get('/i/<path:path>')
|
||||
@limiter.exempt
|
||||
def image(path):
|
||||
is_webp = path.endswith('.webp')
|
||||
return static_file('assets/images', path, is_webp or path.endswith('.gif') or path.endswith('.ttf') or path.endswith('.woff2'), is_webp)
|
||||
|
||||
@app.get('/assets/<path:path>')
|
||||
@app.get('/static/assets/<path:path>')
|
||||
@limiter.exempt
|
||||
def static_service(path):
|
||||
if path.startswith(f'app_{SITE_NAME}_v'):
|
||||
return redirect('/app')
|
||||
is_webp = path.endswith('.webp')
|
||||
return static_file('assets', path, is_webp or path.endswith('.gif') or path.endswith('.ttf') or path.endswith('.woff2'), is_webp)
|
||||
|
||||
### BEGIN FALLBACK ASSET SERVING
|
||||
# In production, we have nginx serve these locations now.
|
||||
# These routes stay for local testing. Requests don't reach them on prod.
|
||||
|
||||
@app.get('/images/<path>')
|
||||
@app.get('/hostedimages/<path>')
|
||||
@app.get("/static/images/<path>")
|
||||
@limiter.exempt
|
||||
def images(path):
|
||||
return static_file('/images', path, True, True)
|
||||
|
||||
@app.get('/videos/<path>')
|
||||
@limiter.exempt
|
||||
def videos(path):
|
||||
return static_file('/videos', path, True, False)
|
||||
|
||||
@app.get('/audio/<path>')
|
||||
@limiter.exempt
|
||||
def audio(path):
|
||||
return static_file('/audio', path, True, False)
|
||||
|
||||
### END FALLBACK ASSET SERVING
|
||||
|
||||
@app.get("/robots.txt")
|
||||
def robots_txt():
|
||||
return send_file("assets/robots.txt")
|
||||
|
||||
no = (21,22,23,24,25,26,27)
|
||||
|
||||
@cache.memoize(timeout=3600)
|
||||
|
@ -350,16 +281,6 @@ def blocks(v):
|
|||
|
||||
return render_template("blocks.html", v=v, users=users, targets=targets)
|
||||
|
||||
@app.get("/banned")
|
||||
@auth_required
|
||||
def banned(v:User):
|
||||
after_30_days = int(time.time()) + 86400 * 30
|
||||
users = g.db.query(User).filter(User.is_banned > 0, or_(User.unban_utc == 0, User.unban_utc > after_30_days))
|
||||
if not v.can_see_shadowbanned:
|
||||
users = users.filter(User.shadowbanned == None)
|
||||
users = users.all()
|
||||
return render_template("banned.html", v=v, users=users)
|
||||
|
||||
@app.get("/formatting")
|
||||
@auth_required
|
||||
def formatting(v:User):
|
||||
|
|
|
@ -7,6 +7,7 @@ from typing import Literal
|
|||
|
||||
import gevent
|
||||
import qrcode
|
||||
from sqlalchemy import nullslast
|
||||
from sqlalchemy.orm import aliased
|
||||
|
||||
from files.classes import *
|
||||
|
@ -167,11 +168,34 @@ def user_voted_posts(v:User, username):
|
|||
def user_voted_comments(v:User, username):
|
||||
return user_voted(v, username, Comment, CommentVote, "userpage/voted_comments.html", True)
|
||||
|
||||
@app.get("/banned")
|
||||
@auth_required
|
||||
def banned(v:User):
|
||||
users = g.db.query(User).filter(
|
||||
User.is_banned > 0,
|
||||
User.truescore > 0,
|
||||
or_(User.unban_utc == 0, User.unban_utc > time.time()),
|
||||
not_(and_(
|
||||
User.profileurl.startswith('/e/'),
|
||||
User.customtitle==None,
|
||||
User.namecolor == DEFAULT_COLOR,
|
||||
User.patron == 0,
|
||||
))
|
||||
)
|
||||
if v.admin_level >= PERMS['VIEW_LAST_ACTIVE']:
|
||||
users = users.order_by(nullslast(User.last_active.desc()))
|
||||
if not v.can_see_shadowbanned:
|
||||
users = users.filter(User.shadowbanned == None)
|
||||
users = users.all()
|
||||
return render_template("banned.html", v=v, users=users)
|
||||
|
||||
@app.get("/grassed")
|
||||
@auth_required
|
||||
def grassed(v:User):
|
||||
users = g.db.query(User).filter(User.ban_reason.like('grass award used by @%'))
|
||||
users = g.db.query(User).filter(
|
||||
User.ban_reason.like('grass award used by @%'),
|
||||
User.unban_utc > time.time(),
|
||||
)
|
||||
if not v.can_see_shadowbanned:
|
||||
users = users.filter(User.shadowbanned == None)
|
||||
users = users.all()
|
||||
|
@ -180,8 +204,18 @@ def grassed(v:User):
|
|||
@app.get("/chuds")
|
||||
@auth_required
|
||||
def chuds(v:User):
|
||||
after_30_days = int(time.time()) + 86400 * 30
|
||||
users = g.db.query(User).filter(or_(User.agendaposter == 1, User.agendaposter > after_30_days))
|
||||
users = g.db.query(User).filter(
|
||||
User.truescore > 0,
|
||||
or_(User.agendaposter == 1, User.agendaposter > time.time()),
|
||||
not_(and_(
|
||||
User.profileurl.startswith('/e/'),
|
||||
User.customtitle==None,
|
||||
User.namecolor == DEFAULT_COLOR,
|
||||
User.patron == 0,
|
||||
))
|
||||
)
|
||||
if v.admin_level >= PERMS['VIEW_LAST_ACTIVE']:
|
||||
users = users.order_by(nullslast(User.last_active.desc()))
|
||||
if not v.can_see_shadowbanned:
|
||||
users = users.filter(User.shadowbanned == None)
|
||||
users = users.order_by(User.username).all()
|
||||
|
@ -389,17 +423,9 @@ def get_profilecss(id):
|
|||
@app.get("/@<username>/song")
|
||||
def usersong(username:str):
|
||||
user = get_user(username)
|
||||
if user.song: return redirect(f"/song/{user.song}.mp3")
|
||||
if user.song: return redirect(f"/songs/{user.song}.mp3")
|
||||
else: abort(404)
|
||||
|
||||
@app.get("/song/<song>")
|
||||
@app.get("/static/song/<song>")
|
||||
def song(song):
|
||||
resp = make_response(send_from_directory('/songs', song))
|
||||
resp.headers.remove("Cache-Control")
|
||||
resp.headers.add("Cache-Control", "public, max-age=3153600")
|
||||
return resp
|
||||
|
||||
@app.post("/subscribe/<post_id>")
|
||||
@limiter.limit(DEFAULT_RATELIMIT_SLOWER)
|
||||
@auth_required
|
||||
|
@ -445,13 +471,13 @@ def message2(v:User, username:str):
|
|||
|
||||
body_html = sanitize(message)
|
||||
|
||||
if not (SITE == 'rdrama.net' and user.id == BLACKJACKBTZ_ID):
|
||||
existing = g.db.query(Comment.id).filter(Comment.author_id == v.id,
|
||||
Comment.sentto == user.id,
|
||||
Comment.body_html == body_html,
|
||||
).first()
|
||||
existing = g.db.query(Comment.id).filter(
|
||||
Comment.author_id == v.id,
|
||||
Comment.sentto == user.id,
|
||||
Comment.body_html == body_html
|
||||
).first()
|
||||
|
||||
if existing: abort(403, "Message already exists.")
|
||||
if existing: abort(403, "Message already exists.")
|
||||
|
||||
c = Comment(author_id=v.id,
|
||||
parent_submission=None,
|
||||
|
@ -727,11 +753,6 @@ def u_username_wall(v:Optional[User], username:str):
|
|||
|
||||
is_following = v and u.has_follower(v)
|
||||
|
||||
if not u.is_visible_to(v):
|
||||
if g.is_api_or_xhr or request.path.endswith(".json"):
|
||||
abort(403, f"@{u.username}'s userpage is private")
|
||||
return render_template("userpage/private.html", u=u, v=v, is_following=is_following), 403
|
||||
|
||||
if v and v.id != u.id:
|
||||
g.db.flush()
|
||||
view = g.db.query(ViewerRelationship).filter_by(viewer_id=v.id, user_id=u.id).one_or_none()
|
||||
|
|
|
@ -6,7 +6,7 @@ from files.__main__ import app, limiter
|
|||
|
||||
|
||||
@app.get("/votes/<link>")
|
||||
@admin_level_required(PERMS['VOTES_VISIBLE'])
|
||||
@auth_required
|
||||
def vote_info_get(v, link):
|
||||
try:
|
||||
if "p_" in link: thing = get_post(int(link.split("p_")[1]), v=v)
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
<p>Two accounts controlled by different people should have most uniqueness percentages at or above 70-80%</p>
|
||||
<p>A sockpuppet account will have its uniqueness percentages significantly lower.</p>
|
||||
|
||||
<button class="btn btn-danger" data-click2="postToastReload(this,'/@{{u1.username}}/alts/?other_username={{u2.username}}')" onclick="areyousure(this)">Link {{u1.username}} and {{u2.username}}</button>
|
||||
<button class="btn btn-danger" data-click="postToastReload(this,'/@{{u1.username}}/alts/?other_username={{u2.username}}')" onclick="areyousure(this)">Link {{u1.username}} and {{u2.username}}</button>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
|
|
@ -61,8 +61,8 @@
|
|||
<form onsubmit="return false;">
|
||||
<label for="link-input-other">Other Username</label>
|
||||
<input autocomplete="off" id="link-input-other" type="text" class="form-control mb-2" name="other_username" placeholder="Other Username">
|
||||
<button id="add-alt-form-link" class="btn btn-danger mr-3" data-click2="submitAddAlt(this)" onclick="areyousure(this)">Add Alt Linked</button>
|
||||
<button id="add-alt-form-delink" class="btn btn-danger" data-click2="submitAddAlt(this)" onclick="areyousure(this)">Add Alt Delinked</button>
|
||||
<button id="add-alt-form-link" class="btn btn-danger mr-3" data-click="submitAddAlt(this)" onclick="areyousure(this)">Add Alt Linked</button>
|
||||
<button id="add-alt-form-delink" class="btn btn-danger" data-click="submitAddAlt(this)" onclick="areyousure(this)">Add Alt Delinked</button>
|
||||
</form>
|
||||
</section>
|
||||
{% endif %}
|
||||
|
|
|
@ -18,10 +18,10 @@
|
|||
<div class="overflow-x-auto"><table class="table table-striped">
|
||||
<thead class="bg-primary text-white">
|
||||
<tr>
|
||||
<th scope="col">Select</th>
|
||||
<th scope="col">Image</th>
|
||||
<th scope="col">Name</th>
|
||||
<th scope="col">Default Description</th>
|
||||
<th>Select</th>
|
||||
<th>Image</th>
|
||||
<th>Name</th>
|
||||
<th>Default Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
<tr>
|
||||
<th>#</th>
|
||||
<th>Name</th>
|
||||
<th>Last Active</th>
|
||||
<th>Truescore</th>
|
||||
<th>Shadowbanned by</th>
|
||||
<th>Shadowban reason</th>
|
||||
</tr>
|
||||
|
@ -15,11 +17,15 @@
|
|||
{% for user in users %}
|
||||
<tr>
|
||||
<td>{{loop.index}}</td>
|
||||
<td>{% include "user_in_table.html" %}</td>
|
||||
<td data-sort-key="{{user.username.lower() if user else ''}}">{%- include 'user_in_table.html' -%}</td>
|
||||
<td {% if user.last_active %}data-time="{{user.last_active}}"{% endif %}></td>
|
||||
<td>{{user.truescore}}</td>
|
||||
<td>{{user.shadowbanned}}</td>
|
||||
<td>{{user.ban_reason}}</td>
|
||||
<td>{% if user.ban_reason %}{{user.ban_reason}}{% endif %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
<tr>
|
||||
<th>#</th>
|
||||
<th>Name</th>
|
||||
<th onclick="sort_table(2)" style="text-align:right;">Truescore</th>
|
||||
<th onclick="sort_table(3)" style="text-align:right;">Mod actions</th>
|
||||
<th style="text-align:right;">Truescore</th>
|
||||
<th style="text-align:right;">Mod actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
|
@ -28,6 +28,6 @@
|
|||
</table>
|
||||
</div>
|
||||
|
||||
<script defer src="{{'js/sort_table.js' | asset}}"></script>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
<table class="table table-striped mb-5">
|
||||
<thead class="bg-primary text-white">
|
||||
<tr>
|
||||
<th onclick="sort_table(0)">#</th>
|
||||
<th>#</th>
|
||||
<th>Name</th>
|
||||
<th>Image</th>
|
||||
<th>Description</th>
|
||||
<th onclick="sort_table(4)">#</th>
|
||||
<th onclick="sort_table(4)">Rarity</th>
|
||||
<th>#</th>
|
||||
<th>Rarity</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
|
@ -32,6 +32,6 @@
|
|||
</table>
|
||||
</div>
|
||||
|
||||
<script defer src="{{'js/sort_table.js' | asset}}"></script>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
|
|
@ -2,12 +2,16 @@
|
|||
{% block pagetitle %}Banned Users{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<h5 class="my-4">Users who are permabanned or have more than 30 days to be unbanned</h5>
|
||||
<h5 class="my-4">Banned Users</h5>
|
||||
<div class="overflow-x-auto"><table class="table table-striped mb-5">
|
||||
<thead class="bg-primary text-white">
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Name</th>
|
||||
{% if v and v.admin_level >= PERMS['VIEW_LAST_ACTIVE'] -%}
|
||||
<th>Last Active</th>
|
||||
{%- endif %}
|
||||
<th>Truescore</th>
|
||||
<th>Ban reason</th>
|
||||
<th>Banned by</th>
|
||||
<th>Unban in</th>
|
||||
|
@ -17,17 +21,21 @@
|
|||
<tr>
|
||||
<td>{{loop.index}}</td>
|
||||
<td>{% include "user_in_table.html" %}</td>
|
||||
{% if v and v.admin_level >= PERMS['VIEW_LAST_ACTIVE'] -%}
|
||||
<td {% if user.last_active %}data-time="{{user.last_active}}"{% endif %}></td>
|
||||
{%- endif %}
|
||||
<td>{{user.truescore}}</td>
|
||||
<td>{% if user.ban_reason %}{{user.ban_reason}}{% endif %}</td>
|
||||
<td>
|
||||
{% with user=user.banned_by %}
|
||||
{% include "user_in_table.html" %}
|
||||
{% endwith %}
|
||||
</td>
|
||||
<td>
|
||||
{{user.unban_in}}
|
||||
{% with user=user.banned_by %}
|
||||
<td data-sort-key="{{user.username.lower() if user else ''}}">
|
||||
{% include "user_in_table.html" %}
|
||||
</td>
|
||||
{% endwith %}
|
||||
<td {% if user.unban_utc %}data-time="{{user.unban_utc}}"{% endif %}></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
|
|
@ -2,12 +2,16 @@
|
|||
{% block pagetitle %}Chuds{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<h5 class="my-4">Users who are permachudded or have more than 30 days to be unchudded</h5>
|
||||
<h5 class="my-4">Chudded Users</h5>
|
||||
<div class="overflow-x-auto"><table class="table table-striped mb-5">
|
||||
<thead class="bg-primary text-white">
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Name</th>
|
||||
{% if v and v.admin_level >= PERMS['VIEW_LAST_ACTIVE'] -%}
|
||||
<th>Last Active</th>
|
||||
{%- endif %}
|
||||
<th>Truescore</th>
|
||||
<th>Unchud in</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -15,8 +19,15 @@
|
|||
<tr>
|
||||
<td>{{loop.index}}</td>
|
||||
<td>{% include "user_in_table.html" %}</td>
|
||||
<td>{{user.unchud_in}}</td>
|
||||
{% if v and v.admin_level >= PERMS['VIEW_LAST_ACTIVE'] -%}
|
||||
<td {% if user.last_active %}data-time="{{user.last_active}}"{% endif %}></td>
|
||||
{%- endif %}
|
||||
<td>{{user.truescore}}</td>
|
||||
<td {% if user.agendaposter != 1 %}data-time="{{user.agendaposter}}"{% endif %}></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
|
|
@ -297,7 +297,7 @@
|
|||
</label>
|
||||
</div>
|
||||
<button type="button" id="edit-btn-{{c.id}}" form="comment-edit-form-{{c.id}}" class="btn btn-primary ml-2 fl-r commentmob" onclick="comment_edit('{{c.id}}');remove_dialog()">Save Edit</button>
|
||||
<button type="button" id="cancel-edit-{{c.id}}" onclick="toggleEdit('{{c.id}}');remove_dialog()" class="btn btn-link text-muted ml-auto cancel-form fl-r commentmob">Cancel</button>
|
||||
<button type="button" id="cancel-edit-{{c.id}}" onclick="toggleEdit('{{c.id}}');remove_dialog()" class="btn btn-link text-muted ml-auto fl-r commentmob">Cancel</button>
|
||||
</form>
|
||||
<div id="preview-edit-{{c.id}}" class="preview mb-3 mt-5"></div>
|
||||
<div class="form-text text-small p-0 m-0"><a href="/formatting" {% if v and v.newtab %}data-target="t" target="_blank"{% endif %}>Formatting help</a></div>
|
||||
|
@ -397,7 +397,9 @@
|
|||
|
||||
{% endif %}
|
||||
|
||||
{% if v and ((not c.ghost and v.admin_level >= PERMS['VOTES_VISIBLE']) or v.id == AEVANN_ID) %}<a href="/votes/{{c.fullname}}" class="btn caction nobackground px-1 text-muted"><i class="fas fa-arrows-v"></i>Votes</a>{% endif %}
|
||||
{% if not c.ghost or (v and v.id == AEVANN_ID) %}
|
||||
<a href="/votes/{{c.fullname}}" class="btn caction nobackground px-1 text-muted"><i class="fas fa-arrows-v"></i>Votes</a>
|
||||
{% endif %}
|
||||
|
||||
<a class="btn caction nobackground px-1 text-muted" href="{{c.permalink}}"><i class="fas fa-book-open"></i>Context</a>
|
||||
|
||||
|
@ -556,7 +558,7 @@
|
|||
{% endif %}
|
||||
</div>
|
||||
|
||||
<button type="button" onclick="document.getElementById('reply-message-{{c.id}}').classList.add('d-none');remove_dialog()" class="btn btn-link text-muted ml-auto cancel-form">Cancel</button>
|
||||
<button type="button" onclick="document.getElementById('reply-message-{{c.id}}').classList.add('d-none');remove_dialog()" class="btn btn-link text-muted ml-auto">Cancel</button>
|
||||
<button type="button" id="save-reply-to-{{c.id}}" class="btn btn-primary ml-2" onclick="post_reply('{{c.id}}');remove_dialog()">Reply</button>
|
||||
</form>
|
||||
<div id="message-reply-{{c.id}}" class="preview mt-2"></div>
|
||||
|
@ -581,7 +583,9 @@
|
|||
<div class="modal-body">
|
||||
<ul class="list-group comment-actions">
|
||||
|
||||
{% if v and ((not c.ghost and v.admin_level >= PERMS['VOTES_VISIBLE']) or v.id == AEVANN_ID) %}<a href="/votes/{{c.fullname}}"><li class="list-group-item"><i class="fas fa-arrows-v mr-2"></i>Votes</li></a>{% endif %}
|
||||
{% if not c.ghost or (v and v.id == AEVANN_ID) %}
|
||||
<a href="/votes/{{c.fullname}}"><li class="list-group-item"><i class="fas fa-arrows-v mr-2"></i>Votes</li></a>
|
||||
{% endif %}
|
||||
|
||||
<a class="list-group-item" href="{{c.permalink}}"><i class="fas fa-book-open mr-2"></i>Context</a>
|
||||
|
||||
|
@ -612,7 +616,7 @@
|
|||
{% if not c.ghost %}
|
||||
<button type="button" id="unblock2-{{c.id}}" data-bs-dismiss="modal" class="text-success list-group-item {% if not c.is_blocking %}d-none{% endif %}" onclick="postToastSwitch(this,'/settings/unblock?username={{c.author.username}}','block2-{{c.id}}','unblock2-{{c.id}}','d-none')"><i class="fas fa-eye-slash text-success mr-2"></i>Unblock user</button>
|
||||
|
||||
<button type="button" id="block2-{{c.id}}" class="{% if c.is_blocking %}d-none{% endif %} list-group-item text-danger" data-click2="postToastSwitch(this,'/settings/block?username={{c.author.username}}','block2-{{c.id}}','unblock2-{{c.id}}','d-none')" onclick="areyousure(this)" data-dismiss="modal"><i class="fas fa-eye-slash fa-fw text-danger mr-2"></i>Block user</button>
|
||||
<button type="button" id="block2-{{c.id}}" class="{% if c.is_blocking %}d-none{% endif %} list-group-item text-danger" data-click="postToastSwitch(this,'/settings/block?username={{c.author.username}}','block2-{{c.id}}','unblock2-{{c.id}}','d-none')" onclick="areyousure(this)" data-dismiss="modal"><i class="fas fa-eye-slash fa-fw text-danger mr-2"></i>Block user</button>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
|
|
|
@ -68,7 +68,9 @@ Text 2
|
|||
<td>Video Files</td>
|
||||
<td>https://files.catbox.moe/v4om92.mp4</td>
|
||||
<td>
|
||||
<video controls preload="none" src="https://files.catbox.moe/v4om92.mp4"></video>
|
||||
<p class="resizable">
|
||||
<video controls preload="none" src="https://files.catbox.moe/v4om92.mp4"></video>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -77,25 +77,16 @@
|
|||
<table class="table table-striped shop">
|
||||
<thead class="bg-primary text-white">
|
||||
<tr>
|
||||
<th scope="col">Hat</th>
|
||||
<th scope="col">Name</th>
|
||||
<th scope="col">Description</th>
|
||||
<th>Hat</th>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
{% if SITE == 'rdrama.net' %}
|
||||
{% if request.values.get("sort") == 'author_asc' %}
|
||||
<th scope="col"><a href="?sort=author_desc">Author</a></th>
|
||||
{% else %}
|
||||
<th scope="col"><a href="?sort=author_asc">Author</a></th>
|
||||
{% endif %}
|
||||
<th scope="col" onclick="sort_table(4)">Owners</th>
|
||||
<th scope="col" onclick="sort_table(5)">Price</th>
|
||||
<th scope="col">Actions</th>
|
||||
<th scope="col" onclick="sort_table(7)">Added on</th>
|
||||
{% else %}
|
||||
<th scope="col" onclick="sort_table(3)">Owners</th>
|
||||
<th scope="col" onclick="sort_table(4)">Price</th>
|
||||
<th scope="col">Actions</th>
|
||||
<th scope="col" onclick="sort_table(6)">Added on</th>
|
||||
<th>Author</a></th>
|
||||
{% endif %}
|
||||
<th>Owners</th>
|
||||
<th>Price</th>
|
||||
<th>Actions</th>
|
||||
<th>Added on</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
|
@ -118,10 +109,10 @@
|
|||
<td class="shop-table-actions" style="width:unset">
|
||||
{% if hat.id not in owned_hat_ids and hat.is_purchasable %}
|
||||
<div id="if-not-owned-{{hat.id}}">
|
||||
<button type="button" id="buy1-{{hat.id}}" class="btn btn-success {% if v.coins < hat.price %}disabled{% endif %}" data-click2="postToastSwitch(this, '/buy_hat/{{hat.id}}', 'if-not-owned-{{hat.id}}', 'if-owned-{{hat.id}}', 'd-none', (xhr)=>{if(xhr.status == 200)document.getElementById('user-coins-amount').innerHTML-={{hat.price}}})" onclick="areyousure(this)"><span class="m-auto">Buy</span></button>
|
||||
<button type="button" id="buy1-{{hat.id}}" class="btn btn-success {% if v.coins < hat.price %}disabled{% endif %}" data-click="postToastSwitch(this, '/buy_hat/{{hat.id}}', 'if-not-owned-{{hat.id}}', 'if-owned-{{hat.id}}', 'd-none', (xhr)=>{if(xhr.status == 200)document.getElementById('user-coins-amount').innerHTML-={{hat.price}}})" onclick="areyousure(this)"><span class="m-auto">Buy</span></button>
|
||||
|
||||
{% if FEATURES['MARSEYBUX'] %}
|
||||
<button type="button" id="buy2-{{hat.id}}" class="marseybux btn btn-success {% if v.marseybux < hat.price %}disabled{% endif %}" data-click2="postToastSwitch(this, '/buy_hat/{{hat.id}}?mb=true', 'if-not-owned-{{hat.id}}', 'if-owned-{{hat.id}}', 'd-none', (xhr)=>{if(xhr.status == 200)document.getElementById('user-bux-amount').innerHTML-={{hat.price}}})" onclick="areyousure(this)"><span class="m-auto">MBux</span></button>
|
||||
<button type="button" id="buy2-{{hat.id}}" class="marseybux btn btn-success {% if v.marseybux < hat.price %}disabled{% endif %}" data-click="postToastSwitch(this, '/buy_hat/{{hat.id}}?mb=true', 'if-not-owned-{{hat.id}}', 'if-owned-{{hat.id}}', 'd-none', (xhr)=>{if(xhr.status == 200)document.getElementById('user-bux-amount').innerHTML-={{hat.price}}})" onclick="areyousure(this)"><span class="m-auto">MBux</span></button>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
@ -138,5 +129,5 @@
|
|||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<script defer src="{{'js/sort_table.js' | asset}}"></script>
|
||||
|
||||
{% endblock %}
|
||||
|
|