core: Automatically select a bridge based on a URL (#928)

* core: Add bridge parameter auto detection

This adds a new 'detect' action which accepts a URL from which an
appropriate bridge is selected and relevant parameters are extracted.
The user is then automatically redirected to the selected bridge.

For example to get a feed from: https://twitter.com/search?q=%23rss-bridge
we could send a request to:
'/?action=detect&format=Atom&url=twitter.com/search%3Fq%3D%2523rss-bridge'
which would redirect to:
'/?action=display&q=%23rss-bridge&bridge=Twitter&format=Atom'.

This auto detection happens on a per-bridge basis, so a new function
'detectParameters' is added to BridgeInterface which bridges may implement.
It takes a URL for an argument and returns a list of parameters that were
extracted, or null if the URL isn't relevant for the bridge.

* [TwitterBridge] Add parameter auto detection

* [BridgeAbstract] Add generic parameter detection

This adds generic "paramater detection" for bridges that don't have any
parameters defined. If the queried URL matches the URI defined in the
bridge (ignoring https://, www. and trailing /) an emtpy list of parameters is
returned.
This commit is contained in:
Roliga 2018-11-26 18:05:41 +01:00 committed by LogMANOriginal
parent b4dbd191d0
commit 49da67cb33
4 changed files with 92 additions and 0 deletions

View File

@ -66,6 +66,41 @@ class TwitterBridge extends BridgeAbstract {
)
);
public function detectParameters($url){
$params = array();
// By keyword or hashtag (search)
$regex = '/^(https?:\/\/)?(www\.)?twitter\.com\/search.*(\?|&)q=([^\/&?\n]+)/';
if(preg_match($regex, $url, $matches) > 0) {
$params['q'] = urldecode($matches[4]);
return $params;
}
// By hashtag
$regex = '/^(https?:\/\/)?(www\.)?twitter\.com\/hashtag\/([^\/?\n]+)/';
if(preg_match($regex, $url, $matches) > 0) {
$params['q'] = urldecode($matches[3]);
return $params;
}
// By list
$regex = '/^(https?:\/\/)?(www\.)?twitter\.com\/([^\/?\n]+)\/lists\/([^\/?\n]+)/';
if(preg_match($regex, $url, $matches) > 0) {
$params['user'] = urldecode($matches[3]);
$params['list'] = urldecode($matches[4]);
return $params;
}
// By username
$regex = '/^(https?:\/\/)?(www\.)?twitter\.com\/([^\/?\n]+)/';
if(preg_match($regex, $url, $matches) > 0) {
$params['u'] = urldecode($matches[3]);
return $params;
}
return null;
}
public function getName(){
switch($this->queriedContext) {
case 'By keyword or hashtag':

View File

@ -96,6 +96,42 @@ try {
header('Content-Type: application/json');
echo json_encode($list, JSON_PRETTY_PRINT);
} elseif($action === 'detect') {
$targetURL = $params['url']
or returnClientError('You must specify a url!');
$format = $params['format']
or returnClientError('You must specify a format!');
foreach(Bridge::listBridges() as $bridgeName) {
if(!Bridge::isWhitelisted($bridgeName)) {
continue;
}
$bridge = Bridge::create($bridgeName);
if($bridge === false) {
continue;
}
$bridgeParams = $bridge->detectParameters($targetURL);
if(is_null($bridgeParams)) {
continue;
}
$bridgeParams['bridge'] = $bridgeName;
$bridgeParams['format'] = $format;
header('Location: ?action=display&' . http_build_query($bridgeParams), true, 301);
die();
}
returnClientError('No bridge found for given URL: ' . $targetURL);
} elseif($action === 'display' && !empty($bridge)) {
$format = $params['format']

View File

@ -278,4 +278,17 @@ abstract class BridgeAbstract implements BridgeInterface {
return static::CACHE_TIMEOUT;
}
/** {@inheritdoc} */
public function detectParameters($url){
$regex = '/^(https?:\/\/)?(www\.)?(.+?)(\/)?$/';
if(empty(static::PARAMETERS)
&& preg_match($regex, $url, $urlMatches) > 0
&& preg_match($regex, static::URI, $bridgeUriMatches) > 0
&& $urlMatches[3] === $bridgeUriMatches[3]) {
return array();
} else {
return null;
}
}
}

View File

@ -114,4 +114,12 @@ interface BridgeInterface {
* @return int Cache timeout
*/
public function getCacheTimeout();
/**
* Returns parameters from given URL or null if URL is not applicable
*
* @param string $url URL to extract parameters from
* @return array|null List of bridge parameters or null if detection failed.
*/
public function detectParameters($url);
}