25 Commits
Author SHA1 Message Date
sugoidogo 75bf46edc2 add aspects command 2025-07-27 22:14:09 -07:00
josephsmendoza 073bad2fe9 add aspect functions and refactor functions for reusable code 2025-07-24 21:12:53 -07:00
josephsmendoza 1e3e651ccb reduce startup delay by skipping pip install if pip folder exists 2025-07-24 09:49:55 -07:00
sugoidogo e4376a62f2 update in seperate thread 2025-07-20 23:18:24 -07:00
sugoidogo d1892a241f fix typo 2025-07-20 23:15:26 -07:00
sugoidogo eb045fa94a fix update function args 2025-07-20 23:14:19 -07:00
sugoidogo f586906a08 add update button to obs 2025-07-20 23:12:04 -07:00
sugoidogo 9278d32549 add command name to settings 2025-07-20 22:51:06 -07:00
josephsmendoza 2784872d12 fix early login request 2025-07-20 15:57:49 -07:00
josephsmendoza 9bfcc1a8a3 gracefully fail refreshing tokens 2025-07-20 15:55:39 -07:00
sugoidogo b730599d7e refresh tokens and log token activity 2025-07-20 02:59:32 -07:00
sugoidogo 32115c5a02 use universal strftime format 2025-07-19 01:57:37 -07:00
sugoidogo 43e3f632cc switch to twitch.py and other improvements 2025-07-19 01:31:50 -07:00
josephsmendoza 4102e8e672 fix overridden event 2025-07-18 17:10:36 -07:00
sugoidogo f0ca3fd16c fix dependency check 2025-07-18 01:39:05 -07:00
sugoidogo df27549942 better dependency check 2025-07-18 01:35:27 -07:00
sugoidogo cdb521b8ad fix loading with no tokens 2025-07-18 01:19:02 -07:00
sugoidogo 6907dacf89 fix library usage for OBS cold start 2025-07-18 01:03:56 -07:00
sugoidogo 06cc06476a add !transits command 2025-07-18 00:25:48 -07:00
sugoidogo 05dfb7215b updated output format 2025-07-16 21:18:54 -07:00
sugoidogo 11a713edbb install dependencies to astrolobot folder 2025-07-16 20:21:55 -07:00
josephsmendoza eba9505d1a more readable output format 2025-07-16 11:36:28 -07:00
josephsmendoza 241394fe2d add simple test without OBS 2025-07-16 11:36:09 -07:00
josephsmendoza f8347eeed8 download swiss ephemeris files as needed 2025-07-16 11:35:34 -07:00
josephsmendoza ee9fb1a969 initial commit 2025-07-16 03:49:20 -07:00
+25 -188
View File
@@ -5,7 +5,6 @@ from urllib.parse import quote_plus
from urllib.request import urlretrieve, urlopen, Request, HTTPError
from threading import Thread
from os import makedirs,path
from functools import cache
import json,sys,webbrowser,importlib,tomllib
def update():
@@ -42,10 +41,6 @@ def dependency_setup():
print('dependencies ready')
def today():
now=datetime.utcnow()
return datetime(now.year,now.month,now.day)
# Astrology functions
def load_settings():
@@ -56,10 +51,6 @@ def load_settings():
return {
'positions':'!positions',
'transits':'!transits',
'major_aspects':'!aspects major',
'minor_aspects':'!aspects minor',
'major_aspect_transits':'!aspects major transits',
'minor_aspect_transits':'!aspects minor transits',
}
def get_zodiac(angle):
@@ -70,8 +61,7 @@ def get_zodiac(angle):
def is_retrograde(speed):
return speed<0
@cache
def get_positions_raw(date=today()):
def get_positions_raw(date):
import swisseph as swe
julian_day = swe.julday(date.year, date.month, date.day)
planets = {
@@ -104,8 +94,7 @@ def get_positions_raw(date=today()):
return positions
@cache
def get_positions(date=today()):
def get_positions(date):
positions={}
for name, position_raw in get_positions_raw(date).items():
@@ -116,7 +105,7 @@ def get_positions(date=today()):
return positions
def get_list_formatted(in_list,isare=False):
def get_list_formatted(in_list,isare=True):
match len(in_list):
case 0:
output='Nothing'
@@ -136,8 +125,7 @@ def get_list_formatted(in_list,isare=False):
output+=' are '
return output
@cache
def get_positions_formatted(date=today()):
def get_positions_formatted(date):
retrograde_planets=[]
position_strings=[]
@@ -146,7 +134,7 @@ def get_positions_formatted(date=today()):
retrograde_planets.append(name)
position_strings.append(name+' is in '+position['zodiac'])
positions_formatted=get_list_formatted(retrograde_planets,True)+'in Retrograde\n'
positions_formatted=get_list_formatted(retrograde_planets)+'in Retrograde\n'
positions_formatted+=', '.join(position_strings[0:2])+'\n'
positions_formatted+=', '.join(position_strings[2:5])+'\n'
@@ -156,16 +144,15 @@ def get_positions_formatted(date=today()):
return positions_formatted
def get_transits():
seconds_in_1_day=86400
@cache
def get_transits(date=today(), maxdays=28):
positions_now=get_positions(date)
now=datetime.utcnow()
positions_now=get_positions(now)
transits={}
days=1
while len(transits)<12 and days<=maxdays:
future_timestamp=date.timestamp()+(days*seconds_in_1_day)
while len(transits)<12 and days<29:
future_timestamp=now.timestamp()+(days*seconds_in_1_day)
future_date=datetime.fromtimestamp(future_timestamp,timezone.utc)
positions_future=get_positions(future_date)
for name, position_future in positions_future.items():
@@ -181,13 +168,11 @@ def get_transits(date=today(), maxdays=28):
return transits
def get_transits_formatted():
date_format='%b %d'
@cache
def get_transits_formatted(date=today(), maxdays=28):
transits_formatted=''
for name,transit in get_transits(date, maxdays).items():
for name,transit in get_transits().items():
if transit['zodiac']!=None:
transits_formatted+=name+' is entering '+transit['zodiac']+' on '+transit['date'].strftime(date_format)+'\n'
if transit['retrograde']==True:
@@ -197,9 +182,8 @@ def get_transits_formatted(date=today(), maxdays=28):
return transits_formatted
@cache
def get_aspects(date=today(), minor=False):
positions=get_positions_raw(date).copy()
def get_aspects(date, minor=False):
positions=get_positions_raw(date)
major_aspects={
'conjuction':{'angle':0,'orb':10.0},
'oposition':{'angle':180,'orb':10.0},
@@ -241,151 +225,18 @@ def get_aspects(date=today(), minor=False):
return aspects
@cache
def get_aspects_formatted(date=today(),minor=False):
def get_aspects_formatted(date,minor=False):
aspects_formatted=''
for planet,aspects in get_aspects(date,minor).items():
aspects_formatted+=planet+' is in '
aspects_list=[]
for aspect_name,aspect_planets in aspects.items():
aspects_list.append(aspect_name+' with '+get_list_formatted(aspect_planets))
aspects_formatted+=get_list_formatted(aspects_list)+'\n'
aspects_list.append(aspect_name+' with '+get_list_formatted(aspect_planets,False))
aspects_formatted+=get_list_formatted(aspects_list,False)+'\n'
return aspects_formatted
@cache
def get_aspect_transits(date=today(),minor=False,maxdays=28):
date_now=today()
timestamp_now=date_now.timestamp()
aspects_now=get_aspects(date_now,minor)
pre_transits={}
days=0
def aspects_contains(aspects,planet_a,aspect=None,planet_b=None):
if planet_a not in aspects:
return False
elif aspect and aspect not in aspects[planet_a]:
return False
elif aspect and planet_b and planet_b not in aspects[planet_a][aspect]:
return False
return True
def ensure_pre_path(planet_a,aspect=None):
if planet_a not in pre_transits:
pre_transits[planet_a]={}
if aspect and aspect not in pre_transits[planet_a]:
pre_transits[planet_a][aspect]={}
def pre_planet_b(planet_a,aspect,planet_b,date_future,direction):
ensure_pre_path(planet_a,aspect)
pre_transits[planet_a][aspect][planet_b]={
'date':date_future,
'direction':direction
}
def pre_aspect(planet_a,aspect,planets,date_future,direction):
ensure_pre_path(planet_a)
pre_transits[planet_a][aspect]={}
for planet_b in planets:
pre_planet_b(planet_a,aspect,planet_b,date_future,direction)
def pre_planet_a(planet_a,aspects,date_future,direction):
pre_transits[planet_a]={}
for aspect,planets in aspects.items():
pre_aspect(planet_a,aspect,planets,date_future,direction)
while days<maxdays:
days+=1
timestamp_future=timestamp_now+(seconds_in_1_day*days)
date_future=datetime.fromtimestamp(timestamp_future,timezone.utc)
aspects_future=get_aspects(date_future)
for planet_a,aspects in aspects_now.items():
try:
pre_transits[planet_a]
except KeyError:
if not aspects_contains(aspects_future,planet_a):
pre_planet_a(planet_a,aspects,date_future,'exiting')
continue
for aspect, planets in aspects.items():
try:
pre_transits[planet_a][aspect]
except KeyError:
if not aspects_contains(aspects_future,planet_a,aspect):
pre_aspect(planet_a,aspect,planets,date_future,'exiting')
continue
for planet_b in planets:
try:
pre_transits[planet_a][aspect][planet_b]
except KeyError:
if not aspects_contains(aspects_future,planet_a,aspect,planet_b):
pre_planet_b(planet_a,aspect,planet_b,date_future,'exiting')
days=0
while days<maxdays:
days+=1
timestamp_future=timestamp_now+(seconds_in_1_day*days)
date_future=datetime.fromtimestamp(timestamp_future,timezone.utc)
aspects_future=get_aspects(date_future)
for planet_a,aspects in aspects_future.items():
try:
pre_transits[planet_a]
except KeyError:
if not aspects_contains(aspects_now,planet_a):
pre_planet_a(planet_a,aspects,date_future,'entering')
continue
for aspect, planets in aspects.items():
try:
pre_transits[planet_a][aspect]
except KeyError:
if not aspects_contains(aspects_now,planet_a,aspect):
pre_aspect(planet_a,aspect,planets,date_future,'entering')
continue
for planet_b in planets:
try:
pre_transits[planet_a][aspect][planet_b]
except KeyError:
if not aspects_contains(aspects_now,planet_a,aspect,planet_b):
pre_planet_b(planet_a,aspect,planet_b,date_future,'entering')
post_transits={}
for planet_a,aspects in pre_transits.items():
post_transits[planet_a]={}
for aspect,planets in aspects.items():
for planet_b,transit in planets.items():
direction=transit['direction']
date=transit['date']
if direction not in post_transits[planet_a]:
post_transits[planet_a][direction]={}
if date not in post_transits[planet_a][direction]:
post_transits[planet_a][direction][date]={}
if aspect not in post_transits[planet_a][direction][date]:
post_transits[planet_a][direction][date][aspect]=[]
post_transits[planet_a][direction][date][aspect].append(planet_b)
return post_transits
@cache
def get_aspect_transits_formatted(date=today(),minor=False,maxdays=28):
aspect_transits=get_aspect_transits(date,minor,maxdays)
aspect_transits_formatted=''
for planet_a,directions in aspect_transits.items():
aspect_transits_formatted+=planet_a+' is '
direction_list=[]
for direction,dates in directions.items():
date_list=[]
for date,aspects in dates.items():
aspect_list=[]
for aspect,planets in aspects.items():
aspect_list.append(aspect+' with '+get_list_formatted(planets))
date_list.append(get_list_formatted(aspect_list)+' on '+date.strftime(date_format))
direction_list.append(direction+' '+get_list_formatted(date_list))
aspect_transits_formatted+=get_list_formatted(direction_list)+'\n'
return aspect_transits_formatted
# Twitch functions
device_code=None
@@ -483,7 +334,7 @@ def main():
async def on_chat_message(data: eventsub.chat.MessageEvent):
config=load_settings()
if data['message']['text']==config['positions']:
for line in get_positions_formatted().splitlines(False):
for line in get_positions_formatted(datetime.now()).splitlines(False):
await client.channel.chat.send_message(line,data['message_id'])
return
if data['message']['text']==config['transits']:
@@ -491,19 +342,11 @@ def main():
await client.channel.chat.send_message(line,data['message_id'])
return
if data['message']['text']==config['major_aspects']:
for line in get_aspects_formatted().splitlines(False):
for line in get_aspects_formatted(datetime.now()).splitlines(False):
await client.channel.chat.send_message(line,data['message_id'])
return
if data['message']['text']==config['minor_aspects']:
for line in get_aspects_formatted(minor=True).splitlines(False):
await client.channel.chat.send_message(line,data['message_id'])
return
if data['message']['text']==config['major_aspect_transits']:
for line in get_aspect_transits_formatted().splitlines(False):
await client.channel.chat.send_message(line,data['message_id'])
return
if data['message']['text']==config['minor_aspect_transits']:
for line in get_aspect_transits_formatted(minor=True).splitlines(False):
for line in get_aspects_formatted(datetime.now(),True).splitlines(False):
await client.channel.chat.send_message(line,data['message_id'])
return
@@ -560,8 +403,6 @@ def script_properties():
obspython.obs_properties_add_text(properties,'transits','transits',obspython.OBS_TEXT_DEFAULT)
obspython.obs_properties_add_text(properties,'major_aspects','major aspects',obspython.OBS_TEXT_DEFAULT)
obspython.obs_properties_add_text(properties,'minor_aspects','minor aspects',obspython.OBS_TEXT_DEFAULT)
obspython.obs_properties_add_text(properties,'major_aspect_transits','major aspect transits',obspython.OBS_TEXT_DEFAULT)
obspython.obs_properties_add_text(properties,'minor_aspect_transits','minor aspect transits',obspython.OBS_TEXT_DEFAULT)
return properties
def script_defaults(settings):
@@ -571,8 +412,6 @@ def script_defaults(settings):
obspython.obs_data_set_default_string(settings,'transits','!transits')
obspython.obs_data_set_default_string(settings,'major_aspects','!aspects major')
obspython.obs_data_set_default_string(settings,'minor_aspects','!aspects minor')
obspython.obs_data_set_default_string(settings,'major_aspect_transits','!aspects major transits')
obspython.obs_data_set_default_string(settings,'minor_aspect_transits','!aspects minor transits')
def script_load(settings):
global obs_settings, save_tokens, load_tokens, load_settings
@@ -603,10 +442,8 @@ if __name__ == '__main__':
def script_path():
return path.dirname(__file__)+'/'
dependency_setup()
print(get_positions_formatted())
print(get_transits_formatted())
print(get_aspects_formatted())
print(get_aspects_formatted(minor=True))
print(get_aspect_transits_formatted())
print(get_aspect_transits_formatted(minor=True))
main()
#print(get_positions_formatted(datetime(2025,7,21)))
#print(get_transits_formatted())
#main()
print(get_aspects_formatted(datetime(2025,7,21)))
print(get_aspects_formatted(datetime(2025,7,21),True))