import moment from 'moment-timezone';
import { ObjectId } from 'mongodb';
import { Mongo } from 'meteor/mongo';

import { Migrations } from '../../../app/migrations/server';
import { Permissions, Settings } from '../../../app/models/server';
import { LivechatBusinessHours } from '../../../app/models/server/raw';
import { LivechatBusinessHourTypes } from '../../../definition/ILivechatBusinessHour';

const migrateCollection = () => {
	const LivechatOfficeHour = new Mongo.Collection('rocketchat_livechat_office_hour');
	const days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
	const officeHours = [];
	days.forEach((day) => {
		const officeHour = LivechatOfficeHour.findOne({ day });
		if (officeHour) {
			officeHours.push(officeHour);
		}
	});

	if (!officeHours || officeHours.length === 0) {
		return;
	}

	const businessHour = {
		name: '',
		active: true,
		type: LivechatBusinessHourTypes.DEFAULT,
		ts: new Date(),
		workHours: officeHours.map((officeHour) => ({
			day: officeHour.day,
			start: {
				time: officeHour.start,
				utc: {
					dayOfWeek: moment(`${ officeHour.day }:${ officeHour.start }`, 'dddd:HH:mm').utc().format('dddd'),
					time: moment(`${ officeHour.day }:${ officeHour.start }`, 'dddd:HH:mm').utc().format('HH:mm'),
				},
				cron: {
					dayOfWeek: moment(`${ officeHour.day }:${ officeHour.start }`, 'dddd:HH:mm').format('dddd'),
					time: moment(`${ officeHour.day }:${ officeHour.start }`, 'dddd:HH:mm').format('HH:mm'),
				},
			},
			finish: {
				time: officeHour.finish,
				utc: {
					dayOfWeek: moment(`${ officeHour.day }:${ officeHour.finish }`, 'dddd:HH:mm').utc().format('dddd'),
					time: moment(`${ officeHour.day }:${ officeHour.finish }`, 'dddd:HH:mm').utc().format('HH:mm'),
				},
				cron: {
					dayOfWeek: moment(`${ officeHour.day }:${ officeHour.finish }`, 'dddd:HH:mm').format('dddd'),
					time: moment(`${ officeHour.day }:${ officeHour.finish }`, 'dddd:HH:mm').format('HH:mm'),
				},
			},
			code: officeHour.code,
			open: officeHour.open,
		})),
		timezone: {
			name: moment.tz.guess(),
			utc: moment().utcOffset() / 60,
		},
	};
	if (LivechatBusinessHours.find({ type: LivechatBusinessHourTypes.DEFAULT }).count() === 0) {
		businessHour._id = new ObjectId().toHexString();
		LivechatBusinessHours.insertOne(businessHour);
	} else {
		LivechatBusinessHours.update({ type: LivechatBusinessHourTypes.DEFAULT }, { $set: { ...businessHour } });
	}
	try {
		Promise.await(LivechatOfficeHour.rawCollection().drop());
	} catch (err) {
		// Ignore if the collection does not exist
		if (!err.code || err.code !== 26) {
			throw err;
		}
	}
};

Migrations.add({
	version: 195,
	up() {
		Settings.remove({ _id: 'Livechat_enable_office_hours' });
		Settings.remove({ _id: 'Livechat_allow_online_agents_outside_office_hours' });
		const permission = Permissions.findOneById('view-livechat-officeHours');
		if (permission) {
			Permissions.upsert({ _id: 'view-livechat-business-hours' }, { $set: { roles: permission.roles } });
			Permissions.remove({ _id: 'view-livechat-officeHours' });
		}
		Promise.await(migrateCollection());
	},
});


const unitsRoute = useRoute('omnichannel-units');

const [monitorsFilter, setMonitorsFilter] = useState('');

const [departmentsFilter, setDepartmentsFilter] = useState('');

