Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/perl
- use strict;
- use experimental 'smartmatch';
- use WWW::Mechanize;
- use JSON::XS;
- use MIME::Base64;
- use XML::Simple;
- use Term::ReadKey;
- use HTTP::Cookies;
- ########################################################################################################################
- # main{} #
- ########################################################################################################################
- # All separate instances of this script (or any other Plex-interacting software) needs its own id.
- my $uuid = '99';
- # Does this thing even have a proper uuid?
- if ($uuid eq '1') {
- # Self-modifying code?
- }
- # Arguments. This is perl, no one nancies around about "debates" and "discussions".
- my ($servername, $friendname, $status, $librarynames) = @ARGV;
- if ($#ARGV != 3) {
- print "\nUsage: plex_share_changer.pl server friend [enable|disable] library1,library2\n";
- exit 1;
- }
- unless ($status eq "enable" || $status eq "disable") {
- print "\nUsage: plex_share_changer.pl server friend [enable|disable] library1,library2\n";
- exit 1;
- }
- my @lns = split(',', $librarynames);
- # Suddenly web robot.
- my $mech = WWW::Mechanize->new(autocheck => 0);
- $mech->agent_alias('Mac Safari');
- # Some headers we apparently need...
- $mech->add_header('X-Plex-Client-Identifier' => $uuid);
- $mech->add_header('X-Plex-Product' => 'Library Share Kicker');
- $mech->add_header('X-Plex-Version' => '0.01');
- # We need to check if we already have a usable token.
- if (-e "$ENV{'HOME'}/.plextoken") {
- my $token = do { local(@ARGV, $/) = "$ENV{'HOME'}/.plextoken"; <> };
- $mech->add_header('X-Plex-Token' => $token);
- # This token might be stale, or the file might have been garbled. We'll check, and if it's bad bounce to the
- # subroutine anyway.
- $mech->get("https://plex.tv/pms/servers.xml");
- if (!$mech->success()) {
- &authenticate;
- }
- }
- else {
- &authenticate;
- }
- # Let's get the server id.
- my %servers;
- $mech->get("https://plex.tv/pms/servers.xml");
- my $xml2 = XMLin($mech->content(), ForceArray => 1);
- foreach my $key (keys $xml2->{'Server'}) {
- if ($xml2->{'Server'}->{$key}->{'owned'}) {
- $servers{$key} = $xml2->{'Server'}->{$key}->{'machineIdentifier'};
- }
- }
- # Notes: It looks like it might be theoretically possible for a single user to have more than one server (why?), so we
- # keep all of them that are "owned", and use whichever one they've specified. Unless they give bullshit, then we just
- # tell them to go fuck themselves. Nicely though, and cryptically.
- unless ($servers{$servername}) {
- print "No such server.\n";
- exit 2;
- }
- # We need to get a list of users.
- my %users;
- $mech->get("https://plex.tv/api/users");
- my $xml = XMLin($mech->content(), ForceArray => 1);
- foreach my $key (keys $xml->{'User'}) {
- $users{$xml->{'User'}->{$key}->{'title'}} = $xml->{'User'}->{$key}->{'Server'}->{$servername}->{'id'};
- }
- unless ($users{$friendname}) {
- print "No such friend.\n";
- exit 3;
- }
- # Now we need a list of library ids.
- my @libraries;
- $mech->get("https://plex.tv/api/servers/" . $servers{$servername} . "/shared_servers/" . $users{$friendname});
- my $xml3 = XMLin($mech->content(), ForceArray => 1);
- foreach my $key (keys $xml3->{'SharedServer'}->{$servername}->{'Section'}) {
- if ($status eq "enable") {
- # if in array or if already
- if ($xml3->{'SharedServer'}->{$servername}->{'Section'}->{$key}->{'shared'}) {
- push(@libraries, $xml3->{'SharedServer'}->{$servername}->{'Section'}->{$key}->{'id'});
- }
- elsif ($xml3->{'SharedServer'}->{$servername}->{'Section'}->{$key}->{'title'} ~~ @lns) {
- push(@libraries, $xml3->{'SharedServer'}->{$servername}->{'Section'}->{$key}->{'id'});
- }
- }
- elsif ($status eq "disable") {
- # if already and not in array
- if ($xml3->{'SharedServer'}->{$servername}->{'Section'}->{$key}->{'shared'} &&
- !($xml3->{'SharedServer'}->{$servername}->{'Section'}->{$key}->{'title'} ~~ @lns)) {
- push(@libraries, $xml3->{'SharedServer'}->{$servername}->{'Section'}->{$key}->{'id'});
- }
- }
- }
- # Send the update to plex.tv for library sharing... once this is done, only those libraries in @libraries will still be
- # shared. (This is why we went through checking if they were already shared, so we could add them to the list.)
- my $j = encode_json { "server_id" => $servers{$servername}, "shared_server" => { "library_section_ids" => \@libraries } };
- $mech->put("https://plex.tv/api/servers/" . $servers{$servername} . "/shared_servers/" . $users{$friendname},
- 'Content-Type' => 'application/json',
- Content => $j);
- ########################################################################################################################
- # Subroutines. #
- ########################################################################################################################
- sub authenticate {
- # Ok, so we'll need a password...
- print "Username (email): ";
- my $u = <STDIN>;
- chomp($u);
- print "Password: ";
- ReadMode ('noecho');
- my $p = <STDIN>;
- chomp($p);
- ReadMode ('restore');
- print "\n";
- # Just sign in.
- $mech->add_header('Authorization' => 'Basic ' . encode_base64("$u:$p"));
- $mech->post("https://plex.tv/users/sign_in.json");
- # Parse for a token!
- my $json = JSON::XS->new->utf8->decode($mech->content());
- $mech->add_header('X-Plex-Token' => $json->{'user'}->{'authentication_token'});
- # So we don't have to do this a second time.
- open(my $fh, '>', "$ENV{'HOME'}/.plextoken");
- print $fh $json->{'user'}->{'authentication_token'};
- close $fh;
- }
Add Comment
Please, Sign In to add comment