#!/usr/bin/perl # getBibTeXFromZotero - get a bibtex file with all references from Zotero # using MozRepl # # Requires installation of MozRepl from CPAN, Firefox, Zotero, and MozRepl # firefox extension. # # The bibtex file will be output to stdout # # Jason Friedman (write.to.jason@gmail.com, www.curiousjason.com) # # Last updated 14th September 2016: allow to use another translator for export (e.g. biblatex), either using translator ID or its name, # allow to use a collection name instead of its index, merge the two scripts together with command-line arguments # translatorObj.setLibraryID(null); did not work for older versions of Zotero, it should now work for both old and new versions # (thanks to Mehdi Bouaziz for these changes) # Update 4th October 2015: Change timeout to 120 seconds (for large files) # Added line translatorObj.setLibraryID(null) to make work with Zotero version >= 4.0.27.1 # (thanks to Werner Koch ) use strict; use warnings; use File::Temp qw/ tempfile/; use Getopt::Long; use MozRepl; use Pod::Usage; Getopt::Long::Configure('bundling'); my $translator = '9cb70025-a888-4a29-a210-93ec52da40d4'; # BibTeX my $help = 0; my $debug = 0; GetOptions('t|translator=s' => \$translator, 'help|?' => \$help, 'debug' => \$debug) or pod2usage(1); pod2usage(1) if $help or @ARGV > 1; my ($collection) = @ARGV; # temporary file to store bibliography (undef,my $filename) = tempfile(); my $repl = MozRepl->new; # Make it quiet (comment out the next line to see the error messages) $repl->setup_log([qw/error fatal/]); $repl->setup; # Set the timeout to 120 seconds $repl->client->{telnet}->timeout(120); my $executestring = q| var zotero = Components.classes['@zotero.org/Zotero;1'].getService(Components.interfaces.nsISupports).wrappedJSObject; var translatorObj = new Zotero.Translate('export'); var error = ''; |; if (defined $collection) { $executestring .= "var collections = Zotero.getCollections();\n"; if ($collection =~ /^[0-9]+$/) { $executestring .= "var collection = collections[$collection];\n"; } else { $executestring .= q|var collection = undefined; for (var i in collections) if (collections[i]['_name'] == "| . $collection . q|") { collection = collections[i]; break; } |; } $executestring .= q|if (collection === undefined) error += "Unable to find collection '| . $collection . q|'\n"; else translatorObj.setCollection(collection); |; } else { $executestring .= q|if (translatorObj.setLibraryID) translatorObj.setLibraryID(null); |; } if ($translator =~ /^[-0-9a-f]{36}$/i) { $executestring .= "translatorObj.setTranslator('$translator');\n"; } else { $executestring .= q|var translators = zotero.Translators.getAll(); var translatorID = undefined; for (var i in translators) if (translators[i]['label'].toUpperCase() == "| . uc($translator) . q|") { translatorID = translators[i]['translatorID']; break; } if (translatorID === undefined) error += "Unable to find translator label '| . $translator . q|'\n"; else translatorObj.setTranslator(translatorID); |; } $executestring .= q|if (error == '') { var filename = '| . $filename . q|'; var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile); file.initWithPath(filename); translatorObj.setLocation(file); translatorObj.translate(); } else { alert(error); } |; if ($debug) { print $executestring; print "\n"; exit; } $repl->execute($executestring); # print to stdout open(FH, $filename) or die "Can't open $filename: $!"; foreach(){ print; } print "\n"; close(FH); # delete the temporary file unlink($filename); __END__ =head1 NAME getBibTeXFromZotero =head1 SYNOPSIS getBibTeXFromZotero [--translator ] [] can be a translatorID or a translator label can be a collection number or a collection name