@ -0,0 +1,3 @@ |
|||||||
|
{ |
||||||
|
"extends": "next/core-web-vitals" |
||||||
|
} |
@ -0,0 +1,36 @@ |
|||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. |
||||||
|
|
||||||
|
# dependencies |
||||||
|
/node_modules |
||||||
|
/.pnp |
||||||
|
.pnp.js |
||||||
|
|
||||||
|
# testing |
||||||
|
/coverage |
||||||
|
|
||||||
|
# next.js |
||||||
|
/.next/ |
||||||
|
/out/ |
||||||
|
|
||||||
|
# production |
||||||
|
/build |
||||||
|
|
||||||
|
# misc |
||||||
|
.DS_Store |
||||||
|
*.pem |
||||||
|
|
||||||
|
# debug |
||||||
|
npm-debug.log* |
||||||
|
yarn-debug.log* |
||||||
|
yarn-error.log* |
||||||
|
.pnpm-debug.log* |
||||||
|
|
||||||
|
# local env files |
||||||
|
.env*.local |
||||||
|
|
||||||
|
# vercel |
||||||
|
.vercel |
||||||
|
|
||||||
|
# typescript |
||||||
|
*.tsbuildinfo |
||||||
|
next-env.d.ts |
@ -0,0 +1,4 @@ |
|||||||
|
{ |
||||||
|
"typescript.tsdk": "node_modules/typescript/lib", |
||||||
|
"typescript.enablePromptUseWorkspaceTsdk": true |
||||||
|
} |
@ -0,0 +1,38 @@ |
|||||||
|
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). |
||||||
|
|
||||||
|
## Getting Started |
||||||
|
|
||||||
|
First, run the development server: |
||||||
|
|
||||||
|
```bash |
||||||
|
npm run dev |
||||||
|
# or |
||||||
|
yarn dev |
||||||
|
# or |
||||||
|
pnpm dev |
||||||
|
``` |
||||||
|
|
||||||
|
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. |
||||||
|
|
||||||
|
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. |
||||||
|
|
||||||
|
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`. |
||||||
|
|
||||||
|
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. |
||||||
|
|
||||||
|
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. |
||||||
|
|
||||||
|
## Learn More |
||||||
|
|
||||||
|
To learn more about Next.js, take a look at the following resources: |
||||||
|
|
||||||
|
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. |
||||||
|
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. |
||||||
|
|
||||||
|
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! |
||||||
|
|
||||||
|
## Deploy on Vercel |
||||||
|
|
||||||
|
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. |
||||||
|
|
||||||
|
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. |
@ -0,0 +1,8 @@ |
|||||||
|
/** @type {import('next').NextConfig} */ |
||||||
|
const nextConfig = { |
||||||
|
experimental: { |
||||||
|
appDir: true, |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
module.exports = nextConfig |
@ -0,0 +1,28 @@ |
|||||||
|
{ |
||||||
|
"name": "site", |
||||||
|
"version": "0.1.0", |
||||||
|
"private": true, |
||||||
|
"scripts": { |
||||||
|
"dev": "next dev", |
||||||
|
"build": "next build", |
||||||
|
"start": "next start -p 3002", |
||||||
|
"lint": "next lint" |
||||||
|
}, |
||||||
|
"dependencies": { |
||||||
|
"@next/font": "13.1.6", |
||||||
|
"@types/node": "18.13.0", |
||||||
|
"@types/react": "18.0.27", |
||||||
|
"@types/react-dom": "18.0.10", |
||||||
|
"eslint": "8.33.0", |
||||||
|
"eslint-config-next": "13.1.6", |
||||||
|
"mysql2": "^3.1.2", |
||||||
|
"next": "13.1.6", |
||||||
|
"react": "18.2.0", |
||||||
|
"react-dom": "18.2.0", |
||||||
|
"react-h5-audio-player": "^3.8.6", |
||||||
|
"react-yandex-metrika": "^2.6.0", |
||||||
|
"semantic-ui-css": "^2.5.0", |
||||||
|
"semantic-ui-react": "^2.1.4", |
||||||
|
"typescript": "4.9.5" |
||||||
|
} |
||||||
|
} |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 676 KiB |
After Width: | Height: | Size: 3.6 MiB |
After Width: | Height: | Size: 310 KiB |
After Width: | Height: | Size: 210 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 629 B |
@ -0,0 +1,107 @@ |
|||||||
|
:root { |
||||||
|
--max-width: 1100px; |
||||||
|
--border-radius: 12px; |
||||||
|
--font-mono: ui-monospace, Menlo, Monaco, 'Cascadia Mono', 'Segoe UI Mono', |
||||||
|
'Roboto Mono', 'Oxygen Mono', 'Ubuntu Monospace', 'Source Code Pro', |
||||||
|
'Fira Mono', 'Droid Sans Mono', 'Courier New', monospace; |
||||||
|
|
||||||
|
--foreground-rgb: 0, 0, 0; |
||||||
|
--background-start-rgb: 214, 219, 220; |
||||||
|
--background-end-rgb: 255, 255, 255; |
||||||
|
|
||||||
|
--primary-glow: conic-gradient( |
||||||
|
from 180deg at 50% 50%, |
||||||
|
#16abff33 0deg, |
||||||
|
#0885ff33 55deg, |
||||||
|
#54d6ff33 120deg, |
||||||
|
#0071ff33 160deg, |
||||||
|
transparent 360deg |
||||||
|
); |
||||||
|
--secondary-glow: radial-gradient( |
||||||
|
rgba(255, 255, 255, 1), |
||||||
|
rgba(255, 255, 255, 0) |
||||||
|
); |
||||||
|
|
||||||
|
--tile-start-rgb: 239, 245, 249; |
||||||
|
--tile-end-rgb: 228, 232, 233; |
||||||
|
--tile-border: conic-gradient( |
||||||
|
#00000080, |
||||||
|
#00000040, |
||||||
|
#00000030, |
||||||
|
#00000020, |
||||||
|
#00000010, |
||||||
|
#00000010, |
||||||
|
#00000080 |
||||||
|
); |
||||||
|
|
||||||
|
--callout-rgb: 238, 240, 241; |
||||||
|
--callout-border-rgb: 172, 175, 176; |
||||||
|
--card-rgb: 180, 185, 188; |
||||||
|
--card-border-rgb: 131, 134, 135; |
||||||
|
} |
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) { |
||||||
|
:root { |
||||||
|
--foreground-rgb: 255, 255, 255; |
||||||
|
--background-start-rgb: 0, 0, 0; |
||||||
|
--background-end-rgb: 0, 0, 0; |
||||||
|
|
||||||
|
--primary-glow: radial-gradient(rgba(1, 65, 255, 0.4), rgba(1, 65, 255, 0)); |
||||||
|
--secondary-glow: linear-gradient( |
||||||
|
to bottom right, |
||||||
|
rgba(1, 65, 255, 0), |
||||||
|
rgba(1, 65, 255, 0), |
||||||
|
rgba(1, 65, 255, 0.3) |
||||||
|
); |
||||||
|
|
||||||
|
--tile-start-rgb: 2, 13, 46; |
||||||
|
--tile-end-rgb: 2, 5, 19; |
||||||
|
--tile-border: conic-gradient( |
||||||
|
#ffffff80, |
||||||
|
#ffffff40, |
||||||
|
#ffffff30, |
||||||
|
#ffffff20, |
||||||
|
#ffffff10, |
||||||
|
#ffffff10, |
||||||
|
#ffffff80 |
||||||
|
); |
||||||
|
|
||||||
|
--callout-rgb: 20, 20, 20; |
||||||
|
--callout-border-rgb: 108, 108, 108; |
||||||
|
--card-rgb: 100, 100, 100; |
||||||
|
--card-border-rgb: 200, 200, 200; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
* { |
||||||
|
box-sizing: border-box; |
||||||
|
padding: 0; |
||||||
|
margin: 0; |
||||||
|
} |
||||||
|
|
||||||
|
html, |
||||||
|
body { |
||||||
|
max-width: 100vw; |
||||||
|
overflow-x: hidden; |
||||||
|
} |
||||||
|
|
||||||
|
body { |
||||||
|
color: rgb(var(--foreground-rgb)); |
||||||
|
background: linear-gradient( |
||||||
|
to bottom, |
||||||
|
transparent, |
||||||
|
rgb(var(--background-end-rgb)) |
||||||
|
) |
||||||
|
rgb(var(--background-start-rgb)); |
||||||
|
} |
||||||
|
|
||||||
|
a { |
||||||
|
color: inherit; |
||||||
|
text-decoration: none; |
||||||
|
} |
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) { |
||||||
|
html { |
||||||
|
color-scheme: dark; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,10 @@ |
|||||||
|
export default function Head() { |
||||||
|
return ( |
||||||
|
<> |
||||||
|
<title>Create Next App</title> |
||||||
|
<meta content="width=device-width, initial-scale=1" name="viewport" /> |
||||||
|
<meta name="description" content="Generated by create next app" /> |
||||||
|
<link rel="icon" href="/favicon.ico" /> |
||||||
|
</> |
||||||
|
) |
||||||
|
} |
@ -0,0 +1,18 @@ |
|||||||
|
import './globals.css' |
||||||
|
|
||||||
|
export default function RootLayout({ |
||||||
|
children, |
||||||
|
}: { |
||||||
|
children: React.ReactNode |
||||||
|
}) { |
||||||
|
return ( |
||||||
|
<html lang="en"> |
||||||
|
{/* |
||||||
|
<head /> will contain the components returned by the nearest parent |
||||||
|
head.tsx. Find out more at https://beta.nextjs.org/docs/api-reference/file-conventions/head
|
||||||
|
*/} |
||||||
|
<head /> |
||||||
|
<body>{children}</body> |
||||||
|
</html> |
||||||
|
) |
||||||
|
} |
@ -0,0 +1,271 @@ |
|||||||
|
.main { |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
justify-content: space-between; |
||||||
|
align-items: center; |
||||||
|
padding: 6rem; |
||||||
|
min-height: 100vh; |
||||||
|
} |
||||||
|
|
||||||
|
.description { |
||||||
|
display: inherit; |
||||||
|
justify-content: inherit; |
||||||
|
align-items: inherit; |
||||||
|
font-size: 0.85rem; |
||||||
|
max-width: var(--max-width); |
||||||
|
width: 100%; |
||||||
|
z-index: 2; |
||||||
|
font-family: var(--font-mono); |
||||||
|
} |
||||||
|
|
||||||
|
.description a { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
gap: 0.5rem; |
||||||
|
} |
||||||
|
|
||||||
|
.description p { |
||||||
|
position: relative; |
||||||
|
margin: 0; |
||||||
|
padding: 1rem; |
||||||
|
background-color: rgba(var(--callout-rgb), 0.5); |
||||||
|
border: 1px solid rgba(var(--callout-border-rgb), 0.3); |
||||||
|
border-radius: var(--border-radius); |
||||||
|
} |
||||||
|
|
||||||
|
.code { |
||||||
|
font-weight: 700; |
||||||
|
font-family: var(--font-mono); |
||||||
|
} |
||||||
|
|
||||||
|
.grid { |
||||||
|
display: grid; |
||||||
|
grid-template-columns: repeat(3, minmax(33%, auto)); |
||||||
|
width: var(--max-width); |
||||||
|
max-width: 100%; |
||||||
|
} |
||||||
|
|
||||||
|
.card { |
||||||
|
padding: 1rem 1.2rem; |
||||||
|
border-radius: var(--border-radius); |
||||||
|
background: rgba(var(--card-rgb), 0); |
||||||
|
border: 1px solid rgba(var(--card-border-rgb), 0); |
||||||
|
transition: background 200ms, border 200ms; |
||||||
|
} |
||||||
|
|
||||||
|
.card span { |
||||||
|
display: inline-block; |
||||||
|
transition: transform 200ms; |
||||||
|
} |
||||||
|
|
||||||
|
.card h2 { |
||||||
|
font-weight: 600; |
||||||
|
margin-bottom: 0.7rem; |
||||||
|
} |
||||||
|
|
||||||
|
.card p { |
||||||
|
margin: 0; |
||||||
|
opacity: 0.6; |
||||||
|
font-size: 0.9rem; |
||||||
|
line-height: 1.5; |
||||||
|
max-width: 34ch; |
||||||
|
} |
||||||
|
|
||||||
|
.center { |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
position: relative; |
||||||
|
padding: 4rem 0; |
||||||
|
} |
||||||
|
|
||||||
|
.center::before { |
||||||
|
background: var(--secondary-glow); |
||||||
|
border-radius: 50%; |
||||||
|
width: 480px; |
||||||
|
height: 360px; |
||||||
|
margin-left: -400px; |
||||||
|
} |
||||||
|
|
||||||
|
.center::after { |
||||||
|
background: var(--primary-glow); |
||||||
|
width: 240px; |
||||||
|
height: 180px; |
||||||
|
z-index: -1; |
||||||
|
} |
||||||
|
|
||||||
|
.center::before, |
||||||
|
.center::after { |
||||||
|
content: ''; |
||||||
|
left: 50%; |
||||||
|
position: absolute; |
||||||
|
filter: blur(45px); |
||||||
|
transform: translateZ(0); |
||||||
|
} |
||||||
|
|
||||||
|
.logo, |
||||||
|
.thirteen { |
||||||
|
position: relative; |
||||||
|
} |
||||||
|
|
||||||
|
.thirteen { |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
width: 75px; |
||||||
|
height: 75px; |
||||||
|
padding: 25px 10px; |
||||||
|
margin-left: 16px; |
||||||
|
transform: translateZ(0); |
||||||
|
border-radius: var(--border-radius); |
||||||
|
overflow: hidden; |
||||||
|
box-shadow: 0px 2px 8px -1px #0000001a; |
||||||
|
} |
||||||
|
|
||||||
|
.thirteen::before, |
||||||
|
.thirteen::after { |
||||||
|
content: ''; |
||||||
|
position: absolute; |
||||||
|
z-index: -1; |
||||||
|
} |
||||||
|
|
||||||
|
/* Conic Gradient Animation */ |
||||||
|
.thirteen::before { |
||||||
|
animation: 6s rotate linear infinite; |
||||||
|
width: 200%; |
||||||
|
height: 200%; |
||||||
|
background: var(--tile-border); |
||||||
|
} |
||||||
|
|
||||||
|
/* Inner Square */ |
||||||
|
.thirteen::after { |
||||||
|
inset: 0; |
||||||
|
padding: 1px; |
||||||
|
border-radius: var(--border-radius); |
||||||
|
background: linear-gradient( |
||||||
|
to bottom right, |
||||||
|
rgba(var(--tile-start-rgb), 1), |
||||||
|
rgba(var(--tile-end-rgb), 1) |
||||||
|
); |
||||||
|
background-clip: content-box; |
||||||
|
} |
||||||
|
|
||||||
|
/* Enable hover only on non-touch devices */ |
||||||
|
@media (hover: hover) and (pointer: fine) { |
||||||
|
.card:hover { |
||||||
|
background: rgba(var(--card-rgb), 0.1); |
||||||
|
border: 1px solid rgba(var(--card-border-rgb), 0.15); |
||||||
|
} |
||||||
|
|
||||||
|
.card:hover span { |
||||||
|
transform: translateX(4px); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@media (prefers-reduced-motion) { |
||||||
|
.thirteen::before { |
||||||
|
animation: none; |
||||||
|
} |
||||||
|
|
||||||
|
.card:hover span { |
||||||
|
transform: none; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* Mobile and Tablet */ |
||||||
|
@media (max-width: 1023px) { |
||||||
|
.content { |
||||||
|
padding: 4rem; |
||||||
|
} |
||||||
|
|
||||||
|
.grid { |
||||||
|
grid-template-columns: 1fr; |
||||||
|
margin-bottom: 120px; |
||||||
|
max-width: 320px; |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
|
||||||
|
.card { |
||||||
|
padding: 1rem 2.5rem; |
||||||
|
} |
||||||
|
|
||||||
|
.card h2 { |
||||||
|
margin-bottom: 0.5rem; |
||||||
|
} |
||||||
|
|
||||||
|
.center { |
||||||
|
padding: 8rem 0 6rem; |
||||||
|
} |
||||||
|
|
||||||
|
.center::before { |
||||||
|
transform: none; |
||||||
|
height: 300px; |
||||||
|
} |
||||||
|
|
||||||
|
.description { |
||||||
|
font-size: 0.8rem; |
||||||
|
} |
||||||
|
|
||||||
|
.description a { |
||||||
|
padding: 1rem; |
||||||
|
} |
||||||
|
|
||||||
|
.description p, |
||||||
|
.description div { |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
position: fixed; |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
|
||||||
|
.description p { |
||||||
|
align-items: center; |
||||||
|
inset: 0 0 auto; |
||||||
|
padding: 2rem 1rem 1.4rem; |
||||||
|
border-radius: 0; |
||||||
|
border: none; |
||||||
|
border-bottom: 1px solid rgba(var(--callout-border-rgb), 0.25); |
||||||
|
background: linear-gradient( |
||||||
|
to bottom, |
||||||
|
rgba(var(--background-start-rgb), 1), |
||||||
|
rgba(var(--callout-rgb), 0.5) |
||||||
|
); |
||||||
|
background-clip: padding-box; |
||||||
|
backdrop-filter: blur(24px); |
||||||
|
} |
||||||
|
|
||||||
|
.description div { |
||||||
|
align-items: flex-end; |
||||||
|
pointer-events: none; |
||||||
|
inset: auto 0 0; |
||||||
|
padding: 2rem; |
||||||
|
height: 200px; |
||||||
|
background: linear-gradient( |
||||||
|
to bottom, |
||||||
|
transparent 0%, |
||||||
|
rgb(var(--background-end-rgb)) 40% |
||||||
|
); |
||||||
|
z-index: 1; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) { |
||||||
|
.vercelLogo { |
||||||
|
filter: invert(1); |
||||||
|
} |
||||||
|
|
||||||
|
.logo, |
||||||
|
.thirteen img { |
||||||
|
filter: invert(1) drop-shadow(0 0 0.3rem #ffffff70); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@keyframes rotate { |
||||||
|
from { |
||||||
|
transform: rotate(360deg); |
||||||
|
} |
||||||
|
to { |
||||||
|
transform: rotate(0deg); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,146 @@ |
|||||||
|
"use client"; |
||||||
|
|
||||||
|
import React, { useState, useEffect} from 'react'; |
||||||
|
import { |
||||||
|
Container, |
||||||
|
Grid, |
||||||
|
Header, |
||||||
|
List, |
||||||
|
Segment, |
||||||
|
Label, |
||||||
|
} from 'semantic-ui-react'; |
||||||
|
import { Item } from 'semantic-ui-react'; |
||||||
|
import 'semantic-ui-css/semantic.min.css'; |
||||||
|
import AudioPlayer from 'react-h5-audio-player'; |
||||||
|
import 'react-h5-audio-player/lib/styles.css'; |
||||||
|
|
||||||
|
type Props = { |
||||||
|
id: number; |
||||||
|
audio: string; |
||||||
|
description: string; |
||||||
|
urlImg: string; |
||||||
|
title_items: string; |
||||||
|
children: Node; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
const Views = async (e : number) =>{ |
||||||
|
console.log('id:',e) |
||||||
|
await fetch('/api/podcasts/views', {method: 'POST', body: e as any}) |
||||||
|
.then((data) => { |
||||||
|
console.log(data) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
const PodcastBlocks: React.FC<Props> = ({id, audio, description, urlImg, title_items}) => ( |
||||||
|
<> |
||||||
|
<Item> |
||||||
|
<Item.Image size='medium' src={'img/'+urlImg} /> |
||||||
|
<Item.Content> |
||||||
|
<Item.Header as='a'>{title_items}</Item.Header> |
||||||
|
<Item.Meta> |
||||||
|
<span className='cinema'></span> |
||||||
|
</Item.Meta> |
||||||
|
<Item.Description> |
||||||
|
{description} |
||||||
|
</Item.Description> |
||||||
|
<AudioPlayer |
||||||
|
src={"audio/"+audio} |
||||||
|
onPlay={e => Views(id)} |
||||||
|
/> |
||||||
|
<Item.Extra> |
||||||
|
<Label icon='globe' content='-' /> |
||||||
|
</Item.Extra> |
||||||
|
</Item.Content> |
||||||
|
</Item> |
||||||
|
</> |
||||||
|
) |
||||||
|
|
||||||
|
|
||||||
|
export default function Home() { |
||||||
|
interface IUser { |
||||||
|
[x: string]: any; |
||||||
|
name: string; |
||||||
|
}; |
||||||
|
const [data, setData] = useState<IUser>(); |
||||||
|
const [isLoading, setLoading] = useState(false) |
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
setLoading(true) |
||||||
|
fetch('/api/podcasts/all') |
||||||
|
.then((res) => res.json()) |
||||||
|
.then((data) => { |
||||||
|
setData(data); |
||||||
|
setLoading(false); |
||||||
|
}) |
||||||
|
}, []) |
||||||
|
|
||||||
|
if (isLoading) return <p>Загрузка...</p> |
||||||
|
if (!data) return <p>Нет интернета</p> |
||||||
|
|
||||||
|
const podcasts = data.map((obj: JSX.IntrinsicAttributes & Props, index: React.Key | null | undefined) => <PodcastBlocks key={index} {...obj}/> ); |
||||||
|
|
||||||
|
return ( |
||||||
|
<> |
||||||
|
<Segment style={{ padding: '8em 0em' }} vertical> |
||||||
|
<Grid container stackable textAlign='center'> |
||||||
|
<Grid.Row> |
||||||
|
<Grid.Column width={12} textAlign='center'> |
||||||
|
<Header as='h3' style={{ fontSize: '4em' }}> |
||||||
|
BlogBaster |
||||||
|
</Header> |
||||||
|
<Header as='h3' style={{ fontSize: '2em' }}> |
||||||
|
Увлечены. Качественно. |
||||||
|
За новое звучание. |
||||||
|
</Header> |
||||||
|
<p style={{ fontSize: '1.33em' }}> |
||||||
|
Если вы хотите стать нашим партнером или рекламодателем — пишите на podcast@blogbaster.xyz |
||||||
|
</p> |
||||||
|
</Grid.Column> |
||||||
|
</Grid.Row> |
||||||
|
</Grid> |
||||||
|
</Segment> |
||||||
|
<Segment style={{ padding: '8em 0em' }} vertical> |
||||||
|
<Container textAlign='left'> |
||||||
|
<Item.Group> |
||||||
|
{podcasts} |
||||||
|
</Item.Group> |
||||||
|
</Container> |
||||||
|
</Segment> |
||||||
|
|
||||||
|
<Segment inverted vertical style={{ padding: '5em 0em' }}> |
||||||
|
<Container> |
||||||
|
<Grid divided inverted stackable> |
||||||
|
<Grid.Row> |
||||||
|
<Grid.Column width={3}> |
||||||
|
<Header inverted as='h4' content='Социальные сети' /> |
||||||
|
<List link inverted> |
||||||
|
<List.Item as='a'>Вконтакте</List.Item> |
||||||
|
<List.Item as='a'>Telegram</List.Item> |
||||||
|
</List> |
||||||
|
</Grid.Column> |
||||||
|
<Grid.Column width={3}> |
||||||
|
<Header inverted as='h4' content='Платформы' /> |
||||||
|
<List link inverted> |
||||||
|
<List.Item as='a'>Яндекс музыка</List.Item> |
||||||
|
<List.Item as='a'>Google подкасты</List.Item> |
||||||
|
<List.Item as='a'>Apple подкасты</List.Item> |
||||||
|
</List> |
||||||
|
</Grid.Column> |
||||||
|
<Grid.Column width={7}> |
||||||
|
<Header as='h4' inverted> |
||||||
|
О нас |
||||||
|
</Header> |
||||||
|
<p> |
||||||
|
BlogBaster 2022 |
||||||
|
</p> |
||||||
|
</Grid.Column> |
||||||
|
</Grid.Row> |
||||||
|
</Grid> |
||||||
|
</Container> |
||||||
|
</Segment> |
||||||
|
</> |
||||||
|
) |
||||||
|
} |
@ -0,0 +1,29 @@ |
|||||||
|
import { writeFileSync } from "fs"; |
||||||
|
import { getAllPosts } from "./posts"; |
||||||
|
import RSS from "rss"; |
||||||
|
const post = [{title:'ddee', url:'dfdf', date:'12.12.22', description:'dfdf dfdf dfdf'}] |
||||||
|
export default async function getRSS() { |
||||||
|
const siteURL = "https://yourdomain.com"; |
||||||
|
const allBlogs = getAllPosts(); |
||||||
|
|
||||||
|
const feed = new RSS({ |
||||||
|
title: "Your Name", |
||||||
|
description: "your description", |
||||||
|
site_url: siteURL, |
||||||
|
feed_url: `${siteURL}/feed.xml`, |
||||||
|
language: "en", |
||||||
|
pubDate: new Date(), |
||||||
|
copyright: `All rights reserved ${new Date().getFullYear()}, Your Name`, |
||||||
|
}); |
||||||
|
|
||||||
|
post.map((post) => { |
||||||
|
feed.item({ |
||||||
|
title: post.title, |
||||||
|
url: `${siteURL}/blogs/${post.slug}`, |
||||||
|
date: post.date, |
||||||
|
description: post.excerpt, |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
writeFileSync("../../public/feed.xml", feed.xml({ indent: true })); |
||||||
|
} |
@ -0,0 +1,13 @@ |
|||||||
|
export function getAllPosts() { |
||||||
|
const posts = getSlugs() |
||||||
|
.map((slug) => { |
||||||
|
return getFrontMatter(slug); |
||||||
|
}) |
||||||
|
.filter((post) => post != null || post != undefined) // Filter post if it is not published
|
||||||
|
.sort((a, b) => { |
||||||
|
if (new Date(a.date) > new Date(b.date)) return -1; |
||||||
|
if (new Date(a.date) < new Date(b.date)) return 1; |
||||||
|
return 0; |
||||||
|
}); |
||||||
|
return posts; |
||||||
|
} |
@ -0,0 +1,13 @@ |
|||||||
|
import Select from "../../../server/db/select"; |
||||||
|
import type { NextApiRequest, NextApiResponse } from 'next'; |
||||||
|
|
||||||
|
const sql = "SELECT items.id, urlImg,items.description, items.title_items, items.audio FROM podcasts, items WHERE podcasts.id=items.id_podcasts and items.status=1"; |
||||||
|
|
||||||
|
export default function handler( |
||||||
|
req: NextApiRequest, |
||||||
|
res: NextApiResponse |
||||||
|
) { |
||||||
|
Select(sql, function(data){ |
||||||
|
res.status(200).json(data); |
||||||
|
}) |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||||
|
import type { NextApiRequest, NextApiResponse } from 'next' |
||||||
|
import Select from "../../../../../server/db/select"; |
||||||
|
import Insert from "../../../../../server/db/insert"; |
||||||
|
import { getRssXml, Items } from '../../../../../сomponents/podcasts'; |
||||||
|
|
||||||
|
const id = 1; |
||||||
|
|
||||||
|
const sql_company = "SELECT * FROM podcasts, company WHERE podcasts.id="+id; |
||||||
|
const sql_items = "SELECT * FROM `podcasts`, items, company WHERE podcasts.id=items.id_podcasts and podcasts.id="+id; |
||||||
|
|
||||||
|
const sql_userAgent = "INSERT INTO views (id_podcasts, userAgent,ip) VALUES (?,?,?)"; |
||||||
|
|
||||||
|
export default function handler( |
||||||
|
req: NextApiRequest, |
||||||
|
res: NextApiResponse |
||||||
|
) { |
||||||
|
const views = [id, req.headers['user-agent'], req.socket.remoteAddress] |
||||||
|
Select(sql_company, function(data_company : any){ |
||||||
|
Select(sql_items, function(data_items : any){ |
||||||
|
res.setHeader('Content-Type', 'text/xml'); |
||||||
|
res.status(200).send(getRssXml(data_company[0])+data_items.map((rows : any) => Items(rows))+'</channel> </rss>'); |
||||||
|
}) |
||||||
|
|
||||||
|
}) |
||||||
|
Insert(sql_userAgent, views as string[], function(message){ |
||||||
|
console.log(message); |
||||||
|
}) |
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,29 @@ |
|||||||
|
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||||
|
import type { NextApiRequest, NextApiResponse } from 'next' |
||||||
|
import Select from "../../../../../server/db/select"; |
||||||
|
import Insert from "../../../../../server/db/insert"; |
||||||
|
import { getRssXml, Items } from '../../../../../сomponents/podcasts'; |
||||||
|
|
||||||
|
const id = 2; |
||||||
|
|
||||||
|
const sql_company = "SELECT * FROM podcasts, company WHERE podcasts.id="+id; |
||||||
|
const sql_items = "SELECT * FROM `podcasts`, items, company WHERE podcasts.id=items.id_podcasts and podcasts.id="+id; |
||||||
|
|
||||||
|
const sql_userAgent = "INSERT INTO views (id_podcasts, userAgent,ip) VALUES (?,?,?)"; |
||||||
|
|
||||||
|
export default function handler( |
||||||
|
req: NextApiRequest, |
||||||
|
res: NextApiResponse |
||||||
|
) { |
||||||
|
const views = [id, req.headers['user-agent'], req.socket.remoteAddress] |
||||||
|
Select(sql_company, function(data_company : any){ |
||||||
|
Select(sql_items, function(data_items : any){ |
||||||
|
res.setHeader('Content-Type', 'text/xml'); |
||||||
|
res.status(200).send(getRssXml(data_company[0])+data_items.map((rows : any) => Items(rows))+'</channel> </rss>'); |
||||||
|
}) |
||||||
|
|
||||||
|
}) |
||||||
|
Insert(sql_userAgent, views as string[], function(message){ |
||||||
|
console.log(message); |
||||||
|
}) |
||||||
|
}
|
@ -0,0 +1,29 @@ |
|||||||
|
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||||
|
import type { NextApiRequest, NextApiResponse } from 'next' |
||||||
|
import Select from "../../../../../server/db/select"; |
||||||
|
import Insert from "../../../../../server/db/insert"; |
||||||
|
import { getRssXml, Items } from '../../../../../сomponents/podcasts'; |
||||||
|
|
||||||
|
const id = 3; |
||||||
|
|
||||||
|
const sql_company = "SELECT * FROM podcasts, company WHERE podcasts.id="+id; |
||||||
|
const sql_items = "SELECT * FROM `podcasts`, items, company WHERE podcasts.id=items.id_podcasts and podcasts.id="+id; |
||||||
|
|
||||||
|
const sql_userAgent = "INSERT INTO views (id_podcasts, userAgent,ip) VALUES (?,?,?)"; |
||||||
|
|
||||||
|
export default function handler( |
||||||
|
req: NextApiRequest, |
||||||
|
res: NextApiResponse |
||||||
|
) { |
||||||
|
const views = [id, req.headers['user-agent'], req.socket.remoteAddress] |
||||||
|
Select(sql_company, function(data_company : any){ |
||||||
|
Select(sql_items, function(data_items : any){ |
||||||
|
res.setHeader('Content-Type', 'text/xml'); |
||||||
|
res.status(200).send(getRssXml(data_company[0])+data_items.map((rows : any) => Items(rows))+'</channel> </rss>'); |
||||||
|
}) |
||||||
|
|
||||||
|
}) |
||||||
|
Insert(sql_userAgent, views as string[], function(message){ |
||||||
|
console.log(message); |
||||||
|
}) |
||||||
|
}
|
@ -0,0 +1,18 @@ |
|||||||
|
import type { NextApiRequest, NextApiResponse } from 'next' |
||||||
|
import Insert from "../../../server/db/insert"; |
||||||
|
|
||||||
|
export default function handler( |
||||||
|
req: NextApiRequest, |
||||||
|
res: NextApiResponse |
||||||
|
) { |
||||||
|
console.log('in') |
||||||
|
const parm = req.body; |
||||||
|
console.log(parm) |
||||||
|
const sql_userAgent = "INSERT INTO views (id_podcasts, userAgent,ip) VALUES (?,?,?)"; |
||||||
|
//const views = [parm, req.headers['user-agent'], req.socket.remoteAddress]
|
||||||
|
res.status(200).json(12); |
||||||
|
//Insert(sql_userAgent, views as string[], function(message){
|
||||||
|
// console.log(message);
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@ |
|||||||
|
import mysql from "mysql2"; |
||||||
|
|
||||||
|
const pool = mysql.createPool({ |
||||||
|
host: process.env.HOST, |
||||||
|
user: process.env.DATABASE, |
||||||
|
database: process.env.DATABASE, |
||||||
|
password: process.env.PASSWORD, |
||||||
|
waitForConnections: true, |
||||||
|
connectionLimit: 10, |
||||||
|
queueLimit: 0 |
||||||
|
}); |
||||||
|
|
||||||
|
module.exports = pool; |
@ -0,0 +1,14 @@ |
|||||||
|
const pool = require("./connect"); |
||||||
|
import {QueryError} from 'mysql2'; |
||||||
|
|
||||||
|
interface definitionInterface{ |
||||||
|
(message:string):void; |
||||||
|
} |
||||||
|
export default function Insert(sql: string, argument: string[], callback: definitionInterface) { |
||||||
|
pool.query(sql, argument, (err: QueryError, rows: string) => { |
||||||
|
if (err) { |
||||||
|
return console.error(err.message); |
||||||
|
} |
||||||
|
pool.releaseConnection(pool); |
||||||
|
}); |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
const pool = require("./connect"); |
||||||
|
import {QueryError} from 'mysql2'; |
||||||
|
|
||||||
|
interface definitionInterface{ |
||||||
|
(message:string):void; |
||||||
|
} |
||||||
|
export default function Select(sql: string, callback: definitionInterface) { |
||||||
|
pool.query(sql, (err: QueryError, rows: string) => { |
||||||
|
callback(rows); |
||||||
|
pool.releaseConnection(pool); |
||||||
|
}); |
||||||
|
} |
@ -0,0 +1,42 @@ |
|||||||
|
interface Props { |
||||||
|
episode: number; |
||||||
|
title: string; |
||||||
|
title_items : string; |
||||||
|
description: string; |
||||||
|
guid: string; |
||||||
|
pubDate: string; |
||||||
|
duration: number; |
||||||
|
urlImg: string; |
||||||
|
fileSize: number; |
||||||
|
audio: string; |
||||||
|
webSite: string; |
||||||
|
nameCompanies: string; |
||||||
|
} |
||||||
|
|
||||||
|
export const Items = (data: Props) => { |
||||||
|
let item =` |
||||||
|
<item> |
||||||
|
<itunes:episodeType>full</itunes:episodeType> |
||||||
|
<itunes:episode>`+data.episode+`</itunes:episode> |
||||||
|
<itunes:season>1</itunes:season> |
||||||
|
<title><![CDATA[`+data.title+': '+data.title_items +`]]></title> |
||||||
|
<description><![CDATA[`+data.description+`]]></description> |
||||||
|
<googleplay:description>`+data.description+`</googleplay:description> |
||||||
|
<itunes:summary>`+data.description+`</itunes:summary> |
||||||
|
<guid isPermaLink="false">`+data.guid+`</guid> |
||||||
|
<pubDate>`+data.pubDate+`</pubDate> |
||||||
|
<itunes:duration>`+data.duration+`</itunes:duration> |
||||||
|
<link>`+data.webSite+'/podcast/'+data.guid+`</link> |
||||||
|
<googleplay:image href="`+data.webSite+'/img/'+data.urlImg+`"/> |
||||||
|
<itunes:image href="`+data.webSite+'/img/'+data.urlImg+`"/> |
||||||
|
<googleplay:explicit>no</googleplay:explicit> |
||||||
|
<itunes:explicit>false</itunes:explicit> |
||||||
|
<enclosure url="`+data.webSite+'/audio/'+data.audio+`" length="`+data.fileSize+`" type="audio/mpeg"/> |
||||||
|
<media:title>`+data.title+': '+data.title_items +`</media:title> |
||||||
|
<media:content url="`+data.webSite+'/audio/'+data.audio+`" fileSize="`+data.fileSize+`" type="audio/mpeg" medium="audio" isDefault="true" expression="full" bitrate="320" channels="2" duration="`+data.duration+`" lang="ru"/> |
||||||
|
<media:thumbnail url="`+data.webSite+'/img/'+data.urlImg+`" width="150" height="150"/> |
||||||
|
<media:copyright url="`+data.webSite+`">© 2022 `+data.nameCompanies+`</media:copyright> |
||||||
|
<creativeCommons:license>https://creativecommons.org/licenses/by/4.0/</creativeCommons:license>
|
||||||
|
</item>`;
|
||||||
|
return(item) |
||||||
|
}; |
@ -0,0 +1,61 @@ |
|||||||
|
import { Items } from './Item' |
||||||
|
|
||||||
|
interface Props { |
||||||
|
map(arg0: (rows: any) => string): unknown; |
||||||
|
title: string, |
||||||
|
atom_link: string, |
||||||
|
email: string, |
||||||
|
nameCompanies: string, |
||||||
|
description: string, |
||||||
|
webSite: string, |
||||||
|
urlImg: string, |
||||||
|
lastBuildDate: string |
||||||
|
} |
||||||
|
|
||||||
|
export const getRssXml = (data: Props) => { |
||||||
|
let item =` |
||||||
|
<rss version="2.0" |
||||||
|
xmlns:atom="http://www.w3.org/2005/Atom" |
||||||
|
xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0/play-podcasts.xsd" |
||||||
|
xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" |
||||||
|
xmlns:content="http://purl.org/rss/1.0/modules/content/" |
||||||
|
xmlns:media="http://search.yahoo.com/mrss/" |
||||||
|
xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" |
||||||
|
> |
||||||
|
<channel> |
||||||
|
<title>`+data.title+`</title> |
||||||
|
<atom:link href="`+data.atom_link+`" rel="self" type="application/rss+xml"/> |
||||||
|
<googleplay:owner>`+data.email+`</googleplay:owner> |
||||||
|
<itunes:owner> |
||||||
|
<itunes:name>`+data.nameCompanies+`</itunes:name> |
||||||
|
<itunes:email>`+data.email+`</itunes:email> |
||||||
|
</itunes:owner> |
||||||
|
<googleplay:author>`+data.nameCompanies+`</googleplay:author> |
||||||
|
<itunes:author>`+data.nameCompanies+`</itunes:author> |
||||||
|
<description>`+data.description+`</description> |
||||||
|
<googleplay:description>`+data.description+`</googleplay:description> |
||||||
|
<itunes:summary>`+data.description+`</itunes:summary> |
||||||
|
<image> |
||||||
|
<link>`+data.webSite+`</link> |
||||||
|
<title>`+data.nameCompanies+`</title> |
||||||
|
<url>`+data.webSite+'/'+data.urlImg+`</url> |
||||||
|
</image> |
||||||
|
<googleplay:image href="`+data.webSite+'/'+data.urlImg+`"/> |
||||||
|
<itunes:image href="`+data.webSite+'/'+data.urlImg+`"/> |
||||||
|
<itunes:category text="Society & Culture"> |
||||||
|
<itunes:category text="Places & Travel"/> |
||||||
|
</itunes:category> |
||||||
|
<itunes:category text="Science"> |
||||||
|
<itunes:category text="Social Sciences"/> |
||||||
|
</itunes:category> |
||||||
|
<language>ru</language> |
||||||
|
<link>`+data.webSite+`</link> |
||||||
|
<copyright>© 2022 `+data.nameCompanies+`</copyright> |
||||||
|
<itunes:type>episodic</itunes:type> |
||||||
|
<googleplay:explicit>no</googleplay:explicit> |
||||||
|
<itunes:explicit>no</itunes:explicit> |
||||||
|
<lastBuildDate>`+data.lastBuildDate+`</lastBuildDate> |
||||||
|
<googleplay:block>yes</googleplay:block>`; |
||||||
|
return(item) |
||||||
|
}; |
||||||
|
|
@ -0,0 +1,2 @@ |
|||||||
|
export * from './Item' |
||||||
|
export * from './getRssXml' |
@ -0,0 +1,29 @@ |
|||||||
|
{ |
||||||
|
"compilerOptions": { |
||||||
|
"target": "es5", |
||||||
|
"lib": ["dom", "dom.iterable", "esnext"], |
||||||
|
"allowJs": true, |
||||||
|
"skipLibCheck": true, |
||||||
|
"strict": true, |
||||||
|
"forceConsistentCasingInFileNames": true, |
||||||
|
"noEmit": true, |
||||||
|
"esModuleInterop": true, |
||||||
|
"module": "esnext", |
||||||
|
"moduleResolution": "node", |
||||||
|
"resolveJsonModule": true, |
||||||
|
"isolatedModules": true, |
||||||
|
"jsx": "preserve", |
||||||
|
"incremental": true, |
||||||
|
"plugins": [ |
||||||
|
{ |
||||||
|
"name": "next" |
||||||
|
} |
||||||
|
], |
||||||
|
"baseUrl": ".", |
||||||
|
"paths": { |
||||||
|
"@/*": ["./src/*"] |
||||||
|
} |
||||||
|
}, |
||||||
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], |
||||||
|
"exclude": ["node_modules"] |
||||||
|
} |