Return to the main TTYtter page
TTYtter Advanced Usage: FOR LEGACY VERSIONS ONLY
Version 1.0.x changes backwards compatibility! Do not use this
document for current versions of TTYtter!
While many extensions will still work, some will
need to be updated for 1.0.0's multi-module system, and still others will
need updates for future state serialization support.
0.9.12 is the
last version to completely support the original TTYtter API
in the manner described below. If you want to create extensions for
the current version,
go to the main page.
Using the TTYtter API, you can considerably customize how the
client interacts with you and displays tweets and direct messages,
as well as use ttytter as a rapid-deployment engine
to construct Twitter bots. ttytter takes care of posting and
receiving tweets and DMs,
and your application can supersede as much or as little
functionality as it needs to. You don't even need to write loops or handle
any actual transactions with the Twitter server.
Please note that certain options or API operations are limited to
certain minimum versions. The API does not exist in TTYtter
versions prior to 0.4. Operations requiring a minimum version of
TTYtter later than this will be specified.
Here are the command line options relevant to the API (see the
full list of command-line options):
- -lib=[library path] (optional)
- Specifies the library to use for custom handlers and setup. The library is
directly required by ttytter and becomes part of it. Your
library must return a true value at the end (an idiom like 1; as
the last line will suffice nicely). If the path of the specified library is
not guaranteed to be in @INC, a fully qualified filespec would be a
good idea.
The actual "methods" and globals you can and must use are
discussed below, but I strongly advise reading this
whole page first.
- -daemon (optional)
- Forces ttytter to run as a "detached" process in the
background (the PID of the new background process is reported). If no library
is given, then this is as if one were running the regular background
update process, but without a console process (so updates continue to appear,
but you must use a command line incantation like
ttytter -status=... or something similar to
actually post, as you are in your shell and not TTYtter).
You must kill the process manually to shut it down.
If a library is defined, then this is the basis of how to construct a fully
automated bot. We'll talk more about this below.
- -twarg=[argument] (optional, 0.7.0+)
- Specifies a user-defined argument string, allowing you to pass data
to your extension library from outside of TTYtter.
-silent might also be handy for independent bots (optional,
0.6.0+).
If your bot is passive and doesn't need to post, it may be helpful
and quite a bit faster to
run it in anonymous mode with -anonymous (optional, 0.7.0+).
This will not work for the examples below that generate tweets.
I have always found it easiest to learn by example, so let's look at three
simple but useful examples before we get to the
API reference. It will make a lot more sense if this
is your first time.
Before getting started: Scripting (0.8+)
Sometimes you don't have to write an extension at all. If you are simply
requesting data that you can get with regular TTYtter commands, and
you have 0.8.0+, then simply scripting TTYtter would be enough.
Suppose you just wanted to find out the last 20 tweets of user
twitterapi and then grep it for something:
echo "/again twitterapi" | ttytter -script -anonymous | grep -i banana
Or, maybe you want to find Japanese wannabe poets (0.9.4+):
echo "/search #haiku" | ttytter -script -anonymous
The -script argument, as you
will recall, disables automatic updates, sets -silent, and disables
ANSI colour and other settings inappropriate for not-a-terminal.
In the above example,
if you're simply interested in fetching specific types of tweets or filtering
out others, a
-filter option and a set of hashtags could be all you require. See
Command-line options.
Obviously, you are not limited to single commands; you could have an entire
command file if you like, and just pass that in with redirection or as an
argument (ttytter -script my_script_file).
Remember that if you want
to wait for all processes to finish emitting data before ending the script,
you must end your file with /end
(or end-of-file will be seen as
/quit and all pending queued asynchronous commands will be cancelled).
For example, this does not work:
echo "/a" | ttytter -script # THIS DOES NOT WORK
You need to rewrite it like this (here using the printf command):
printf "/a\n/end\n" | ttytter -script
which sends the /again and then makes the console wait until
the asynchronous command has finished (/end). In particular,
remember that /again (without arguments), /refresh,
/dmrefresh and /dmagain are all asynchronous. But
you could stack these commands (e.g.
printf "/a\n/dma\n/end\n" | ttytter -script
would fetch both your timeline and your direct messages, in order [tweets
first, then DMs], and then wait for both tasks to finish). There is no
harm in using /end for synchronous commands: it simply becomes
an implied /quit. When in doubt,
add it, especially if you are getting no output from a command.
Scripting is limited only to what commands the console understands, since
basically you're driving the console. Similarly, it is difficult to hook error
responses for any given particular command since the console does not offer
this behaviour and thus scripted applications cannot be considered bulletproof.
Thus, if you need to change TTYtter's behaviour in a way the
console does not support, or need to write custom behaviour for enhanced
reliability or fallbacks, you will need to use an extension -- which brings us
to our first training-wheels, yet useful, example.
ARE YOU USING AN OLD VERSION? READ ME FIRST!:
In the examples below, most of them will print to a filehandle reference
$stdout instead of to STDOUT directly. This is the
recommended practice starting in version 0.9.0 since $stdout may not
directly point to the actual file descriptor for standard output, and may
need to pass through filtering to support all the user's options. If you
are writing for versions of TTYtter prior to 0.9, however, you
should substitute STDOUT for $stdout in the following
sections of code.
A first example: Displaying more tweet metadata
TTYtter throws away a lot of (in this context) irrelevant metadata
by default when it formats tweets, but suppose you're interested in seeing
a little more under the surface. Here is an example of a more florid way of
displaying tweets. Place this into a separate file (example name:
spammytweets.pl) and invoke it with
ttytter -lib=spammytweets.pl or wherever you stored it:
$handle = sub {
my $ref = shift;
print $stdout ($ref->{'id'}, " ",
&descape($ref->{'user'}->{'name'}), " ",
&descape($ref->{'user'}->{'location'}), " ==> ",
&descape($ref->{'text'}), "\n");
return 1;
};
This introduces the general way of writing handlers: rather than having
regular Perl subroutines, instead you assign anonymous subroutine
references to specific global scalars (listed below).
This particular subroutine reference, $handle, is called for every
tweet that is to be displayed and is handed a hash reference containing the
individual fields of the tweet.
Until 0.9.5,
a peculiarity of the way ttytter handled JSON is that it adds
certain unambiguous quote-escapes to aid it in interpretation. For those
fields that are likely to have quote-escapes (free text fields, particularly),
the library function &descape was used to turn ttytter's
internal quote-escapes back into regular quotes.
After 0.9.5, changes to the
JSON interpreter removed that need, but there are other conversion steps that
&descape performs which you will still probably want, so you
should still be calling this routine. It is not done automatically
for you for reasons of efficiency, since it is not needed for fields you will
not be displaying or digesting in your routine.
The handler returns 1 to tell ttytter that one logical tweet
was handled. If it had declined to handle it for some reason, it should
return zero.
Note that the library just ends. Any other setup that needs to be done should
be done by the library before it exits. Because an anonymous subroutine
reference is considered a "true" value, this small library does not need the
1; idiom at the end.
With this library running, suddenly ttytter's background updates
take a new form:
92780182 Jenny How Malaysia ==> nice cold morning.. feels so lazy.... :)
92780192 Clifford Dog Desierto de Sonora Mexico ==> @ingridipity: huy que mal, espero que sea Cerveza Ligera ;)
92780202 Kelly Sims Torrance, Ca ==> also, the showcase on ee site is cool to see how others are using it
You can also use this with a script to fetch tweets and format them in a
particular fashion, suitable for piping to something else; remember, using
-script and -lib=... together is completely valid!
This exercise is left for the reader.
An "enhanced" first example: A Twitter filter
Suppose you are only interested in one particular subject, let's say, bananas.
It should be entirely obvious that you can filter on any term just by using
a regular expression search on the relevant JSON field. Yes, you could just
grep the output or use the -filter option,
but this is another way:
$handle = sub {
my $ref = shift;
my $text = &descape($ref->{'text'});
return 0 if ($text !~ /banana/i);
print $stdout ($ref->{'id'}, " ",
&descape($ref->{'user'}->{'name'}), " ",
&descape($ref->{'user'}->{'location'}), " ==> ",
$text, "\n");
return 1;
};
Note that tweets that do not match up are not printed, and a zero is returned
to alert TTYtter that the tweet was declined. Only if it actually
is accepted (in this case for printing) is one returned.
The idea of "accepting" a tweet is more closely examined in the next
example.
A second example: A Twitter logger
Naturally, you are not restricted merely to output. For those inclined
towards blackmail, you can create a "logger" that not only displays the
tweets it receives, but neatly organizes them into files:
$store->{'master'} = "$ENV{'HOME'}/twt.bookmark";
if(open(S, $store->{'master'})) {
$last_id = 0+scalar(<S>);
print $stdout "LIB: init last id: $last_id\n";
close(S);
}
$handle = sub {
my $ref = shift;
return 0 if ($ref->{'user'}->{'protected'} eq 'true');
my $sn = &descape($ref->{'user'}->{'screen_name'});
my $string = &descape($ref->{'created_at'}) .
" \@$sn " .
&descape($ref->{'user'}->{'name'}) .
" says: " .
&descape($ref->{'text'}) . "\n";
$sn =~ s#/#-#g;
open(S, ">>", "${sn}.twt") ||
die("can't open ${sn}.twt for append: $!\n");
binmode(S, ":utf8") unless ($seven);
print S $string;
close(S);
&defaulthandle($ref);
return 1;
};
$conclude = sub {
print $stdout "LIB: writing out: $last_id\n";
if(open(S, ">".$store->{'master'})) {
print S $last_id;
close(S);
} else {
print $stdout "LIB: failure to write: $!\n";
}
&defaultconclude;
};
This library not only displays the tweets you receive, but it also organizes
them into individual [screenname].twt files with date stamps and
full names. It will not log users who are protected.
This more elabourate example also illustrates some other standard things:
Make the above into an automated logging bot "instantly"
It should be obvious that this could be made into a background bot simply
by turning off the output you don't need to have displayed
(i.e., either with the -silent option to suppress everything,
or commenting out or deleting unneeded output lines like the LIB:
output and &defaulthandle), starting
ttytter with -lib=... and -daemon, and then
letting the bot just slurp tweets out into files in the background. Presto,
instant logging bot! Remember that even though no logical tweets are
being displayed, they are still being accepted, so $handle should
still return 1.
Make the above into a hashtag logger "instantly" (0.9.4+)
So, let's say you built the automated logging bot above,
but you're having a conference or an interview between lots of people
on Twitter (like #bigshindig). If you're following all those people,
you could filter for the hashtag, and return 0 for tweets that don't contain
it.
But say you're not following everyone in the conversation, or there
are too many people to follow. In that
case, turn off your timeline and then put the hashtag into $track.
Then, you'll only see that hashtag. To do this, insert these lines
at the very beginning:
$track = '#bigshindig';
$notimeline = 1;
A third example: A Twitter parrot
First, a word of warning: please don't actually run this, you will
irritate a lot of people! This is a very silly example, but it will
give you a basis on how to create interactive applications. It is
intentionally broken so that it can't be used as is, but yet serve an
educational purpose.
This library creates a Twitter parrot, which is to say any tweet it can
see, it will tweet again. To avoid an endless loop, it determines the user
it is running as and won't parrot back something it itself has said.
(This example, therefore, will not work in anonymous mode.)
die("I can't run anonymously") if ($anonymous);
$store->{'dontecho'} = $whoami;
# if this fails, or we are prior to 0.7.0, we must split $user
($store->{'dontecho'}, $store->{'crap'}) = split(/:/, $user, 2)
if (!length($whoami));
$handle = sub {
my $ref = shift;
my $sn = &descape($ref->{'user'}->{'screen_name'});
return if ($sn eq $store->{'dontecho'});
my $string = "\@$sn " . &descape($ref->{'text'});
die("broken");
&updatest($string);
&defaulthandle($ref);
return 1;
};
Most of this we have seen before, except for the global $whoami
(and/or $user;
be nice: the user's password may be there too, so behave please), and the
subroutine &updatest, which is used to send a new status for
the current user. It should be obvious to the reader that making a more
interactive system is just a matter of parsing the text of the tweet, and
then tweeting out a smarter or at least less aggravating response.
Third example redux: Making the parrot use direct messages instead
Or, you can make it much, much less aggravating by having it only
talk to people who actually directly message it -- hence, surprise surprise,
direct messaging support.
Direct messaging operation is supported in 0.6 and higher,
and is handled almost exactly the same way as regular tweets
except that it uses $dmhandle instead. These changes to the
above example should suffice:
[...]
$dmhandle = sub {
[...]
my $sn = &descape($ref->{'sender'}->{'screen_name'});
[...]
my $string = "D $sn " . &descape($ref->{'text'});
[...]
};
Here, we query the screen name from the sender field, reply using the
Twitter D command in a standard post, and return 1 to tell
TTYtter that the direct message was accepted and acted upon.
Note that only a minimal change in logic is required to make this happen
on direct messages instead of public tweets and vice versa.
The "anti-loop" logic isn't really needed here, but is nice to account
for and won't harm anything either.
To make such bots effective and the communication bidirectional,
essentially you must be following everyone
who follows you. This can be done with the Twitter API in a programmatic,
delayed fashion, but if you are doing this on a large scale you should
speak with the Twitter developers (now is a good time to subscribe to
twitter-development-talk).
An exercise for the reader: as written, just like in our logger example,
every time the bot starts it will go through its most recent 20 DMs all
over again, even if it had already processed them previously.
Change this example to use a bookmark as well (hint:
$dmconclude and $last_dm).
Tying it all together: a publicly-accessible
TTYtter-powered application
It is also possible to drive TTYtter as a client instead of as a bot.
@funkatron brought up
a Gopher twitter interface on the Twitter development list, which being as I
am a huge gopher fan
(gopher URL) and a
Twitter nut,
sounded like a logical junction of two obsessions.
The result is Twitpher (gopher URL),
a gateway that reads the public timeline or a specified user's timeline
and displays it as a formatted gopher menu. If your browser cannot handle
gopher URLs, here is a HTTP proxied
link to see what it looks like.
_ _ _ _
| |___ __ _(_) |_ _ __| |_ ___ _ _
| _\ V V / | _| '_ \ ' \/ -_) '_|
\__|\_/\_/|_|\__| .__/_||_\___|_|
Gopher-Twitter |_| gateway
Reload for most current tweets from the public timeline.
Click a tweet to see more from that user.
<Church_Mouse> I mourn the loss of my old house. It is cold and empty. And I have work to do. -- Wed Jan 09 04:11:21 +0000 2008
<darwinpr> Why won't I stop following Shel? Do I enjoy pain? -- Wed Jan 09 04:11:22 +0000 2008
Here is the source
for the library, which will open in a new window so you can refer to it.
It requires 0.7.0+.
(This has been removed -- the new Twitpher is significantly different. You
should really read the current API docs.)
Twitpher uses TTYtter as its client rather than running as a bot.
It accomplishes this in the following ways:
- It obtains arguments from the
gopher executable stub. The stub passes the argument
using -twarg, although you could also use an environment variable
for a similar effect. Twitpher then sanitizes the username to prevent
various kinds of naughtiness.
- It establishes its custom environment, including forcing
anonymous mode on and overriding several
options like -seven, which is usually not helpful in Gopher.
- It dups standard output to a custom filehandle it writes
its output to so that output is limited purely
to what the library generates, and -silent suppresses the rest.
(This is possible because the code in TTYtter to squelch standard
output is intentionally placed after the library's initialization.)
However, because the library name is printed before it can specify the
-silent option, the gopher executable stub passes -silent
too to make it quiet. Note that dupping standard output
is no longer needed in 0.8.0 to achieve this effect -- see
the DUPSTDOUT filehandle.
- It implements a small gopher library, using anonymous subroutine
references stored in $Lib_ globals.
- It takes over the console and drives TTYtter itself with
the $console subroutine reference, which is described below.
Twitpher takes advantage of the asynchronous nature of the console by
setting a timeout with sleep. In the background, if the timeline
was successfully downloaded or an error is propagated, then after the
tweets are displayed (if any),
$conclude kills the parent process to end execution
and the timeout is not reached.
On the other hand, should the background process hang waiting for a
response, the timeout will occur and the hijacked console will
display a message and instead kill the child background process to end
execution.
- Handlers are set for direct messages (in this case to ignore them,
and none should be received in any case), tweets and error conditions.
Although this all sounds tremendously complex, the whole shooting match is just
around 3K, much of which is prompts and text. I think it makes a fine example
of how expressive you can be in a small space by using TTYtter as
the back end for your Twitter application.
If you've created an application or bot that uses TTYtter, I would
love to know about it and possibly include it in a list of
TTYtter-powered applications. Please send a description to
ckaiser@floodgap.com.
API reference
Superclassable subroutine references
These subroutine references can be used to replace or augment TTYtter
behaviour. The default behaviour is always available using
the &default* subroutine (e.g., the default $handle
routine can be called with &defaulthandle). The default
routine expects to be called with the same arguments the "super-routine"
was called with.
The API is not available for TTYtter versions prior to 0.4. Subroutine
references are specified with minimum supported version; if none is given,
it is available in any version from 0.4 higher.
- $addaction (argument 1: command line) (0.9.2+)
- Called after initial commandline processing by the default console to allow
the implementation of custom commands or to override internal commands (except
/quit, etc., which obviously probably shouldn't be overridden). If the
routine returns 0, then TTYtter assumes that the routine does not want
or recognize the command line it was provided, and continues with processing.
If the routine returns 1, then TTYtter assumes that the routine
accepted (or at least wants to suppress further processing of) the command
line for its own internal processing, and no further processing is done. Here
is a simple, fairly useless example that implements /fubar and
/ls commands:
$addaction = sub {
my $command = shift;
if ($command eq '/fubar') {
print $stdout "You are teh FUBAR.\n";
return 1;
}
if ($command =~ s#^/ls\s*##) {
# leaving the argument in $command
system("/bin/ls $command");
return 1;
}
return 0;
};
Default behaviour is to return 0. This routine is one-way, i.e., if you rewrite
the command line within $addaction, TTYtter will discard it
and resume with its own copy. If you want to actually alter the command line
itself and have TTYtter process that (e.g., macro or alias
substitution), look at $precommand.
- $authenticate (no arguments) (0.9.3+)
-
AS OF 0.9.4 THE $authenticate METHOD IS OFFICIALLY UNSTABLE
AGAIN. Applications using this method may break when OAuth support is
added to TTYtter, as this method will be used to handle generating
signed OAuth requests. YOU ARE WARNED.
Look at the $user and $anonymous options, along with the
selected user agent, and generate authentication credential options to send
to that user agent. The &defaultauthenticate subroutine is designed
to be a model; this routine checks that a username was specified, asks for a
password if one were not specified, and then formats it into a
command line option for either Lynx or cURL depending on which one
is in use.
This could be used by Mac users, for example, to fetch credentials from the
keychain. As reported by Uwe Dauernheim (not tested by me, since I don't
routinely use the Mac OS X Keychain), here is one way you
could fetch username and password using the security tool:
USER=`security find-internet-password -s "twitter.com" | grep "\"acct\"" | sed "s/.*\"acct\"<blob>=\"\(.*\)\".*/\1/"`
PASS=`security 2>&1 > /dev/null find-internet-password -gs "twitter.com" | sed "s/password: \"\(.*\)\"/\1/"`
Making this into a user $authenticate routine should be
straightforward using &defaultauthenticate as a template, and is
left as an exercise to the reader (if someone writes a working module, I will
be very happy to post it here).
- $autocompletion (argument 1: text to be completed,
argument 2: state of current command line, argument 3: position within
line of text to be completed) (0.9+)
- Called, if readline mode is enabled, by the operating
Term::ReadLine::* driver whenever TAB completion is needed. An
array of fully-qualified likely choices is expected as a return value. For
an example of how such a routine would operate,
look at &defaultautocompletion. You should be
familiar with Term::ReadLine to make the most of this hook.
- $conclude (no arguments)
- Called at the end of each cycle of tweet processing. Default behaviour is
to do nothing additional (except in 0.9.3 and up, where the count from
-filter is displayed if requested).
Return value, if any, is discarded.
- $console (no arguments) (0.6+)
- Master loop to manage the console. Default behaviour is to initialize the
history, print an initial prompt, and then accept data line by line from
standard input until a terminating command is received or the input stream
ends. Return value, if any, is discarded, and TTYtter will terminate
completely when the routine is exited.
Nothing says your console routine actually has to take user input, by the
way -- it can do its own thing and ignore standard input completely
(see Twitpher above for an example of using
the console for getting background timeouts for free). It can even drive the
(real)
console itself with its own commands in 0.9.4+ using &ucommand.
This hook can also be used to run code after initialization of the console
but prior to accepting user input. If so, your code should end with something
like goto &defaultconsole; to transparently return control
to the default handler.
- $dmconclude (no arguments) (0.6+)
- Called at the end of each cycle of direct message processing. Default
behaviour is to do nothing additional. Return value, if any, is discarded.
- $dmhandle (argument 1: hash reference) (0.6+)
- Called when a direct message is to be displayed or otherwise
handled in some manner. The
keys of the hash reference are based on those specified by the Twitter API.
Note that as a side effect of Perl's interpretation of the JSON, logical
true and false in Boolean fields are rendered as literal text
true and false. The routine, naturally, is not obligated
to generate any output if it desires. Default behaviour is to display screen
name, time stamp provided by Twitter, and the text of the direct message.
For success, the number of "logical DMs" handled
(almost always one) should be returned.
If the DM was declined for processing, a zero value should be returned.
In 0.8.0+, you can pass your hash reference to &standarddm for
the "default" formatting, which will return a string formatted according to
whatever standard options are set (such as -timestamp, -wrap,
-ansi, etc.)
- $exception (argument 1: exception number, argument 2: exception
text)
- Called when a non-fatal exception is received during processing of tweets.
Argument 2 is guaranteed to be human readable text corresponding to argument 1,
which comes more or less from this table:
- 1: timeout or no data
- 2: Twitter error or status message received
3: hit rate limit (0.5.x only, deprecated in 0.6+)
- 4: unexpected HTTP return code not caught by other exceptions (0.8.2+)
- 10: JSON cut (unexpected end)
- 11: JSON null list (missing or corrupt array reference)
12: JSON absolute null list (list with no members received)
(0.5.x only, deprecated in 0.6+)
The exception number
code is provided simultaneously to facilitate localization or custom
notification. Exceptions passed to $exception
are designed to be informative only, as TTYtter can
recover from these errors and automatically try again.
Fatal errors are raised immediately and the library does not receive
notification for technical reasons. Default behaviour is to print the error
text to standard output.
Return value, if any, is discarded.
Twitter is now using a generalized error reporting method to indicate
server-based exceptions, including hitting the API rate limit. All of these
errors are swallowed up under code 2; to distinguish them, check the
error text. Although the old rate-limit trigger message is still parsed for,
and can still theoretically generate code 3, this message has been replaced
by the new reporting convention in practise.
Code 12 is no longer reported as a null list can be valid in some
contexts. However, this is generally transparently intercepted silently
for you in contexts that it is not.
- $handle (argument 1: hash reference, [optional] argument 2:
origination)
- Called when a tweet is to be displayed or otherwise
handled in some manner. The
keys of the hash reference are based on those specified by the Twitter API.
Note that as a side effect of Perl's interpretation of the JSON, logical
true and false in Boolean fields are rendered as literal text
true and false. The routine, naturally, is not obligated
to generate any output if it desires. Default behaviour is to display the
tweet formatted to standard options (in 0.8.0+, using &standardtweet
[below]) with screen name and tweet text, and in 0.9.5+, with the tweet's
menu code prepended. For success, the number of "logical tweets" handled
(almost always one) should be returned.
If the tweet was declined for processing, a zero value should be returned.
In 0.8.0+, you can pass your hash reference to &standardtweet for
the "default" formatting, which will return a string formatted according to
whatever standard options are set (such as -timestamp, -ansi,
-wrap, etc.) In 0.9.5+, if ANSI is enabled,
this is also affected by $choosecolour.
In 0.8.1+, an optional origination argument is also passed, giving the command
that caused the tweet to be displayed. Origination classes defined currently
are a null string, meaning a
new tweet; replies
meaning tweets from the /replies command; or
again meaning old tweets usually from the /again command).
The distinction is important; replies does not appear on new replies,
but only on replies that you ask for. This is on purpose to ensure that API
activity results are consistent and match up. Note that again
overrides replies, and since /again can sometimes pull up new
tweets, the originator is blanked on purpose for those new ones so they are
properly seen as new. The complexity here is mostly intended for those clients
who want to distinguish old and new tweets, or tweets that a user requested
versus tweets that were automatically fetched, and handle them differently.
- $heartbeat (no arguments) (0.6+)
- Called at the beginning of each automatic refresh cycle (in either
daemon or interactive mode). Default behaviour is to do nothing additional.
Return value, if any, is discarded.
- $precommand (argument 1: command prior to processing) (0.8.2+)
- Called as soon as a command is received for processing, even before
history substitution. Allows you to implement your own preprocessing.
The new command should be returned as a single response, and is subject
to things like % substitution and so on. Default behaviour is to
just return the same command without further pre-substitution. Although you
could also attempt to intercept and handle custom commands here too,
$addaction is a better choice for that purpose.
-
$prepost (argument 1: tweet prior to posting) (0.8.2+)
$postpost (argument 1: tweet after posting) (0.8.2+)
- These two are paired, so they are listed together. $prepost
is called when a tweet is about to be URL-encoded and sent, allowing you
to implement your own tweet preprocessor (such as, say, a translation or
shortening
service). The new tweet should be returned as a single response. After the
tweet is posted, $postpost is called with the final tweet (which
barring an act of God or cosmic radiation should be the same as what
$prepost returned), which is useful for tools such as loggers.
Default behaviour for the former is to simply
return the same tweet without further pre-substitution, and for the latter,
to do nothing.
- $prompt (0.8.6 and prior, no arguments) (0.9.0 and following,
[optional] argument 1: information only) (0.7+)
- Called every time a prompt is to be displayed by the console.
Default
behaviour is to display TTYtter>, followed by a separating
space. If ANSI colour is enabled, the prompt is displayed in
cyan.
Starting in version 0.9.0, the prompt is only printed by the default
handler if -readline
is not enabled (otherwise the prompt is maintained
by ReadLine). If optional argument 1 is true, then the prompt and
its screen width (which may not be the same as its length) are returned as
a list for interested subroutines. Starting in version 0.9.3, when the
prompt is printed or requested, the wordwrap subroutine is hinted to use
it in calculations by setting global $wrapseq to zero.
- $tweettype (argument 1: hash reference, argument 2: screen
name, argument 3: tweet text) (0.9.7+)
- Called to determine what class a tweet should be (which should be
returned as a string); DMs are discovered separately (there is no
corresponding $dmtype). The four standard tweet classes are
me reply search default; you could define other classes for
use, say, with the notification framework (discussed below) or with your
own custom $handle routine. To fall
back on the standard tweet class selection, simply
return &defaulttweettype($ref, $sn, $tweet) for ones you
don't want to classify yourself.
Writing custom notification drivers (0.9.7+)
Your API extension can define a custom notification driver, which is handled
differently from the above. In general, the argument
to -notifytype=... is turned into a function name using the
notifier_ prefix, e.g.,
-notifytype=growl indicates that the subroutine
notifier_growl should be called for notifications. Thus, if you
wanted to define, say, a notifier_email subroutines for E-mail
notifications, then you invoke it with -notifytype=email after
including it with -lib or -olib.
The notification subroutine is called in two ways: with no arguments (or
more accurately, with a single argument of undef) during
initialization, and thereafter with three arguments: the class (as
determined by $tweettype), the tweet string
as processed by &standardtweet as a convenience, and a
hash reference to the tweet in case you want to format it yourself.
Your routine will then handle the notification, and return. Return value,
if any, is discarded.
The default drivers included (¬ifier_growl and
¬ifier_libnotify) are instructive examples. Both are
formatted in the same basic way: during initialization they seek out
their required utilities (growlnotify and notify-send
respectively) and store them in an appropriate global, and then as
tweets are passed to the notifier they then pass them off to their
dependent utility with the correct command line arguments on standard input.
Neither of the built-in drivers
do anything special with the class currently. However, your driver may
decide to in fact do special things with each class, and your customized
$tweettype method, if you choose to write one, can tag tweets
with new classes that your custom notification routine can handle (say,
a class peter for tweets from your friend Peter; for those
tweets, $tweettype would return 'peter', and you would add
peter to your list of classes in -notifies=...).
This is entirely supported, and you can of course simply fall through to
&defaulttweettype for other tweets that are not from Peter to
get default behaviour otherwise.
Note that notification routines
are called only for new tweets; tweets identified as old do not
get passed to the notifier to avoid ping-ponging.
Library routines
These routines are explicitly designated as available for calling from a
user application. Other routines may also be utilized, but are not guaranteed
to maintain compatible naming or calling convention in future versions. They
are not overridable.
- &descape (argument 1: data, [optional] argument 2: Unicode
mode)
- General text decoding routine. This single entry point is responsible for
removing internal quote-escaping for entity data (all versions
prior to 0.9.5) and HTML ampersand-entity encoding (0.5.1+), converting
escaped UTF-8 characters into their correct/desired form (0.5.1+),
and returning the
de-escaped data. If the data contains UTF-8 entities and UTF-8 is disabled
with -seven, then the entities are rendered as dots ('.').
The processed data is returned.
If optional
argument 2 is true, then UTF-8 entities are rendered in HTML "ampersand" form,
even if UTF-8 is "off." This is particularly useful for web applications.
Starting in version 0.5.1, &descape will also convert many
ampersand-escaped entities into ASCII as well, unless argument 2 is true
(in which case it assumes that you wish them to remain ampersand-escaped
like the UTF-8 entities will be).
- &grabjson (argument 1: URL, [optional] argument 2:
last ID, [optional] argument 3: don't authenticate)
- Asks URL for a JSON data source, attempts to convert it into a Perl
variable structure,
and returns either a reference to a hash, reference to an array or a scalar,
or an undefined reference if there was a problem. Severe or unexpected
parsing errors cause an immediate fatal shutdown for security reasons. If
optional argument 2 is true, then a since_id= is added to the request
for you. Figuring out how to interpret the reference is your problem;
however, &grabjson will do some normalization on the reference
if it appears to be coming from the Search API to make it look like a regular
Twitter API response.
Starting with 0.9.4, if argument 3 is true, then authentication headers
are not sent with the request.
- &screech (argument 1: error text)
- Emit error text to standard output (ring the bell if supported),
and kill and shutdown immediately. Used as an escape hatch for unsafe
situations, or fatal errors. Note that this bypasses $conclude, and
as such, no further notification is given to the library that a fatal
shutdown has occurred. This routine does not return.
- &standardtweet, &standarddm (argument 1:
hash reference) (0.8+)
- These routines
return the default pre-formatted string according to any user-specified
arguments for a tweet or DM respectively
indicated by the hash reference passed it. See $handle and
$dmhandle respectively.
- &ucommand (argument 1: console command) (0.9.4+)
- Executes a command as if you had typed it at the console, even if you
have hooked $console or are not using the console. This is
particularly useful for modifying arguments in realtime, because certain
command line arguments like $track have a pre-compilation step that
is triggered by the /set command, for example.
- &updatest (argument 1: status text, [optional] argument 2:
interactive mode, [optional] argument 3: in reply to status ID)
- Update the current user's status with status. If optional
argument 2 is true, any error condition will also be displayed on
standard output. If optional argument 3 is specified, then the posted tweet
will have its in-reply-to value set to the specified ID (0.9.5+).
A status value
is returned: zero if the post was successful, or a return code
dependent on Lynx or curl if not (see respective documentations).
Return code 99 indicates that the subprocess could not even start, possibly
due to change in the filesystem or permissions.
Exposed globals
These globals are explicitly designated as available or permissible for
user operation and manipulation. Globals specific to the library itself
should always use the prefix $Lib_. Manipulating other globals
could interfere with normal TTYtter operation, and are not guaranteed
to retain the same function or name in future versions.
- $TTYtter_VERSION
-
The current major/minor version of TTYtter (currently a string
containing a float value, but was previously
a float value [so version 0.7 was represented as 0.7, but now 0.9 is
"0.9"]). This doesn't include the
patch level; see the next variable for that.
- $TTYtter_PATCH_VERSION
-
The current patch level of this release of TTYtter, loaded into
a separate scalar for backwards compatibility; although
this was not defined prior to 0.5.1, the patch level of previous versions
can be safely assumed to be patchlevel 0, and as such a nice idiom is to use
(0+$TTYtter_PATCH_VERSION) which is guaranteed to give zero for
old versions and will not bug out on current ones. This is an integer,
so $TTYtter_VERSION 0.5 and $TTYtter_PATCH_VERSION 1
indicates version 0.5.1.
- $url $lynx $curl $pause $user $seven $lib $daemon $verbose $script
$ttytteristas $avatar $leader $noprompt $rc
$superverbose $hold $status $update $dmurl $rlurl $frurl $shorturl
$queryurl $trendurl $slowpost $verify
$dmpause $silent $anonymous $ansi $readline $notimeline $colourprompt
$coloursearch $colourdefault $favurl $favsurl $myfavsurl $favdelurl
$colourme $colourdm $colourreply $colourwarn $track $filter $track $notrack
$noansi $timestamp $uurl $rurl $wurl $maxhist $twarg
- These are the manifestations of the valid command line options, set to
their respective specified values (or 1 for true Boolean values). For the
meanings of these options, see Command-line
options.
A few of these options ($filter, $track) compile internal
representations for speed, so changing these globals may not necessarily
change behaviour.
$twarg is special as it is explicitly designated as user-defined,
i.e., it's your way of passing external data or arguments into your code.
Don't trust it, do sanitize it if you're not the source.
It is available in 0.7+.
- $whoami
- The current screen name in use. It is populated automatically for you
in 0.7+. It is not immediately instantiated, and in 0.9.3+ is in fact not
instantiated until the $authenticate method has been executed,
so you may still need to rely on $user for early initialization.
Changing $whoami does not necessarily change the credentials sent
by TTYtter.
- $parent $child
- The PID of the parent and child processes. In interactive mode, both are
defined; in daemon mode, only the latter (the parent ID becomes zero).
Neither should be modified, or processes may not get properly
terminated.
- $last_id
- The last/highest tweet ID so far processed. It starts at zero, but may
be advanced to skip tweets as $handle (or &defaulthandle
where not specified) is only called for new tweets, viz., tweets with an ID
higher than $last_id. Even if $handle returns zero for an
arbitrary tweet, that tweet's ID is still considered for $last_id.
- $last_dm
- Analogously, the last/highest direct message ID so far processed. Its
behaviour is exactly the same as $last_id, including starting from
zero on startup, and even if $dmhandle returns zero for an arbitrary
DM, that DM's ID is still considered for $last_dm.
- $lasttwit (0.8.1+)
- The last successful tweet (empty if no tweets have been made). This is
not carried from session to session.
- DUPSTDOUT (0.8+)
- The DUPSTDOUT filehandle is defined in 0.8+ and allows you to
emit to standard output even if everything else is being suppressed with
-silent. As its name suggests, it is a simple dup(3) of
standard output. -silent forces output to DUPSTDOUT, but
only from &defaulthandle and &defaultdmhandle;
everything else still goes to STDOUT.
- $CCme $CCreply $CCdm $CCsearch $CCprompt $CCwarn (0.9.4+)
$CCdefault (0.9.7+)
- The surface manifestation of the -colour* command line options,
viz., the actual printable terminal sequences. This is preferred rather than
specifying exact colours when matching a particular tweet class.
Send comments and six-packs of Mr Pibb to
ckaiser@floodgap.com,
or return to the main TTYtter page.
Cameron Kaiser