Skip to content

Commit a407593

Browse files
committed
closes #194, resolved #204, resolved #205, resolved #207, resolved #208, resolved #210, resolved #212; proxy API kinda resolves #202, watchdog for urls.txt and search.txt, proxy refresh interval, patch driver on every thread start, random command
1 parent 5787f2e commit a407593

File tree

5 files changed

+407
-97
lines changed

5 files changed

+407
-97
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
.venv/
22
.vscode/
33
__pycache__/
4+
patched_drivers/
45
database.db
56
database_backup.db
67
config.json

README.md

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,40 @@ Simple program to increase YouTube views written in Python. Works with live stre
4040
* High speed Internet Connection
4141
* Good proxy list (http, https, socks4, socks5)
4242
* Google Chrome installed on your OS (not Chromium)
43-
* Chrome driver will be downloaded automatically by undetected-chromedriver
43+
44+
# Features
45+
* YouTube default, live streaming and YouTube Music support
46+
* Multithreaded and Dynamic thread support
47+
* Auto download chrome driver
48+
* Patch chrome driver on the start of every thread by undetected-chromedriver
49+
* Proxy support
50+
* location : text file (must be on path) / proxy API (should work with most of the proxy providers)
51+
* type : http, https, socks4, socks5
52+
* format : `ip:port`, `user:pass@ip:port`, `ip:port:user:pass`
53+
* proxy refresh after a certain time specified by the user
54+
* rotating proxy support
55+
* chrome v70+ randomized user agent based on platform
56+
* canvas,audio,font,webgl fingerprint defender and IP leak prevent by webrtc control
57+
* geolocation, timezone, referer spoofing
58+
* direct link or search *keyword* on YouTube then watch the video by matching exact video *title*
59+
* modify urls.txt and search.txt on the fly without restarting program
60+
* HTTP api on localhost and a database to store view count
61+
* config.json to save settings
62+
* bypass consent page and several other pop up
63+
* save bandwidth by reducing video quality
64+
* can set higher(100%) watch duration percentage to increase *Watch time*, change playback speed
4465

4566

4667
# Proxies
4768
*[IPRoyal](https://iproyal.com?r=18862) offers datacenter and residential proxies. The Royal Residential proxies have a large pool with addresses in over 160 countries all over the world, so they can generate a massive number of views. IPRoyal agreed to provide a huge discount for my script users, so the price will be as low as 0.60USD/GB! To get this incredible 80% discount for Royal Residential proxies, use the discount code: `youtube80`*
4869

4970

5071
* ## Free Proxy
51-
Try not to use free proxies. But if you have a paid subscription and you want to use authenticated IP feature, then you can use the free proxy category.
72+
Try not to use free proxies. But if you have a paid subscription and you want to use authenticated IP feature, then you can use the free proxy category. Provide your text file path (where you saved the proxies) when the script asks for a proxy file name or a proxy API.
5273
N.B: Available for **http(s)/socks4/socks5**
5374

5475
* ## Premium Proxy
55-
Proxies with authentication can also be done. To do so put your proxies in this format `username:password@ipaddress:port`or `ipaddress:port:username:password` in a text file. Every single line will contain a single proxy. Provide your text file path when the script asks for a proxy file name.
76+
Proxies with authentication can also be done. To do so put your proxies in this format `username:password@ipaddress:port`or `ipaddress:port:username:password` in a text file. Every single line will contain a single proxy. Provide your text file path when the script asks for a proxy file name or a proxy API.
5677

5778
N.B: Only available for **http** type proxy.
5879

@@ -61,7 +82,9 @@ Simple program to increase YouTube views written in Python. Works with live stre
6182
N.B: Available for **http(s)/socks4/socks5**
6283

6384
Or direct use username:password combo like this `username:password@ipaddress:port` or `ipaddress:port:username:password` as Main Gateway.
85+
6486
N.B: Only available for **http** type proxy.
87+
You can use proxy API too.
6588

6689
# HTTP API
6790
Live logs fetched every 10 seconds and statistics in graphs are available on http://localhost:5000/ .Or [http://ip_of_your_pc:5000/](http://ip_of_your_pc:5000/) use this to access from another device under same network. A SQLite Database is being used to store your generated views from this script.
@@ -82,13 +105,13 @@ Simple program to increase YouTube views written in Python. Works with live stre
82105

83106

84107
# Live Stream
85-
From now on, this script supports live streams too. Just use this script as you would for the already uploaded video. Script will automatically know if your video is live. Just bear in mind, you need a **high-end pc** for higher threads to get more viewers.
108+
This script supports live streams too. Just use this script as you would for the already uploaded video. Script will automatically know if your video is live. Just bear in mind, you need a **high-end pc** for higher threads to get more viewers.
86109
Basically, script will check every 60 secs if youtube shows `x watching now` is present. If your live stream ends, script will check 5 times to be sure. In another word, after your live stream ends, script takes 5 minutes to close the driver.
87110

88111
If you have never used this script before, use this first for an already uploaded video. This way, you will have a better understanding of how this script works. To do so, keep reading.
89112

90113
# YouTube Music
91-
Can generate views on YouTube Music too. In **urls.txt** put your music link like this `https://music.youtube.com/watch?v=xxxxx`. Script will automatically load YouTube Music when it sees link have `music.youtube.com`. **Search feature is not available for this.** So you need to either empty or delete the search.txt otherwise it will start searching videos in default YouTube.
114+
Can generate views on YouTube Music too. In **urls.txt** put your music link like this `https://music.youtube.com/watch?v=xxxxx`. Script will automatically load YouTube Music when it sees link have `music.youtube.com`. **Search feature is not available for this.** So you need to empty the search.txt otherwise it will start searching videos in default YouTube.
92115

93116
# Windows
94117
* ## Binary Release

config.py

Lines changed: 91 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,20 @@ class bcolors:
1919

2020
def create_config():
2121
print(bcolors.WARNING + 'Your preferences will be saved so that you don\'t need to answer these questions again.' + bcolors.ENDC)
22-
print(bcolors.WARNING + 'Just Hit Enter to accept default or recommended values without typing anything\n' + bcolors.ENDC)
22+
print(bcolors.WARNING + 'Just Hit Enter to accept default or recommended values without typing anything.' + bcolors.ENDC)
2323

2424
config = {}
2525
port = 5000
2626
auth_required = False
27+
proxy_api = False
2728

2829
http_api = str(input(
29-
bcolors.OKBLUE + 'Do you want to enable a HTTP api on local server? (default=Yes) [Yes/no] : ' + bcolors.ENDC)).lower()
30+
bcolors.OKBLUE + '\nDo you want to enable a HTTP API on local server? (default=Yes) [Yes/no] : ' + bcolors.ENDC)).lower()
3031

