diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index b730ea7..f130f16 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -1,6 +1,8 @@
-name: Test
+name: Upload Videos
on:
- push
+ push:
+ branches:
+ - test
jobs:
build:
@@ -11,9 +13,16 @@ jobs:
uses: actions/checkout@v2
- name: Configure environment
- run: echo AUTH_TOKEN=${{ secrets.AUTH_TOKEN }} >> .env
+ run: |
+ echo AUTH_TOKEN=${{ secrets.AUTH_TOKEN }} >> .env
+ echo CLIENT_ID=${{ secrets.CLIENT_ID }} >> .env
+ echo CLIENT_SECRET=${{ secrets.CLIENT_SECRET }} >> .env
+ echo REFRESH_TOKEN=${{ secrets.REFRESH_TOKEN }} >> .env
- name: Run the script
run: |
+ chmod +x download_ngrok.sh
+ ./download_ngrok.sh ${{ secrets.NGROK_TOKEN }}
chmod +x ./script.sh
./script.sh
+
diff --git a/download_ngrok.sh b/download_ngrok.sh
new file mode 100755
index 0000000..10506da
--- /dev/null
+++ b/download_ngrok.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+url="https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-linux-amd64.tgz"
+wget $url -O ngrok.tgz
+tar -xvf ngrok.tgz
+rm -rf ngrok.tgz
+chmod +x ngrok
+./ngrok config add-authtoken $1
+
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..269a5b9
--- /dev/null
+++ b/index.html
@@ -0,0 +1,134 @@
+
+
+
+
+
+ HTML Form
+
+
+
+ Google ile Giriş Yap
+
+
+
+
+
+
+
+
+
+
diff --git a/runserver.sh b/runserver.sh
new file mode 100755
index 0000000..879a0ac
--- /dev/null
+++ b/runserver.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+./ngrok http 8000 > /dev/null &
+pid=$!
+
+sleep 10
+
+url=$(curl -sq http://localhost:4045/api/tunnels | jq -r '.tunnels[0].public_url')
+if [ -z "$url" ]; then
+ url=$(curl -sq http://localhost:4040/api/tunnels | jq -r '.tunnels[0].public_url')
+fi
+if [ -z "$url" ]; then
+ echo "Failed to get URL"
+ exit 1
+fi
+
+echo "Server is live at $url"
+
+pip3 install -r requirements.txt
+python3 server.py
+
+# kill ngrok
+kill $pid
+pkill -9 ngrok
diff --git a/script.sh b/script.sh
old mode 100644
new mode 100755
index ee8bdd8..35fbb7d
--- a/script.sh
+++ b/script.sh
@@ -1,5 +1,10 @@
#!/bin/bash
+chmod +x runserver.sh
+./runserver.sh
+exit 0
+
+
# This script will be executed inside the container
pip3 install -r requirements.txt
diff --git a/server.py b/server.py
new file mode 100644
index 0000000..ef3ab95
--- /dev/null
+++ b/server.py
@@ -0,0 +1,75 @@
+from http import server
+import json
+from upload_video import DownloadVideos, GetRefreshTokenFromCode
+
+class MyHandler(server.BaseHTTPRequestHandler):
+ def do_GET(self):
+ # send index.html file to client
+ self.send_response(200)
+ self.send_header('Content-type', 'text/html')
+ self.end_headers()
+ with open('index.html', 'rb') as f:
+ self.wfile.write(f.read())
+
+ def do_POST(self):
+ # request body parameters
+ # token (received from client)
+ # List of videos (received from client)
+
+ print("POST request received")
+
+ content_length = int(self.headers['Content-Length'])
+ post_data = self.rfile.read(content_length)
+
+ print("Parsing data...")
+ data = json.loads(post_data.decode('utf-8'))
+ code = data['code']
+ videos = data['videos']
+
+ print("videos[0]:", videos[0])
+
+ print("Validating input...")
+ # validate input
+ assert type(code) == str
+ assert type(videos) == list
+ for video in videos:
+ assert type(video) == dict
+ assert 'title' in video
+ assert 'id' in video
+
+ # get refresh token from code
+
+ print("Getting refresh token...", flush = True)
+ if not code:
+ self.send_response(400)
+ self.end_headers()
+ self.wfile.write(b'Error: Code not found')
+ return
+ try:
+ refresh_token = GetRefreshTokenFromCode(code)
+ except Exception as e:
+ print("Error getting refresh token:", e)
+ self.send_response(500)
+ # data = {'error': 'Error getting refresh token'}
+ self.end_headers()
+ self.wfile.write(b'Error getting refresh token: ' + str(e).encode('utf-8'))
+ return
+
+ print("Downloading videos...", flush = True)
+ self.send_response(200)
+ self.end_headers()
+ self.wfile.write(b'Videos downloading...')
+ # send response to client
+ self.finish()
+
+ DownloadVideos(refresh_token, videos)
+
+ exit(0)
+
+
+server_address = ('', 8000)
+httpd = server.HTTPServer(server_address, MyHandler)
+httpd.serve_forever()
+
+
+
diff --git a/upload_video.py b/upload_video.py
index c60c11c..ddf6b93 100644
--- a/upload_video.py
+++ b/upload_video.py
@@ -1,11 +1,34 @@
import json
import os
+import re
from dotenv import load_dotenv
import requests
+import time
+import subprocess
# Load environment variables
load_dotenv()
+
+def get_access_token(refresh_token = None):
+ # Get access token from a refresh token
+ # Return a tuple of (access_token, expires_in)
+ refresh_token = refresh_token or os.getenv('REFRESH_TOKEN')
+ client_id = os.getenv('CLIENT_ID')
+ client_secret = os.getenv('CLIENT_SECRET')
+ r = requests.post('https://oauth2.googleapis.com/token', data={
+ 'client_id': client_id,
+ 'client_secret': client_secret,
+ 'refresh_token': refresh_token,
+ 'grant_type': 'refresh_token'
+ })
+ print(f"Getting access token: {r.status_code}")
+ if not r.status_code == 200:
+ print("Failed to get access token!")
+ print(r.content)
+ # print(r.json())
+ return r.json()['access_token'], r.json()['expires_in']
+
def load_videos(path):
# Load videos from a path
# Return a list of videos
@@ -18,16 +41,42 @@ def load_videos(path):
def download_video(title, url):
# Download a video from a url
# Return a video object
- os.system(f"curl '{url}' -o '{title}.mp4'")
+ print(f"Downloading video: {title}", flush = True)
+ os.system(f"curl -s '{url}' -o '{title}.mp4'")
def check_if_auth_code_valid(auth_code):
r = requests.get(f'https://youtube.googleapis.com/youtube/v3/videos?part=snippet,contentDetails,statistics&id=Ks-_Mh1QhMc&key={auth_code}')
print(f"Checking if auth code is valid: {r.status_code}")
- print(r.content)
+ if not r.status_code == 200:
+ print("Auth code is not valid!")
+ print(r.content)
+ assert r.status_code == 200
+
+def get_download_link(video_id):
+ main_url = f'https://video.sibnet.ru/shell.php?videoid={video_id}'
+ r = requests.get(main_url)
assert r.status_code == 200
+ url = re.search(b"src: \"(.*)\", type: \"video/mp4\"", r.content).group(1).decode()
+ url = f"https://video.sibnet.ru{url}"
+ user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
+
+ r = requests.head(url, headers={'Referer': main_url, 'User-Agent': user_agent}, allow_redirects=False)
+ if not r.status_code == 302:
+ print("Failed to get download link!")
+ print(r.headers)
+ print(r.content)
+ url = r.headers.get('Location')[2:]
+ url = f"https://{url}"
+
+ r = requests.get(url, headers={'User-Agent': user_agent}, allow_redirects=False)
+ url = r.headers.get('Location')
+ print(f"Getting download link: {r.status_code}", flush=True)
+ return url
+
def create_resumable_upload(auth_token, video_len, title):
- r = requests.post(f"https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&part=snippet,status,contentDetails&key={auth_token}", headers={
+ r = requests.post("https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&part=snippet,status,contentDetails", headers={
+ 'Authorization': f'Bearer {auth_token}',
'Content-Type': 'application/json; charset=UTF-8',
'X-Upload-Content-Length': video_len,
'X-Upload-Content-Type': 'video/mp4'
@@ -40,29 +89,90 @@ def create_resumable_upload(auth_token, video_len, title):
'privacyStatus': 'private'
}
})
-
- print(r.status_code)
- print(r.headers)
+ print(f"Creating resumable upload: {r.status_code}", flush = True)
+ if not r.status_code == 200:
+ print("Failed to create resumable upload!", flush=True)
+ print(r.content, flush=True)
+ # print(r.headers)
return r.headers['Location']
def upload_video(location, title, auth_token, video_len):
+ print(f"Uploading video: {title}, length: {video_len}", flush = True)
video_bin = open(f'{title}.mp4', 'rb').read()
r = requests.put(location, data=video_bin, headers={
- 'Authorization:': f'Bearer {auth_token}',
+ 'Authorization': f'Bearer {auth_token}',
'Content-Type': 'video/mp4',
'Content-Length': video_len
})
+ print("Uploading success, status code:", r.status_code, flush=True)
+
+def delete_video(title):
+ print(f"Deleting video from container: {title}", flush=True)
+ try:
+ name = f"{title}.mp4"
+ subprocess.call(["rm", name])
+ except Exception as e:
+ print("rm failed, error:", e)
+
+def main():
+ auth_token = os.getenv('AUTH_TOKEN')
+ assert auth_token != None
+ # check_if_auth_code_valid(auth_token)
+ videos = load_videos('videos.json')
+
+ time_now = time.time()
+ auth_token, expires_in = get_access_token()
+
+ for video in videos:
+ title = video['title']
+ video_id = int(video['id'])
+ url = get_download_link(video_id)
+ download_video(title, url)
+ video_len = str(os.path.getsize(f'{title}.mp4'))
+ if time.time() - time_now > expires_in:
+ auth_token, expires_in = get_access_token()
+ location = create_resumable_upload(auth_token, video_len, title)
+ upload_video(location, title, auth_token, video_len)
+
+def DownloadVideos(refresh_token, videos):
+ time_now = time.time()
+ auth_token, expires_in = get_access_token(refresh_token)
+ print("Videos:", videos, flush=True)
+ for video in videos:
+ title = video['title']
+ video_id = int(video['id'])
+ print(f"Video: {title}", flush=True)
+ url = get_download_link(video_id)
+ download_video(title, url)
+ video_len = str(os.path.getsize(f'{title}.mp4'))
+ if time.time() - time_now > expires_in:
+ auth_token, expires_in = get_access_token()
+ location = create_resumable_upload(auth_token, video_len, title)
+ upload_video(location, title, auth_token, video_len)
+ delete_video(title)
+
+def GetRefreshTokenFromCode(code):
+ client_id = os.getenv('CLIENT_ID')
+ if not client_id:
+ raise Exception("Client ID not found!")
+ client_secret = os.getenv('CLIENT_SECRET')
+ if not client_secret:
+ raise Exception("Client Secret not found!")
+ r = requests.post('https://oauth2.googleapis.com/token', data={
+ 'code': code,
+ 'client_id': client_id,
+ 'client_secret': client_secret,
+ 'redirect_uri': 'http://127.0.0.1:8000/callback',
+ 'grant_type': 'authorization_code'
+ })
+ print(f"Getting refresh token from code: {r.status_code}")
+ if not r.status_code == 200:
+ print("Failed to get refresh token!")
+ print(r.content)
+ raise Exception(r.content)
+ return r.json()['refresh_token']
-auth_token = os.getenv('AUTH_TOKEN')
-assert auth_token != None
-check_if_auth_code_valid(auth_token)
-videos = load_videos('videos.json')
+if __name__ == '__main__':
+ main()
-for video in videos:
- title = video['title']
- url = video['url']
- download_video(title, url)
- video_len = str(os.path.getsize(f'{title}.mp4'))
- location = create_resumable_upload(auth_token, video_len, title)
- upload_video(location, title, auth_token, video_len)
diff --git a/videos.json b/videos.json
index 214ebfe..49dc2d7 100644
--- a/videos.json
+++ b/videos.json
@@ -1,6 +1,10 @@
[
{
- "title": "Re Zero Part 11",
- "url": "https://dv8-2.sibnet.ru/44/50/43/4450436.mp4?st=aigsKKNCwNbeFo_M6avH5Q&e=1701010000&stor=8&noip=1"
+ "title": "Jujutsu Kaisen 23. Bölüm",
+ "id": "4265338"
+ },
+ {
+ "title": "Jujutsu Kaisen 24. Bölüm",
+ "id": "4772671"
}
]