Jump to content
  • Status: Pending

My "topic title" game is strong, I know... Leaving you all there with just a WHAT, and you're thinking I just may have forgot to type out the rest of it? Come on peeps, you should know me by now.

Ok... onward, So I have this really cool Python Script (and so help me god, if someone says why didn't you do it this way... and they show me a place in the Admin CP... I'll be like that 80's mom in Kmart with the kids!).

OMG!!! I know I am boring myself at this point... But you guys are my therapist, so I have to get it all of that brain stuff out there. Ok I am done... So I created a little simple python script:

import os
import sys
import json
from flask import Flask, request, jsonify
import requests
import logging

# Dynamically set the working directory to the script's directory
BASE_DIR = os.path.dirname(os.path.abspath(sys.argv[0]))

# Load Configuration
CONFIG_PATH = os.path.join(BASE_DIR, 'config', 'config.json')

try:
	with open(CONFIG_PATH, 'r') as config_file:
		config = json.load(config_file)
	
	except FileNotFoundError:
		print(f" Configuration file not found at {CONFIG_PATH}. Please ensure 'config.json' exists in the 'config' folder.")
		exit(1)
	except json.JSONDecodeError:
	    print(" Failed to parse 'config.json'. Please check the file for JSON formatting errors.")
	    exit(1)

# Extract Configurations
SETTINGS = config.get('settings', {})
IPS_API_KEY = SETTINGS.get('ips_api_key')
IPS_API_URL = f"{SETTINGS.get('ips_api_url', 'https://codenamejessica.com/api/core/messages')}?key={IPS_API_KEY}"
ADMIN_ID = SETTINGS.get('author_id')
ADMIN_NAME = SETTINGS.get('author_name')
LOG_FILE = os.path.join(BASE_DIR, SETTINGS.get('log_file', 'logs/send_welcome.log'))
DEBUG = SETTINGS.get('debug', False)

# Ensure log directory exists
os.makedirs(os.path.dirname(LOG_FILE), exist_ok=True)

# Logging setup
logging.basicConfig(filename=LOG_FILE, level=logging.DEBUG if DEBUG else logging.INFO, format="%(asctime)s - %(message)s")
app = Flask(__name__)

# Function to send a Private Message
def send_welcome_pm(user_id, username):
	payload = {
		"title": f" Welcome to CodenameJessica, {username}! ",
		"to[]": str(user_id),
		"body": (
			f"We're thrilled to have you here, {username}! <br><br>"
			"<strong style='color: hsl(0, 70%, 60%);'>Getting Started:</strong>"
			"<ul style='list-style: none; padding-left: 0;'>"
			"  <li> <strong style='color: hsl(100, 70%, 50%);'>Introduce yourself</strong> in the [<a href='/forums/forum/27-meet-and-greet/'>Meet and Greet</a>].</li>"
			"  <li> <strong style='color: hsl(30, 70%, 60%);'>Join the conversation</strong> in [<a href='/forums/forum/25-the-lounge/'>The Lounge</a>]. Answer fun question starters or create your own!</li>"
			"  <li> <strong style='color: hsl(210, 90%, 60%);'>Test your skills</strong> with our [<a href='/forums/forum/9-programming-challenges/'>Programming Challenges</a>].</li>"
			"  <li> <strong style='color: white;'>Share your Feedback or Suggestions</strong> in the [<a href='/forums/forum/63-feedback-suggestions/'>Feedback & Suggestion Forum</a>].</li>"
			"  <li> <strong style='color: hsl(260, 90%, 70%);'>Explore & join</strong> clubs that match your interests! </li>"
			"</ul><br>"
			" <strong style='color: hsl(30, 70%, 60%);'>Get Involved:</strong>"
			"<ul style='list-style: none; padding-left: 0;'>"
			"  <li> <strong style='color: hsl(100, 70%, 50%);'>Get or share</strong> [<a href='/forums/forum/3-programming/'>Programming Help</a>]</li>"
			"  <li> <strong style='color: hsl(30, 70%, 60%);'>Discover and share</strong> [<a href='/forums/forum/10-server-administration/'>Server Administration Tips</a>]</li>"
			"  <li> <strong style='color: hsl(0, 70%, 60%);'>Stay updated</strong> with the latest [<a href='/forums/forum/17-security/'>Best Security Practices</a>]</li>"
			"  <li> <strong style='color: hsl(210, 90%, 60%);'>Advance your career</strong> with [<a href='/forums/forum/74-professional-development/'>Professional Development</a>] resources</li>"
			"</ul>"
			"Or simply connect with a community of passionate, driven individuals, we've got you covered!<br><br>"
			"At <strong>CodenameJessica</strong>, we celebrate diversity and foster meaningful connections within the Tech and Enterprise communities. "
			"If you ever need help , feel free to tag me or any of our moderators. "
			"We can't wait to see the amazing things you'll bring to our community!<br><br>"
			"- <strong style='color: hsl(260, 90%, 70%);'>Jessica</strong>, <span data-i-color='soft'>Founder of CodenameJessica</span>"
		),
		"from": ADMIN_ID,
		"author_name": ADMIN_NAME
	}
	
	logging.info(f" Sending payload to API: {payload}")
	
	try:
		response = requests.post(IPS_API_URL, data=payload)
		if response.status_code in [200, 201]:
			logging.info(f" Private message sent to {username} (User ID: {user_id})")
		else:
			logging.error(f" Failed to send PM: {response.status_code} - {response.text}")
    except Exception as e:
		logging.error(f" Exception while sending PM: {e}")
		
# Webhook listener for new user registrations
@app.route("/welcome", methods=["POST"])
def register_webhook():
	try:
		data = request.get_json()
		logging.info(f" Received webhook data: {data}")
		user_id = data.get("id")  # Invision's User ID
		username = data.get("name", "")
		
		if user_id and username:
			send_welcome_pm(user_id, username)
			return jsonify({"message": " Welcome PM sent"}), 200
			
        return jsonify({"error": " Invalid request, missing user_id or username"}), 400
    except Exception as e:
        logging.error(f" Webhook processing error: {e}")
        return jsonify({"error": " Internal server error"}), 500

if __name__ == "__main__":
	app.run(host="0.0.0.0", port=5000)

It is a very simple script to listen on port 5000 for a webhook from IPS, IPC, Invision (What the hell is it really called, I've seen like 5 names), start the action and poof... The new user has a Welcome Private Message... Nice pretty, formatted, perfect. Just like... (you thought I was going to say, me didn't you, nope... I was going to say YOU - awe, how gross)...

OK, so this all works perfectly, so where is the bug you're asking? When the new user logs in, there is no notification that they have a new message. The message is there, but no notification.

TADA! Told you we would get there... Now is this a bug or a feature?

DISCLAIMER!!!! This was freaking hilarious in my head with a Morgan Freeman dramatic role voice... "And that, dear reader, is where Jessica realized... the notification was never coming."

User Feedback

Recommended Comments

teraßyte

Clients

The API does have the code to send out the notification:

		$post = $commentClass::create( $item, $postContents, TRUE, NULL, NULL, \IPS\Member::load( (int) \IPS\Request::i()->from ), \IPS\DateTime::create() );
		
		$item->first_msg_id = $post->id;
		$item->save();

		/* Authorize sender and recipients */
		$item->authorize( array_map( function( $member ) { return (int) $member; }, array_merge( array( \IPS\Request::i()->from ), \IPS\Request::i()->to ) ) );

		/* Send notifications */
		$post->sendNotifications();

		return new \IPS\Api\Response( 201, $item->id );

If the notification is not going out, the default option for PMs must be set to disabled in your ACP. New users use the default values setup in ACP:

Daniel F

Invision Community Team

Can you clarify what you mean with "notification" ? is it the email/notification as mentioned by @teraßyte ?

Or is there literally no indicator for new PMs at all aka no Badge at top of the PM icon and no notification flash?

When I visit the community once I created a PM via REST with this code:

var_dump(
	\IPS\Http\Url::external( $url . "/core/messages" )->request()->login( $key, "" )->post(
		array(
			'from'		=> 2,
			'to'	=> [1],
			'title'		=> 'test',
			'body'		=> 'content test',
			)
		)->decodeJson()
	);

I'm seeing the badge with the new private messages and also the notification flash at the bottom of the page appears.

CleanShot 2025-02-01 at 20.29.41.png

Or is there literally no indicator for new PMs at all aka no Badge at top of the PM icon and no notification flash?

It is that... No indicator or pop notification that a PM has been received.

Daniel F

Invision Community Team

Could you please take a look at the core_members database table, if the msg_count_total, msg_count_new and msg_count_reset columns have values for the recently created member who get the PM.

I am testing something now... I think I am missing:

"is_new": True,
"notification": True,

in the payload of the API response.

That seemed to resolve it... Once I set the is_new and notification to true, I was alerted right away I received a message. Crisis, or at least this bug is not a bug... IT'S A FEATURE!!!! YAY!

| 14 | SomeOneAlreadyTookMyName | 3 | alancooley2181@outlook.com | 1738432646 | 174.101.160.196 | NULL | NULL | 0 | 1 | 0 | NULL | NULL | NULL | 0 | 1 | 1738436122 | 0 | 1738436078 | 1738439633 | 0 | {"content":0,"comments":0,"method":"immediate"} | 0 | | someonealreadytookmyname | NULL | NULL |

0 | 0 | $2y$10$41ZA1vby0lIFBcnSTFIo1OBDmGMyYfgWgyqSOKIv0Fm7UhiQXz8Im | NULL | 65536 | 0,0 | 0 | NULL | 6dc462 | NULL |

NULL | NULL | NULL | NULL | 0 | 0 | none | | NULL | NULL | America/New_York | | [] |

1738436104 | | 25165840 | 0 | 0 | 0 | NULL | NULL | 0 | NULL | NULL | NULL | NULL |

0 | | | 0 | NULL | 0 | NULL | 0 | 0 | NULL | NULL | 0 |

That is the mysql output will parse that now

Daniel F

Invision Community Team

This sounds weird, there's no need for is_new and notification in the payload, it's literally not available.
/core/messages accepts literally only


	 * @apiparam	int		from			User ID conversation is from
	 * @apiparam	array	to				One or more user IDs conversation is sent to
	 * @apiparam	string	title			Conversation title
	 * @apiparam	string	body			Conversation body

https://invisioncommunity.com/developers/rest-api?endpoint=core/messages/POSTindex

msg_show_notification: 0
msg_count_total: 1
msg_count_new: 0
notification_cnt: 0
members_disable_pm: 0
msg_count_reset: 1738436122

That is all I can see out of that.

Yeah, I was looking at that, I think it was a fluke.

(edited)

When I said it was a fluke, I meant the is_new and notification being sent as true. This did not impact the failure of a notification when someone has a notification.

If someone wants to verify, they can go to my website, create an account, and you should have a new PM, I did notice the email when I set up a fake user to test this. But the notification badge, or popup notification did not show even though the message was in their Forum's inbox.

If you do create an account to test and want to delete it, just let me know and I will delete your account.

Edited by Code Name Jessica