Add Fever API support
This commit is contained in:
parent
ab406e8eaa
commit
5801258ace
@ -69,6 +69,7 @@ Documentation
|
|||||||
- [Translations](docs/translations.markdown)
|
- [Translations](docs/translations.markdown)
|
||||||
- [Themes](docs/themes.markdown)
|
- [Themes](docs/themes.markdown)
|
||||||
- [API documentation](http://miniflux.net/api.html)
|
- [API documentation](http://miniflux.net/api.html)
|
||||||
|
- [Fever API](docs/fever.markdown)
|
||||||
- [FAQ](docs/faq.markdown)
|
- [FAQ](docs/faq.markdown)
|
||||||
|
|
||||||
Todo and known bugs
|
Todo and known bugs
|
||||||
|
@ -32,7 +32,7 @@ defined('HTTP_TIMEOUT') or define('HTTP_TIMEOUT', 20);
|
|||||||
|
|
||||||
defined('BASE_URL_DIRECTORY') or define('BASE_URL_DIRECTORY', dirname($_SERVER['PHP_SELF']));
|
defined('BASE_URL_DIRECTORY') or define('BASE_URL_DIRECTORY', dirname($_SERVER['PHP_SELF']));
|
||||||
defined('ROOT_DIRECTORY') or define('ROOT_DIRECTORY', __DIR__);
|
defined('ROOT_DIRECTORY') or define('ROOT_DIRECTORY', __DIR__);
|
||||||
defined('DATA_DIRECTORY') or define('DATA_DIRECTORY', 'data');
|
defined('DATA_DIRECTORY') or define('DATA_DIRECTORY', __DIR__.'/data');
|
||||||
|
|
||||||
defined('ENABLE_MULTIPLE_DB') or define('ENABLE_MULTIPLE_DB', true);
|
defined('ENABLE_MULTIPLE_DB') or define('ENABLE_MULTIPLE_DB', true);
|
||||||
defined('DB_FILENAME') or define('DB_FILENAME', 'db.sqlite');
|
defined('DB_FILENAME') or define('DB_FILENAME', 'db.sqlite');
|
||||||
|
@ -74,7 +74,7 @@ Router\get_action('auto-update', function() {
|
|||||||
Router\get_action('generate-tokens', function() {
|
Router\get_action('generate-tokens', function() {
|
||||||
|
|
||||||
Model\Config\new_tokens();
|
Model\Config\new_tokens();
|
||||||
Response\redirect('?action=config#api');
|
Response\redirect('?action=config');
|
||||||
});
|
});
|
||||||
|
|
||||||
// Optimize the database manually
|
// Optimize the database manually
|
||||||
|
27
docs/fever-api.markdown
Normal file
27
docs/fever-api.markdown
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
Fever API
|
||||||
|
=========
|
||||||
|
|
||||||
|
Miniflux support the [Fever API](http://feedafever.com/api).
|
||||||
|
That means you can use mobile applications compatible with Fever.
|
||||||
|
|
||||||
|
This feature have been tested with the following apps:
|
||||||
|
|
||||||
|
- [Press for Android](http://twentyfivesquares.com/press/)
|
||||||
|
|
||||||
|
Configuration
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Miniflux generates a random password for the Fever API.
|
||||||
|
All information are available from the **preferences page**.
|
||||||
|
|
||||||
|
- URL: http://your_miniflux_url/fever/
|
||||||
|
- Username: Your username
|
||||||
|
- Password: random (visible on the settings page)
|
||||||
|
|
||||||
|
Notes
|
||||||
|
-----
|
||||||
|
|
||||||
|
- Links, sparks, kindling, favicons and groups are not supported.
|
||||||
|
- All feeds will be under a category "All" because Miniflux doesn't support categories.
|
||||||
|
- Only JSON responses are handled.
|
||||||
|
- If you have multiple users with Miniflux, that will works only with the default user.
|
318
fever/index.php
Normal file
318
fever/index.php
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require '../common.php';
|
||||||
|
|
||||||
|
use Model\Feed;
|
||||||
|
use PicoDb\Database;
|
||||||
|
|
||||||
|
// Route handler
|
||||||
|
function route($name, Closure $callback = null)
|
||||||
|
{
|
||||||
|
static $routes = array();
|
||||||
|
|
||||||
|
if ($callback !== null) {
|
||||||
|
$routes[$name] = $callback;
|
||||||
|
}
|
||||||
|
else if (isset($routes[$name])) {
|
||||||
|
$routes[$name]();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialize the payload in Json (XML is not supported)
|
||||||
|
function response(array $response)
|
||||||
|
{
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
echo json_encode($response);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fever authentication
|
||||||
|
function auth()
|
||||||
|
{
|
||||||
|
$credentials = Database::get('db')->table('config')
|
||||||
|
->columns('username', 'fever_token')
|
||||||
|
->findOne();
|
||||||
|
|
||||||
|
$api_key = md5($credentials['username'].':'.$credentials['fever_token']);
|
||||||
|
|
||||||
|
$response = array(
|
||||||
|
'api_version' => 3,
|
||||||
|
'auth' => (int) (@$_POST['api_key'] === $api_key),
|
||||||
|
'last_refreshed_on_time' => time(),
|
||||||
|
);
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call: ?api&groups
|
||||||
|
route('groups', function() {
|
||||||
|
|
||||||
|
$response = auth();
|
||||||
|
|
||||||
|
if ($response['auth']) {
|
||||||
|
|
||||||
|
$feed_ids = Database::get('db')
|
||||||
|
->table('feeds')
|
||||||
|
->findAllByColumn('id');
|
||||||
|
|
||||||
|
$response['groups'] = array(
|
||||||
|
array(
|
||||||
|
'id' => 1,
|
||||||
|
'title' => t('All'),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$response['feeds_groups'] = array(
|
||||||
|
array(
|
||||||
|
'group_id' => 1,
|
||||||
|
'feed_ids' => implode(',', $feed_ids),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
response($response);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Call: ?api&feeds
|
||||||
|
route('feeds', function() {
|
||||||
|
|
||||||
|
$response = auth();
|
||||||
|
|
||||||
|
if ($response['auth']) {
|
||||||
|
|
||||||
|
$response['feeds'] = array();
|
||||||
|
$feeds = Feed\get_all();
|
||||||
|
$feed_ids = array();
|
||||||
|
|
||||||
|
foreach ($feeds as $feed) {
|
||||||
|
$response['feeds'][] = array(
|
||||||
|
'id' => (int) $feed['id'],
|
||||||
|
'favicon_id' => 1,
|
||||||
|
'title' => $feed['title'],
|
||||||
|
'url' => $feed['feed_url'],
|
||||||
|
'site_url' => $feed['site_url'],
|
||||||
|
'is_spark' => 0,
|
||||||
|
'last_updated_on_time' => $feed['last_checked'] ?: time(),
|
||||||
|
);
|
||||||
|
|
||||||
|
$feed_ids[] = $feed['id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$response['feeds_groups'] = array(
|
||||||
|
array(
|
||||||
|
'group_id' => 1,
|
||||||
|
'feed_ids' => implode(',', $feed_ids),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
response($response);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Call: ?api&favicons
|
||||||
|
route('favicons', function() {
|
||||||
|
|
||||||
|
$response = auth();
|
||||||
|
|
||||||
|
if ($response['auth']) {
|
||||||
|
$response['favicons'] = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
response($response);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Call: ?api&items
|
||||||
|
route('items', function() {
|
||||||
|
|
||||||
|
$response = auth();
|
||||||
|
|
||||||
|
if ($response['auth']) {
|
||||||
|
|
||||||
|
$offset = 0;
|
||||||
|
$direction = 'ASC';
|
||||||
|
|
||||||
|
if (isset($_GET['since_id']) && is_numeric($_GET['since_id'])) {
|
||||||
|
|
||||||
|
$offset = $_GET['since_id'];
|
||||||
|
$direction = 'ASC';
|
||||||
|
}
|
||||||
|
else if (isset($_GET['max_id']) && is_numeric($_GET['max_id'])) {
|
||||||
|
|
||||||
|
$offset = $_GET['max_id'];
|
||||||
|
$direction = 'DESC';
|
||||||
|
}
|
||||||
|
|
||||||
|
$query = Database::get('db')
|
||||||
|
->table('items')
|
||||||
|
->columns(
|
||||||
|
'rowid',
|
||||||
|
'feed_id',
|
||||||
|
'title',
|
||||||
|
'author',
|
||||||
|
'content',
|
||||||
|
'url',
|
||||||
|
'updated',
|
||||||
|
'status',
|
||||||
|
'bookmark'
|
||||||
|
)
|
||||||
|
->orderby('rowid', $direction)
|
||||||
|
->offset($offset)
|
||||||
|
->limit(50);
|
||||||
|
|
||||||
|
if (! empty($_GET['with_ids'])) {
|
||||||
|
$query->in('rowid', explode(',', $_GET['with_ids']));
|
||||||
|
}
|
||||||
|
|
||||||
|
$items = $query->findAll();
|
||||||
|
$response['items'] = array();
|
||||||
|
|
||||||
|
foreach ($items as $item) {
|
||||||
|
$response['items'][] = array(
|
||||||
|
'id' => (int) $item['rowid'],
|
||||||
|
'feed_id' => (int) $item['feed_id'],
|
||||||
|
'title' => $item['title'],
|
||||||
|
'author' => $item['author'],
|
||||||
|
'html' => $item['content'],
|
||||||
|
'url' => $item['url'],
|
||||||
|
'is_saved' => (int) $item['bookmark'],
|
||||||
|
'is_read' => $item['status'] == 'read' ? 1 : 0,
|
||||||
|
'created_on_time' => $item['updated'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$response['total_items'] = Database::get('db')
|
||||||
|
->table('items')
|
||||||
|
->neq('status', 'removed')
|
||||||
|
->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
response($response);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Call: ?api&links
|
||||||
|
route('links', function() {
|
||||||
|
|
||||||
|
$response = auth();
|
||||||
|
|
||||||
|
if ($response['auth']) {
|
||||||
|
$response['links'] = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
response($response);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Call: ?api&unread_item_ids
|
||||||
|
route('unread_item_ids', function() {
|
||||||
|
|
||||||
|
$response = auth();
|
||||||
|
|
||||||
|
if ($response['auth']) {
|
||||||
|
|
||||||
|
$item_ids = Database::get('db')
|
||||||
|
->table('items')
|
||||||
|
->eq('status', 'unread')
|
||||||
|
->findAllByColumn('rowid');
|
||||||
|
|
||||||
|
$response['unread_item_ids'] = implode(',', $item_ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
response($response);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Call: ?api&saved_item_ids
|
||||||
|
route('saved_item_ids', function() {
|
||||||
|
|
||||||
|
$response = auth();
|
||||||
|
|
||||||
|
if ($response['auth']) {
|
||||||
|
|
||||||
|
$item_ids = Database::get('db')
|
||||||
|
->table('items')
|
||||||
|
->eq('bookmark', 1)
|
||||||
|
->findAllByColumn('rowid');
|
||||||
|
|
||||||
|
$response['saved_item_ids'] = implode(',', $item_ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
response($response);
|
||||||
|
});
|
||||||
|
|
||||||
|
// handle write items
|
||||||
|
route('write_items', function() {
|
||||||
|
|
||||||
|
$response = auth();
|
||||||
|
|
||||||
|
if ($response['auth']) {
|
||||||
|
|
||||||
|
$query = Database::get('db')
|
||||||
|
->table('items')
|
||||||
|
->eq('rowid', $_POST['id']);
|
||||||
|
|
||||||
|
if ($_POST['as'] === 'saved') {
|
||||||
|
$query->update(array('bookmark' => 1));
|
||||||
|
}
|
||||||
|
else if ($_POST['as'] === 'unsaved') {
|
||||||
|
$query->update(array('bookmark' => 0));
|
||||||
|
}
|
||||||
|
else if ($_POST['as'] === 'read') {
|
||||||
|
$query->update(array('status' => 'read'));
|
||||||
|
}
|
||||||
|
else if ($_POST['as'] === 'unread') {
|
||||||
|
$query->update(array('status' => 'unread'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
response($response);
|
||||||
|
});
|
||||||
|
|
||||||
|
// handle write feeds
|
||||||
|
route('write_feeds', function() {
|
||||||
|
|
||||||
|
$response = auth();
|
||||||
|
|
||||||
|
if ($response['auth']) {
|
||||||
|
|
||||||
|
Database::get('db')
|
||||||
|
->table('items')
|
||||||
|
->eq('feed_id', $_POST['id'])
|
||||||
|
->lte('updated', $_POST['before'])
|
||||||
|
->update(array('status' => $_POST['as'] === 'read' ? 'read' : 'unread'));
|
||||||
|
}
|
||||||
|
|
||||||
|
response($response);
|
||||||
|
});
|
||||||
|
|
||||||
|
// handle write groups
|
||||||
|
route('write_groups', function() {
|
||||||
|
|
||||||
|
$response = auth();
|
||||||
|
|
||||||
|
if ($response['auth']) {
|
||||||
|
|
||||||
|
Database::get('db')
|
||||||
|
->table('items')
|
||||||
|
->lte('updated', $_POST['before'])
|
||||||
|
->update(array('status' => $_POST['as'] === 'read' ? 'read' : 'unread'));
|
||||||
|
}
|
||||||
|
|
||||||
|
response($response);
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach (array_keys($_GET) as $action) {
|
||||||
|
route($action);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! empty($_POST['mark']) && ! empty($_POST['as']) && ! empty($_POST['id'])) {
|
||||||
|
|
||||||
|
if ($_POST['mark'] === 'item') {
|
||||||
|
route('write_items');
|
||||||
|
}
|
||||||
|
else if ($_POST['mark'] === 'feed' && ! empty($_POST['before'])) {
|
||||||
|
route('write_feeds');
|
||||||
|
}
|
||||||
|
else if ($_POST['mark'] === 'group' && ! empty($_POST['before'])) {
|
||||||
|
route('write_groups');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
response(auth());
|
@ -96,14 +96,6 @@ return array(
|
|||||||
'Never' => 'Nikdy',
|
'Never' => 'Nikdy',
|
||||||
'After %d day' => 'Po %d dni',
|
'After %d day' => 'Po %d dni',
|
||||||
'After %d days' => 'Po %d dnech',
|
'After %d days' => 'Po %d dnech',
|
||||||
'French' => 'Francouzština',
|
|
||||||
'English' => 'Angličtina',
|
|
||||||
'German' => 'Němčina',
|
|
||||||
'Italian' => 'Italština',
|
|
||||||
// 'Spanish' => '',
|
|
||||||
'Simplified Chinese' => 'Zjednodušená čínština',
|
|
||||||
'Czech' => 'Čeština',
|
|
||||||
// 'Portuguese' => '',
|
|
||||||
'unread' => 'nepřečtené',
|
'unread' => 'nepřečtené',
|
||||||
'bookmark' => 'přidat do záložek',
|
'bookmark' => 'přidat do záložek',
|
||||||
'remove bookmark' => 'odstranit záložku',
|
'remove bookmark' => 'odstranit záložku',
|
||||||
@ -230,4 +222,7 @@ return array(
|
|||||||
// 'Remove this feed' => '',
|
// 'Remove this feed' => '',
|
||||||
// 'Miniflux' => '',
|
// 'Miniflux' => '',
|
||||||
// 'mini<span>flux</span>' => '',
|
// 'mini<span>flux</span>' => '',
|
||||||
|
// 'Username:' => '',
|
||||||
|
// 'Password:' => '',
|
||||||
|
// 'All' => '',
|
||||||
);
|
);
|
||||||
|
@ -96,14 +96,6 @@ return array(
|
|||||||
'Never' => 'Niemals',
|
'Never' => 'Niemals',
|
||||||
'After %d day' => 'Nach %d Tag',
|
'After %d day' => 'Nach %d Tag',
|
||||||
'After %d days' => 'Nach %d Tagen',
|
'After %d days' => 'Nach %d Tagen',
|
||||||
'French' => 'Französisch',
|
|
||||||
'English' => 'Englisch',
|
|
||||||
'German' => 'Deutsch',
|
|
||||||
'Italian' => 'Italienisch',
|
|
||||||
'Spanish' => 'Spanisch',
|
|
||||||
'Simplified Chinese' => 'Vereinfachtes Chinesisch',
|
|
||||||
'Czech' => 'Tschechisch',
|
|
||||||
'Portuguese' => 'Portugiesisch',
|
|
||||||
'unread' => 'ungelesen',
|
'unread' => 'ungelesen',
|
||||||
'bookmark' => 'lesezeichen',
|
'bookmark' => 'lesezeichen',
|
||||||
'remove bookmark' => 'lesezeichen entfernen',
|
'remove bookmark' => 'lesezeichen entfernen',
|
||||||
@ -230,4 +222,7 @@ return array(
|
|||||||
// 'Remove this feed' => '',
|
// 'Remove this feed' => '',
|
||||||
// 'Miniflux' => '',
|
// 'Miniflux' => '',
|
||||||
// 'mini<span>flux</span>' => '',
|
// 'mini<span>flux</span>' => '',
|
||||||
|
// 'Username:' => '',
|
||||||
|
// 'Password:' => '',
|
||||||
|
// 'All' => '',
|
||||||
);
|
);
|
||||||
|
@ -96,14 +96,6 @@ return array(
|
|||||||
'Never' => 'Nunca',
|
'Never' => 'Nunca',
|
||||||
'After %d day' => 'Después de %d día',
|
'After %d day' => 'Después de %d día',
|
||||||
'After %d days' => 'Después de %d días',
|
'After %d days' => 'Después de %d días',
|
||||||
'French' => 'Francés',
|
|
||||||
'English' => 'Inglés',
|
|
||||||
'German' => 'Alemán',
|
|
||||||
'Italian' => 'Italiano',
|
|
||||||
'Spanish' => 'Español',
|
|
||||||
'Simplified Chinese' => 'Chino simplificado',
|
|
||||||
'Czech' => 'Checo',
|
|
||||||
'Portuguese' => 'Portugués',
|
|
||||||
'unread' => 'no leídos',
|
'unread' => 'no leídos',
|
||||||
'bookmark' => 'añadir a marcadores',
|
'bookmark' => 'añadir a marcadores',
|
||||||
'remove bookmark' => 'borrar marcador',
|
'remove bookmark' => 'borrar marcador',
|
||||||
@ -230,4 +222,7 @@ return array(
|
|||||||
// 'Remove this feed' => '',
|
// 'Remove this feed' => '',
|
||||||
// 'Miniflux' => '',
|
// 'Miniflux' => '',
|
||||||
// 'mini<span>flux</span>' => '',
|
// 'mini<span>flux</span>' => '',
|
||||||
|
// 'Username:' => '',
|
||||||
|
// 'Password:' => '',
|
||||||
|
// 'All' => '',
|
||||||
);
|
);
|
||||||
|
@ -96,14 +96,6 @@ return array(
|
|||||||
'Never' => 'Jamais',
|
'Never' => 'Jamais',
|
||||||
'After %d day' => 'Après %d jour',
|
'After %d day' => 'Après %d jour',
|
||||||
'After %d days' => 'Après %d jours',
|
'After %d days' => 'Après %d jours',
|
||||||
'French' => 'Français',
|
|
||||||
'English' => 'Anglais',
|
|
||||||
'German' => 'Allemand',
|
|
||||||
'Italian' => 'Italien',
|
|
||||||
'Spanish' => 'Espagnol',
|
|
||||||
'Simplified Chinese' => 'Chinois simplifié',
|
|
||||||
'Czech' => 'Tchèque',
|
|
||||||
'Portuguese' => 'Portuguais',
|
|
||||||
'unread' => 'non lus',
|
'unread' => 'non lus',
|
||||||
'bookmark' => 'ajouter aux favoris',
|
'bookmark' => 'ajouter aux favoris',
|
||||||
'remove bookmark' => 'supprimer des favoris',
|
'remove bookmark' => 'supprimer des favoris',
|
||||||
@ -230,4 +222,7 @@ return array(
|
|||||||
'Remove this feed' => 'Supprimer cet abonnement',
|
'Remove this feed' => 'Supprimer cet abonnement',
|
||||||
'Miniflux' => 'Miniflux',
|
'Miniflux' => 'Miniflux',
|
||||||
'mini<span>flux</span>' => 'mini<span>flux</span>',
|
'mini<span>flux</span>' => 'mini<span>flux</span>',
|
||||||
|
'Username:' => 'Utilisateur :',
|
||||||
|
'Password:' => 'Mot de passe :',
|
||||||
|
'All' => 'Tout',
|
||||||
);
|
);
|
||||||
|
@ -96,14 +96,6 @@ return array(
|
|||||||
'Never' => 'Mai',
|
'Never' => 'Mai',
|
||||||
'After %d day' => 'Dopo %d giorno',
|
'After %d day' => 'Dopo %d giorno',
|
||||||
'After %d days' => 'Dopo %d giorni',
|
'After %d days' => 'Dopo %d giorni',
|
||||||
'French' => 'Francese',
|
|
||||||
'English' => 'Inglese',
|
|
||||||
'German' => 'Tedesco',
|
|
||||||
'Italian' => 'Italiano',
|
|
||||||
// 'Spanish' => '',
|
|
||||||
'Simplified Chinese' => 'Cinese semplificato',
|
|
||||||
'Czech' => 'Ceco',
|
|
||||||
// 'Portuguese' => '',
|
|
||||||
'unread' => 'non letti',
|
'unread' => 'non letti',
|
||||||
'bookmark' => 'bookmark',
|
'bookmark' => 'bookmark',
|
||||||
'remove bookmark' => 'cancella bookmark',
|
'remove bookmark' => 'cancella bookmark',
|
||||||
@ -230,4 +222,7 @@ return array(
|
|||||||
// 'Remove this feed' => '',
|
// 'Remove this feed' => '',
|
||||||
// 'Miniflux' => '',
|
// 'Miniflux' => '',
|
||||||
// 'mini<span>flux</span>' => '',
|
// 'mini<span>flux</span>' => '',
|
||||||
|
// 'Username:' => '',
|
||||||
|
// 'Password:' => '',
|
||||||
|
// 'All' => '',
|
||||||
);
|
);
|
||||||
|
@ -96,14 +96,6 @@ return array(
|
|||||||
'Never' => 'Nunca',
|
'Never' => 'Nunca',
|
||||||
'After %d day' => 'Depois %d dias',
|
'After %d day' => 'Depois %d dias',
|
||||||
'After %d days' => 'Depois %d dias',
|
'After %d days' => 'Depois %d dias',
|
||||||
'French' => 'Frances',
|
|
||||||
'English' => 'Ingles',
|
|
||||||
'German' => 'Alemão',
|
|
||||||
'Italian' => 'Italiano',
|
|
||||||
// 'Spanish' => '',
|
|
||||||
'Simplified Chinese' => 'Chinês Simplificado',
|
|
||||||
// 'Czech' => '',
|
|
||||||
'Portuguese' => 'Português',
|
|
||||||
'unread' => 'não lido',
|
'unread' => 'não lido',
|
||||||
'bookmark' => 'lesezeichen',
|
'bookmark' => 'lesezeichen',
|
||||||
'remove bookmark' => 'lesezeichen löschen',
|
'remove bookmark' => 'lesezeichen löschen',
|
||||||
@ -230,4 +222,7 @@ return array(
|
|||||||
// 'Remove this feed' => '',
|
// 'Remove this feed' => '',
|
||||||
// 'Miniflux' => '',
|
// 'Miniflux' => '',
|
||||||
// 'mini<span>flux</span>' => '',
|
// 'mini<span>flux</span>' => '',
|
||||||
|
// 'Username:' => '',
|
||||||
|
// 'Password:' => '',
|
||||||
|
// 'All' => '',
|
||||||
);
|
);
|
||||||
|
@ -96,14 +96,6 @@ return array(
|
|||||||
'Never' => '从不',
|
'Never' => '从不',
|
||||||
'After %d day' => '%d 天之后',
|
'After %d day' => '%d 天之后',
|
||||||
'After %d days' => '%d 天之后',
|
'After %d days' => '%d 天之后',
|
||||||
'French' => '法语',
|
|
||||||
'English' => '英语',
|
|
||||||
'German' => '德语',
|
|
||||||
'Italian' => '意大利人',
|
|
||||||
// 'Spanish' => '',
|
|
||||||
'Simplified Chinese' => '简体中文',
|
|
||||||
'Czech' => '捷克语',
|
|
||||||
// 'Portuguese' => '',
|
|
||||||
'unread' => '未读',
|
'unread' => '未读',
|
||||||
'bookmark' => '收藏',
|
'bookmark' => '收藏',
|
||||||
'remove bookmark' => '取消收藏',
|
'remove bookmark' => '取消收藏',
|
||||||
@ -230,4 +222,7 @@ return array(
|
|||||||
// 'Remove this feed' => '',
|
// 'Remove this feed' => '',
|
||||||
// 'Miniflux' => '',
|
// 'Miniflux' => '',
|
||||||
// 'mini<span>flux</span>' => '',
|
// 'mini<span>flux</span>' => '',
|
||||||
|
// 'Username:' => '',
|
||||||
|
// 'Password:' => '',
|
||||||
|
// 'All' => '',
|
||||||
);
|
);
|
||||||
|
@ -2,13 +2,14 @@
|
|||||||
|
|
||||||
namespace Model\Config;
|
namespace Model\Config;
|
||||||
|
|
||||||
|
use DirectoryIterator;
|
||||||
use SimpleValidator\Validator;
|
use SimpleValidator\Validator;
|
||||||
use SimpleValidator\Validators;
|
use SimpleValidator\Validators;
|
||||||
use PicoDb\Database;
|
use PicoDb\Database;
|
||||||
use PicoFeed\Config as ReaderConfig;
|
use PicoFeed\Config as ReaderConfig;
|
||||||
use PicoFeed\Logging;
|
use PicoFeed\Logging;
|
||||||
|
|
||||||
const DB_VERSION = 28;
|
const DB_VERSION = 29;
|
||||||
const HTTP_USER_AGENT = 'Miniflux (http://miniflux.net)';
|
const HTTP_USER_AGENT = 'Miniflux (http://miniflux.net)';
|
||||||
|
|
||||||
// Get PicoFeed config
|
// Get PicoFeed config
|
||||||
@ -34,7 +35,6 @@ function get_reader_config()
|
|||||||
function get_iframe_whitelist()
|
function get_iframe_whitelist()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
'//www.youtube.com',
|
|
||||||
'http://www.youtube.com',
|
'http://www.youtube.com',
|
||||||
'https://www.youtube.com',
|
'https://www.youtube.com',
|
||||||
'http://player.vimeo.com',
|
'http://player.vimeo.com',
|
||||||
@ -62,27 +62,23 @@ function write_debug()
|
|||||||
// Get available timezone
|
// Get available timezone
|
||||||
function get_timezones()
|
function get_timezones()
|
||||||
{
|
{
|
||||||
$timezones = \timezone_identifiers_list();
|
$timezones = timezone_identifiers_list();
|
||||||
return array_combine(array_values($timezones), $timezones);
|
return array_combine(array_values($timezones), $timezones);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all supported languages
|
// Get all supported languages
|
||||||
function get_languages()
|
function get_languages()
|
||||||
{
|
{
|
||||||
$languages = array(
|
return array(
|
||||||
'cs_CZ' => t('Czech'),
|
'cs_CZ' => 'Čeština',
|
||||||
'de_DE' => t('German'),
|
'de_DE' => 'Deutsch',
|
||||||
'en_US' => t('English'),
|
'en_US' => 'English',
|
||||||
'es_ES' => t('Spanish'),
|
'es_ES' => 'Español',
|
||||||
'fr_FR' => t('French'),
|
'fr_FR' => 'Français',
|
||||||
'it_IT' => t('Italian'),
|
'it_IT' => 'Italiano',
|
||||||
'pt_BR' => t('Portuguese'),
|
'pt_BR' => 'Português',
|
||||||
'zh_CN' => t('Simplified Chinese'),
|
'zh_CN' => '简体中国',
|
||||||
);
|
);
|
||||||
|
|
||||||
asort($languages);
|
|
||||||
|
|
||||||
return $languages;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all skins
|
// Get all skins
|
||||||
@ -94,7 +90,7 @@ function get_themes()
|
|||||||
|
|
||||||
if (file_exists(THEME_DIRECTORY)) {
|
if (file_exists(THEME_DIRECTORY)) {
|
||||||
|
|
||||||
$dir = new \DirectoryIterator(THEME_DIRECTORY);
|
$dir = new DirectoryIterator(THEME_DIRECTORY);
|
||||||
|
|
||||||
foreach ($dir as $fileinfo) {
|
foreach ($dir as $fileinfo) {
|
||||||
|
|
||||||
@ -180,6 +176,7 @@ function new_tokens()
|
|||||||
'api_token' => generate_token(),
|
'api_token' => generate_token(),
|
||||||
'feed_token' => generate_token(),
|
'feed_token' => generate_token(),
|
||||||
'bookmarklet_token' => generate_token(),
|
'bookmarklet_token' => generate_token(),
|
||||||
|
'fever_token' => substr(generate_token(), 0, 8),
|
||||||
);
|
);
|
||||||
|
|
||||||
return Database::get('db')->table('config')->update($values);
|
return Database::get('db')->table('config')->update($values);
|
||||||
@ -242,6 +239,7 @@ function get_all()
|
|||||||
'theme',
|
'theme',
|
||||||
'api_token',
|
'api_token',
|
||||||
'feed_token',
|
'feed_token',
|
||||||
|
'fever_token',
|
||||||
'bookmarklet_token',
|
'bookmarklet_token',
|
||||||
'auth_google_token',
|
'auth_google_token',
|
||||||
'auth_mozilla_token',
|
'auth_mozilla_token',
|
||||||
|
@ -2,6 +2,14 @@
|
|||||||
|
|
||||||
namespace Schema;
|
namespace Schema;
|
||||||
|
|
||||||
|
use PDO;
|
||||||
|
use Model\Config;
|
||||||
|
|
||||||
|
function version_29($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('ALTER TABLE config ADD COLUMN fever_token INTEGER DEFAULT "'.substr(Config\generate_token(), 0, 8).'"');
|
||||||
|
}
|
||||||
|
|
||||||
function version_28($pdo)
|
function version_28($pdo)
|
||||||
{
|
{
|
||||||
$pdo->exec('ALTER TABLE feeds ADD COLUMN rtl INTEGER DEFAULT 0');
|
$pdo->exec('ALTER TABLE feeds ADD COLUMN rtl INTEGER DEFAULT 0');
|
||||||
@ -14,7 +22,7 @@ function version_27($pdo)
|
|||||||
|
|
||||||
function version_26($pdo)
|
function version_26($pdo)
|
||||||
{
|
{
|
||||||
$pdo->exec('ALTER TABLE config ADD COLUMN bookmarklet_token TEXT DEFAULT "'.\Model\Config\generate_token().'"');
|
$pdo->exec('ALTER TABLE config ADD COLUMN bookmarklet_token TEXT DEFAULT "'.Config\generate_token().'"');
|
||||||
}
|
}
|
||||||
|
|
||||||
function version_25($pdo)
|
function version_25($pdo)
|
||||||
@ -95,7 +103,7 @@ function version_15($pdo)
|
|||||||
|
|
||||||
function version_14($pdo)
|
function version_14($pdo)
|
||||||
{
|
{
|
||||||
$pdo->exec('ALTER TABLE config ADD COLUMN feed_token TEXT DEFAULT "'.\Model\Config\generate_token().'"');
|
$pdo->exec('ALTER TABLE config ADD COLUMN feed_token TEXT DEFAULT "'.Config\generate_token().'"');
|
||||||
}
|
}
|
||||||
|
|
||||||
function version_13($pdo)
|
function version_13($pdo)
|
||||||
@ -105,7 +113,7 @@ function version_13($pdo)
|
|||||||
|
|
||||||
function version_12($pdo)
|
function version_12($pdo)
|
||||||
{
|
{
|
||||||
$pdo->exec('ALTER TABLE config ADD COLUMN api_token TEXT DEFAULT "'.\Model\Config\generate_token().'"');
|
$pdo->exec('ALTER TABLE config ADD COLUMN api_token TEXT DEFAULT "'.Config\generate_token().'"');
|
||||||
}
|
}
|
||||||
|
|
||||||
function version_11($pdo)
|
function version_11($pdo)
|
||||||
@ -119,7 +127,7 @@ function version_11($pdo)
|
|||||||
|
|
||||||
$rq->execute();
|
$rq->execute();
|
||||||
|
|
||||||
$items = $rq->fetchAll(\PDO::FETCH_ASSOC);
|
$items = $rq->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
foreach ($items as $item) {
|
foreach ($items as $item) {
|
||||||
|
|
||||||
|
@ -72,15 +72,27 @@
|
|||||||
</div>
|
</div>
|
||||||
<section>
|
<section>
|
||||||
<div class="alert alert-normal">
|
<div class="alert alert-normal">
|
||||||
<h3 id="api"><?= t('API') ?></h3>
|
<h3 id="fever"><?= t('Fever API') ?></h3>
|
||||||
|
<ul>
|
||||||
|
<li><?= t('Link:') ?> <strong><?= Helper\get_current_base_url().'fever/' ?></strong></li>
|
||||||
|
<li><?= t('Username:') ?> <strong><?= Helper\escape($values['username']) ?></strong></li>
|
||||||
|
<li><?= t('Password:') ?> <strong><?= Helper\escape($values['fever_token']) ?></strong></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="alert alert-normal">
|
||||||
|
<h3 id="bookmarks"><?= t('Bookmarks') ?></h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<?= t('Bookmarklet:') ?>
|
<?= t('Bookmarklet:') ?>
|
||||||
<a href="javascript:location.href='<?= Helper\get_current_base_url() ?>?action=subscribe&token=<?= urlencode($values['bookmarklet_token']) ?>&url='+encodeURIComponent(location.href)"><?= t('Subscribe with Miniflux') ?></a> (<?= t('Drag and drop this link to your bookmarks') ?>)
|
<a href="javascript:location.href='<?= Helper\get_current_base_url() ?>?action=subscribe&token=<?= urlencode($values['bookmarklet_token']) ?>&url='+encodeURIComponent(location.href)"><?= t('Subscribe with Miniflux') ?></a> (<?= t('Drag and drop this link to your bookmarks') ?>)
|
||||||
<li>
|
<li>
|
||||||
<?= t('Bookmarks RSS Feed:') ?>
|
<a href="<?= Helper\get_current_base_url().'?action=bookmark-feed&token='.urlencode($values['feed_token']) ?>" target="_blank"><?= t('Bookmark RSS Feed') ?></a>
|
||||||
<a href="<?= Helper\get_current_base_url().'?action=bookmark-feed&token='.urlencode($values['feed_token']) ?>" target="_blank"><?= Helper\get_current_base_url().'?action=bookmark-feed&token='.urlencode($values['feed_token']) ?></a>
|
|
||||||
</li>
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="alert alert-normal">
|
||||||
|
<h3 id="api"><?= t('API') ?></h3>
|
||||||
|
<ul>
|
||||||
<li><?= t('API endpoint:') ?> <strong><?= Helper\get_current_base_url().'jsonrpc.php' ?></strong></li>
|
<li><?= t('API endpoint:') ?> <strong><?= Helper\get_current_base_url().'jsonrpc.php' ?></strong></li>
|
||||||
<li><?= t('API username:') ?> <strong><?= Helper\escape($values['username']) ?></strong></li>
|
<li><?= t('API username:') ?> <strong><?= Helper\escape($values['username']) ?></strong></li>
|
||||||
<li><?= t('API token:') ?> <strong><?= Helper\escape($values['api_token']) ?></strong></li>
|
<li><?= t('API token:') ?> <strong><?= Helper\escape($values['api_token']) ?></strong></li>
|
||||||
|
Loading…
Reference in New Issue
Block a user