const { itemsList: monitorsList, loadMoreItems: loadMoreMonitors } = useMonitorsList(

useMemo(() => ({ limit: 50, filter: monitorsFilter }), [monitorsFilter]),

const { phase: monitorsPhase, items: monitorsItems, itemCount: monitorsTotal } = useRecordList(

keep keep keep keep keep replace keep keep keep keep

useMemo(() => ({ filter: monitorsFilter }), [monitorsFilter]),

import { Meteor } from 'meteor/meteor';
import { Tracker } from 'meteor/tracker';

import { callbacks } from '../../../app/callbacks/client';
import { settings } from '../../../app/settings/client';

Meteor.startup(() => {
	Tracker.autorun(() => {
		const options = {
			parser: settings.get('Markdown_Parser'),
			supportSchemesForLink: settings.get('Markdown_SupportSchemesForLink'),
			headers: settings.get('Markdown_Headers'),
			rootUrl: Meteor.absoluteUrl(),
			marked: {
				gfm: settings.get('Markdown_Marked_GFM'),
				tables: settings.get('Markdown_Marked_Tables'),
				breaks: settings.get('Markdown_Marked_Breaks'),
				pedantic: settings.get('Markdown_Marked_Pedantic'),
				smartLists: settings.get('Markdown_Marked_SmartLists'),
				smartypants: settings.get('Markdown_Marked_Smartypants'),
			},
		};

		import('../../../app/markdown/client').then(({ createMarkdownMessageRenderer }) => {
			const renderMessage = createMarkdownMessageRenderer(options);
			callbacks.remove('renderMessage', 'markdown');
			callbacks.add('renderMessage', renderMessage, callbacks.priority.HIGH, 'markdown');
		});
	});
});


const { itemsList: departmentsList, loadMoreItems: loadMoreDepartments } = useDepartmentsList(

useMemo(() => ({ limit: 50, filter: departmentsFilter }), [departmentsFilter]),

keep keep keep keep keep replace keep keep keep keep keep

useMemo(() => ({ filter: departmentsFilter, unitId }), [departmentsFilter, unitId]),

import { escapeRegExp } from '@rocket.chat/string-helpers';

import {
	LivechatDepartment,
} from '../../../../../app/models/server/raw';

export const findAllDepartmentsAvailable = async (unitId, offset, count, text) => {
	const filterReg = new RegExp(escapeRegExp(text), 'i');

	const cursor = LivechatDepartment.find({
		$or: [{ ancestors: { $in: [unitId] } }, { ancestors: { $exists: false } }],
		...text && { name: filterReg },

	}, { limit: count, offset });

	const departments = await cursor.toArray();
	const total = await cursor.count();
	const departmentsFiltered = departments.filter((department) => !department.ancestors?.length);

	return { departments: departmentsFiltered, total };
};

export const findAllDepartmentsByUnit = async (unitId, offset, count) => {
	const cursor = LivechatDepartment.find({
		ancestors: { $in: [unitId] },
	}, { limit: count, offset });

	const total = await cursor.count();
	const departments = await cursor.toArray();

	return { departments, total };
};


import React from 'react';

import NotFoundPage from './NotFoundPage';

export default {
	title: 'views/notFound/NotFoundPage',
	component: NotFoundPage,
};

export const Default = () => <NotFoundPage />;


import { Box, Button, ButtonGroup, Margins, TextInput, Field, Icon } from '@rocket.chat/fuselage';
import React, { useCallback, useState, useMemo, useEffect } from 'react';

import DeleteSuccessModal from '../../../components/DeleteSuccessModal';
import DeleteWarningModal from '../../../components/DeleteWarningModal';
import VerticalBar from '../../../components/VerticalBar';
import { useSetModal } from '../../../contexts/ModalContext';
import { useMethod } from '../../../contexts/ServerContext';
import { useToastMessageDispatch } from '../../../contexts/ToastMessagesContext';
import { useTranslation } from '../../../contexts/TranslationContext';
import { useFileInput } from '../../../hooks/useFileInput';
import { validate, createSoundData } from './lib';

function EditSound({ close, onChange, data, ...props }) {
	const t = useTranslation();
	const dispatchToastMessage = useToastMessageDispatch();
	const setModal = useSetModal();

	const { _id, name: previousName } = data || {};
	const previousSound = useMemo(() => data || {}, [data]);

	const [name, setName] = useState(() => data?.name ?? '');
	const [sound, setSound] = useState(() => data ?? {});

	useEffect(() => {
		setName(previousName || '');
		setSound(previousSound || '');
	}, [previousName, previousSound, _id]);

	const deleteCustomSound = useMethod('deleteCustomSound');
	const uploadCustomSound = useMethod('uploadCustomSound');
	const insertOrUpdateSound = useMethod('insertOrUpdateSound');

	const handleChangeFile = useCallback((soundFile) => {
		setSound(soundFile);
	}, []);

	const hasUnsavedChanges = useMemo(() => previousName !== name || previousSound !== sound, [
		name,
		previousName,
		previousSound,
		sound,
	]);

	const saveAction = useCallback(
		async (sound) => {
			const soundData = createSoundData(sound, name, { previousName, previousSound, _id });
			const validation = validate(soundData, sound);
			if (validation.length === 0) {
				let soundId;
				try {
					soundId = await insertOrUpdateSound(soundData);
				} catch (error) {
					dispatchToastMessage({ type: 'error', message: error });
				}

				soundData._id = soundId;
				soundData.random = Math.round(Math.random() * 1000);

				if (sound && sound !== previousSound) {
					dispatchToastMessage({ type: 'success', message: t('Uploading_file') });

					const reader = new FileReader();
					reader.readAsBinaryString(sound);
					reader.onloadend = () => {
						try {
							uploadCustomSound(reader.result, sound.type, soundData);
							return dispatchToastMessage({ type: 'success', message: t('File_uploaded') });
						} catch (error) {
							dispatchToastMessage({ type: 'error', message: error });
						}
					};
				}
			}

			validation.forEach((error) =>
				dispatchToastMessage({
					type: 'error',
					message: t('error-the-field-is-required', { field: t(error) }),
				}),
			);
		},
		[
			_id,
			dispatchToastMessage,
			insertOrUpdateSound,
			name,
			previousName,
			previousSound,
			t,
			uploadCustomSound,
		],
	);

	const handleSave = useCallback(async () => {
		saveAction(sound);
		onChange();
	}, [saveAction, sound, onChange]);

	const handleDeleteButtonClick = useCallback(() => {
		const handleClose = () => {
			setModal(null);
			close();
			onChange();
		};

		const handleDelete = async () => {
			try {
				await deleteCustomSound(_id);
				setModal(() => (
					<DeleteSuccessModal children={t('Custom_Sound_Has_Been_Deleted')} onClose={handleClose} />
				));
			} catch (error) {
				dispatchToastMessage({ type: 'error', message: error });
				onChange();
			}
		};

		const handleCancel = () => {
			setModal(null);
		};

		setModal(() => (
			<DeleteWarningModal
				children={t('Custom_Sound_Delete_Warning')}
				onDelete={handleDelete}
				onCancel={handleCancel}
			/>
		));
	}, [_id, close, deleteCustomSound, dispatchToastMessage, onChange, setModal, t]);

	const [clickUpload] = useFileInput(handleChangeFile, 'audio/mp3');

	return (
		<VerticalBar.ScrollableContent {...props}>
			<Field>
				<Field.Label>{t('Name')}</Field.Label>
				<Field.Row>
					<TextInput
						value={name}
						onChange={(e) => setName(e.currentTarget.value)}
						placeholder={t('Name')}
					/>
				</Field.Row>
			</Field>

			<Field>
				<Field.Label alignSelf='stretch'>{t('Sound_File_mp3')}</Field.Label>
				<Box display='flex' flexDirection='row' mbs='none'>
					<Margins inline='x4'>
						<Button square onClick={clickUpload}>
							<Icon name='upload' size='x20' />
						</Button>
						{(sound && sound.name) || 'none'}
					</Margins>
				</Box>
			</Field>

			<Field>
				<Field.Row>
					<ButtonGroup stretch w='full'>
						<Button onClick={close}>{t('Cancel')}</Button>
						<Button primary onClick={handleSave} disabled={!hasUnsavedChanges}>
							{t('Save')}
						</Button>
					</ButtonGroup>
				</Field.Row>
			</Field>
			<Field>
				<Field.Row>
					<ButtonGroup stretch w='full'>
						<Button primary danger onClick={handleDeleteButtonClick}>
							<Icon name='trash' mie='x4' />
							{t('Delete')}
						</Button>
					</ButtonGroup>
				</Field.Row>
			</Field>
		</VerticalBar.ScrollableContent>
	);
}

export default EditSound;


keep keep keep keep replace keep keep keep keep

import {
	INodeProperties,
} from 'n8n-workflow';

export const videoOperations = [
	{
		displayName: 'Operation',
		name: 'operation',
		type: 'options',
		displayOptions: {
			show: {
				resource: [
					'video',
				],
			},
		},
		options: [
			{
				name: 'Delete',
				value: 'delete',
				description: 'Delete a video',
			},
			{
				name: 'Get',
				value: 'get',
				description: 'Get a video',
			},
			{
				name: 'Get All',
				value: 'getAll',
				description: 'Retrieve all videos',
			},
			{
				name: 'Rate',
				value: 'rate',
				description: 'Rate a video',
			},
			{
				name: 'Update',
				value: 'update',
				description: 'Update a video',
			},
			{
				name: 'Upload',
				value: 'upload',
				description: 'Upload a video',
			},
		],
		default: 'getAll',
		description: 'The operation to perform.',
	},
] as INodeProperties[];

export const videoFields = [
	/* -------------------------------------------------------------------------- */
	/*                                 video:upload                               */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Title',
		name: 'title',
		type: 'string',
		required: true,
		displayOptions: {
			show: {
				operation: [
					'upload',
				],
				resource: [
					'video',
				],
			},
		},
		default: '',
	},
	{
		displayName: 'Region Code',
		name: 'regionCode',
		type: 'options',
		typeOptions: {
			loadOptionsMethod: 'getCountriesCodes',
		},
		displayOptions: {
			show: {
				operation: [
					'upload',
				],
				resource: [
					'video',
				],
			},
		},
		default: '',
	},
	{
		displayName: 'Category ID',
		name: 'categoryId',
		type: 'options',
		typeOptions: {
			loadOptionsMethod: 'getVideoCategories',
			loadOptionsDependsOn: [
				'regionCode',
			],
		},
		displayOptions: {
			show: {
				operation: [
					'upload',
				],
				resource: [
					'video',
				],
			},
		},
		default: '',
	},
	{
		displayName: 'Binary Property',
		name: 'binaryProperty',
		type: 'string',
		required: true,
		displayOptions: {
			show: {
				operation: [
					'upload',
				],
				resource: [
					'video',
				],
			},
		},
		default: 'data',
	},
	{
		displayName: 'Options',
		name: 'options',
		type: 'collection',
		placeholder: 'Add Option',
		default: {},
		displayOptions: {
			show: {
				operation: [
					'upload',
				],
				resource: [
					'video',
				],
			},
		},
		options: [
			{
				displayName: 'Default Language',
				name: 'defaultLanguage',
				type: 'options',
				typeOptions: {
					loadOptionsMethod: 'getLanguages',
				},
				default: '',
				description: `The language of the text in the playlist resource's title and description properties.`,
			},
			{
				displayName: 'Description',
				name: 'description',
				type: 'string',
				default: '',
				description: `The playlist's description.`,
			},
			{
				displayName: 'Embeddable',
				name: 'embeddable',
				type: 'boolean',
				default: false,
				description: `This value indicates whether the video can be embedded on another website.`,
			},
			{
				displayName: 'License',
				name: 'license',
				type: 'options',
				options: [
					{
						name: 'Creative Common',
						value: 'creativeCommon',
					},
					{
						name: 'Youtube',
						value: 'youtube',
					},
				],
				default: '',
				description: `The video's license.`,
			},
			{
				displayName: 'Notify Subscribers',
				name: 'notifySubscribers',
				type: 'boolean',
				default: false,
				description: `The notifySubscribers parameter indicates whether YouTube should send a notification about the new video to users who subscribe to the video's channel`,
			},
			{
				displayName: 'Privacy Status',
				name: 'privacyStatus',
				type: 'options',
				options: [
					{
						name: 'Private',
						value: 'private',
					},
					{
						name: 'Public',
						value: 'public',
					},
					{
						name: 'Unlisted',
						value: 'unlistef',
					},
				],
				default: '',
				description: `The playlist's privacy status.`,
			},
			{
				displayName: 'Public Stats Viewable',
				name: 'publicStatsViewable',
				type: 'boolean',
				default: true,
				description: `This value indicates whether the extended video statistics on the video's watch page are publicly viewable.`,
			},
			{
				displayName: 'Publish At',
				name: 'publishAt',
				type: 'dateTime',
				default: '',
				description: `If you set a value for this property, you must also set the status.privacyStatus property to private.`,
			},
			{
				displayName: 'Recording Date',
				name: 'recordingDate',
				type: 'dateTime',
				default: '',
				description: `The date and time when the video was recorded`,
			},
			{
				displayName: 'Self Declared Made For Kids',
				name: 'selfDeclaredMadeForKids',
				type: 'boolean',
				default: false,
				description: `This value indicates whether the video is designated as child-directed, and it contains the current "made for kids" status of the video`,
			},
			{
				displayName: 'Tags',
				name: 'tags',
				type: 'string',
				default: '',
				description: `Keyword tags associated with the playlist. Mulplie can be defined separated by comma`,
			},
		],
	},
	/* -------------------------------------------------------------------------- */
	/*                                 video:delete                               */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Video ID',
		name: 'videoId',
		type: 'string',
		required: true,
		displayOptions: {
			show: {
				operation: [
					'delete',
				],
				resource: [
					'video',
				],
			},
		},
		description: 'ID of the video',
		default: '',
	},
	{
		displayName: 'Options',
		name: 'options',
		type: 'collection',
		placeholder: 'Add Option',
		default: {},
		displayOptions: {
			show: {
				operation: [
					'delete',
				],
				resource: [
					'video',
				],
			},
		},
		options: [
			{
				displayName: 'On Behalf Of Content Owner',
				name: 'onBehalfOfContentOwner',
				type: 'string',
				default: '',
				description: `The onBehalfOfContentOwner parameter indicates that the request's authorization credentials identify

				a YouTube CMS user who is acting on behalf of the content owner specified in the parameter value`,
			},
		],
	},
	/* -------------------------------------------------------------------------- */
	/*                                 video:get                                  */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Video ID',
		name: 'videoId',
		type: 'string',
		required: true,
		displayOptions: {
			show: {
				operation: [
					'get',
				],
				resource: [
					'video',
				],
			},
		},
		default: '',
	},
	{
		displayName: 'Fields',
		name: 'part',
		type: 'multiOptions',
		options: [
			{
				name: '*',
				value: '*',
			},
			{
				name: 'Content Details',
				value: 'contentDetails',
			},
			{
				name: 'ID',
				value: 'id',
			},
			{
				name: 'Live Streaming Details',
				value: 'liveStreamingDetails',
			},
			{
				name: 'Localizations',
				value: 'localizations',
			},
			{
				name: 'Player',
				value: 'player',
			},
			{
				name: 'Recording Details',
				value: 'recordingDetails',
			},
			{
				name: 'Snippet',
				value: 'snippet',
			},
			{
				name: 'Statistics',
				value: 'statistics',
			},
			{
				name: 'Status',
				value: 'status',
			},
			{
				name: 'Topic Details',
				value: 'topicDetails',
			},
		],
		required: true,
		displayOptions: {
			show: {
				operation: [
					'get',
				],
				resource: [
					'video',
				],
			},
		},
		description: 'The fields parameter specifies a comma-separated list of one or more video resource properties that the API response will include.',
		default: ['*'],
	},
	{
		displayName: 'Options',
		name: 'options',
		type: 'collection',
		placeholder: 'Add Option',
		default: {},
		displayOptions: {
			show: {
				operation: [
					'get',
				],
				resource: [
					'video',
				],
			},
		},
		options: [
			{
				displayName: 'On Behalf Of Content Owner',
				name: 'onBehalfOfContentOwner',
				type: 'string',
				default: '',
				description: `The onBehalfOfContentOwner parameter indicates that the request's authorization credentials identify

				a YouTube CMS user who is acting on behalf of the content owner specified in the parameter value`,
			},
		],
	},
	/* -------------------------------------------------------------------------- */
	/*                                 video:getAll                               */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Return All',
		name: 'returnAll',
		type: 'boolean',
		displayOptions: {
			show: {
				operation: [
					'getAll',
				],
				resource: [
					'video',
				],
			},
		},
		default: false,
		description: 'If all results should be returned or only up to a given limit.',
	},
	{
		displayName: 'Limit',
		name: 'limit',
		type: 'number',
		displayOptions: {
			show: {
				operation: [
					'getAll',
				],
				resource: [
					'video',
				],
				returnAll: [
					false,
				],
			},
		},
		typeOptions: {
			minValue: 1,
			maxValue: 50,
		},
		default: 25,
		description: 'How many results to return.',
	},
	{
		displayName: 'Filters',
		name: 'filters',
		type: 'collection',
		placeholder: 'Add Option',
		default: {},
		displayOptions: {
			show: {
				operation: [
					'getAll',
				],
				resource: [
					'video',
				],
			},
		},
		options: [
			{
				displayName: 'Channel ID',
				name: 'channelId',
				type: 'string',
				default: '',
				description: `The channelId parameter indicates that the API response should only contain resources created by the channel.`,
			},
			{
				displayName: 'For Developer',
				name: 'forDeveloper',
				type: 'boolean',
				default: false,
				description: `The forDeveloper parameter restricts the search to only retrieve videos uploaded via the developer's application or website`,
			},
			{
				displayName: 'Published After',
				name: 'publishedAfter',
				type: 'dateTime',
				default: '',
				description: `The publishedAfter parameter indicates that the API response should only contain resources created at or after the specified time.`,
			},
			{
				displayName: 'Published Before',
				name: 'publishedBefore',
				type: 'dateTime',
				default: '',
				description: `The publishedBefore parameter indicates that the API response should only contain resources created before or at the specified time.`,
			},
			{
				displayName: 'Query',
				name: 'q',
				type: 'string',
				default: '',
				description: `The q parameter specifies the query term to search for.`,
			},
			{
				displayName: 'Region Code',
				name: 'regionCode',
				type: 'options',
				typeOptions: {
					loadOptionsMethod: 'getCountriesCodes',
				},
				default: '',
				description: `The regionCode parameter instructs the API to select a video chart available in the specified region.`,
			},
			{
				displayName: 'Related To Video ID',
				name: 'relatedToVideoId',
				type: 'string',
				default: '',
				description: 'The relatedToVideoId parameter retrieves a list of videos that are related to the video that the parameter value identifies',
			},
			{
				displayName: 'Video Category ID',
				name: 'videoCategoryId',
				type: 'string',
				default: '',
				description: `The videoCategoryId parameter identifies the video category for which the chart should be retrieved.`,
			},
			{
				displayName: 'Video Syndicated ',
				name: 'videoSyndicated',
				type: 'boolean',
				default: false,
				description: `The videoSyndicated parameter lets you to restrict a search to only videos that can be played outside youtube.com.`,
			},
			{
				displayName: 'Video Type',
				name: 'videoType',
				type: 'options',
				options: [
					{
						name: 'Any',
						value: 'any',
					},
					{
						name: 'Episode',
						value: 'episode',
					},
					{
						name: 'Movie',
						value: 'movie',
					},
				],
				default: '',
				description: `The videoType parameter lets you restrict a search to a particular type of videos`,
			},
		],
	},
	{
		displayName: 'Options',
		name: 'options',
		type: 'collection',
		placeholder: 'Add Option',
		default: {},
		displayOptions: {
			show: {
				operation: [
					'getAll',
				],
				resource: [
					'video',
				],
			},
		},
		options: [
			{
				displayName: 'Order',
				name: 'order',
				type: 'options',
				options: [
					{
						name: 'Date',
						value: 'date',
					},
					{
						name: 'Relevance',
						value: 'relevance',
					},
				],
				default: 'relevance',
			},
			{
				displayName: 'Safe Search',
				name: 'safeSearch',
				type: 'options',
				options: [
					{
						name: 'Moderate',
						value: 'moderate',
						description: 'YouTube will filter some content from search results and, at the least, will filter content that is restricted in your locale',
					},
					{
						name: 'none',
						value: 'none',
						description: 'YouTube will not filter the search result set',
					},
					{
						name: 'Strict',
						value: 'strict',
						description: 'YouTube will try to exclude all restricted content from the search result set',
					},
				],
				default: '',
			},
		],
	},
	/* -------------------------------------------------------------------------- */
	/*                                 video:rate                                 */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Video ID',
		name: 'videoId',
		type: 'string',
		required: true,
		displayOptions: {
			show: {
				operation: [
					'rate',
				],
				resource: [
					'video',
				],
			},
		},
		default: '',
	},
	{
		displayName: 'Rating',
		name: 'rating',
		type: 'options',
		displayOptions: {
			show: {
				operation: [
					'rate',
				],
				resource: [
					'video',
				],
			},
		},
		options: [
			{
				name: 'Dislike',
				value: 'dislike',
				description: 'Records that the authenticated user disliked the video.',
			},
			{
				name: 'Like',
				value: 'like',
				description: 'Records that the authenticated user liked the video.',
			},
			{
				name: 'None',
				value: 'none',
				description: 'Removes any rating that the authenticated user had previously set for the video.',
			},
		],
		default: '',
	},
	/* -------------------------------------------------------------------------- */
	/*                                 video:update                               */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Video ID',
		name: 'videoId',
		type: 'string',
		required: true,
		displayOptions: {
			show: {
				operation: [
					'update',
				],
				resource: [
					'video',
				],
			},
		},
		default: '',
	},
	{
		displayName: 'Title',
		name: 'title',
		type: 'string',
		required: true,
		displayOptions: {
			show: {
				operation: [
					'update',
				],
				resource: [
					'video',
				],
			},
		},
		default: '',
	},
	{
		displayName: 'Region Code',
		name: 'regionCode',
		type: 'options',
		typeOptions: {
			loadOptionsMethod: 'getCountriesCodes',
		},
		displayOptions: {
			show: {
				operation: [
					'update',
				],
				resource: [
					'video',
				],
			},
		},
		default: '',
	},
	{
		displayName: 'Category ID',
		name: 'categoryId',
		type: 'options',
		typeOptions: {
			loadOptionsMethod: 'getVideoCategories',
			loadOptionsDependsOn: [
				'regionCode',
			],
		},
		displayOptions: {
			show: {
				operation: [
					'update',
				],
				resource: [
					'video',
				],
			},
		},
		default: '',
	},
	{
		displayName: 'Update Fields',
		name: 'updateFields',
		type: 'collection',
		placeholder: 'Add Option',
		default: {},
		displayOptions: {
			show: {
				operation: [
					'update',
				],
				resource: [
					'video',
				],
			},
		},
		options: [
			{
				displayName: 'Default Language',
				name: 'defaultLanguage',
				type: 'options',
				typeOptions: {
					loadOptionsMethod: 'getLanguages',
				},
				default: '',
				description: `The language of the text in the playlist resource's title and description properties.`,
			},
			{
				displayName: 'Description',
				name: 'description',
				type: 'string',
				default: '',
				description: `The playlist's description.`,
			},
			{
				displayName: 'Embeddable',
				name: 'embeddable',
				type: 'boolean',
				default: false,
				description: `This value indicates whether the video can be embedded on another website.`,
			},
			{
				displayName: 'License',
				name: 'license',
				type: 'options',
				options: [
					{
						name: 'Creative Common',
						value: 'creativeCommon',
					},
					{
						name: 'Youtube',
						value: 'youtube',
					},
				],
				default: '',
				description: `The video's license.`,
			},
			{
				displayName: 'Notify Subscribers',
				name: 'notifySubscribers',
				type: 'boolean',
				default: false,
				description: `The notifySubscribers parameter indicates whether YouTube should send a notification about the new video to users who subscribe to the video's channel`,
			},
			{
				displayName: 'Privacy Status',
				name: 'privacyStatus',
				type: 'options',
				options: [
					{
						name: 'Private',
						value: 'private',
					},
					{
						name: 'Public',
						value: 'public',
					},
					{
						name: 'Unlisted',
						value: 'unlistef',
					},
				],
				default: '',
				description: `The playlist's privacy status.`,
			},
			{
				displayName: 'Public Stats Viewable',
				name: 'publicStatsViewable',
				type: 'boolean',
				default: true,
				description: `This value indicates whether the extended video statistics on the video's watch page are publicly viewable.`,
			},
			{
				displayName: 'Publish At',
				name: 'publishAt',
				type: 'dateTime',
				default: '',
				description: `If you set a value for this property, you must also set the status.privacyStatus property to private.`,
			},
			{
				displayName: 'Recording Date',
				name: 'recordingDate',
				type: 'dateTime',
				default: '',
				description: `The date and time when the video was recorded`,
			},
			{
				displayName: 'Self Declared Made For Kids',
				name: 'selfDeclaredMadeForKids',
				type: 'boolean',
				default: false,
				description: `This value indicates whether the video is designated as child-directed, and it contains the current "made for kids" status of the video`,
			},
			{
				displayName: 'Tags',
				name: 'tags',
				type: 'string',
				default: '',
				description: `Keyword tags associated with the playlist. Mulplie can be defined separated by comma`,
			},
		],
	},
] as INodeProperties[];


