In an attempt to revitalize my blog, I recently switched themes, this time to the cool Magazeen theme and decided to highlight some fresh and inspiring content by cherry-picking tweets. Inspired by Dan Cederholm's Simplebits, where "tweets" were mixed with blog posts way before twitter was started, I decided to aggregate some of my tweets on my site. Let's see how I've done it.
Well, it sounds easy, right, since Twitter has this feed of tweets for each user, so I could just grab my feed and display items from there? First of all, I needed to be able to highlight them among blog posts. I'm still undecided on allowing comments or not (not that I expect floods of comments, but picking tweets out of their home medium and allowing comments here might not be conceptually right). But them being nodes allows me to list them with the blog posts and to include them in the site feed. While this might get duplicate content for people who both follow my blog and twitter feed, I decided to highlight some items for their usefulness, and having them as nodes ensures that they can be on for longer, sticking them out of the quick waterfall of twitter.
So to create nodes of feed items, I picked the coolest kid on the block, Feeds module. It creates tweet nodes for me dutifully (see the project page for setup instructions and video links). For those nodes to be unpublished by default, I learned (via twitter), that the default node type settings are adhered to. This still does not allow me to provide a default author and default input format (see below), but it is an experiment so far, so it will get better.
Tweets have certain special items like @username references and #hashtags. These should be linked to their respective twitter.com pages, and twitter module has input filters for these which I could use to build up an input format. (Given my use case, I had no use for the rest of the twitter module, so I took the format code into my site-specific module, and do not actually use twitter.module.) The twitter feed also includes my username at the beginning, which my site readers will either know or do not care about, so I also wrote a quick filter which will transform my username to a "from twitter" link at the end of the node body.
Finally, some custom theming needed to be done for tweet nodes. Hiding the node title and author seemed appropriate, as well as some font size adjustments, so tweets stand out a bit.
I'll surely keep refining this, and if nothing else, the cherry-picking process gives me reasons to come back to my blog more often, so it might inspire me to write more, which could be useful on its own.
Way to go!
I'm glad to see Feeds being put to use.
2 issues that may be related / of interest:
- Assign author of imported nodes http://drupal.org/node/652180
- Currently default filter configuration is being used for aggregated nodes, more granular control may be desired (no issue yet).
I like this theme by the way.
format assignment
For format assignment, it might be possible to use a module which sets default input formats per node types, and if feedapi just picks that up, then we can generalize this functionality (instead of building it into feeds). Per-content type input formats are a popular topic anyway.
Would you be able so share
Would you be able so share your module code?
used twitter module code
Used the two existing filters from twitter module and this was my added filter:
$text = preg_replace('!^([^:]+):(.+)$!', '<p class="tweet">\2</p><p class="reference"><a href="http://twitter.com/\1">from twitter</a></p>', $text);
Twitter Module Input Filter Implementation
Hey there Gábor,
Thanks for this helpful post. I'm looking to do essentially the very same thing you've described here. I have just a few questions and would be really grateful for any help you may be able to offer.
/**
* Implementation of hook_filter().
* - Twitter @username converter:
* .Converts Twitter-style @usernames into links to Twitter account pages.
* - Twitter #hashtag converter:
* .Converts Twitter-style #hashtags into links to hashtags.org.
*/
function twitter_filter($op, $delta = 0, $format = -1, $text = '') {
switch ($op) {
case 'list':
return array(0 => t('Twitter @username converter'), 1 => t('Twitter #hashtag converter'));
case 'description':
switch ($delta) {
case 0:
return t('Converts Twitter-style @usernames into links to Twitter account pages.');
case 1:
return t('Converts Twitter-style #hashtags into links to hashtags.org.');
default:
return;
}
case 'process':
switch ($delta) {
case 0:
return twitter_link_filter($text);
case 1:
return twitter_link_filter($text, '#', 'http://search.twitter.com/search?q=%23');
default:
$text;
}
default:
return $text;
}
}
/**
* Implementation of hook_filter_tips().
*/
function twitter_filter_tips($delta, $format, $long = FALSE) {
global $base_url;
switch ($delta) {
case 0:
return t('Twitter-style @usersnames are linked to their Twitter account pages.');
case 1:
return t('Twitter-style #hashtags are linked to !url.', array('!url' => '<a href="http://search.twitter.com/">search.twitter.com</a>'));
}
}
/**
* This helper function converts Twitter-style @usernames and #hashtags into
* actual links.
*/
function twitter_link_filter($text, $prefix = '@', $destination = 'http://twitter.com/') {
$matches = array(
'/\>' . $prefix . '([a-z0-9_]+)/i',
'/^' . $prefix . '([a-z0-9_]+)/i',
'/(\s+)' . $prefix . '([a-z0-9_]+)/i',
);
$replacements = array(
'><a href="' . $destination . '${1}">' . $prefix . '${1}</a>',
'<a href="' . $destination . '${1}">' . $prefix . '${1}</a>',
'${1}<a href="' . $destination . '${2}">' . $prefix . '${2}</a>',
);
return preg_replace($matches, $replacements, $text);
}