-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnotifications.py
323 lines (292 loc) · 16 KB
/
notifications.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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
import dotenv, os, pyttsx3, pytz, datetime, genshin, asyncio, json, functools, psutil
from win11toast import toast_async
from time import localtime, strftime
ZZZn_path = os.path.dirname(os.path.realpath(__file__))
toast_async = functools.partial(toast_async, app_id="ZZZ Notifications", on_click=lambda args: None, on_dismissed=lambda args: None, on_failed=lambda args: None)
dotenv.load_dotenv(dotenv_path=f"{ZZZn_path}/settings.env")
zzz = genshin.Client()
engine = pyttsx3.init()
os.system("") # To make colors in errors always work
timezones = {"eu": "Etc/GMT-1", "as": "Etc/GMT-8", "us": "Etc/GMT+5"}
if os.path.exists("cache.json"):
pass
else:
with open("cache.json", "w", encoding='utf-8') as cache_f:
data = {
'shiyu_season': 0
}
json.dump(data, cache_f, indent=4)
if os.getenv('set_cookies_method') == 'auto':
zzz.set_browser_cookies()
elif os.getenv('set_cookies_method') == 'login':
if os.getenv('ltuid') == 0 or os.getenv('ltoken') == "":
print("\33[31mERROR | Incorrect ltuid or ltoken empty!\033[0m")
exit()
else:
zzz.set_cookies(ltuid=int(os.getenv('ltuid')), ltoken=os.getenv('ltoken'))
else:
print("\33[31mERROR | Incorrect value for \"set_cookies_method\"! \n\33[93mSet it to: \"login\" or \"auto\"\033[0m")
exit()
if os.getenv("server") not in ["eu", "us", "as"]:
print("\33[31mERROR | Incorrect value for \"server\"! \n\33[93mSet it to on of this values: \"eu\", \"us\", \"as\"\033[0m")
exit()
def margin(input, margin, milestone):
return any(int(x) <= input <= int(x) + margin for x in milestone)
def closest(input, milestone):
return min(milestone, key=lambda x: abs(int(x) - input))
async def battery():
battery_notification_send = False
battery_last_count = -1
battery_milestone_stop_notifications_until = -1
icon = {
'src': f'file://{ZZZn_path}/ico/Battery.ico',
'placement': 'appLogoOverride'
}
while(True):
ac = await zzz.get_game_accounts()
for account in ac:
if "nap" in account.game_biz:
uid = account.uid
notes = await zzz.get_zzz_notes(uid=uid)
if battery_notification_send == True:
if battery_last_count != notes.battery_charge.current:
battery_notification_send = False
if (os.getenv('battery_milestone')) == 'True':
if notes.battery_charge.current <= battery_milestone_stop_notifications_until:
battery_notification_send = True
else:
battery_milestone_stop_notifications_until = -1
if (os.getenv('battery_milestone')) == 'True':
battery_milestones = os.getenv('battery_milestones').split(', ')
if margin(notes.battery_charge.current, int(os.getenv("battery_milestones_margin")), battery_milestones):
if battery_notification_send == False:
print(f"{strftime('%H:%M:%S', localtime())} | One of your Battery Charge milestone was reached")
if os.getenv('tts') == 'True':
engine.say("One of your Battery Charge milestone was reached")
engine.runAndWait()
battery_last_count = notes.battery_charge.current
await toast_async("One of your Battery Charge milestone was reached", f"You currently have {notes.battery_charge.current} Battery Charge out of {notes.battery_charge.max}", icon=icon)
battery_notification_send = True
battery_milestone_stop_notifications_until = int(closest(notes.battery_charge.current, battery_milestones)) + int(os.getenv("battery_milestones_margin"))
else:
if battery_notification_send == False:
if notes.battery_charge.current == notes.battery_charge.max:
print(f"{strftime('%H:%M:%S', localtime())} | Your Battery Charge is FULL")
if os.getenv('tts') == 'True':
engine.say("Your Battery Charge is FULL")
engine.runAndWait()
battery_last_count = notes.battery_charge.current
await toast_async("Your Battery Charge is FULL", f"You currently have {notes.battery_charge.current} Battery Charge out of {notes.battery_charge.max}", icon=icon)
battery_notification_send = True
else:
if battery_notification_send == False:
if notes.battery_charge.current == notes.battery_charge.max:
print(f"{strftime('%H:%M:%S', localtime())} | Your Battery Charge is FULL")
if os.getenv('tts') == 'True':
engine.say("Your Battery Charge is FULL")
engine.runAndWait()
battery_last_count = notes.battery_charge.current
await toast_async("Your Battery Charge is FULL", f"You currently have {notes.battery_charge.current} Battery Charge out of {notes.battery_charge.max}", icon=icon)
battery_notification_send = True
await asyncio.sleep(480)
async def daily():
daily_last_day = -1
timezone = pytz.timezone('Etc/GMT-8')
icon = {
'src': f'file://{ZZZn_path}/ico/Daily.ico',
'placement': 'appLogoOverride'
}
while (True):
day = datetime.datetime.now(timezone).strftime('%d')
if daily_last_day != day:
try:
reward = await zzz.claim_daily_reward(game=genshin.Game.ZZZ)
except genshin.AlreadyClaimed:
daily_last_day = day
except genshin.DailyGeetestTriggered:
url = "https://act.hoyolab.com/bbs/event/signin/zzz/e202406031448091.html?act_id=e202406031448091"
print(f"\33[31mERROR | Captcha Triggerd and script couldn't collect your daily! You have to collect it yourself here {url}\033[0m")
else:
print(f"{strftime('%H:%M:%S', localtime())} | Claimed daily reward - {reward.amount}x {reward.name}")
if os.getenv('tts') == 'True':
engine.say("Collected your daily check-in reward")
engine.runAndWait()
daily_last_day = day
if os.getenv('daily_not') == 'True':
await toast_async("Collected your daily check-in reward", f"Claimed daily reward - {reward.amount}x {reward.name}", icon=icon)
await asyncio.sleep(900)
async def shop():
last_day = -1
icon = {
'src': f'file://{ZZZn_path}/ico/Shop.ico',
'placement': 'appLogoOverride'
}
while(True):
day = int(datetime.datetime.now(pytz.timezone(timezones[os.getenv("server")])).strftime('%d'))
if last_day != day:
last_day = day
if day == 1:
print(f"{strftime('%H:%M:%S', localtime())} | Shop has been reset today")
if os.getenv('tts') == 'True':
engine.say("Shop has been reset today")
engine.runAndWait()
await toast_async("Shop reset", f"Shop has been reset today", icon=icon)
await asyncio.sleep(900)
shiyu_reset = False
async def shiyu():
last_day = -1
started_between_0_3 = False
global shiyu_reset
error = False
icon = {
'src': f'file://{ZZZn_path}/ico/Shiyu.ico',
'placement': 'appLogoOverride'
}
while(True):
day = int(datetime.datetime.now(pytz.timezone(timezones[os.getenv("server")])).strftime('%d'))
hour = int(datetime.datetime.now(pytz.timezone(timezones[os.getenv("server")])).strftime('%H'))
exe = True if hour >= 4 else False
if (last_day != day and exe) or (not exe and not started_between_0_3 and day != last_day + 1):
started_between_0_3 = not started_between_0_3
last_day = day
ac = await zzz.get_game_accounts()
for account in ac:
if "nap" in account.game_biz:
uid = account.uid
try:
shiyu = await zzz.get_shiyu_defense(uid=uid)
shiyu_old = await zzz.get_shiyu_defense(uid=uid, previous=True)
except genshin.GeetestError as ex:
print(f"\33[31mERROR | Captcha triggered while fetching Shiyu Defense data. Go to your Battle Chronicle and complete a captcha for the script to be able to notify you when Shiyu Defense resets!\033[0m")
if os.getenv('tts') == 'True':
engine.say("Shiyu Defense reset data can't be collected! More information about the error is available in the console.")
engine.runAndWait()
await toast_async("Shiyu Defense Error", f"Shiyu Defense reset data can't be collected!\nMore information about the error is available in the console.", icon=icon)
return
with open("cache.json", "r", encoding='utf-8') as cache_f:
cache = json.load(cache_f)
season = cache['shiyu_season']
cache_f.close()
if shiyu.schedule_id == 0 and shiyu_old.schedule_id == 0 and error == False:
error = True
print(f"\33[31mERROR | Shiyu Defense reset data can't be collected! If you haven't completed Shiyu Defense in the previous season, both `schedule_id` values are 0, making it impossible to check if the season has changed. Complete the current season, and going forward, you will receive notifications about season resets.\033[0m")
if os.getenv('tts') == 'True':
engine.say("Shiyu Defense reset data can't be collected! More information about the error is available in the console.")
engine.runAndWait()
await toast_async("Shiyu Defense Error", f"Shiyu Defense reset data can't be collected!\nMore information about the error is available in the console.", icon=icon)
elif shiyu.schedule_id == 0 and shiyu_old.schedule_id != 0:
if season != shiyu_old.schedule_id + 1:
with open("cache.json", "w", encoding='utf-8') as cache_f:
shiyu_reset = True
cache['shiyu_season'] = shiyu_old.schedule_id + 1
json.dump(cache, cache_f, indent=4)
cache_f.close()
print(f"{strftime('%H:%M:%S', localtime())} | Shiyu Defense has been reset")
if os.getenv('tts') == 'True':
engine.say("Shiyu Defense has been reset")
engine.runAndWait()
await toast_async("Shiyu Defense reset", f"Shiyu Defense has been reset", icon=icon)
elif shiyu.schedule_id != 0 and shiyu.schedule_id != cache['shiyu_season']:
with open("cache.json", "w", encoding='utf-8') as cache_f:
cache['shiyu_season'] = shiyu.schedule_id
json.dump(cache, cache_f, indent=4)
cache_f.close()
await asyncio.sleep(900)
async def reminder():
global shiyu_reset
game_on = False
icon_s = {
'src': f'file://{ZZZn_path}/ico/Shop.ico',
'placement': 'appLogoOverride'
}
icon_sh = {
'src': f'file://{ZZZn_path}/ico/Shiyu.ico',
'placement': 'appLogoOverride'
}
icon_v = {
'src': f'file://{ZZZn_path}/ico/Video.ico',
'placement': 'appLogoOverride'
}
icon_sc = {
'src': f'file://{ZZZn_path}/ico/Scratch.ico',
'placement': 'appLogoOverride'
}
while (True):
name = "zenlesszonezero.exe" # "notepad++.exe"
if name in (p.name().lower() for p in psutil.process_iter()):
if game_on == False:
game_on = True
ac = await zzz.get_game_accounts()
for account in ac:
if "nap" in account.game_biz:
uid = account.uid
notes = await zzz.get_zzz_notes(uid=uid)
if (int(os.getenv("reminder_additional_delay")) != 0):
await asyncio.sleep(int(os.getenv("reminder_additional_delay")))
day = int(datetime.datetime.now(pytz.timezone(timezones[os.getenv("server")])).strftime('%d'))
if os.getenv("reminder_shop") == "True":
if day == 1:
print(f"REMINDER {strftime('%H:%M:%S', localtime())} | Shop has been reset today")
if os.getenv('tts') == 'True':
engine.say("REMINDER Shop has been reset today")
engine.runAndWait()
await toast_async("Shop reset", f"Shop has been reset today", icon=icon_s)
if os.getenv("reminder_shiyu") == "True":
if shiyu_reset:
print(f"REMINDER {strftime('%H:%M:%S', localtime())} | Shiyu Defense has been reset")
if os.getenv('tts') == 'True':
engine.say("REMINDER Shiyu Defense has been reset")
engine.runAndWait()
await toast_async("Shiyu Defense reset", f"Shiyu Defense has been reset", icon=icon_sh)
if os.getenv("reminder_video") == "True":
if notes.video_store_state == genshin.models.VideoStoreState.REVENUE_AVAILABLE:
print(f"REMINDER {strftime('%H:%M:%S', localtime())} | Video Store can be collected")
if os.getenv('tts') == 'True':
engine.say("REMINDER Video Store can be collected")
engine.runAndWait()
await toast_async("Video Store completed", f"Video Store can be collected", icon=icon_v)
elif notes.video_store_state == genshin.models.VideoStoreState.WAITING_TO_OPEN:
print(f"REMINDER {strftime('%H:%M:%S', localtime())} | Video Store is closed!")
if os.getenv('tts') == 'True':
engine.say("REMINDER Video Store is closed! Open it to collect denies!")
engine.runAndWait()
await toast_async("Video Store closed", f"Video Store is closed!\nOpen it to collect denies!", icon=icon_v)
if os.getenv("reminder_scratch") == "True":
if notes.scratch_card_completed == False:
print(f"REMINDER {strftime('%H:%M:%S', localtime())} | Scratch Card can be scratch")
if os.getenv('tts') == 'True':
engine.say("REMINDER Scratch Card can be scratch")
engine.runAndWait()
await toast_async("Scratch Card", f"Scratch Card can be scratch", icon=icon_sc)
else:
if game_on == True:
game_on = False
await asyncio.sleep(int(os.getenv("reminder_time")))
if __name__ == "__main__":
loop = asyncio.get_event_loop()
print("-----------------------------------")
if (os.getenv('battery_not')) == 'True':
task1 = asyncio.ensure_future(battery())
print("Battery Charge turned on")
if (os.getenv('daily_check_in')) == 'True':
task2 = asyncio.ensure_future(daily())
print("Daily check-in turned on")
if (os.getenv('shop_not')) == 'True':
task3 = asyncio.ensure_future(shop())
print("Shop reset turned on")
if (os.getenv('shiyu_not')) == 'True':
task4 = asyncio.ensure_future(shiyu())
print("Shiyu Defense reset turned on")
if (os.getenv('reminder')) == 'True':
task5 = asyncio.ensure_future(reminder())
print('Reminders turned on:')
if (os.getenv('reminder_shop')) == 'True':
print("- Shop")
if (os.getenv('reminder_shiyu')) == 'True':
print("- Shiyu Defense")
if (os.getenv('reminder_video')) == 'True':
print("- Video Store")
if (os.getenv('reminder_scratch')) == 'True':
print("- Scratch Card")
print("-----------------------------------")
loop.run_forever()