import {
	INodeProperties,
 } from 'n8n-workflow';

export const contactOperations = [
	{
		displayName: 'Operation',
		name: 'operation',
		type: 'options',
		displayOptions: {
			show: {
				resource: [
					'contact',
				],
			},
		},
		options: [
			{
				name: 'Create',
				value: 'create',
				description: 'create a contact',
			},
			{
				name: 'Get',
				value: 'get',
				description: 'Get a contact',
			},
			{
				name: 'Get All',
				value: 'getAll',
				description: 'Get all contacts',
			},
			{
				name: 'Update',
				value: 'update',
				description: 'Update a contact',
			},
		],
		default: 'create',
		description: 'The operation to perform.',
	},
] as INodeProperties[];

export const contactFields = [

/* -------------------------------------------------------------------------- */
/*                                contact:create                              */
/* -------------------------------------------------------------------------- */
	{
		displayName: 'Organization ID',
		name: 'organizationId',
		type: 'options',
		typeOptions: {
			loadOptionsMethod: 'getTenants',
		},
		default: '',
		displayOptions: {
			show: {
				resource: [
					'contact',
				],
				operation: [
					'create',
				],
			},
		},
		required: true,
	},
	{
		displayName: 'Name',
		name: 'name',
		type: 'string',
		default: '',
		displayOptions: {
			show: {
				resource: [
					'contact',
				],
				operation: [
					'create',
				],
			},
		},
		description: 'Full name of contact/organisation',
		required: true,
	},
	{
		displayName: 'Additional Fields',
		name: 'additionalFields',
		type: 'collection',
		placeholder: 'Add Field',
		default: {},
		displayOptions: {
			show: {
				resource: [
					'contact',
				],
				operation: [
					'create',
				],
			},
		},
		options: [
			{
				displayName: 'Account Number',
				name: 'accountNumber',
				type: 'string',
				default: '',
				description: 'A user defined account number',
			},
			// {
			// 	displayName: 'Addresses',
			// 	name: 'addressesUi',
			// 	type: 'fixedCollection',
			// 	typeOptions: {
			// 		multipleValues: true,
			// 	},
			// 	default: '',
			// 	placeholder: 'Add Address',
			// 	options: [
			// 		{
			// 			name: 'addressesValues',
			// 			displayName: 'Address',
			// 			values: [
			// 				{
			// 					displayName: 'Type',
			// 					name: 'type',
			// 					type: 'options',
			// 					options: [
			// 						{
			// 							name: 'PO Box',
			// 							value: 'POBOX',
			// 						},
			// 						{
			// 							name: 'Street',
			// 							value: 'STREET',
			// 						},
			// 					],
			// 					default: '',
			// 				},
			// 				{
			// 					displayName: 'Line 1',
			// 					name: 'line1',
			// 					type: 'string',
			// 					default: '',
			// 				},
			// 				{
			// 					displayName: 'Line 2',
			// 					name: 'line2',
			// 					type: 'string',
			// 					default: '',
			// 				},
			// 				{
			// 					displayName: 'City',
			// 					name: 'city',
			// 					type: 'string',
			// 					default: '',
			// 				},
			// 				{
			// 					displayName: 'Region',
			// 					name: 'region',
			// 					type: 'string',
			// 					default: '',
			// 				},
			// 				{
			// 					displayName: 'Postal Code',
			// 					name: 'postalCode',
			// 					type: 'string',
			// 					default: '',
			// 				},
			// 				{
			// 					displayName: 'Country',
			// 					name: 'country',
			// 					type: 'string',
			// 					default: '',
			// 				},
			// 				{
			// 					displayName: 'Attention To',
			// 					name: 'attentionTo',
			// 					type: 'string',
			// 					default: '',
			// 				},
			// 			],
			// 		},
			// 	],
			// },
			{
				displayName: 'Bank Account Details',
				name: 'bankAccountDetails',
				type: 'string',
				default: '',
				description: 'Bank account number of contact',
			},
			{
				displayName: 'Contact Number',
				name: 'contactNumber',
				type: 'string',
				default: '',
				description: 'This field is read only on the Xero contact screen, used to identify contacts in external systems',
			},
			{
				displayName: 'Contact Status',
				name: 'contactStatus',
				type: 'options',
				options: [
					{
						name: 'Active',
						value: 'ACTIVE',
						description: 'The Contact is active and can be used in transactions',
					},
					{
						name: 'Archived',
						value: 'ARCHIVED',
						description: 'The Contact is archived and can no longer be used in transactions',
					},
					{
						name: 'GDPR Request',
						value: 'GDPRREQUEST',
						description: 'The Contact is the subject of a GDPR erasure request',
					},
				],
				default: '',
				description: 'Current status of a contact - see contact status types',
			},
			{
				displayName: 'Default Currency',
				name: 'defaultCurrency',
				type: 'string',
				default: '',
				description: 'Default currency for raising invoices against contact',
			},
			{
				displayName: 'Email',
				name: 'emailAddress',
				type: 'string',
				default: '',
				description: 'Email address of contact person (umlauts not supported) (max length = 255)',
			},
			{
				displayName: 'First Name',
				name: 'firstName',
				type: 'string',
				default: '',
				description: 'First name of contact person (max length = 255)',
			},
			{
				displayName: 'Last Name',
				name: 'lastName',
				type: 'string',
				default: '',
				description: 'Last name of contact person (max length = 255)',
			},
			// {
			// 	displayName: 'Phones',
			// 	name: 'phonesUi',
			// 	type: 'fixedCollection',
			// 	typeOptions: {
			// 		multipleValues: true,
			// 	},
			// 	default: '',
			// 	placeholder: 'Add Phone',
			// 	options: [
			// 		{
			// 			name: 'phonesValues',
			// 			displayName: 'Phones',
			// 			values: [
			// 				{
			// 					displayName: 'Type',
			// 					name: 'type',
			// 					type: 'options',
			// 					options: [
			// 						{
			// 							name: 'Default',
			// 							value: 'DEFAULT',
			// 						},
			// 						{
			// 							name: 'DDI',
			// 							value: 'DDI',
			// 						},
			// 						{
			// 							name: 'Mobile',
			// 							value: 'MOBILE',
			// 						},
			// 						{
			// 							name: 'Fax',
			// 							value: 'FAX',
			// 						},
			// 					],
			// 					default: '',
			// 				},
			// 				{
			// 					displayName: 'Number',
			// 					name: 'phoneNumber',
			// 					type: 'string',
			// 					default: '',
			// 				},
			// 				{
			// 					displayName: 'Area Code',
			// 					name: 'phoneAreaCode',
			// 					type: 'string',
			// 					default: '',
			// 				},
			// 				{
			// 					displayName: 'Country Code',
			// 					name: 'phoneCountryCode',
			// 					type: 'string',
			// 					default: '',
			// 				},
			// 			],
			// 		},
			// 	],
			// },
			{
				displayName: 'Purchase Default Account Code',
				name: 'purchasesDefaultAccountCode',
				type: 'options',
				typeOptions: {
					loadOptionsMethod: 'getAccountCodes',
				},
				default: '',
				description: 'The default purchases account code for contacts',
			},
			{
				displayName: 'Sales Default Account Code',
				name: 'salesDefaultAccountCode',
				type: 'options',
				typeOptions: {
					loadOptionsMethod: 'getAccountCodes',
				},
				default: '',
				description: 'The default sales account code for contacts',
			},
			{
				displayName: 'Skype',
				name: 'skypeUserName',
				type: 'string',
				default: '',
				description: 'Skype user name of contact',
			},
			{
				displayName: 'Tax Number',
				name: 'taxNumber',
				type: 'string',
				default: '',
				description: 'Tax number of contact',
			},
			{
				displayName: 'Xero Network Key',
				name: 'xeroNetworkKey',
				type: 'string',
				default: '',
				description: 'Store XeroNetworkKey for contacts',
			},
		],
	},
/* -------------------------------------------------------------------------- */
/*                                 contact:get                                */
/* -------------------------------------------------------------------------- */
	{
		displayName: 'Organization ID',
		name: 'organizationId',
		type: 'options',
		typeOptions: {
			loadOptionsMethod: 'getTenants',
		},
		default: '',
		displayOptions: {
			show: {
				resource: [
					'contact',
				],
				operation: [
					'get',
				],
			},
		},
		required: true,
	},
	{
		displayName: 'Contact ID',
		name: 'contactId',
		type: 'string',
		default: '',
		displayOptions: {
			show: {
				resource: [
					'contact',
				],
				operation: [
					'get',
				],
			},
		},
		required: true,
	},
/* -------------------------------------------------------------------------- */
/*                                   contact:getAll                           */
/* -------------------------------------------------------------------------- */
	{
		displayName: 'Organization ID',
		name: 'organizationId',
		type: 'options',
		typeOptions: {
			loadOptionsMethod: 'getTenants',
		},
		default: '',
		displayOptions: {
			show: {
				resource: [
					'contact',
				],
				operation: [
					'getAll',
				],
			},
		},
		required: true,
	},
	{
		displayName: 'Return All',
		name: 'returnAll',
		type: 'boolean',
		displayOptions: {
			show: {
				resource: [
					'contact',
				],
				operation: [
					'getAll',
				],
			},
		},
		default: false,
		description: 'If all results should be returned or only up to a given limit.',
	},
	{
		displayName: 'Limit',
		name: 'limit',
		type: 'number',
		displayOptions: {
			show: {
				resource: [
					'contact',
				],
				operation: [
					'getAll',
				],
				returnAll: [
					false,
				],
			},
		},
		typeOptions: {
			minValue: 1,
			maxValue: 100,
		},
		default: 100,
		description: 'How many results to return.',
	},
	{
		displayName: 'Options',
		name: 'options',
		type: 'collection',
		placeholder: 'Add Option',
		default: {},
		displayOptions: {
			show: {
				resource: [
					'contact',
				],
				operation: [
					'getAll',
				],
			},
		},
		options: [
			{
				displayName: 'Include Archived',
				name: 'includeArchived',
				type: 'boolean',
				default: false,
				description: `Contacts with a status of ARCHIVED will be included in the response`,
			},
			{
				displayName: 'Order By',
				name: 'orderBy',
				type: 'string',
				placeholder: 'contactID',
				default: '',
				description: 'Order by any element returned',
			},
			{
				displayName: 'Sort Order',
				name: 'sortOrder',
				type: 'options',
				options: [
					{
						name: 'Asc',
						value: 'ASC',
					},
					{
						name: 'Desc',
						value: 'DESC',
					},
				],
				default: '',
				description: 'Sort order',
			},
			{
				displayName: 'Where',
				name: 'where',
				type: 'string',
				typeOptions: {
					alwaysOpenEditWindow: true,
				},
				placeholder: 'EmailAddress!=null&&EmailAddress.StartsWith("boom")',
				default: '',
				description: `The where parameter allows you to filter on endpoints and elements that don't have explicit parameters. Examples Here`,
			},
		],
	},
/* -------------------------------------------------------------------------- */
/*                                contact:update                              */
/* -------------------------------------------------------------------------- */
	{
		displayName: 'Organization ID',
		name: 'organizationId',
		type: 'options',
		typeOptions: {
			loadOptionsMethod: 'getTenants',
		},
		default: '',
		displayOptions: {
			show: {
				resource: [
					'contact',
				],
				operation: [
					'update',
				],
			},
		},
		required: true,
	},
	{
		displayName: 'Contact ID',
		name: 'contactId',
		type: 'string',
		default: '',
		displayOptions: {
			show: {
				resource: [
					'contact',
				],
				operation: [
					'update',
				],
			},
		},
		required: true,
	},
	{
		displayName: 'Update Fields',
		name: 'updateFields',
		type: 'collection',
		placeholder: 'Add Field',
		default: {},
		displayOptions: {
			show: {
				resource: [
					'contact',
				],
				operation: [
					'update',
				],
			},
		},
		options: [
			{
				displayName: 'Account Number',
				name: 'accountNumber',
				type: 'string',
				default: '',
				description: 'A user defined account number',
			},
			// {
			// 	displayName: 'Addresses',
			// 	name: 'addressesUi',
			// 	type: 'fixedCollection',
			// 	typeOptions: {
			// 		multipleValues: true,
			// 	},
			// 	default: '',
			// 	placeholder: 'Add Address',
			// 	options: [
			// 		{
			// 			name: 'addressesValues',
			// 			displayName: 'Address',
			// 			values: [
			// 				{
			// 					displayName: 'Type',
			// 					name: 'type',
			// 					type: 'options',
			// 					options: [
			// 						{
			// 							name: 'PO Box',
			// 							value: 'POBOX',
			// 						},
			// 						{
			// 							name: 'Street',
			// 							value: 'STREET',
			// 						},
			// 					],
			// 					default: '',
			// 				},
			// 				{
			// 					displayName: 'Line 1',
			// 					name: 'line1',
			// 					type: 'string',
			// 					default: '',
			// 				},
			// 				{
			// 					displayName: 'Line 2',
			// 					name: 'line2',
			// 					type: 'string',
			// 					default: '',
			// 				},
			// 				{
			// 					displayName: 'City',
			// 					name: 'city',
			// 					type: 'string',
			// 					default: '',
			// 				},
			// 				{
			// 					displayName: 'Region',
			// 					name: 'region',
			// 					type: 'string',
			// 					default: '',
			// 				},
			// 				{
			// 					displayName: 'Postal Code',
			// 					name: 'postalCode',
			// 					type: 'string',
			// 					default: '',
			// 				},
			// 				{
			// 					displayName: 'Country',
			// 					name: 'country',
			// 					type: 'string',
			// 					default: '',
			// 				},
			// 				{
			// 					displayName: 'Attention To',
			// 					name: 'attentionTo',
			// 					type: 'string',
			// 					default: '',
			// 				},
			// 			],
			// 		},
			// 	],
			// },
			{
				displayName: 'Bank Account Details',
				name: 'bankAccountDetails',
				type: 'string',
				default: '',
				description: 'Bank account number of contact',
			},
			{
				displayName: 'Contact Number',
				name: 'contactNumber',
				type: 'string',
				default: '',
				description: 'This field is read only on the Xero contact screen, used to identify contacts in external systems',
			},
			{
				displayName: 'Contact Status',
				name: 'contactStatus',
				type: 'options',
				options: [
					{
						name: 'Active',
						value: 'ACTIVE',
						description: 'The Contact is active and can be used in transactions',
					},
					{
						name: 'Archived',
						value: 'ARCHIVED',
						description: 'The Contact is archived and can no longer be used in transactions',
					},
					{
						name: 'GDPR Request',
						value: 'GDPRREQUEST',
						description: 'The Contact is the subject of a GDPR erasure request',
					},
				],
				default: '',
				description: 'Current status of a contact - see contact status types',
			},
			{
				displayName: 'Default Currency',
				name: 'defaultCurrency',
				type: 'string',
				default: '',
				description: 'Default currency for raising invoices against contact',
			},
			{
				displayName: 'Email',
				name: 'emailAddress',
				type: 'string',
				default: '',
				description: 'Email address of contact person (umlauts not supported) (max length = 255)',
			},
			{
				displayName: 'First Name',
				name: 'firstName',
				type: 'string',
				default: '',
				description: 'First name of contact person (max length = 255)',
			},
			{
				displayName: 'Last Name',
				name: 'lastName',
				type: 'string',
				default: '',
				description: 'Last name of contact person (max length = 255)',
			},
			{
				displayName: 'Name',
				name: 'name',
				type: 'string',
				default: '',
				description: 'Full name of contact/organisation',
			},
			// {
			// 	displayName: 'Phones',
			// 	name: 'phonesUi',
			// 	type: 'fixedCollection',
			// 	typeOptions: {
			// 		multipleValues: true,
			// 	},
			// 	default: '',
			// 	placeholder: 'Add Phone',
			// 	options: [
			// 		{
			// 			name: 'phonesValues',
			// 			displayName: 'Phones',
			// 			values: [
			// 				{
			// 					displayName: 'Type',
			// 					name: 'type',
			// 					type: 'options',
			// 					options: [
			// 						{
			// 							name: 'Default',
			// 							value: 'DEFAULT',
			// 						},
			// 						{
			// 							name: 'DDI',
			// 							value: 'DDI',
			// 						},
			// 						{
			// 							name: 'Mobile',
			// 							value: 'MOBILE',
			// 						},
			// 						{
			// 							name: 'Fax',
			// 							value: 'FAX',
			// 						},
			// 					],
			// 					default: '',
			// 				},
			// 				{
			// 					displayName: 'Number',
			// 					name: 'phoneNumber',
			// 					type: 'string',
			// 					default: '',
			// 				},
			// 				{
			// 					displayName: 'Area Code',
			// 					name: 'phoneAreaCode',
			// 					type: 'string',
			// 					default: '',
			// 				},
			// 				{
			// 					displayName: 'Country Code',
			// 					name: 'phoneCountryCode',
			// 					type: 'string',
			// 					default: '',
			// 				},
			// 			],
			// 		},
			// 	],
			// },
			{
				displayName: 'Purchase Default Account Code',
				name: 'purchasesDefaultAccountCode',
				type: 'options',
				typeOptions: {
					loadOptionsMethod: 'getAccountCodes',
				},
				default: '',
				description: 'The default purchases account code for contacts',
			},
			{
				displayName: 'Sales Default Account Code',
				name: 'salesDefaultAccountCode',
				type: 'options',
				typeOptions: {
					loadOptionsMethod: 'getAccountCodes',
				},
				default: '',
				description: 'The default sales account code for contacts',
			},
			{
				displayName: 'Skype',
				name: 'skypeUserName',
				type: 'string',
				default: '',
				description: 'Skype user name of contact',
			},
			{
				displayName: 'Tax Number',
				name: 'taxNumber',
				type: 'string',
				default: '',
				description: 'Tax number of contact',
			},
			{
				displayName: 'Xero Network Key',
				name: 'xeroNetworkKey',
				type: 'string',
				default: '',
				description: 'Store XeroNetworkKey for contacts',
			},
		],
	},
] as INodeProperties[];


