From 9f4970b3eea4206d4ea8d76e88d21390fe0791c2 Mon Sep 17 00:00:00 2001 From: "luan.lrt4@gmail.com" Date: Sat, 26 Mar 2022 05:33:49 -0300 Subject: [PATCH] refactor: separate protobuf stuff from utilities --- lib/Actions.js | 19 +++++----- lib/proto/index.js | 92 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 9 deletions(-) create mode 100644 lib/proto/index.js diff --git a/lib/Actions.js b/lib/Actions.js index 283a8794..4cf90371 100644 --- a/lib/Actions.js +++ b/lib/Actions.js @@ -2,7 +2,7 @@ const Uuid = require('uuid'); const Axios = require('axios'); -const Utils = require('./Utils'); +const Proto = require('./proto'); const Constants = require('./Constants'); /** @@ -32,7 +32,7 @@ async function engage(session, engagement_type, args = {}) { break; case 'comment/create_comment': data.commentText = args.text; - data.createCommentParams = Utils.encodeCommentParams(args.video_id); + data.createCommentParams = Proto.encodeCommentParams(args.video_id); break; default: } @@ -55,11 +55,11 @@ async function engage(session, engagement_type, args = {}) { * @returns {Promise.<{ success: boolean; status_code: number; data: object; message?: string }>} */ async function browse(session, action_type, args = {}) { - if (!session.logged_in && action_type != 'home_feed' && - action_type !== 'lyrics' && action_type !== 'music_playlist' && - action_type !== 'playlist') - throw new Error('You are not signed-in'); - + if (!session.logged_in && action_type != 'home_feed' + && action_type !== 'lyrics' && action_type !== 'music_playlist' + && action_type !== 'playlist') + throw new Error('You are not signed-in'); + const data = { context: session.context }; switch (action_type) { case 'account_notifications': @@ -88,6 +88,7 @@ async function browse(session, action_type, args = {}) { data.context = context; data.browseId = args.browse_id; break; + case 'channel': case 'playlist': data.browseId = args.browse_id; break; @@ -192,7 +193,7 @@ async function search(session, client, args = {}) { const data = { context: session.context }; switch (client) { case 'YOUTUBE': - data.params = Utils.encodeFilter(args.options.period, args.options.duration, args.options.order); + data.params = Proto.encodeSearchFilter(args.options.period, args.options.duration, args.options.order); data.query = args.query; break; case 'YTMUSIC': @@ -276,7 +277,7 @@ async function livechat(session, action_type, args = {}) { break; case 'live_chat/send_message': data.context = session.context; - data.params = Utils.encodeMessageParams(args.channel_id, args.video_id); + data.params = Proto.encodeMessageParams(args.channel_id, args.video_id); data.clientMessageId = `ytjs-${Uuid.v4()}`; data.richMessage = { textSegments: [{ text: args.text }] diff --git a/lib/proto/index.js b/lib/proto/index.js new file mode 100644 index 00000000..47ab888e --- /dev/null +++ b/lib/proto/index.js @@ -0,0 +1,92 @@ +'use strict'; + +const Fs = require('fs'); +const Proto = require('protons'); + +/** + * Encodes advanced search filters. + * + * @param {string} period - Period in which a video is uploaded: any | hour | day | week | month | year + * @param {string} duration - The duration of a video: any | short | long + * @param {string} order - The order of the search results: relevance | rating | age | views + * @returns {string} + */ +function encodeSearchFilter(period, duration, order) { + const youtube_proto = Proto(Fs.readFileSync(`${__dirname}/youtube.proto`)); + + const periods = { 'any': null, 'hour': 1, 'day': 2, 'week': 3, 'month': 4, 'year': 5 }; + const durations = { 'any': null, 'short': 1, 'long': 2 }; + const orders = { 'relevance': null, 'rating': 1, 'age': 2, 'views': 3 }; + + const search_filter_buff = youtube_proto.SearchFilter.encode({ + number: orders[order], + filter: { + param_0: periods[period], + param_1: (period == 'hour' && order == 'relevance') ? null : 1, + param_2: durations[duration] + } + }); + + return encodeURIComponent(Buffer.from(search_filter_buff).toString('base64')); +} + +/** + * Encodes livestream message parameters. + * + * @param {string} channel_id - The id of the channel hosting the livestream. + * @param {string} video_id - The id of the livestream. + * @returns {string} + */ +function encodeMessageParams(channel_id, video_id) { + const youtube_proto = Proto(Fs.readFileSync(`${__dirname}/youtube.proto`)); + + const buf = youtube_proto.LiveMessageParams.encode({ + params: { + ids: { channel_id, video_id } + }, + number_0: 1, + number_1: 4 + }); + + return Buffer.from(encodeURIComponent(Buffer.from(buf).toString('base64'))).toString('base64'); +} + +/** + * Encodes comment parameters. + * + * @param {string} video_id - The id of the video you're commenting on. + * @returns {string} + */ +function encodeCommentParams(video_id) { + const youtube_proto = Proto(Fs.readFileSync(`${__dirname}/youtube.proto`)); + + const buf = youtube_proto.CreateCommentParams.encode({ + video_id, + params: { index: 0 }, + number: 7 + }); + + return encodeURIComponent(Buffer.from(buf).toString('base64')); +} + +/** + * Encodes notification preferences. + * + * @param {string} channel_id - The id of the channel. + * @param {string} index - The index of the preference id. + * @returns {string} + */ +function encodeNotificationPref(channel_id, index) { + const youtube_proto = Proto(Fs.readFileSync(`${__dirname}/youtube.proto`)); + + const buf = youtube_proto.NotificationPreferences.encode({ + channel_id, + pref_id: { index }, + number_0: 0, + number_1: 4 + }); + + return encodeURIComponent(Buffer.from(buf).toString('base64')); +} + +module.exports = { encodeMessageParams, encodeCommentParams, encodeNotificationPref, encodeSearchFilter }; \ No newline at end of file