3132
if http_api == 'y' or http_api == 'yes' or http_api == '':
3233
enabled = True
3334
port = input(bcolors.OKCYAN +
34-
'Enter a free port (default=5000) : ' + bcolors.ENDC)
35+
'\nEnter a free port (default=5000) : ' + bcolors.ENDC)
3536
if port == '':
3637
port = 5000
3738
else:
@@ -47,46 +48,56 @@ def create_config():
4748
}
4849

4950
database = str(input(
50-
bcolors.OKBLUE + 'Do you want to store your daily generated view counts in a Database ? (default=Yes) [Yes/no] : ' + bcolors.ENDC)).lower()
51+
bcolors.OKBLUE + '\nDo you want to store your daily generated view counts in a Database ? (default=Yes) [Yes/no] : ' + bcolors.ENDC)).lower()
5152

52-
if database == 'y' or database == 'yes':
53+
if database == 'y' or database == 'yes' or database == "":
5354
database = True
5455
else:
5556
database = False
5657
config["database"] = database
5758

58-
views = int(input(bcolors.WARNING + 'Amount of views : ' + bcolors.ENDC))
59+
views = int(input(bcolors.WARNING + '\nAmount of views : ' + bcolors.ENDC))
5960
config["views"] = views
61+
62+
print(bcolors.WARNING + '\nMinimum and Maximum watch duration percentages have no impact on live streams.' + bcolors.ENDC)
63+
print(bcolors.WARNING + 'For live streaming, script will play the video until the stream is finished.' + bcolors.ENDC)
6064

61-
minimum = input(bcolors.WARNING + 'Minimum watch duration in percentage (default=85) : ' + bcolors.ENDC)
65+
minimum = input(
66+
bcolors.WARNING + '\nMinimum watch duration in percentage (default = 85) : ' + bcolors.ENDC)
6267
if minimum == '':
6368
minimum = 85.0
6469
else:
6570
minimum = float(minimum)
6671
config["minimum"] = minimum
6772

68-
maximum = input(bcolors.WARNING + 'Maximum watch duration in percentage (default=95) : ' + bcolors.ENDC)
73+
maximum = input(
74+
bcolors.WARNING + '\nMaximum watch duration in percentage (default = 95) : ' + bcolors.ENDC)
6975
if maximum == '':
7076
maximum = 95.0
7177
else:
7278
maximum = float(maximum)
73-
config["maximum"] = maximum
79+
config["maximum"] = maximum
7480

