├── Master-Colab.ipynb └── Master_Colab_Notebook_Working_&_Updated_(March_2020).ipynb /Master_Colab_Notebook_Working_&_Updated_(March_2020).ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "Master Colab Notebook - Working & Updated (March 2020)", 7 | "provenance": [], 8 | "collapsed_sections": [ 9 | "zRTgBdCpBWMh", 10 | "cOUZEXihsqCD", 11 | "bNAroQWy6hL3", 12 | "wZMZjX127rmx", 13 | "4E-uzYrv5o0B", 14 | "ZVIyGBSmjlOY", 15 | "AAOkoLYa1nQb", 16 | "smfdosUWghxD", 17 | "Nx9ud5luiyJY", 18 | "8YFON0D4mVdr", 19 | "StT2bKf2WmKj", 20 | "mtIWnZ60Sczn", 21 | "jWNiE-RGECHM", 22 | "MbJ_88vSD-K2", 23 | "yTPpo294F0U8", 24 | "n3MWoStHEnJx", 25 | "DYreGU9NvCdk", 26 | "t0eVljW0O0CG", 27 | "ukxnQC4c0nuR", 28 | "EFOqhHG6hOVH", 29 | "KgNPvGccgwd8", 30 | "RDHuIkoi6l9a", 31 | "NQ0TxfKeghR8", 32 | "FpJXJiRl6-gK", 33 | "2f-THZmDoOaY", 34 | "MSUasbRUDP3B", 35 | "0xI8WiUPji3k", 36 | "Nl4RbJbX0-a4", 37 | "QlsUJhNwyeV3", 38 | "cHTe9qp2E6f5", 39 | "kAdRu4gm5k8v" 40 | ], 41 | "include_colab_link": true 42 | }, 43 | "kernelspec": { 44 | "name": "python3", 45 | "display_name": "Python 3" 46 | }, 47 | "accelerator": "TPU" 48 | }, 49 | "cells": [ 50 | { 51 | "cell_type": "markdown", 52 | "metadata": { 53 | "id": "view-in-github", 54 | "colab_type": "text" 55 | }, 56 | "source": [ 57 | "\"Open" 58 | ] 59 | }, 60 | { 61 | "cell_type": "markdown", 62 | "metadata": { 63 | "colab_type": "text", 64 | "id": "zRTgBdCpBWMh" 65 | }, 66 | "source": [ 67 | "# ✦ *Quick Useful Scripts:*" 68 | ] 69 | }, 70 | { 71 | "cell_type": "markdown", 72 | "metadata": { 73 | "id": "cOUZEXihsqCD", 74 | "colab_type": "text" 75 | }, 76 | "source": [ 77 | "## ✧ MediaInfo" 78 | ] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "metadata": { 83 | "id": "NTULRguzu0b0", 84 | "colab_type": "code", 85 | "cellView": "form", 86 | "colab": {} 87 | }, 88 | "source": [ 89 | "path = \"\" #@param {type:\"string\"}\n", 90 | "save_txt = False #@param {type:\"boolean\"}\n", 91 | "import os, uuid, re, IPython\n", 92 | "import ipywidgets as widgets\n", 93 | "import time\n", 94 | "\n", 95 | "from glob import glob\n", 96 | "from IPython.display import HTML, clear_output\n", 97 | "from google.colab import output, drive\n", 98 | "\n", 99 | "def mediainfo():\n", 100 | " display(HTML(\"
\"))\n", 101 | "# print(path.split(\"/\")[::-1][0])\n", 102 | " display(HTML(\"
\"))\n", 103 | "# media = !mediainfo \"$path\"\n", 104 | "# media = \"\\n\".join(media).replace(os.path.dirname(path)+\"/\", \"\")\n", 105 | " get_ipython().system_raw(\"\"\"mediainfo --LogFile=\"/root/.nfo\" \"$path\" \"\"\")\n", 106 | " with open('/root/.nfo', 'r') as file:\n", 107 | " media = file.read()\n", 108 | " media = media.replace(os.path.dirname(path)+\"/\", \"\")\n", 109 | " print(media)\n", 110 | " get_ipython().system_raw(\"rm -f '/root/.nfo'\")\n", 111 | " \n", 112 | " if save_txt:\n", 113 | " txt = path.rpartition('.')[0] + \".txt\"\n", 114 | " if os.path.exists(txt):\n", 115 | " get_ipython().system_raw(\"rm -f '$txt'\")\n", 116 | " !curl -s https://pastebin.com/raw/TApKLQfM -o \"$txt\"\n", 117 | " with open(txt, 'a+') as file:\n", 118 | " file.write(\"\\n\\n\")\n", 119 | " file.write(media)\n", 120 | "\n", 121 | "while not os.path.exists(\"/content/drive\"):\n", 122 | " try:\n", 123 | " drive.mount(\"/content/drive\")\n", 124 | " clear_output(wait=True)\n", 125 | " except:\n", 126 | " clear_output()\n", 127 | " \n", 128 | "if not os.path.exists(\"/usr/bin/mediainfo\"):\n", 129 | " get_ipython().system_raw(\"apt-get install mediainfo\")\n", 130 | " \n", 131 | "mediainfo()" 132 | ], 133 | "execution_count": 0, 134 | "outputs": [] 135 | }, 136 | { 137 | "cell_type": "markdown", 138 | "metadata": { 139 | "id": "bNAroQWy6hL3", 140 | "colab_type": "text" 141 | }, 142 | "source": [ 143 | "## ✧ Generate Streamable Video Links from Google Drive\n", 144 | "##### *Note: This cell will only work with links that are shared publically*" 145 | ] 146 | }, 147 | { 148 | "cell_type": "code", 149 | "metadata": { 150 | "colab_type": "code", 151 | "cellView": "form", 152 | "id": "W4EXnKHuwmq0", 153 | "colab": {} 154 | }, 155 | "source": [ 156 | "import re\n", 157 | "\n", 158 | "shared_file_link = \"https://drive.google.com/open?id=\" #@param {type:\"string\"}\n", 159 | "result = re.search(\"[\\w-]{33}\", shared_file_link)\n", 160 | "your_api_key = \"\" #@param {type:\"string\"}\n", 161 | "drive_file_id = result.group(0)\n", 162 | "\n", 163 | "beg_url = \"https://www.googleapis.com/drive/v3/files/\"\n", 164 | "end_url = \"/?key=\" + your_api_key + \"&alt=media\"\n", 165 | "\n", 166 | "print(beg_url + drive_file_id + end_url)\n", 167 | "\n", 168 | "## *This cell will only work with links that are shared publically*" 169 | ], 170 | "execution_count": 0, 171 | "outputs": [] 172 | }, 173 | { 174 | "cell_type": "markdown", 175 | "metadata": { 176 | "id": "wZMZjX127rmx", 177 | "colab_type": "text" 178 | }, 179 | "source": [ 180 | "## ✧ Crash Colab to clear all RAM" 181 | ] 182 | }, 183 | { 184 | "cell_type": "code", 185 | "metadata": { 186 | "id": "OH3xVkwWmPYL", 187 | "colab_type": "code", 188 | "cellView": "form", 189 | "colab": {} 190 | }, 191 | "source": [ 192 | "#@title ← ឵឵ ឵Run this cell to crash your current Runtime if you're low on memory\n", 193 | "#@markdown After crashing, you'll have access to all the preoccupied storage\n", 194 | "some_str = ' ' * 5120000000000" 195 | ], 196 | "execution_count": 0, 197 | "outputs": [] 198 | }, 199 | { 200 | "cell_type": "markdown", 201 | "metadata": { 202 | "id": "4E-uzYrv5o0B", 203 | "colab_type": "text" 204 | }, 205 | "source": [ 206 | "# **0.** Mounting with rclone\n", 207 | "# \"rclone\"/" 208 | ] 209 | }, 210 | { 211 | "cell_type": "code", 212 | "metadata": { 213 | "id": "iroeLPFdXbif", 214 | "colab_type": "code", 215 | "cellView": "form", 216 | "colab": {} 217 | }, 218 | "source": [ 219 | "#@markdown

Step 1. Upload your rclone.conf profile

\n", 220 | "#@markdown
*required to mount your drive!
\n", 221 | "#@markdown \n", 222 | "Setup_Time_Zone = False \n", 223 | "\n", 224 | "import os; from google.colab import files; from IPython.display import HTML, clear_output\n", 225 | "\n", 226 | "def upload_conf():\n", 227 | " try:\n", 228 | " display(HTML(\"

Please upload the config file of rclone (rclone.conf) from your computer.


\"))\n", 229 | " UploadConfig = files.upload().keys()\n", 230 | " clear_output(wait=True)\n", 231 | " if len(UploadConfig) == 0:\n", 232 | " return display(HTML(\"

File upload has been cancelled during upload file.


\"))\n", 233 | " elif len(UploadConfig) == 1:\n", 234 | " for fn in UploadConfig:\n", 235 | " if os.path.isfile(\"/content/\" + fn) == True:\n", 236 | " os.environ[\"rclone_conf\"] = fn\n", 237 | " !mv -f \"$rclone_conf\" /root/.rclone.conf\n", 238 | " !chmod 666 /root/.rclone.conf\n", 239 | " if Setup_Time_Zone == True:\n", 240 | " !sudo dpkg-reconfigure tzdata\n", 241 | " clear_output(wait=True)\n", 242 | " if os.path.isfile(\"/usr/bin/rclone\") == True:\n", 243 | " return display(HTML(\"

Config has been changed.


\"))\n", 244 | " else:\n", 245 | " !rm -rf /content/sample_data/\n", 246 | " !curl -s https://rclone.org/install.sh | sudo bash\n", 247 | " clear_output(wait=True)\n", 248 | " return display(HTML(\"

Installation has been successfully completed.


\"))\n", 249 | " else:\n", 250 | " return display(HTML(\"

File upload has been failed during upload file.


\"))\n", 251 | " else:\n", 252 | " for fn in UploadConfig:\n", 253 | " os.environ[\"rclone_conf\"] = fn\n", 254 | " !rm -f \"$rclone_conf\"\n", 255 | " return display(HTML(\"

Please uploading only one file at a time.


\"))\n", 256 | " except:\n", 257 | " clear_output(wait=True)\n", 258 | " return display(HTML(\"

Error occurred during upload file.


\"))\n", 259 | "\n", 260 | "upload_conf()" 261 | ], 262 | "execution_count": 0, 263 | "outputs": [] 264 | }, 265 | { 266 | "cell_type": "code", 267 | "metadata": { 268 | "id": "mp6XoynaX4HN", 269 | "colab_type": "code", 270 | "cellView": "form", 271 | "colab": {} 272 | }, 273 | "source": [ 274 | "# ============================= FORM ============================= #\n", 275 | "#@markdown

Step 2. Mount your Drive with rclone

\n", 276 | "#@markdown \n", 277 | "rclone_config_name = \"GDrive\" #@param {type:\"string\"}\n", 278 | "local_mount_location = \"/content/udrive/\" #@param {type:\"string\"}\n", 279 | "# ============================= FORM ============================= #\n", 280 | "import time\n", 281 | "import os\n", 282 | "\n", 283 | "# clear nohup\n", 284 | "open(\"nohup.out\", 'w').close()\n", 285 | "\n", 286 | "\n", 287 | "# unmount first\n", 288 | "\n", 289 | "!fusermount -u $local_mount_location 2>/dev/null\n", 290 | "\n", 291 | "\n", 292 | "# mount without waiting for the command to complete\n", 293 | "!mkdir $local_mount_location 2>/dev/null\n", 294 | "!nohup rclone mount $rclone_config_name: $local_mount_location --buffer-size 96M & \n", 295 | " \n", 296 | "\n", 297 | "\n", 298 | "# Show the output that was written to nohup\n", 299 | "time.sleep(3)\n", 300 | "f = open(r\"nohup.out\", \"r\")\n", 301 | "nohupText = f.read()\n", 302 | "f.close()\n", 303 | "\n", 304 | "\n", 305 | "dirs = os.listdir(local_mount_location)\n", 306 | "\n", 307 | "if len(dirs) > 0:\n", 308 | " clear_output(wait=True)\n", 309 | " print(\"Succeeded. \", str(len(dirs)), \"dirs found at\", local_mount_location)\n", 310 | "\n", 311 | "else:\n", 312 | " print(\"\\n\\nNot succeeded. No files or directories in mounted location. \\nCheck your config name and content. If the rclone command was not found, run the cell above.\\n\\n\")\n", 313 | " print(\"log:\\n\", nohupText)" 314 | ], 315 | "execution_count": 0, 316 | "outputs": [] 317 | }, 318 | { 319 | "cell_type": "markdown", 320 | "metadata": { 321 | "id": "ZVIyGBSmjlOY", 322 | "colab_type": "text" 323 | }, 324 | "source": [ 325 | "# **1**. Mounting Google Drive\n", 326 | "# \"GDrive\"/" 327 | ] 328 | }, 329 | { 330 | "cell_type": "code", 331 | "metadata": { 332 | "id": "6DzJx4rdjvUQ", 333 | "colab_type": "code", 334 | "cellView": "form", 335 | "colab": {} 336 | }, 337 | "source": [ 338 | "#@markdown

឵឵Click Here to Mount your Google Drive

\n", 339 | "#@markdown
(Provided by Google)
\n", 340 | "from google.colab import drive\n", 341 | "drive.mount('/content/drive')" 342 | ], 343 | "execution_count": 0, 344 | "outputs": [] 345 | }, 346 | { 347 | "cell_type": "code", 348 | "metadata": { 349 | "id": "IsQPA4qZD4hK", 350 | "colab_type": "code", 351 | "cellView": "form", 352 | "colab": {} 353 | }, 354 | "source": [ 355 | "#@markdown

឵឵Click Here to Force Remount your Google Drive

\n", 356 | "#@markdown
(Only use if needed)
\n", 357 | "drive.mount(\"/content/drive\", force_remount=True)" 358 | ], 359 | "execution_count": 0, 360 | "outputs": [] 361 | }, 362 | { 363 | "cell_type": "markdown", 364 | "metadata": { 365 | "id": "AAOkoLYa1nQb", 366 | "colab_type": "text" 367 | }, 368 | "source": [ 369 | "# **2**. qBitTorrent\n", 370 | "# \"qBitTorrent\"/\"+\"/\"ngrok\"/" 371 | ] 372 | }, 373 | { 374 | "cell_type": "markdown", 375 | "metadata": { 376 | "id": "smfdosUWghxD", 377 | "colab_type": "text" 378 | }, 379 | "source": [ 380 | "## **A**. \"ngrok\"/\n" 381 | ] 382 | }, 383 | { 384 | "cell_type": "markdown", 385 | "metadata": { 386 | "id": "0jctMTc3-rPt", 387 | "colab_type": "text" 388 | }, 389 | "source": [ 390 | "* You'll need your own ngrok Auth Token to use this cell. After logging in, you can find it [here](https://dashboard.ngrok.com/auth).\n", 391 | " * [Screenshot](https://yuju.pw/y/8Z3S.png) locating your ngrok Auth Token." 392 | ] 393 | }, 394 | { 395 | "cell_type": "code", 396 | "metadata": { 397 | "colab_type": "code", 398 | "cellView": "form", 399 | "id": "dmAyXqzfL9yK", 400 | "colab": {} 401 | }, 402 | "source": [ 403 | "#@title ← ឵឵ Run This Cell for ***qBitTorrent*** *v4.1.7 Web UI*\n", 404 | "Ngrok_Token = \"\" #@param {type:\"string\"}\n", 405 | "import os, time, urllib.request, json; from IPython.display import clear_output\n", 406 | "if os.path.isfile(\"/usr/bin/qbittorrent-nox\") == False:\n", 407 | " get_ipython().system_raw(\"apt update -qq -y && yes \"\" | add-apt-repository ppa:qbittorrent-team/qbittorrent-stable\")\n", 408 | " get_ipython().system_raw(\"apt install qbittorrent-nox\")\n", 409 | " get_ipython().system_raw(\"mkdir -p -m 666 /{content/qBittorrent,root/{.qBittorrent_temp,.config/qBittorrent}} && curl -s https://pastebin.com/raw/XbthBkJU -o /root/.config/qBittorrent/qBittorrent.conf\")\n", 410 | " print(\"qBittorrent successfully installed.\")\n", 411 | " clear_output(wait=True)\n", 412 | "else:\n", 413 | " print(\"qBittorrent already installed. Skipping...\")\n", 414 | " clear_output(wait=True)\n", 415 | " !pkill qbittorrent-nox\n", 416 | " \n", 417 | "!qbittorrent-nox -d --webui-port=4444\n", 418 | "print(\"qBittorrent started \")\n", 419 | "clear_output(wait=True)\n", 420 | "\n", 421 | "if os.path.isfile(\"/usr/local/bin/ngrok\") == False:\n", 422 | " !wget -q -c -nc https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip\n", 423 | " !unzip -qq -n ngrok-stable-linux-amd64.zip\n", 424 | " !mv ngrok /usr/local/bin/ngrok\n", 425 | " !rm -f /content/ngrok-stable-linux-amd64.zip\n", 426 | " print(\"ngrok successfully installed.\")\n", 427 | " clear_output(wait=True)\n", 428 | "else:\n", 429 | " print(\"ngrok already installed. Skipping... \")\n", 430 | " clear_output(wait=True)\n", 431 | " !pkill ngrok\n", 432 | " \n", 433 | "if os.path.isfile(\"/usr/bin/rclone\") == False:\n", 434 | " get_ipython().system_raw('curl https://rclone.org/install.sh | sudo bash &')\n", 435 | " print(\"Rclone successfully installed\")\n", 436 | " clear_output(wait=True)\n", 437 | "else:\n", 438 | " print(\"Rclone already installed. Skipping...\")\n", 439 | " clear_output(wait=True)\n", 440 | "\n", 441 | "get_ipython().system_raw('/usr/local/bin/ngrok authtoken $Ngrok_Token && /usr/local/bin/ngrok http 4444 &')\n", 442 | "print(\"Hold on...\")\n", 443 | "time.sleep(10)\n", 444 | "clear_output(wait=True)\n", 445 | "with urllib.request.urlopen('http://localhost:4040/api/tunnels') as response:\n", 446 | " data = json.loads(response.read().decode())\n", 447 | " host = data['tunnels'][0]['public_url'][8:]\n", 448 | " print(f'Open this link in new tab http://{host}')" 449 | ], 450 | "execution_count": 0, 451 | "outputs": [] 452 | }, 453 | { 454 | "cell_type": "markdown", 455 | "metadata": { 456 | "colab_type": "text", 457 | "id": "Nx9ud5luiyJY" 458 | }, 459 | "source": [ 460 | "## **B**. \"ngrok\"/\n", 461 | "#### (***Not Recommended***)\n" 462 | ] 463 | }, 464 | { 465 | "cell_type": "code", 466 | "metadata": { 467 | "id": "aO74zstqkSsh", 468 | "colab_type": "code", 469 | "cellView": "form", 470 | "colab": {} 471 | }, 472 | "source": [ 473 | "#@title ← ឵឵ Run This Cell for ***qBitTorrent*** *v4.1.7 Web UI* \n", 474 | "#@markdown
- Don't use the mounted Google Drive as a save path for torrent; data corruption will most likely occur.
\n", 475 | "Old_Version = False #@param {type:\"boolean\"}\n", 476 | "# ================================================================ #\n", 477 | "\n", 478 | "import os, psutil, IPython, uuid, time\n", 479 | "import ipywidgets as widgets\n", 480 | "\n", 481 | "from IPython.display import HTML, clear_output\n", 482 | "from google.colab import output\n", 483 | "\n", 484 | "class MakeButton(object):\n", 485 | " def __init__(self, title, callback):\n", 486 | " self._title = title\n", 487 | " self._callback = callback\n", 488 | " def _repr_html_(self):\n", 489 | " callback_id = 'button-' + str(uuid.uuid4())\n", 490 | " output.register_callback(callback_id, self._callback)\n", 491 | " template = \"\"\"\n", 492 | " \"\"\"\n", 498 | " html = template.format(title=self._title, callback_id=callback_id)\n", 499 | " return html\n", 500 | " \n", 501 | "def MakeLabel(description, button_style):\n", 502 | " return widgets.Button(description=description, disabled=True, button_style=button_style)\n", 503 | "\n", 504 | "def RandomGenerator():\n", 505 | " return time.strftime(\"%S\") + str(time.time()).split(\".\")[-1]\n", 506 | "\n", 507 | "def CheckProcess(process, command):\n", 508 | " for pid in psutil.pids():\n", 509 | " try:\n", 510 | " p = psutil.Process(pid)\n", 511 | " if process in p.name():\n", 512 | " for arg in p.cmdline():\n", 513 | " if command in str(arg): \n", 514 | " return True\n", 515 | " else:\n", 516 | " pass\n", 517 | " else:\n", 518 | " pass\n", 519 | " except:\n", 520 | " continue\n", 521 | " \n", 522 | "def AutoSSH(name,port):\n", 523 | " get_ipython().system_raw(\"autossh -l \" + name + \" -M 0 -fNT -o 'StrictHostKeyChecking=no' -o 'ServerAliveInterval 300' -o 'ServerAliveCountMax 30' -R 80:localhost:\" + port + \" ssh.localhost.run &\")\n", 524 | " get_ipython().system_raw(\"autossh -M 0 -fNT -o 'StrictHostKeyChecking=no' -o 'ServerAliveInterval 300' -o 'ServerAliveCountMax 30' -R \" + name + \":80:localhost:\" + port + \" serveo.net &\")\n", 525 | "\n", 526 | "def Start_Server():\n", 527 | " if CheckProcess(\"qbittorrent-nox\", \"\") != True:\n", 528 | " get_ipython().system_raw(\"qbittorrent-nox -d --webui-port=6006\")\n", 529 | " if CheckProcess(\"autossh\", \"qb\" + Random_Number) != True:\n", 530 | " AutoSSH(\"qb\" + Random_Number, \"6006\")\n", 531 | "\n", 532 | "try:\n", 533 | " try:\n", 534 | " Random_Number\n", 535 | " except NameError:\n", 536 | " display(MakeLabel(\"Installing in Progress\", \"warning\"))\n", 537 | " Random_Number = RandomGenerator()\n", 538 | " get_ipython().system_raw(\"rm -rf /content/sample_data/ &\")\n", 539 | " if os.path.isfile(\"/usr/bin/qbittorrent-nox\") == False:\n", 540 | " get_ipython().system_raw(\"apt update -qq -y && yes \"\" | add-apt-repository ppa:qbittorrent-team/qbittorrent-stable\")\n", 541 | " if Old_Version == True:\n", 542 | " get_ipython().system_raw(\"apt install qbittorrent-nox=4.0.3-1 -qq -y\")\n", 543 | " else:\n", 544 | " get_ipython().system_raw(\"apt install qbittorrent-nox -qq -y\")\n", 545 | " get_ipython().system_raw(\"mkdir -p -m 666 /{content/qBittorrent,root/{.qBittorrent_temp,.config/qBittorrent}} && wget -q https://minormole.github.io/RcloneLab/res/qbittorrent/qBittorrent.conf -O /root/.config/qBittorrent/qBittorrent.conf\")\n", 546 | " if os.path.isfile(\"/usr/bin/autossh\") == False:\n", 547 | " get_ipython().system_raw(\"apt install autossh -qq -y\")\n", 548 | " Start_Server()\n", 549 | " clear_output(wait=True)\n", 550 | " display(MakeLabel(\"✔ Successfully\", \"success\"), MakeButton(\"Recheck\", Start_Server), HTML(\"

qBittorrent

\" \\\n", 551 | " \"Website
\" \\\n", 552 | " \"Website (Backup)

\"))\n", 553 | "except:\n", 554 | " clear_output(wait=True)\n", 555 | " display(MakeLabel(\"✘ Unsuccessfully\", \"danger\"))" 556 | ], 557 | "execution_count": 0, 558 | "outputs": [] 559 | }, 560 | { 561 | "cell_type": "markdown", 562 | "metadata": { 563 | "id": "8YFON0D4mVdr", 564 | "colab_type": "text" 565 | }, 566 | "source": [ 567 | "# **3**. JDownloader\n", 568 | "# \"JDownloader\"/" 569 | ] 570 | }, 571 | { 572 | "cell_type": "code", 573 | "metadata": { 574 | "id": "eyTydVIrm2Ms", 575 | "colab_type": "code", 576 | "cellView": "form", 577 | "colab": {} 578 | }, 579 | "source": [ 580 | "#@markdown ← ឵឵ Click Here to Install JDownloader\n", 581 | "\n", 582 | "import os, uuid, re, IPython\n", 583 | "import ipywidgets as widgets\n", 584 | "\n", 585 | "from glob import glob\n", 586 | "from IPython.display import HTML, clear_output\n", 587 | "from google.colab import output\n", 588 | "\n", 589 | "Email = widgets.Text(placeholder=\"*Required\", description=\"Email:\")\n", 590 | "Password = widgets.Text(placeholder=\"*Required\", description=\"Password:\")\n", 591 | "Device = widgets.Text(placeholder=\"Optional\", description=\"Name:\")\n", 592 | "SavePath = widgets.Dropdown(value=\"/content\", options=[\"/content\", \"/content/Downloads\"], description=\"Save Path:\")\n", 593 | "\n", 594 | "class MakeButton(object):\n", 595 | " def __init__(self, title, callback, style):\n", 596 | " self._title = title\n", 597 | " self._callback = callback\n", 598 | " self._style = style\n", 599 | " def _repr_html_(self):\n", 600 | " callback_id = 'button-' + str(uuid.uuid4())\n", 601 | " output.register_callback(callback_id, self._callback)\n", 602 | " if self._style != \"\":\n", 603 | " style_html = \"p-Widget jupyter-widgets jupyter-button widget-button mod-\" + self._style\n", 604 | " else:\n", 605 | " style_html = \"p-Widget jupyter-widgets jupyter-button widget-button\"\n", 606 | " template = \"\"\"\n", 607 | " \"\"\"\n", 613 | " html = template.format(title=self._title, callback_id=callback_id, style_html=style_html)\n", 614 | " return html\n", 615 | " \n", 616 | "def MakeLabel(description, button_style):\n", 617 | " return widgets.Button(description=description, disabled=True, button_style=button_style)\n", 618 | "\n", 619 | "def RefreshPath():\n", 620 | " if os.path.exists(\"/content/drive/\"):\n", 621 | " if os.path.exists(\"/content/drive/Shared drives/\"):\n", 622 | " SavePath.options = [\"/content\", \"/content/Downloads\", \"/content/drive/My Drive\"] + glob(\"/content/drive/Shared drives/*\")\n", 623 | " else:\n", 624 | " SavePath.options = [\"/content\", \"/content/Downloads\", \"/content/drive/My Drive\"]\n", 625 | " else:\n", 626 | " SavePath.options = [\"/content\", \"/content/Downloads\"]\n", 627 | "\n", 628 | "def LoginForm():\n", 629 | " clear_output()\n", 630 | " Email.value = \"\"\n", 631 | " Password.value = \"\"\n", 632 | " Device.value = \"\"\n", 633 | " RefreshPath()\n", 634 | " display(HTML(\"

If you don't have an account yet, please register here.

\"), HTML(\"
\"), Email, Password, Device, SavePath)\n", 635 | " if not os.path.exists(\"/content/drive/\"):\n", 636 | " display(HTML(\"*If you want to save in Google Drive please run the cell below.\"))\n", 637 | " display(HTML(\"
\"), MakeButton(\"Login\", CheckLogin, \"info\"))\n", 638 | " if os.path.isfile(\"/root/.JDownloader/cfg/org.jdownloader.api.myjdownloader.MyJDownloaderSettings.json\"):\n", 639 | " display(MakeButton(\"Cancel\", Show, \"danger\"))\n", 640 | " \n", 641 | "def RestartForm():\n", 642 | " clear_output()\n", 643 | " display(MakeLabel(\"Restart Confirm?\", \"\"), MakeButton(\"Confirm\", Restart, \"danger\"), MakeButton(\"Cancel\", Show, \"warning\"))\n", 644 | " \n", 645 | "def ExitForm():\n", 646 | " clear_output()\n", 647 | " display(MakeLabel(\"Exit Confirm?\", \"\"), MakeButton(\"Confirm\", Exit, \"danger\"), MakeButton(\"Cancel\", Show, \"warning\"))\n", 648 | "\n", 649 | "def CheckLogin():\n", 650 | " try:\n", 651 | " if not Email.value.strip():\n", 652 | " ERROR = \"Email field is empty.\"\n", 653 | " THROW_ERROR\n", 654 | " if not \"@\" in Email.value and not \".\" in Email.value:\n", 655 | " ERROR = \"Email is an incorrect format.\"\n", 656 | " THROW_ERROR\n", 657 | " if not Password.value.strip():\n", 658 | " ERROR = \"Password field is empty.\"\n", 659 | " THROW_ERROR\n", 660 | " if not bool(re.match(\"^[a-zA-Z0-9]+$\", Device.value)) and Device.value.strip():\n", 661 | " ERROR = \"Only alphanumeric are allowed for the device name.\"\n", 662 | " THROW_ERROR\n", 663 | " Login()\n", 664 | " except:\n", 665 | " print(ERROR)\n", 666 | "\n", 667 | "def Login():\n", 668 | " clear_output()\n", 669 | " if SavePath.value == \"/content\":\n", 670 | " get_ipython().system_raw(\"echo '{\\\"defaultdownloadfolder\\\" : \\\"/content\\\"}' > /root/.JDownloader/cfg/org.jdownloader.settings.GeneralSettings.json\")\n", 671 | " elif SavePath.value == \"/content/Downloads\":\n", 672 | " get_ipython().system_raw(\"mkdir -p -m 666 /content/Downloads\")\n", 673 | " get_ipython().system_raw(\"echo '{\\\"defaultdownloadfolder\\\" : \\\"/content/Downloads\\\"}' > /root/.JDownloader/cfg/org.jdownloader.settings.GeneralSettings.json\")\n", 674 | " else:\n", 675 | " get_ipython().system_raw(\"echo '{\\\"defaultdownloadfolder\\\" : \\\"\" + SavePath.value + \"\\\"}' > /root/.JDownloader/cfg/org.jdownloader.settings.GeneralSettings.json\")\n", 676 | " if Device.value.strip() == \"\":\n", 677 | " Device.value = Email.value\n", 678 | " get_ipython().system_raw(\"pkill -9 -e -f java\")\n", 679 | " get_ipython().system_raw(\"echo '{\\\"email\\\" : \\\"'\" + Email.value + \"'\\\", \\\"password\\\" : \\\"'\" + Password.value + \"'\\\", \\\"devicename\\\" : \\\"'\" + Device.value + \"'\\\", \\\"directconnectmode\\\" : \\\"LAN\\\"}' > /root/.JDownloader/cfg/org.jdownloader.api.myjdownloader.MyJDownloaderSettings.json\")\n", 680 | " get_ipython().system_raw(\"java -jar /root/.JDownloader/JDownloader.jar -norestart -noerr -r &\")\n", 681 | " Show()\n", 682 | "\n", 683 | "def Restart():\n", 684 | " get_ipython().system_raw(\"pkill -9 -e -f java\")\n", 685 | " get_ipython().system_raw(\"java -jar /root/.JDownloader/JDownloader.jar -norestart -noerr -r &\")\n", 686 | " Show()\n", 687 | " \n", 688 | "def Exit():\n", 689 | " get_ipython().system_raw(\"pkill -9 -e -f java\")\n", 690 | " clear_output()\n", 691 | " display(MakeButton(\"Start\", Restart, \"info\"))\n", 692 | " \n", 693 | "def Show():\n", 694 | " clear_output()\n", 695 | " display(MakeLabel(\"Control Panel\", \"\"), HTML(\"

You can login to the WebUI by clicking here.

\"), HTML(\"

If the server didn't showup in 30 sec. please re-login.

\"), HTML(\"
\"), MakeButton(\"Re-Login\", LoginForm, \"info\"), MakeButton(\"Restart\", RestartForm, \"warning\"), MakeButton(\"Exit\", ExitForm, \"danger\"))\n", 696 | " \n", 697 | " \n", 698 | "if not os.path.isfile(\"/root/.JDownloader/JDownloader.jar\"):\n", 699 | " clear_output()\n", 700 | " display(MakeLabel(\"Installing in Progress\", \"warning\"))\n", 701 | " get_ipython().system_raw(\"rm -rf /content/sample_data/ && apt install openjdk-8-jre-headless -qq -y && mkdir -p -m 666 /root/.JDownloader && wget -q http://installer.jdownloader.org/JDownloader.jar -O /root/.JDownloader/JDownloader.jar && java -jar /root/.JDownloader/JDownloader.jar -norestart -h\")\n", 702 | " LoginForm()\n", 703 | "elif not os.path.isfile(\"/root/.JDownloader/cfg/org.jdownloader.api.myjdownloader.MyJDownloaderSettings.json\"):\n", 704 | " LoginForm()\n", 705 | "else: \n", 706 | " Show()" 707 | ], 708 | "execution_count": 0, 709 | "outputs": [] 710 | }, 711 | { 712 | "cell_type": "markdown", 713 | "metadata": { 714 | "id": "StT2bKf2WmKj", 715 | "colab_type": "text" 716 | }, 717 | "source": [ 718 | "# **4**. wget\n", 719 | "# \"qBitTorrent\"/\n" 720 | ] 721 | }, 722 | { 723 | "cell_type": "code", 724 | "metadata": { 725 | "id": "_NiTOoCg-hLp", 726 | "colab_type": "code", 727 | "cellView": "form", 728 | "colab": {} 729 | }, 730 | "source": [ 731 | "#@title

Run to Download a DDL File\n", 732 | "#@markdown

Example URL: https://files.catbox.moe/archive.zip\n", 733 | "direct_URL = \"\" #@param {type:\"string\"}\n", 734 | "output_dir = \"/content\" #@param {type:\"string\"}\n", 735 | "\n", 736 | "!wget \"$Direct_URL\" \"$output_dir\"" 737 | ], 738 | "execution_count": 0, 739 | "outputs": [] 740 | }, 741 | { 742 | "cell_type": "markdown", 743 | "metadata": { 744 | "id": "mtIWnZ60Sczn", 745 | "colab_type": "text" 746 | }, 747 | "source": [ 748 | "# **5**. folderclone\n", 749 | "\n", 750 | "# \"qBitTorrent\"/\n", 751 | "\n" 752 | ] 753 | }, 754 | { 755 | "cell_type": "markdown", 756 | "metadata": { 757 | "id": "jWNiE-RGECHM", 758 | "colab_type": "text" 759 | }, 760 | "source": [ 761 | "### **Step 1.** Installing Required modules" 762 | ] 763 | }, 764 | { 765 | "cell_type": "code", 766 | "metadata": { 767 | "id": "12dTZfUQEN8b", 768 | "colab_type": "code", 769 | "cellView": "form", 770 | "colab": {} 771 | }, 772 | "source": [ 773 | "#@markdown

Run this cell to install all required modules

\n", 774 | "!pip3 install folderclone" 775 | ], 776 | "execution_count": 0, 777 | "outputs": [] 778 | }, 779 | { 780 | "cell_type": "markdown", 781 | "metadata": { 782 | "id": "MbJ_88vSD-K2", 783 | "colab_type": "text" 784 | }, 785 | "source": [ 786 | "### **Step 2.** Pulling your repo from GitHub\n", 787 | "- *Remove* \"https://\" *from Repo link*" 788 | ] 789 | }, 790 | { 791 | "cell_type": "code", 792 | "metadata": { 793 | "id": "h5kQ5bxsDNiX", 794 | "colab_type": "code", 795 | "cellView": "form", 796 | "colab": {} 797 | }, 798 | "source": [ 799 | "#@markdown

Click here download your private repo

\n", 800 | "import os\n", 801 | "username = \"\" #@param {type:\"string\"}\n", 802 | "Password = \"\"#@param {type:\"string\"}\n", 803 | "Repolink = \"github.com/Sarah/MFCBPDEMO\"#@param {type:\"string\"}\n", 804 | "!git clone https://\"$username\":\"$Password\"@\"$Repolink\".git" 805 | ], 806 | "execution_count": 0, 807 | "outputs": [] 808 | }, 809 | { 810 | "cell_type": "markdown", 811 | "metadata": { 812 | "id": "yTPpo294F0U8", 813 | "colab_type": "text" 814 | }, 815 | "source": [ 816 | "### **Step 3.** Adding All SAs to Google Group" 817 | ] 818 | }, 819 | { 820 | "cell_type": "markdown", 821 | "metadata": { 822 | "id": "m2b0lgo8Pc8C", 823 | "colab_type": "text" 824 | }, 825 | "source": [ 826 | "- Add your service accounts emails to one collective Google Group (limit 100 per day)\n", 827 | "- Share your `@googlegroups.com` email with the Source TD, and the Destination TD\n", 828 | "\n", 829 | "

Important:

\n", 830 | "
✧ ឵After completing this step, you can skip it in the future!" 831 | ] 832 | }, 833 | { 834 | "cell_type": "markdown", 835 | "metadata": { 836 | "id": "n3MWoStHEnJx", 837 | "colab_type": "text" 838 | }, 839 | "source": [ 840 | "### **Step 4.** Running folderclone\n" 841 | ] 842 | }, 843 | { 844 | "cell_type": "code", 845 | "metadata": { 846 | "colab_type": "code", 847 | "cellView": "form", 848 | "id": "nLyWJmQXO4vr", 849 | "colab": {} 850 | }, 851 | "source": [ 852 | "#@title

Run to clone all folders + files from src to dest\n", 853 | "#@markdown Paste only the Folder IDs for these values:\n", 854 | "src = \"\" #@param {type:\"string\"}\n", 855 | "dest = \"\" #@param {type:\"string\"}\n", 856 | "accountspath = \"/content/folderclone/accounts\"#@param {type:\"string\"}\n", 857 | "!multifolderclone -s \"$src\" -d \"$dest\" --path \"$accountspath\"" 858 | ], 859 | "execution_count": 0, 860 | "outputs": [] 861 | }, 862 | { 863 | "cell_type": "markdown", 864 | "metadata": { 865 | "id": "505daA1YPSdW", 866 | "colab_type": "text" 867 | }, 868 | "source": [ 869 | "- Add the Source Folder ID and then the Destination Folder ID\n", 870 | "- Note: ***Your source*** *(*`src`*)* ***folder must be publically accessible***\n", 871 | "\n", 872 | "##### Folder IDs are found at the end of the URL:\n", 873 | "![](https://yuju.pw/y/qNvy.png)" 874 | ] 875 | }, 876 | { 877 | "cell_type": "markdown", 878 | "metadata": { 879 | "id": "DYreGU9NvCdk", 880 | "colab_type": "text" 881 | }, 882 | "source": [ 883 | "## ***Extra***" 884 | ] 885 | }, 886 | { 887 | "cell_type": "markdown", 888 | "metadata": { 889 | "id": "t0eVljW0O0CG", 890 | "colab_type": "text" 891 | }, 892 | "source": [ 893 | "### **Bonus 1:** Deleting a Directory *(if needed, just in case)*\n", 894 | "#### ✧ Note: This is ***not required***" 895 | ] 896 | }, 897 | { 898 | "cell_type": "code", 899 | "metadata": { 900 | "id": "LgG4fBSgO9Ev", 901 | "colab_type": "code", 902 | "cellView": "form", 903 | "colab": {} 904 | }, 905 | "source": [ 906 | "#@title

Run This Cell to Delete a Directory\n", 907 | "import os, shutil\n", 908 | "path = \"\" #@param {type:\"string\"}\n", 909 | "shutil.rmtree(path)\n", 910 | "print(\"Successfully deleted 👍\")" 911 | ], 912 | "execution_count": 0, 913 | "outputs": [] 914 | }, 915 | { 916 | "cell_type": "markdown", 917 | "metadata": { 918 | "id": "ukxnQC4c0nuR", 919 | "colab_type": "text" 920 | }, 921 | "source": [ 922 | "# **6.** FFmpeg\n", 923 | "# \"RcloneLab\"/" 924 | ] 925 | }, 926 | { 927 | "cell_type": "markdown", 928 | "metadata": { 929 | "id": "EFOqhHG6hOVH", 930 | "colab_type": "text" 931 | }, 932 | "source": [ 933 | "## ***Required to use Scripts:*** Install FFmpeg" 934 | ] 935 | }, 936 | { 937 | "cell_type": "code", 938 | "metadata": { 939 | "id": "hFeE-qPuhTiK", 940 | "colab_type": "code", 941 | "colab": {} 942 | }, 943 | "source": [ 944 | "!apt install ffmpeg" 945 | ], 946 | "execution_count": 0, 947 | "outputs": [] 948 | }, 949 | { 950 | "cell_type": "markdown", 951 | "metadata": { 952 | "id": "KgNPvGccgwd8", 953 | "colab_type": "text" 954 | }, 955 | "source": [ 956 | "## FFmpeg Scripts *(Convert, Edit, Trim + more)*" 957 | ] 958 | }, 959 | { 960 | "cell_type": "markdown", 961 | "metadata": { 962 | "id": "RDHuIkoi6l9a", 963 | "colab_type": "text" 964 | }, 965 | "source": [ 966 | "###» Display Media File Codecs + Metadata" 967 | ] 968 | }, 969 | { 970 | "cell_type": "markdown", 971 | "metadata": { 972 | "id": "X4yIG_nqYAoH", 973 | "colab_type": "text" 974 | }, 975 | "source": [ 976 | "> *You can ignore the \"At least one output file must be specified\" error after running this.*\n" 977 | ] 978 | }, 979 | { 980 | "cell_type": "code", 981 | "metadata": { 982 | "id": "Sv8au_RO6WUs", 983 | "colab_type": "code", 984 | "cellView": "form", 985 | "colab": {} 986 | }, 987 | "source": [ 988 | "import os, sys, re\n", 989 | "\n", 990 | "media_file_path = \"\" #@param {type:\"string\"}\n", 991 | "\n", 992 | "os.environ['inputFile'] = media_file_path\n", 993 | "\n", 994 | "!ffmpeg -i \"$inputFile\" -hide_banner" 995 | ], 996 | "execution_count": 0, 997 | "outputs": [] 998 | }, 999 | { 1000 | "cell_type": "markdown", 1001 | "metadata": { 1002 | "id": "NQ0TxfKeghR8", 1003 | "colab_type": "text" 1004 | }, 1005 | "source": [ 1006 | "###» Convert *.mkv* ➔ *.mp4* (Lossless)" 1007 | ] 1008 | }, 1009 | { 1010 | "cell_type": "code", 1011 | "metadata": { 1012 | "id": "Ls4O5VLwief-", 1013 | "colab_type": "code", 1014 | "cellView": "form", 1015 | "colab": {} 1016 | }, 1017 | "source": [ 1018 | "import os, sys, re\n", 1019 | "\n", 1020 | "video_file_path = \"\" #@param {type:\"string\"}\n", 1021 | "\n", 1022 | "output_file_path = re.search(\"^[\\/].+\\/\", video_file_path)\n", 1023 | "output_file_path_raw = output_file_path.group(0)\n", 1024 | "delsplit = re.search(\"\\/(?:.(?!\\/))+$\", video_file_path)\n", 1025 | "filename = re.sub(\"^[\\/]\", \"\", delsplit.group(0))\n", 1026 | "filename_raw = re.sub(\".{4}$\", \"\", filename)\n", 1027 | "\n", 1028 | "os.environ['inputFile'] = video_file_path\n", 1029 | "os.environ['outputFile'] = filename_raw\n", 1030 | "os.environ['outputPath'] = output_file_path_raw\n", 1031 | "\n", 1032 | "!ffmpeg -hide_banner -i \"$inputFile\" -c copy -strict experimental \"$outputPath\"\"$outputFile\".mp4" 1033 | ], 1034 | "execution_count": 0, 1035 | "outputs": [] 1036 | }, 1037 | { 1038 | "cell_type": "markdown", 1039 | "metadata": { 1040 | "id": "FpJXJiRl6-gK", 1041 | "colab_type": "text" 1042 | }, 1043 | "source": [ 1044 | "###» Trim Video File (Lossless)" 1045 | ] 1046 | }, 1047 | { 1048 | "cell_type": "code", 1049 | "metadata": { 1050 | "id": "iFBUeQhn7QTc", 1051 | "colab_type": "code", 1052 | "cellView": "form", 1053 | "colab": {} 1054 | }, 1055 | "source": [ 1056 | "import os, sys, re\n", 1057 | "\n", 1058 | "video_file_path = \"\" #@param {type:\"string\"}\n", 1059 | "start_time = \"00:00:00.000\" #@param {type:\"string\"}\n", 1060 | "end_time = \"00:01:00.000\" #@param {type:\"string\"}\n", 1061 | "\n", 1062 | "output_file_path = re.search(\"^[\\/].+\\/\", video_file_path)\n", 1063 | "output_file_path_raw = output_file_path.group(0)\n", 1064 | "delsplit = re.search(\"\\/(?:.(?!\\/))+$\", video_file_path)\n", 1065 | "filename = re.sub(\"^[\\/]\", \"\", delsplit.group(0))\n", 1066 | "filename_raw = re.sub(\".{4}$\", \"\", filename)\n", 1067 | "file_extension = re.search(\".{3}$\", filename)\n", 1068 | "file_extension_raw = file_extension.group(0)\n", 1069 | "\n", 1070 | "os.environ['inputFile'] = video_file_path\n", 1071 | "os.environ['outputPath'] = output_file_path_raw\n", 1072 | "os.environ['startTime'] = start_time\n", 1073 | "os.environ['endTime'] = end_time\n", 1074 | "os.environ['fileName'] = filename_raw\n", 1075 | "os.environ['fileExtension'] = file_extension_raw\n", 1076 | "\n", 1077 | "!ffmpeg -hide_banner -i \"$inputFile\" -ss \"$startTime\" -to \"$endTime\" -c copy \"$outputPath\"/\"$fileName\"-TRIM.\"$fileExtension\"" 1078 | ], 1079 | "execution_count": 0, 1080 | "outputs": [] 1081 | }, 1082 | { 1083 | "cell_type": "markdown", 1084 | "metadata": { 1085 | "colab_type": "text", 1086 | "id": "2f-THZmDoOaY" 1087 | }, 1088 | "source": [ 1089 | "###» Extract Audio from Video File (Lossless)" 1090 | ] 1091 | }, 1092 | { 1093 | "cell_type": "code", 1094 | "metadata": { 1095 | "id": "nSeO98YQoTJe", 1096 | "colab_type": "code", 1097 | "cellView": "form", 1098 | "colab": {} 1099 | }, 1100 | "source": [ 1101 | "import os, sys, re\n", 1102 | "\n", 1103 | "video_file_path = \"\" #@param {type:\"string\"}\n", 1104 | "output_file_extension = 'm4a' #@param [\"m4a\", \"mp3\", \"opus\", \"flac\", \"wav\"]\n", 1105 | "\n", 1106 | "delsplit = re.search(\"\\/(?:.(?!\\/))+$\", video_file_path)\n", 1107 | "output_file_path = re.search(\"^[\\/].+\\/\", video_file_path)\n", 1108 | "filename = re.sub(\"^[\\/]\", \"\", delsplit.group(0))\n", 1109 | "filename_raw = re.sub(\".{4}$\", \"\", filename)\n", 1110 | "\n", 1111 | "os.environ['inputFile'] = video_file_path\n", 1112 | "os.environ['outputPath'] = output_file_path.group(0)\n", 1113 | "os.environ['fileName'] = filename_raw\n", 1114 | "os.environ['fileType'] = output_file_extension\n", 1115 | "\n", 1116 | "!ffmpeg -hide_banner -i \"$inputFile\" -vn -c:a copy \"$outputPath\"/\"$fileName\"-audio.\"$fileType\"" 1117 | ], 1118 | "execution_count": 0, 1119 | "outputs": [] 1120 | }, 1121 | { 1122 | "cell_type": "markdown", 1123 | "metadata": { 1124 | "id": "MSUasbRUDP3B", 1125 | "colab_type": "text" 1126 | }, 1127 | "source": [ 1128 | "###» Re-encode a Video to a Different Resolution" 1129 | ] 1130 | }, 1131 | { 1132 | "cell_type": "code", 1133 | "metadata": { 1134 | "id": "nd2LvSRZCxRe", 1135 | "colab_type": "code", 1136 | "cellView": "form", 1137 | "colab": {} 1138 | }, 1139 | "source": [ 1140 | "import os, sys, re\n", 1141 | "\n", 1142 | "video_file_path = '' #@param {type:\"string\"}\n", 1143 | "resolution = '1080p' #@param [\"1080p\", \"720p\", \"480p\", \"360p\", \"240p\"]\n", 1144 | "file_type = 'mp4' #@param [\"mkv\", \"mp4\"]\n", 1145 | "\n", 1146 | "delsplit = re.search(\"\\/(?:.(?!\\/))+$\", video_file_path)\n", 1147 | "testsplit = video_file_path.split(\"/\")\n", 1148 | "filename = re.sub(\"^[\\/]\", \"\", delsplit.group(0))\n", 1149 | "filename_raw = re.sub(\".{4}$\", \"\", filename)\n", 1150 | "resolution_raw = re.search(\"[^p]{3,4}\", resolution)\n", 1151 | "output_file_path = re.search(\"^[\\/].+\\/\", video_file_path)\n", 1152 | "\n", 1153 | "os.environ['inputFile'] = video_file_path\n", 1154 | "os.environ['outputPath'] = output_file_path.group(0)\n", 1155 | "os.environ['fileName'] = filename_raw\n", 1156 | "os.environ['fileType'] = file_type\n", 1157 | "os.environ['resolutionHeight'] = resolution_raw.group(0)\n", 1158 | "\n", 1159 | "!ffmpeg -hide_banner -i \"$inputFile\" -vf \"scale=-1:\"$resolutionHeight\"\" -c:a copy -strict experimental \"$outputPath\"/\"$fileName\"-\"$resolutionHeight\"p.\"$fileType\"" 1160 | ], 1161 | "execution_count": 0, 1162 | "outputs": [] 1163 | }, 1164 | { 1165 | "cell_type": "markdown", 1166 | "metadata": { 1167 | "id": "0xI8WiUPji3k", 1168 | "colab_type": "text" 1169 | }, 1170 | "source": [ 1171 | "# **7.** SSH Access\n", 1172 | "# \"RcloneLab\"/\n" 1173 | ] 1174 | }, 1175 | { 1176 | "cell_type": "code", 1177 | "metadata": { 1178 | "id": "fsceu1YCkoes", 1179 | "colab_type": "code", 1180 | "cellView": "form", 1181 | "colab": {} 1182 | }, 1183 | "source": [ 1184 | "#@markdown

Run to enable SSH acccess\n", 1185 | "#@markdown

This will ask for your ngrok token from: https://dashboard.ngrok.com/auth
\n", 1186 | "#Generate root password\n", 1187 | "import random, string\n", 1188 | "password = ''.join(random.choice(string.ascii_letters + string.digits) for i in range(20))\n", 1189 | "#Download ngrok\n", 1190 | "! wget -q -c -nc https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip\n", 1191 | "! unzip -qq -n ngrok-stable-linux-amd64.zip\n", 1192 | "#Setup sshd\n", 1193 | "! apt-get install -qq -o=Dpkg::Use-Pty=0 openssh-server pwgen > /dev/null\n", 1194 | "#Set root password\n", 1195 | "! echo root:$password | chpasswd\n", 1196 | "! mkdir -p /var/run/sshd\n", 1197 | "! echo \"PermitRootLogin yes\" >> /etc/ssh/sshd_config\n", 1198 | "! echo \"PasswordAuthentication yes\" >> /etc/ssh/sshd_config\n", 1199 | "! echo \"LD_LIBRARY_PATH=/usr/lib64-nvidia\" >> /root/.bashrc\n", 1200 | "! echo \"export LD_LIBRARY_PATH\" >> /root/.bashrc\n", 1201 | "#Run sshd\n", 1202 | "get_ipython().system_raw('/usr/sbin/sshd -D &')\n", 1203 | "#Ask token\n", 1204 | "print(\"Copy authtoken from https://dashboard.ngrok.com/auth\")\n", 1205 | "import getpass\n", 1206 | "authtoken = getpass.getpass()\n", 1207 | "#Create tunnel\n", 1208 | "get_ipython().system_raw('./ngrok authtoken $authtoken && ./ngrok tcp 22 &')\n", 1209 | "#Print root password\n", 1210 | "print(\"Root password: {}\".format(password))\n", 1211 | "#Get public address\n", 1212 | "! curl -s http://localhost:4040/api/tunnels | python3 -c \\\n", 1213 | "\"import sys, json; print(json.load(sys.stdin)['tunnels'][0]['public_url'])\"" 1214 | ], 1215 | "execution_count": 0, 1216 | "outputs": [] 1217 | }, 1218 | { 1219 | "cell_type": "markdown", 1220 | "metadata": { 1221 | "id": "Nl4RbJbX0-a4", 1222 | "colab_type": "text" 1223 | }, 1224 | "source": [ 1225 | "# **8.** youtube-dl\n", 1226 | "# \"RcloneLab\"/" 1227 | ] 1228 | }, 1229 | { 1230 | "cell_type": "code", 1231 | "metadata": { 1232 | "id": "dCK-puiMnHYj", 1233 | "colab_type": "code", 1234 | "cellView": "form", 1235 | "colab": {} 1236 | }, 1237 | "source": [ 1238 | "#@markdown

Click Here to use youtube-dl

\n", 1239 | "\n", 1240 | "import os, uuid, urllib.parse\n", 1241 | "import ipywidgets as widgets\n", 1242 | "Archive = False\n", 1243 | "\n", 1244 | "from glob import glob\n", 1245 | "from urllib.parse import urlparse, parse_qs\n", 1246 | "from IPython.display import HTML, clear_output, YouTubeVideo\n", 1247 | "from IPython.utils.io import ask_yes_no\n", 1248 | "from google.colab import output, files\n", 1249 | "\n", 1250 | "Links = widgets.Textarea(placeholder='''Video/Playlist Link\n", 1251 | "(one link per line)''')\n", 1252 | "\n", 1253 | "VideoQ = widgets.Dropdown(options=[\"Best Quality (VP9 upto 4K)\", \"Best Compatibility (H.264 upto 1080p)\"])\n", 1254 | "\n", 1255 | "AudioQ = widgets.Dropdown(options=[\"Best Quality (Opus)\", \"Best Compatibility (M4A)\"])\n", 1256 | "\n", 1257 | "Subtitle = widgets.ToggleButton(value=True, description=\"Subtitle\", button_style=\"info\", tooltip=\"Subtitle\")\n", 1258 | "\n", 1259 | "SavePathYT = widgets.Dropdown(options=[\"/content\", \"/content/Downloads\"])\n", 1260 | "\n", 1261 | "AudioOnly = widgets.ToggleButton(value=False, description=\"Audio Only\", button_style=\"\", tooltip=\"Audio Only\")\n", 1262 | "\n", 1263 | "Resolution = widgets.Select(options=[\"Highest\", \"4K\", \"1440p\", \"1080p\", \"720p\", \"480p\", \"360p\", \"240p\", \"144p\"], value=\"Highest\")\n", 1264 | "\n", 1265 | "Extension = widgets.Select(options=[\"mkv\", \"webm\"], value=\"mkv\")\n", 1266 | "\n", 1267 | "UsernameYT = widgets.Text(placeholder=\"Username\")\n", 1268 | "\n", 1269 | "PasswordYT = widgets.Text(placeholder=\"Password\")\n", 1270 | "\n", 1271 | "SecAuth = widgets.Text(placeholder=\"2nd Factor Authentication\")\n", 1272 | "\n", 1273 | "VideoPW = widgets.Text(placeholder=\"Video Password\")\n", 1274 | "\n", 1275 | "GEOBypass = widgets.Dropdown(options=[\"Disable\", \"Hide\", \"AD\", \"AE\", \"AF\", \"AG\", \"AI\", \"AL\", \"AM\", \"AO\", \"AQ\", \"AR\", \"AS\", \"AT\", \"AU\", \"AW\", \"AX\", \"AZ\", \"BA\", \"BB\", \"BD\", \"BE\", \"BF\", \"BG\", \"BH\", \"BI\", \"BJ\", \"BL\", \"BM\", \"BN\", \"BO\", \"BQ\", \"BR\", \"BS\", \"BT\", \"BV\", \"BW\", \"BY\", \"BZ\", \"CA\", \"CC\", \"CD\", \"CF\", \"CG\", \"CH\", \"CI\", \"CK\", \"CL\", \"CM\", \"CN\", \"CO\", \"CR\", \"CU\", \"CV\", \"CW\", \"CX\", \"CY\", \"CZ\", \"DE\", \"DJ\", \"DK\", \"DM\", \"DO\", \"DZ\", \"EC\", \"EE\", \"EG\", \"EH\", \"ER\", \"ES\", \"ET\", \"FI\", \"FJ\", \"FK\", \"FM\", \"FO\", \"FR\", \"GA\", \"GB\", \"GD\", \"GE\", \"GF\", \"GG\", \"GH\", \"GI\", \"GL\", \"GM\", \"GN\", \"GP\", \"GQ\", \"GR\", \"GS\", \"GT\", \"GU\", \"GW\", \"GY\", \"HK\", \"HM\", \"HN\", \"HR\", \"HT\", \"HU\", \"ID\", \"IE\", \"IL\", \"IM\", \"IN\", \"IO\", \"IQ\", \"IR\", \"IS\", \"IT\", \"JE\", \"JM\", \"JO\", \"JP\", \"KE\", \"KG\", \"KH\", \"KI\", \"KM\", \"KN\", \"KP\", \"KR\", \"KW\", \"KY\", \"KZ\", \"LA\", \"LB\", \"LC\", \"LI\", \"LK\", \"LR\", \"LS\", \"LT\", \"LU\", \"LV\", \"LY\", \"MA\", \"MC\", \"MD\", \"ME\", \"MF\", \"MG\", \"MH\", \"MK\", \"ML\", \"MM\", \"MN\", \"MO\", \"MP\", \"MQ\", \"MR\", \"MS\", \"MT\", \"MU\", \"MV\", \"MW\", \"MX\", \"MY\", \"MZ\", \"NA\", \"NC\", \"NE\", \"NF\", \"NG\", \"NI\", \"NL\", \"NO\", \"NP\", \"NR\", \"NU\", \"NZ\", \"OM\", \"PA\", \"PE\", \"PF\", \"PG\", \"PH\", \"PK\", \"PL\", \"PM\", \"PN\", \"PR\", \"PS\", \"PT\", \"PW\", \"PY\", \"QA\", \"RE\", \"RO\", \"RS\", \"RU\", \"RW\", \"SA\", \"SB\", \"SC\", \"SD\", \"SE\", \"SG\", \"SH\", \"SI\", \"SJ\", \"SK\", \"SL\", \"SM\", \"SN\", \"SO\", \"SR\", \"SS\", \"ST\", \"SV\", \"SX\", \"SY\", \"SZ\", \"TC\", \"TD\", \"TF\", \"TG\", \"TH\", \"TJ\", \"TK\", \"TL\", \"TM\", \"TN\", \"TO\", \"TR\", \"TT\", \"TV\", \"TW\", \"TZ\", \"UA\", \"UG\", \"UM\", \"US\", \"UY\", \"UZ\", \"VA\", \"VC\", \"VE\", \"VG\", \"VI\", \"VN\", \"VU\", \"WF\", \"WS\", \"YE\", \"YT\", \"ZA\", \"ZM\", \"ZW\"])\n", 1276 | "\n", 1277 | "ProxyYT = widgets.Text(placeholder=\"Proxy URL\")\n", 1278 | "\n", 1279 | "MinSleep = widgets.BoundedIntText(value=0, min=0, max=300, step=1, description=\"Min:\")\n", 1280 | "\n", 1281 | "MaxSleep = widgets.BoundedIntText(value=0, min=0, max=300, step=1, description=\"Max:\")\n", 1282 | "\n", 1283 | "ExtraArg = widgets.Text(placeholder=\"Extra Arguments\")\n", 1284 | "\n", 1285 | "class MakeButton(object):\n", 1286 | " def __init__(self, title, callback, style):\n", 1287 | " self._title = title\n", 1288 | " self._callback = callback\n", 1289 | " self._style = style\n", 1290 | " def _repr_html_(self):\n", 1291 | " callback_id = 'button-' + str(uuid.uuid4())\n", 1292 | " output.register_callback(callback_id, self._callback)\n", 1293 | " if self._style != \"\":\n", 1294 | " style_html = \"p-Widget jupyter-widgets jupyter-button widget-button mod-\" + self._style\n", 1295 | " else:\n", 1296 | " style_html = \"p-Widget jupyter-widgets jupyter-button widget-button\"\n", 1297 | " template = \"\"\"\n", 1298 | " \"\"\"\n", 1304 | " html = template.format(title=self._title, callback_id=callback_id, style_html=style_html)\n", 1305 | " return html\n", 1306 | " \n", 1307 | "def MakeLabel(description, button_style):\n", 1308 | " return widgets.Button(description=description, disabled=True, button_style=button_style)\n", 1309 | "\n", 1310 | "def upload_archive():\n", 1311 | " if ask_yes_no(\"Do you already have an archive file? (y/n)\", default=\"\", interrupt=\"\"):\n", 1312 | " try:\n", 1313 | " display(HTML(\"

Please upload an archive from your computer.


\"))\n", 1314 | " UploadConfig = files.upload().keys()\n", 1315 | " clear_output(wait=True)\n", 1316 | " if len(UploadConfig) == 0:\n", 1317 | " return display(HTML(\"

File upload has been cancelled during upload file.


\"))\n", 1318 | " elif len(UploadConfig) == 1:\n", 1319 | " for fn in UploadConfig:\n", 1320 | " if os.path.isfile(\"/content/\" + fn):\n", 1321 | " get_ipython().system_raw(\"mv -f \" + \"\\\"\" + fn + \"\\\" /root/.youtube-dl.txt && chmod 666 /root/.youtube-dl.txt\")\n", 1322 | " AudioOnly.observe(AudioOnlyChange)\n", 1323 | " Subtitle.observe(SubtitleChange)\n", 1324 | " AudioQ.observe(AudioQChange)\n", 1325 | " ShowYT()\n", 1326 | " else:\n", 1327 | " return display(HTML(\"

File upload has been failed during upload file.


\"))\n", 1328 | " else:\n", 1329 | " for fn in UploadConfig:\n", 1330 | " get_ipython().system_raw(\"rm -f \" + \"\\\"\" + fn + \"\\\"\")\n", 1331 | " return display(HTML(\"

Please uploading only one file at a time.


\"))\n", 1332 | " except:\n", 1333 | " clear_output(wait=True)\n", 1334 | " return display(HTML(\"

Error occurred during upload file.


\"))\n", 1335 | " else:\n", 1336 | " get_ipython().system_raw(\"touch '/root/.youtube-dl.txt'\")\n", 1337 | " AudioOnly.observe(AudioOnlyChange)\n", 1338 | " Subtitle.observe(SubtitleChange)\n", 1339 | " AudioQ.observe(AudioQChange)\n", 1340 | " ShowYT()\n", 1341 | "\n", 1342 | "def RefreshPathYT():\n", 1343 | " if os.path.exists(\"/content/drive/\"):\n", 1344 | " if os.path.exists(\"/content/drive/Shared drives/\"):\n", 1345 | " SavePathYT.options = [\"/content\", \"/content/Downloads\", \"/content/drive/My Drive\"] + glob(\"/content/drive/My Drive/*/\") + glob(\"/content/drive/Shared drives/*/\")\n", 1346 | " else:\n", 1347 | " SavePathYT.options = [\"/content\", \"/content/Downloads\", \"/content/drive/My Drive\"] + glob(\"/content/drive/My Drive/*/\")\n", 1348 | " else:\n", 1349 | " SavePathYT.options = [\"/content\", \"/content/Downloads\"]\n", 1350 | "\n", 1351 | "def AudioOnlyChange(change):\n", 1352 | " if change[\"type\"] == \"change\" and change[\"new\"]:\n", 1353 | " VideoQ.disabled = True\n", 1354 | " Subtitle.disabled = True\n", 1355 | " if Subtitle.value:\n", 1356 | " Subtitle.button_style = \"info\"\n", 1357 | " else:\n", 1358 | " Subtitle.button_style = \"\"\n", 1359 | " Resolution.disabled = True\n", 1360 | " Extension.options = [\"best\", \"aac\", \"flac\", \"mp3\", \"m4a\", \"opus\", \"vorbis\", \"wav\"]\n", 1361 | " Extension.value = \"best\"\n", 1362 | " AudioOnly.button_style = \"info\"\n", 1363 | " elif change[\"type\"] == \"change\" and change[\"new\"] == False:\n", 1364 | " VideoQ.disabled = False\n", 1365 | " Subtitle.disabled = False\n", 1366 | " if Subtitle.value:\n", 1367 | " Subtitle.button_style = \"info\"\n", 1368 | " else:\n", 1369 | " Subtitle.button_style = \"\"\n", 1370 | " Resolution.disabled = False\n", 1371 | " if AudioQ.value == \"Best Quality (Opus)\":\n", 1372 | " Extension.options = [\"mkv\", \"webm\"]\n", 1373 | " else:\n", 1374 | " Extension.options = [\"mkv\", \"mp4\", \"webm\"]\n", 1375 | " Extension.value = \"mkv\"\n", 1376 | " AudioOnly.button_style = \"\"\n", 1377 | "\n", 1378 | "def SubtitleChange(change):\n", 1379 | " if change[\"type\"] == \"change\" and change[\"new\"]:\n", 1380 | " Subtitle.button_style = \"info\"\n", 1381 | " elif change[\"type\"] == \"change\" and change[\"new\"] == False:\n", 1382 | " Subtitle.button_style = \"\"\n", 1383 | "\n", 1384 | "def AudioQChange(change):\n", 1385 | " if change[\"type\"] == \"change\" and change[\"new\"] == \"Best Quality (Opus)\":\n", 1386 | " Extension.options = [\"mkv\", \"webm\"]\n", 1387 | " Extension.value = \"mkv\"\n", 1388 | " elif change[\"type\"] == \"change\" and change[\"new\"] == \"Best Compatibility (M4A)\":\n", 1389 | " Extension.options = [\"mkv\", \"mp4\", \"webm\"]\n", 1390 | " Extension.value = \"mkv\"\n", 1391 | "\n", 1392 | "def ShowYT():\n", 1393 | " clear_output(wait=True)\n", 1394 | " RefreshPathYT()\n", 1395 | " display(widgets.HBox([widgets.VBox([widgets.HTML(\"Link:\"), Links,\n", 1396 | " widgets.HTML(\"For website that require an account:\"), UsernameYT, PasswordYT, SecAuth, VideoPW,\n", 1397 | " widgets.HTML(\"GEO Bypass Country:\"), GEOBypass,\n", 1398 | " widgets.HTML(\"Proxy:\"), ProxyYT,\n", 1399 | " widgets.HTML(\"Sleep Interval (second):\"), MinSleep, MaxSleep]),\n", 1400 | " widgets.VBox([widgets.HTML(\"Video Quality:\"), VideoQ, widgets.HTML(\"Resolution:\"), Resolution,\n", 1401 | " widgets.HTML(\"Audio Quality:\"), AudioQ, widgets.HTML(\"Extension:\"), Extension,\n", 1402 | " widgets.HTML(\"Extra Options:\"), widgets.HBox([Subtitle, AudioOnly]),\n", 1403 | " widgets.HTML(\"Extra Arguments:\"), ExtraArg])]), HTML(\"

Save Location:

\"),\n", 1404 | " SavePathYT, MakeButton(\"Refresh\", RefreshPathYT, \"\"))\n", 1405 | " if not os.path.exists(\"/content/drive/\"):\n", 1406 | " display(HTML(\"*If you want to save in Google Drive please run the cell below.\"))\n", 1407 | " display(HTML(\"
\"), MakeButton(\"Download\", DownloadYT, \"info\"))\n", 1408 | "\n", 1409 | "def DownloadYT():\n", 1410 | " if Links.value.strip():\n", 1411 | " Count = 0\n", 1412 | " Total = str(len(Links.value.splitlines()))\n", 1413 | " # Account Check\n", 1414 | " if UsernameYT.value.strip() and PasswordYT.value.strip():\n", 1415 | " accountC = \"--username \\\"\" + UsernameYT.value + \"\\\" --password \\\"\" + PasswordYT.value + \"\\\"\"\n", 1416 | " else:\n", 1417 | " accountC = \"\"\n", 1418 | " if SecAuth.value.strip():\n", 1419 | " secauthC = \"-2 \" + SecAuth.value\n", 1420 | " else:\n", 1421 | " secauthC = \"\"\n", 1422 | " if VideoPW.value.strip():\n", 1423 | " videopwC = \"--video-password \" + VideoPW.value\n", 1424 | " else:\n", 1425 | " videopwC = \"\"\n", 1426 | " # Proxy\n", 1427 | " if ProxyYT.value.strip():\n", 1428 | " proxyytC = \"--proxy \" + ProxyYT.value\n", 1429 | " else:\n", 1430 | " proxyytC = \"\"\n", 1431 | " # GEO Bypass\n", 1432 | " if GEOBypass.value == \"Disable\":\n", 1433 | " geobypass = \"\"\n", 1434 | " elif GEOBypass.value == \"Hide\":\n", 1435 | " geobypass = \"--geo-bypass\"\n", 1436 | " else:\n", 1437 | " geobypass = \"--geo-bypass-country \" + GEOBypass.value\n", 1438 | " # Video Quality\n", 1439 | " if VideoQ.value == \"Best Quality (VP9 upto 4K)\":\n", 1440 | " videoqC = \"webm\"\n", 1441 | " else:\n", 1442 | " videoqC = \"mp4\"\n", 1443 | " # Audio Quality\n", 1444 | " if AudioQ.value == \"Best Quality (Opus)\":\n", 1445 | " audioqC = \"webm\"\n", 1446 | " else:\n", 1447 | " audioqC = \"m4a\"\n", 1448 | " # Audio Only Check\n", 1449 | " if AudioOnly.value:\n", 1450 | " subtitleC = \"\"\n", 1451 | " thumbnailC = \"\"\n", 1452 | " extC = \"-x --audio-quality 0 --audio-format \" + Extension.value\n", 1453 | " codecC = \"bestaudio[ext=\" + audioqC + \"]/bestaudio/best\"\n", 1454 | " else:\n", 1455 | " if Subtitle.value:\n", 1456 | " subtitleC = \"--all-subs --convert-subs srt --embed-subs\"\n", 1457 | " else:\n", 1458 | " subtitleC = \"\"\n", 1459 | " if Extension.value == \"mp4\":\n", 1460 | " thumbnailC = \"--embed-thumbnail\"\n", 1461 | " else:\n", 1462 | " thumbnailC = \"\"\n", 1463 | " extC = \"--merge-output-format \" + Extension.value\n", 1464 | " if Resolution.value == \"Highest\":\n", 1465 | " codecC = \"bestvideo[ext=\" + videoqC + \"]+bestaudio[ext=\" + audioqC + \"]/bestvideo+bestaudio/best\"\n", 1466 | " else:\n", 1467 | " codecC = \"bestvideo[ext=\" + videoqC + \",height<=\" + Resolution.value.replace(\"4K\", \"2160\").replace(\"p\", \"\") + \"]+bestaudio[ext=\" + audioqC + \"]/bestvideo[height<=\" + Resolution.value.replace(\"4K\", \"2160\").replace(\"p\", \"\") + \"]+bestaudio/bestvideo+bestaudio/best\"\n", 1468 | " # Archive\n", 1469 | " if os.path.isfile(\"/root/.youtube-dl.txt\"):\n", 1470 | " archiveC = \"--download-archive \\\"/root/.youtube-dl.txt\\\"\"\n", 1471 | " else:\n", 1472 | " archiveC = \"\"\n", 1473 | " # Sleep Interval\n", 1474 | " if MinSleep.value > 0 and MaxSleep.value > 0:\n", 1475 | " minsleepC = \"--min-sleep-interval \" + MinSleep.value\n", 1476 | " maxsleepC = \"--max-sleep-interval \" + MaxSleep.value\n", 1477 | " else:\n", 1478 | " minsleepC = \"\"\n", 1479 | " maxsleepC = \"\"\n", 1480 | " # Extra Arguments\n", 1481 | " extraargC = ExtraArg.value\n", 1482 | " for Link in Links.value.splitlines():\n", 1483 | " clear_output(wait=True)\n", 1484 | " Count += 1\n", 1485 | " display(HTML(\"

Processing link \" + str(Count) + \" out of \" + Total + \"

\"))\n", 1486 | " if \"youtube.com\" in Link or \"youtu.be\" in Link:\n", 1487 | " display(HTML(\"

Currently downloading...


\"), YouTubeVideo(Link, width=640, height=360), HTML(\"
\"))\n", 1488 | " else:\n", 1489 | " display(HTML(\"

Currently downloading \" + Link + \"


\"))\n", 1490 | " if (\"youtube.com\" in Link or \"youtu.be\" in Link) and \"list=\" in Link:\n", 1491 | " !youtube-dl -i --no-warnings --yes-playlist --add-metadata $accountC $secauthC $videopwC $minsleepC $maxsleepC $geobypass $proxyytC $extC $thumbnailC $subtitleC $archiveC $extraargC -f \"$codecC\" -o \"/root/.YouTube-DL/%(playlist)s/%(playlist_index)s - %(title)s.%(ext)s\" \"$Link\"\n", 1492 | " else:\n", 1493 | " !youtube-dl -i --no-warnings --yes-playlist --add-metadata $accountC $secauthC $videopwC $minsleepC $maxsleepC $geobypass $proxyytC $extC $thumbnailC $subtitleC $archiveC $extraargC -f \"$codecC\" -o \"/root/.YouTube-DL/%(title)s.%(ext)s\" \"$Link\"\n", 1494 | " if not os.path.exists(SavePathYT.value):\n", 1495 | " get_ipython().system_raw(\"mkdir -p -m 666 \" + SavePathYT.value)\n", 1496 | " get_ipython().system_raw(\"mv /root/.YouTube-DL/* '\" + SavePathYT.value + \"/'\")\n", 1497 | " # Archive Download\n", 1498 | " if os.path.isfile(\"/root/.youtube-dl.txt\"):\n", 1499 | " files.download(\"/root/.youtube-dl.txt\")\n", 1500 | " ShowYT()\n", 1501 | "\n", 1502 | "if not os.path.isfile(\"/usr/local/bin/youtube-dl\"):\n", 1503 | " get_ipython().system_raw(\"rm -rf /content/sample_data/ && mkdir -p -m 666 /root/.YouTube-DL/ && apt-get install atomicparsley && curl -L https://yt-dl.org/downloads/latest/youtube-dl -o /usr/local/bin/youtube-dl && chmod a+rx /usr/local/bin/youtube-dl\")\n", 1504 | "if Archive:\n", 1505 | " upload_archive()\n", 1506 | "else:\n", 1507 | " AudioOnly.observe(AudioOnlyChange)\n", 1508 | " Subtitle.observe(SubtitleChange)\n", 1509 | " AudioQ.observe(AudioQChange)\n", 1510 | " ShowYT()" 1511 | ], 1512 | "execution_count": 0, 1513 | "outputs": [] 1514 | }, 1515 | { 1516 | "cell_type": "markdown", 1517 | "metadata": { 1518 | "id": "QlsUJhNwyeV3", 1519 | "colab_type": "text" 1520 | }, 1521 | "source": [ 1522 | "# **9**. rcloneLab\n", 1523 | "# \"RcloneLab\"/" 1524 | ] 1525 | }, 1526 | { 1527 | "cell_type": "code", 1528 | "metadata": { 1529 | "id": "9qOSyk-RCTCz", 1530 | "colab_type": "code", 1531 | "cellView": "form", 1532 | "colab": {} 1533 | }, 1534 | "source": [ 1535 | "# ============================= FORM ============================= #\n", 1536 | "# @markdown #### Execute rClone\n", 1537 | "# @markdown ---\n", 1538 | "# @markdown ##### Quick move (Select and leave all boxes):\n", 1539 | "# @markdown #####{\n", 1540 | "Quick_Move = \"None\" # @param [\"None\",\"simpleTorrent\", \"Peerflix\", \"qBittorrent\", \"extract\", \"error\"]\n", 1541 | "# @markdown #####}\n", 1542 | "\n", 1543 | "Mode = \"Move\" # @param [\"Move\", \"Copy\", \"Sync\", \"Verify\", \"Dedupe\", \"Clean Empty Dirs\", \"Empty Trash\"]\n", 1544 | "Source = \"\" # @param {type:\"string\"}\n", 1545 | "Destination = \"\" # @param {type:\"string\"}\n", 1546 | "Extra_Arguments = \"\" # @param {type:\"string\"}\n", 1547 | "COPY_SHARED_FILES = False # @param{type: \"boolean\"}\n", 1548 | "Compare = \"Size & Checksum\"\n", 1549 | "TRANSFERS, CHECKERS = 20, 20\n", 1550 | "THROTTLE_TPS = True\n", 1551 | "BRIDGE_TRANSFER = False # @param{type: \"boolean\"}\n", 1552 | "FAST_LIST = False # @param{type: \"boolean\"}\n", 1553 | "OPTIMIZE_GDRIVE = True\n", 1554 | "SIMPLE_LOG = True\n", 1555 | "RECORD_LOGFILE = False # @param{type: \"boolean\"}\n", 1556 | "SKIP_NEWER_FILE = False\n", 1557 | "SKIP_EXISTED = False\n", 1558 | "SKIP_UPDATE_MODTIME = False\n", 1559 | "ONE_FILE_SYSTEM = False\n", 1560 | "LOG_LEVEL = \"DEBUG\"\n", 1561 | "SYNC_MODE = \"Delete after transfering\"\n", 1562 | "SYNC_TRACK_RENAME = True\n", 1563 | "DEDUPE_MODE = \"Largest\"\n", 1564 | "USE_TRASH = True\n", 1565 | "DRY_RUN = False # @param{type: \"boolean\"}\n", 1566 | "# ================================================================ #\n", 1567 | "if Quick_Move == \"None\":\n", 1568 | " pass\n", 1569 | "elif Quick_Move == \"simpleTorrent\" and Source == \"\" and Destination == \"\":\n", 1570 | " Mode = \"Move\"\n", 1571 | " Source = \"/content/downloads\"\n", 1572 | " Destination = \"/content/drive/My Drive\" \n", 1573 | "elif Quick_Move == \"Peerflix\" and Source == \"\" and Destination == \"\":\n", 1574 | " Mode = \"Move\"\n", 1575 | " Source = \"/content/peerflix\"\n", 1576 | " Destination = \"/content/drive/My Drive\" \n", 1577 | "elif Quick_Move == \"qBittorrent\" and Source == \"\" and Destination == \"\":\n", 1578 | " Mode = \"Move\"\n", 1579 | " Source = \"/content/qBittorrent\"\n", 1580 | " Destination = \"/content/drive/My Drive\"\n", 1581 | "elif Quick_Move == \"extract\" and Source == \"\" and Destination == \"\":\n", 1582 | " Mode = \"Move\"\n", 1583 | " Source = \"/content/extract\"\n", 1584 | " Destination = \"/content/drive/My Drive\"\n", 1585 | "elif Quick_Move == \"error\":\n", 1586 | " raise Exception(\"You are selected Error!\")\n", 1587 | "\n", 1588 | "from os import path as _p\n", 1589 | "\n", 1590 | "if not _p.exists(\"/root/.ipython/rlab_utils.py\"):\n", 1591 | " from shlex import split as _spl\n", 1592 | " from subprocess import run\n", 1593 | "\n", 1594 | " shellCmd = \"wget -qq https://biplobsd.github.io/RLabClone/res/rlab_utils.py \\\n", 1595 | " -O /root/.ipython/rlab_utils.py\"\n", 1596 | " run(_spl(shellCmd))\n", 1597 | "\n", 1598 | "from datetime import datetime as _dt\n", 1599 | "from rlab_utils import (\n", 1600 | " displayOutput,\n", 1601 | " checkAvailable,\n", 1602 | " runSh,\n", 1603 | " prepareSession,\n", 1604 | " PATH_RClone_Config,\n", 1605 | " accessSettingFile,\n", 1606 | " memGiB,\n", 1607 | ")\n", 1608 | "\n", 1609 | "\n", 1610 | "def populateActionArg():\n", 1611 | " if Mode == \"Copy\":\n", 1612 | " actionArg = \"copy\"\n", 1613 | " elif Mode == \"Sync\":\n", 1614 | " actionArg = \"sync\"\n", 1615 | " elif Mode == \"Verify\":\n", 1616 | " actionArg = \"check\"\n", 1617 | " elif Mode == \"Dedupe\":\n", 1618 | " actionArg = \"dedupe largest\"\n", 1619 | " elif Mode == \"Clean Empty Dirs\":\n", 1620 | " actionArg = \"rmdirs\"\n", 1621 | " elif Mode == \"Empty Trash\":\n", 1622 | " actionArg = \"delete\"\n", 1623 | " else:\n", 1624 | " actionArg = \"move\"\n", 1625 | "\n", 1626 | " return actionArg\n", 1627 | "\n", 1628 | "\n", 1629 | "def populateCompareArg():\n", 1630 | " if Compare == \"Mod-Time\":\n", 1631 | " compareArg = \"--ignore-size\"\n", 1632 | " elif Compare == \"Size\":\n", 1633 | " compareArg = \"--size-only\"\n", 1634 | " elif Compare == \"Checksum\":\n", 1635 | " compareArg = \"-c --ignore-size\"\n", 1636 | " else:\n", 1637 | " compareArg = \"-c\"\n", 1638 | "\n", 1639 | " return compareArg\n", 1640 | "\n", 1641 | "\n", 1642 | "def populateOptimizeGDriveArg():\n", 1643 | " return (\n", 1644 | " \"--buffer-size 256M \\\n", 1645 | " --drive-chunk-size 256M \\\n", 1646 | " --drive-upload-cutoff 256M \\\n", 1647 | " --drive-acknowledge-abuse \\\n", 1648 | " --drive-keep-revision-forever\"\n", 1649 | " if OPTIMIZE_GDRIVE\n", 1650 | " else \"--buffer-size 128M\"\n", 1651 | " )\n", 1652 | "\n", 1653 | "\n", 1654 | "def populateGDriveCopyArg():\n", 1655 | " if BRIDGE_TRANSFER and memGiB() < 13:\n", 1656 | " global TRANSFERS, CHECKERS\n", 1657 | " TRANSFERS, CHECKERS = 10, 80\n", 1658 | " else:\n", 1659 | " pass\n", 1660 | " return \"--disable copy\" if BRIDGE_TRANSFER else \"--drive-server-side-across-configs\"\n", 1661 | "\n", 1662 | "\n", 1663 | "def populateStatsArg():\n", 1664 | " statsArg = \"--stats-one-line --stats=5s\" if SIMPLE_LOG else \"--stats=5s -P\"\n", 1665 | " if LOG_LEVEL != \"OFF\":\n", 1666 | " statsArg += \" -v\" if SIMPLE_LOG else \"-vv\"\n", 1667 | " elif LOG_LEVEL == \"INFO\":\n", 1668 | " statsArg += \" --log-level INFO\"\n", 1669 | " elif LOG_LEVEL == \"ERROR\":\n", 1670 | " statsArg += \" --log-level ERROR\"\n", 1671 | " else:\n", 1672 | " statsArg += \" --log-level DEBUG\"\n", 1673 | " return statsArg\n", 1674 | "\n", 1675 | "\n", 1676 | "def populateSyncModeArg():\n", 1677 | " if Mode != \"Sync\":\n", 1678 | " return \"\"\n", 1679 | " elif SYNC_MODE == \"Delete before transfering\":\n", 1680 | " syncModeArg = \"--delete-before\"\n", 1681 | " elif SYNC_MODE == \"Delete after transfering\":\n", 1682 | " syncModeArg = \"--delete-after\"\n", 1683 | " else:\n", 1684 | " syncModeArg = \"--delete-during\"\n", 1685 | " if SYNC_TRACK_RENAME:\n", 1686 | " syncModeArg += \" --track-renames\"\n", 1687 | " return syncModeArg\n", 1688 | "\n", 1689 | "\n", 1690 | "def populateDedupeModeArg():\n", 1691 | " if DEDUPE_MODE == \"Interactive\":\n", 1692 | " dedupeModeArg = \"--dedupe-mode interactive\"\n", 1693 | " elif DEDUPE_MODE == \"Skip\":\n", 1694 | " dedupeModeArg = \"--dedupe-mode skip\"\n", 1695 | " elif DEDUPE_MODE == \"First\":\n", 1696 | " dedupeModeArg = \"--dedupe-mode first\"\n", 1697 | " elif DEDUPE_MODE == \"Newest\":\n", 1698 | " dedupeModeArg = \"--dedupe-mode newest\"\n", 1699 | " elif DEDUPE_MODE == \"Oldest\":\n", 1700 | " dedupeModeArg = \"--dedupe-mode oldest\"\n", 1701 | " elif DEDUPE_MODE == \"Rename\":\n", 1702 | " dedupeModeArg = \"--dedupe-mode rename\"\n", 1703 | " else:\n", 1704 | " dedupeModeArg = \"--dedupe-mode largest\"\n", 1705 | "\n", 1706 | " return dedupeModeArg\n", 1707 | "\n", 1708 | "\n", 1709 | "def generateCmd():\n", 1710 | " sharedFilesArgs = (\n", 1711 | " \"--drive-shared-with-me --files-from /content/upload.txt --no-traverse\"\n", 1712 | " if COPY_SHARED_FILES\n", 1713 | " else \"\"\n", 1714 | " )\n", 1715 | "\n", 1716 | " logFileArg = f\"--log-file /content/rclone_log.txt -vv -P\"\n", 1717 | "\n", 1718 | " args = [\n", 1719 | " \"rclone\",\n", 1720 | " f\"--config {PATH_RClone_Config}/rclone.conf\",\n", 1721 | " '--user-agent \"Mozilla\"',\n", 1722 | " populateActionArg(),\n", 1723 | " f'\"{Source}\"',\n", 1724 | " f'\"{Destination}\"' if Mode in (\"Move\", \"Copy\", \"Sync\") else \"\",\n", 1725 | " f\"--transfers {str(TRANSFERS)}\",\n", 1726 | " f\"--checkers {str(CHECKERS)}\",\n", 1727 | " ]\n", 1728 | "\n", 1729 | " if Mode == \"Verify\":\n", 1730 | " args.append(\"--one-way\")\n", 1731 | " elif Mode == \"Empty Trash\":\n", 1732 | " args.append(\"--drive-trashed-only --drive-use-trash=false\")\n", 1733 | " else:\n", 1734 | " args.extend(\n", 1735 | " [\n", 1736 | " populateGDriveCopyArg(),\n", 1737 | " populateSyncModeArg(),\n", 1738 | " populateCompareArg(),\n", 1739 | " populateOptimizeGDriveArg(),\n", 1740 | " \"-u\" if SKIP_NEWER_FILE else \"\",\n", 1741 | " \"--ignore-existing\" if SKIP_EXISTED else \"\",\n", 1742 | " \"--no-update-modtime\" if SKIP_UPDATE_MODTIME else \"\",\n", 1743 | " \"--one-file-system\" if ONE_FILE_SYSTEM else \"\",\n", 1744 | " \"--tpslimit 95 --tpslimit-burst 40\" if THROTTLE_TPS else \"\",\n", 1745 | " \"--fast-list\" if FAST_LIST else \"\",\n", 1746 | " \"--delete-empty-src-dirs\" if Mode == \"Move\" else \"\",\n", 1747 | " ]\n", 1748 | " )\n", 1749 | " args.extend(\n", 1750 | " [\n", 1751 | " \"-n\" if DRY_RUN else \"\",\n", 1752 | " populateStatsArg() if not RECORD_LOGFILE else logFileArg,\n", 1753 | " sharedFilesArgs,\n", 1754 | " Extra_Arguments,\n", 1755 | " ]\n", 1756 | " )\n", 1757 | "\n", 1758 | " return args\n", 1759 | "\n", 1760 | "\n", 1761 | "def executeRclone():\n", 1762 | " prepareSession()\n", 1763 | " if Source.strip() == \"\":\n", 1764 | " displayOutput(\"❌ The Source field is empty.\")\n", 1765 | " return\n", 1766 | " if checkAvailable(\"/content/rclone_log.txt\"):\n", 1767 | " if not checkAvailable(\"/content/logfiles\"):\n", 1768 | " runSh(\"mkdir -p -m 666 /content/logfiles\")\n", 1769 | " job = accessSettingFile(\"job.txt\")\n", 1770 | " runSh(\n", 1771 | " f'mv /content/rclone_log.txt /content/logfiles/{job[\"title\"]}_{job[\"status\"]}_logfile.txt'\n", 1772 | " )\n", 1773 | "\n", 1774 | " onGoingJob = {\n", 1775 | " \"title\": f'{Mode}_{Source}_{Destination}_{_dt.now().strftime(\"%a-%H-%M-%S\")}',\n", 1776 | " \"status\": \"ongoing\",\n", 1777 | " }\n", 1778 | " accessSettingFile(\"job.txt\", onGoingJob)\n", 1779 | "\n", 1780 | " cmd = \" \".join(generateCmd())\n", 1781 | " runSh(cmd, output=True)\n", 1782 | " displayOutput(Mode, \"success\")\n", 1783 | "\n", 1784 | " onGoingJob[\"status\"] = \"finished\"\n", 1785 | " accessSettingFile(\"job.txt\", onGoingJob)\n", 1786 | "\n", 1787 | "executeRclone()\n" 1788 | ], 1789 | "execution_count": 0, 1790 | "outputs": [] 1791 | }, 1792 | { 1793 | "cell_type": "code", 1794 | "metadata": { 1795 | "id": "whyei9P7GIsM", 1796 | "colab_type": "code", 1797 | "cellView": "form", 1798 | "colab": {} 1799 | }, 1800 | "source": [ 1801 | "#@markdown

rclone webui


\n", 1802 | "import os, signal\n", 1803 | "import random\n", 1804 | "import string\n", 1805 | "import urllib.request\n", 1806 | "from IPython.display import HTML, clear_output\n", 1807 | "import time\n", 1808 | "\n", 1809 | "#####################################\n", 1810 | "USE_FREE_TOKEN = True # @param {type:\"boolean\"}\n", 1811 | "TOKEN = \"\" # @param {type:\"string\"}\n", 1812 | "#@markdown Default
 username : user
 password : pass\n", 1813 | "HOME = os.path.expanduser(\"~\")\n", 1814 | "runW = get_ipython()\n", 1815 | "\n", 1816 | "if not os.path.exists(f\"{HOME}/.ipython/ttmg.py\"):\n", 1817 | " hCode = \"https://raw.githubusercontent.com/biplobsd/\" \\\n", 1818 | " \"Google-Colab-CloudTorrent/master/res/ttmg.py\"\n", 1819 | " urllib.request.urlretrieve(hCode, f\"{HOME}/.ipython/ttmg.py\")\n", 1820 | "\n", 1821 | "if not os.path.exists(\"/root/.ipython/rlab_utils.py\"):\n", 1822 | " from shlex import split as _spl\n", 1823 | " from subprocess import run\n", 1824 | "\n", 1825 | " shellCmd = \"wget -qq https://biplobsd.github.io/RLabClone/res/rlab_utils.py \\\n", 1826 | " -O /root/.ipython/rlab_utils.py\"\n", 1827 | " run(_spl(shellCmd))\n", 1828 | "\n", 1829 | "from ttmg import (\n", 1830 | " runSh,\n", 1831 | " loadingAn,\n", 1832 | " ngrok,\n", 1833 | " displayUrl,\n", 1834 | " findProcess,\n", 1835 | " CWD,\n", 1836 | " textAn,\n", 1837 | " checkAvailable\n", 1838 | ")\n", 1839 | "from rlab_utils import (\n", 1840 | " displayOutput,\n", 1841 | " checkAvailable,\n", 1842 | " prepareSession,\n", 1843 | " PATH_RClone_Config,\n", 1844 | " accessSettingFile,\n", 1845 | " memGiB,\n", 1846 | ")\n", 1847 | "\n", 1848 | "loadingAn()\n", 1849 | "prepareSession()\n", 1850 | "pid = findProcess(\"rclone\", \"rcd\", isPid=True)\n", 1851 | "try:\n", 1852 | " os.kill(int(pid), signal.SIGTERM)\n", 1853 | "except TypeError:\n", 1854 | " pass\n", 1855 | "cmd = \"rclone rcd --rc-web-gui --rc-addr :5572\" \\\n", 1856 | " \" --rc-serve\" \\\n", 1857 | " \" --rc-user=user --rc-pass=pass\" \\\n", 1858 | " \" --rc-no-auth\" \\\n", 1859 | " rf\" --config {PATH_RClone_Config}/rclone.conf\" \\\n", 1860 | " ' --user-agent \"Mozilla\"' \\\n", 1861 | " ' --transfers 16' \\\n", 1862 | " \" &\"\n", 1863 | "runSh(cmd, shell=True)\n", 1864 | "# START_SERVER\n", 1865 | "# Ngrok region 'us','eu','ap','au','sa','jp','in'\n", 1866 | "clear_output()\n", 1867 | "Server = ngrok(\n", 1868 | " TOKEN, USE_FREE_TOKEN, [['rclone', 5572, 'http'],\n", 1869 | " ['filebrowser', 4000, 'http']], 'ap', \n", 1870 | " [f\"{HOME}/.ngrok2/filebrowserRclone.yml\", 4099]\n", 1871 | ").start('rclone', displayB=False)\n", 1872 | "# output\n", 1873 | "clear_output()\n", 1874 | "displayUrl(Server, pNamU='Rclone webUI : ', \n", 1875 | " ExUrl=fr\"http://user:pass@{Server['url'][7:]}\")" 1876 | ], 1877 | "execution_count": 0, 1878 | "outputs": [] 1879 | }, 1880 | { 1881 | "cell_type": "code", 1882 | "metadata": { 1883 | "id": "-BeHgvH1aNIJ", 1884 | "colab_type": "code", 1885 | "cellView": "form", 1886 | "colab": {} 1887 | }, 1888 | "source": [ 1889 | "#@markdown

Create/Edit Rclone config

Create a new remote with name, type and options.
After created your config file download that. Next time just upload and you are done!
\n", 1890 | "import os, urllib.request\n", 1891 | "from IPython.display import HTML\n", 1892 | "USE_FREE_TOKEN = True # @param {type:\"boolean\"}\n", 1893 | "TOKEN = \"\" # @param {type:\"string\"}\n", 1894 | "HOME = os.path.expanduser(\"~\")\n", 1895 | "runW = get_ipython()\n", 1896 | "\n", 1897 | "if not os.path.exists(f\"{HOME}/.ipython/ttmg.py\"):\n", 1898 | " hCode = \"https://raw.githubusercontent.com/biplobsd/\" \\\n", 1899 | " \"Google-Colab-CloudTorrent/master/res/ttmg.py\"\n", 1900 | " urllib.request.urlretrieve(hCode, f\"{HOME}/.ipython/ttmg.py\")\n", 1901 | "\n", 1902 | "#####################################\n", 1903 | "\n", 1904 | "if not os.path.exists(\"/root/.ipython/rlab_utils.py\"):\n", 1905 | " from shlex import split as _spl\n", 1906 | " from subprocess import run\n", 1907 | "\n", 1908 | " shellCmd = \"wget -qq https://biplobsd.github.io/RLabClone/res/rlab_utils.py \\\n", 1909 | " -O /root/.ipython/rlab_utils.py\"\n", 1910 | " run(_spl(shellCmd))\n", 1911 | "\n", 1912 | "from rlab_utils import (\n", 1913 | " prepareSession,\n", 1914 | " PATH_RClone_Config,\n", 1915 | " runSh\n", 1916 | ")\n", 1917 | "from ttmg import (\n", 1918 | " ngrok\n", 1919 | ")\n", 1920 | "\n", 1921 | "###################################\n", 1922 | "import codecs\n", 1923 | "import contextlib\n", 1924 | "import locale\n", 1925 | "import os\n", 1926 | "import pty\n", 1927 | "import select\n", 1928 | "import signal\n", 1929 | "import subprocess\n", 1930 | "import sys\n", 1931 | "import termios\n", 1932 | "import time\n", 1933 | "\n", 1934 | "\n", 1935 | "from IPython.utils import text\n", 1936 | "import six\n", 1937 | "from google.colab import _ipython\n", 1938 | "from google.colab import _message\n", 1939 | "from google.colab.output import _tags\n", 1940 | "\n", 1941 | "# Linux read(2) limits to 0x7ffff000 so stay under that for clarity.\n", 1942 | "_PTY_READ_MAX_BYTES_FOR_TEST = 2**20 # 1MB\n", 1943 | "\n", 1944 | "_ENCODING = 'UTF-8'\n", 1945 | "\n", 1946 | "class ShellResult(object):\n", 1947 | " \"\"\"Result of an invocation of the shell magic.\n", 1948 | "\n", 1949 | " Note: This is intended to mimic subprocess.CompletedProcess, but has slightly\n", 1950 | " different characteristics, including:\n", 1951 | " * CompletedProcess has separate stdout/stderr properties. A ShellResult\n", 1952 | " has a single property containing the merged stdout/stderr stream,\n", 1953 | " providing compatibility with the existing \"!\" shell magic (which this is\n", 1954 | " intended to provide an alternative to).\n", 1955 | " * A custom __repr__ method that returns output. When the magic is invoked as\n", 1956 | " the only statement in the cell, Python prints the string representation by\n", 1957 | " default. The existing \"!\" shell magic also returns output.\n", 1958 | " \"\"\"\n", 1959 | "\n", 1960 | " def __init__(self, args, returncode, command_output):\n", 1961 | " self.args = args\n", 1962 | " self.returncode = returncode\n", 1963 | " self.output = command_output\n", 1964 | "\n", 1965 | " def check_returncode(self):\n", 1966 | " if self.returncode:\n", 1967 | " raise subprocess.CalledProcessError(\n", 1968 | " returncode=self.returncode, cmd=self.args, output=self.output)\n", 1969 | "\n", 1970 | " def _repr_pretty_(self, p, cycle): # pylint:disable=unused-argument\n", 1971 | " # Note: When invoking the magic and not assigning the result\n", 1972 | " # (e.g. %shell echo \"foo\"), Python's default semantics will be used and\n", 1973 | " # print the string representation of the object. By default, this will\n", 1974 | " # display the __repr__ of ShellResult. Suppress this representation since\n", 1975 | " # the output of the command has already been displayed to the output window.\n", 1976 | " if cycle:\n", 1977 | " raise NotImplementedError\n", 1978 | "\n", 1979 | "\n", 1980 | "def _configure_term_settings(pty_fd):\n", 1981 | " term_settings = termios.tcgetattr(pty_fd)\n", 1982 | " # ONLCR transforms NL to CR-NL, which is undesirable. Ensure this is disabled.\n", 1983 | " # http://man7.org/linux/man-pages/man3/termios.3.html\n", 1984 | " term_settings[1] &= ~termios.ONLCR\n", 1985 | "\n", 1986 | " # ECHOCTL echoes control characters, which is undesirable.\n", 1987 | " term_settings[3] &= ~termios.ECHOCTL\n", 1988 | "\n", 1989 | " termios.tcsetattr(pty_fd, termios.TCSANOW, term_settings)\n", 1990 | "\n", 1991 | "\n", 1992 | "def _run_command(cmd, clear_streamed_output):\n", 1993 | " \"\"\"Calls the shell command, forwarding input received on the stdin_socket.\"\"\"\n", 1994 | " locale_encoding = locale.getpreferredencoding()\n", 1995 | " if locale_encoding != _ENCODING:\n", 1996 | " raise NotImplementedError(\n", 1997 | " 'A UTF-8 locale is required. Got {}'.format(locale_encoding))\n", 1998 | "\n", 1999 | " parent_pty, child_pty = pty.openpty()\n", 2000 | " _configure_term_settings(child_pty)\n", 2001 | "\n", 2002 | " epoll = select.epoll()\n", 2003 | " epoll.register(\n", 2004 | " parent_pty,\n", 2005 | " (select.EPOLLIN | select.EPOLLOUT | select.EPOLLHUP | select.EPOLLERR))\n", 2006 | "\n", 2007 | " try:\n", 2008 | " temporary_clearer = _tags.temporary if clear_streamed_output else _no_op\n", 2009 | "\n", 2010 | " with temporary_clearer(), _display_stdin_widget(\n", 2011 | " delay_millis=500) as update_stdin_widget:\n", 2012 | " # TODO(b/115531839): Ensure that subprocesses are terminated upon\n", 2013 | " # interrupt.\n", 2014 | " p = subprocess.Popen(\n", 2015 | " cmd,\n", 2016 | " shell=True,\n", 2017 | " executable='/bin/bash',\n", 2018 | " stdout=child_pty,\n", 2019 | " stdin=child_pty,\n", 2020 | " stderr=child_pty,\n", 2021 | " close_fds=True)\n", 2022 | " # The child PTY is only needed by the spawned process.\n", 2023 | " os.close(child_pty)\n", 2024 | "\n", 2025 | " return _monitor_process(parent_pty, epoll, p, cmd, update_stdin_widget)\n", 2026 | " finally:\n", 2027 | " epoll.close()\n", 2028 | " os.close(parent_pty)\n", 2029 | "\n", 2030 | "\n", 2031 | "class _MonitorProcessState(object):\n", 2032 | "\n", 2033 | " def __init__(self):\n", 2034 | " self.process_output = six.StringIO()\n", 2035 | " self.is_pty_still_connected = True\n", 2036 | "\n", 2037 | "\n", 2038 | "def _monitor_process(parent_pty, epoll, p, cmd, update_stdin_widget):\n", 2039 | " \"\"\"Monitors the given subprocess until it terminates.\"\"\"\n", 2040 | " state = _MonitorProcessState()\n", 2041 | "\n", 2042 | " # A single UTF-8 character can span multiple bytes. os.read returns bytes and\n", 2043 | " # could return a partial byte sequence for a UTF-8 character. Using an\n", 2044 | " # incremental decoder is incrementally fed input bytes and emits UTF-8\n", 2045 | " # characters.\n", 2046 | " decoder = codecs.getincrementaldecoder(_ENCODING)()\n", 2047 | "\n", 2048 | " num_interrupts = 0\n", 2049 | " echo_status = None\n", 2050 | " while True:\n", 2051 | " try:\n", 2052 | " result = _poll_process(parent_pty, epoll, p, cmd, decoder, state)\n", 2053 | " if result is not None:\n", 2054 | " return result\n", 2055 | " term_settings = termios.tcgetattr(parent_pty)\n", 2056 | " new_echo_status = bool(term_settings[3] & termios.ECHO)\n", 2057 | " if echo_status != new_echo_status:\n", 2058 | " update_stdin_widget(new_echo_status)\n", 2059 | " echo_status = new_echo_status\n", 2060 | " except KeyboardInterrupt:\n", 2061 | " try:\n", 2062 | " num_interrupts += 1\n", 2063 | " if num_interrupts == 1:\n", 2064 | " p.send_signal(signal.SIGINT)\n", 2065 | " elif num_interrupts == 2:\n", 2066 | " # Process isn't responding to SIGINT and user requested another\n", 2067 | " # interrupt. Attempt to send SIGTERM followed by a SIGKILL if the\n", 2068 | " # process doesn't respond.\n", 2069 | " p.send_signal(signal.SIGTERM)\n", 2070 | " time.sleep(0.5)\n", 2071 | " if p.poll() is None:\n", 2072 | " p.send_signal(signal.SIGKILL)\n", 2073 | " except KeyboardInterrupt:\n", 2074 | " # Any interrupts that occur during shutdown should not propagate.\n", 2075 | " pass\n", 2076 | "\n", 2077 | " if num_interrupts > 2:\n", 2078 | " # In practice, this shouldn't be possible since\n", 2079 | " # SIGKILL is quite effective.\n", 2080 | " raise\n", 2081 | "\n", 2082 | "\n", 2083 | "def _poll_process(parent_pty, epoll, p, cmd, decoder, state):\n", 2084 | " \"\"\"Polls the process and captures / forwards input and output.\"\"\"\n", 2085 | "\n", 2086 | " terminated = p.poll() is not None\n", 2087 | " if terminated:\n", 2088 | " termios.tcdrain(parent_pty)\n", 2089 | " # We're no longer interested in write events and only want to consume any\n", 2090 | " # remaining output from the terminated process. Continuing to watch write\n", 2091 | " # events may cause early termination of the loop if no output was\n", 2092 | " # available but the pty was ready for writing.\n", 2093 | " epoll.modify(parent_pty,\n", 2094 | " (select.EPOLLIN | select.EPOLLHUP | select.EPOLLERR))\n", 2095 | "\n", 2096 | " output_available = False\n", 2097 | "\n", 2098 | " events = epoll.poll()\n", 2099 | " input_events = []\n", 2100 | " for _, event in events:\n", 2101 | " if event & select.EPOLLIN:\n", 2102 | " output_available = True\n", 2103 | " raw_contents = os.read(parent_pty, _PTY_READ_MAX_BYTES_FOR_TEST)\n", 2104 | " import re\n", 2105 | " decoded_contents = re.sub(r\"http:\\/\\/127.0.0.1:53682\", Server[\"url\"], \n", 2106 | " decoder.decode(raw_contents))\n", 2107 | " sys.stdout.write(decoded_contents)\n", 2108 | " state.process_output.write(decoded_contents)\n", 2109 | "\n", 2110 | " if event & select.EPOLLOUT:\n", 2111 | " # Queue polling for inputs behind processing output events.\n", 2112 | " input_events.append(event)\n", 2113 | "\n", 2114 | " # PTY was disconnected or encountered a connection error. In either case,\n", 2115 | " # no new output should be made available.\n", 2116 | " if (event & select.EPOLLHUP) or (event & select.EPOLLERR):\n", 2117 | " state.is_pty_still_connected = False\n", 2118 | "\n", 2119 | " for event in input_events:\n", 2120 | " # Check to see if there is any input on the stdin socket.\n", 2121 | " # pylint: disable=protected-access\n", 2122 | " input_line = _message._read_stdin_message()\n", 2123 | " # pylint: enable=protected-access\n", 2124 | " if input_line is not None:\n", 2125 | " # If a very large input or sequence of inputs is available, it's\n", 2126 | " # possible that the PTY buffer could be filled and this write call\n", 2127 | " # would block. To work around this, non-blocking writes and keeping\n", 2128 | " # a list of to-be-written inputs could be used. Empirically, the\n", 2129 | " # buffer limit is ~12K, which shouldn't be a problem in most\n", 2130 | " # scenarios. As such, optimizing for simplicity.\n", 2131 | " input_bytes = bytes(input_line.encode(_ENCODING))\n", 2132 | " os.write(parent_pty, input_bytes)\n", 2133 | "\n", 2134 | " # Once the process is terminated, there still may be output to be read from\n", 2135 | " # the PTY. Wait until the PTY has been disconnected and no more data is\n", 2136 | " # available for read. Simply waiting for disconnect may be insufficient if\n", 2137 | " # there is more data made available on the PTY than we consume in a single\n", 2138 | " # read call.\n", 2139 | " if terminated and not state.is_pty_still_connected and not output_available:\n", 2140 | " sys.stdout.flush()\n", 2141 | " command_output = state.process_output.getvalue()\n", 2142 | " return ShellResult(cmd, p.returncode, command_output)\n", 2143 | "\n", 2144 | " if not output_available:\n", 2145 | " # The PTY is almost continuously available for reading input to provide\n", 2146 | " # to the underlying subprocess. This means that the polling loop could\n", 2147 | " # effectively become a tight loop and use a large amount of CPU. Add a\n", 2148 | " # slight delay to give resources back to the system while monitoring the\n", 2149 | " # process.\n", 2150 | " # Skip this delay if we read output in the previous loop so that a partial\n", 2151 | " # read doesn't unnecessarily sleep before reading more output.\n", 2152 | " # TODO(b/115527726): Rather than sleep, poll for incoming messages from\n", 2153 | " # the frontend in the same poll as for the output.\n", 2154 | " time.sleep(0.1)\n", 2155 | "\n", 2156 | "\n", 2157 | "@contextlib.contextmanager\n", 2158 | "def _display_stdin_widget(delay_millis=0):\n", 2159 | " \"\"\"Context manager that displays a stdin UI widget and hides it upon exit.\n", 2160 | "\n", 2161 | " Args:\n", 2162 | " delay_millis: Duration (in milliseconds) to delay showing the widget within\n", 2163 | " the UI.\n", 2164 | "\n", 2165 | " Yields:\n", 2166 | " A callback that can be invoked with a single argument indicating whether\n", 2167 | " echo is enabled.\n", 2168 | " \"\"\"\n", 2169 | " shell = _ipython.get_ipython()\n", 2170 | " display_args = ['cell_display_stdin', {'delayMillis': delay_millis}]\n", 2171 | " _message.blocking_request(*display_args, parent=shell.parent_header)\n", 2172 | "\n", 2173 | " def echo_updater(new_echo_status):\n", 2174 | " # Note: Updating the echo status uses colab_request / colab_reply on the\n", 2175 | " # stdin socket. Input provided by the user also sends messages on this\n", 2176 | " # socket. If user input is provided while the blocking_request call is still\n", 2177 | " # waiting for a colab_reply, the input will be dropped per\n", 2178 | " # https://github.com/googlecolab/colabtools/blob/56e4dbec7c4fa09fad51b60feb5c786c69d688c6/google/colab/_message.py#L100.\n", 2179 | " update_args = ['cell_update_stdin', {'echo': new_echo_status}]\n", 2180 | " _message.blocking_request(*update_args, parent=shell.parent_header)\n", 2181 | "\n", 2182 | " yield echo_updater\n", 2183 | "\n", 2184 | " hide_args = ['cell_remove_stdin', {}]\n", 2185 | " _message.blocking_request(*hide_args, parent=shell.parent_header)\n", 2186 | "\n", 2187 | "\n", 2188 | "@contextlib.contextmanager\n", 2189 | "def _no_op():\n", 2190 | " yield\n", 2191 | "\n", 2192 | "###################################\n", 2193 | "prepareSession()\n", 2194 | "\n", 2195 | "Server = ngrok(\n", 2196 | " TOKEN, USE_FREE_TOKEN, [['rcloneConfig', 53682, 'http'], \n", 2197 | " ['pyload', 8000, 'http']], 'sa', \n", 2198 | " [f\"{HOME}/.ngrok2/rclonePyload.yml\", 4074]\n", 2199 | ").start('rcloneConfig', displayB=False, v=False)\n", 2200 | "\n", 2201 | "printData = \"\"\"Copy this URL,\n", 2202 | " It's needed for authentication purposes.\n", 2203 | " After completing your account select, you redirect to a website, after back\n", 2204 | " you need to change http://127.0.0.0:53682 to {}\"\"\".format(Server['url'])\n", 2205 | "print(printData)\n", 2206 | "display(HTML('  See how

'))\n", 2207 | "print(f\"{Server['url']}\", end=\"\\n\\n\")\n", 2208 | "_run_command(f\"rclone config --config {PATH_RClone_Config}/rclone.conf\", False)" 2209 | ], 2210 | "execution_count": 0, 2211 | "outputs": [] 2212 | }, 2213 | { 2214 | "cell_type": "code", 2215 | "metadata": { 2216 | "id": "uB-vkVstVpVs", 2217 | "colab_type": "code", 2218 | "cellView": "form", 2219 | "colab": {} 2220 | }, 2221 | "source": [ 2222 | "# ============================= FORM ============================= #\n", 2223 | "# @markdown #### Execute Upload Local File\n", 2224 | "MODE = \"RCONFIG\" # @param ['UTILS', 'RCONFIG', 'RCONFIG_append', \"GENERATELIST\"]\n", 2225 | "REMOTE = \"mnc\" # @param {type:\"string\"}\n", 2226 | "QUERY_PATTERN = \"\" # @param {type:\"string\"}\n", 2227 | "# @markdown #### For not able to upload local file : https://stackoverflow.com/a/58661947\n", 2228 | "# ================================================================ #\n", 2229 | "\n", 2230 | "from os import path as _p\n", 2231 | "\n", 2232 | "if not _p.exists(\"/root/.ipython/rlab_utils.py\"):\n", 2233 | " from shlex import split as _spl\n", 2234 | " from subprocess import run # nosec\n", 2235 | "\n", 2236 | " shellCmd = \"wget -qq https://biplobsd.github.io/RLabClone/res/rlab_utils.py \\\n", 2237 | " -O /root/.ipython/rlab_utils.py\"\n", 2238 | " run(_spl(shellCmd)) # nosec\n", 2239 | "\n", 2240 | "import importlib, rlab_utils\n", 2241 | "from google.colab import files # pylint: disable=import-error #nosec\n", 2242 | "from rlab_utils import checkAvailable, runSh, PATH_RClone_Config, prepareSession\n", 2243 | "\n", 2244 | "\n", 2245 | "def generateUploadList():\n", 2246 | " prepareSession()\n", 2247 | " if checkAvailable(\"/content/upload.txt\"):\n", 2248 | " runSh(\"rm -f upload.txt\")\n", 2249 | " runSh(\n", 2250 | " f\"rclone --config {PATH_RClone_Config}/rclone.conf lsf {REMOTE}: --include '{QUERY_PATTERN}' --drive-shared-with-me --files-only --max-depth 1 > /content/upload.txt\",\n", 2251 | " shell=True, # nosec\n", 2252 | " )\n", 2253 | "\n", 2254 | "\n", 2255 | "def uploadLocalFiles():\n", 2256 | " prepareSession()\n", 2257 | " if MODE == \"UTILS\":\n", 2258 | " filePath = \"/root/.ipython/rlab_utils.py\"\n", 2259 | " elif MODE in (\"RCONFIG\", \"RCONFIG_append\"):\n", 2260 | " filePath = f\"{PATH_RClone_Config}/rclone.conf\"\n", 2261 | " else:\n", 2262 | " pass\n", 2263 | "\n", 2264 | " try:\n", 2265 | " if checkAvailable(filePath):\n", 2266 | " runSh(f\"rm -f {filePath}\")\n", 2267 | " print(\"Select file from your computer.\\n\")\n", 2268 | " uploadedFile = files.upload()\n", 2269 | " fileNameDictKeys = uploadedFile.keys()\n", 2270 | " fileNo = len(fileNameDictKeys)\n", 2271 | " if fileNo > 1:\n", 2272 | " for fn in fileNameDictKeys:\n", 2273 | " runSh(f'rm -f \"/content/{fn}\"')\n", 2274 | " return print(\"\\nPlease only upload a single config file.\")\n", 2275 | " elif fileNo == 0:\n", 2276 | " return print(\"\\nFile upload cancelled.\")\n", 2277 | " elif fileNo == 1:\n", 2278 | " for fn in fileNameDictKeys:\n", 2279 | " if checkAvailable(f\"/content/{fn}\"):\n", 2280 | " if MODE == \"RCONFIG_append\":\n", 2281 | " import urllib\n", 2282 | " urllib.request.urlretrieve(\"https://biplobsd.github.io/RLabClone/res/rclonelab/rclone.conf\",\n", 2283 | " \"/usr/local/sessionSettings/rclone.conf\")\n", 2284 | " with open(f\"/content/{fn}\", 'r+') as r:\n", 2285 | " new_data = r.read()\n", 2286 | " runSh(f'rm -f \"/content/{fn}\"')\n", 2287 | " with open(filePath, 'r+') as f:\n", 2288 | " old_data = f.read()\n", 2289 | " f.seek(0)\n", 2290 | " f.truncate(0)\n", 2291 | " f.write(old_data + new_data)\n", 2292 | " print(\"\\nUpdate completed.\")\n", 2293 | " else:\n", 2294 | " runSh(f'mv -f \"/content/{fn}\" {filePath}')\n", 2295 | " runSh(f\"chmod 666 {filePath}\")\n", 2296 | " runSh(f'rm -f \"/content/{fn}\"')\n", 2297 | " importlib.reload(rlab_utils)\n", 2298 | " print(\"\\nUpload completed.\")\n", 2299 | " return\n", 2300 | " else:\n", 2301 | " print(\"\\nNo file\")\n", 2302 | " return\n", 2303 | " except:\n", 2304 | " return print(\"\\nUpload process Error.\")\n", 2305 | "\n", 2306 | "\n", 2307 | "if MODE == \"GENERATELIST\":\n", 2308 | " generateUploadList()\n", 2309 | "else:\n", 2310 | " uploadLocalFiles()\n" 2311 | ], 2312 | "execution_count": 0, 2313 | "outputs": [] 2314 | }, 2315 | { 2316 | "cell_type": "code", 2317 | "metadata": { 2318 | "id": "RG2o5dgK5P4j", 2319 | "colab_type": "code", 2320 | "cellView": "form", 2321 | "colab": {} 2322 | }, 2323 | "source": [ 2324 | "# ============================= FORM ============================= #\n", 2325 | "# @markdown #### Download config file.\n", 2326 | "MODE = \"RCONFIG\" # @param ['UTILS', 'RCONFIG']\n", 2327 | "# ================================================================ #\n", 2328 | "from google.colab import files\n", 2329 | "\n", 2330 | "def downloadFile():\n", 2331 | " if MODE == \"UTILS\":\n", 2332 | " filePath = \"/root/.ipython/rlab_utils.py\"\n", 2333 | " elif MODE == \"RCONFIG\":\n", 2334 | " filePath = f\"{PATH_RClone_Config}/rclone.conf\"\n", 2335 | " else:\n", 2336 | " pass\n", 2337 | " try:\n", 2338 | " files.download(filePath)\n", 2339 | " except FileNotFoundError:\n", 2340 | " print(\"File not found!\")\n", 2341 | "\n", 2342 | "if __name__ == \"__main__\":\n", 2343 | " downloadFile()\n" 2344 | ], 2345 | "execution_count": 0, 2346 | "outputs": [] 2347 | }, 2348 | { 2349 | "cell_type": "markdown", 2350 | "metadata": { 2351 | "id": "cHTe9qp2E6f5", 2352 | "colab_type": "text" 2353 | }, 2354 | "source": [ 2355 | "# **10**. NZBget\n", 2356 | "# \"logo\"/\"nzbget\"/" 2357 | ] 2358 | }, 2359 | { 2360 | "cell_type": "code", 2361 | "metadata": { 2362 | "id": "UinZqhU6XBKF", 2363 | "colab_type": "code", 2364 | "cellView": "form", 2365 | "colab": {} 2366 | }, 2367 | "source": [ 2368 | "#@markdown

← Click Here to Use NZBget (ngrok)

\n", 2369 | "Ngrok_Token = \"\" #@param {type:\"string\"}\n", 2370 | "\n", 2371 | "import os, psutil, uuid, time, urllib.request, json; from IPython.display import clear_output\n", 2372 | "import ipywidgets as widgets\n", 2373 | "from IPython.display import HTML, clear_output\n", 2374 | "from google.colab import output\n", 2375 | "\n", 2376 | "class MakeButton(object):\n", 2377 | " def __init__(self, title, callback):\n", 2378 | " self._title = title\n", 2379 | " self._callback = callback\n", 2380 | " def _repr_html_(self):\n", 2381 | " callback_id = 'button-' + str(uuid.uuid4())\n", 2382 | " output.register_callback(callback_id, self._callback)\n", 2383 | " template = \"\"\"\n", 2384 | " \"\"\"\n", 2390 | " html = template.format(title=self._title, callback_id=callback_id)\n", 2391 | " return html\n", 2392 | " \n", 2393 | "def MakeLabel(description, button_style):\n", 2394 | " return widgets.Button(description=description, disabled=True, button_style=button_style)\n", 2395 | "\n", 2396 | "if os.path.isfile(\"/usr/local/bin/ngrok\") == False:\n", 2397 | " !wget -q -c -nc https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip\n", 2398 | " !unzip -qq -n ngrok-stable-linux-amd64.zip\n", 2399 | " !mv ngrok /usr/local/bin/ngrok\n", 2400 | " !rm -f /content/ngrok-stable-linux-amd64.zip\n", 2401 | " print(\"ngrok successfully installed.\")\n", 2402 | " clear_output(wait=True)\n", 2403 | "else:\n", 2404 | " print(\"ngrok already installed. Skipping... \")\n", 2405 | " clear_output(wait=True)\n", 2406 | " !pkill ngrok\n", 2407 | "\n", 2408 | "def RandomGenerator():\n", 2409 | " return time.strftime(\"%S\") + str(time.time()).split(\".\")[-1]\n", 2410 | "\n", 2411 | "def CheckProcess(process, command):\n", 2412 | " for pid in psutil.pids():\n", 2413 | " try:\n", 2414 | " p = psutil.Process(pid)\n", 2415 | " if process in p.name():\n", 2416 | " for arg in p.cmdline():\n", 2417 | " if command in str(arg): \n", 2418 | " return True\n", 2419 | " else:\n", 2420 | " pass\n", 2421 | " else:\n", 2422 | " pass\n", 2423 | " except:\n", 2424 | " continue\n", 2425 | "\n", 2426 | "try:\n", 2427 | " try:\n", 2428 | " Random_NumberNZ\n", 2429 | " except NameError:\n", 2430 | " Random_NumberNZ = RandomGenerator()\n", 2431 | " display(MakeLabel('Installing in Progress', 'warning'))\n", 2432 | " if os.path.isfile(\"/content/nzbget/nzbget\") == False:\n", 2433 | " !mkdir /content/nzbget\n", 2434 | " get_ipython().system_raw(\"rm -rf /content/sample_data/ && wget https://nzbget.net/download/nzbget-latest-bin-linux.run && sh nzbget-latest-bin-linux.run\")\n", 2435 | " if CheckProcess(\"nzbget\", \"\") != True:\n", 2436 | " get_ipython().system_raw(\"/content/nzbget/nzbget -s &\")\n", 2437 | "except:\n", 2438 | " clear_output(wait=True)\n", 2439 | "\n", 2440 | "get_ipython().system_raw('/usr/local/bin/ngrok authtoken $Ngrok_Token && /usr/local/bin/ngrok http 6789 &')\n", 2441 | "time.sleep(10)\n", 2442 | "clear_output(wait=True)\n", 2443 | "with urllib.request.urlopen('http://localhost:4040/api/tunnels') as response:\n", 2444 | " data = json.loads(response.read().decode())\n", 2445 | " host = data['tunnels'][0]['public_url'][8:]\n", 2446 | " print(f'Open this link in new tab http://{host}')" 2447 | ], 2448 | "execution_count": 0, 2449 | "outputs": [] 2450 | }, 2451 | { 2452 | "cell_type": "markdown", 2453 | "metadata": { 2454 | "id": "kAdRu4gm5k8v", 2455 | "colab_type": "text" 2456 | }, 2457 | "source": [ 2458 | "# **11**. 7-Zip + UNRAR\n", 2459 | "\"7zip\"" 2460 | ] 2461 | }, 2462 | { 2463 | "cell_type": "code", 2464 | "metadata": { 2465 | "id": "MXv72l138scn", 2466 | "colab_type": "code", 2467 | "cellView": "form", 2468 | "colab": {} 2469 | }, 2470 | "source": [ 2471 | "#@markdown

Required: Install 7-Zip + UNRAR\n", 2472 | "!sudo apt update\n", 2473 | "!sudo apt install p7zip-full p7zip-rar unrar rar" 2474 | ], 2475 | "execution_count": 0, 2476 | "outputs": [] 2477 | }, 2478 | { 2479 | "cell_type": "code", 2480 | "metadata": { 2481 | "colab_type": "code", 2482 | "cellView": "form", 2483 | "id": "VjDJz38G9fqo", 2484 | "colab": {} 2485 | }, 2486 | "source": [ 2487 | "#@markdown

» Run to change current working directory\n", 2488 | "import os\n", 2489 | "new_dir = \"\" #@param {type:\"string\"}\n", 2490 | "\n", 2491 | "%cd \"$new_dir\"" 2492 | ], 2493 | "execution_count": 0, 2494 | "outputs": [] 2495 | }, 2496 | { 2497 | "cell_type": "code", 2498 | "metadata": { 2499 | "id": "QTmQKpsm8fFQ", 2500 | "colab_type": "code", 2501 | "cellView": "form", 2502 | "colab": {} 2503 | }, 2504 | "source": [ 2505 | "#@title » Extract Archive (.zip, .rar, .7z, etc.)\n", 2506 | "import os, sys, re\n", 2507 | "\n", 2508 | "archive_file_path = \"\" #@param {type:\"string\"}\n", 2509 | "os.environ['inputFile'] = archive_file_path\n", 2510 | "\n", 2511 | "!7z e \"$inputFile\"" 2512 | ], 2513 | "execution_count": 0, 2514 | "outputs": [] 2515 | }, 2516 | { 2517 | "cell_type": "code", 2518 | "metadata": { 2519 | "colab_type": "code", 2520 | "cellView": "form", 2521 | "id": "pWKlqyFP_qkX", 2522 | "colab": {} 2523 | }, 2524 | "source": [ 2525 | "#@title » Create .zip from Folder\n", 2526 | "import os, sys, re\n", 2527 | "\n", 2528 | "folder_path = \"\" #@param {type:\"string\"}\n", 2529 | "\n", 2530 | "output_file_path = re.search(\"^[\\/].+\\/\", folder_path)\n", 2531 | "output_file_path_raw = output_file_path.group(0)\n", 2532 | "delsplit = re.search(\"\\/(?:.(?!\\/))+$\", folder_path)\n", 2533 | "folder_name = re.sub(\"^[\\/]\", \"\", delsplit.group(0))\n", 2534 | "\n", 2535 | "os.environ['inputDir'] = folder_path\n", 2536 | "os.environ['outputPath'] = output_file_path_raw\n", 2537 | "os.environ['folderName'] = folder_name\n", 2538 | "\n", 2539 | "!7z a -tzip \"$outputPath\"/\"$folderName\".zip \"$inputDir\"" 2540 | ], 2541 | "execution_count": 0, 2542 | "outputs": [] 2543 | } 2544 | ] 2545 | } --------------------------------------------------------------------------------