init
This commit is contained in:
9
ljcom/htdocs/phonepost/about.bml
Normal file
9
ljcom/htdocs/phonepost/about.bml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?page
|
||||
title=>About Post by Phone
|
||||
body<=
|
||||
<?h1 What is Post by Phone? h1?>
|
||||
<?p Post by Phone is a new feature on LiveJournal that allows a person to call up a phone number and record a post for their journal. Post by Phone is a <a href="/paidaccounts/">paid account</a> perk; paying members can make up to 15 posts a month. p?>
|
||||
<?h1 How do I listen to an audio post? h1?>
|
||||
<?p Audio posts are recorded and compressed into <a href="http://www.vorbis.com/">Ogg Vorbis</a> files. There are a lot of <a href="./ogg.bml">media players for different operating systems</a> that will play <tt>.ogg</tt> files, and most are free to download and use. p?>
|
||||
<=body
|
||||
page?>
|
||||
29
ljcom/htdocs/phonepost/encodings.bml
Normal file
29
ljcom/htdocs/phonepost/encodings.bml
Normal file
@@ -0,0 +1,29 @@
|
||||
<?page
|
||||
title=>Encoding Choices
|
||||
body<=
|
||||
|
||||
<?p We offer three options for phone post encodings:
|
||||
MP3, Ogg Vorbis, and GSM-encoded WAV. Which you choose is up to you. p?>
|
||||
|
||||
<?h1 MP3 h1?>
|
||||
<?p MP3 files are playable by nearly everyone. They can also be
|
||||
transfered to a handheld MP3 player, so you can listen to your
|
||||
friends' phone posts on the go.
|
||||
p?>
|
||||
|
||||
<?h1 Ogg Vorbis h1?>
|
||||
<?p
|
||||
Ogg Vorbis is a high-quality, open-source alternative
|
||||
to MP3. Information on what .ogg is and how to play them can be found
|
||||
on our <a href="/phonepost/ogg.bml">Ogg Vorbis</a> page.
|
||||
p?>
|
||||
|
||||
<?h1 WAV h1?>
|
||||
<?p
|
||||
WAV files are smaller and more compact, but they don't sound
|
||||
as good as MP3 or Ogg. Use this if file size is an issue for you.
|
||||
p?>
|
||||
|
||||
<=body
|
||||
page?>
|
||||
|
||||
56
ljcom/htdocs/phonepost/index.bml
Normal file
56
ljcom/htdocs/phonepost/index.bml
Normal file
@@ -0,0 +1,56 @@
|
||||
<?page
|
||||
title=>Post by Phone
|
||||
head<=
|
||||
<style type="text/css">
|
||||
dt {font-weight: bold; }
|
||||
</style>
|
||||
<=head
|
||||
body<=
|
||||
<?p Post by Phone support is a new LiveJournal feature that allows you to post audio files straight from your phone. It's easy: p?>
|
||||
<ol>
|
||||
<li>Call one of <a href="./numbers.bml">our designated numbers</a></li>
|
||||
<li>Use your PIN to authorize your phone number</li><li>Record your post</li>
|
||||
</ol>
|
||||
<?p Our system will <a href="./ogg.bml">compress</a> and post the audio file to your journal as a new entry. p?>
|
||||
<?p You can choose from MP3, Ogg Vorbis, or WAV format at the <a href="/manage/phonepost.bml">Settings</a> page. p?><br />
|
||||
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
my $remote = LJ::get_remote();
|
||||
return unless $remote;
|
||||
|
||||
my $phonemax = LJ::get_cap($remote, 'phonepost_monthquota') || 0;
|
||||
if ($phonemax > 0) {
|
||||
my $dbcr = LJ::get_cluster_reader($remote);
|
||||
my $phoneusage = $dbcr->selectrow_array
|
||||
("SELECT COUNT(*) FROM phonepostentry ".
|
||||
"WHERE userid=? AND ".
|
||||
"MONTH(FROM_UNIXTIME(posttime)) = MONTH(NOW()) AND ".
|
||||
"YEAR(FROM_UNIXTIME(posttime)) = YEAR(NOW())",
|
||||
undef, $remote->{userid});
|
||||
|
||||
my $diskmax = LJ::get_cap($remote, 'disk_quota');
|
||||
my $diskusage = sprintf("%0.2f", LJ::Blob::get_disk_usage($remote, 'phonepost') / 1024**2);
|
||||
return "<?standout <table><tr><th colspan='2' style='text-align: center'>Status</td></tr>".
|
||||
"<th style='text-align: right'>Disk Space:</th>".
|
||||
"<td>You are currently using $diskusage MB out of $diskmax MB</td></tr>".
|
||||
"<tr><th style='text-align: right'>Phone Posts:</th><td>You have made $phoneusage posts out of $phonemax</td></tr></table> standout?>";
|
||||
} else {
|
||||
return "<?standout <a href='/paidaccounts/'>Purchase a paid account</a> to start using Post by Phone standout?>";
|
||||
}
|
||||
}
|
||||
_code?>
|
||||
<?h1 Links h1?>
|
||||
<dl>
|
||||
<dt><a href="/manage/phonepost.bml"><?_ml /manage/phonepost.bml.title _ml?></a></dt>
|
||||
<dd>Manage your authorized phone number and post by phone identification number</dd>
|
||||
|
||||
<dt><a href="/manage/files.bml">File Manager</a></dt>
|
||||
<dd>Manage your available disk space & phone posts</dd>
|
||||
|
||||
<dt><a href="./encodings.bml">Audio encodings</a></dt>
|
||||
<dd>The different audio formats we support for your posts</dd>
|
||||
</dl>
|
||||
<=body
|
||||
page?>
|
||||
90
ljcom/htdocs/phonepost/numbers.bml
Normal file
90
ljcom/htdocs/phonepost/numbers.bml
Normal file
@@ -0,0 +1,90 @@
|
||||
<?page
|
||||
title=>Post by Phone Access Numbers
|
||||
body<=
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
return LJ::server_down_html() if $LJ::SERVER_DOWN;
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
my $quota = LJ::get_cap($remote, 'phonepost_monthquota');
|
||||
my $ret;
|
||||
|
||||
unless ( $quota > 0) {
|
||||
if ($remote) {
|
||||
$ret .= "<?p Your account is not permitted to use the <a href='/phonepost/'>Post by Phone</a> service, ".
|
||||
"so only the area code and city of each number is displayed. If you'd like to make ".
|
||||
"posts to your journal through your phone, see the <a href='/paidaccounts/'>Paid Accounts</a> ".
|
||||
"page for information on purchasing a paid account. p?>";
|
||||
} else {
|
||||
$ret .= "<?p Listed below are area codes and cities where we've established a ".
|
||||
"<a href='/phonepost/'>Post by Phone</a> number. <a href='/paidaccounts/'>Paid Accounts</a> can ".
|
||||
"<a href='/login.bml?ret=1'>log in</a> to see the complete set of phone numbers. p?>";
|
||||
}
|
||||
} else {
|
||||
$ret .= "<?p The <a href='/phonepost/'>Post by Phone</a> interface can be reached by calling any of the following numbers: p?>";
|
||||
}
|
||||
|
||||
my $nums = LJ::MemCache::get("phonepost_nums");
|
||||
unless ($nums) {
|
||||
my %sname;
|
||||
LJ::load_codes({ "state" => \%sname });
|
||||
$nums = {}; # state code -> [ [number, city]* ]
|
||||
open (NUM, "$ENV{LJHOME}/other_sites/phonepost/numbers.csv");
|
||||
while (<NUM>) {
|
||||
next unless /^(\w\w+)\s*,\s*(\d\d\d\-\d\d\d)\s*[,\-]\s*(\d\d\d\d)\s*\,\s*(.+?)\s*\n/;
|
||||
my ($state, $exch, $number, $city) = ($1, $2, $3, $4);
|
||||
if ($city eq uc($city)) {
|
||||
$city = lc($city);
|
||||
$city =~ s/\b(\w)/\u$1/g;
|
||||
}
|
||||
my $sname = $sname{$state} || $state;
|
||||
$city =~ s/\s*Zone.+//;
|
||||
$nums->{$sname} ||= [];
|
||||
push @{$nums->{$sname}}, [ "$exch-$number", $city ];
|
||||
}
|
||||
foreach my $st (keys %$nums) {
|
||||
$nums->{$st} = [ sort { lc($a->[1]) cmp lc($b->[1]) } @{$nums->{$st}} ];
|
||||
}
|
||||
LJ::MemCache::set("phonepost_nums", $nums, 60*5);
|
||||
}
|
||||
|
||||
my $tot = 0;
|
||||
$tot += scalar(@{$nums->{$_}}) foreach (keys %$nums);
|
||||
|
||||
$ret .= "<b>Jump to:</b> " . join(" | ", map {
|
||||
"<a href='#$_'>$_</a>" } sort { lc($a) cmp lc($b) } keys %$nums);
|
||||
|
||||
|
||||
my $shown = 0;
|
||||
my $col = 1;
|
||||
$ret .= "<div style='background-color: #ffe680; float: right; width: 175px; font-size: 0.8em; border: 1px outset #333; padding: 2px;'>";
|
||||
$ret .= "<strong style='text-decoration: underline'>Caution:</strong><br /> Some local telephone companies charge for local calls that are outside of your selected calling plan.";
|
||||
$ret .= "<br /><br />If you are not sure that an access number is within your calling plan, contact your local telephone company.";
|
||||
$ret .= "<br /><br />You are responsible for all charges associated with calling this service.</div>";
|
||||
|
||||
$ret .= "<?p <?de Note: We're in the process of adding more numbers. de?> p?>";
|
||||
|
||||
$ret .= "<table style='margin-left: 40px'><tr valign='top'><td>";
|
||||
foreach my $sname (sort { lc($a) cmp lc($b) } keys %$nums) {
|
||||
$ret .= "<div style='margin-top: 10px; white-space: nowrap'><a name='$sname'><b>$sname</b></a></div>\n";
|
||||
foreach my $rec (@{$nums->{$sname}}) {
|
||||
my $shownum = $rec->[0];
|
||||
$shownum =~ s/^(\d{3})[-\s.](\d{3})[-\s.](\d{4})/$1-xxx-xxxx/ unless $quota > 0;
|
||||
$ret .= "$shownum: $rec->[1]<br />\n";
|
||||
$shown++;
|
||||
}
|
||||
if ($col == 1 && $shown > ($tot / 2)) {
|
||||
$col++;
|
||||
$ret .= "</td><td>";
|
||||
}
|
||||
|
||||
}
|
||||
$ret .= "</tr></table>";
|
||||
|
||||
$ret .= "<?p We respectfully request that you not share these numbers with others, as we'd like to avoid unnecessary phone traffic. p?>" if $quota > 0;
|
||||
return $ret;
|
||||
}
|
||||
_code?>
|
||||
<=body
|
||||
page?>
|
||||
28
ljcom/htdocs/phonepost/ogg.bml
Normal file
28
ljcom/htdocs/phonepost/ogg.bml
Normal file
@@ -0,0 +1,28 @@
|
||||
<?page
|
||||
title=>Ogg Vorbis
|
||||
body<=
|
||||
<?h1 What is Ogg Vorbis? h1?>
|
||||
<?p <a href="http://www.vorbis.com/">Ogg Vorbis</a> is an audio compression format, comparable to other formats like mp3, aac, wma, and ra. Ogg is different from others however, because it is an open specification, is free to use by any person or business, and is not encumbered by any patent. p?>
|
||||
<?p We offer your phone posts as <tt>.ogg</tt> files because Ogg Vorbis is an open source project, an ideal we strongly believe in. p?>
|
||||
<?h1 How do I listen to <tt>.ogg</tt> files? h1?>
|
||||
<?p Ogg decoders, the software library that allows you to listen to <tt>.ogg</tt> files, are <a href="http://www.vorbis.com/download.psp">available for a variety of media players on various operating systems</a>, including: p?>
|
||||
<?h2 <a href="http://www.vorbis.com/software.psp?pid=2">Windows</a> h2?>
|
||||
<ul>
|
||||
<li><a href="http://www.winamp.com/">Winamp 2 & 3</a></li>
|
||||
<li><a href="http://sonique.lycos.com/">Sonique</a></li>
|
||||
<li><a href="http://www.zinf.org/">Zinf</a></li>
|
||||
</ul>
|
||||
<?h2 <a href="http://www.vorbis.com/software.psp?pid=3">MacOS</a> / <a href="http://www.vorbis.com/software.psp?pid=4">MacOS X</a> h2?>
|
||||
<ul>
|
||||
<li><a href="http://www.panic.com/audion/">Audion 3</a></li>
|
||||
<li><a href="http://mint.unsanity.com/">Mint Audio</a></li>
|
||||
<li><a href="http://www.videolan.org/vlc/">vlc</a></li></ul>
|
||||
<?h2 <a href="http://www.vorbis.com/software.psp?pid=1">Linux / BSD</a> h2?>
|
||||
<ul>
|
||||
<li><a href="http://www.xmms.org/">XMMS</a></li>
|
||||
<li><a href="http://www.zinf.org/">Zinf</a></li>
|
||||
<li><a href="http://sourceforge.net/projects/ovplayer/">ovplayer</a></li>
|
||||
</ul>
|
||||
<?p We are also maintaining <a href="http://www.livejournal.com/support/faqbrowse.bml?faqid=184">a list of instructions on achieving Ogg Vorbis playback</a> in other media players. p?>
|
||||
<=body
|
||||
page?>
|
||||
146
ljcom/htdocs/phonepost/transcribe.bml
Normal file
146
ljcom/htdocs/phonepost/transcribe.bml
Normal file
@@ -0,0 +1,146 @@
|
||||
<?page
|
||||
title=>PhonePost transcription
|
||||
body<=
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%POST %GET $ret);
|
||||
|
||||
my $MAX_REVS = 10;
|
||||
my $dppid = $GET{'ppid'} + 0;
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
my $u = LJ::load_user($GET{user});
|
||||
return "Invalid user." unless $u;
|
||||
my $is_owner = $remote && $remote->{userid} == $u->{userid};
|
||||
|
||||
my $bid = $dppid >> 8;
|
||||
my $ppe = LJ::PhonePost::get_phonepost_entry($u, $bid);
|
||||
return "Invalid phone post entry." unless $ppe && $ppe->{jitemid} && $ppe->{anum} == $dppid % 256;
|
||||
|
||||
# check security of item
|
||||
my $logrow = LJ::get_log2_row($u, $ppe->{jitemid});
|
||||
return "Invalid phone post entry. (Phone post exists, entry has been deleted.)" unless $logrow;
|
||||
unless ($logrow->{security} eq "public") {
|
||||
my $remote = LJ::get_remote();
|
||||
return "Access denied." unless LJ::can_view($remote, $logrow);
|
||||
}
|
||||
|
||||
my $jlink = LJ::item_link($u, $logrow->{jitemid}, $logrow->{anum});
|
||||
my $may_trans = LJ::PhonePost::may_transcribe($u, $remote);
|
||||
|
||||
return "Database unavailable." unless $u->writer;
|
||||
|
||||
my @trans_log;
|
||||
my $max_revid = 0;
|
||||
my $sth = $u->prepare("SELECT revid,posterid,posttime,subject,body " .
|
||||
"FROM phoneposttrans WHERE journalid=? AND blobid=?");
|
||||
$sth->execute($u->{userid}, $bid);
|
||||
while (my $r = $sth->fetchrow_hashref) {
|
||||
push @trans_log, $r;
|
||||
|
||||
# Once the owner has transcribed, no one else is allowed to.
|
||||
$may_trans = 0 if $r->{posterid} == $u->{userid} && !$is_owner;
|
||||
|
||||
# Everyone but the owner can only transcribe once.
|
||||
$may_trans = 0 if $remote &&
|
||||
$remote->{userid} != $u->{userid} &&
|
||||
$r->{posterid} == $remote->{userid};
|
||||
$max_revid = $r->{revid} > $max_revid ? $r->{revid} : $max_revid;
|
||||
}
|
||||
@trans_log = sort { $b->{revid} <=> $a->{revid} } @trans_log;
|
||||
|
||||
# The last revision 'slot' is reserved for the owner.
|
||||
$may_trans = 0 if $max_revid >= $MAX_REVS - 1 && !$is_owner;
|
||||
|
||||
# Save new revision.
|
||||
my $midair;
|
||||
if (LJ::did_post() && $may_trans) {
|
||||
|
||||
# Sanity check the rev id, make sure someone isn't faking it.
|
||||
my $revid = $POST{revid} + 0;
|
||||
my $new_revid = $max_revid + 1;
|
||||
return "Invalid revision ID." unless $revid >= 1 && $revid <= $new_revid && $revid <= $MAX_REVS;
|
||||
return "Last revision reserved for owner." if $revid == $MAX_REVS && !$is_owner;
|
||||
|
||||
my $body = LJ::trim($POST{body});
|
||||
my $subject = LJ::trim($POST{subj});
|
||||
return LJ::bad_input('Empty transcription') unless $body =~ /\S/;
|
||||
return LJ::bad_input('Invalid encoding') unless LJ::is_utf8($body) && LJ::is_utf8($subject);
|
||||
return LJ::bad_input('Subject too long.') if length($subject) > 200;
|
||||
return LJ::bad_input('Body too long.') if length($body) > 4096;
|
||||
|
||||
my $verb = 'INSERT';
|
||||
$verb = 'REPLACE' if $revid == $MAX_REVS && $is_owner;
|
||||
my $rv = $u->do("$verb IGNORE INTO phoneposttrans SET " .
|
||||
"revid=?, posterid=?, posttime=UNIX_TIMESTAMP(), subject=?, body=?, " .
|
||||
"journalid=?, blobid=?", undef,
|
||||
$new_revid, $remote->{userid}, $subject,
|
||||
$body, $u->{userid}, $bid);
|
||||
|
||||
# Duplicate revision numbers. Force user to review.
|
||||
$midair = $new_revid unless $rv > 0;
|
||||
|
||||
my $newr = { 'revid'=>$new_revid, 'posterid'=>$remote->{userid},
|
||||
'subject'=>$subject, 'body'=>$body };
|
||||
|
||||
unless ($midair) {
|
||||
# Add post to display.
|
||||
unshift @trans_log, $newr;
|
||||
$may_trans = 0 unless $is_owner;
|
||||
|
||||
# Modify journal subject.
|
||||
$u->do("UPDATE logtext2 SET subject=? WHERE journalid=? AND jitemid=?", undef,
|
||||
LJ::ehtml("Phone Post: $subject"), $u->{userid}, $logrow->{jitemid});
|
||||
my $memkey = [ $u->{userid}, "logtext:$u->{clusterid}:$u->{userid}:$logrow->{jitemid}" ];
|
||||
LJ::MemCache::delete($memkey);
|
||||
|
||||
# and delete the latest info
|
||||
$memkey = [$u->{userid},"ppelt:$u->{userid}:$bid"];
|
||||
LJ::MemCache::delete($memkey);
|
||||
$memkey = [$u->{userid},"ppetu:$u->{userid}:$bid"];
|
||||
LJ::MemCache::delete($memkey);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$ret .= "<div>[<< Back to <a href='$jlink'>this entry</a> from " . LJ::ljuser($u) . ']</div>';
|
||||
# Purty icon
|
||||
$ret .= '<div style="margin:30px;">' . LJ::PhonePost::make_link($remote, $u->{userid}, $bid, 'notrans') . '</div>';
|
||||
|
||||
if ($midair) {
|
||||
$ret .= "<?p Whoops! Someone added a transcription while you were making yours. Please compare with revision #$midair before re-posting. p?>";
|
||||
$ret .= "<div style='margin-left:40px;margin-bottom:40px'><i>";
|
||||
$ret .= "<b>" . LJ::ehtml($POST{subj}) . '</b><br />' if $POST{subj};
|
||||
$ret .= LJ::ehtml($POST{body}) . '</i></div>';
|
||||
}
|
||||
|
||||
# Display form.
|
||||
if ($may_trans) {
|
||||
$ret .= "<form method='post' action='transcribe.bml?user=$u->{user}&ppid=$dppid'>";
|
||||
$ret .= LJ::html_hidden('revid', $max_revid + 1);
|
||||
$ret .= "<?h2 Update transcription for this phonepost: h2?>";
|
||||
$ret .= "<div>";
|
||||
$ret .= '<b>Subject: </b>' . LJ::html_text({ name=>'subj', size=>50 }) . '<br />';
|
||||
$ret .= LJ::html_textarea({ name=>'body', cols=>70, rows=>5 }) . '<br />';
|
||||
$ret .= "<?standout ";
|
||||
$ret .= LJ::html_submit('save');
|
||||
$ret .= ' standout?></div></form>';
|
||||
}
|
||||
|
||||
# Display previous translations.
|
||||
foreach my $r (@trans_log) {
|
||||
$ret .= "<?h2 Revision #<b>$r->{revid}</b> by " . LJ::ljuser(LJ::get_username($r->{posterid})) . ' h2?>';
|
||||
$ret .= "<div style='margin-left:40px; margin-bottom:20px'>";
|
||||
$ret .= '<b>' . LJ::ehtml($r->{subject}) . '</b><br />' if $r->{subject};
|
||||
my $body = LJ::ehtml($r->{body});
|
||||
$body =~ s/\n/<br \/>/g;
|
||||
$ret .= $body;
|
||||
$ret .= "</div>";
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
_code?>
|
||||
<=body
|
||||
page?>
|
||||
Reference in New Issue
Block a user