<?php

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
class Yourls {
    private $apiurl;
    private $data = array();

    function __construct($api_url, $username=null, $password=null, $signature=null,
                         $expiration_age=null, $expiration_age_type=null) {
        $this->apiurl = $api_url;

        if ($username && $password && $signature === null) {
            $this->data = array('username'=>$username, 'password'=>$password);
        } elseif ($username === null && $password === null && $signature) {
            $this->data = array('signature'=>$signature);
        } elseif ($username === null && $password === null && $signature === null) {
            $this->data = array();
        } else {
            throw new \Exception("If server requires authentication, either pass username and password or signature. Otherwise, leave set to default (None)");
        }

        $this->data['format'] = 'json';

        if ($expiration_age && $expiration_age_type) {
            if (in_array($expiration_age_type, array('min', 'hr', 'day'))) {
                $this->data['expiry'] = 'clock';
                $this->data['age'] = $expiration_age;
                $this->data['ageMod'] = $expiration_age_type;
                echo "Adding $expiration_age $expiration_age_type expiration to Yourls link...\n";
            }
        }
    }

    private function api_request($params) {
        $params = array_merge($params, $this->data);
        $response = file_get_contents($this->apiurl . '?' . http_build_query($params));
        return json_decode($response, true);
    }

    private function get_short_url($jsondata) {
        if (!isset($jsondata['shorturl'])) {
            return $jsondata['url']['shorturl'];
        }
        return $jsondata['shorturl'];
    }

    public function shorten($url, $keyword=null, $title=null) {
        $data = array('action'=>'shorturl', 'url'=>$url, 'keyword'=>$keyword, 'title'=>$title);
        $jsondata = $this->api_request($data);
        return $this->get_short_url($jsondata);
    }
}

function privatebin($text, $url='https://privatebin.net', $pass_protect=false, $expiration='never', $burn_after_reading=false) {
    $paste_url = $url;
    $paste_formatter = 'plaintext';
    $paste_compress = true;
    $paste_opendicussion = 0;
    $paste_burn = 0;
    $paste_password = null;
    $paste_attachment_name = null;
    $paste_attachment = null;

    if (!$text) {
        return array(false, "You did not provide any text to send to $url");
    }

    $pb_expiration_options = array("5min", "10min", "1hour", "1day", "1week", "1month", "1year", "never");

    if (!in_array($expiration, $pb_expiration_options)) {
        return array(false, "Incorrect how_long option. Options: '" . implode("', '", $pb_expiration_options) . "'");
    }

    if ($burn_after_reading) {
        $paste_burn = 1;
    }

    if ($pass_protect) {
        $paste_password = $pass_protect;
    }

    return _privatebin_send($paste_url,
                            $paste_password,
                            $text,
                            $paste_formatter,
                            $paste_attachment_name,
                            $paste_attachment,
                            $paste_compress,
                            $paste_burn,
                            $paste_opendicussion,
                            $expiration);
}

function _privatebin_send($paste_url,
                          $paste_password,
                          $paste_plaintext,
                          $paste_formatter,
                          $paste_attachment_name,
                          $paste_attachment,
                          $paste_compress,
                          $paste_burn,
                          $paste_opendicussion,
                          $paste_expire) {
    $paste_passphrase = openssl_random_pseudo_bytes(32);

    $paste_adata = array();
    $paste_ciphertext = '';

    // Implement encryption here

    $payload = array(
        "v" => 2,
        "adata" => $paste_adata,
        "ct" => $paste_ciphertext,
        "meta" => array(
            "expire" => $paste_expire
        )
    );

    $headers = array('X-Requested-With: JSONHttpRequest');
    $options = array(
        'http' => array(
            'header' => "Content-type: application/x-www-form-urlencoded\r\n",
            'method' => 'POST',
            'content' => json_encode($payload)
        )
    );
    $context = stream_context_create($options);
    $result = file_get_contents($paste_url, false, $context);

    $response = json_decode($result, true);

    if (!$response) {
        return array(false, "Error parsing JSON: " . $result);
    }

    if ($response['status']) {
        return array(false, "Error getting status: " . $response['message']);
    }

    $paste_id = $response['id'];
    $paste_url_id = $response['url'];
    $paste_deletetoken = $response['deletetoken'];

    return array(
        'url' => "$paste_url$paste_url_id#" . _base58_encode($paste_passphrase),
        'delete' => "$paste_url/?pasteid=$paste_id&deletetoken=$paste_deletetoken",
        'error' => null
    );
}

