commit bd158cb106efc27a31c0cac4c1e8487de542e5c6 Author: eleksir Date: Wed Sep 16 01:02:19 2020 +0300 Initial commit. Split joyproxy from myapi as separate application. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..4ff3f42 --- /dev/null +++ b/LICENSE @@ -0,0 +1,127 @@ + The "Artistic License" + + Preamble + +The intent of this document is to state the conditions under which a +Package may be copied, such that the Copyright Holder maintains some +semblance of artistic control over the development of the package, +while giving the users of the package the right to use and distribute +the Package in a more-or-less customary fashion, plus the right to make +reasonable modifications. + +Definitions: + + "Package" refers to the collection of files distributed by the + Copyright Holder, and derivatives of that collection of files + created through textual modification. + + "Standard Version" refers to such a Package if it has not been + modified, or has been modified in accordance with the wishes + of the Copyright Holder as specified below. + + "Copyright Holder" is whoever is named in the copyright or + copyrights for the package. + + "You" is you, if you're thinking about copying or distributing + this Package. + + "Reasonable copying fee" is whatever you can justify on the + basis of media cost, duplication charges, time of people involved, + and so on. (You will not be required to justify it to the + Copyright Holder, but only to the computing community at large + as a market that must bear the fee.) + + "Freely Available" means that no fee is charged for the item + itself, though there may be fees involved in handling the item. + It also means that recipients of the item may redistribute it + under the same conditions they received it. + +1. You may make and give away verbatim copies of the source form of the +Standard Version of this Package without restriction, provided that you +duplicate all of the original copyright notices and associated disclaimers. + +2. You may apply bug fixes, portability fixes and other modifications +derived from the Public Domain or from the Copyright Holder. A Package +modified in such a way shall still be considered the Standard Version. + +3. You may otherwise modify your copy of this Package in any way, provided +that you insert a prominent notice in each changed file stating how and +when you changed that file, and provided that you do at least ONE of the +following: + + a) place your modifications in the Public Domain or otherwise make them + Freely Available, such as by posting said modifications to Usenet or + an equivalent medium, or placing the modifications on a major archive + site such as uunet.uu.net, or by allowing the Copyright Holder to include + your modifications in the Standard Version of the Package. + + b) use the modified Package only within your corporation or organization. + + c) rename any non-standard executables so the names do not conflict + with standard executables, which must also be provided, and provide + a separate manual page for each non-standard executable that clearly + documents how it differs from the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +4. You may distribute the programs of this Package in object code or +executable form, provided that you do at least ONE of the following: + + a) distribute a Standard Version of the executables and library files, + together with instructions (in the manual page or equivalent) on where + to get the Standard Version. + + b) accompany the distribution with the machine-readable source of + the Package with your modifications. + + c) give non-standard executables non-standard names, and clearly + document the differences in manual pages (or equivalent), together + with instructions on where to get the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +5. You may charge a reasonable copying fee for any distribution of this +Package. You may charge any fee you choose for support of this +Package. You may not charge a fee for this Package itself. However, +you may distribute this Package in aggregate with other (possibly +commercial) programs as part of a larger (possibly commercial) software +distribution provided that you do not advertise this Package as a +product of your own. You may embed this Package's interpreter within +an executable of yours (by linking); this shall be construed as a mere +form of aggregation, provided that the complete Standard Version of the +interpreter is so embedded. + +6. The scripts and library files supplied as input to or produced as +output from the programs of this Package do not automatically fall +under the copyright of this Package, but belong to whoever generated +them, and may be sold commercially, and may be aggregated with this +Package. If such scripts or library files are aggregated with this +Package via the so-called "undump" or "unexec" methods of producing a +binary executable image, then distribution of such an image shall +neither be construed as a distribution of this Package nor shall it +fall under the restrictions of Paragraphs 3 and 4, provided that you do +not represent such an executable image as a Standard Version of this +Package. + +7. C subroutines (or comparably compiled subroutines in other +languages) supplied by you and linked into this Package in order to +emulate subroutines and variables of the language defined by this +Package shall not be considered part of this Package, but are the +equivalent of input as in Paragraph 6, provided these subroutines do +not change the language in any way that would cause it to fail the +regression tests for the language. + +8. Aggregation of this Package with a commercial distribution is always +permitted provided that the use of this Package is embedded; that is, +when no overt attempt is made to make this Package's interfaces visible +to the end user of the commercial distribution. Such use shall not be +construed as a distribution of this Package. + +9. The name of the Copyright Holder may not be used to endorse or promote +products derived from this software without specific prior written permission. + +10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + The End diff --git a/README.md b/README.md new file mode 100644 index 0000000..71a17a4 --- /dev/null +++ b/README.md @@ -0,0 +1,44 @@ +# Joyproxy + +## Что это? + +Своего рода API, делающий запросы в img#.reactor.cc + +## Зачем это нужно? + +Сайт reactor.cc не даёт возможности постить на внешние ресурсы ссылки без +указания правильного referer-а. + +Эта прокся призвана частично решить эту проблему через создание линков вида +`https://сайт/префикс/joyproxy/img1.reactor.cc/pics/post/mp4/видосик.mp4` + +Сгенерировать ссылку можно запостив урл с видосиком в форму на страничке +`https://сайт/префикс/joyurl` + +## Как это работает? + +При обращении к сгенерённому урлу, апи вначале идёт на сайт, выкачивает +видосик во временный каталог, отдаёт видосик клиенту и удаляет его из +временного каталога. Есть встроенное ограничение на размер файла в 10Мб. + +## Как это запустить? + +Я это запускаю как [PSGI][1]-приложение, через [UWSGI][2]. + +Для запуска понадобятся: + +* uwsgi версии 2.0.15 или новее +* perl-5.18 или новее (вплоть до 5.32.x) +* модули perl-HTTP-Tiny, perl-URI-URL, perl-URL-Escape, perl-local-lib. + +Можно использовать модули из системы, а можно подтянуть их из CPAN-а с помощью +[cpanm][3] (но, правда, perl-local-lib всё же придётся поставить, так как без +него ничего не заработает). + +## Кому сказать спасибо? + +Авторам, редакторам и тем, кто поддерживает `reactor.cc` + +[1]: https://uwsgi-docs.readthedocs.io/en/latest/Perl.html +[2]: https://github.com/unbit/uwsgi +[3]: https://github.com/miyagawa/cpanminus diff --git a/bootstrap.sh b/bootstrap.sh new file mode 100644 index 0000000..697f373 --- /dev/null +++ b/bootstrap.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +cpanm -l vendor_perl --self-contained --force --update --installdeps . + +# vim: set ft=perl noet ai ts=4 sw=4 sts=4: diff --git a/cpanfile b/cpanfile new file mode 100644 index 0000000..227c3eb --- /dev/null +++ b/cpanfile @@ -0,0 +1,3 @@ +require HTTP::Tiny; +require URI::URL; +require URI::Escape; diff --git a/joyproxy.pm b/joyproxy.pm new file mode 100644 index 0000000..20933cd --- /dev/null +++ b/joyproxy.pm @@ -0,0 +1,169 @@ +package joyproxy; + +use 5.018; +use strict; +use warnings "all"; +use utf8; +use open qw(:std :utf8); + +use HTTP::Tiny; +use URI::URL; +use URI::Escape qw(uri_unescape); + +use Exporter qw(import); +use vars qw/$VERSION/; + +$VERSION = "1.0"; +our @EXPORT = qw(joyproxy joyurl); + +$| = 1; + +sub joyproxy ($) { + my $str = shift; + chomp($str); + + return ('500', 'text/plain', 'This is not reactor video') if ($str !~ /^img[0-9]+\.reactor\.cc/); + + my ($file, $filesize) = __dlfunc("http://$str"); + + if (defined($file)) { + my $buf = ''; + + if (open(VID, '<', $file)) { + read(VID, $buf, $filesize); + close VID; + + if ($file =~ /\.mp4/i) { + return ('200', 'video/mp4', $buf); + } elsif ($file =~ /\.webm/i) { + return ('200', 'video/webm', $buf); + } else { + return ('200', 'video/mpeg', $buf); + } + } else { + unlink $file if (-f $file); + return ('500', 'text/plain', "Unable to open file in temporary loaction: $!\n"); + } + } else { + return ('500', 'text/plain', "Unable to get file from remote source!\n"); + } +} + +sub joyurl (@) { + my $str = shift; + my $host = shift; + my $prefix = shift; + $str = uri_unescape($str); + + if (length($str) < 60) { + $str = ''; + } else { + $str = substr($str, 14); + } + + if ($str =~ /^img\d+\.reactor\.cc/) { + # img1.reactor.cc/pics/post/webm/видосик.webm + my @url = split(/\//, $str); + + if (($url[3] eq 'webm' || $url[3] eq 'mp4') and + ($url[4] =~ /\.webm$/ || $url[4] =~ /\.mp4$/)) { + # we prefer mp4, right?, so + my $fname; + $fname = substr($url[4], 0, -4) if (substr($url[4], -4, 4) eq '.mp4'); + $fname = substr($url[4], 0, -5) if (substr($url[4], -5, 6) eq '.webm'); + + $str = sprintf( + "https://%s/%s/joyproxy/%s/%s/%s/mp4/%s.mp4", + $host, + $prefix, + $url[0], + $url[1], + $url[2], + $fname + ); + + $str = __urlencode($str); + } else { + $str = ''; + } + } else { + $str = ''; + } + + my $msg = "\n\n
\n
\n\n
$str\n\n\n"; + + return ('200', 'text/html', $msg); +} + +sub __urlencode($) { + my $str = shift; + my $urlobj = url $str; + $str = $urlobj->as_string; + $urlobj = undef; + undef $urlobj; + return $str; +} + +sub __dlfunc($) { + my $url = shift; + + if (! -d "/tmp/joyproxy") { + warn "no /tmp/joyproxy"; + return (undef, undef) unless (mkdir("/tmp/joyproxy")); + } + + my @tmparray = split(/\//, $url); + my $file = $tmparray[@tmparray - 1]; + $#tmparray = -1; undef @tmparray; + $file = "/tmp/joyproxy/" . $file; + $url = __urlencode($url); + + my $http = HTTP::Tiny->new(max_size => 10485760); + + my $response = $http->get( + $url, + { + headers => { + "Accept" => '*/*', + "Accept-Encoding" => 'identity;q=1, *;q=0', + "Accept-Language" => 'ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7', + "Range" => 'bytes=0-', + "Referer" => 'http://old.reactor.cc/all', + "User-Agent" => "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36" + } + } + ); + + if ($response->{success}) { + my $filesize = 0; + + open (FILE, '>', $file) or do { + $http = undef; + $response = undef; + return (undef, undef); + }; + + binmode FILE; + + print (FILE $response->{content}) or do { + $http = undef; + $response = undef; + return (undef, undef); + }; + + close FILE; + $http = undef; + $response = undef; + $filesize = (stat($file))[7]; + return ($file, $filesize); + } else { + $http = undef; + $response = undef; + return (undef, undef); + } +} + + +1; + +# vim: set ft=perl noet ai ts=4 sw=4 sts=4: diff --git a/joyproxy.psgi b/joyproxy.psgi new file mode 100644 index 0000000..591cc13 --- /dev/null +++ b/joyproxy.psgi @@ -0,0 +1,51 @@ +use 5.018; +use strict; +use warnings "all"; +use utf8; +use open qw(:std :utf8); + +use lib qw(. ./vendor_perl/lib/perl5); +use joyproxy qw(joyurl joyproxy); + +$| = 1; + +my $prefix = "api"; + +my $app = sub { + my $env = shift; + + my $msg = "Your Opinion is very important for us, please stand by.\n"; + my $status = '404'; + my $content = 'text/plain'; + + if ($env->{PATH_INFO} =~ /$prefix\/joyproxy\/(.+)/) { + my $joyproxyurl = $1; + ($status, $content, $msg) = ('400', $content, "Bad Request?\n"); + + if (($joyproxyurl =~ /\.mp4/i) or ($joyproxyurl =~ /\.webm/i)) { + ($status, $content, $msg) = joyproxy($joyproxyurl); + } + } + + if ($env->{PATH_INFO} =~ /$prefix\/joyurl/) { + if (defined($env->{QUERY_STRING})) { + ($status, $content, $msg) = joyurl($env->{QUERY_STRING}, $env->{HTTP_HOST}, $prefix); + } else { + ($status, $content, $msg) = joyurl('', $env->{HTTP_HOST}, $prefix); + } + } + + use bytes; + my $length = length($msg); + no bytes; + + return [ + $status, + [ 'Content-Type' => $content, 'Content-Length' => $length ], + [ $msg ], + ]; +}; + + +__END__ +# vim: set ft=perl noet ai ts=4 sw=4 sts=4: