0
Fork 0
mirror of https://codeberg.org/SafeTwitch/safetwitch.git synced 2024-12-22 05:12:57 -05:00

Run eslint and fix all issues

This commit is contained in:
dragongoose 2023-03-18 13:49:02 -04:00
parent 0c38345bd1
commit c31def6221
14 changed files with 333 additions and 272 deletions

View file

@ -11,5 +11,6 @@ module.exports = {
],
parserOptions: {
ecmaVersion: 'latest'
}
},
'ignorePatterns': ["*.config.*"]
}

View file

@ -1,12 +1,12 @@
<script setup lang="ts">
import { RouterView } from 'vue-router'
import NavbarItem from './components/Navbar.vue'
import NavbarItem from './components/NavbarView.vue'
</script>
<template>
<navbar-item></navbar-item>
<Suspense>
<RouterView />
</Suspense>
</template>
</template>

View file

@ -1,3 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@tailwind utilities;

View file

@ -1,27 +1,22 @@
import type { VideoJsPlayer } from "video.js";
import "videojs-contrib-quality-levels";
import type { QualityLevelList } from "videojs-contrib-quality-levels";
import 'videojs-contrib-quality-levels'
import type { QualityLevelList } from 'videojs-contrib-quality-levels'
export const createQualitySelector = (player: VideoJsPlayer) => {
const qualityLevels: QualityLevelList = player.qualityLevels()
let currentIndex = 0
export const createQualitySelector = (player: any) => {
const qualityLevels: QualityLevelList = player.qualityLevels()
player.hlsQualitySelector()
var myButton = player.controlBar.addChild("button");
var myButtonDom = myButton.el();
myButtonDom.innerHTML = "Hello";
const myButton = player.controlBar.addChild('button')
const myButtonDom = myButton.el()
myButtonDom.innerHTML = 'Hello'
myButtonDom.addEventListener('click', () => {
})
myButtonDom.addEventListener('click', () => {})
qualityLevels.on('change', function() {
console.log('Quality Level changed!');
console.log('New level:', qualityLevels[qualityLevels.selectedIndex]);
console.log(qualityLevels)
qualityLevels.on('change', function () {
console.log('Quality Level changed!')
console.log('New level:', qualityLevels[qualityLevels.selectedIndex])
console.log(qualityLevels)
const qualityLabel = qualityLevels[qualityLevels.selectedIndex].height?.toString() + 'p'
const qualityLabel = qualityLevels[qualityLevels.selectedIndex].height?.toString() + 'p'
myButtonDom.textContent = qualityLabel ?? ''
});
}
myButtonDom.textContent = qualityLabel ?? ''
})
}

View file

@ -1,26 +0,0 @@
<script lang="ts">
export default {};
import { RouterLink } from 'vue-router'
</script>
<template>
<div class="p-4 flex items-center justify-between bg-ctp-base text-white">
<h1 class="font-bold text-2xl">Naqvbar</h1>
<div>
<form class="relative">
<label for="searchBar" class="hidden">Search</label>
<v-icon name="io-search-outline" class="text-black absolute my-auto inset-y-0 left-2"></v-icon>
<input type="text" id="searchBar" name="searchBar" placeholder="Search" class="rounded-md p-1 pl-8 text-black">
</form>
</div>
<ul class="inline-flex space-x-6 font-medium">
<router-link to="">Github</router-link>
<router-link to="/preferences">Preferences</router-link>
<router-link to="/about">About</router-link>
</ul>
</div>
</template>

View file

@ -0,0 +1,32 @@
<script lang="ts">
export default {}
</script>
<template>
<div class="p-4 flex items-center justify-between bg-ctp-base text-white">
<h1 class="font-bold text-2xl">Naqvbar</h1>
<div>
<form class="relative">
<label for="searchBar" class="hidden">Search</label>
<v-icon
name="io-search-outline"
class="text-black absolute my-auto inset-y-0 left-2"
></v-icon>
<input
type="text"
id="searchBar"
name="searchBar"
placeholder="Search"
class="rounded-md p-1 pl-8 text-black"
/>
</form>
</div>
<ul class="inline-flex space-x-6 font-medium">
<router-link to="">Github</router-link>
<router-link to="/preferences">Preferences</router-link>
<router-link to="/about">About</router-link>
</ul>
</div>
</template>

View file

