John :: Affirming Consequents, Denying Antecedents (idonotlikepeas) wrote in suggestions,
John :: Affirming Consequents, Denying Antecedents
idonotlikepeas
suggestions

lj-specific tags to set posting metadata options

Title
lj-specific tags to set posting metadata options

Short, concise description of the idea
Allow the use of lj-specific tags to set the appropriate metadata options on an entry when posting it via any method (Jabber, web, e-mail, SMS, what have you).

Full description of the idea
Currently, the only way to set specific metadata options (post security, music, mood, location, and so on) on posts is to send them in through the web interface or via a client that supports the option in question. Whenever a new method of making a post appears (e.g. mobile posting, posting via the beta Jabber service), a new method must be created to allow that metadata to be set. And then, whenever a new piece of metadata is added (e.g. location), everything has to be updated to allow it.

In addition to these methods, pseudo-html tags like lj-user and lj-cut could be used to set metadata on entries. These would be used in the entry text and then cut by the lj protocol parser, so they wouldn't appear in the entry long-term, but only set options on it. (Precedent here is polls, which are created by tags but then really spawn a completely separate entity.)

So, for instance, one might post an entry via Jabber like this:

<lj-meta subject="This is my jabber entry"> Well, I was in my IM client, and I thought I'd post an entry. Guess I was bored. <lj-meta current_mood="bored"> Anyway, I guess I better go. My house is about to blow down because of the tornado outside. <lj-meta current_location="inside a tornado" taglist="weather, boredom">

An ordered list of benefits
  • This would make updating every interface somewhat less urgent when changes are made to the metadata.
  • Users of unupdated clients and interfaces could make use of new capabilities immediately rather than waiting for the maintainers to catch up.
  • Additional metadata could be added without cluttering the existing interface.
  • Interfaces which are already simple, such as the Jabber interface, don't have to have complexity added to them in order to allow the features that more robust interfaces do.

An ordered list of problems/issues involved
  • Depending on how much processing of the entry is currently done on submit and edit, this might harm performance.
  • Each tag might appear multiple times in an entry. (The simplest way of dealing with that would just be to use the last one every time.)

An organized list, or a few short paragraphs detailing suggestions for implementation
  • Probably update postevent and editevent libs to yank the tags and make the appropriate adjustments to the entry. Implementing it that close to delivery means it isn't dependent on any particular client mechanism.
  • Could use tags similar to http://www.livejournal.com/manage/emailpost.bml?mode=help&type=headers but for simplicity might be better to have something like <lj-meta current_mood="exanimate"> (so that the parser doesn't have to trigger on as many tags).
  • Here's a potential patch which probably needs some work, but does the right thing under the limited testing I did:
    @@ -4,6 +4,7 @@
     use strict;
     use LJ::Constants;
     use Unicode::MapUTF8 ();
    +use HTML::TokeParser ();
     use Class::Autouse qw(
                           LJ::Event::JournalNewEntry
                           LJ::Event::UserNewEntry
    @@ -663,6 +664,11 @@
         $uowner = LJ::want_user($uowner) unless LJ::isu($uowner);
         my $clusterid = $uowner->{'clusterid'};
     
    +    # Process event to see if tags in body need to override metadata
    +    if ($req->{'event'} =~ /\<\s*lj-meta\b/i) {
    +        return fail($err, 205) unless LJ::metadata_process($req, $u);
    +    }
    +
         my $dbh = LJ::get_db_writer();
         my $dbcm = LJ::get_cluster_master($uowner);
     
    @@ -1150,6 +1156,11 @@
         $uowner = LJ::want_user($uowner) unless LJ::isu($uowner);
         my $clusterid = $uowner->{'clusterid'};
         my $posterid = $u->{'userid'};
    +    # Process event to see if tags in body need to override metadata
    +    if ($req->{'event'} =~ /\<\s*lj-meta\b/i) {
    +        return fail($err, 205) unless LJ::metadata_process($req, $u);
    +    }
    +
         my $qallowmask = $req->{'allowmask'}+0;
         my $sth;
     
    @@ -3400,4 +3411,81 @@
         $res->{"menu_${mn}_count"} = $mi;
     }
     
    +# given an request hashref, checks body to see if other metadata needs to be
    +# updated from lj-meta tag(s)
    +sub metadata_process {
    +    my ($req, $u) = (shift, shift);
    +
    +    my $props = $req->{'props'};
    +    my $event = $req->{'event'};
    +    my $p = HTML::TokeParser->new(\$event);
    +    my $newdata = '';
    +    while (my $token = $p->get_token) {
    +        my $type = $token->[0];
    +        my $tag = $token->[1];
    +        my $attr = $token->[2];
    +        if ($type eq "S") {
    +            # If it's a start tag, continue and parse things
    +        } elsif ($type eq 'E') {
    +            next if $tag eq 'lj-meta';
    +            $newdata .= "</$tag>";
    +            next;
    +        } elsif ($type eq "T" || $type eq "D") {
    +            $newdata .= $token->[1];
    +            next;
    +        } elsif ($type eq "C") {
    +            # ignore comments
    +            next;
    +        } elsif ($type eq "PI") {
    +            $newdata .= "<?$tag>";
    +            next;
    +        } else {
    +            $newdata .= "<!-- OTHER: " . $type . "-->\n";
    +            next;
    +        }
    +
    +        unless ($tag eq 'lj-meta') {
    +            $newdata .= "<$tag";
    +            foreach (keys %$attr) {
    +                $newdata .= " $_=\"$attr->{$_}\"";
    +            }
    +            $newdata .= ">";
    +            next;
    +        }
    +        foreach (qw(taglist picture_keyword current_mood current_music 
    +                    current_location)) {
    +           $props->{$_} = LJ::trim($attr->{$_}) if exists $attr->{$_};
    +        }
    +        foreach (qw(usejournal subject)) {
    +           $req->{$_} = $attr->{$_} if exists $attr->{$_};
    +        }
    +        my $comments = LJ::trim(lc($attr->{'comments'}));
    +        if ($comments eq 'off') { $props->{'opt_nocomments'} = 1; }
    +        elsif ($comments eq 'noemail') { $props->{'opt_noemail'} = 1; }
    +        my $security = LJ::trim(lc($attr->{'security'}));
    +        my $allowmask;
    +        if ($security =~ /^(public|private|friends)/) {
    +            if ($1 eq 'friends') {
    +                $security = 'usemask';
    +                $allowmask = 1;
    +            }
    +        } elsif ($security) {
    +            # Get the mask for the requested friends group, default to private.
    +            my $group = LJ::get_friend_group($u, { 'name'=>$security });
    +            if ($group) {
    +                $security = 'usemask';
    +                $allowmask = (1 << $group->{'groupnum'});
    +            } else {
    +                $security = 'private';
    +            }
    +        }
    +        $req->{'security'} = $security if $security;
    +        $req->{'allowmask'} = $allowmask if $allowmask;
    +        # Don't put anything in newdata for meta tags
    +    }
    +    $req->{'event'} = $newdata;
    +
    +    return 1;
    +}
    +
     1;
Tags: entry creation, entry management, lj-specific markup, § historical
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 20 comments