This commit is contained in:
bingus_violet 2024-12-19 02:13:15 -06:00
parent 444316d4b0
commit 9d632c07be
13 changed files with 1412 additions and 0 deletions

3
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,3 @@
{
"vscord.app.privacyMode.enable": true
}

8
constants.js Normal file
View file

@ -0,0 +1,8 @@
import * as path from "path"
import { fileURLToPath } from "url"
export const flavors = ["#reflectivedetective", "#alearfred"]
export const variety = 200
export const PORT = process.env.PORT || 8080
export const __dirname = path.dirname(fileURLToPath(import.meta.url))
export const staticPath = path.join(__dirname, "static")

12
frontend.js Normal file
View file

@ -0,0 +1,12 @@
import { PORT, staticPath } from "./constants.js"
import express from "express"
import { middleware } from "./pageUpdater.js"
export const app = express()
app.use(middleware)
app.use(express.static(staticPath))
app.listen(PORT, () => {
console.log("THE AWESOMEST YAOI GENERATOR OF ALL TIME is now listening on port: " + PORT)
})

1
index.js Normal file
View file

@ -0,0 +1 @@
import "./frontend.js"

1113
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

20
package.json Normal file
View file

@ -0,0 +1,20 @@
{
"name": "dandys-world-yaoi-spinner",
"version": "1.0.0",
"description": "Bruhh where am I???",
"main": "index.js",
"type": "module",
"scripts": {
"start": "node index.js"
},
"repository": {
"type": "git",
"url": "https://git.viois.gay/Violet/Dandys-World-Yaoi-Spinner"
},
"author": "Violet",
"license": "Unlicense",
"dependencies": {
"@the-convocation/twitter-scraper": "^0.14.1",
"express": "^4.21.2"
}
}

54
pageUpdater.js Normal file
View file

@ -0,0 +1,54 @@
import * as path from "path"
import * as fs from "fs"
import { staticPath } from "./constants.js"
import { flavors, variety } from "./constants.js"
import { getYaoi } from "./scraper.js"
export async function middleware(req, res, next) {
var filePath = (req.baseUrl + req.path).trim()
if (!filePath.includes(".")) {
if (filePath.charAt(filePath.length - 1) != '/') {
res.redirect(filePath + '/')
return
}
filePath = path.join(filePath, '/index.html')
}
filePath = path.join(staticPath, filePath || 'index.html')
if (fs.existsSync(filePath) && filePath.includes(".html")) {
var data = fs.readFileSync(filePath).toString()
res.contentType(path.basename(filePath))
data = await converter(data)
res.send(data)
}
else {
next()
}
}
export async function converter(html) {
var replacers = {
"FLAVOR_COUNT": flavors.length,
"VARIETY": variety,
"FLAVORS": flavors.join(", ").replace(/,(?=[^,]+$)/, ' &'),
"SPIN_BUTTON": `<a href="/spin" id="yaoiButton"><div>S</div><div>P</div><div>I</div><div>N</div></a>`,
"YAOI": () => {
var yaoi = getYaoi()
if (yaoi) {
return `<div class="post">${yaoi.html}</div>`
}
}
}
for (var key in replacers) {
html = html.replaceAll(`{${key}}`, replacers[key])
}
return html
}

29
scraper.js Normal file
View file

@ -0,0 +1,29 @@
import { Scraper } from "@the-convocation/twitter-scraper"
import { flavors, variety } from "./constants.js"
const scraper = new Scraper({
})
await scraper.login(process.env.USERNAME, process.env.PASSWORD)
export async function scrapeYaoi() {
var finalArray = []
for (let flavor of flavors) {
console.log(flavor)
var search = scraper.searchTweets(flavor, variety, "media")
for await (var value of search) {
if (value.html.includes("img")) {
finalArray.push(value)
}
}
}
return finalArray
}
export var yaoiList = await scrapeYaoi()
export function getYaoi() {
var yaoi = yaoiList[Math.floor(Math.random() * yaoiList.length)]
return yaoi
}

Binary file not shown.

Binary file not shown.