75-
category = input(bcolors.OKCYAN + "What's your proxy category? " +
81+
category = input(bcolors.OKCYAN + "\nWhat's your proxy category? " +
7682
"[F = Free (without user:pass), P = Premium (with user:pass), R = Rotating Proxy] : " + bcolors.ENDC).lower()
7783

7884
if category == 'f':
7985
handle_proxy = str(input(
80-
bcolors.OKBLUE + 'Let YouTube Viewer handle proxies ? (recommended=No) [No/yes] : ' + bcolors.ENDC)).lower()
86+
bcolors.OKBLUE + '\nLet YouTube Viewer handle proxies ? (recommended=No) [No/yes] : ' + bcolors.ENDC)).lower()
8187

8288
if handle_proxy == 'y' or handle_proxy == 'yes':
8389
filename = False
8490
proxy_type = False
91+
8592
else:
8693
filename = input(bcolors.OKCYAN +
87-
'Enter your proxy file name: ' + bcolors.ENDC)
94+
'\nEnter your proxy File Name or Proxy API link : ' + bcolors.ENDC)
95+
96+
if 'http://' in filename or 'https://' in filename:
97+
proxy_api = True
98+
8899
handle_proxy = str(input(
89-
bcolors.OKBLUE + "Select proxy type [1 = HTTP , 2 = SOCKS4, 3 = SOCKS5, 4 = ALL] : " + bcolors.ENDC)).lower()
100+
bcolors.OKBLUE + "\nSelect proxy type [1 = HTTP , 2 = SOCKS4, 3 = SOCKS5, 4 = ALL] : " + bcolors.ENDC)).lower()
90101

91102
if handle_proxy == '1':
92103
proxy_type = 'http'
@@ -97,26 +108,40 @@ def create_config():
97108
elif handle_proxy == '4':
98109
proxy_type = False
99110
else:
100-
print(
101-
'Please input 1 for HTTP, 2 for SOCKS4, 3 for SOCKS5 and 4 for ALL proxy type')
111+
input(
112+
'\nPlease input 1 for HTTP, 2 for SOCKS4, 3 for SOCKS5 and 4 for ALL proxy type ')
102113
sys.exit()
103114

104115
elif category == 'p' or category == 'r':
105116
if category == 'r':
117+
print(bcolors.WARNING + '\nIf you use the Proxy API link, script will scrape the proxy list on each thread start.' + bcolors.ENDC)
118+
print(bcolors.WARNING + 'And will use one proxy randomly from that list to ensure session management.' + bcolors.ENDC)
106119
filename = input(bcolors.OKCYAN +
107-
'Enter your Rotating Proxy service Main Gateway : ' + bcolors.ENDC)
120+
'\nEnter your Rotating Proxy service Main Gateway or Proxy API link : ' + bcolors.ENDC)
121+
122+
if 'http://' in filename or 'https://' in filename:
123+
proxy_api = True
124+
auth_required = input(bcolors.OKCYAN +
125+
'\nProxies need authentication? (default=No) [No/yes] : ' + bcolors.ENDC).lower()
126+
if auth_required == 'y' or auth_required == 'yes' or auth_required == "":
127+
auth_required = True
128+
proxy_type = 'http'
129+
else:
130+
auth_required = False
108131

109-
if '@' in filename:
110-
auth_required = True
111-
proxy_type = 'http'
112-
elif filename.count(':') == 3:
113-
split = filename.split(':')
114-
filename = f'{split[2]}:{split[-1]}@{split[0]}:{split[1]}'
115-
auth_required = True
116-
proxy_type = 'http'
117132
else:
133+
if '@' in filename:
134+
auth_required = True
135+
proxy_type = 'http'
136+
elif filename.count(':') == 3:
137+
split = filename.split(':')
138+
filename = f'{split[2]}:{split[-1]}@{split[0]}:{split[1]}'
139+
auth_required = True
140+
proxy_type = 'http'
141+
142+
if not auth_required:
118143
handle_proxy = str(input(
119-
bcolors.OKBLUE + "Select proxy type [1 = HTTP , 2 = SOCKS4, 3 = SOCKS5] : " + bcolors.ENDC)).lower()
144+
bcolors.OKBLUE + "\nSelect proxy type [1 = HTTP , 2 = SOCKS4, 3 = SOCKS5] : " + bcolors.ENDC)).lower()
120145