@ -1,16 +1,66 @@
<script lang="ts">
export default {
props: {
isLive: {
type: Boolean,
default() {
return false;
}
}
},
import { ref, type Ref } from 'vue'
export default {
props: {
isLive: {
type: Boolean,
default() {
return false
}
},
channelName: {
type: String
}
},
setup(props) {
let messages: Ref<
{ username: string; channel: string; message: string; messageType: string }[]
> = ref([])
let ws = new WebSocket('ws://localhost:7000')
return {
ws,
messages,
props
}
},
mounted() {
const chatList = this.$refs.chatList as Element
this.ws.onmessage = (message) => {
if (message.data !== 'OK') {
this.messages.push(JSON.parse(message.data))
this.scrollToBottom(chatList)
}
}
this.ws.onopen = (data) => {
console.log(data)
this.ws.send('JOIN ' + this.props.channelName)
}
},
methods: {
getChat() {
return this.messages
},
scrollToBottom(el: Element) {
el.scrollTop = el.scrollHeight
}
}
}
</script>
<template>
<div v-if="isLive" class="p-3 bg-ctp-crust rounded-lg w-full max-w-xs">
</div>
</template>
<div v-if="isLive" class="p-3 bg-ctp-crust rounded-lg w-full max-w-xs flex flex-col">
<ul class="overflow-y-scroll h-[82vh]" ref="chatList">
<li v-for="message in getChat()" :key="messages.indexOf(message)">
<div class="text-white inline-flex">
<p class="text-sm">
<strong class="text-ctp-pink font-bold text-sm">{{ message.username }}</strong
>: {{ message.message }}
</p>
</div>
</li>
</ul>
</div>
</template>

View file

@ -5,10 +5,12 @@
</template>
<script lang="ts">
// Importing video-js
import videojs from 'video.js';
import { createQualitySelector } from '../assets/qualitySelector'
import "videojs-contrib-quality-levels";
import "../assets/vjs-theme.css"
import videojs from 'video.js'
import qualitySelector from 'videojs-hls-quality-selector'
import qualityLevels from 'videojs-contrib-quality-levels'
videojs.registerPlugin('qualityLevels', qualityLevels)
videojs.registerPlugin('hlsQualitySelector', qualitySelector)
export default {
name: 'VideoJsPlayer',
@ -16,7 +18,7 @@ export default {
options: {
type: Object,
default() {
return {};
return {}
}
}
},
@ -30,22 +32,8 @@ export default {
// when the component is being mounted
mounted() {
this.player = videojs('video-player', this.options, () => {
this.player.log('video player ready', this);
this.player.hlsQualitySelector({
displayCurrentQuality: true,
});
createQualitySelector(this.player)
});
},
// destroying the video player
// when the component is being destroyed
beforeDestroy() {
if (this.player) {
this.player.dispose();
}
this.player.hlsQualitySelector({ displayCurrentQuality: true })
})
}
}
</script><link rel="stylesheet" href="style.css">
</script>

View file

@ -8,13 +8,29 @@ import 'video.js/dist/video-js.css'
const app = createApp(App)
import { OhVueIcon, addIcons } from "oh-vue-icons";
import { IoSearchOutline, IoLink, FaCircleNotch, BiTwitter, BiInstagram, BiDiscord, BiYoutube, BiTiktok } from "oh-vue-icons/icons";
import { OhVueIcon, addIcons } from 'oh-vue-icons'
import {
IoSearchOutline,
IoLink,
FaCircleNotch,
BiTwitter,
BiInstagram,
BiDiscord,
BiYoutube,
BiTiktok
} from 'oh-vue-icons/icons'
addIcons(IoSearchOutline, IoLink, FaCircleNotch, BiTwitter, BiInstagram, BiDiscord, BiYoutube, BiTiktok)
addIcons(
IoSearchOutline,
IoLink,
FaCircleNotch,
BiTwitter,
BiInstagram,
BiDiscord,
BiYoutube,
BiTiktok
)
app.component("v-icon", OhVueIcon);
app.component('v-icon', OhVueIcon)
app.use(router)
app.mount('#app')

View file

