-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
173 lines (132 loc) · 6.11 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# This script will automatically open chrome, create a new tab,
# then go to HoyoLab's daily forum rewards page
# It will then collect your daily reward for you
# And close the created tab
# NOTE: If your chosen browser is already open, ensure this script runs on the same monitor
# The active browser window is on, otherwise it won't provide the desired result
from calendar import monthrange
from math import floor, ceil
import pyautogui as pag
import datetime as dt
import subprocess
import config
import shlex
import time
# Complete prepwork needed to collect reward
def setup_page():
# Move cursor to center of page, this ensures it will scroll properly
pag.moveTo(pag.size().width / 2, pag.size().height / 2)
# Scroll down to get the full calendar in view
pag.scroll(-1 * (floor(pag.size().height / 2)) + config.BOOTSTRAP_HEIGHT)
time.sleep(config.SHORT_LOAD)
# Zoom out x steps to get the full calendar in view
for i in range(config.ZOOM_STEP):
pag.hotkey('ctrlleft', '-')
# Destroy the open page and reset any changes made
def destroy_page():
# Zoom back to the user's original zoom level
for i in range(config.ZOOM_STEP):
pag.hotkey('ctrlleft', '+')
# Chrome hotkey to close tab
pag.hotkey('ctrlleft', 'w')
# Locate and drag the cursor to today's reward
def find_reward():
i, x, y = 0, 0, 0
searching = True
try:
# Search for today's reward
rewards = list(pag.locateAllOnScreen('assets/indicator.png', grayscale=True, confidence=config.CONFIDENCE))
# Account for UTC +8 Offset
now = dt.datetime.utcnow() + dt.timedelta(hours=8)
month_length = monthrange(now.year, now.month)[1]
# If we didn't find any rewards, throw an error
if rewards is None:
raise pag.ImageNotFoundException('Could not locate rewards')
# We found more rewards than actually exist, throw an error
elif len(rewards) > month_length:
raise pag.ImageNotFoundException('Too many rewards found')
# We have not found today's reward on screen
if now.day > len(rewards):
while searching:
# Scroll down to next row
pag.scroll(-1 * config.VERTICAL_OFFSET)
time.sleep(config.SHORT_LOAD)
# Scan page again for rewards
rewards = list(pag.locateAllOnScreen('assets/indicator.png', grayscale=True, confidence=config.CONFIDENCE))
# If the day is on the screen
# After scrolling, account for week lost in the view
if now.day - (i * 7) <= len(rewards):
# Decrement index by one to account for list starting at 0 but days starting at 1
x, y = pag.center(rewards[(now.day % 7) - 1])
# Get number of rows on screen
rows_visible = ceil(len(rewards) / 7)
# Calculate the correct y to click at
# The y we get from center will go to shit
y = config.VERTICAL_OFFSET * rows_visible
searching = False
# If we find more reward icons than days in the month something went wrong, throw error
if len(rewards) > month_length or i > config.MAX_SEARCHES:
raise pag.ImageNotFoundException('Too many rewards found')
# If we have searched x times and can't find it, throw error
elif i > config.MAX_SEARCHES:
raise pag.ImageNotFoundException('Reward not found within search period')
i += 1
# Today's reward was within view at start
else:
# We know where today's icon is
x, y = pag.center(rewards[now.day - 1])
# Move cursor to location, accounting for specified offsets
# Tween makes it look more human (kinda not really, but less bot-like)
pag.moveTo(x + config.CLICK_X_OFFSET, y + config.CLICK_Y_OFFSET, duration=config.MOVEMENT_DURATION,
tween=pag.easeInOutExpo)
print('Collected reward')
del rewards
except pag.ImageNotFoundException as infe:
# The indicator was not found
pag.alert("Today's reward could not be found. Have you already claimed it?")
# Save error to console
print(infe)
# Reset the user's zoom
for i in range(config.ZOOM_STEP):
pag.hotkey('ctrlleft', '+')
print('Collection failed, aborting...')
# Close the current tab
pag.hotkey('ctrlleft', 'w')
# Exit the program
exit()
# Handle confirming and collecting reward
def collect_reward():
# Clicking opens confirmation menu
pag.click()
def main():
print('Opening website...')
# Open chrome as a subprocess using the current user accounts
# Theoretically this works with any browser, only tested with Chrome
proc = subprocess.Popen(shlex.split(rf'"{config.BROWSER}" "{config.URL}"'))
# Wait x seconds to make sure the page loads
time.sleep(config.TIME_LOAD_PAGE)
# Kill the subprocess, it's no longer needed
proc.kill()
# Now that the page is loaded, prepare it
setup_page()
# Wait x second(s) after setup for safetyyyyyy
time.sleep(config.SHORT_LOAD)
# Go to today's reward location on screen
find_reward()
# Perform any necessary actions to collect reward
collect_reward()
# Wait x seconds after collecting reward
time.sleep(config.CONFIRM_LOAD)
print('Closing website')
destroy_page()
# Run at least once, on start
main()
while config.RUN_DAILY:
# Calculate how long to wait until next execution
# UTC is unnecessary, system time works fine as this is for the end-user only
now = dt.datetime.now()
tomorrow = now + dt.timedelta(hours=config.RUN_INTERVAL)
print(f'Going to sleep. Next run on {tomorrow.strftime("%b %d, %Y at %H:%M:%S")}')
time.sleep((tomorrow - now).total_seconds())
# Run script
main()