@xbibzlibrary/tiktokscrap
Version:
Powerful TikTok Scraper and Downloader Library
146 lines (114 loc) • 5.67 kB
text/typescript
import { ValidationError } from '../errors';
import { TikTokSearchOptions, TikTokUserFeedOptions, TikTokHashtagFeedOptions, TikTokDownloadOptions } from '../types';
import Logger from './logger';
export class Validator {
private logger = Logger;
public validateUrl(url: string): boolean {
try {
const urlObj = new URL(url);
return urlObj.protocol === 'http:' || urlObj.protocol === 'https:';
} catch (error) {
return false;
}
}
public validateTikTokUrl(url: string): boolean {
if (!this.validateUrl(url)) {
return false;
}
const tiktokRegex = /^https?:\/\/(www\.)?tiktok\.com\/(@[\w.-]+)\/(video|photo)\/([\d]+)(\?.*)?$/;
return tiktokRegex.test(url);
}
public validateTikTokUsername(username: string): boolean {
const usernameRegex = /^@[\w.-]+$/;
return usernameRegex.test(username);
}
public validateTikTokHashtag(hashtag: string): boolean {
const hashtagRegex = /^#?[\w]+$/;
return hashtagRegex.test(hashtag);
}
public validateSearchOptions(options: TikTokSearchOptions): void {
if (!options || typeof options !== 'object') {
throw new ValidationError('Search options must be an object');
}
if (!options.keyword || typeof options.keyword !== 'string' || options.keyword.trim() === '') {
throw new ValidationError('Keyword is required and must be a non-empty string');
}
if (options.cursor !== undefined && (typeof options.cursor !== 'number' || options.cursor < 0)) {
throw new ValidationError('Cursor must be a non-negative number');
}
if (options.count !== undefined && (typeof options.count !== 'number' || options.count <= 0 || options.count > 100)) {
throw new ValidationError('Count must be a positive number not exceeding 100');
}
if (options.sortType !== undefined && ![0, 1, 2].includes(options.sortType)) {
throw new ValidationError('Sort type must be 0 (Relevant), 1 (Latest), or 2 (Most liked)');
}
if (options.publishTime !== undefined && ![0, 1, 2, 3].includes(options.publishTime)) {
throw new ValidationError('Publish time must be 0 (All time), 1 (Within 1 day), 2 (Within 7 days), or 3 (Within 30 days)');
}
if (options.duration !== undefined && ![0, 1, 2].includes(options.duration)) {
throw new ValidationError('Duration must be 0 (All), 1 (Under 15s), or 2 (Over 15s)');
}
}
public validateUserFeedOptions(options: TikTokUserFeedOptions): void {
if (!options || typeof options !== 'object') {
throw new ValidationError('User feed options must be an object');
}
if (!options.username || typeof options.username !== 'string' || options.username.trim() === '') {
throw new ValidationError('Username is required and must be a non-empty string');
}
if (!this.validateTikTokUsername(options.username)) {
throw new ValidationError('Invalid TikTok username format');
}
if (options.cursor !== undefined && (typeof options.cursor !== 'number' || options.cursor < 0)) {
throw new ValidationError('Cursor must be a non-negative number');
}
if (options.count !== undefined && (typeof options.count !== 'number' || options.count <= 0 || options.count > 100)) {
throw new ValidationError('Count must be a positive number not exceeding 100');
}
if (options.type !== undefined && !['post', 'like'].includes(options.type)) {
throw new ValidationError('Type must be either "post" or "like"');
}
}
public validateHashtagFeedOptions(options: TikTokHashtagFeedOptions): void {
if (!options || typeof options !== 'object') {
throw new ValidationError('Hashtag feed options must be an object');
}
if (!options.hashtag || typeof options.hashtag !== 'string' || options.hashtag.trim() === '') {
throw new ValidationError('Hashtag is required and must be a non-empty string');
}
if (!this.validateTikTokHashtag(options.hashtag)) {
throw new ValidationError('Invalid TikTok hashtag format');
}
if (options.cursor !== undefined && (typeof options.cursor !== 'number' || options.cursor < 0)) {
throw new ValidationError('Cursor must be a non-negative number');
}
if (options.count !== undefined && (typeof options.count !== 'number' || options.count <= 0 || options.count > 100)) {
throw new ValidationError('Count must be a positive number not exceeding 100');
}
}
public validateDownloadOptions(options: TikTokDownloadOptions): void {
if (!options || typeof options !== 'object') {
throw new ValidationError('Download options must be an object');
}
if (options.outputDir !== undefined && (typeof options.outputDir !== 'string' || options.outputDir.trim() === '')) {
throw new ValidationError('Output directory must be a non-empty string');
}
if (options.filename !== undefined && (typeof options.filename !== 'string' || options.filename.trim() === '')) {
throw new ValidationError('Filename must be a non-empty string');
}
if (options.progressCallback !== undefined && typeof options.progressCallback !== 'function') {
throw new ValidationError('Progress callback must be a function');
}
}
public validateId(id: string): void {
if (!id || typeof id !== 'string' || id.trim() === '') {
throw new ValidationError('ID is required and must be a non-empty string');
}
}
public validateSecUid(secUid: string): void {
if (!secUid || typeof secUid !== 'string' || secUid.trim() === '') {
throw new ValidationError('SecUid is required and must be a non-empty string');
}
}
}
export default Validator;