'use strict' import { youtube_v3 } from 'googleapis' import { Context, Service, ServiceBroker, ServiceSchema } from 'moleculer' import GoogleServices from '../mixins/google.mixin' import { FeedResponse, FeedResult } from '../types/feed' import { ApiMeta } from '../types/meta' export default class YoutubeService extends Service { private google = new GoogleServices().google private channels: [channel: string, id: string][] = [ ['Red Plateaus', 'UCsln1E-ttrNPsMivrnf9V7w'], ['Zoe Baker', 'UC3FD64RRsrCLpiZNkq7ZkSg'], ['Jonas Ceika,', 'UCSkzHxIcfoEr69MWBdo0ppg'], ['Radical Reviewer', 'UC_V9wKk1Dd2rpZ4fxj7pKXA'], ['donoteat01', 'UCFdazs-6CNzSVv1J0a-qy4A'], ['Contra', 'UCNvsIonJdJ5E4EXMa65VYpA'], ['Shaun', 'UCJ6o36XL0CpYb6U5dNBiXHQ'], ['hbomb', 'UClt01z1wHHT7c5lKcU8pxRQ'], ['Philo tube', 'UC2PA-AKmVpU6NKCGtZq_rKQ'], ['anark', 'UC1CjJYTUeor8EUFsbgwu5TQ'] ] // @ts-ignore public constructor (public broker: ServiceBroker, schema: ServiceSchema<{}> = {}) { super(broker) this.parseServiceSchema(Service.mergeSchemas({ name: 'youtube', actions: { /** * Get aggregate feed * */ feed: { cache: true, rest: { method: 'GET', path: '/feed', }, async handler (this: YoutubeService, ctx: Context<{}, ApiMeta>): Promise { return this.GetAggregatedFeed() } } } }, schema)) } public async GetAggregatedFeed (): Promise { const onlyVideos = (item: youtube_v3.Schema$Activity) => item.snippet.type === 'upload' return (await Promise.all( this.channels.map(([channel, id]) => this.GetActivities(id)) )) .flatMap(response => response.data.items) .filter(onlyVideos) .map(item => this.PickActivityProperties(item)) } private GetActivities (channelId: string) { return this.google.youtube('v3').activities.list({ channelId, part: ['snippet', 'contentDetails'], maxResults: 1000 }) } private PickBestThumbnail (thumbnails: youtube_v3.Schema$ThumbnailDetails) { return String(Object.values(thumbnails).sort((a, b) => b.width - a.width)[0].url).split('/').pop() /* https://i.ytimg.com/vi/${id}/${thumbnail} */ } private PickActivityProperties (activity: youtube_v3.Schema$Activity): FeedResult { return { title: activity.snippet.title, id: activity.contentDetails.upload.videoId, description: activity.snippet.description?.substring(0, 127).split('\n')[0], thumbnail: this.PickBestThumbnail(activity.snippet.thumbnails), channel: activity.snippet.channelId, date: new Date(activity.snippet.publishedAt).valueOf() } } }