@ -1,5 +1,4 @@
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
import UserView from '../views/UserView.vue'
import PageNotFound from '../views/PageNotFound.vue'
import PrivacyPageView from '../views/PrivacyPageView.vue'
@ -7,11 +6,6 @@ import PrivacyPageView from '../views/PrivacyPageView.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/privacy',
name: 'about',
@ -21,7 +15,7 @@ const router = createRouter({
path: '/:username',
component: UserView
},
{ path: '/:pathMatch(.*)*', component: PageNotFound}
{ path: '/:pathMatch(.*)*', component: PageNotFound }
]
})

View file

@ -1,7 +0,0 @@
<script setup lang="ts">
</script>
<template>
</template>

View file

@ -1,11 +1,11 @@
<script lang="ts">
export default {};
export default {}
</script>
<template>
<div class="flex flex-col items-center pt-10 font-bold text-5xl text-white">
<h1>oops....</h1>
<h1>this page wasn't found()</h1>
<h2 class="text-4xl">maybe go <RouterLink to="/" class="text-gray-500">home</RouterLink>?</h2>
</div>
</template>
<div class="flex flex-col items-center pt-10 font-bold text-5xl text-white">
<h1>oops....</h1>
<h1>this page wasn't found()</h1>
<h2 class="text-4xl">maybe go <RouterLink to="/" class="text-gray-500">home</RouterLink>?</h2>
</div>
</template>

View file

@ -1,26 +1,24 @@
<script lang="ts">
export default {};
export default {}
</script>
<template>
<article class="prose prose-invert border-2 border-ctp-peach max-w-prose bg-ctp-crust rounded-lg mx-auto p-8 pt-10 text-white">
<h1>Privacy Policy</h1>
<p>For the oficial instance, no logs are kept except for
when an error is met that affects the user is encounered.
An example of this is when data retrieval fails when a user
requests. No identifying information is kept except for the
time of request. below is an example of this data</p>
<code class="">
{
"endpoint":"/api/users/chibidoki",
"level":"warn","message":
"No element found for selector: li.InjectLayout-sc-1i43xsx-0:nth-child(2) > a:nth-child(1) > div:nth-child(1) > div:nth-child(1) > p:nth-child(1)",
"origin":"http://localhost:5173",
"reqId":"fed6f1f6-403f-4d6a-9943-3d07ea7bf9bb",
"timestamp":"2023-03-07T22:42:37.982Z"
}
</code>
</article>
</template>
<article
class="prose prose-invert border-2 border-ctp-peach max-w-prose bg-ctp-crust rounded-lg mx-auto p-8 pt-10 text-white"
>
<h1>Privacy Policy</h1>
<p>
For the oficial instance, no logs are kept except for when an error is met that affects the
user is encounered. An example of this is when data retrieval fails when a user requests. No
identifying information is kept except for the time of request. below is an example of this
data
</p>
<code class="">
{ "endpoint":"/api/users/chibidoki", "level":"warn","message": "No element found for selector:
li.InjectLayout-sc-1i43xsx-0:nth-child(2) > a:nth-child(1) > div:nth-child(1) >
div:nth-child(1) > p:nth-child(1)", "origin":"http://localhost:5173",
"reqId":"fed6f1f6-403f-4d6a-9943-3d07ea7bf9bb", "timestamp":"2023-03-07T22:42:37.982Z" }
</code>
</article>
</template>

View file