121146
if handle_proxy == '1':
122147
proxy_type = 'http'
@@ -125,63 +150,87 @@ def create_config():
125150
elif handle_proxy == '3':
126151
proxy_type = 'socks5'
127152
else:
128-
print(
129-
'Please input 1 for HTTP, 2 for SOCKS4 and 3 for SOCKS5 proxy type')
153+
input(
154+
'\nPlease input 1 for HTTP, 2 for SOCKS4 and 3 for SOCKS5 proxy type ')
130155
sys.exit()
156+
131157
else:
132158
filename = input(bcolors.OKCYAN +
133-
'Enter your proxy file name: ' + bcolors.ENDC)
159+
'\nEnter your proxy File Name or Proxy API link : ' + bcolors.ENDC)
134160
auth_required = True
135161
proxy_type = 'http'
136-
162+
if 'http://' in filename or 'https://' in filename:
163+
proxy_api = True
137164
else:
138-
print('Please input F for Free, P for Premium and R for Rotating proxy')
165+
input('\nPlease input F for Free, P for Premium and R for Rotating proxy ')
139166
sys.exit()
140167

168+
refresh = -1
169+
if category != 'r':
170+
refresh = float(input(
171+
bcolors.OKCYAN+'\nEnter a interval to reload proxies from File or API (in minute) : ' + bcolors.ENDC))
172+
141173
config["proxy"] = {
142174
"category": category,
143175
"proxy_type": proxy_type,
144176
"filename": filename,
145177
"authentication": auth_required,
178+
"proxy_api": proxy_api,
179+
"refresh": refresh
146180
}
147181

148182
gui = str(input(
149-
bcolors.OKCYAN + 'Do you want to run in headless(background) mode? (recommended=No) [No/yes] : ' + bcolors.ENDC)).lower()
183+
bcolors.OKCYAN + '\nDo you want to run in headless(background) mode? (recommended=No) [No/yes] : ' + bcolors.ENDC)).lower()
150184

151185
if gui == 'y' or gui == 'yes':
152186
background = True
153187
else:
154188
background = False
155189

156190
bandwidth = str(input(
157-
bcolors.OKBLUE + 'Reduce video quality to save Bandwidth? (recommended=No) [No/yes] : ' + bcolors.ENDC)).lower()
191+
bcolors.OKBLUE + '\nReduce video quality to save Bandwidth? (recommended=No) [No/yes] : ' + bcolors.ENDC)).lower()
158192

159193
if bandwidth == 'y' or bandwidth == 'yes':
160194
bandwidth = True
161195
else:
162196
bandwidth = False
163197

164-
threads = input(
165-
bcolors.OKCYAN+'Threads [Amount of chrome driver you want to use] (recommended = 5): ' + bcolors.ENDC)
166-
if threads == '':
167-
threads = 5
198+
playback_speed = input(
199+
bcolors.OKBLUE + '\nChoose Playback speed [1 = Normal(1x), 2 = Slow(random .25x, .5x, .75x), 3 = Fast(random 1.25x, 1.5x, 1.75x)] (default = 1) : ' + bcolors.ENDC)
200+
if playback_speed == "":
201+
playback_speed = 1
202+
else:
203+
playback_speed = int(playback_speed)
204+
205+
print(bcolors.WARNING +
206+
'\nScript will dynamically update thread amount when proxy reload happens.' + bcolors.ENDC)
207+
print(bcolors.WARNING + 'If you wish to use the same amount of threads all the time, enter the same number in Maximum and Minimum threads.' + bcolors.ENDC)
208+
max_threads = input(
209+
bcolors.OKCYAN + '\nMaximum Threads [Amount of chrome driver you want to use] (recommended = 5): ' + bcolors.ENDC)
210+
if max_threads == '':
211+
max_threads = 5
168212
else:
169-
threads = int(threads)
213+
max_threads = int(max_threads)
170214

171-
if enabled:
172-
threads += 1
215+
min_threads = input(
216+
bcolors.OKCYAN + '\nMinimum Threads [Amount of chrome driver you want to use] (recommended = 2): ' + bcolors.ENDC)
217+
if min_threads == '':
218+
min_threads = 2
219+
else:
220+
min_threads = int(min_threads)
173221

174222
config["background"] = background
175223
config["bandwidth"] = bandwidth
176-
config["threads"] = threads
224+
config["playback_speed"] = playback_speed
225+
config["max_threads"] = max_threads
226+
config["min_threads"] = min_threads
177227

178228
json_object = json.dumps(config, indent=4)
179229

180-
# Writing to sample.json
181230
with open("config.json", "w") as outfile:
182231
outfile.write(json_object)
183232

184-
print(bcolors.OKGREEN + 'Your preferences are saved in config.json. You can always create a new config file from youtube_viewer.py' + bcolors.ENDC)
233+
print(bcolors.OKGREEN + '\nYour preferences are saved in config.json. You can always create a new config file from youtube_viewer.py' + bcolors.ENDC)
185234
print(bcolors.OKGREEN + 'Or by running `python config.py` ' + bcolors.ENDC)
186235

187236

requirements.txt

54 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)