Improve playlists feature

- 'playlist item' -> 'playlist media'
- improve search
- handle multiple matching media
This commit is contained in:
KaKi87 2024-01-28 23:49:23 +01:00
parent d8ee08f7bb
commit 7006d52b6f

62
main.js
View file

@ -51,13 +51,15 @@ const
} }
}, },
setConfig = async (id, config) => await writeFile(`./data/${id}.json`, JSON.stringify(config)), setConfig = async (id, config) => await writeFile(`./data/${id}.json`, JSON.stringify(config)),
parseMediaPath = path => { parseMediaUrl = url => {
const title = path const
.slice(path.lastIndexOf('/') + 1, path.lastIndexOf('.')) pathname = decodeURI(new URL(url).pathname),
.replace(/[\s\-._()&+\[\],]/g, ' ') title = pathname
.replace(/\s+/g, ' '); .slice(pathname.lastIndexOf('/') + 1, pathname.lastIndexOf('.'))
.replace(/[\s\-._()&+\[\],]/g, ' ')
.replace(/\s+/g, ' ');
return { return {
path, url,
title, title,
keywords: title.toLowerCase().split(' ') keywords: title.toLowerCase().split(' ')
}; };
@ -145,8 +147,8 @@ const
.alias('pl') .alias('pl')
.description('Manage playlists & play on MPV') .description('Manage playlists & play on MPV')
.argument('[name]', 'Playlist name') .argument('[name]', 'Playlist name')
.argument('[item]', 'Playlist item index/name/partial name') .argument('[media]', 'Playlist media index/title/partial title')
.action(async (name, item) => { .action(async (name, media) => {
const const
config = await getConfig(authorID) || {}, config = await getConfig(authorID) || {},
newPlaylistUrl = attachments[0]?.url; newPlaylistUrl = attachments[0]?.url;
@ -184,31 +186,35 @@ const
if(/\.m3u8?$/i.test(playlistPathname)){ if(/\.m3u8?$/i.test(playlistPathname)){
if(!rawPlaylistData.startsWith('#EXTM3U')) if(!rawPlaylistData.startsWith('#EXTM3U'))
rawPlaylistData = `#EXTM3U\n${rawPlaylistData}`; rawPlaylistData = `#EXTM3U\n${rawPlaylistData}`;
playlistItems = M3uParser.parse(rawPlaylistData).medias.map(item => ({ playlistItems = M3uParser.parse(rawPlaylistData).medias.map(item => parseMediaUrl(item['location']));
url: item['location'],
title: item['name'] || new URL(item['location']).pathname.split('/').slice(-1)[0]
}));
} }
if(/\.xspf?$/i.test(playlistPathname)){ if(/\.xspf?$/i.test(playlistPathname))
playlistItems = parseXspf(rawPlaylistData)['playlist']['tracks'].map(item => ({ playlistItems = parseXspf(rawPlaylistData)['playlist']['tracks'].map(item => parseMediaUrl(item['location']));
url: item['location'], if(!media)
title: item['title'] || new URL(item['location']).pathname.split('/').slice(-1)[0]
}));
}
if(!item)
return response = { return response = {
output: outdent ` output: outdent `
📀 ${playlist.name} 📀 ${playlist.name}
${playlistItems.map((item, index) => `${index + 1}. \`${item.title}\``).join('\n')} ${playlistItems.map((item, index) => `${index + 1}. \`${item.title}\``).join('\n')}
` `
}; };
const playlistItem = /^\d+$/.test(item) const
? playlistItems[parseInt(item) - 1] isIndex = /^\d+$/.test(media),
: playlistItems.find(({ title }) => title.toLowerCase().includes(item.toLowerCase())); keywords = isIndex ? undefined : media.toLowerCase().split(' '),
if(!playlistItem) matchingPlaylistItems = isIndex
return response = { embed: { title: `❌ Item not found` } }; ? [playlistItems[parseInt(media) - 1]]
await adb(`am start -a android.intent.action.VIEW -d ${playlistItem.url} -t video/any is.xyz.mpv`); : playlistItems.filter(item => keywords.every(keyword => item.keywords.includes(keyword)));
return response = { embed: { title: `▶️ \`${playlistItem.title}\`` } }; if(matchingPlaylistItems.length === 0)
return response = { embed: { title: `❌ Media not found` } };
if(matchingPlaylistItems.length > 1)
return response = {
output: outdent `
🔎 Multiple media found :
${matchingPlaylistItems.map(item => `${playlistItems.indexOf(item) + 1}\\. \`${item.title}\``).join('\n')}
`
};
const [matchingPlaylistItem] = matchingPlaylistItems;
await adb(`am start -a android.intent.action.VIEW -d ${matchingPlaylistItem.url} -t video/any is.xyz.mpv`);
return response = { embed: { title: `▶️ \`${matchingPlaylistItem.title}\`` } };
}); });
program program
.command('playlist.rm') .command('playlist.rm')
@ -232,7 +238,7 @@ const
.description('List & play local media') .description('List & play local media')
.argument('[media]', 'Media title/partial title') .argument('[media]', 'Media title/partial title')
.action(async title => { .action(async title => {
const mediaList = (await adb(`find ${localMediaRootPath} -iname "*.mkv" -o -iname "*.mp4"`)).split('\n').map(parseMediaPath); const mediaList = (await adb(`find ${localMediaRootPath} -iname "*.mkv" -o -iname "*.mp4"`)).split('\n').map(path => parseMediaUrl(`file://${path}`));
if(!title) if(!title)
return response = { return response = {
output: outdent ` output: outdent `
@ -253,7 +259,7 @@ const
` `
}; };
const [matchingMedia] = matchingMediaList; const [matchingMedia] = matchingMediaList;
await adb(`am start -a android.intent.action.VIEW -n com.android.gallery3d/.app.MovieActivity -d "${matchingMedia.path}" -e MediaPlayerType 2`); await adb(`am start -a android.intent.action.VIEW -n com.android.gallery3d/.app.MovieActivity -d "${matchingMedia.url}" -e MediaPlayerType 2`);
return response = { embed: { title: `▶️ \`${matchingMedia.title}\`` } }; return response = { embed: { title: `▶️ \`${matchingMedia.title}\`` } };
}); });
program program