Skip to content

Commit

Permalink
Update gs_messenger.py
Browse files Browse the repository at this point in the history
Added PM timestamps and New PM notifications.
  • Loading branch information
ghostwalkr authored Dec 23, 2020
1 parent 72412b5 commit f1d1fc4
Showing 1 changed file with 51 additions and 9 deletions.
60 changes: 51 additions & 9 deletions gs_messenger.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,22 @@ class GSBot:
def __init__(self):
self.session = None
self.logged_in = False
self.post_key = ""
self.post_key = "" # Value provided in MyBB HTML which is necessary for requesting resources.
self.new_pms = False
self.pmlist = []

def fetcher(self):
"Periodically updates the PM list. Intended to run in background thread"
while True:
self.getPms(verbose=False)
if self.new_pms:
print("\nNew Private Message")
self.new_pms = False
sleep(180) # 3 minutes

def login(self, username, password, startFetcher=True):
"Authenticate with GreySec"
# Returns None if authentication was successful and sets self.logged_in to True, raises exception otherwise.
self.session = requests.Session()
response = self.session.get("https://greysec.net")
# Search the HTML for the "my_post_key" value. It's used in MyBB sessions and required to login.
Expand Down Expand Up @@ -78,13 +85,18 @@ def login(self, username, password, startFetcher=True):
return

def logout(self):
"Log out of Greysec"
# Sets self.logged_in to False
response = self.session.get("https://greysec.net/index.php")
html = BeautifulSoup(response.text, "html.parser")
logout_link = html.find("a", href=compile("\w*action=logout\w*")).attrs["href"]
self.session.get("https://greysec.net/" + logout_link)
self.logged_in = False

def getPms(self, page=1, verbose=True):
"Retrieves PMs from account. Need to be authenticated first."
# page: <int> The page number of the PMs to get. Gets just the first page by default. No need to get all the PMs at once.
# verbose: <bool> Whether to output info to the user. It's only set to False when used by the fetcher method.
mid = 0
private_messages = []
# {title:example, sender:example, contents:example, isUnread:true}
Expand All @@ -94,33 +106,48 @@ def getPms(self, page=1, verbose=True):
response = self.session.get("https://greysec.net/private.php", params={"fid":"0", "page":page})

# Find PMs
# Example 'pm' dictionary:
# {"title": "test", "isunread":"True", "msgid": "3", "sender":"Friend", "pmid":"2377", "contents":"hello world"}
html = BeautifulSoup(response.text, "html.parser")

results = [result for result in html.find_all("a", class_=["old_pm", "new_pm"])]
for result in results:
pm = {}
if result.attrs["class"][0] == "new_pm":
pm["isunread"] = True
self.new_pms = True
elif result.attrs["class"][0] == "old_pm":
pm["isunread"] = False
else:
pm["isunread"] = "Unknown"


# mid: message id. used by the command interpreter to index the messages
pm["msgid"] = mid
pm["title"] = result.text
nextTd = result.find_next("td")
pm["sender"] = nextTd.text
pmUrl = result.attrs["href"]
pmPage = self.session.get("https://greysec.net/" + pmUrl)
# pmid: used by greysec for replying to PMs
pm["pmid"] = findall("pmid=\d{1,7}", pmPage.url)[0].strip("pmid=")
pmHtml = BeautifulSoup(pmPage.text, "html.parser")
pm["contents"] = pmHtml.find("div", class_="post_body scaleimages").text

pmDate = pmHtml.find(class_="post_date")
try:
pmRecvdDate = findall("\d{1,2}-\d{1,2}-\d{4}", str(pmDate))[0]
pmRecvdTime = findall("\d{1,2}:\d{1,2} [AP]M", pmDate.text)[0]
except:
pmRecvdDate, pmRecvdTime = findall("\d{2}-\d{2}-\d{4}, \d{2}:\d{2} [AP]M", str(pmDate))[0].split(",")

pm["timestamp"] = f"{pmRecvdDate} {pmRecvdTime}"

# Show progress of message retrieval
if verbose:
if (mid + 1) % 2 == 0:
percentage = round((mid + 1) / len(results) * 100, 1)
print(f"Retrieved: {percentage}%")

private_messages.append(pm)
mid += 1

Expand All @@ -129,9 +156,16 @@ def getPms(self, page=1, verbose=True):
print("Retrieval complete")

def sendPm(self, subject, msg, recipient, pmid=0):
"Send a PM to a user"
# subject <string> - the subject of the message.
# msg <string> - the message to send
# recipient <string> - username of account to send PM to.
# pmid <int> - The PM id we're replying to, or 0 if composing new message
# returns: True on successful sending, False otherwise.
# Only specify pmid if you're replying to a message. Not for composing new messages.
if bot.logged_in:
# Get my_post_key
# Need to get new post key. Greysec was complaining about the program using the original post key used for logging in for some reason.
response = self.session.get("https://greysec.net/private.php")
pmPage = BeautifulSoup(response.text, "html.parser")
self.post_key = pmPage.find("input", attrs={"name":"my_post_key"}).attrs["value"]
Expand All @@ -149,6 +183,7 @@ def sendPm(self, subject, msg, recipient, pmid=0):
"message": msg
}
response = self.session.post("https://greysec.net/private.php", data=postData)
# The following isn't going to handle errors very well. Further testing is required to determine what could go wrong so it can be handled.
if response.status_code == 200:
return True
else:
Expand All @@ -162,6 +197,8 @@ class CommandInterpreter(cmd.Cmd):

def do_login(self, arg):
"Log into your GreySec account"
if bot.logged_in: print("You're already logged in"); return

while True:
username = input("Username: ").strip()
password = getpass("Password: ")
Expand All @@ -179,6 +216,9 @@ def do_login(self, arg):
fetcher = Thread(target=bot.fetcher)
fetcher.start()

# change prompt
self.prompt = f"{BLUE}[{username}@greysec.net]{RESET} > "

def do_retrieve(self, arg=1):
"Get PMs from GreySec. retrieve <pagenumber> (automatically done when program starts)"
if bot.logged_in:
Expand Down Expand Up @@ -212,11 +252,13 @@ def do_read(self, arg):
for p in bot.pmlist:
if p["msgid"] == int(arg.strip()):
found = True
print("\n" + "=" * 20)
print(p["title"])
print("=" * 20)
print(p["sender"])
print("=" * 20)
print("\n" + "=" * 40)
print("Subject:", p["title"])
print("=" * len(p["title"]))
print("Sender:", p["sender"])
print("=" * len(p["title"]))
print("Timestamp:", p["timestamp"])
print("=" * len(p["timestamp"]))
print(p["contents"])
if not found:
print("Message not found")
Expand Down Expand Up @@ -306,7 +348,7 @@ def do_compose(self, arg):
def do_quit(self, arg):
"Exit the program"
print("Bye friend!")
bye()
sys.exit(0)

## Main ####

Expand Down

0 comments on commit f1d1fc4

Please sign in to comment.