Getting ffprobe data from TorrServer API (#1628)

* Minor improvements

* Update posting_tpl.tpl

* Updated

* Update TorrServerAPI.php

* Update TorrServerAPI.php

* Updated

* Updated

* Updated

* Update playback_m3u.php

* Update init_bb.php

* Updated

* Update playback_m3u.php

* Update displaying_torrent.php

* Updated

* Update playback_m3u.tpl

* Update TorrServerAPI.php

* Update TorrServerAPI.php

* Updated

* Update playback_m3u.php

* Update playback_m3u.php

* Update playback_m3u.php

* Updated

* Updated

* Update main.php

* Update main.php

* Update main.php

* Update main.php

* Update playback_m3u.php

* Updated

* Updated

* Update playback_m3u.php

* Update playback_m3u.tpl

* Update playback_m3u.php

* Updated

* Update playback_m3u.php

* Updated

* Update playback_m3u.php

* Update playback_m3u.tpl

* Updated

* Update playback_m3u.php

* Update playback_m3u.tpl

* Updated

* Updated

* Update playback_m3u.php

* Update playback_m3u.php

* Update playback_m3u.php

* Update playback_m3u.php

* Update playback_m3u.php

* Update playback_m3u.php

* Updated

* Updated

* Update TorrServerAPI.php

* Revert "Update TorrServerAPI.php"

This reverts commit 9726d0d019.

* Update Ajax.php

* Updated

* Update playback_m3u.tpl

* Update playback_m3u.tpl

* Update playback_m3u.tpl

* Update playback_m3u.php

* Updated

* Updated

* Updated

* Updated

* Update playback_m3u.tpl

* Updated

* Updated

* Revert "Updated"

This reverts commit 5431f1fa51.

* Reapply "Updated"

This reverts commit 61c49dba62.

* Updated

* Update playback_m3u.tpl

* Update TorrServerAPI.php

* Updated

* Update playback_m3u.tpl

* Updated

* Update playback_m3u.php

* Update playback_m3u.tpl

* Update playback_m3u.tpl

* Update playback_m3u.php

* Updated

* Updated

* Update CHANGELOG.md

* Update CHANGELOG.md

* Update Ajax.php

* Update ffprobe_info.php

* Update ffprobe_info.php

* Update ffprobe_info.php

* Update TorrServerAPI.php

* Update CHANGELOG.md
This commit is contained in:
Roman Kelesidis 2024-09-01 00:25:38 +07:00 committed by GitHub
commit 383fa7f9b6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 279 additions and 23 deletions

View file

@ -9,7 +9,7 @@
- [CLI] TorrentPier installer ☕️ [\#1576](https://github.com/torrentpier/torrentpier/pull/1576), [\#1582](https://github.com/torrentpier/torrentpier/pull/1582), [\#1585](https://github.com/torrentpier/torrentpier/pull/1585), [\#1591](https://github.com/torrentpier/torrentpier/pull/1591) ([belomaxorka](https://github.com/belomaxorka)) - [CLI] TorrentPier installer ☕️ [\#1576](https://github.com/torrentpier/torrentpier/pull/1576), [\#1582](https://github.com/torrentpier/torrentpier/pull/1582), [\#1585](https://github.com/torrentpier/torrentpier/pull/1585), [\#1591](https://github.com/torrentpier/torrentpier/pull/1591) ([belomaxorka](https://github.com/belomaxorka))
- Added some new HTML meta-tags [\#1562](https://github.com/torrentpier/torrentpier/pull/1562) ([belomaxorka](https://github.com/belomaxorka)) - Added some new HTML meta-tags [\#1562](https://github.com/torrentpier/torrentpier/pull/1562) ([belomaxorka](https://github.com/belomaxorka))
- Added robots meta-tag support 🤖 [\#1587](https://github.com/torrentpier/torrentpier/pull/1587) ([belomaxorka](https://github.com/belomaxorka)) - Added robots meta-tag support 🤖 [\#1587](https://github.com/torrentpier/torrentpier/pull/1587) ([belomaxorka](https://github.com/belomaxorka))
- Added [TorrServer](https://github.com/YouROK/TorrServer) instance support! 🎞 [\#1603](https://github.com/torrentpier/torrentpier/pull/1603), [\#1623](https://github.com/torrentpier/torrentpier/pull/1623), [\#1624](https://github.com/torrentpier/torrentpier/pull/1624) ([belomaxorka](https://github.com/belomaxorka)) - Added [TorrServer](https://github.com/YouROK/TorrServer) instance support! 🎞 [\#1603](https://github.com/torrentpier/torrentpier/pull/1603), [\#1623](https://github.com/torrentpier/torrentpier/pull/1623), [\#1624](https://github.com/torrentpier/torrentpier/pull/1624), [\#1628](https://github.com/torrentpier/torrentpier/pull/1628) ([belomaxorka](https://github.com/belomaxorka))
- Newtopic: Added configuring robots indexing [\#1599](https://github.com/torrentpier/torrentpier/pull/1599) ([belomaxorka](https://github.com/belomaxorka)) - Newtopic: Added configuring robots indexing [\#1599](https://github.com/torrentpier/torrentpier/pull/1599) ([belomaxorka](https://github.com/belomaxorka))
- Added showing releaser stats in profile [\#1568](https://github.com/torrentpier/torrentpier/pull/1568) ([belomaxorka](https://github.com/belomaxorka)) - Added showing releaser stats in profile [\#1568](https://github.com/torrentpier/torrentpier/pull/1568) ([belomaxorka](https://github.com/belomaxorka))
- Improved `filelist.php` [\#1586](https://github.com/torrentpier/torrentpier/pull/1586) ([belomaxorka](https://github.com/belomaxorka)) - Improved `filelist.php` [\#1586](https://github.com/torrentpier/torrentpier/pull/1586) ([belomaxorka](https://github.com/belomaxorka))
@ -20,7 +20,7 @@
- Increased `USEREMAIL_MAX_LENGTH` [\#1566](https://github.com/torrentpier/torrentpier/pull/1566) ([belomaxorka](https://github.com/belomaxorka)) - Increased `USEREMAIL_MAX_LENGTH` [\#1566](https://github.com/torrentpier/torrentpier/pull/1566) ([belomaxorka](https://github.com/belomaxorka))
- Minor improvements [\#1570](https://github.com/torrentpier/torrentpier/pull/1570), [\#1571](https://github.com/torrentpier/torrentpier/pull/1571), [\#1575](https://github.com/torrentpier/torrentpier/pull/1575), [\#1589](https://github.com/torrentpier/torrentpier/pull/1589), [\#1592](https://github.com/torrentpier/torrentpier/pull/1592), [\#1605](https://github.com/torrentpier/torrentpier/pull/1605), [\#1611](https://github.com/torrentpier/torrentpier/pull/1611), [\#1612](https://github.com/torrentpier/torrentpier/pull/1612), [\#1615](https://github.com/torrentpier/torrentpier/pull/1615), [\#1627](https://github.com/torrentpier/torrentpier/pull/1627) ([belomaxorka](https://github.com/belomaxorka)) - Minor improvements [\#1570](https://github.com/torrentpier/torrentpier/pull/1570), [\#1571](https://github.com/torrentpier/torrentpier/pull/1571), [\#1575](https://github.com/torrentpier/torrentpier/pull/1575), [\#1589](https://github.com/torrentpier/torrentpier/pull/1589), [\#1592](https://github.com/torrentpier/torrentpier/pull/1592), [\#1605](https://github.com/torrentpier/torrentpier/pull/1605), [\#1611](https://github.com/torrentpier/torrentpier/pull/1611), [\#1612](https://github.com/torrentpier/torrentpier/pull/1612), [\#1615](https://github.com/torrentpier/torrentpier/pull/1615), [\#1627](https://github.com/torrentpier/torrentpier/pull/1627) ([belomaxorka](https://github.com/belomaxorka))
- Updated deps [\#1563](https://github.com/torrentpier/torrentpier/pull/1563), [\#1564](https://github.com/torrentpier/torrentpier/pull/1564), [\#1608](https://github.com/torrentpier/torrentpier/pull/1608), [\#1609](https://github.com/torrentpier/torrentpier/pull/1609), [\#1610](https://github.com/torrentpier/torrentpier/pull/1610) ([belomaxorka](https://github.com/belomaxorka)) - Updated deps [\#1563](https://github.com/torrentpier/torrentpier/pull/1563), [\#1564](https://github.com/torrentpier/torrentpier/pull/1564), [\#1608](https://github.com/torrentpier/torrentpier/pull/1608), [\#1609](https://github.com/torrentpier/torrentpier/pull/1609), [\#1610](https://github.com/torrentpier/torrentpier/pull/1610) ([belomaxorka](https://github.com/belomaxorka))
- New Crowdin updates [\#1569](https://github.com/torrentpier/torrentpier/pull/1569), [\#1572](https://github.com/torrentpier/torrentpier/pull/1572), [\#1573](https://github.com/torrentpier/torrentpier/pull/1573), [\#1574](https://github.com/torrentpier/torrentpier/pull/1574), [\#1588](https://github.com/torrentpier/torrentpier/pull/1588), [\#1590](https://github.com/torrentpier/torrentpier/pull/1590), [\#1600](https://github.com/torrentpier/torrentpier/pull/1600), [\#1601](https://github.com/torrentpier/torrentpier/pull/1601), [\#1606](https://github.com/torrentpier/torrentpier/pull/1606), [\#1607](https://github.com/torrentpier/torrentpier/pull/1607), [\#1625](https://github.com/torrentpier/torrentpier/pull/1625), [\#1626](https://github.com/torrentpier/torrentpier/pull/1626), [\#1629](https://github.com/torrentpier/torrentpier/pull/1629) ([Exileum](https://github.com/Exileum)) - New Crowdin updates [\#1569](https://github.com/torrentpier/torrentpier/pull/1569), [\#1572](https://github.com/torrentpier/torrentpier/pull/1572), [\#1573](https://github.com/torrentpier/torrentpier/pull/1573), [\#1574](https://github.com/torrentpier/torrentpier/pull/1574), [\#1588](https://github.com/torrentpier/torrentpier/pull/1588), [\#1590](https://github.com/torrentpier/torrentpier/pull/1590), [\#1600](https://github.com/torrentpier/torrentpier/pull/1600), [\#1601](https://github.com/torrentpier/torrentpier/pull/1601), [\#1606](https://github.com/torrentpier/torrentpier/pull/1606), [\#1607](https://github.com/torrentpier/torrentpier/pull/1607), [\#1625](https://github.com/torrentpier/torrentpier/pull/1625), [\#1626](https://github.com/torrentpier/torrentpier/pull/1626), [\#1629](https://github.com/torrentpier/torrentpier/pull/1629), [\#1630](https://github.com/torrentpier/torrentpier/pull/1630) ([Exileum](https://github.com/Exileum))
## [v2.4.4](https://github.com/torrentpier/torrentpier/tree/v2.4.4) (2024-07-22) ## [v2.4.4](https://github.com/torrentpier/torrentpier/tree/v2.4.4) (2024-07-22)
[Full Changelog](https://github.com/torrentpier/torrentpier/compare/v2.4.3...v2.4.4) [Full Changelog](https://github.com/torrentpier/torrentpier/compare/v2.4.3...v2.4.4)

View file

@ -15,12 +15,12 @@ require __DIR__ . '/common.php';
$user->session_start(); $user->session_start();
if ($bb_cfg['bt_disable_dht'] && IS_GUEST) { if ($bb_cfg['bt_disable_dht'] && IS_GUEST) {
bb_simple_die($lang['BT_PRIVATE_TRACKER'], 403); bb_die($lang['BT_PRIVATE_TRACKER'], 403);
} }
$topic_id = isset($_GET[POST_TOPIC_URL]) ? (int)$_GET[POST_TOPIC_URL] : 0; $topic_id = isset($_GET[POST_TOPIC_URL]) ? (int)$_GET[POST_TOPIC_URL] : 0;
if (!$topic_id) { if (!$topic_id) {
bb_simple_die($lang['INVALID_TOPIC_ID'], 404); bb_die($lang['INVALID_TOPIC_ID'], 404);
} }
$sql = 'SELECT t.attach_id, t.info_hash, t.info_hash_v2, t.size, ad.physical_filename $sql = 'SELECT t.attach_id, t.info_hash, t.info_hash_v2, t.size, ad.physical_filename
@ -31,7 +31,7 @@ $sql = 'SELECT t.attach_id, t.info_hash, t.info_hash_v2, t.size, ad.physical_fil
LIMIT 1'; LIMIT 1';
if (!$row = DB()->fetch_row($sql)) { if (!$row = DB()->fetch_row($sql)) {
bb_simple_die($lang['INVALID_TOPIC_ID_DB'], 404); bb_die($lang['INVALID_TOPIC_ID_DB'], 404);
} }
// Protocol meta // Protocol meta
@ -45,7 +45,7 @@ $t_hash_field = $meta_v2 ? 'piecesRoot' : 'sha1';
$file_path = get_attachments_dir() . '/' . $row['physical_filename']; $file_path = get_attachments_dir() . '/' . $row['physical_filename'];
if (!is_file($file_path)) { if (!is_file($file_path)) {
bb_simple_die($lang['TOR_NOT_FOUND'], 410); bb_die($lang['TOR_NOT_FOUND'], 410);
} }
$file_contents = file_get_contents($file_path); $file_contents = file_get_contents($file_path);
@ -60,18 +60,18 @@ if ($bb_cfg['flist_max_files']) {
} }
if ($file_count > $bb_cfg['flist_max_files']) { if ($file_count > $bb_cfg['flist_max_files']) {
bb_simple_die(sprintf($lang['BT_FLIST_LIMIT'], $bb_cfg['flist_max_files'], $file_count), 410); bb_die(sprintf($lang['BT_FLIST_LIMIT'], $bb_cfg['flist_max_files'], $file_count), 410);
} }
} }
try { try {
$torrent = \Arokettu\Torrent\TorrentFile::loadFromString($file_contents); $torrent = \Arokettu\Torrent\TorrentFile::loadFromString($file_contents);
} catch (\Exception $e) { } catch (\Exception $e) {
bb_simple_die(htmlCHR("{$lang['TORFILE_INVALID']}: {$e->getMessage()}"), 410); bb_die(htmlCHR("{$lang['TORFILE_INVALID']}: {$e->getMessage()}"), 410);
} }
if (IS_GUEST && $torrent->isPrivate()) { if (IS_GUEST && $torrent->isPrivate()) {
bb_simple_die($lang['BT_PRIVATE_TORRENT'], 403); bb_die($lang['BT_PRIVATE_TORRENT'], 403);
} }
$files = $torrent->$t_version_field()->$t_files_field(); $files = $torrent->$t_version_field()->$t_files_field();

View file

@ -0,0 +1,106 @@
<?php
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
if (!defined('IN_AJAX')) {
die(basename(__FILE__));
}
global $bb_cfg, $lang;
if (!$bb_cfg['torr_server']['enabled']) {
$this->ajax_die($lang['MODULE_OFF']);
}
if (!$attach_id = (int)$this->request['attach_id'] or !is_numeric($attach_id)) {
$this->ajax_die($lang['INVALID_ATTACH_ID']);
}
if (!$file_index = (int)$this->request['file_index'] or !is_numeric($file_index)) {
$this->ajax_die("Invalid file index: $file_index");
}
if (!$info_hash = (string)$this->request['info_hash'] or !ctype_xdigit($info_hash)) {
$this->ajax_die("Invalid info_hash: $info_hash");
}
$isAudio = !empty($this->request['is_audio']);
// Get ffprobe info from TorrServer
$ffpInfo = (new \TorrentPier\TorrServerAPI())->getFfpInfo($info_hash, $file_index, $attach_id);
$ffpInfo = $ffpInfo->{$file_index};
if (isset($ffpInfo->streams)) {
// Video codec information
$videoCodecIndex = array_search('video', array_column($ffpInfo->streams, 'codec_type'));
if (is_int($videoCodecIndex)) {
$videoCodecInfo = $ffpInfo->streams[$videoCodecIndex];
}
// Audio codec information
$audioTracks = array_filter($ffpInfo->streams, function ($e) {
return $e->codec_type === 'audio';
});
// Audio tracks information
$audioDub = array_map(function ($stream) {
global $lang;
$result = '<span class="warnColor2">' . sprintf($lang['AUDIO_TRACK'], (!isset($stream->index) || $stream->index === 0) ? 1 : $stream->index) . '</span><br>';
if (isset($stream->tags->language)) {
if (isset($stream->tags->title)) {
$result .= '<b>' . mb_strtoupper($stream->tags->language, 'UTF-8') . ' (' . $stream->tags->title . ')' . '</b>';
} else {
$result .= '<b>' . mb_strtoupper($stream->tags->language, 'UTF-8') . '</b>';
}
$result .= '<br>';
}
if (!empty($stream->codec_name)) {
$result .= sprintf($lang['AUDIO_CODEC'], $stream->codec_long_name, mb_strtoupper($stream->codec_name, 'UTF-8')) . '<br>';
}
if (!empty($stream->bit_rate)) {
$result .= sprintf($lang['BITRATE'], humn_bitrate($stream->bit_rate)) . '<br>';
}
if (!empty($stream->sample_rate)) {
$result .= sprintf($lang['SAMPLE_RATE'], $stream->sample_rate) . '<br>';
}
if (!empty($stream->channels)) {
$result .= sprintf($lang['CHANNELS'], $stream->channels) . '<br>';
}
if (!empty($stream->channel_layout)) {
$result .= sprintf($lang['CHANNELS_LAYOUT'], $stream->channel_layout);
}
return $result;
}, $audioTracks);
// Generate output data
$data = [
'filesize' => sprintf($lang['FILESIZE'] . ': <b>%s</b>', humn_size($ffpInfo->format->size)),
'resolution' => (!$isAudio && isset($videoCodecInfo)) ? sprintf($lang['RESOLUTION'], $videoCodecInfo->width . 'x' . $videoCodecInfo->height) : '',
'video_codec' => (!$isAudio && isset($videoCodecInfo->codec_name)) ? sprintf($lang['VIDEO_CODEC'], $videoCodecInfo->codec_long_name, mb_strtoupper($videoCodecInfo->codec_name, 'UTF-8')) : '',
'audio_dub' => implode('<hr>', $audioDub)
];
// Validate output data
$result = '<hr>';
if (!empty($data['resolution'])) {
$result .= $data['resolution'] . '<br>';
}
if (!empty($data['filesize'])) {
$result .= $data['filesize'] . '<br>';
}
if (!empty($data['video_codec'])) {
$result .= $data['video_codec'];
}
if (!empty($data['audio_dub'])) {
$result .= '<hr>' . $data['audio_dub'];
}
$this->response['ffprobe_data'] = $result;
}
$this->response['file_index'] = $file_index;

View file

@ -226,7 +226,7 @@ if ($tor_reged && $tor_info) {
// TorrServer integration // TorrServer integration
if ($bb_cfg['torr_server']['enabled'] && (!IS_GUEST || !$bb_cfg['torr_server']['disable_for_guest']) && (new \TorrentPier\TorrServerAPI())->getM3UPath($attach_id)) { if ($bb_cfg['torr_server']['enabled'] && (!IS_GUEST || !$bb_cfg['torr_server']['disable_for_guest']) && (new \TorrentPier\TorrServerAPI())->getM3UPath($attach_id)) {
$template->assign_block_vars('postrow.attach.tor_reged.tor_server', [ $template->assign_block_vars('postrow.attach.tor_reged.tor_server', [
'TORR_SERVER_M3U_LINK' => PLAYBACK_M3U_URL . $attach_id, 'TORR_SERVER_M3U_LINK' => PLAYBACK_M3U_URL . $bt_topic_id,
'TORR_SERVER_M3U_ICON' => $images['icon_tor_m3u_icon'], 'TORR_SERVER_M3U_ICON' => $images['icon_tor_m3u_icon'],
]); ]);
} }

View file

@ -595,6 +595,29 @@ function humn_size($size, $rounder = null, $min = null, $space = '&nbsp;')
return round($size, $rounder) . $space . $ext; return round($size, $rounder) . $space . $ext;
} }
/**
* Bitrate to human-readable format
*
* @param int $bitrate
* @param string $space
* @return string
*/
function humn_bitrate(int $bitrate, string $space = '&nbsp;'): string
{
if ($bitrate >= 1000000) {
$unit = 'Mbps';
$bitrate /= 1000000;
} elseif ($bitrate >= 1000) {
$unit = 'kbps';
$bitrate /= 1000;
} else {
$unit = 'bps';
}
$formattedBitrate = number_format($bitrate, 2);
return $formattedBitrate . $space . $unit;
}
function bt_show_ip($ip, $port = '') function bt_show_ip($ip, $port = '')
{ {
global $bb_cfg; global $bb_cfg;

View file

@ -302,7 +302,7 @@ define('PROFILE_URL', 'profile.php?mode=viewprofile&amp;' . POST_USERS_URL . '='
define('BONUS_URL', 'profile.php?mode=bonus'); define('BONUS_URL', 'profile.php?mode=bonus');
define('TOPIC_URL', 'viewtopic.php?' . POST_TOPIC_URL . '='); define('TOPIC_URL', 'viewtopic.php?' . POST_TOPIC_URL . '=');
define('FILELIST_URL', 'filelist.php?' . POST_TOPIC_URL . '='); define('FILELIST_URL', 'filelist.php?' . POST_TOPIC_URL . '=');
define('PLAYBACK_M3U_URL', 'playback_m3u.php?attach_id='); define('PLAYBACK_M3U_URL', 'playback_m3u.php?' . POST_TOPIC_URL . '=');
define('USER_AGENT', strtolower($_SERVER['HTTP_USER_AGENT'])); define('USER_AGENT', strtolower($_SERVER['HTTP_USER_AGENT']));

View file

@ -64,6 +64,8 @@ $lang['CLEAR'] = 'Clear';
$lang['MOVE_TO_TOP'] = 'Move to top'; $lang['MOVE_TO_TOP'] = 'Move to top';
$lang['UNKNOWN'] = 'Unknown'; $lang['UNKNOWN'] = 'Unknown';
$lang['COPY_TO_CLIPBOARD'] = 'Copy to clipboard'; $lang['COPY_TO_CLIPBOARD'] = 'Copy to clipboard';
$lang['NO_ITEMS'] = 'There seems to be no data here...';
$lang['PLEASE_TRY_AGAIN'] = 'Please try again after few seconds...';
$lang['NEXT_PAGE'] = 'Next'; $lang['NEXT_PAGE'] = 'Next';
$lang['PREVIOUS_PAGE'] = 'Previous'; $lang['PREVIOUS_PAGE'] = 'Previous';
@ -1268,9 +1270,20 @@ $lang['DOWNLOAD'] = 'Download'; // this Language Variable is defined in admin.ph
$lang['FILESIZE'] = 'Filesize'; $lang['FILESIZE'] = 'Filesize';
$lang['VIEWED'] = 'Viewed'; $lang['VIEWED'] = 'Viewed';
$lang['EXTENSION_DISABLED_AFTER_POSTING'] = 'The Extension \'%s\' was deactivated by an board admin, therefore this Attachment is not displayed.'; // used in Posts and PM's, replace %s with mime type $lang['EXTENSION_DISABLED_AFTER_POSTING'] = 'The Extension \'%s\' was deactivated by an board admin, therefore this Attachment is not displayed.'; // used in Posts and PM's, replace %s with mime type
// Viewtopic -> Display of Attachments -> TorrServer integration
$lang['STREAM'] = 'Stream';
$lang['RESOLUTION'] = 'Resolution: <b>%s</b>';
$lang['CHANNELS'] = 'Channels: <b>%s</b>';
$lang['CHANNELS_LAYOUT'] = 'Channels layout: <b>%s</b>';
$lang['BITRATE'] = 'Bitrate: <b>%s</b>';
$lang['SAMPLE_RATE'] = 'Sample rate: <b>%s</b>';
$lang['AUDIO_TRACK'] = 'Audio track information (%d):';
$lang['AUDIO_CODEC'] = 'Audio codec: <b title="%s">%s</b>';
$lang['VIDEO_CODEC'] = 'Video codec: <b title="%s">%s</b>';
$lang['SHOW_MORE_INFORMATION_FILE'] = 'Show more information about file';
$lang['DOWNLOAD_M3U_FILE'] = 'Download .m3u file'; $lang['DOWNLOAD_M3U_FILE'] = 'Download .m3u file';
$lang['PLAYBACK_M3U'] = 'Playback .m3u file'; $lang['PLAYBACK_M3U'] = 'Playback .m3u file';
$lang['STREAM'] = 'Stream';
$lang['COPY_STREAM_LINK'] = 'Copy stream link to clipboard'; $lang['COPY_STREAM_LINK'] = 'Copy stream link to clipboard';
$lang['M3U_NOT_SUPPORTED'] = 'This file cannot be played in the browser...'; $lang['M3U_NOT_SUPPORTED'] = 'This file cannot be played in the browser...';
$lang['M3U_NOTICE'] = 'Some browsers do not support playback of certain video formats. In such a case, you can download the .m3u file and play it using a third-party player'; $lang['M3U_NOTICE'] = 'Some browsers do not support playback of certain video formats. In such a case, you can download the .m3u file and play it using a third-party player';

View file

@ -18,7 +18,7 @@ if (!$bb_cfg['torr_server']['enabled']) {
// Valid file formats // Valid file formats
$validFormats = [ $validFormats = [
'audio' => ['mp3', 'flac', 'wav'], 'audio' => ['mp3', 'flac', 'wav'],
'video' => ['mp4', 'mkv', 'avi'] 'video' => ['mp4', 'mkv', 'avi', 'm4v']
]; ];
// Start session management // Start session management
@ -27,13 +27,24 @@ $user->session_start(['req_login' => $bb_cfg['torr_server']['disable_for_guest']
// Disable robots indexing // Disable robots indexing
$page_cfg['allow_robots'] = false; $page_cfg['allow_robots'] = false;
// Check attach_id // Check topic_id
if (!$attach_id = request_var('attach_id', 0)) { $topic_id = isset($_GET[POST_TOPIC_URL]) ? (int)$_GET[POST_TOPIC_URL] : 0;
bb_die($lang['INVALID_ATTACH_ID']); if (!$topic_id) {
bb_die($lang['INVALID_TOPIC_ID'], 404);
}
// Getting torrent info from database
$sql = 'SELECT attach_id, info_hash, info_hash_v2
FROM ' . BB_BT_TORRENTS . '
WHERE topic_id = ' . $topic_id . '
LIMIT 1';
if (!$row = DB()->fetch_row($sql)) {
bb_die($lang['INVALID_TOPIC_ID_DB'], 404);
} }
// Check m3u file exist // Check m3u file exist
if (!$m3uFile = (new \TorrentPier\TorrServerAPI())->getM3UPath($attach_id)) { if (!$m3uFile = (new \TorrentPier\TorrServerAPI())->getM3UPath($row['attach_id'])) {
bb_die($lang['ERROR_NO_ATTACHMENT']); bb_die($lang['ERROR_NO_ATTACHMENT']);
} }
@ -49,6 +60,7 @@ foreach ($m3uData as $entry) {
if (!filter_var($streamLink, FILTER_VALIDATE_URL)) { if (!filter_var($streamLink, FILTER_VALIDATE_URL)) {
continue; continue;
} }
parse_str(parse_url($streamLink, PHP_URL_QUERY), $urlParams);
// Parse tags // Parse tags
foreach ($entry->getExtTags() as $extTag) { foreach ($entry->getExtTags() as $extTag) {
@ -65,11 +77,16 @@ foreach ($m3uData as $entry) {
// Validate file extension // Validate file extension
$getExtension = pathinfo($title, PATHINFO_EXTENSION); $getExtension = pathinfo($title, PATHINFO_EXTENSION);
if ($getExtension === 'm3u') {
// Skip m3u files
continue;
}
$filesCount++; $filesCount++;
$rowClass = ($filesCount % 2) ? 'row1' : 'row2'; $rowClass = ($filesCount % 2) ? 'row1' : 'row2';
$template->assign_block_vars('m3ulist', [ $template->assign_block_vars('m3ulist', [
'ROW_NUMBER' => $filesCount, 'ROW_NUMBER' => $filesCount,
'FILE_INDEX' => $urlParams['index'],
'ROW_CLASS' => $rowClass, 'ROW_CLASS' => $rowClass,
'IS_VALID' => in_array($getExtension, array_merge($validFormats['audio'], $validFormats['video'])), 'IS_VALID' => in_array($getExtension, array_merge($validFormats['audio'], $validFormats['video'])),
'IS_AUDIO' => in_array($getExtension, $validFormats['audio']), 'IS_AUDIO' => in_array($getExtension, $validFormats['audio']),
@ -81,8 +98,12 @@ foreach ($m3uData as $entry) {
// Generate output // Generate output
$template->assign_vars([ $template->assign_vars([
'HAS_ITEMS' => $filesCount > 0,
'PAGE_TITLE' => $lang['PLAYBACK_M3U'], 'PAGE_TITLE' => $lang['PLAYBACK_M3U'],
'FILES_COUNT' => sprintf($lang['BT_FLIST_FILE_PATH'], declension($filesCount, 'files')), 'ATTACH_ID' => $row['attach_id'],
'INFO_HASH' => bin2hex($row['info_hash'] ?? $row['info_hash_v2']),
'FILES_COUNT_TITLE' => sprintf($lang['BT_FLIST_FILE_PATH'], declension($filesCount, 'files')),
'U_TOPIC' => TOPIC_URL . $topic_id,
]); ]);
print_page('playback_m3u.tpl'); print_page('playback_m3u.tpl');

View file

@ -41,6 +41,7 @@ class Ajax
'manage_group' => ['user'], 'manage_group' => ['user'],
'callseed' => ['user'], 'callseed' => ['user'],
'ffprobe_info' => ['guest'],
'thx' => ['guest'], 'thx' => ['guest'],
'view_post' => ['guest'], 'view_post' => ['guest'],
'view_torrent' => ['guest'], 'view_torrent' => ['guest'],
@ -526,9 +527,18 @@ class Ajax
* *
* @return void * @return void
*/ */
public function thx() public function thx()
{ {
require AJAX_DIR . '/thanks.php'; require AJAX_DIR . '/thanks.php';
} }
/**
* Get info from ffprobe (TorrServer API)
*
* @return void
*/
public function ffprobe_info()
{
require AJAX_DIR . '/ffprobe_info.php';
}
} }

View file

@ -12,6 +12,8 @@ namespace TorrentPier;
use Curl\Curl; use Curl\Curl;
use CURLFile; use CURLFile;
use stdClass;
/** /**
* Class TorrServerAPI * Class TorrServerAPI
* @package TorrentPier * @package TorrentPier
@ -33,7 +35,8 @@ class TorrServerAPI
private array $endpoints = [ private array $endpoints = [
'playlist' => 'playlist', 'playlist' => 'playlist',
'upload' => 'torrent/upload', 'upload' => 'torrent/upload',
'stream' => 'stream' 'stream' => 'stream',
'ffprobe' => 'ffp'
]; ];
/** /**
@ -175,6 +178,10 @@ class TorrServerAPI
*/ */
public function removeM3U(string|int $attach_id): bool public function removeM3U(string|int $attach_id): bool
{ {
// Remove ffprobe data from cache
CACHE('tr_cache')->rm("ffprobe_m3u_$attach_id");
// Unlink .m3u file
$m3uFile = get_attachments_dir() . '/' . self::M3U['prefix'] . $attach_id . self::M3U['extension']; $m3uFile = get_attachments_dir() . '/' . self::M3U['prefix'] . $attach_id . self::M3U['extension'];
if (is_file($m3uFile)) { if (is_file($m3uFile)) {
if (unlink($m3uFile)) { if (unlink($m3uFile)) {
@ -187,6 +194,49 @@ class TorrServerAPI
return false; return false;
} }
/**
* Returns info from TorrServer in-build ffprobe
*
* @param string $hash
* @param int $index
* @param int|string $attach_id
* @return mixed
*/
public function getFfpInfo(string $hash, int $index, int|string $attach_id): mixed
{
global $bb_cfg;
if (!$response = CACHE('tr_cache')->get("ffprobe_m3u_$attach_id")) {
$response = new stdClass();
}
if (!isset($response->{$index})) {
// Make stream call to store torrent in memory
for ($i = 0, $max_try = 3; $i <= $max_try; $i++) {
if ($this->getStream($hash)) {
break;
} elseif ($i == $max_try) {
return false;
}
}
$curl = new Curl();
$curl->setTimeout($bb_cfg['torr_server']['timeout']);
$curl->setHeader('Accept', 'application/json');
$curl->get($this->url . $this->endpoints['ffprobe'] . '/' . $hash . '/' . $index);
$response->{$index} = $curl->response;
if ($curl->httpStatusCode === 200 && !empty($response->{$index})) {
CACHE('tr_cache')->set("ffprobe_m3u_$attach_id", $response, 3600);
} else {
bb_log("TorrServer (ERROR) [$this->url]: Response code: {$curl->httpStatusCode}\n", $this->logFile);
}
$curl->close();
}
return $response;
}
/** /**
* Up stream * Up stream
* *

View file

@ -1,18 +1,43 @@
<h1 class="pagetitle">{PAGE_TITLE}</h1> <h1 class="pagetitle">{PAGE_TITLE}</h1>
<script type="text/javascript">
ajax.ffprobe_info = function (file_index, is_audio) {
ajax.exec({
action: 'ffprobe_info',
attach_id: {ATTACH_ID},
info_hash: '{INFO_HASH}',
file_index: file_index,
is_audio: is_audio
});
};
ajax.callback.ffprobe_info = function (data) {
if (data.ffprobe_data) {
$('#ffprobe_' + data.file_index).html(data.ffprobe_data);
} else {
$('#ffprobe_' + data.file_index).append('<hr><span class="warnColor2">{L_PLEASE_TRY_AGAIN}</span>');
}
}
</script>
<table class="forumline"> <table class="forumline">
<thead> <thead>
<tr> <tr>
<th>#</th> <th>#</th>
<th>{FILES_COUNT}</th> <th>{FILES_COUNT_TITLE}</th>
<th>{L_STREAM}</th> <th>{L_STREAM}</th>
</tr> </tr>
</thead> </thead>
<!-- IF HAS_ITEMS -->
<!-- BEGIN m3ulist --> <!-- BEGIN m3ulist -->
<tbody> <tbody>
<tr class="{m3ulist.ROW_CLASS} tCenter"> <tr class="{m3ulist.ROW_CLASS} tCenter">
<td>{m3ulist.ROW_NUMBER}</td> <td>{m3ulist.ROW_NUMBER}</td>
<td width="40%">{m3ulist.TITLE}</td> <td width="40%"><b>{m3ulist.TITLE}</b>
<div id="ffprobe_{m3ulist.FILE_INDEX}">
<hr>
<a href="#" onclick="ajax.ffprobe_info({m3ulist.FILE_INDEX}, '{m3ulist.IS_AUDIO}'); return false;">{L_SHOW_MORE_INFORMATION_FILE}</a>
</div>
</td>
<td> <td>
<a href="#" onclick="return false;" class="copyElement" data-clipboard-text="{m3ulist.STREAM_LINK}">{L_COPY_STREAM_LINK}</a>&nbsp;&middot; <a href="#" onclick="return false;" class="copyElement" data-clipboard-text="{m3ulist.STREAM_LINK}">{L_COPY_STREAM_LINK}</a>&nbsp;&middot;
<a target="_blank" href="{m3ulist.M3U_DL_LINK}">{L_DOWNLOAD_M3U_FILE}</a> <a target="_blank" href="{m3ulist.M3U_DL_LINK}">{L_DOWNLOAD_M3U_FILE}</a>
@ -26,6 +51,13 @@
</tr> </tr>
</tbody> </tbody>
<!-- END m3ulist --> <!-- END m3ulist -->
<!-- ELSE -->
<tbody>
<tr>
<td class="row1 tCenter pad_8" colspan="3">{L_NO_ITEMS}</td>
</tr>
</tbody>
<!-- ENDIF -->
<tfoot> <tfoot>
<tr> <tr>
<td class="catBottom warnColor1" colspan="4">{L_M3U_NOTICE}</td> <td class="catBottom warnColor1" colspan="4">{L_M3U_NOTICE}</td>
@ -36,6 +68,7 @@
<!--bottom_info--> <!--bottom_info-->
<div class="bottom_info"> <div class="bottom_info">
<div class="spacer_8"></div> <div class="spacer_8"></div>
<a href="{U_TOPIC}">{L_TOPIC_RETURN}</a>
<div id="timezone"> <div id="timezone">
<p>{CURRENT_TIME}</p> <p>{CURRENT_TIME}</p>
<p>{S_TIMEZONE}</p> <p>{S_TIMEZONE}</p>

View file

@ -4722,7 +4722,7 @@ $(function(){
<input type="button" value="Включить в этом форуме" class="bold" onclick="ajax.topic_tpl('assign', {tpl_id: $('#forum_tpl_select').val()})" /> &nbsp; <input type="button" value="Включить в этом форуме" class="bold" onclick="ajax.topic_tpl('assign', {tpl_id: $('#forum_tpl_select').val()})" /> &nbsp;
<input type="button" value="Загрузить" onclick="ajax.topic_tpl('load')" /> &nbsp; <input type="button" value="Загрузить" onclick="ajax.topic_tpl('load')" /> &nbsp;
<input type="button" value="{L_REMOVE}" onclick="ajax.topic_tpl('remove')" /> &nbsp; <input type="button" value="{L_REMOVE}" onclick="ajax.topic_tpl('remove')" /> &nbsp;
<!-- ELSE -->Нет щаблонов для релизов<!-- ENDIF --> <!-- ELSE -->Нет шаблонов для релизов<!-- ENDIF -->
<br /><br /> <br /><br />
<span class="gen"> <span class="gen">
<!-- IF NO_TPL_ASSIGNED --> <!-- IF NO_TPL_ASSIGNED -->