@ -1,162 +1,182 @@
<script lang="ts" >
<script lang="ts">
import { ref, onMounted } from 'vue'
import { useRoute } from "vue-router";
import { useRoute } from 'vue-router'
import type { StreamerData } from '../../../server/types/scraping/Streamer'
import VideoPlayer from '../components/VideoPlayer.vue'
import TwitchChat from '../components/TwitchChat.vue'
export default {
async setup() {
const route = useRoute()
const username = route.params.username
async setup() {
const route = useRoute()
const username = route.params.username
const getUser = async () => {
const res = await fetch(`http://localhost:7000/api/users/${username}`)
const getUser = async () => {
const res = await fetch(`http://localhost:7000/api/users/${username}`)
if (res.status !== 200) {
const data = await res.json()
if(!data.code) {
return {
status: "error",
code: "error"
}
}
if (res.status !== 200) {
const data = await res.json()
return {
...data
}
}
const data: StreamerData = await res.json()
data.pfp = `http://localhost:7000/proxy/img?imageUrl=${encodeURIComponent(data.pfp)}`
return data
if (!data.code) {
return {
status: 'error',
code: 'error'
}
}
const data = ref()
onMounted(async () => {
const fetchedUser = await getUser()
data.value = fetchedUser
})
return {
data,
videoOptions: {
autoplay: true,
controls: true,
sources: [
{
src:
`http://localhost:7000/proxy/stream/${username}/hls.m3u8`,
type: 'application/vnd.apple.mpegurl',
}],
fluid: true
}
...data
}
},
components: {
VideoPlayer,
TwitchChat
},
methods: {
truncate(value: string, length: number) {
if (value.length > length) {
return value.substring(0, length) + "...";
} else {
return value;
}
},
},
}
}
const data: StreamerData = await res.json()
data.pfp = `http://localhost:7000/proxy/img?imageUrl=${encodeURIComponent(data.pfp)}`
return data
}
const data = ref()
onMounted(async () => {
const fetchedUser = await getUser()
data.value = fetchedUser
})
return {
data,
videoOptions: {
autoplay: true,
controls: true,
sources: [
{
src: `http://localhost:7000/proxy/stream/${username}/hls.m3u8`,
type: 'application/vnd.apple.mpegurl'
}
],
fluid: true
}
}
},
components: {
VideoPlayer,
TwitchChat
},
methods: {
truncate(value: string, length: number) {
if (value.length > length) {
return value.substring(0, length) + '...'
} else {
return value
}
}
}
}
</script>
<template>
<div v-if="!data" id="loadingDiv" class="flex mx-auto justify-center bg-ctp-crust rounded-lg w-2/3 p-2 text-white">
<div class="flex space-x-3">
<h1 class="text-4xl font-bold"> Searching... </h1>
<v-icon name="fa-circle-notch" class="animate-spin w-10 h-10"></v-icon>
</div>
<div
v-if="!data"
id="loadingDiv"
class="flex mx-auto justify-center bg-ctp-crust rounded-lg w-2/3 p-2 text-white"
>
<div class="flex space-x-3">
<h1 class="text-4xl font-bold">Searching...</h1>
<v-icon name="fa-circle-notch" class="animate-spin w-10 h-10"></v-icon>
</div>
</div>
<div
v-else-if="data.status === 'error'"
class="flex flex-col max-w-prose justify-center text-center mx-auto p-6 bg-ctp-crust rounded-lg text-white"
>
<div class="mb-6">
<h1 class="font-bold text-5xl">oops...</h1>
<p class="font-bold text-3xl">this wasn't supposed to happen</p>
</div>
<div v-else-if="data.status === 'error'" class="flex flex-col max-w-prose justify-center text-center mx-auto p-6 bg-ctp-crust rounded-lg text-white">
<div class="mb-6">
<h1 class="font-bold text-5xl">oops...</h1>
<p class="font-bold text-3xl">this wasn't supposed to happen</p>
<p class="text-xl">
the server was encountered an error while retriving the data, and now we're here :3
</p>
<div class="mt-5">
<p class="text-xl">please contact the administrator with this code</p>
<p class="text-xl">error identifier: {{ data.code }}</p>
</div>
</div>
<div v-else class="w-full inline-flex space-x-4 justify-center p-4">
<div class="flex flex-wrap bg-ctp-crust p-6 rounded-lg max-w-prose min-w-[65ch] text-white">
<div v-if="data.isLive" class="w-full mx-auto rounded-lg mb-5">
<video-player :options="videoOptions"> </video-player>
</div>
<div class="w-full flex-wrap p-3">
<div class="inline-flex w-2/3">
<div class="w-20 h-20 relative">
<img
:src="data.pfp"
class="rounded-full border-4 p-0.5 w-auto h-20"
:style="`border-color: ${data.colorHex};`"
/>
<span
v-if="data.isLive"
class="absolute top-16 right-[1.2rem] bg-ctp-red font-bold text-sm p-1.5 py-0.5 rounded-md"
>LIVE</span
>
</div>
<div class="ml-3 content-between">
<h1 class="text-4xl font-bold">{{ data.username }}</h1>
<h1 v-if="!data.stream" class="font-bold text-md self-end">
{{ data.followersAbbv }} Followers
</h1>
<div v-else class="w-[12rem]">
<p class="text-sm font-bold text-gray-200 self-end">
{{ truncate(data.stream.title, 75) }}
</p>
</div>
</div>
</div>
<p class="text-xl">the server was encountered an error while retriving the data, and now we're here :3</p>
<div class="mt-5">
<p class="text-xl">please contact the administrator with this code</p>
<p class="text-xl">error identifier: {{ data.code }}</p>
<div class="inline-flex w-1/3 float-right h-full text-right">
<div v-if="!data.isLive" class="w-full">
<p
class="font-bold bg-ctp-mantle p-3 py-2 rounded-lg w-min float-right border-2 border-ctp-red"
>
OFFLINE
</p>
</div>
<div v-else class="w-full">
<ul class="text-xs font-bold text-right space-x-1 space-y-1 overflow-y-auto">
<li
v-for="tag in data.stream.tags"
:key="tag"
class="inline-flex bg-ctp-mantle p-1.5 px-2 rounded-md"
>
{{ tag }}
</li>
</ul>
</div>
</div>
</div>
<div class="bg-ctp-mantle m-5 p-5 pt-3 rounded-lg w-full space-y-3">
<div class="inline-flex w-full">
<span class="pr-3 font-bold text-3xl">About</span>
</div>
<p class="mb-5">{{ data.about }}</p>
<hr class="my-auto w-full bg-gray-200 rounded-full opacity-40" />
<ul class="flex font-semibold text-md justify-start flex-wrap flex-row">
<li v-for="link in data.socials" :key="link">
<a :href="link.link" class="text-white hover:text-gray-400 mr-4">
<v-icon :name="`bi-${link.type}`" class="w-6 h-6 mr-1"></v-icon>
<span>{{ link.name }}</span>
</a>
</li>
</ul>
</div>
</div>
<div v-else class="w-full inline-flex space-x-4 justify-center p-4">
<div class="flex flex-wrap bg-ctp-crust p-6 rounded-lg max-w-prose min-w-[65ch] text-white">
<div v-if="data.isLive" class="w-full mx-auto rounded-lg mb-5">
<video-player
:options="videoOptions">
</video-player>
</div>
<div class="w-full flex-wrap p-3">
<div class="inline-flex w-2/3">
<div class="w-20 h-20 relative">
<img :src="data.pfp" class="rounded-full border-4 p-0.5 w-auto h-20" :style="`border-color: ${data.colorHex};`">
<span v-if="data.isLive" class="absolute top-16 right-[1.2rem] bg-ctp-red font-bold text-sm p-1.5 py-0.5 rounded-md">LIVE</span>
</div>
<div class="ml-3 content-between">
<h1 class="text-4xl font-bold">{{ data.username }}</h1>
<h1 v-if="!data.stream" class="font-bold text-md self-end ">{{ data.followersAbbv }} Followers</h1>
<div v-else class="w-[12rem]">
<p class="text-sm font-bold text-gray-200 self-end"> {{ truncate(data.stream.title, 75) }} </p>
</div>
</div>
</div>
<div class="inline-flex w-1/3 float-right h-full text-right">
<div v-if="!data.isLive" class="w-full">
<p class="font-bold bg-ctp-mantle p-3 py-2 rounded-lg w-min float-right border-2 border-ctp-red">OFFLINE</p>
</div>
<div v-else class="w-full">
<ul class="text-xs font-bold text-right space-x-1 space-y-1 overflow-y-auto">
<li v-for="tag in data.stream.tags" class="inline-flex bg-ctp-mantle p-1.5 px-2 rounded-md">
{{ tag }}
</li>
</ul>
</div>
</div>
</div>
<div class="bg-ctp-mantle m-5 p-5 pt-3 rounded-lg w-full space-y-3">
<div class="inline-flex w-full">
<span class="pr-3 font-bold text-3xl">About</span>
</div>
<p class="mb-5">{{ data.about }}</p>
<hr class="my-auto w-full bg-gray-200 rounded-full opacity-40" />
<ul class="flex font-semibold text-md justify-start flex-wrap flex-row">
<li v-for="link in data.socials">
<a :href="link.link" class="text-white hover:text-gray-400 mr-4">
<v-icon :name="`bi-${link.type}`" class="w-6 h-6 mr-1"></v-icon>
<span>{{ link.name }}</span>
</a>
</li>
</ul>
</div>
</div>
<twitch-chat :isLive="data.isLive"></twitch-chat>
</div>
<twitch-chat :isLive="data.isLive" :channelName="data.username"></twitch-chat>
</div>
</template>