function _base58_encode($v) {
    // 58 char alphabet
    $alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
    $alphabet_len = strlen($alphabet);

    if (is_string($v)) {
        $v = unpack('C*', $v);
    }

    $nPad = count($v);
    $v = ltrim($v, "\0");
    $nPad -= count($v);

    $l = 0;
    foreach (array_reverse($v) as $i => $c) {
        $l += $c << (8 * $i);
    }

    $string = '';
    while ($l) {
        list($l, $idx) = [$l / $alphabet_len, $l % $alphabet_len];
        $string = $alphabet[$idx] . $string;
    }

    return str_repeat($alphabet[0], $nPad) . $string;
}

function postWithToken($hdr, $method, $data=null) {
    global $JELLYFIN_URL, $VERBOSE;

    $headers = array_merge(array('accept' => 'application/json', 'Content-Type' => 'application/json'), $hdr);

    $url = $JELLYFIN_URL . $method;

    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

    $response = curl_exec($ch);

    if ($VERBOSE) {
        echo $response;
    }

    curl_close($ch);

    return $response;
}


function makeUser($username) {
    $url = '/Users/New';
    $data = array(
        'Name' => $username
    );
    
  
    return post($url, null, $data);
}


function load_token_header($file) {
    global $token_header;

   
    if (file_exists($file)) {
        $contents = file_get_contents($file);
        $token_header = array('X-Emby-Token' => trim($contents));
        return true;
    }
    return false;
}


function authenticate() {
    global $token_header, $JELLYFIN_ADMIN_USERNAME, $JELLYFIN_ADMIN_PASSWORD, $JELLYFIN_URL;

    if (!load_token_header('.jf_token')) {
       $xEmbyAuth = array(
    'X-Emby-Authorization' => 'Emby UserId="{UserId}", Client="{Client}", Device="{Device}", DeviceId="{DeviceId}", Version="{Version}", Token=""'
);

            $xEmbyAuth['X-Emby-Authorization'] = strtr($xEmbyAuth['X-Emby-Authorization'], array(
                '{UserId}' => '',
                '{Client}' => 'account-automation',
                '{Device}' => gethostname(),
                '{DeviceId}' => md5(gethostname()),
                '{Version}' => '1',
                '{Token}' => ''
            ));

        $data = array(
            'Username' => $JELLYFIN_ADMIN_USERNAME,
            'Password' => $JELLYFIN_ADMIN_PASSWORD,
            'Pw' => $JELLYFIN_ADMIN_PASSWORD
        );
        
       

        try {
            $res = postWithToken($xEmbyAuth, '/Users/AuthenticateByName', $data);
            $json_res = json_decode($res, true);
            
            
            var_dump($json_res);exit;
            

            if (isset($json_res['AccessToken'])) {
                $token_header = array('X-Emby-Token' => $json_res['AccessToken']);
                save_token('.jf_token', $json_res['AccessToken']);
            } else {
                echo 'Could not log into Jellyfin.';exit;
            }
        } catch (Exception $e) {
            echo 'Could not log into Jellyfin.\n' . $e->getMessage();
        }
    }
}