import {
	ICredentialType,
	NodePropertyTypes,
} from 'n8n-workflow';

export class GumroadApi implements ICredentialType {
	name = 'gumroadApi';
	displayName = 'Gumroad API';
	documentationUrl = 'gumroad';
	properties = [
		{
			displayName: 'Access Token',
			name: 'accessToken',
			type: 'string' as NodePropertyTypes,
			default: '',
		},
	];
}


import {
	IExecuteFunctions,
} from 'n8n-core';

import {
	IDataObject,
	INodeExecutionData,
	INodeType,
	INodeTypeDescription,
} from 'n8n-workflow';

import {
	segmentApiRequest,
} from './GenericFunctions';

import {
	groupFields,
	groupOperations,
} from './GroupDescription';

import {
	identifyFields,
	identifyOperations,
} from './IdentifyDescription';

import {
	IIdentify,
} from './IdentifyInterface';

import {
	trackFields,
	trackOperations,
} from './TrackDescription';

import {
	IGroup,
	ITrack,
} from './TrackInterface';

import * as uuid from 'uuid/v4';
import { customerFields } from '../CustomerIo/CustomerDescription';

export class Segment implements INodeType {
	description: INodeTypeDescription = {
		displayName: 'Segment',
		name: 'segment',
		icon: 'file:segment.png',
		group: ['output'],
		version: 1,
		subtitle: '={{$parameter["operation"] + ":" + $parameter["resource"]}}',
		description: 'Consume Segment API',
		defaults: {
			name: 'Segment',
			color: '#6ebb99',
		},
		inputs: ['main'],
		outputs: ['main'],
		credentials: [
			{
				name: 'segmentApi',
				required: true,
			},
		],
		properties: [
			{
				displayName: 'Resource',
				name: 'resource',
				type: 'options',
				options: [
					{
						name: 'Group',
						value: 'group',
						description: 'Group lets you associate an identified user with a group',
					},
					{
						name: 'Identify',
						value: 'identify',
						description: 'Identify lets you tie a user to their actions',
					},
					{
						name: 'Track',
						value: 'track',
						description: 'Track lets you record events',
					},
				],
				default: 'identify',
				description: 'Resource to consume.',
			},
			...groupOperations,
			...groupFields,
			...identifyOperations,
			...trackOperations,
			...identifyFields,
			...trackFields,
		],
	};

