Refactored variable naming to prevent conflicts and added an option for default content handling.

This commit is contained in:
mm 2025-03-30 00:54:13 +08:00
parent e7cb832d5a
commit 99af4fcd67
5 changed files with 64 additions and 46 deletions

View file

@ -5,11 +5,12 @@ Usually used to handle cases where the content retrieved via XPath from an artic
To use it, upload this entire directory to the FreshRSS `./extensions` directory on your server and enable it on the extension panel in FreshRSS. To use it, upload this entire directory to the FreshRSS `./extensions` directory on your server and enable it on the extension panel in FreshRSS.
Note: If an XPath expression error causes content to not be found, return the entire webpage retrieved by cURL by default. Note: If an XPath expression error causes content to not found, The default behavior is not to modify the feed if no content is matched.
## Changelog ## Changelog
* 0.2.1 - The test can be used normally. * 0.2.1 - The test can be used normally.
* 0.2.2 - Add an option to decide whether to modify the feed when the XPath does not match and Modify the input field to a textarea.
## Configuration settings ## Configuration settings

View file

@ -5,13 +5,18 @@
<form action="<?= _url('extension', 'configure', 'e', urlencode($this->getName())) ?>" method="post"> <form action="<?= _url('extension', 'configure', 'e', urlencode($this->getName())) ?>" method="post">
<input type="hidden" name="_csrf" value="<?= FreshRSS_Auth::csrfToken() ?>" /> <input type="hidden" name="_csrf" value="<?= FreshRSS_Auth::csrfToken() ?>" />
<div class="form-group"> <div class="form-group">
<label class="group-name" for="allow_url"><?= _t('ext.replaceEntryUrl.allow_url') ?></label> <label class="group-name" for="replaceEntryUrl_matchUrlKeyValues"><?= _t('ext.replaceEntryUrl.matchUrlKeyValues') ?></label>
<div class="group-controls"> <div class="group-controls">
<input type="text" name="allow_url" id="allow_url" <textarea name="replaceEntryUrl_matchUrlKeyValues" id="replaceEntryUrl_matchUrlKeyValues" rows="5" cols="30"><?= htmlspecialchars(FreshRSS_Context::userConf()->attributeString('replaceEntryUrl_matchUrlKeyValues') ?? '', ENT_COMPAT, 'UTF-8') ?></textarea>
value="<?= htmlspecialchars(FreshRSS_Context::userConf()->attributeString('allow_url') ?? '', ENT_COMPAT, 'UTF-8') ?>"> </div>
</div>
<div class="form-group">
<label class="group-name" for="replaceEntryUrl_filterXPathContent"><?= _t('ext.replaceEntryUrl.filterXPathContent') ?></label>
<div class="group-controls">
<input type="checkbox" name="replaceEntryUrl_filterXPathContent" id="replaceEntryUrl_filterXPathContent" value="1"
<?= FreshRSS_Context::userConf()->attributeBool('replaceEntryUrl_filterXPathContent') ? 'checked' : '' ?>>
</div> </div>
</div> </div>
<div class="form-group form-actions"> <div class="form-group form-actions">
<div class="group-controls"> <div class="group-controls">

View file

