Skip to content

Commit

Permalink
Merge branch 'develop-ts' of https://github.com/MrBrax/LiveStreamDVR
Browse files Browse the repository at this point in the history
…into develop-ts
  • Loading branch information
MrBrax committed Nov 18, 2023
2 parents d2e9b1d + 541b698 commit 05db1b9
Show file tree
Hide file tree
Showing 14 changed files with 223 additions and 48 deletions.
2 changes: 2 additions & 0 deletions client-vue/src/assets/_variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ $boxart-height: 190px;
--body-font: Roboto, Helvetica, Arial;
--text-darker: #3d3d3d;

--color-danger: #f14668;

--header-color: #111;
--header-font: "Montserrat", sans-serif;

Expand Down
17 changes: 17 additions & 0 deletions client-vue/src/assets/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -134,13 +134,30 @@ svg[data-icon] {
}
*/

/** @deprecated */
.text-is-error {
color: #f00;
&.flashing {
animation: 1s ease-in-out infinite live;
}
}

.has-text-danger {
color: var(--color-danger);
}

.has-text-warning {
color: #f80;
}

.has-text-success {
color: #1db51d;
}

.has-bg-danger {
background-color: var(--color-danger);
}

.is-warning {
color: #f80;
}
Expand Down
35 changes: 35 additions & 0 deletions client-vue/src/components/reusables/DBoolean.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<template>
<span v-if="value" class="boolean has-text-success">
<span class="icon"><fa :icon="['fas', 'check']" /></span>
<span>{{ t("boolean.yes") }}</span>
</span>
<span v-else class="boolean has-text-danger">
<span class="icon"><fa :icon="['fas', 'times']" /></span>
<span>{{ t("boolean.no") }}</span>
</span>
</template>

<style lang="scss" scoped>
.boolean {
display: inline-flex;
align-items: center;
.icon {
vertical-align: middle;
}
}
</style>