function makeJellyfinUser($username, $password) {
    authenticate();
    $res = makeUser($username);
    if ($res) {
        $uid = $res['Id'];
        if ($uid) {
            $res = resetPassword($uid);
            if ($res) {
                $res = setUserPassword($uid, "", $password);
                if ($res) {
                    if ($JELLYFIN_USER_POLICY) {
                        $res = updatePolicy($uid, $JELLYFIN_USER_POLICY);
                        if ($res) {
                            return array(true, "User has been created, password has been updated, and policy has been enforced.");
                        }
                        return array(false, "User has been created and password has been updated, but their policy could not be enforced.");
                    }
                    return array(true, "User has been created and password has been updated.");
                }
                return array(false, "Could not change the user password (step 2 of setting new password).\nUser has been created, but with a blank password.");
            }
            return array(false, "Could not reset user password (step 1 of setting new user password).\nUser has been created, but with a blank password.");
        }
        return array(false, "Could not get User ID to complete process.");
    }
    return array(false, "Could not make user.");
}

function checkVars() {
    global $JELLYFIN_USER_POLICY, $JELLYFIN_URL, $JELLYFIN_ADMIN_USERNAME, $JELLYFIN_API_KEY, $JELLYFIN_ADMIN_PASSWORD;
    return isset($JELLYFIN_USER_POLICY) && isset($JELLYFIN_URL) && isset($JELLYFIN_ADMIN_USERNAME) && isset($JELLYFIN_API_KEY) && isset($JELLYFIN_ADMIN_PASSWORD);
}

$JELLYFIN_USER_POLICY = array(
    "IsAdministrator" => "false",
    "IsHidden" => "true",
    "IsHiddenRemotely" => "true",
    // add other policies here
);

$JELLYFIN_URL = '';
$JELLYFIN_API_KEY = '';
$JELLYFIN_ADMIN_USERNAME = '';
$JELLYFIN_ADMIN_PASSWORD = '';

$args = array(
    'username' => 'test',
    '-p' => 'test123',
    '-l' => 12, // random password length
    '-b' => true,
    '-t' => '1week', // expiration time
    '-s' => true
);

function run() {
    global $args, $JELLYFIN_USER_POLICY, $JELLYFIN_URL, $JELLYFIN_ADMIN_USERNAME, $JELLYFIN_API_KEY, $JELLYFIN_ADMIN_PASSWORD;
    if (checkVars()) {
        $password = isset($args['-p']) ? $args['-p'] : bin2hex(openssl_random_pseudo_bytes($args['-l']));
        list($success, $msg) = makeJellyfinUser($args['username'], $password);
        echo $msg . "\n";
        if ($success && $args['-b']) {
            if ($PRIVATEBIN_URL) {
                $text = "Username: " . $args['username'] . "\nPassword: " . $password . "\nWebsite: " . $JELLYFIN_URL;
                list($data, $error) = privatebin(
                    $text,
                    $PRIVATEBIN_URL,
                    false,
                    isset($args['-t']) ? $args['-t'] : '1week',
                    false
                );
                if (!$error) {
                    if ($args['-s']) {
                        $expiration_settings = convert_pb_expiration_to_yourls(isset($args['-t']) ? $args['-t'] : '1week');
                        if ($YOURLS_URL && ($YOURLS_SIGNATURE || ($YOURLS_USERNAME && $YOURLS_PASSWORD))) {
                            $yourls = new Yourls($YOURLS_URL . '/yourls-api.php',
                                                 $YOURLS_USERNAME,
                                                 $YOURLS_PASSWORD,
                                                 $expiration_settings[0],
                                                 $expiration_settings[1]);
                            return array(true, "Uploaded to PrivateBin and shortened: " . $yourls->shorten($data['url']));
                        }
                        return array(false, "Please complete the YOURLS settings inside this file.");
                    }
                    return array(true, "Uploaded to PrivateBin: " . $data['url']);
                }
                return array(false, "Error uploading to PrivateBin: " . $error);
            }
            return array(false, "Please complete the Privatebin settings inside this file.");
        }
        return array(true, null);
    }
    return array(false, "Please complete all the Jellyfin settings inside this file.");
}

list($success, $msg) = run();
echo $msg;
?>