@ -3,7 +3,7 @@
declare(strict_types=1); declare(strict_types=1);
class replaceEntryUrlExtension extends Minz_Extension { class replaceEntryUrlExtension extends Minz_Extension {
const ALLOWED_LIST = []; const ALLOWED_LIST = [];
const GET_FULL_CONTENT = false;
/** /**
* @throws FreshRSS_Context_Exception * @throws FreshRSS_Context_Exception
*/ */
@ -13,13 +13,16 @@ class replaceEntryUrlExtension extends Minz_Extension {
} }
$save = false; $save = false;
/*If you want to replace it during refresh, uncomment this line and comment out the line below. it used in test*/ /*If you want to replace it during refresh, uncomment this line and comment out the line below. it used in test*/
// $this->registerHook('entry_before_display', [self::class, 'processEntry']); //$this->registerHook('entry_before_display', [self::class, 'processEntry']);
$this->registerHook('entry_before_insert', [self::class, 'processEntry']); $this->registerHook('entry_before_insert', [self::class, 'processEntry']);
if (FreshRSS_Context::userConf()->attributeString('allow_url') === null) { if (FreshRSS_Context::userConf()->attributeString('replaceEntryUrl_matchUrlKeyValues') === null) {
FreshRSS_Context::userConf()->_attribute('allow_url', self::ALLOWED_LIST); FreshRSS_Context::userConf()->_attribute('replaceEntryUrl_matchUrlKeyValues', self::ALLOWED_LIST);
$save = true;
}
if (FreshRSS_Context::userConf()->attributeBool('replaceEntryUrl_filterXPathContent') === null) {
FreshRSS_Context::userConf()->_attribute('replaceEntryUrl_filterXPathContent', self::GET_FULL_CONTENT);
$save = true; $save = true;
} }
} }
/** /**
@ -29,7 +32,8 @@ class replaceEntryUrlExtension extends Minz_Extension {
$this->registerTranslates(); $this->registerTranslates();
if (Minz_Request::isPost()) { if (Minz_Request::isPost()) {
FreshRSS_Context::userConf()->_attribute('allow_url', Minz_Request::paramString('allow_url', plaintext: true) ?: self::ALLOWED_LIST); FreshRSS_Context::userConf()->_attribute('replaceEntryUrl_matchUrlKeyValues', Minz_Request::paramString('replaceEntryUrl_matchUrlKeyValues', plaintext: true) ?: self::ALLOWED_LIST);
FreshRSS_Context::userConf()->_attribute('replaceEntryUrl_filterXPathContent', Minz_Request::paramBoolean('replaceEntryUrl_filterXPathContent'));
FreshRSS_Context::userConf()->save(); FreshRSS_Context::userConf()->save();
} }
} }
@ -41,37 +45,41 @@ class replaceEntryUrlExtension extends Minz_Extension {
* @throws FreshRSS_Context_Exception * @throws FreshRSS_Context_Exception
*/ */
public static function processEntry(FreshRSS_Entry $entry): FreshRSS_Entry { public static function processEntry(FreshRSS_Entry $entry): FreshRSS_Entry {
$allow_array = ""; $useDefaultIfEmpty = FreshRSS_Context::userConf()->attributeBool('replaceEntryUrl_filterXPathContent') ?? false;
$allow_url_str = FreshRSS_Context::userConf()->attributeString('allow_url'); $allow_array = "";
if (!is_string($allow_url_str) || $allow_url_str === '') { $allow_url_str = FreshRSS_Context::userConf()->attributeString('replaceEntryUrl_matchUrlKeyValues');
return $entry; if (!is_string($allow_url_str) || $allow_url_str === '') {
} return $entry;
$allow_array = json_decode($allow_url_str,true);
$allow_url = [];
if(json_last_error() === JSON_ERROR_NONE && is_array($allow_array)){
foreach ($allow_array as $key => $value) {
array_push($allow_url, (string)$key);
}
}
if(!is_array($allow_array)){
return $entry;
}
$link = $entry->link();
$my_xpath = self::isUrlAllowed($link,$allow_url,$allow_array);
if (empty($my_xpath)) {
return $entry;
} }
$response = self::curlDownloadContent($link); $allow_array = json_decode($allow_url_str,true);
if($response != false){
$article = self:: extractMainContent($response,$my_xpath); $allow_url = [];
$entry->_content ($article);
if(json_last_error() === JSON_ERROR_NONE && is_array($allow_array)){
foreach ($allow_array as $key => $value) {
array_push($allow_url, (string)$key);
} }
}
if(!is_array($allow_array)){
return $entry;
}
$link = $entry->link();
$my_xpath = self::isUrlAllowed($link,$allow_url,$allow_array);
if (empty($my_xpath)) {
return $entry;
}
$response = self::curlDownloadContent($link);
$article = "";
if($response != false){
$article = self:: extractMainContent($response,$my_xpath,$useDefaultIfEmpty);
}
if($article != ""){
$entry->_content ($article);
}
return $entry; return $entry;
} }
@ -102,16 +110,19 @@ class replaceEntryUrlExtension extends Minz_Extension {
} }
public static function extractMainContent(string $content,string $my_xpath): string { public static function extractMainContent(string $content,string $my_xpath,bool $useDefaultIfEmpty): string {
$doc = new DOMDocument(); $doc = new DOMDocument();
libxml_use_internal_errors(true); libxml_use_internal_errors(true);
$doc->loadHTML(mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8')); $doc->loadHTML(mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8'));
$xpath = new DOMXPath($doc); $xpath = new DOMXPath($doc);
$nodes = $xpath->query($my_xpath); $nodes = $xpath->query($my_xpath);
$mainContent = "";
if ($nodes instanceof DOMNodeList && $nodes->length > 0) { if ($nodes instanceof DOMNodeList && $nodes->length > 0) {
$mainContent = $doc->saveHTML($nodes->item(0)); $mainContent = $doc->saveHTML($nodes->item(0));
}else{ }
elseif($useDefaultIfEmpty)
{
$mainContent = $content; $mainContent = $content;
} }
libxml_clear_errors(); libxml_clear_errors();
@ -136,7 +147,7 @@ class replaceEntryUrlExtension extends Minz_Extension {
if (is_string($xpath_value)) { if (is_string($xpath_value)) {
return $xpath_value; return $xpath_value;
} }
return ''; return "";
} }
return ""; return "";
} }

View file

@ -2,6 +2,7 @@
return array( return array(
'replaceEntryUrl' => array( 'replaceEntryUrl' => array(
'allow_url' => 'replace domain:' 'matchUrlKeyValues' => 'domain json:',
'filterXPathContent' => 'Return full content by default'
), ),
); );

View file

@ -2,7 +2,7 @@
"name": "replace Entry Url", "name": "replace Entry Url",
"author": "fiifff", "author": "fiifff",
"description": "Replace the URL in the content of subscription entries with the actual content of the URL.", "description": "Replace the URL in the content of subscription entries with the actual content of the URL.",
"version": "0.2.1", "version": "0.2.2",
"entrypoint": "replaceEntryUrl", "entrypoint": "replaceEntryUrl",
"type": "user" "type": "user"
} }