From d0ae2a80db2941878678d0a960cee3e25ab5c5b7 Mon Sep 17 00:00:00 2001 From: horacio9a Date: Mon, 18 Mar 2024 10:14:52 +0100 Subject: [PATCH] v.2.1.0 Cam4 Anonymous All Modes Recorder for Python3.12 --- c43.py | 502 ++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 304 insertions(+), 198 deletions(-) diff --git a/c43.py b/c43.py index adcf0bc..5b4daa0 100644 --- a/c43.py +++ b/c43.py @@ -1,7 +1,7 @@ -# Cam4 Anonymous All Modes Recorder v.2.0.2 by horacio9a for Python 3.9.1 +# Cam4 FFMPEG/STREAMLINK/YTDL Anonymous All Modes Recorder v.2.1.0 by horacio9a for Python 3.12.2 # coding: utf-8 -import sys, os, urllib, urllib3, ssl, re, time, datetime, requests, random, command, livestreamer, streamlink +import sys, os, urllib, urllib3, ssl, re, time, datetime, requests, command, streamlink urllib3.disable_warnings() from urllib3 import PoolManager from urllib.parse import quote @@ -11,6 +11,7 @@ from termcolor import colored import configparser Config = configparser.ConfigParser() Config.read('config3.ini') +country_domain = Config.get('settings', 'country_domain') init() print() @@ -81,34 +82,68 @@ if mod == 'C4OW': if mod == 'C4OA': while True: try: - c4oa = int(input(colored(' => Select => <500(0) <1000(1) <1500(2) <2000(3) <2500(4) <3000(5) <3500(6) => ', 'white', 'on_blue'))) + c4oa = int(input(colored(' => Select => <250(0) <500(1) <750(2) <1000(3) <1250(4) <1500(5) <1750(6) <2000(7) <2250(8) <2500(9) <2750(10) <3000(11) => ', 'white', 'on_blue'))) print() break except ValueError: print(colored('\n => Input must be a number <=\n', 'white', 'on_red')) - if c4oa > 6: + if c4oa > 11: sys.exit() if c4oa == 0: - oa = 'OA500' + oa = 'OA250' if c4oa == 1: - oa = 'OA1000' + oa = 'OA500' if c4oa == 2: - oa = 'OA1500' + oa = 'OA750' if c4oa == 3: - oa = 'OA2000' + oa = 'OA1000' if c4oa == 4: - oa = 'OA2500' + oa = 'OA1250' if c4oa == 5: - oa = 'OA3000' + oa = 'OA1500' if c4oa == 6: - oa = 'OA3500' + oa = 'OA1750' + if c4oa == 7: + oa = 'OA2000' + if c4oa == 8: + oa = 'OA2250' + if c4oa == 9: + oa = 'OA2500' + if c4oa == 10: + oa = 'OA2750' + if c4oa == 11: + oa = 'OA3000' + + if oa == 'OA250': + while True: + try: + modellist = open(Config.get('files', 'online_all_model_list'),'r') + for (num, value) in enumerate(modellist): + if num in range (250, 3000): + break + print(' =>',(num+1),value[:-1]) + print() + mn = int(input(colored(' => Select C4 Online All Models => ', 'white', 'on_blue'))) + print() + nr_lines = sum(1 for line in open(Config.get('files', 'online_all_model_list'))) + if mn > nr_lines: + print(colored(' => Too big number <=', 'white', 'on_red')) + print() + print(colored(' => END <=', 'white','on_blue')) + sys.exit() + break + except ValueError: + print(colored('\n => Input must be a number <=\n', 'white', 'on_red')) + model = open(Config.get('files', 'online_all_model_list'), 'r').readlines()[mn-1][:-1] + print ((colored(' => Selected C4 Online All Model => {} <=', 'white', 'on_blue')).format(model)) + print() if oa == 'OA500': while True: try: modellist = open(Config.get('files', 'online_all_model_list'),'r') for (num, value) in enumerate(modellist): - if num in range (500, 5000): + if num in range (500, 3000): break print(' =>',(num+1),value[:-1]) print() @@ -127,14 +162,62 @@ if mod == 'C4OA': print ((colored(' => Selected C4 Online All Model => {} <=', 'white', 'on_blue')).format(model)) print() + if oa == 'OA750': + while True: + try: + modellist = open(Config.get('files', 'online_all_model_list'),'r') + for (num, value) in enumerate(modellist): + if num in range (750, 3000): + break + print(' =>',(num+1),value[:-1]) + print() + mn = int(input(colored(' => Select C4 Online All Models => ', 'white', 'on_blue'))) + print() + nr_lines = sum(1 for line in open(Config.get('files', 'online_all_model_list'))) + if mn > nr_lines: + print(colored(' => Too big number <=', 'white', 'on_red')) + print() + print(colored(' => END <=', 'white','on_blue')) + sys.exit() + break + except ValueError: + print(colored('\n => Input must be a number <=\n', 'white', 'on_red')) + model = open(Config.get('files', 'online_all_model_list'), 'r').readlines()[mn-1][:-1] + print ((colored(' => Selected C4 Online All Model => {} <=', 'white', 'on_blue')).format(model)) + print() + if oa == 'OA1000': while True: try: modellist = open(Config.get('files', 'online_all_model_list'),'r') for (num, value) in enumerate(modellist): - if num in range (1000, 5000): - break - print(' =>',(num+1),value[:-1]) + if num in range (1000, 3000): + break + print(' =>',(num+1),value[:-1]) + print() + mn = int(input(colored(' => Select C4 Online All Models => ', 'white', 'on_blue'))) + print() + nr_lines = sum(1 for line in open(Config.get('files', 'online_all_model_list'))) + if mn > nr_lines: + print(colored(' => Too big number <=', 'white', 'on_red')) + print() + print(colored(' => END <=', 'white','on_blue')) + sys.exit() + break + except ValueError: + print(colored('\n => Input must be a number <=\n', 'white', 'on_red')) + model = open(Config.get('files', 'online_all_model_list'), 'r').readlines()[mn-1][:-1] + print ((colored(' => Selected C4 Online All Model => {} <=', 'white', 'on_blue')).format(model)) + print() + + if oa == 'OA1250': + while True: + try: + modellist = open(Config.get('files', 'online_all_model_list'),'r') + for (num, value) in enumerate(modellist): + if num in range (1250, 3000): + break + print(' =>',(num+1),value[:-1]) print() mn = int(input(colored(' => Select C4 Online All Models => ', 'white', 'on_blue'))) print() @@ -156,9 +239,9 @@ if mod == 'C4OA': try: modellist = open(Config.get('files', 'online_all_model_list'),'r') for (num, value) in enumerate(modellist): - if num in range (1500, 5000): - break - print(' =>',(num+1),value[:-1]) + if num in range (1500, 3000): + break + print(' =>',(num+1),value[:-1]) print() mn = int(input(colored(' => Select C4 Online All Models => ', 'white', 'on_blue'))) print() @@ -175,14 +258,56 @@ if mod == 'C4OA': print ((colored(' => Selected C4 Online All Model => {} <=', 'white', 'on_blue')).format(model)) print() + if oa == 'OA1750': + while True: + try: + modellist = open(Config.get('files', 'online_all_model_list'),'r') + for (num, value) in enumerate(modellist): + if num in range (1750, 3000): + break + print(' =>',(num+1),value[:-1]) + print() + mn = int(input(colored(' => Select C4 Online All Models => ', 'white', 'on_blue'))) + print() + break + except ValueError: + print(colored('\n => Input must be a number <=\n', 'white', 'on_red')) + model = open(Config.get('files', 'online_all_model_list'), 'r').readlines()[mn-1][:-1] + print ((colored(' => Selected C4 Online All Model => {} <=', 'white', 'on_blue')).format(model)) + print() + if oa == 'OA2000': while True: try: modellist = open(Config.get('files', 'online_all_model_list'),'r') for (num, value) in enumerate(modellist): - if num in range (2000, 5000): - break - print(' =>',(num+1),value[:-1]) + if num in range (2000, 3000): + break + print(' =>',(num+1),value[:-1]) + print() + mn = int(input(colored(' => Select C4 Online All Models => ', 'white', 'on_blue'))) + print() + nr_lines = sum(1 for line in open(Config.get('files', 'online_all_model_list'))) + if mn > nr_lines: + print(colored(' => Too big number <=', 'white', 'on_red')) + print() + print(colored(' => END <=', 'white','on_blue')) + sys.exit() + break + except ValueError: + print(colored('\n => Input must be a number <=\n', 'white', 'on_red')) + model = open(Config.get('files', 'online_all_model_list'), 'r').readlines()[mn-1][:-1] + print ((colored(' => Selected C4 Online All Model => {} <=', 'white', 'on_blue')).format(model)) + print() + + if oa == 'OA2250': + while True: + try: + modellist = open(Config.get('files', 'online_all_model_list'),'r') + for (num, value) in enumerate(modellist): + if num in range (2250, 3000): + break + print(' =>',(num+1),value[:-1]) print() mn = int(input(colored(' => Select C4 Online All Models => ', 'white', 'on_blue'))) print() @@ -204,9 +329,9 @@ if mod == 'C4OA': try: modellist = open(Config.get('files', 'online_all_model_list'),'r') for (num, value) in enumerate(modellist): - if num in range (2500, 5000): - break - print(' =>',(num+1),value[:-1]) + if num in range (2500, 3000): + break + print(' =>',(num+1),value[:-1]) print() mn = int(input(colored(' => Select C4 Online All Models => ', 'white', 'on_blue'))) print() @@ -222,193 +347,174 @@ if mod == 'C4OA': model = open(Config.get('files', 'online_all_model_list'), 'r').readlines()[mn-1][:-1] print ((colored(' => Selected C4 Online All Model => {} <=', 'white', 'on_blue')).format(model)) print() - - if oa == 'OA3000': - while True: - try: - modellist = open(Config.get('files', 'online_all_model_list'),'r') - for (num, value) in enumerate(modellist): - if num in range (3000, 5000): - break - print(' =>',(num+1),value[:-1]) - print() - mn = int(input(colored(' => Select C4 Online All Models => ', 'white', 'on_blue'))) - print() - nr_lines = sum(1 for line in open(Config.get('files', 'online_all_model_list'))) - if mn > nr_lines: - print(colored(' => Too big number <=', 'white', 'on_red')) - print() - print(colored(' => END <=', 'white','on_blue')) - sys.exit() - break - except ValueError: - print(colored('\n => Input must be a number <=\n', 'white', 'on_red')) - model = open(Config.get('files', 'online_all_model_list'), 'r').readlines()[mn-1][:-1] - print ((colored(' => Selected C4 Online All Model => {} <=', 'white', 'on_blue')).format(model)) - print() - - if oa == 'OA3500': - while True: - try: - modellist = open(Config.get('files', 'online_all_model_list'),'r') - for (num, value) in enumerate(modellist): - if num in range (3500, 5000): - break - print(' =>',(num+1),value[:-1]) - print() - mn = int(input(colored(' => Select C4 Online All Models => ', 'white', 'on_blue'))) - print() - break - except ValueError: - print(colored('\n => Input must be a number <=\n', 'white', 'on_red')) - model = open(Config.get('files', 'online_all_model_list'), 'r').readlines()[mn-1][:-1] - print ((colored(' => Selected C4 Online All Model => {} <=', 'white', 'on_blue')).format(model)) - print() -url ='https://www.cam4.com/rest/v1.0/profile/{}/streamInfo'.format(model) + if oa == 'OA2750': + while True: + try: + modellist = open(Config.get('files', 'online_all_model_list'),'r') + for (num, value) in enumerate(modellist): + if num in range (2750, 3000): + break + print(' =>',(num+1),value[:-1]) + print() + mn = int(input(colored(' => Select C4 Online All Models => ', 'white', 'on_blue'))) + print() + nr_lines = sum(1 for line in open(Config.get('files', 'online_all_model_list'))) + if mn > nr_lines: + print(colored(' => Too big number <=', 'white', 'on_red')) + print() + print(colored(' => END <=', 'white','on_blue')) + sys.exit() + break + except ValueError: + print(colored('\n => Input must be a number <=\n', 'white', 'on_red')) + model = open(Config.get('files', 'online_all_model_list'), 'r').readlines()[mn-1][:-1] + print ((colored(' => Selected C4 Online All Model => {} <=', 'white', 'on_blue')).format(model)) + print() + + if oa == 'OA3000': + while True: + try: + modellist = open(Config.get('files', 'online_all_model_list'),'r') + for (num, value) in enumerate(modellist): + if num in range (3000, 3000): + break + print(' =>',(num+1),value[:-1]) + print() + mn = int(input(colored(' => Select C4 Online All Models => ', 'white', 'on_blue'))) + print() + nr_lines = sum(1 for line in open(Config.get('files', 'online_all_model_list'))) + if mn > nr_lines: + print(colored(' => Too big number <=', 'white', 'on_red')) + print() + print(colored(' => END <=', 'white','on_blue')) + sys.exit() + break + except ValueError: + print(colored('\n => Input must be a number <=\n', 'white', 'on_red')) + model = open(Config.get('files', 'online_all_model_list'), 'r').readlines()[mn-1][:-1] + print ((colored(' => Selected C4 Online All Model => {} <=', 'white', 'on_blue')).format(model)) + print() + +url ='https://{}.cam4.com/rest/v1.0/profile/{}/streamInfo'.format(country_domain, model) manager = PoolManager(10) r = manager.request('GET', url) enc = quote(r.data) dec= unquote(enc) -if 'canUseCDN":true' in dec: - hlsurl0 = dec.split('cdnURL":"')[1] - hlsurl = hlsurl0.split('"')[0] - if len(hlsurl) > 0: - try: - streamName0 = dec.split('streamName":"')[1] - streamName = streamName0.split('-')[0] - except: - sys.exit() +if len(dec) > 0: + hlsur2 = dec.split('cdnURL":"')[1] + hlsurl = hlsur2.split('"')[0] + print ((colored(' => HlsUrl => {} <=', 'white', 'on_magenta')).format(hlsurl)) + print () + try: + mode = int(input(colored(' => Mode => Exit(5) - URL(4) - YTDL(3) - SL(2) - FFMPEG(1) - PLAYER(0) => ', 'white', 'on_green'))) + except ValueError: + print() + print(colored(' => Input must be a number <=', 'white', 'on_red')) + if mode > 5: + print() + print(colored(' => Too big number <=', 'white', 'on_red')) + mod = 'EXIT' + if mode == 0: + mod = 'PLAYER' + if mode == 1: + mod = 'FFMPEG' + if mode == 2: + mod = 'SL' + if mode == 3: + mod = 'YTDL' + if mode == 4: + mod = 'URL' + if mode == 5: + mod = 'EXIT' - while True: - try: - mode = int(input(colored(' => Mode => Exit(6) - URL(5) - YTDL(4) - LS(3) - SL(2) - FFMPEG(1) - PLAYER(0) => ', 'white', 'on_green'))) - break - except ValueError: - print() - print(colored(' => Input must be a number <=', 'white', 'on_red')) - if mode > 6: - print() - print(colored(' => Too big number <=', 'white', 'on_red')) - mod = 'EXIT' - if mode == 0: - mod = 'PLAYER' - if mode == 1: - mod = 'FFMPEG' - if mode == 2: - mod = 'SL' - if mode == 3: - mod = 'LS' - if mode == 4: - mod = 'YTDL' - if mode == 5: - mod = 'URL' - if mode == 6: - mod = 'EXIT' + timestamp = str(time.strftime('%d%m%Y-%H%M%S')) + path = Config.get('folders', 'output_folder') + fn = model + '_C4_' + timestamp + fn1 = model + '_C4_' + timestamp + '.flv' + fn2 = model + '_C4_' + timestamp + '.mp4' + fn3 = model + '_C4_' + timestamp + '.ts' + fn4 = model + '_C4_' + timestamp + '.txt' + pf1 = (path + fn1) + pf2 = (path + fn2) + pf3 = (path + fn3) + pf4 = (path + fn4) + player = Config.get('files', 'player') + ffmpeg = Config.get('files', 'ffmpeg') + youtube = Config.get('files', 'youtube') + streamlink = Config.get('files', 'streamlink') - timestamp = str(time.strftime('%d%m%Y-%H%M%S')) - stime = str(time.strftime('%H:%M:%S')) - path = Config.get('folders', 'output_folder') - fn = streamName + '_C4_' + timestamp - fn1 = streamName + '_C4_' + timestamp + '.flv' - fn2 = streamName + '_C4_' + timestamp + '.mp4' - fn3 = streamName + '_C4_' + timestamp + '.ts' - fn4 = streamName + '_C4_' + timestamp + '.txt' - pf1 = (path + fn1) - pf2 = (path + fn2) - pf3 = (path + fn3) - pf4 = (path + fn4) - player = Config.get('files', 'player') - ffmpeg = Config.get('files', 'ffmpeg') - youtube = Config.get('files', 'youtube') - streamlink = Config.get('files', 'streamlink') - livestreamer = Config.get('files', 'livestreamer') + if mod == 'PLAYER': + print() + print ((colored(' => PLAYER => {} <=', 'white', 'on_magenta')).format(fn)) + print() + command = ('{} -p {} {} best'.format(streamlink, player, hlsurl)) + os.system(command) + while True: + try: + print() + prog = int(input(colored(' => Mode => URL(4) - YTDL(3) - SL(2) - FFMPEG(1) - Exit(0) => ', 'white', 'on_green'))) + break + except ValueError: + print() + print(colored(' => Input must be a number <=', 'white', 'on_red')) + print() + if prog > 4: + print() + print(colored(' => Too big number <=', 'white', 'on_red')) + mod = 'EXIT' + if prog == 0: + mod = 'EXIT' + if prog == 1: + mod = 'FFMPEG' + if prog == 2: + mod = 'SL' + if prog == 3: + mod = 'YTDL' + if prog == 4: + mod = 'URL' - if mod == 'PLAYER': - print() - print ((colored(' => PLAYER => {} <=', 'white', 'on_magenta')).format(fn)) - print() - command = ('{} -p {} {} best'.format(streamlink, player, hlsurl)) - os.system(command) - while True: - try: - print() - prog = int(input(colored(' => Mode => URL(5) - YTDL(4) - LS(3) - SL(2) - FFMPEG(1) - Exit(0) => ', 'white', 'on_green'))) - break - except ValueError: - print() - print(colored(' => Input must be a number <=', 'white', 'on_red')) - if prog > 5: - print() - print(colored(' => Too big number <=', 'white', 'on_red')) - mod = 'EXIT' - if prog == 0: - mod = 'EXIT' - if prog == 1: - mod = 'FFMPEG' - if prog == 2: - mod = 'SL' - if prog == 3: - mod = 'LS' - if prog == 4: - mod = 'YTDL' - if prog == 5: - mod = 'URL' + if mod == 'FFMPEG': + print() + print ((colored(' => FFMPEG-REC => {} <=', 'white', 'on_red')).format(pf1)) + command = '{} -hide_banner -loglevel panic -i {} -c:v copy -c:a aac -b:a 128k {}'.format(ffmpeg,hlsurl,pf1) + os.system(command) + sys.exit() - if mod == 'FFMPEG': - print() - print ((colored(' => FFMPEG-REC => {} <=', 'white', 'on_red')).format(fn1)) - command = ('{} -hide_banner -loglevel panic -i {} -c:v copy -c:a aac -b:a 128k {}'.format(ffmpeg,hlsurl,pf1)) - os.system(command) - sys.exit() + if mod == 'SL': + print() + print ((colored(' => SL-REC => {} Size ( Time @ Speed ) <=', 'white', 'on_red')).format(pf2)) + print() + command = ('{} hls://{} best -Q --hls-live-edge 1 --hls-playlist-reload-attempts 9 --hls-segment-threads 3 --hls-segment-timeout 5.0 --hls-timeout 20.0 -o {}'.format(streamlink,hlsurl,pf2)) + os.system(command) + print() + print(colored(' => END <=', 'white','on_blue')) + sys.exit() - if mod == 'SL': - print() - print ((colored(' => SL-REC => {} ( Size @ Speed ) <=', 'white', 'on_red')).format(fn2)) - print() - command = ('{} hls://{} best -Q --hls-live-edge 1 --hls-playlist-reload-attempts 9 --hls-segment-threads 3 --hls-segment-timeout 5.0 --hls-timeout 20.0 -o {}'.format(streamlink,hlsurl,pf2)) - os.system(command) - print() - print(colored(' => END <= ', 'white','on_blue')) - sys.exit() + if mod == 'YTDL': + print() + print ((colored(' => YTDL-REC => {} <=', 'white', 'on_red')).format(pf3)) + command = ('{} -i --geo-bypass --hls-use-mpegts --no-part -q --no-warnings --no-check-certificate {} -o {}'.format(youtube,hlsurl,pf3)) + os.system(command) + print() + print(colored(' => END <= ', 'white','on_blue')) + sys.exit() - if mod == 'LS': - print() - print ((colored(' => LS-REC => {} ( Size @ Speed ) <=', 'white', 'on_red')).format(fn2)) - print() - command = ('{} hlsvariant://{} best -Q -o {}'.format(livestreamer,hlsurl,pf2)) - os.system(command) - print() - print(colored(' => END <= ', 'white','on_blue')) - sys.exit() + if mod == 'URL': + print() + print((colored(' => URL => {} <=', 'white', 'on_red')).format(pf4)) + file=open(pf4,'w') + file.write(hlsurl) + file.close() + print() + print(colored(' => END <=', 'white','on_blue')) + sys.exit() - if mod == 'YTDL': - print() - print ((colored(' => YTDL-REC => {} <=', 'white', 'on_red')).format(fn3)) - command = ('{} -i --geo-bypass --hls-use-mpegts --no-part -q --no-warnings --no-check-certificate {} -o {}'.format(youtube,hlsurl,pf3)) - os.system(command) - print() - print(colored(' => END <= ', 'white','on_blue')) - sys.exit() - - if mod == 'URL': - print() - print((colored(' => URL => {} <=', 'white', 'on_green')).format(fn4)) - file=open(pf4,'w') - file.write(hlsurl) - file.close() - print() - print(colored(' => END <=', 'white','on_blue')) - sys.exit() - - if mod == 'EXIT': - print() - print(colored(' => END <=', 'white','on_blue')) - sys.exit() - - else: - sys.exit() + if mod == 'EXIT': + print() + print(colored(' => END <=', 'white','on_blue')) + sys.exit() else: print(colored(' => Model is offline or wrong name <=', 'white','on_red'))