mirror of
https://github.com/ajayyy/SponsorBlock.git
synced 2025-12-12 06:27:14 +03:00
Add functions for importing/exporting segments
This commit is contained in:
@@ -44,4 +44,8 @@ export function getCategorySuffix(category: Category): string {
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
export function shortCategoryName(categoryName: string): string {
|
||||
return chrome.i18n.getMessage("category_" + categoryName + "_short") || chrome.i18n.getMessage("category_" + categoryName);
|
||||
}
|
||||
65
src/utils/exporter.ts
Normal file
65
src/utils/exporter.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { ActionType, Category, SegmentUUID, SponsorSourceType, SponsorTime } from "../types";
|
||||
import { shortCategoryName } from "./categoryUtils";
|
||||
import { GenericUtils } from "./genericUtils";
|
||||
|
||||
export function exportTimes(segments: SponsorTime[]): string {
|
||||
let result = "";
|
||||
for (const segment of segments) {
|
||||
if (![ActionType.Full, ActionType.Mute].includes(segment.actionType)
|
||||
&& segment.source !== SponsorSourceType.YouTube) {
|
||||
result += exportTime(segment) + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function exportTime(segment: SponsorTime): string {
|
||||
const name = segment.description || shortCategoryName(segment.category);
|
||||
|
||||
return `${GenericUtils.getFormattedTime(segment.segment[0])}${
|
||||
segment.segment[1] && segment.segment[0] !== segment.segment[1]
|
||||
? ` - ${GenericUtils.getFormattedTime(segment.segment[1])}` : ""} ${name}`;
|
||||
}
|
||||
|
||||
export function importTimes(data: string, videoDuration: number): SponsorTime[] {
|
||||
const lines = data.split("\n");
|
||||
const result: SponsorTime[] = [];
|
||||
for (const line of lines) {
|
||||
const match = line.match(/(?:(\d+:\d+)+(?:\.\d+)?)|(?:\d+(?=s| second))/g);
|
||||
if (match) {
|
||||
const startTime = GenericUtils.getFormattedTimeToSeconds(match[0]);
|
||||
if (startTime) {
|
||||
const specialCharsMatcher = /^(?:\s+seconds?)?[:()-\s]*|(?:\s+at)?[:()-\s]+$/g
|
||||
const titleLeft = line.split(match[0])[0].replace(specialCharsMatcher, "");
|
||||
let titleRight = null;
|
||||
const split2 = line.split(match[1] || match[0]);
|
||||
titleRight = split2[split2.length - 1].replace(specialCharsMatcher, "");
|
||||
|
||||
const title = titleLeft?.length > titleRight?.length ? titleLeft : titleRight;
|
||||
if (title) {
|
||||
const segment: SponsorTime = {
|
||||
segment: [startTime, GenericUtils.getFormattedTimeToSeconds(match[1])],
|
||||
category: "chapter" as Category,
|
||||
actionType: ActionType.Chapter,
|
||||
description: title,
|
||||
source: SponsorSourceType.Local,
|
||||
UUID: GenericUtils.generateUserID() as SegmentUUID
|
||||
};
|
||||
|
||||
if (result.length > 0 && result[result.length - 1].segment[1] === null) {
|
||||
result[result.length - 1].segment[1] = segment.segment[0];
|
||||
}
|
||||
|
||||
result.push(segment);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result.length > 0 && result[result.length - 1].segment[1] === null) {
|
||||
result[result.length - 1].segment[1] = videoDuration;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -35,6 +35,36 @@ function getFormattedTimeToSeconds(formatted: string): number | null {
|
||||
return hours * 3600 + minutes * 60 + seconds;
|
||||
}
|
||||
|
||||
function getFormattedTime(seconds: number, precise?: boolean): string {
|
||||
seconds = Math.max(seconds, 0);
|
||||
|
||||
const hours = Math.floor(seconds / 60 / 60);
|
||||
const minutes = Math.floor(seconds / 60) % 60;
|
||||
let minutesDisplay = String(minutes);
|
||||
let secondsNum = seconds % 60;
|
||||
if (!precise) {
|
||||
secondsNum = Math.floor(secondsNum);
|
||||
}
|
||||
|
||||
let secondsDisplay = String(precise ? secondsNum.toFixed(3) : secondsNum);
|
||||
|
||||
if (secondsNum < 10) {
|
||||
//add a zero
|
||||
secondsDisplay = "0" + secondsDisplay;
|
||||
}
|
||||
if (hours && minutes < 10) {
|
||||
//add a zero
|
||||
minutesDisplay = "0" + minutesDisplay;
|
||||
}
|
||||
if (isNaN(hours) || isNaN(minutes)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const formatted = (hours ? hours + ":" : "") + minutesDisplay + ":" + secondsDisplay;
|
||||
|
||||
return formatted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the error message in a nice string
|
||||
*
|
||||
@@ -80,9 +110,29 @@ function hexToRgb(hex: string): {r: number, g: number, b: number} {
|
||||
} : null;
|
||||
}
|
||||
|
||||
function generateUserID(length = 36): string {
|
||||
const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
let result = "";
|
||||
if (window.crypto && window.crypto.getRandomValues) {
|
||||
const values = new Uint32Array(length);
|
||||
window.crypto.getRandomValues(values);
|
||||
for (let i = 0; i < length; i++) {
|
||||
result += charset[values[i] % charset.length];
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
for (let i = 0; i < length; i++) {
|
||||
result += charset[Math.floor(Math.random() * charset.length)];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export const GenericUtils = {
|
||||
wait,
|
||||
getFormattedTime,
|
||||
getFormattedTimeToSeconds,
|
||||
getErrorMessage,
|
||||
getLuminance
|
||||
getLuminance,
|
||||
generateUserID
|
||||
}
|
||||
Reference in New Issue
Block a user