2024-06-05 17:39:00 +00:00
import os , sys
2024-06-03 23:24:56 +00:00
from slack_bolt import App
from slack_bolt . adapter . socket_mode import SocketModeHandler
from dotenv import load_dotenv
import firepup650 as fp
2024-06-05 18:11:46 +00:00
from traceback import format_exc
2024-06-03 23:24:56 +00:00
input = fp . replitInput
2024-06-04 22:18:48 +00:00
fp . replitCursor = (
fp . bcolors . REPLIT + " >>> " + fp . bcolors . RESET
) # Totally not hijacking one of my functions to use ;P
2024-06-03 23:24:56 +00:00
load_dotenv ( )
2024-06-04 21:08:13 +00:00
for requiredVar in [ " SLACK_BOT_TOKEN " , " SLACK_APP_TOKEN " ] :
if not os . environ . get ( requiredVar ) :
2024-06-04 22:18:48 +00:00
raise ValueError (
2024-06-05 17:52:56 +00:00
f ' Missing required environment variable " { requiredVar } " . Please create a .env file in the same directory as this script and define the missing variable. '
2024-06-04 22:18:48 +00:00
)
2024-06-03 23:24:56 +00:00
2024-06-05 18:05:50 +00:00
print ( " [INFO] Establishing a connection to slack... " )
2024-06-03 23:24:56 +00:00
app = App ( token = os . environ . get ( " SLACK_BOT_TOKEN " ) )
client = app . client
2024-06-05 17:39:00 +00:00
userMappings = { }
try :
if " --no-cache " in sys . argv :
2024-06-05 18:05:50 +00:00
print ( " [INFO] Skipping cache on user request " )
2024-06-05 17:39:00 +00:00
raise ImportError ( " User requested to skip cache " )
2024-06-05 18:05:50 +00:00
print ( " [INFO] Trying to load user mappings from cache... " )
2024-06-05 17:39:00 +00:00
from cache import userMappings
2024-06-05 18:01:23 +00:00
print (
2024-06-05 18:05:50 +00:00
""" [INFO] Cache load OK.
[ INFO ] Reminder : If you need to regenerate the cache , call the script with ` - - no - cache ` """
2024-06-05 18:01:23 +00:00
)
2024-06-05 17:39:00 +00:00
except ImportError :
users_list = [ ]
2024-06-05 18:05:50 +00:00
print ( " [WARN] Cache load failed, falling back to full load from slack... " )
2024-06-05 17:39:00 +00:00
cursor = " N/A "
pages = 0
2024-06-05 18:01:23 +00:00
while (
cursor
) : # If slack gives us a cursor, then we ain't done loading user data yet
2024-06-05 17:39:00 +00:00
data = " "
if cursor != " N/A " :
data = client . users_list ( cursor = cursor , limit = 1000 )
else :
data = client . users_list ( limit = 1000 )
cursor = data [ " response_metadata " ] [ " next_cursor " ]
users_list . extend ( data [ " members " ] )
pages + = 1
2024-06-05 18:05:57 +00:00
print (
2024-09-11 12:50:42 +00:00
f " [INFO] Pages of users loaded: { pages } (Estimated user count: { pages } 000) "
2024-06-05 18:05:57 +00:00
)
2024-06-05 17:39:00 +00:00
del pages
2024-06-05 18:05:50 +00:00
print ( " [INFO] Building user mappings now, this shouldn ' t take long... " )
2024-09-11 12:50:42 +00:00
#print(users_list[38])
2024-06-05 18:01:23 +00:00
for (
user
) in (
users_list
) : # Map user ID mentions to user name mentions, it's nicer when printing messages for thread selection.
2024-06-05 17:39:00 +00:00
userMappings [ f " <@ { user [ ' id ' ] } > " ] = (
2024-09-11 12:50:42 +00:00
f " <@ { user [ ' profile ' ] [ ' display_name_normalized ' ] } | { user [ ' id ' ] } > "
2024-06-05 17:50:37 +00:00
if user [ " profile " ] [ " display_name_normalized " ]
2024-06-05 18:01:00 +00:00
else ( # User is missing a display name for some reason, fallback to real names
2024-09-11 12:50:42 +00:00
f " <@ { user [ ' profile ' ] [ ' real_name_normalized ' ] } | { user [ ' id ' ] } > "
2024-06-05 17:50:37 +00:00
if user [ " profile " ] [ " real_name_normalized " ]
2024-06-05 18:01:00 +00:00
else f " <@ { user [ ' id ' ] } > " # User is missing a real name too... Fallback to ID
2024-06-05 17:48:35 +00:00
)
2024-06-05 17:39:00 +00:00
)
2024-06-05 18:05:50 +00:00
print ( " [INFO] All mappings generated, writing cache file now... " )
2024-06-05 18:01:23 +00:00
with open (
" cache.py " , " w "
) as cacheFile : # It is many times faster to load from a local file instead of from slack
2024-06-05 17:39:00 +00:00
cacheFile . write ( f " userMappings = { userMappings } " )
2024-06-05 18:05:50 +00:00
print ( " [INFO] Cache saved. " )
2024-06-04 22:15:21 +00:00
2024-06-05 18:05:50 +00:00
print ( " [INFO] User mappings loaded. User count: " , len ( userMappings ) )
2024-06-04 22:15:21 +00:00
2024-06-03 23:24:56 +00:00
if __name__ == " __main__ " :
2024-06-05 18:05:50 +00:00
print ( " [INFO] ^D at any time to terminate program " )
2024-06-03 23:24:56 +00:00
while 1 :
2024-06-04 21:37:19 +00:00
chan = input ( " Channel ID " )
2024-06-03 23:24:56 +00:00
try :
2024-06-05 18:05:50 +00:00
print ( " [INFO] ^C to change channel " )
2024-06-03 23:24:56 +00:00
while 1 :
2024-06-04 21:37:19 +00:00
thread = input ( " Reply to a thread? (y|N) " ) . lower ( ) . startswith ( " y " )
2024-06-03 23:24:56 +00:00
ts = None
if thread :
2024-06-04 22:18:48 +00:00
hasID = (
2024-09-11 12:50:42 +00:00
input ( " Do you have the TS ID? (y|N) " ) . lower ( ) . startswith ( " y " )
2024-06-04 22:18:48 +00:00
)
2024-06-03 23:24:56 +00:00
if not hasID :
try :
2024-06-04 22:18:48 +00:00
print (
2024-06-05 18:05:50 +00:00
" [INFO] Getting the last 50 messages for threading options... "
2024-06-04 22:18:48 +00:00
)
2024-06-03 23:24:56 +00:00
res = client . conversations_history (
2024-06-04 21:37:19 +00:00
channel = chan , inclusive = True , limit = 50
2024-06-03 23:24:56 +00:00
)
2024-06-04 21:37:19 +00:00
messages = res [ " messages " ]
texts = { }
2024-06-05 18:05:57 +00:00
print (
" [INFO] Building messages, this might take a little bit... "
)
2024-06-04 21:37:19 +00:00
for i in range ( len ( messages ) ) :
2024-06-04 22:15:21 +00:00
label = f ' { messages [ i ] [ " text " ] } ( { messages [ i ] [ " ts " ] } ) '
2024-06-05 17:39:00 +00:00
for user in userMappings :
label = label . replace ( user , userMappings [ user ] )
2024-06-04 22:15:21 +00:00
texts [ label ] = i
2024-06-04 22:18:48 +00:00
found = messages [
fp . menu (
texts ,
" Please select the message to reply to as a thread " ,
)
]
2024-06-03 23:24:56 +00:00
ts = found [ " ts " ]
except Exception as E :
2024-06-05 18:11:46 +00:00
print ( " [WARN] Exception: " )
2024-06-05 18:15:34 +00:00
for line in format_exc ( ) . split ( " \n " ) [ : - 1 ] :
2024-06-05 18:11:46 +00:00
print ( f " [WARN] { line } " )
2024-06-04 21:37:19 +00:00
break
2024-06-03 23:24:56 +00:00
else :
ts = input ( " TS ID " )
2024-06-04 22:18:48 +00:00
print (
2024-06-05 18:05:50 +00:00
" [INFO] ^C to change/exit thread (^C twice if you want to change channel) "
2024-06-04 22:18:48 +00:00
)
2024-06-04 21:37:19 +00:00
try :
2024-06-04 22:18:48 +00:00
while 1 :
2024-06-05 05:06:46 +00:00
msg = input (
" [THREAD] Message (Raw text, not blocks) "
) . replace ( " \\ n " , " \n " )
2024-06-04 22:18:48 +00:00
try :
2024-06-04 22:23:56 +00:00
client . chat_postMessage (
channel = chan , text = msg , thread_ts = ts
2024-06-03 23:24:56 +00:00
)
2024-06-05 18:05:50 +00:00
print ( " [INFO] Message sent (to the thread)! " )
2024-06-04 22:18:48 +00:00
except Exception as E :
2024-06-05 18:11:46 +00:00
print ( " [WARN] Exception: " )
2024-06-05 18:15:34 +00:00
for line in format_exc ( ) . split ( " \n " ) [ : - 1 ] :
2024-06-05 18:11:46 +00:00
print ( f " [WARN] { line } " )
break
2024-06-04 21:37:19 +00:00
except KeyboardInterrupt :
print ( )
if ts :
continue
2024-06-05 05:06:46 +00:00
msg = input ( " [CHANNEL] Message (Raw text, not blocks) " ) . replace (
" \\ n " , " \n "
)
2024-06-03 23:24:56 +00:00
try :
2024-09-11 12:50:42 +00:00
ts = client . chat_postMessage ( channel = chan , text = msg ) [ ' ts ' ]
print ( f " [INFO] Message sent (to the channel)! (TS ID: { ts } " )
2024-06-03 23:24:56 +00:00
except Exception as E :
2024-06-05 18:11:46 +00:00
print ( " [WARN] Exception: " )
2024-06-05 18:15:34 +00:00
for line in format_exc ( ) . split ( " \n " ) [ : - 1 ] :
2024-06-05 18:11:46 +00:00
print ( f " [WARN] { line } " )
break
2024-06-03 23:24:56 +00:00
except KeyboardInterrupt :
print ( )