<script lang="ts" setup>
import { defineProps } from "vue";
import { library } from "@fortawesome/fontawesome-svg-core";
import { faCheck, faTimes } from "@fortawesome/free-solid-svg-icons";
import { useI18n } from "vue-i18n";
library.add(faCheck, faTimes);
const { t } = useI18n();
const props = defineProps<{
value: boolean;
}>();
</script>
5 changes: 4 additions & 1 deletion client-vue/src/components/streamer/ClipDownloadModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
{{ formatNumberShort(clip.view_count, 0) }} views
&bull;
{{ formatDistanceToNow(new Date(clip.created_at)) }} ago
<small>({{ format(new Date(clip.created_at), "yyyy-MM-dd HH:mm:ss") }})</small>
<small>({{ format(new Date(clip.created_at), `${store.cfg('locale.date-format')} ${store.cfg('locale.time-format')}`) }})</small>
</p>
<p>
by {{ clip.creator_name }}, playing {{ clip.game_id }}
Expand Down Expand Up @@ -57,6 +57,7 @@ import { useI18n } from "vue-i18n";
import type { ApiResponse } from "@common/Api/Api";
import type { ChannelTypes } from "@/twitchautomator";
import { formatDistanceToNow, format } from "date-fns";
import { useStore } from "@/store";
library.add(faSpinner, faTwitch);
const props = defineProps<{
Expand All @@ -68,6 +69,8 @@ const { t } = useI18n();
const onlineClips = ref<Clip[]>([]);
const loading = ref(false);
const store = useStore();
// clips
async function fetchTwitchClips() {
if (!props.streamer) return;
Expand Down
5 changes: 4 additions & 1 deletion client-vue/src/components/streamer/VideoDownloadModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

{{ formatDistanceToNow(new Date(vod.created_at)) }} ago

<small>({{ format(new Date(vod.created_at), "yyyy-MM-dd HH:mm:ss") }})</small>
<small>({{ format(new Date(vod.created_at), `${store.cfg('locale.date-format')} ${store.cfg('locale.time-format')}`) }})</small>
</p>
<p>{{ vod.description }}</p>
<ul>
Expand Down Expand Up @@ -68,6 +68,7 @@ import { useI18n } from "vue-i18n";
import type { ApiResponse } from "@common/Api/Api";
import type { ChannelTypes } from "@/twitchautomator";
import { formatDistanceToNow, format } from "date-fns";
import { useStore } from "@/store";
library.add(faSpinner);
const props = defineProps<{
Expand All @@ -80,6 +81,8 @@ const onlineVods = ref<ProxyVideo[]>([]);
const loading = ref(false);
const quality = ref<string>("best");
const store = useStore();
// videos
async function fetchTwitchVods() {
if (!props.streamer) return;
Expand Down
5 changes: 4 additions & 1 deletion client-vue/src/components/vod/VodItemChapters.vue
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,10 @@
</tr>
</tbody>
</table>
<div v-else class="text-is-error padding-1">No chapters found</div>
<div v-else class="has-text-danger padding-1">
<span class="icon"><fa icon="exclamation-triangle" /></span>
No chapters found
</div>
</div>
</transition>
</div>
Expand Down
2 changes: 1 addition & 1 deletion client-vue/src/components/vod/VodItemStatus.vue
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
</template>
</template>
<template v-else-if="!vod.is_capturing && !vod.is_converting && !vod.is_finalized">
<em>Waiting to finalize video (since {{ vod.ended_at ? formatDate(vod.ended_at, "yyyy-MM-dd HH:mm:ss") : "(unknown)" }})</em>
<em>Waiting to finalize video (since {{ vod.ended_at ? formatDate(vod.ended_at, `${store.cfg('locale.date-format')} ${store.cfg('locale.time-format')}`) : "(unknown)" }})</em>
</template>
<template v-else>
<em>No video file or error</em>
Expand Down
37 changes: 22 additions & 15 deletions client-vue/src/components/vod/VodItemVideoInfo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,46 +15,46 @@
<li>
<strong>{{ t("vod.video-info.created") }}:</strong>
<template v-if="vod.created_at">
{{ " " + formatDate(vod.created_at, "yyyy-MM-dd HH:mm:ss") }}
{{ " " + formatDate(vod.created_at, `${store.cfg("locale.date-format")} ${store.cfg("locale.time-format")}`) }}
</template>
<span v-else class="text-is-error">No created_at</span>
</li>
<li v-if="showAdvanced">
<strong>{{ t("vod.video-info.went-live") }}:</strong>
<template v-if="vod.started_at">
{{ formatDate(vod.started_at, "yyyy-MM-dd HH:mm:ss") }}
{{ formatDate(vod.started_at, `${store.cfg("locale.date-format")} ${store.cfg("locale.time-format")}`) }}
</template>
<span v-else class="text-is-error">No started_at</span>
</li>
<li v-if="showAdvanced">
<strong>{{ t("vod.video-info.capture-launched") }}:</strong>
<template v-if="vod.capture_started">
{{ formatDate(vod.capture_started, "yyyy-MM-dd HH:mm:ss") }}
{{ formatDate(vod.capture_started, `${store.cfg("locale.date-format")} ${store.cfg("locale.time-format")}`) }}
</template>
<span v-else class="text-is-error">No capture_started</span>
</li>
<li v-if="showAdvanced">
<strong>{{ t("vod.video-info.wrote-file") }}:</strong>
<template v-if="vod.capture_started2">
{{ formatDate(vod.capture_started2, "yyyy-MM-dd HH:mm:ss") }}
{{ formatDate(vod.capture_started2, `${store.cfg("locale.date-format")} ${store.cfg("locale.time-format")}`) }}
</template>
<span v-else class="text-is-error">No capture_started2</span>
</li>
<li>
<strong>{{ t("vod.video-info.stream-end") }}:</strong>
<template v-if="vod.ended_at">
{{ " " + formatDate(vod.ended_at, "yyyy-MM-dd HH:mm:ss") }}
{{ " " + formatDate(vod.ended_at, `${store.cfg("locale.date-format")} ${store.cfg("locale.time-format")}`) }}
</template>
<span v-else class="text-is-error">No ended_at</span>
</li>
<template v-if="vod.capture_started && vod.conversion_started">
<li>
<strong>{{ t("vod.video-info.capture-start") }}:</strong>
{{ formatDate(vod.capture_started, "yyyy-MM-dd HH:mm:ss") }}
{{ formatDate(vod.capture_started, `${store.cfg("locale.date-format")} ${store.cfg("locale.time-format")}`) }}
</li>
<li>
<strong>{{ t("vod.video-info.conversion-start") }}:</strong>
{{ formatDate(vod.conversion_started, "yyyy-MM-dd HH:mm:ss") }}
{{ formatDate(vod.conversion_started, `${store.cfg("locale.date-format")} ${store.cfg("locale.time-format")}`) }}
</li>
</template>
<li v-if="vod.getDuration() && showAdvanced">
Expand All @@ -69,19 +69,23 @@
</li>
<li>
<strong>{{ t("vod.video-info.chat-downloaded") }}:</strong>
{{ vod.is_chat_downloaded ? t("boolean.yes") : t("boolean.no") }}
<!--{{ vod.is_chat_downloaded ? t("boolean.yes") : t("boolean.no") }}-->
<d-boolean :value="vod.is_chat_downloaded" />
</li>
<li>
<strong>{{ t("vod.video-info.chat-dumped") }}:</strong>
{{ vod.is_chatdump_captured ? t("boolean.yes") : t("boolean.no") }}
<!--{{ vod.is_chatdump_captured ? t("boolean.yes") : t("boolean.no") }}-->
<d-boolean :value="vod.is_chatdump_captured" />
</li>
<li>
<strong>{{ t("vod.video-info.chat-rendered") }}:</strong>
{{ vod.is_chat_rendered ? t("boolean.yes") : t("boolean.no") }}
<!--{{ vod.is_chat_rendered ? t("boolean.yes") : t("boolean.no") }}-->
<d-boolean :value="vod.is_chat_rendered" />
</li>
<li>
<strong>{{ t("vod.video-info.chat-burned") }}:</strong>
{{ vod.is_chat_burned ? t("boolean.yes") : t("boolean.no") }}
<!--{{ vod.is_chat_burned ? t("boolean.yes") : t("boolean.no") }}-->
<d-boolean :value="vod.is_chat_burned" />
</li>
</ul>
</article>
Expand Down Expand Up @@ -249,7 +253,8 @@
</template>
<li>
<strong>{{ t("vod.video-info.downloaded") }}:</strong>
{{ vod.is_vod_downloaded ? t("boolean.yes") : t("boolean.no") }}
<!--{{ vod.is_vod_downloaded ? t("boolean.yes") : t("boolean.no") }}-->
<d-boolean :value="vod.is_vod_downloaded" />
</li>
</ul>
</article>
Expand Down Expand Up @@ -366,6 +371,7 @@ function youtubePlaylistLink(playlist_id: string): string {
</script>

<style lang="scss" scoped>
@import "../../assets/_variables";
.info-columns {
margin-top: 1em;
display: flex;
Expand Down Expand Up @@ -411,12 +417,13 @@ function youtubePlaylistLink(playlist_id: string): string {
.duration-difference {
color: #fff;
background-color: #ce1b1b;
text-shadow: 1px 1px 0 #991111;
font-family: 'Roboto Condensed', sans-serif;
background-color: var(--color-danger);
// text-shadow: 1px 1px 2px #4b0909;
padding: 0.2em 0.5em;
border-radius: 0.2em;
line-height: 1.3em;
font-size: 0.8em;
font-size: 0.9em;
max-width: 250px;
}
</style>
2 changes: 2 additions & 0 deletions client-vue/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import i18n from "./plugins/i18n";
import LoadingBox from "@/components/reusables/LoadingBox.vue";
import DButton from "@/components/reusables/DButton.vue";
import DSelect from "@/components/reusables/DSelect.vue";
import DBoolean from "@/components/reusables/DBoolean.vue";

if (import.meta.env.BASE_URL !== undefined) {
axios.defaults.baseURL = import.meta.env.BASE_URL;
Expand All @@ -30,6 +31,7 @@ createApp(App)
.component("LoadingBox", LoadingBox)
.component("DButton", DButton)
.component("DSelect", DSelect)
.component("DBoolean", DBoolean)
// .mixin(titleMixin)
// .mixin(helpers)
.mount("#app");
18 changes: 16 additions & 2 deletions common/ServerConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ export const settingsFields: Record<string, SettingField> = {
help: "Enable this if your server is not exposed to the internet, aka no EventSub support.",
},

date_format: {
group: "Basic",
"locale.date-format": {
group: "Locale",
text: "Date format",
type: "object",
default: "yyyy-MM-dd",
Expand All @@ -124,6 +124,20 @@ export const settingsFields: Record<string, SettingField> = {
"dd-MM yyyy": "31-12 2021",
"MM-dd yyyy": "12-31 2021",
},
migrate: "date_format",
},

"locale.time-format": {
group: "Locale",
text: "Time format",
type: "object",
default: "HH:mm:ss",
choices: {
"HH:mm:ss": "23:59:59 (default)",
"HH:mm": "23:59",
"hh:mm:ss a": "11:59:59 PM",
"hh:mm a": "11:59 PM",
},
},

motd: {
Expand Down
18 changes: 16 additions & 2 deletions server/src/Core/Config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { debugLog } from "@/Helpers/Console";
import { GetRunningProcesses, execSimple } from "@/Helpers/Execute";
import { is_docker } from "@/Helpers/System";
import { isNumber } from "@/Helpers/Types";
import type { SettingField } from "@common/Config";
import { settingsFields } from "@common/ServerConfig";
import type { AxiosResponse } from "axios";
Expand Down Expand Up @@ -331,15 +332,28 @@ export class Config {
setting.stripslash &&
typeof newValue === "string"
) {
newValue = newValue.replace(/\/$/, "");
newValue = newValue.replace(/\/$/, "").replace(/\\$/, "");
}

if (setting.type === "number" && typeof newValue === "string") {
if (!isNumber(newValue)) {
throw new Error(
`Invalid value for setting '${key}': ${newValue}`
);
}
newValue = parseInt(newValue);
}

if (setting.type === "boolean" && typeof newValue === "string") {
newValue = newValue === "true" || newValue === "1";
if (newValue === "true" || newValue === "1") {
newValue = true;
} else if (newValue === "false" || newValue === "0") {
newValue = false;
} else {
throw new Error(
`Invalid value for setting '${key}': ${newValue}`
);
}
}

if (setting.type == "array") {
Expand Down
4 changes: 4 additions & 0 deletions server/src/Helpers/Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,7 @@ export function isKickChannel(
export function isError(compareData: unknown): compareData is Error {
return compareData instanceof Error;
}

export function isNumber(compareData: string): boolean {
return !isNaN(Number(compareData));
}
7 changes: 0 additions & 7 deletions server/src/Providers/Twitch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,6 @@ export class TwitchHelper {
"oauth_user_refresh.json"
);

/** @deprecated */
static readonly accessTokenExpire = 60 * 60 * 24 * 60 * 1000; // 60 days
/** @deprecated */
static readonly accessTokenRefresh = 60 * 60 * 24 * 30 * 1000; // 30 days

/** @deprecated */
static readonly PHP_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss.SSSSSS";
static readonly TWITCH_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
static readonly TWITCH_DATE_FORMAT_MS = "yyyy-MM-dd'T'HH:mm:ss'.'SSS'Z'";

Expand Down
Loading

0 comments on commit 05db1b9

Please sign in to comment.