I’m trying to write a little plugin that converts labels to tags in generated feeds (so I can get them into other apps). Since I have little to no experience with ttrss plugins I’d really apppreciate your input.
And I have no experience with public functions.
If I understand this correctly I need to write a plugin that hooks into HOOK_ARTICLE_EXPORT_FEED. It will be called before the generated feed is created (is this triggered when the URL of the generated feed is called?).
So here’s what I have so far:
<?php
class Labels_To_Tags extends Plugin {
private $host;
public function about() {
return array(1.0,
'Add labels as tags in generated feeds',
'C');
}
public function api_version() {
return 2;
}
public function init( $host ) {
$this->host = $host;
$host->add_hook( $host::HOOK_ARTICLE_EXPORT_FEED, $this );
}
public function hook_article_export_feed( $line, $feed, $is_cat ) {
// get all LABELS for this article / line
$labels = Article::get_article_labels($line['id']);
if (count($labels) > 0) {
// get all TAGS for this article / line
$tags = Article::get_article_tags($line['id']);
// if article has tags add them to array first
if (count($tags) > 0) {
$article['tags'] = array();
foreach ($tags as $tag) {
array_push($article['tags'], $tag);
}
} else {
$article['tags'] = array();
}
foreach ($labels as $label) {
array_push($article['tags'], $label);
}
}
return $line;
}
}
?>
@JustAMacUser hope you don’t mind me pinging you but I saw in some other post that you have some experience with plugins for generated feeds.
Could you please take a quick look.
If you spot obvious errors or if the whole approach is wrong please let me know.
It would such a great help and save me a lot of time/work if I could make this work.
Thank you.
The code has a small error in that you’re receiving the article into the variable $line but only ever manipulating the variable $article. I think this is just a copy/paste error so you’d just need to change the references to $article.
To address your question, I don’t think this is going to work because on line 124 the tags are fetched and added to the published feed without using the tags key of the $line array. This means all the changes from the plugin would never be used.
In order to make this work you’d need to change the core, replacing:
But, as always, I recommend against changing the core because then you have to maintain that forever.
You might be better off hooking earlier, when the articles are coming into the database after fetching. I haven’t looked to see if plugin hooks would support that.
As an aside: I could see that it might be beneficial to move the tags portion earlier in the code so that plugins can work with that data. I’ll let fox weigh in on that. I don’t mind doing a PR he’s okay with the change but doesn’t want to do it himself.
And your hook_article_export_feed method would be simplified to something like:
public function hook_article_export_feed( $line, $feed, $is_cat ) {
// get all LABELS for this article / line
$labels = Article::get_article_labels($line['id']);
if (count($labels) > 0) {
foreach ($labels as $label) {
array_push($line['tags'], $label);
}
$line['tags'] = array_unique($line['tags']);
}
return $line;
}
I threw in array_unique; it’s not strictly necessary but would avoid having two of the same feed categories if an article had both a label and tag with the same name.
Thank you so much @JustAMacUser and fox!
I’ve just updated but unfortunately the labels don’t show up as tags in my generated feed for starred articles. I’ve disabled and reenabled the plugin and tried this with several articles, no luck.
Here’s the plugin code incl. your improved part:
<?php
class Labels_To_Tags extends Plugin {
private $host;
public function about() {
return array(1.0,
'Add labels as tags in generated feeds',
'nvab');
}
public function api_version() {
return 2;
}
public function init( $host ) {
$this->host = $host;
$host->add_hook( $host::HOOK_ARTICLE_EXPORT_FEED, $this );
}
public function hook_article_export_feed( $line, $feed, $is_cat ) {
// get all LABELS for this article / line
$labels = Article::get_article_labels($line['id']);
if (count($labels) > 0) {
foreach ($labels as $label) {
array_push($line['tags'], $label[1]); // the name of the label is in [1]
}
$line['tags'] = array_unique($line['tags']);
}
return $line;
}
}
?>
I did more testing and it seems that my plugin has no effect:
Even if I only include this line in the hook_article_export_feed function in my plugin: array_push($line['tags'], 'testlabel');
testlabel is not part of the tags in the generated feed.
If I add this line in tt-rss/classes/handler/public.php (in the atom part below line 72) it appears in the generated feed.
I don’t know why my plugin has no effect, not even with this simple test line.
btw since your plugin is running without valid user session, i suggest verifying that you pass a valid owner uid - if needed - to methods like get_article_labels and anything else from tt-rss core.
It all works now on the tt-rss side, labels appear as categories in the generated feed.
Unfortunately, all the trouble may have been for nothing because DevonthinkPro (DTP) which I use to archive stuff just won’t see the extra tags that the plugin added.
It’s as if DTP received the articles from the generated feed before my plugin even had a chance to add the extra tags.
Anyway, I really wanted to thank you and JustAMacUser for all your help. I really appreciate it. Thank you so much.
If I add the code to append the labels as tags just after$line['tags'] (line 183) has been defined in tt-rss/classes/handlers/public.php then DTP picks up the extra tags (labels). And that’s so far the only (bad) way I’ve managed to get these labels as tags into DTP.
Is my plugin too slow/late to modify the generated feed and DTP so fast at grabbing it that by the time my plugin is done DTP has already finished grabbing the unmodified generated feed without the changes?
BTW when you said I could trying changing the link slightly which one did you refer to?
<?php
class Labels_To_Tags extends Plugin {
private $host;
public function about() {
return array(1.0,
'Add labels as tags in generated feeds',
'vnab',
true);
}
public function api_version() {
return 2;
}
public function init( $host ) {
$this->host = $host;
$host->add_hook( $host::HOOK_ARTICLE_EXPORT_FEED, $this );
}
public function hook_article_export_feed( $line, $feed, $is_cat ) {
$owner_uid = $this->host->get_owner_uid();
// get all LABELS for this article / line
$labels = Article::get_article_labels($line['id'], $owner_uid);
if (count($labels) > 0) {
foreach ($labels as $label) {
array_push($line['tags'], $label[1]); // the name of the label is in [1]
}
$line['tags'] = array_unique($line['tags']);
}
return $line;
}
}
?>
well, you’re getting owner_uid the wrong way, $this->host->get_owner_uid(); is not going to return anything because there’s nobody logged on. it looks like its not actually easily accessible from this hook so i’ll add it to the function prototype (don’t forget to add it to the hook):
Yes, that did it! Thank you so much. That’s incredible.
There’s just one more thing that’s been on my mind:
after many years my archive has now over 150 tags which I’d have to create/mirror in tt-rss.
Will tt-rss be ok with that many labels? Have you ever had any kind of user feedback that suggests otherwise?
And is there a way to batch import/create that many labels?
But really, you made my day. Thank you, fox. Good night.
The background story: recently I’ve found a new iOS client app which supports ttrss without the fever plugin. The developer is very friendly and accommodating. We didn’t find a ttrss API method for assigning/editing/removing article tags but we found this plugin that justamacuser once mentioned and which seems to add API support for labels.
That’s how I got the idea of using labels as tags.
I briefly considered if it was possible to write a plugin that adds such api methods for tags but really, from a realistic pov, that’s just so beyond what I can achieve.
So hopefully the app will eventually support labels and then I’m quite content with that. It’s not tags but probably the next best thing. The important thing is that I can assign keywords to articles in the iOS client app and they end up in the archive eventually. Some time ago I wouldn’t even have dared to dream about this. Very nice.
well, you could ask that plugin guy to add methods for tags, those might be useful for his project and others who might be using that plugin.
like i said, tags would fit a lot better for what you’re trying to accomplish, labels UI is not really designed to deal with hundreds of them. it’s for a higher level categories of interest, i guess, of which you’d have less.
Yeah, seems that I was a little too eager and overlooked the (admittedly small ) banner that announced that he set the repo to archived/read-only. His successor ‘app’ uses the fever plugin for tt-rss. It is what it is…
Before I give up on assigning article keywords altogether in iOS client apps and return to using the fever plugin again I might as well wait and see if the labels approach works out.
Thank you for your advice and help.