	async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
		const items = this.getInputData();
		const returnData: IDataObject[] = [];
		const length = items.length as unknown as number;
		const qs: IDataObject = {};
		let responseData;
		const resource = this.getNodeParameter('resource', 0) as string;
		const operation = this.getNodeParameter('operation', 0) as string;

		for (let i = 0; i < length; i++) {
			if (resource === 'group') {
				//https://segment.com/docs/connections/sources/catalog/libraries/server/http-api/#group
				if (operation === 'add') {
					const userId = this.getNodeParameter('userId', i) as string;
					const groupId = this.getNodeParameter('groupId', i) as string;
					const traits = (this.getNodeParameter('traits', i) as IDataObject).traitsUi as IDataObject;
					const context = (this.getNodeParameter('context', i) as IDataObject).contextUi as IDataObject;
					const integrations = (this.getNodeParameter('integrations', i) as IDataObject).integrationsUi as IDataObject;
					const body: IGroup = {
						groupId,
						traits: {
							company: {},
							address: {},
						},
						context: {
							app: {},
							campaign: {},
							device: {},
						},
						integrations: {},
					};
					if (userId) {
						body.userId = userId as string;
					} else {
						body.anonymousId = uuid();
					}
					if (traits) {
						if (traits.email) {
							body.traits!.email = traits.email as string;
						}
						if (traits.firstname) {
							body.traits!.firstname = traits.firstname as string;
						}
						if (traits.lastname) {
							body.traits!.lastname = traits.lastname as string;
						}
						if (traits.gender) {
							body.traits!.gender = traits.gender as string;
						}
						if (traits.phone) {
							body.traits!.phone = traits.phone as string;
						}
						if (traits.username) {
							body.traits!.username = traits.username as string;
						}
						if (traits.website) {
							body.traits!.website = traits.website as string;
						}
						if (traits.age) {
							body.traits!.age = traits.age as number;
						}
						if (traits.avatar) {
							body.traits!.avatar = traits.avatar as string;
						}
						if (traits.birthday) {
							body.traits!.birthday = traits.birthday as string;
						}
						if (traits.createdAt) {
							body.traits!.createdAt = traits.createdAt as string;
						}
						if (traits.description) {
							body.traits!.description = traits.description as string;
						}
						if (traits.id) {
							body.traits!.id = traits.id as string;
						}

						if (traits.company) {
							const company = (traits.company as IDataObject).companyUi as IDataObject;
							if (company) {
								if (company.id) {
									//@ts-ignore
									body.traits.company.id = company.id as string;
								}
								if (company.name) {
									//@ts-ignore
									body.traits.company.name = company.name as string;
								}
								if (company.industry) {
									//@ts-ignore
									body.traits.company.industry = company.industry as string;
								}
								if (company.employeeCount) {
									//@ts-ignore
									body.traits.company.employeeCount = company.employeeCount as number;
								}
								if (company.plan) {
									//@ts-ignore
									body.traits.company.plan = company.plan as string;
								}
							}
						}
						if (traits.address) {
							const address = (traits.address as IDataObject).addressUi as IDataObject;
							if (address) {
								if (address.street) {
									//@ts-ignore
									body.traits.address.street = address.street as string;
								}
								if (address.city) {
									//@ts-ignore
									body.traits.address.city = address.city as string;
								}
								if (address.state) {
									//@ts-ignore
									body.traits.address.state = address.state as string;
								}
								if (address.postalCode) {
									//@ts-ignore
									body.traits.address.postalCode = address.postalCode as string;
								}
								if (address.country) {
									//@ts-ignore
									body.traits.address.country = address.country as string;
								}
							}
						}
					}
					if (context) {
						if (context.active) {
							body.context!.active = context.active as boolean;
						}
						if (context.ip) {
							body.context!.ip = context.ip as string;
						}
						if (context.locate) {
							body.context!.locate = context.locate as string;
						}
						if (context.page) {
							body.context!.page = context.page as string;
						}
						if (context.timezone) {
							body.context!.timezone = context.timezone as string;
						}
						if (context.timezone) {
							body.context!.timezone = context.timezone as string;
						}
						if (context.app) {
							const app = (context.app as IDataObject).appUi as IDataObject;
							if (app) {
								if (app.name) {
									//@ts-ignore
									body.context.app.name = app.name as string;
								}
								if (app.version) {
									//@ts-ignore
									body.context.app.version = app.version as string;
								}
								if (app.build) {
									//@ts-ignore
									body.context.app.build = app.build as string;
								}
							}
						}
						if (context.campaign) {
							const campaign = (context.campaign as IDataObject).campaignUi as IDataObject;
							if (campaign) {
								if (campaign.name) {
									//@ts-ignore
									body.context.campaign.name = campaign.name as string;
								}
								if (campaign.source) {
									//@ts-ignore
									body.context.campaign.source = campaign.source as string;
								}
								if (campaign.medium) {
									//@ts-ignore
									body.context.campaign.medium = campaign.medium as string;
								}
								if (campaign.term) {
									//@ts-ignore
									body.context.campaign.term = campaign.term as string;
								}
								if (campaign.content) {
									//@ts-ignore
									body.context.campaign.content = campaign.content as string;
								}
							}
						}

						if (context.device) {
							const device = (context.device as IDataObject).deviceUi as IDataObject;
							if (device) {
								if (device.id) {
									//@ts-ignore
									body.context.device.id = device.id as string;
								}
								if (device.manufacturer) {
									//@ts-ignore
									body.context.device.manufacturer = device.manufacturer as string;
								}
								if (device.model) {
									//@ts-ignore
									body.context.device.model = device.model as string;
								}
								if (device.type) {
									//@ts-ignore
									body.context.device.type = device.type as string;
								}
								if (device.version) {
									//@ts-ignore
									body.context.device.version = device.version as string;
								}
							}
						}
					}
					if (integrations) {
						if (integrations.all) {
							body.integrations!.all = integrations.all as boolean;
						}
						if (integrations.salesforce) {
							body.integrations!.salesforce = integrations.salesforce as boolean;
						}
					}
					responseData = await segmentApiRequest.call(this, 'POST', '/group', body);
				}
			}
			if (resource === 'identify') {
				//https://segment.com/docs/connections/sources/catalog/libraries/server/http-api/#identify
				if (operation === 'create') {
					const userId = this.getNodeParameter('userId', i) as string;
					const traits = (this.getNodeParameter('traits', i) as IDataObject).traitsUi as IDataObject;
					const context = (this.getNodeParameter('context', i) as IDataObject).contextUi as IDataObject;
					const integrations = (this.getNodeParameter('integrations', i) as IDataObject).integrationsUi as IDataObject;
					const body: IIdentify = {
						traits: {
							company: {},
							address: {},
						},
						context: {
							app: {},
							campaign: {},
							device: {},
						},
						integrations: {},
					};
					if (userId) {
						body.userId = userId as string;
					} else {
						body.anonymousId = uuid();
					}
					if (traits) {
						if (traits.email) {
							body.traits!.email = traits.email as string;
						}
						if (traits.firstname) {
							body.traits!.firstname = traits.firstname as string;
						}
						if (traits.lastname) {
							body.traits!.lastname = traits.lastname as string;
						}
						if (traits.gender) {
							body.traits!.gender = traits.gender as string;
						}
						if (traits.phone) {
							body.traits!.phone = traits.phone as string;
						}
						if (traits.username) {
							body.traits!.username = traits.username as string;
						}
						if (traits.website) {
							body.traits!.website = traits.website as string;
						}
						if (traits.age) {
							body.traits!.age = traits.age as number;
						}
						if (traits.avatar) {
							body.traits!.avatar = traits.avatar as string;
						}
						if (traits.birthday) {
							body.traits!.birthday = traits.birthday as string;
						}
						if (traits.createdAt) {
							body.traits!.createdAt = traits.createdAt as string;
						}
						if (traits.description) {
							body.traits!.description = traits.description as string;
						}
						if (traits.id) {
							body.traits!.id = traits.id as string;
						}
						if (traits.customTraitsUi) {
							const customTraits = (traits.customTraitsUi as IDataObject).customTraitValues as IDataObject[];
							if (customTraits && customTraits.length !== 0) {
								for (const customTrait of customTraits) {
									body.traits![customTrait.key as string] = customTrait.value;
								}
							}
						}
						if (traits.company) {
							const company = (traits.company as IDataObject).companyUi as IDataObject;
							if (company) {
								if (company.id) {
									//@ts-ignore
									body.traits.company.id = company.id as string;
								}
								if (company.name) {
									//@ts-ignore
									body.traits.company.name = company.name as string;
								}
								if (company.industry) {
									//@ts-ignore
									body.traits.company.industry = company.industry as string;
								}
								if (company.employeeCount) {
									//@ts-ignore
									body.traits.company.employeeCount = company.employeeCount as number;
								}
								if (company.plan) {
									//@ts-ignore
									body.traits.company.plan = company.plan as string;
								}
							}
						}
						if (traits.address) {
							const address = (traits.address as IDataObject).addressUi as IDataObject;
							if (address) {
								if (address.street) {
									//@ts-ignore
									body.traits.address.street = address.street as string;
								}
								if (address.city) {
									//@ts-ignore
									body.traits.address.city = address.city as string;
								}
								if (address.state) {
									//@ts-ignore
									body.traits.address.state = address.state as string;
								}
								if (address.postalCode) {
									//@ts-ignore
									body.traits.address.postalCode = address.postalCode as string;
								}
								if (address.country) {
									//@ts-ignore
									body.traits.address.country = address.country as string;
								}
							}
						}
					}
					if (context) {
						if (context.active) {
							body.context!.active = context.active as boolean;
						}
						if (context.ip) {
							body.context!.ip = context.ip as string;
						}
						if (context.locate) {
							body.context!.locate = context.locate as string;
						}
						if (context.page) {
							body.context!.page = context.page as string;
						}
						if (context.timezone) {
							body.context!.timezone = context.timezone as string;
						}
						if (context.timezone) {
							body.context!.timezone = context.timezone as string;
						}
						if (context.app) {
							const app = (context.app as IDataObject).appUi as IDataObject;
							if (app) {
								if (app.name) {
									//@ts-ignore
									body.context.app.name = app.name as string;
								}
								if (app.version) {
									//@ts-ignore
									body.context.app.version = app.version as string;
								}
								if (app.build) {
									//@ts-ignore
									body.context.app.build = app.build as string;
								}
							}
						}
						if (context.campaign) {
							const campaign = (context.campaign as IDataObject).campaignUi as IDataObject;
							if (campaign) {
								if (campaign.name) {
									//@ts-ignore
									body.context.campaign.name = campaign.name as string;
								}
								if (campaign.source) {
									//@ts-ignore
									body.context.campaign.source = campaign.source as string;
								}
								if (campaign.medium) {
									//@ts-ignore
									body.context.campaign.medium = campaign.medium as string;
								}
								if (campaign.term) {
									//@ts-ignore
									body.context.campaign.term = campaign.term as string;
								}
								if (campaign.content) {
									//@ts-ignore
									body.context.campaign.content = campaign.content as string;
								}
							}
						}

						if (context.device) {
							const device = (context.device as IDataObject).deviceUi as IDataObject;
							if (device) {
								if (device.id) {
									//@ts-ignore
									body.context.device.id = device.id as string;
								}
								if (device.manufacturer) {
									//@ts-ignore
									body.context.device.manufacturer = device.manufacturer as string;
								}
								if (device.model) {
									//@ts-ignore
									body.context.device.model = device.model as string;
								}
								if (device.type) {
									//@ts-ignore
									body.context.device.type = device.type as string;
								}
								if (device.version) {
									//@ts-ignore
									body.context.device.version = device.version as string;
								}
							}
						}
					}
					if (integrations) {
						if (integrations.all) {
							body.integrations!.all = integrations.all as boolean;
						}
						if (integrations.salesforce) {
							body.integrations!.salesforce = integrations.salesforce as boolean;
						}
					}

					if (Object.keys(traits.company as IDataObject).length === 0) {
						//@ts-ignore
						delete body.traits.company;
					}

					if (Object.keys(traits.address as IDataObject).length === 0) {
						//@ts-ignore
						delete body.traits.address;
					}

					responseData = await segmentApiRequest.call(this, 'POST', '/identify', body);
				}
			}
			if (resource === 'track') {
				//https://segment.com/docs/connections/sources/catalog/libraries/server/http-api/#track
				if (operation === 'event') {
					const userId = this.getNodeParameter('userId', i) as string;
					const event = this.getNodeParameter('event', i) as string;
					const traits = (this.getNodeParameter('traits', i) as IDataObject).traitsUi as IDataObject;
					const context = (this.getNodeParameter('context', i) as IDataObject).contextUi as IDataObject;
					const integrations = (this.getNodeParameter('integrations', i) as IDataObject).integrationsUi as IDataObject;
					const properties = (this.getNodeParameter('properties', i) as IDataObject).propertiesUi as IDataObject;
					const body: ITrack = {
						event,
						traits: {
							company: {},
							address: {},
						},
						context: {
							app: {},
							campaign: {},
							device: {},
						},
						integrations: {},
						properties: {},
					};
					if (userId) {
						body.userId = userId as string;
					} else {
						body.anonymousId = uuid();
					}
					if (traits) {
						if (traits.email) {
							body.traits!.email = traits.email as string;
						}
						if (traits.firstname) {
							body.traits!.firstname = traits.firstname as string;
						}
						if (traits.lastname) {
							body.traits!.lastname = traits.lastname as string;
						}
						if (traits.gender) {
							body.traits!.gender = traits.gender as string;
						}
						if (traits.phone) {
							body.traits!.phone = traits.phone as string;
						}
						if (traits.username) {
							body.traits!.username = traits.username as string;
						}
						if (traits.website) {
							body.traits!.website = traits.website as string;
						}
						if (traits.age) {
							body.traits!.age = traits.age as number;
						}
						if (traits.avatar) {
							body.traits!.avatar = traits.avatar as string;
						}
						if (traits.birthday) {
							body.traits!.birthday = traits.birthday as string;
						}
						if (traits.createdAt) {
							body.traits!.createdAt = traits.createdAt as string;
						}
						if (traits.description) {
							body.traits!.description = traits.description as string;
						}
						if (traits.id) {
							body.traits!.id = traits.id as string;
						}
						if (traits.customTraitsUi) {
							const customTraits = (traits.customTraitsUi as IDataObject).customTraitValues as IDataObject[];
							if (customTraits && customTraits.length !== 0) {
								for (const customTrait of customTraits) {
									body.traits![customTrait.key as string] = customTrait.value;
								}
							}
						}
						if (traits.company) {
							const company = (traits.company as IDataObject).companyUi as IDataObject;
							if (company) {
								if (company.id) {
									//@ts-ignore
									body.traits.company.id = company.id as string;
								}
								if (company.name) {
									//@ts-ignore
									body.traits.company.name = company.name as string;
								}
								if (company.industry) {
									//@ts-ignore
									body.traits.company.industry = company.industry as string;
								}
								if (company.employeeCount) {
									//@ts-ignore
									body.traits.company.employeeCount = company.employeeCount as number;
								}
								if (company.plan) {
									//@ts-ignore
									body.traits.company.plan = company.plan as string;
								}
							}
						}
						if (traits.address) {
							const address = (traits.address as IDataObject).addressUi as IDataObject;
							if (address) {
								if (address.street) {
									//@ts-ignore
									body.traits.address.street = address.street as string;
								}
								if (address.city) {
									//@ts-ignore
									body.traits.address.city = address.city as string;
								}
								if (address.state) {
									//@ts-ignore
									body.traits.address.state = address.state as string;
								}
								if (address.postalCode) {
									//@ts-ignore
									body.traits.address.postalCode = address.postalCode as string;
								}
								if (address.country) {
									//@ts-ignore
									body.traits.address.country = address.country as string;
								}
							}
						}
					}
					if (context) {
						if (context.active) {
							body.context!.active = context.active as boolean;
						}
						if (context.ip) {
							body.context!.ip = context.ip as string;
						}
						if (context.locate) {
							body.context!.locate = context.locate as string;
						}
						if (context.page) {
							body.context!.page = context.page as string;
						}
						if (context.timezone) {
							body.context!.timezone = context.timezone as string;
						}
						if (context.timezone) {
							body.context!.timezone = context.timezone as string;
						}
						if (context.app) {
							const app = (context.app as IDataObject).appUi as IDataObject;
							if (app) {
								if (app.name) {
									//@ts-ignore
									body.context.app.name = app.name as string;
								}
								if (app.version) {
									//@ts-ignore
									body.context.app.version = app.version as string;
								}
								if (app.build) {
									//@ts-ignore
									body.context.app.build = app.build as string;
								}
							}
						}
						if (context.campaign) {
							const campaign = (context.campaign as IDataObject).campaignUi as IDataObject;
							if (campaign) {
								if (campaign.name) {
									//@ts-ignore
									body.context.campaign.name = campaign.name as string;
								}
								if (campaign.source) {
									//@ts-ignore
									body.context.campaign.source = campaign.source as string;
								}
								if (campaign.medium) {
									//@ts-ignore
									body.context.campaign.medium = campaign.medium as string;
								}
								if (campaign.term) {
									//@ts-ignore
									body.context.campaign.term = campaign.term as string;
								}
								if (campaign.content) {
									//@ts-ignore
									body.context.campaign.content = campaign.content as string;
								}
							}
						}

						if (context.device) {
							const device = (context.device as IDataObject).deviceUi as IDataObject;
							if (device) {
								if (device.id) {
									//@ts-ignore
									body.context.device.id = device.id as string;
								}
								if (device.manufacturer) {
									//@ts-ignore
									body.context.device.manufacturer = device.manufacturer as string;
								}
								if (device.model) {
									//@ts-ignore
									body.context.device.model = device.model as string;
								}
								if (device.type) {
									//@ts-ignore
									body.context.device.type = device.type as string;
								}
								if (device.version) {
									//@ts-ignore
									body.context.device.version = device.version as string;
								}
							}
						}
					}
					if (integrations) {
						if (integrations.all) {
							body.integrations!.all = integrations.all as boolean;
						}
						if (integrations.salesforce) {
							body.integrations!.salesforce = integrations.salesforce as boolean;
						}
					}
					if (properties) {
						if (properties.revenue) {
							body.properties!.revenue = properties.revenue as number;
						}
						if (properties.currency) {
							body.properties!.currency = properties.currency as string;
						}
						if (properties.value) {
							body.properties!.value = properties.value as string;
						}
					}

					if (Object.keys(traits.company as IDataObject).length === 0) {
						//@ts-ignore
						delete body.traits.company;
					}

					if (Object.keys(traits.address as IDataObject).length === 0) {
						//@ts-ignore
						delete body.traits.address;
					}

					responseData = await segmentApiRequest.call(this, 'POST', '/track', body);
				}
				//https://segment.com/docs/connections/sources/catalog/libraries/server/http-api/#page
				if (operation === 'page') {
					const userId = this.getNodeParameter('userId', i) as string;
					const event = this.getNodeParameter('event', i) as string;
					const traits = (this.getNodeParameter('traits', i) as IDataObject).traitsUi as IDataObject;
					const context = (this.getNodeParameter('context', i) as IDataObject).contextUi as IDataObject;
					const integrations = (this.getNodeParameter('integrations', i) as IDataObject).integrationsUi as IDataObject;
					const properties = (this.getNodeParameter('properties', i) as IDataObject).propertiesUi as IDataObject;
					const body: ITrack = {
						event,
						traits: {
							company: {},
							address: {},
						},
						context: {
							app: {},
							campaign: {},
							device: {},
						},
						integrations: {},
						properties: {},
					};
					if (userId) {
						body.userId = userId as string;
					} else {
						body.anonymousId = uuid();
					}
					if (traits) {
						if (traits.email) {
							body.traits!.email = traits.email as string;
						}
						if (traits.firstname) {
							body.traits!.firstname = traits.firstname as string;
						}
						if (traits.lastname) {
							body.traits!.lastname = traits.lastname as string;
						}
						if (traits.gender) {
							body.traits!.gender = traits.gender as string;
						}
						if (traits.phone) {
							body.traits!.phone = traits.phone as string;
						}
						if (traits.username) {
							body.traits!.username = traits.username as string;
						}
						if (traits.website) {
							body.traits!.website = traits.website as string;
						}
						if (traits.age) {
							body.traits!.age = traits.age as number;
						}
						if (traits.avatar) {
							body.traits!.avatar = traits.avatar as string;
						}
						if (traits.birthday) {
							body.traits!.birthday = traits.birthday as string;
						}
						if (traits.createdAt) {
							body.traits!.createdAt = traits.createdAt as string;
						}
						if (traits.description) {
							body.traits!.description = traits.description as string;
						}
						if (traits.id) {
							body.traits!.id = traits.id as string;
						}
						if (traits.company) {
							const company = (traits.company as IDataObject).companyUi as IDataObject;
							if (company) {
								if (company.id) {
									//@ts-ignore
									body.traits.company.id = company.id as string;
								}
								if (company.name) {
									//@ts-ignore
									body.traits.company.name = company.name as string;
								}
								if (company.industry) {
									//@ts-ignore
									body.traits.company.industry = company.industry as string;
								}
								if (company.employeeCount) {
									//@ts-ignore
									body.traits.company.employeeCount = company.employeeCount as number;
								}
								if (company.plan) {
									//@ts-ignore
									body.traits.company.plan = company.plan as string;
								}
							}
						}
						if (traits.address) {
							const address = (traits.address as IDataObject).addressUi as IDataObject;
							if (address) {
								if (address.street) {
									//@ts-ignore
									body.traits.address.street = address.street as string;
								}
								if (address.city) {
									//@ts-ignore
									body.traits.address.city = address.city as string;
								}
								if (address.state) {
									//@ts-ignore
									body.traits.address.state = address.state as string;
								}
								if (address.postalCode) {
									//@ts-ignore
									body.traits.address.postalCode = address.postalCode as string;
								}
								if (address.country) {
									//@ts-ignore
									body.traits.address.country = address.country as string;
								}
							}
						}
					}
					if (context) {
						if (context.active) {
							body.context!.active = context.active as boolean;
						}
						if (context.ip) {
							body.context!.ip = context.ip as string;
						}
						if (context.locate) {
							body.context!.locate = context.locate as string;
						}
						if (context.page) {
							body.context!.page = context.page as string;
						}
						if (context.timezone) {
							body.context!.timezone = context.timezone as string;
						}
						if (context.timezone) {
							body.context!.timezone = context.timezone as string;
						}
						if (context.app) {
							const app = (context.app as IDataObject).appUi as IDataObject;
							if (app) {
								if (app.name) {
									//@ts-ignore
									body.context.app.name = app.name as string;
								}
								if (app.version) {
									//@ts-ignore
									body.context.app.version = app.version as string;
								}
								if (app.build) {
									//@ts-ignore
									body.context.app.build = app.build as string;
								}
							}
						}
						if (context.campaign) {
							const campaign = (context.campaign as IDataObject).campaignUi as IDataObject;
							if (campaign) {
								if (campaign.name) {
									//@ts-ignore
									body.context.campaign.name = campaign.name as string;
								}
								if (campaign.source) {
									//@ts-ignore
									body.context.campaign.source = campaign.source as string;
								}
								if (campaign.medium) {
									//@ts-ignore
									body.context.campaign.medium = campaign.medium as string;
								}
								if (campaign.term) {
									//@ts-ignore
									body.context.campaign.term = campaign.term as string;
								}
								if (campaign.content) {
									//@ts-ignore
									body.context.campaign.content = campaign.content as string;
								}
							}
						}

						if (context.device) {
							const device = (context.device as IDataObject).deviceUi as IDataObject;
							if (device) {
								if (device.id) {
									//@ts-ignore
									body.context.device.id = device.id as string;
								}
								if (device.manufacturer) {
									//@ts-ignore
									body.context.device.manufacturer = device.manufacturer as string;
								}
								if (device.model) {
									//@ts-ignore
									body.context.device.model = device.model as string;
								}
								if (device.type) {
									//@ts-ignore
									body.context.device.type = device.type as string;
								}
								if (device.version) {
									//@ts-ignore
									body.context.device.version = device.version as string;
								}
							}
						}
					}
					if (integrations) {
						if (integrations.all) {
							body.integrations!.all = integrations.all as boolean;
						}
						if (integrations.salesforce) {
							body.integrations!.salesforce = integrations.salesforce as boolean;
						}
					}
					if (properties) {
						if (properties.name) {
							body.properties!.name = properties.name as number;
						}
						if (properties.path) {
							body.properties!.path = properties.path as string;
						}
						if (properties.referrer) {
							body.properties!.referrer = properties.referrer as string;
						}
						if (properties.search) {
							body.properties!.search = properties.search as string;
						}
						if (properties.title) {
							body.properties!.title = properties.title as string;
						}
						if (properties.url) {
							body.properties!.url = properties.url as string;
						}
						if (properties.keywords) {
							body.properties!.keywords = properties.keywords as string;
						}
					}
					responseData = await segmentApiRequest.call(this, 'POST', '/page', body);
				}
			}
			if (Array.isArray(responseData)) {
				returnData.push.apply(returnData, responseData as IDataObject[]);
			} else {
				returnData.push(responseData as IDataObject);
			}
		}
		return [this.helpers.returnJsonArray(returnData)];
	}
}


