LiveJournal

jEdit S2 edit mode

Originally posted on 2005-05-02

This will give you syntax highlighting in jEdit for LiveJournal’s S2 styling system.

Drop into [jedit profile dir]/modes/ and edit catalog to include something like <MODE FILE="s2.xml" NAME="S2" FILE_NAME_GLOB="*.s2" />

Source: s2.xml

<?xml version="1.0"?>
 
<!DOCTYPE MODE SYSTEM "xmode.dtd">
 
<MODE>
  <PROPS>
    <PROPERTY NAME="lineComment" VALUE="#" />
    <PROPERTY NAME="indentOpenBrackets" VALUE="{" />
    <PROPERTY NAME="indentCloseBrackets" VALUE="}" />
    <PROPERTY NAME="lineUpClosingBracket" VALUE="true" />
  </PROPS>
  <RULES ESCAPE="\" HIGHLIGHT_DIGITS="TRUE" IGNORE_CASE="FALSE">
    <!-- Comments -->
    <EOL_SPAN TYPE="COMMENT1">#</EOL_SPAN>
 
    <!-- Variables -->
    <SEQ_REGEXP HASH_CHAR="$" TYPE="KEYWORD2">\$(?:(\.|\*)|\w)+</SEQ_REGEXP>
 
    <!-- Literals -->
    <SPAN TYPE="LITERAL1">
      <BEGIN>"""</BEGIN>
      <END>"""</END>
    </SPAN>
    <SPAN TYPE="LITERAL1" DELEGATE="LITERAL">
      <BEGIN>"</BEGIN>
      <END>"</END>
    </SPAN>
 
    <!-- Function calls -->
    <MARK_PREVIOUS TYPE="FUNCTION" EXCLUDE_MATCH="TRUE">(</MARK_PREVIOUS>
 
    <!-- Operators -->
    <SEQ TYPE="OPERATOR">&gt;=</SEQ>
    <SEQ TYPE="OPERATOR">&lt;=</SEQ>
    <SEQ TYPE="OPERATOR">&gt;</SEQ>
    <SEQ TYPE="OPERATOR">&lt;</SEQ>
    <SEQ TYPE="OPERATOR">=</SEQ>
    <SEQ TYPE="OPERATOR">+</SEQ>
    <SEQ TYPE="OPERATOR">-</SEQ>
    <SEQ TYPE="OPERATOR">/</SEQ>
    <SEQ TYPE="OPERATOR">*</SEQ>
    <SEQ TYPE="OPERATOR">%</SEQ>
    <SEQ TYPE="OPERATOR">}</SEQ>
    <SEQ TYPE="OPERATOR">{</SEQ>
    <SEQ TYPE="OPERATOR">?</SEQ>
    <SEQ TYPE="OPERATOR">:</SEQ>
 
    <!-- Keywords -->
    <KEYWORDS>
      <KEYWORD1>return</KEYWORD1>
      <KEYWORD1>if</KEYWORD1>
      <KEYWORD1>while</KEYWORD1>
      <KEYWORD1>elsif</KEYWORD1>
      <KEYWORD1>else</KEYWORD1>
      <KEYWORD1>foreach</KEYWORD1>
      <KEYWORD2>int</KEYWORD2>
      <KEYWORD2>bool</KEYWORD2>
      <KEYWORD2>string</KEYWORD2>
      <KEYWORD1>layerinfo</KEYWORD1>
      <KEYWORD1>property</KEYWORD1>
      <KEYWORD1>set</KEYWORD1>
      <KEYWORD1>function</KEYWORD1>
      <KEYWORD1>var</KEYWORD1>
      <KEYWORD1>class</KEYWORD1>
 
      <OPERATOR>not</OPERATOR>
      <OPERATOR>and</OPERATOR>
      <OPERATOR>or</OPERATOR>
 
      <KEYWORD3>isnull</KEYWORD3>
      <KEYWORD3>defined</KEYWORD3>
      <KEYWORD3>newnull</KEYWORD3>
      <KEYWORD3>new</KEYWORD3>
      <KEYWORD3>reverse</KEYWORD3>
      <KEYWORD3>size</KEYWORD3>
      <KEYWORD3>extends</KEYWORD3>
      <KEYWORD3>builtin</KEYWORD3>
      <KEYWORD3>use</KEYWORD3>
    </KEYWORDS>
  </RULES>
</MODE>

Del.icio.us LiveJournal post

Originally written on 2005-06-04.

I thought it would be cool to have link digests posted in my journal once in a while automatically. It would leave a record of places I’ve been and things I’ve been interested in, but haven’t had the time/itch to write extensively about.

There are quite a few requirements:

  1. must be called periodically (ie. via cron)
  2. a functioning mail setup must be present
  3. paid LJ account for email posting
  4. a bunch of Perl modules that your host may not have (mine didn’t have XML::Simple). I’m lazy, though, and just wanted to use the tools at my disposal.

Note: If you’re going to use this, you may need to append “&count=n” to the API url (where n is an int between 1 and 100) to get the appropriate number of recent posts. I don’t use del.icio.us extensively, so the default 15 is good for me.

I hope I got the LWP stuff right. The script will back-off if yelled at, but it’s quite persistent otherwise (which may not be a good thing). Maybe I’ll tune down the number of repeated requests before giving up.

So, now, if I post any new links with a ljpost tag, it should automatically update every Friday and lj-cut the entry if there are too many links.

Source: Perl file

#!/usr/bin/perl -w
 
# Copyright Dmitri Vassilenko (dv [at] glyphy [dot] com)
# Personal use is OK. Keep the ownership info.
 
# Needs to be called from cron (or whatever you have) once in a while.
# Upon each successive call with no arguments, it will query del.icio.us
# for new posts under a certain tag and store the fetched data on disk along
# with the last post time. Naturally, you shouldn't run this in a tight loop.
# I run this a couple of times a day. You may get throttled by del.icio.us if
# you poll too often.
# To force a post, use the -u cmd-line option.
# If you post a lot, you may wish to append "&count=n" to $DEL_API, where n
# is the number of posts you'd like to fetch. The default is 15 and max is 100.
 
### Requirements
use strict;
use Getopt::Std;
use Data::Dumper;
use LWP::UserAgent;
use XML::Simple;
use Storable;
use DateTime::Format::W3CDTF;
use Mail::Send;
 
########## Define constants ##########
use constant LJ_USERNAME  => 'YourLJUsername';
use constant LJ_PIN       => 'YourLJEmailPostingPin';
my  $DEL_USERNAME          = 'YourDeliciousUsername';
my  $DEL_PASSWORD          = 'YourDeliciousPassword';
my  $DEL_TAG               = 'postingTag';
 
# changing the following is optional
my  $DEL_API = "https://api.del.icio.us/v1/posts/recent?tag=$DEL_TAG";
use constant TIME_FILE    => '/home/you/last'; # stores last update time
use constant POSTS_FILE   => '/home/you/posts'; # stores queued items for posting
use constant MAX_DOC_SIZE => 100000; # in bytes
use constant TIMEOUT      => 10;
use constant MAX_POSTS    => 7; # after this # of new items, an lj-cut is used
use constant MIN_POSTS    => 3; # don't post less than this # of items
######################################
 
sub usage {
  print "Usage: ljdelpost [-u] [-s] [-t n]
Fetches the last few posts from del.icio.us and stores them on disk.
      -u updates and forces a post
      -s shows the latest posts currently stored on disk without posting them
      -t n trims the posts list to n last posts\n";
}
 
# Parse commands
my $cmds = getopts('usht:');
our($opt_h, $opt_s, $opt_u, $opt_t);
if (defined $opt_h) { usage(); exit 0 }
 
########## Fetch stored data from disk ##########
if (! -e TIME_FILE) {
  my $initial_time = 0;
  store(\$initial_time, TIME_FILE);
}
my $last = retrieve(TIME_FILE); # Last update time from epoch
 
if (! -e POSTS_FILE) {
  my @initial_posts;
  store(\@initial_posts, POSTS_FILE);
}
my $sposts = retrieve(POSTS_FILE); # Posts stored on disk
#################################################
 
if (defined $opt_t) {
    splice(@{$sposts}, $opt_t);
    store($sposts, POSTS_FILE) or die "Can't store %a in " . POSTS_FILE . "\n";
    $opt_s = 1;
}
 
if (defined $opt_s) {
  print "Stored posts:\n";
  print Dumper($sposts);
  exit 0;
}
 
my $ua = new LWP::UserAgent;
my $content;
 
$ua->max_size(MAX_DOC_SIZE);
$ua->timeout(TIMEOUT);
$ua->agent("LJDelPost (http://www.livejournal.com/users/troworld/162341.html)");
 
my $req = new HTTP::Request GET => $DEL_API;
$req->authorization_basic($DEL_USERNAME, $DEL_PASSWORD);
my $res;
 
while ($res = $ua->request($req)) {
  if ($res->is_success) {
    $content = $res->content;
    last;
  } else {
    warn "Error: " . $res->code . ' ' . $res->message;
    exit 1 if ($res->code == 503 || $res->code == 401); # Back off
    sleep 60;
  }
}
 
my $posts = XMLin($content, ForceArray => 1)->{post};
my $f = DateTime::Format::W3CDTF->new;
 
my $dt; # Date of $i'th post
my @newposts; # will be copied to disk when complete
my $newtime = $f->parse_datetime($posts->[0]->{time}); # date of last new post
foreach my $i (@{$posts}) {
  $dt = $f->parse_datetime($i->{time});
  last unless ($dt->epoch() > ${$last}); # Posts are in descending order sorted
                                         # by time
  push @newposts, $i;
}
 
# Copy new posts to disk
if ($#newposts >= 0) {
  unshift @{$sposts}, @newposts;
  store($sposts, POSTS_FILE) or die "Can't store %a in " . POSTS_FILE . "\n";
  store(\$newtime->epoch(), TIME_FILE) or die "Can't store %a in " . TIME_FILE . "\n"; # update last post time
}
 
if (defined $opt_u) {
  if ($#{$sposts} < 0 || $#{$sposts} < MIN_POSTS) {
    warn 'Not enough new posts. Not sending any messages.';
    exit 0;
  }
  my $msg = new Mail::Send;
  $msg->to(LJ_USERNAME . '+' . LJ_PIN . '@post.livejournal.com');
  #$msg->cc('your@email.com'); # CC yourself
  $msg->subject('Links for ' . $newtime->day . ' ' . $newtime->month_name . ' ' . $newtime->year);
  my $mailer = $msg->open;
  #open(my $mailer, '>-'); # for debugging purposes
 
  print $mailer "lj-security: public\nlj-tags: links\nlj-userpic: default\n\n";
  print $mailer "<lj-cut text=\"" . @{$sposts} . " links\">" if ($#{$sposts}+1 > MAX_POSTS);
  print $mailer "<lj-raw>\n<ul class='delList'>\n";
 
  foreach my $i (reverse @{$sposts}) {
    my $posted_time = $f->parse_datetime($i->{time});
    print $mailer '    <li class="delPost">
        <a href="' . $i->{href} .
    '">' . $i->{description} . '</a> <small>(Posted on ' . $posted_time->day . ' ' . $posted_time->month_name . ' ' . $posted_time->year . ' @ ' . $posted_time->hms . ' ' . $posted_time->time_zone_short_name . ")</small>\n";
    print $mailer '        <div class="delExt">' . $i->{extended} . "</div>\n" if (exists $i->{extended});
    my $tagline = $i->{tag};
    $tagline =~ s|$DEL_TAG||; # kill the lj tag
    if (length $tagline > 0) {
      my @tags = split(' ', $tagline);
      print $mailer '        <div class="delTags">Tags: ';
      foreach my $j (@tags) {
        print $mailer '<a href="http://del.icio.us/' . $DEL_USERNAME . "/$j\">$j</a> ";
      }
      print $mailer "</div>\n";
    }
    print $mailer "    </li>\n";
  }
  print $mailer "</ul>\n";
  print $mailer '</lj-raw>';
  print $mailer "</lj-cut>\n" if ($#{$sposts}+1 > MAX_POSTS);
  $mailer->close; # Send the message
 
  my @cleanposts;
  store(\@cleanposts, POSTS_FILE) or die "Can't store %a in " . POSTS_FILE . "\n";
}
Syndicate content Syndicate content