17
static/index.html Normal file
View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<title>Yaoi Spinner</title>
</head>
<body>
<h1>The Yaoi Spinner</h1>
<p>Welcome to the awesomest Yaoi Spinner ever. You can gamble yaoi. Yup. #imstraight</p>
{SPIN_BUTTON}
<p>All Yaoi is sourced from Twitter. Randomly chosen from a mix of {FLAVOR_COUNT} different searches! Currently searches for {VARIETY} posts each of {FLAVORS}</p>
</body>
</html>

17
static/spin/index.html Normal file
View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="../style.css">
<title>Yaoi Spinner</title>
</head>
<body>
<!-- <h1>The Yaoi Spinner</h1> -->
{YAOI}
{SPIN_BUTTON}
<p>All Yaoi is sourced from Twitter. Randomly chosen from a mix of {FLAVOR_COUNT} different searches! Currently searches for {VARIETY} posts each of {FLAVORS}</p>
</body>
</html>

138
static/style.css Normal file
View file

@ -0,0 +1,138 @@
:root {
--gay-erasure: 1
}
@font-face {
font-display: swap;
font-family: 'RubikBold';
font-style: bold;
font-weight: 600;
src: url('./fonts/rubik-v28-latin-600.woff2') format('woff2');
}
@font-face {
font-display: swap;
font-family: 'Rubik';
font-style: normal;
font-weight: 400;
src: url('./fonts/rubik-v28-latin-regular.woff2') format('woff2');
}
body {
background-color: rgb(20, 20, 60);
/* background: linear-gradient(145deg, rgb(30, 30, 80), rgb(0, 0, 0)); */
padding: 5px calc(5px + 5%);
color: white;
text-align: center;
font-family: "Rubik", Verdana, Geneva, Tahoma, sans-serif;
}
html {
min-height: 100%;
}
h1 {
font-size: 3rem;
}
p {
font-size: 1.2rem;
}
#yaoiButton {
background: linear-gradient(
90deg,
rgba(255, 0, 0, var(--gay-erasure)) 0%,
rgba(255, 154, 0, var(--gay-erasure)) 10%,
rgba(208, 222, 33, var(--gay-erasure)) 20%,
rgba(79, 220, 74, var(--gay-erasure)) 30%,
rgba(63, 218, 216, var(--gay-erasure)) 40%,
rgba(47, 201, 226, var(--gay-erasure)) 50%,
rgba(28, 127, 238, var(--gay-erasure)) 60%,
rgba(95, 21, 242, var(--gay-erasure)) 70%,
rgba(186, 12, 248, var(--gay-erasure)) 80%,
rgba(251, 7, 217, var(--gay-erasure)) 90%,
rgba(255, 0, 0, var(--gay-erasure)) 100%
);
background-size: 300px auto;
background-position-x: 0px;
/* border: 2px white solid;
padding: 10px; */
display: inline-block;
-webkit-text-stroke: white 3px;
font-size: 5rem;
animation-name: slidebg;
animation-duration: 2.5s;
animation-timing-function: linear;
animation-iteration-count: infinite;
font-weight: bold;
background-clip: text;
-webkit-text-fill-color: transparent;
transition: transform 2s cubic-bezier(0.075, 0.82, 0.165, 1);
}
#yaoiButton:hover {
transform: scale(1.1);
}
#yaoiButton > div {
display: inline-block;
animation-name: float;
animation-duration: 1s;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-timing-function: cubic-bezier(0.445, 0.05, 0.55, 0.95);
animation-fill-mode: both;
}
#yaoiButton > div:nth-child(2) {
animation-delay: 0.25s;
}
#yaoiButton > div:nth-child(3) {
animation-delay: 0.5s;
}
#yaoiButton > div:nth-child(4) {
animation-delay: 0.75s;
}
.post {
background-color: black;
border: 2px gray solid;
text-align: left;
padding: 5px 16px;
width: 600px;
margin: auto;
}
img {
width: 100%;
border-radius: 16px;
margin: 16px auto;
object-fit: cover;
}
@keyframes float {
from {
transform: translateY(-5px);
}
to {
transform: translateY(5px);
}
}
@keyframes slidebg {
from {
background-position-x: 0px;
}
to {
background-position-x: 300px;
}
}