import {
	INodeProperties,
} from 'n8n-workflow';

export const playlistOperations = [
	{
		displayName: 'Operation',
		name: 'operation',
		type: 'options',
		displayOptions: {
			show: {
				resource: [
					'playlist',
				],
			},
		},
		options: [
			{
				name: 'Create',
				value: 'create',
				description: 'Create a playlist',
			},
			{
				name: 'Delete',
				value: 'delete',
				description: 'Delete a playlist',
			},
			{
				name: 'Get',
				value: 'get',
				description: 'Get a playlist',
			},
			{
				name: 'Get All',
				value: 'getAll',
				description: 'Retrieve all playlists',
			},
			{
				name: 'Update',
				value: 'update',
				description: 'Update a playlist',
			},
		],
		default: 'getAll',
		description: 'The operation to perform.',
	},
] as INodeProperties[];

export const playlistFields = [
	/* -------------------------------------------------------------------------- */
	/*                                 playlist:create                            */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Title',
		name: 'title',
		type: 'string',
		required: true,
		displayOptions: {
			show: {
				operation: [
					'create',
				],
				resource: [
					'playlist',
				],
			},
		},
		default: '',
		description: `The playlist's title.`,
	},
	{
		displayName: 'Options',
		name: 'options',
		type: 'collection',
		placeholder: 'Add Option',
		default: {},
		displayOptions: {
			show: {
				operation: [
					'create',
				],
				resource: [
					'playlist',
				],
			},
		},
		options: [
			{
				displayName: 'Description',
				name: 'description',
				type: 'string',
				default: '',
				description: `The playlist's description.`,
			},
			{
				displayName: 'Privacy Status',
				name: 'privacyStatus',
				type: 'options',
				options: [
					{
						name: 'Private',
						value: 'private',
					},
					{
						name: 'Public',
						value: 'public',
					},
					{
						name: 'Unlisted',
						value: 'unlistef',
					},
				],
				default: '',
				description: `The playlist's privacy status.`,
			},
			{
				displayName: 'Tags',
				name: 'tags',
				type: 'string',
				default: '',
				description: `Keyword tags associated with the playlist. Mulplie can be defined separated by comma`,
			},
			{
				displayName: 'Default Language',
				name: 'defaultLanguage',
				type: 'options',
				typeOptions: {
					loadOptionsMethod: 'getLanguages',
				},
				default: '',
				description: `The language of the text in the playlist resource's title and description properties.`,
			},
			{
				displayName: 'On Behalf Of Content Owner Channel',
				name: 'onBehalfOfContentOwnerChannel',
				type: 'string',
				default: '',
				description: `The onBehalfOfContentOwnerChannel parameter specifies the YouTube channel ID of the channel to which a video is being added.

				This parameter is required when a request specifies a value for the onBehalfOfContentOwner parameter, and it can only be used in conjunction with that parameter.`,
			},
			{
				displayName: 'On Behalf Of Content Owner',
				name: 'onBehalfOfContentOwner',
				type: 'string',
				default: '',
				description: `The onBehalfOfContentOwner parameter indicates that the request's authorization credentials identify

				a YouTube CMS user who is acting on behalf of the content owner specified in the parameter value`,
			},
		],
	},
	/* -------------------------------------------------------------------------- */
	/*                                 playlist:get                               */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Playlist ID',
		name: 'playlistId',
		type: 'string',
		required: true,
		displayOptions: {
			show: {
				operation: [
					'get',
				],
				resource: [
					'playlist',
				],
			},
		},
		default: '',
	},
	{
		displayName: 'Fields',
		name: 'part',
		type: 'multiOptions',
		options: [
			{
				name: '*',
				value: '*',
			},
			{
				name: 'Content Details',
				value: 'contentDetails',
			},
			{
				name: 'ID',
				value: 'id',
			},
			{
				name: 'Localizations',
				value: 'localizations',
			},
			{
				name: 'Player',
				value: 'player',
			},
			{
				name: 'Snippet',
				value: 'snippet',
			},
			{
				name: 'Status',
				value: 'status',
			},
		],
		required: true,
		displayOptions: {
			show: {
				operation: [
					'get',
				],
				resource: [
					'playlist',
				],
			},
		},
		description: 'The fields parameter specifies a comma-separated list of one or more playlist resource properties that the API response will include.',
		default: ['*'],
	},
	{
		displayName: 'Options',
		name: 'options',
		type: 'collection',
		placeholder: 'Add Option',
		default: {},
		displayOptions: {
			show: {
				operation: [
					'get',
				],
				resource: [
					'playlist',
				],
			},
		},
		options: [
			{
				displayName: 'On Behalf Of Content Owner',
				name: 'onBehalfOfContentOwner',
				type: 'string',
				default: '',
				description: `The onBehalfOfContentOwner parameter indicates that the request's authorization credentials identify

				a YouTube CMS user who is acting on behalf of the content owner specified in the parameter value`,
			},
			{
				displayName: 'On Behalf Of Content Owner Channel',
				name: 'onBehalfOfContentOwnerChannel',
				type: 'string',
				default: '',
				description: `The onBehalfOfContentOwnerChannel parameter specifies the YouTube channel ID of the channel to which a video is being added`,
			},
		],
	},
	/* -------------------------------------------------------------------------- */
	/*                                 playlist:delete                            */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Playlist ID',
		name: 'playlistId',
		type: 'string',
		required: true,
		displayOptions: {
			show: {
				operation: [
					'delete',
				],
				resource: [
					'playlist',
				],
			},
		},
		default: '',
	},
	{
		displayName: 'Options',
		name: 'options',
		type: 'collection',
		placeholder: 'Add Option',
		default: {},
		displayOptions: {
			show: {
				operation: [
					'delete',
				],
				resource: [
					'playlist',
				],
			},
		},
		options: [
			{
				displayName: 'On Behalf Of Content Owner',
				name: 'onBehalfOfContentOwner',
				type: 'string',
				default: '',
				description: `The onBehalfOfContentOwner parameter indicates that the request's authorization credentials identify

				a YouTube CMS user who is acting on behalf of the content owner specified in the parameter value`,
			},
		],
	},
	/* -------------------------------------------------------------------------- */
	/*                                 playlist:getAll                            */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Fields',
		name: 'part',
		type: 'multiOptions',
		options: [
			{
				name: '*',
				value: '*',
			},
			{
				name: 'Content Details',
				value: 'contentDetails',
			},
			{
				name: 'ID',
				value: 'id',
			},
			{
				name: 'Localizations',
				value: 'localizations',
			},
			{
				name: 'Player',
				value: 'player',
			},
			{
				name: 'Snippet',
				value: 'snippet',
			},
			{
				name: 'Status',
				value: 'status',
			},
		],
		required: true,
		displayOptions: {
			show: {
				operation: [
					'getAll',
				],
				resource: [
					'playlist',
				],
			},
		},
		description: 'The fields parameter specifies a comma-separated list of one or more playlist resource properties that the API response will include.',
		default: ['*'],
	},
	{
		displayName: 'Return All',
		name: 'returnAll',
		type: 'boolean',
		displayOptions: {
			show: {
				operation: [
					'getAll',
				],
				resource: [
					'playlist',
				],
			},
		},
		default: false,
		description: 'If all results should be returned or only up to a given limit.',
	},
	{
		displayName: 'Limit',
		name: 'limit',
		type: 'number',
		displayOptions: {
			show: {
				operation: [
					'getAll',
				],
				resource: [
					'playlist',
				],
				returnAll: [
					false,
				],
			},
		},
		typeOptions: {
			minValue: 1,
			maxValue: 50,
		},
		default: 25,
		description: 'How many results to return.',
	},
	{
		displayName: 'Filters',
		name: 'filters',
		type: 'collection',
		placeholder: 'Add Option',
		default: {},
		displayOptions: {
			show: {
				operation: [
					'getAll',
				],
				resource: [
					'playlist',
				],
			},
		},
		options: [
			{
				displayName: 'Channel ID',
				name: 'channelId',
				type: 'string',
				default: '',
				description: `This value indicates that the API should only return the specified channel's playlists.`,
			},
			{
				displayName: 'ID',
				name: 'id',
				type: 'string',
				default: '',
				description: `The id parameter specifies a comma-separated list of the YouTube playlist ID(s) for the resource(s) that are being retrieved. In a playlist resource, the id property specifies the playlist's YouTube playlist ID.`,
			},
		],
	},
	{
		displayName: 'Options',
		name: 'options',
		type: 'collection',
		placeholder: 'Add Option',
		default: {},
		displayOptions: {
			show: {
				operation: [
					'getAll',
				],
				resource: [
					'playlist',
				],
			},
		},
		options: [
			{
				displayName: 'On Behalf Of Content Owner Channel',
				name: 'onBehalfOfContentOwnerChannel',
				type: 'string',
				default: '',
				description: `The onBehalfOfContentOwnerChannel parameter specifies the YouTube channel ID of the channel to which a video is being added.

				This parameter is required when a request specifies a value for the onBehalfOfContentOwner parameter, and it can only be used in conjunction with that parameter.`,
			},
			{
				displayName: 'On Behalf Of Content Owner',
				name: 'onBehalfOfContentOwner',
				type: 'string',
				default: '',
				description: `The onBehalfOfContentOwner parameter indicates that the request's authorization credentials identify

				a YouTube CMS user who is acting on behalf of the content owner specified in the parameter value`,
			},
		],
	},
	/* -------------------------------------------------------------------------- */
	/*                                 playlist:update                            */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Playlist ID',
		name: 'playlistId',
		type: 'string',
		required: true,
		displayOptions: {
			show: {
				operation: [
					'update',
				],
				resource: [
					'playlist',
				],
			},
		},
		default: '',
		description: `The playlist's title.`,
	},
	{
		displayName: 'Title',
		name: 'title',
		type: 'string',
		required: true,
		displayOptions: {
			show: {
				operation: [
					'update',
				],
				resource: [
					'playlist',
				],
			},
		},
		default: '',
		description: `The playlist's title.`,
	},
	{
		displayName: 'Update Fields',
		name: 'updateFields',
		type: 'collection',
		placeholder: 'Add Field',
		default: {},
		displayOptions: {
			show: {
				operation: [
					'update',
				],
				resource: [
					'playlist',
				],
			},
		},
		options: [
			{
				displayName: 'Default Language',
				name: 'defaultLanguage',
				type: 'options',
				typeOptions: {
					loadOptionsMethod: 'getLanguages',
				},
				default: '',
				description: `The language of the text in the playlist resource's title and description properties.`,
			},
			{
				displayName: 'Description',
				name: 'description',
				type: 'string',
				default: '',
				description: `The playlist's description.`,
			},
			{
				displayName: 'On Behalf Of Content Owner',
				name: 'onBehalfOfContentOwner',
				type: 'string',
				default: '',
				description: `The onBehalfOfContentOwner parameter indicates that the request's authorization credentials identify

				a YouTube CMS user who is acting on behalf of the content owner specified in the parameter value`,
			},
			{
				displayName: 'Privacy Status',
				name: 'privacyStatus',
				type: 'options',
				options: [
					{
						name: 'Private',
						value: 'private',
					},
					{
						name: 'Public',
						value: 'public',
					},
					{
						name: 'Unlisted',
						value: 'unlistef',
					},
				],
				default: '',
				description: `The playlist's privacy status.`,
			},
			{
				displayName: 'Tags',
				name: 'tags',
				type: 'string',
				default: '',
				description: `Keyword tags associated with the playlist. Mulplie can be defined separated by comma`,
			},
		],
	},
] as INodeProperties[];